summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 00:55:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 00:55:53 +0000
commit3d0386f27ca66379acf50199e1d1298386eeeeb8 (patch)
treef87bd4a126b3a843858eb447e8fd5893c3ee3882
parentInitial commit. (diff)
downloadknot-resolver-upstream.tar.xz
knot-resolver-upstream.zip
Adding upstream version 3.2.1.upstream/3.2.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.clang-tidy11
-rw-r--r--.dir-locals.el9
-rw-r--r--.gitignore71
-rw-r--r--.gitlab-ci.yml645
-rw-r--r--.gitmodules9
-rw-r--r--.luacheckrc83
-rw-r--r--.travis.yml36
-rw-r--r--AUTHORS12
-rw-r--r--COPYING687
-rw-r--r--CodingStyle5
-rw-r--r--Dockerfile76
-rw-r--r--Makefile188
-rw-r--r--NEWS701
-rw-r--r--README.md74
-rw-r--r--bench/bench.mk28
-rw-r--r--bench/bench_lru.c250
-rw-r--r--bench/bench_lru_set1.tsv65536
-rw-r--r--ci/README.md21
-rw-r--r--ci/debian-stable/Dockerfile92
-rw-r--r--ci/debian-unstable/Dockerfile43
-rw-r--r--ci/debian-unstable/README1
-rw-r--r--ci/fedora/Dockerfile22
-rwxr-xr-xci/pytests/lint.sh16
-rwxr-xr-xci/pytests/pylint-run.sh9
-rwxr-xr-xci/pytests/run-extended.sh5
-rwxr-xr-xci/pytests/run.sh3
-rw-r--r--ci/respdiff/kresd.config24
-rw-r--r--ci/respdiff/respdiff-tcp.conf50
-rw-r--r--ci/respdiff/respdiff-tls.conf50
-rw-r--r--ci/respdiff/respdiff-udp.conf50
-rwxr-xr-xci/respdiff/restart-bind.sh2
-rwxr-xr-xci/respdiff/restart-kresd.sh11
-rwxr-xr-xci/respdiff/restart-unbound.sh2
-rwxr-xr-xci/respdiff/run-respdiff-tests.sh25
-rwxr-xr-xci/respdiff/start-resolvers.sh11
-rwxr-xr-xci/travis.py47
-rw-r--r--client/client.mk14
-rw-r--r--client/kresc.c471
-rw-r--r--config.mk45
-rw-r--r--contrib/base32hex.c289
-rw-r--r--contrib/base32hex.h72
-rw-r--r--contrib/base64.c268
-rw-r--r--contrib/base64.h107
-rw-r--r--contrib/ccan/asprintf/LICENSE17
-rw-r--r--contrib/ccan/asprintf/_info45
-rw-r--r--contrib/ccan/asprintf/asprintf.c56
-rw-r--r--contrib/ccan/asprintf/asprintf.h50
-rw-r--r--contrib/ccan/compiler/LICENSE28
-rw-r--r--contrib/ccan/compiler/_info64
-rw-r--r--contrib/ccan/compiler/compiler.h231
-rw-r--r--contrib/ccan/compiler/test/compile_fail-printf.c22
-rw-r--r--contrib/ccan/compiler/test/run-is_compile_constant.c15
-rw-r--r--contrib/ccan/ilog/LICENSE28
-rw-r--r--contrib/ccan/ilog/_info50
-rw-r--r--contrib/ccan/ilog/ilog.c141
-rw-r--r--contrib/ccan/ilog/ilog.h151
-rw-r--r--contrib/ccan/ilog/test/run-out-of-line.c65
-rw-r--r--contrib/ccan/ilog/test/run.c60
-rw-r--r--contrib/ccan/json/LICENSE17
-rw-r--r--contrib/ccan/json/_info119
-rw-r--r--contrib/ccan/json/json.c1381
-rw-r--r--contrib/ccan/json/json.h117
-rw-r--r--contrib/ccan/json/test/common.h18
-rw-r--r--contrib/ccan/json/test/run-construction.c191
-rw-r--r--contrib/ccan/json/test/run-decode-encode.c77
-rw-r--r--contrib/ccan/json/test/run-stringify.c108
-rw-r--r--contrib/ccan/json/test/run-validate.c49
-rw-r--r--contrib/ccan/json/test/test-strings224
-rw-r--r--contrib/ccan/json/test/test-strings-reencoded90
-rw-r--r--contrib/cleanup.h37
-rw-r--r--contrib/config.h6
-rw-r--r--contrib/contrib.mk22
-rw-r--r--contrib/licenses/BSD-MIT17
-rw-r--r--contrib/licenses/CC028
-rw-r--r--contrib/licenses/LGPL2502
-rw-r--r--contrib/lmdb/LICENSE47
-rw-r--r--contrib/lmdb/lmdb.h1604
-rw-r--r--contrib/lmdb/mdb.c10258
-rw-r--r--contrib/lmdb/midl.c359
-rw-r--r--contrib/lmdb/midl.h186
-rw-r--r--contrib/murmurhash3/LICENSE28
-rw-r--r--contrib/murmurhash3/murmurhash3.c74
-rw-r--r--contrib/murmurhash3/murmurhash3.h6
-rw-r--r--contrib/ucw/LICENSE502
-rw-r--r--contrib/ucw/alloc.h36
-rw-r--r--contrib/ucw/config.h58
-rw-r--r--contrib/ucw/lib.h125
-rw-r--r--contrib/ucw/mempool-fmt.c100
-rw-r--r--contrib/ucw/mempool.c601
-rw-r--r--contrib/ucw/mempool.h565
-rw-r--r--contrib/wire.h175
-rw-r--r--coverage.mk55
-rw-r--r--daemon/README.rst1394
-rw-r--r--daemon/bindings.c1849
-rw-r--r--daemon/bindings.h88
-rw-r--r--daemon/cache.test/clear.test.lua211
-rw-r--r--daemon/cache.test/testroot.zone1256
-rw-r--r--daemon/cache.test/testroot.zone.unsigned215
-rw-r--r--daemon/daemon.mk79
-rw-r--r--daemon/engine.c1055
-rw-r--r--daemon/engine.h89
-rw-r--r--daemon/ffimodule.c289
-rw-r--r--daemon/ffimodule.h33
-rw-r--r--daemon/io.c494
-rw-r--r--daemon/io.h46
-rw-r--r--daemon/lua/config.lua35
-rw-r--r--daemon/lua/kres-gen.lua430
-rwxr-xr-xdaemon/lua/kres-gen.sh216
-rw-r--r--daemon/lua/kres.lua952
-rw-r--r--daemon/lua/sandbox.lua458
-rw-r--r--daemon/lua/trust_anchors.lua.in663
-rw-r--r--daemon/lua/trust_anchors.test/bootstrap.test.lua108
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_extra_attr.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_elem_extra.xml17
-rw-r--r--daemon/lua/trust_anchors.test/err_elem_missing.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_multi_ta.xml19
-rw-r--r--daemon/lua/trust_anchors.test/ok0_badtimes.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok1.xml10
-rw-r--r--daemon/lua/trust_anchors.test/ok1_expired1.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok1_notyet1.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok2.xml16
-rwxr-xr-xdaemon/lua/trust_anchors.test/regen.sh2
-rw-r--r--daemon/lua/trust_anchors.test/unsupp_nonroot.xml10
-rw-r--r--daemon/lua/trust_anchors.test/unsupp_xml_v11.xml10
-rw-r--r--daemon/lua/trust_anchors.test/webserv.lua234
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca.pem24
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca.tmpl3
-rwxr-xr-xdaemon/lua/trust_anchors.test/x509/gen.sh11
-rw-r--r--daemon/lua/trust_anchors.test/x509/server-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/server.pem26
-rw-r--r--daemon/lua/trust_anchors.test/x509/server.tmpl6
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca.pem24
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca.tmpl3
-rw-r--r--daemon/lua/zonefile.lua91
-rw-r--r--daemon/main.c840
-rw-r--r--daemon/network.c446
-rw-r--r--daemon/network.h70
-rw-r--r--daemon/session.c767
-rw-r--r--daemon/session.h147
-rw-r--r--daemon/tls.c1282
-rw-r--r--daemon/tls.h224
-rw-r--r--daemon/tls_ephemeral_credentials.c249
-rw-r--r--daemon/tls_session_ticket-srv.c262
-rw-r--r--daemon/worker.c2010
-rw-r--r--daemon/worker.h171
-rw-r--r--daemon/zimport.c818
-rw-r--r--daemon/zimport.h68
-rw-r--r--distro/arch/PKGBUILD56
-rw-r--r--distro/arch/install15
-rw-r--r--distro/common/kresd.conf19
-rw-r--r--distro/common/kresd.no_ta.conf19
-rw-r--r--distro/common/root.keys2
-rw-r--r--distro/common/systemd/README.md31
-rw-r--r--distro/common/systemd/drop-in/listen-tls.conf7
-rw-r--r--distro/common/systemd/drop-in/listen-udp-tcp.conf8
-rw-r--r--distro/common/systemd/drop-in/systemd-compat.conf17
-rw-r--r--distro/common/systemd/kresd-control@.socket16
-rw-r--r--distro/common/systemd/kresd-tls.socket16
-rw-r--r--distro/common/systemd/kresd.socket17
-rw-r--r--distro/common/systemd/kresd.systemd.7230
-rw-r--r--distro/common/systemd/kresd.target8
-rw-r--r--distro/common/systemd/kresd@.service17
-rw-r--r--distro/common/tmpfiles/knot-resolver.conf4
-rw-r--r--distro/deb/NEWS23
-rw-r--r--distro/deb/README.source70
-rw-r--r--distro/deb/changelog6
-rw-r--r--distro/deb/clean4
-rw-r--r--distro/deb/compat1
-rw-r--r--distro/deb/control137
-rw-r--r--distro/deb/copyright448
-rw-r--r--distro/deb/docs1
-rwxr-xr-xdistro/deb/init-d-script239
-rw-r--r--distro/deb/knot-resolver-doc.doc-base11
-rw-r--r--distro/deb/knot-resolver-doc.docs1
-rw-r--r--distro/deb/knot-resolver-doc.links2
-rw-r--r--distro/deb/knot-resolver-module-http.install6
-rw-r--r--distro/deb/knot-resolver-module-http.links5
-rw-r--r--distro/deb/knot-resolver-module-tinyweb.install1
-rw-r--r--distro/deb/knot-resolver.dirs3
-rw-r--r--distro/deb/knot-resolver.install38
-rw-r--r--distro/deb/knot-resolver.kresd.default13
-rw-r--r--distro/deb/knot-resolver.kresd.init59
-rw-r--r--distro/deb/knot-resolver.links2
-rw-r--r--distro/deb/knot-resolver.manpages2
-rw-r--r--distro/deb/knot-resolver.postinst30
-rw-r--r--distro/deb/knot-resolver.postrm8
-rw-r--r--distro/deb/knot-resolver.triggers1
-rw-r--r--distro/deb/kresd.conf19
-rw-r--r--distro/deb/libkres-dev.install3
-rw-r--r--distro/deb/libkres9.install1
-rw-r--r--distro/deb/libkres9.symbols144
-rw-r--r--distro/deb/not-installed1
-rw-r--r--distro/deb/patches/0001-Update-documentation-of-keyfile-ro.patch41
-rw-r--r--distro/deb/patches/series1
-rwxr-xr-xdistro/deb/rules68
-rw-r--r--distro/deb/source/format1
-rw-r--r--distro/deb/tests/control2
-rw-r--r--distro/rpm/knot-resolver.spec235
-rw-r--r--distro/tests/README.md42
-rw-r--r--distro/tests/arch/Vagrantfile16
-rw-r--r--distro/tests/centos7/Vagrantfile19
-rw-r--r--distro/tests/debian9/Vagrantfile16
-rw-r--r--distro/tests/fedora28/Vagrantfile19
-rw-r--r--distro/tests/fedora29/Vagrantfile19
-rw-r--r--distro/tests/knot-resolver-test.yaml148
-rw-r--r--distro/tests/leap15/Vagrantfile16
-rw-r--r--distro/tests/repos.yaml3
-rwxr-xr-xdistro/tests/test-distro.sh32
-rw-r--r--distro/tests/tumbleweed/Vagrantfile16
-rw-r--r--distro/tests/ubuntu1604/Vagrantfile19
-rw-r--r--distro/tests/ubuntu1804/Vagrantfile19
-rw-r--r--distro/tests/ubuntu1810/Vagrantfile19
-rw-r--r--doc/Doxyfile19
-rw-r--r--doc/NEWS.rst6
-rw-r--r--doc/README.md27
-rw-r--r--doc/_static/.gitignore0
-rw-r--r--doc/build.rst321
-rw-r--r--doc/conf.py71
-rw-r--r--doc/daemon.rst1
-rw-r--r--doc/doc.mk14
-rw-r--r--doc/index.rst26
-rw-r--r--doc/kresd.8.in172
-rw-r--r--doc/lib.rst58
-rw-r--r--doc/modules.rst37
-rw-r--r--doc/modules_api.rst1
-rw-r--r--doc/requirements.txt2
-rw-r--r--doc/resolution.pngbin0 -> 95991 bytes
-rw-r--r--etc/config.cluster40
-rw-r--r--etc/config.docker39
-rw-r--r--etc/config.isp36
-rw-r--r--etc/config.personal23
-rw-r--r--etc/config.splitview33
-rw-r--r--etc/etc.mk16
-rw-r--r--etc/icann-ca.pem82
-rw-r--r--etc/root.hints92
-rw-r--r--lib/README.rst314
-rw-r--r--lib/cache/api.c889
-rw-r--r--lib/cache/api.h201
-rw-r--r--lib/cache/cdb_api.h68
-rw-r--r--lib/cache/cdb_lmdb.c710
-rw-r--r--lib/cache/cdb_lmdb.h23
-rw-r--r--lib/cache/entry_list.c293
-rw-r--r--lib/cache/entry_pkt.c224
-rw-r--r--lib/cache/entry_rr.c146
-rw-r--r--lib/cache/impl.h412
-rw-r--r--lib/cache/knot_pkt.c106
-rw-r--r--lib/cache/nsec1.c511
-rw-r--r--lib/cache/nsec3.c501
-rw-r--r--lib/cache/peek.c724
-rw-r--r--lib/cookies/alg_containers.c72
-rw-r--r--lib/cookies/alg_containers.h49
-rw-r--r--lib/cookies/alg_sha.c122
-rw-r--r--lib/cookies/alg_sha.h30
-rw-r--r--lib/cookies/control.h49
-rw-r--r--lib/cookies/helper.c296
-rw-r--r--lib/cookies/helper.h86
-rw-r--r--lib/cookies/lru_cache.c70
-rw-r--r--lib/cookies/lru_cache.h69
-rw-r--r--lib/cookies/nonce.c34
-rw-r--r--lib/cookies/nonce.h43
-rw-r--r--lib/defines.h102
-rw-r--r--lib/dnssec.c473
-rw-r--r--lib/dnssec.h152
-rw-r--r--lib/dnssec/nsec.c540
-rw-r--r--lib/dnssec/nsec.h105
-rw-r--r--lib/dnssec/nsec3.c776
-rw-r--r--lib/dnssec/nsec3.h82
-rw-r--r--lib/dnssec/signature.c307
-rw-r--r--lib/dnssec/signature.h42
-rw-r--r--lib/dnssec/ta.c185
-rw-r--r--lib/dnssec/ta.h87
-rw-r--r--lib/generic/README.rst60
-rw-r--r--lib/generic/array.h166
-rw-r--r--lib/generic/lru.c236
-rw-r--r--lib/generic/lru.h249
-rw-r--r--lib/generic/map.c354
-rw-r--r--lib/generic/map.h115
-rw-r--r--lib/generic/pack.h249
-rw-r--r--lib/generic/queue.c124
-rw-r--r--lib/generic/queue.h260
-rw-r--r--lib/generic/set.h105
-rw-r--r--lib/generic/trie.c912
-rw-r--r--lib/generic/trie.h150
-rw-r--r--lib/layer.h107
-rw-r--r--lib/layer/cache.c31
-rw-r--r--lib/layer/iterate.c1135
-rw-r--r--lib/layer/iterate.h36
-rw-r--r--lib/layer/validate.c1133
-rw-r--r--lib/lib.mk110
-rw-r--r--lib/module.c170
-rw-r--r--lib/module.h111
-rw-r--r--lib/nsrep.c563
-rw-r--r--lib/nsrep.h188
-rw-r--r--lib/resolve.c1648
-rw-r--r--lib/resolve.h332
-rw-r--r--lib/rplan.c308
-rw-r--r--lib/rplan.h221
-rw-r--r--lib/utils.c1084
-rw-r--r--lib/utils.h495
-rw-r--r--lib/zonecut.c597
-rw-r--r--lib/zonecut.h173
-rw-r--r--modules/README.rst331
-rw-r--r--modules/bogus_log/README.rst41
-rw-r--r--modules/bogus_log/bogus_log.c150
-rw-r--r--modules/bogus_log/bogus_log.mk8
-rw-r--r--modules/bogus_log/test.integr/deckard.yaml13
-rw-r--r--modules/bogus_log/test.integr/kresd_config.j282
-rw-r--r--modules/bogus_log/test.integr/val_minimal_expiredsignature.rpl124
-rw-r--r--modules/cookies/README.rst54
-rw-r--r--modules/cookies/cookiectl.c684
-rw-r--r--modules/cookies/cookiectl.h47
-rw-r--r--modules/cookies/cookiemonster.c469
-rw-r--r--modules/cookies/cookiemonster.h27
-rw-r--r--modules/cookies/cookies.c100
-rw-r--r--modules/cookies/cookies.mk8
-rw-r--r--modules/daf/README.rst137
-rw-r--r--modules/daf/daf.js294
-rw-r--r--modules/daf/daf.lua353
-rw-r--r--modules/daf/daf.mk3
-rw-r--r--modules/detect_time_jump/README.rst20
-rw-r--r--modules/detect_time_jump/detect_time_jump.lua44
-rw-r--r--modules/detect_time_jump/detect_time_jump.mk2
-rw-r--r--modules/detect_time_skew/README.rst21
-rw-r--r--modules/detect_time_skew/detect_time_skew.lua85
-rw-r--r--modules/detect_time_skew/detect_time_skew.mk2
-rw-r--r--modules/dns64/README.rst26
-rw-r--r--modules/dns64/dns64.lua103
-rw-r--r--modules/dns64/dns64.mk2
-rw-r--r--modules/dns64/dns64.test.lua52
-rw-r--r--modules/dnstap/README.rst24
-rw-r--r--modules/dnstap/dnstap.c382
-rw-r--r--modules/dnstap/dnstap.mk8
-rw-r--r--modules/dnstap/dnstap.pb-c.c523
-rw-r--r--modules/dnstap/dnstap.pb-c.h343
-rw-r--r--modules/dnstap/dnstap.proto269
-rw-r--r--modules/edns_keepalive/README.rst12
-rw-r--r--modules/edns_keepalive/edns_keepalive.c77
-rw-r--r--modules/edns_keepalive/edns_keepalive.mk5
-rw-r--r--modules/etcd/README.rst44
-rw-r--r--modules/etcd/etcd.lua55
-rw-r--r--modules/etcd/etcd.mk2
-rw-r--r--modules/experimental_dot_auth/README.rst84
-rw-r--r--modules/experimental_dot_auth/basexx.lua320
-rw-r--r--modules/experimental_dot_auth/experimental_dot_auth.lua122
-rw-r--r--modules/experimental_dot_auth/experimental_dot_auth.mk2
-rw-r--r--modules/graphite/README.rst49
-rw-r--r--modules/graphite/graphite.lua141
-rw-r--r--modules/graphite/graphite.mk2
-rw-r--r--modules/hints/README.rst113
-rw-r--r--modules/hints/hints.c668
-rw-r--r--modules/hints/hints.mk8
-rw-r--r--modules/hints/tests/hints.test.lua36
-rw-r--r--modules/hints/tests/hints_test.zone1
-rw-r--r--modules/http/README.rst345
-rw-r--r--modules/http/http.lua414
-rw-r--r--modules/http/http.mk3
-rw-r--r--modules/http/http.test.lua89
-rw-r--r--modules/http/http_trace.lua109
-rw-r--r--modules/http/prometheus.lua172
-rw-r--r--modules/http/static/LICENSE7
-rw-r--r--modules/http/static/bootstrap-theme.min.css6
-rw-r--r--modules/http/static/bootstrap.min.css11
-rw-r--r--modules/http/static/bootstrap.min.js7
-rw-r--r--modules/http/static/d3.js5
-rw-r--r--modules/http/static/datamaps.world.min.js2
-rw-r--r--modules/http/static/dygraph-combined.js6
-rw-r--r--modules/http/static/epoch.css1
-rw-r--r--modules/http/static/epoch.js3
-rw-r--r--modules/http/static/favicon.icobin0 -> 1498 bytes
-rw-r--r--modules/http/static/glyphicons-halflings-regular.woff2bin0 -> 18028 bytes
-rw-r--r--modules/http/static/jquery.js4
-rw-r--r--modules/http/static/kresd.css43
-rw-r--r--modules/http/static/kresd.js366
-rw-r--r--modules/http/static/main.tpl87
-rw-r--r--modules/http/static/selectize.bootstrap3.min.css1
-rw-r--r--modules/http/static/selectize.min.css1
-rw-r--r--modules/http/static/selectize.min.js3
-rw-r--r--modules/http/static/topojson.js1
-rw-r--r--modules/http/test_tls/broken.crt3
-rw-r--r--modules/http/test_tls/broken.keybin0 -> 512 bytes
-rw-r--r--modules/http/test_tls/test.crt10
-rw-r--r--modules/http/test_tls/test.key9
-rw-r--r--modules/http/test_tls/tls.test.lua164
-rw-r--r--modules/modules.mk106
-rw-r--r--modules/nsid/README.rst35
-rw-r--r--modules/nsid/nsid.c122
-rw-r--r--modules/nsid/nsid.mk6
-rw-r--r--modules/nsid/nsid.test.lua21
-rw-r--r--modules/policy/README.rst284
-rw-r--r--modules/policy/lua-aho-corasick/.gitignore6
-rw-r--r--modules/policy/lua-aho-corasick/LICENSE28
-rw-r--r--modules/policy/lua-aho-corasick/Makefile134
-rw-r--r--modules/policy/lua-aho-corasick/README.md40
-rw-r--r--modules/policy/lua-aho-corasick/ac.cxx101
-rw-r--r--modules/policy/lua-aho-corasick/ac.h49
-rw-r--r--modules/policy/lua-aho-corasick/ac_fast.cxx468
-rw-r--r--modules/policy/lua-aho-corasick/ac_fast.hpp124
-rw-r--r--modules/policy/lua-aho-corasick/ac_lua.cxx173
-rw-r--r--modules/policy/lua-aho-corasick/ac_slow.cxx318
-rw-r--r--modules/policy/lua-aho-corasick/ac_slow.hpp158
-rw-r--r--modules/policy/lua-aho-corasick/ac_util.hpp69
-rw-r--r--modules/policy/lua-aho-corasick/load_ac.lua90
-rw-r--r--modules/policy/lua-aho-corasick/mytest.cxx200
-rw-r--r--modules/policy/lua-aho-corasick/tests/Makefile65
-rw-r--r--modules/policy/lua-aho-corasick/tests/ac_bench.cxx519
-rw-r--r--modules/policy/lua-aho-corasick/tests/ac_test_aggr.cxx135
-rw-r--r--modules/policy/lua-aho-corasick/tests/ac_test_simple.cxx275
-rw-r--r--modules/policy/lua-aho-corasick/tests/dict/README.txt1
-rw-r--r--modules/policy/lua-aho-corasick/tests/dict/dict1.txt11
-rw-r--r--modules/policy/lua-aho-corasick/tests/load_ac_test.lua82
-rw-r--r--modules/policy/lua-aho-corasick/tests/lua_test.lua67
-rw-r--r--modules/policy/lua-aho-corasick/tests/test_base.hpp60
-rw-r--r--modules/policy/lua-aho-corasick/tests/test_bigfile.cxx167
-rw-r--r--modules/policy/lua-aho-corasick/tests/test_main.cxx33
-rw-r--r--modules/policy/noipv6.test.integr/broken-ipv6.rpl46
-rw-r--r--modules/policy/noipv6.test.integr/deckard.yaml12
-rw-r--r--modules/policy/noipv6.test.integr/kresd_config.j250
-rw-r--r--modules/policy/noipvx.test.integr/broken-ipvx.rpl34
-rw-r--r--modules/policy/noipvx.test.integr/deckard.yaml12
-rw-r--r--modules/policy/noipvx.test.integr/kresd_config.j251
-rw-r--r--modules/policy/policy.lua756
-rw-r--r--modules/policy/policy.mk15
-rw-r--r--modules/policy/policy.test.lua52
-rw-r--r--modules/policy/test.integr/deckard.yaml12
-rw-r--r--modules/policy/test.integr/kresd_config.j249
-rw-r--r--modules/policy/test.integr/refuse.rpl24
-rw-r--r--modules/predict/README.rst51
-rw-r--r--modules/predict/predict.lua186
-rw-r--r--modules/predict/predict.mk2
-rw-r--r--modules/predict/tests/predict.test.lua60
-rw-r--r--modules/prefill/README.rst41
-rw-r--r--modules/prefill/prefill.lua208
-rw-r--r--modules/prefill/prefill.mk2
-rw-r--r--modules/priming/README.rst17
-rw-r--r--modules/priming/priming.lua129
-rw-r--r--modules/priming/priming.mk2
-rw-r--r--modules/rebinding/README.rst25
-rw-r--r--modules/rebinding/rebinding.lua112
-rw-r--r--modules/rebinding/rebinding.mk2
-rw-r--r--modules/rebinding/test.integr/deckard.yaml12
-rw-r--r--modules/rebinding/test.integr/kresd_config.j249
-rw-r--r--modules/rebinding/test.integr/module_rebinding.rpl833
-rw-r--r--modules/renumber/README.rst25
-rw-r--r--modules/renumber/renumber.lua126
-rw-r--r--modules/renumber/renumber.mk2
-rw-r--r--modules/rfc7706.rst3
-rw-r--r--modules/serve_stale/README.rst21
-rw-r--r--modules/serve_stale/serve_stale.lua44
-rw-r--r--modules/serve_stale/serve_stale.mk2
-rw-r--r--modules/serve_stale/test.integr/deckard.yaml12
-rw-r--r--modules/serve_stale/test.integr/kresd_config.j249
-rw-r--r--modules/serve_stale/test.integr/module_serve_stale.rpl278
-rw-r--r--modules/stats/README.rst163
-rw-r--r--modules/stats/stats.c502
-rw-r--r--modules/stats/stats.mk5
-rw-r--r--modules/stats/test.integr/deckard.yaml12
-rw-r--r--modules/stats/test.integr/kresd_config.j299
-rw-r--r--modules/stats/test.integr/stats.rpl193
-rw-r--r--modules/ta_sentinel/README.rst17
-rw-r--r--modules/ta_sentinel/ta_sentinel.lua88
-rw-r--r--modules/ta_sentinel/ta_sentinel.mk2
-rw-r--r--modules/ta_signal_query/README.rst22
-rw-r--r--modules/ta_signal_query/ta_signal_query.lua62
-rw-r--r--modules/ta_signal_query/ta_signal_query.mk2
-rw-r--r--modules/view/README.rst89
-rw-r--r--modules/view/addr.test.integr/deckard.yaml12
-rw-r--r--modules/view/addr.test.integr/kresd_config.j253
-rw-r--r--modules/view/addr.test.integr/module_view_addr.rpl78
-rw-r--r--modules/view/tsig.test.integr/deckard.yaml12
-rw-r--r--modules/view/tsig.test.integr/kresd_config.j255
-rw-r--r--modules/view/tsig.test.integr/module_view_tsig.rpl113
-rw-r--r--modules/view/view.lua118
-rw-r--r--modules/view/view.mk2
-rw-r--r--modules/workarounds/README.rst14
-rw-r--r--modules/workarounds/workarounds.lua54
-rw-r--r--modules/workarounds/workarounds.mk2
-rw-r--r--platform.mk230
-rwxr-xr-xscripts/build-in-obs.sh29
-rwxr-xr-xscripts/coverage_c_combine.sh24
-rwxr-xr-xscripts/coverage_env.sh40
-rwxr-xr-xscripts/embed-lua.sh10
-rwxr-xr-xscripts/gen-cdefs.sh72
-rwxr-xr-xscripts/kresd-host.lua114
-rwxr-xr-xscripts/kresd-query.lua64
-rw-r--r--scripts/kresd.apparmor29
-rwxr-xr-xscripts/launch-test-instance.sh26
-rwxr-xr-xscripts/luacov_gen_empty.sh17
-rwxr-xr-xscripts/luacov_to_info.lua56
-rwxr-xr-xscripts/make-archive.sh15
-rwxr-xr-xscripts/make-distrofiles.sh53
-rwxr-xr-xscripts/make-srpm.sh13
-rwxr-xr-xscripts/map_install_src.lua167
-rwxr-xr-xscripts/obs-testbuild.sh38
-rw-r--r--tests/.gitignore6
-rw-r--r--tests/README.rst29
-rwxr-xr-xtests/clang_scan_build.sh51
-rw-r--r--tests/config/basic.test.lua202
-rw-r--r--tests/config/cache.test.lua59
-rw-r--r--tests/config/keyfile/bad_args.args1
-rw-r--r--tests/config/keyfile/bad_args.returncode1
-rw-r--r--tests/config/keyfile/bad_args.test.lua0
-rw-r--r--tests/config/keyfile/load_ta.args1
-rw-r--r--tests/config/keyfile/load_ta.test.lua37
-rw-r--r--tests/config/keyfile/nonexist_keyfile1.args1
-rw-r--r--tests/config/keyfile/nonexist_keyfile1.returncode1
-rw-r--r--tests/config/keyfile/nonexist_keyfile1.test.lua2
-rw-r--r--tests/config/keyfile/nonexist_keyfile2.args1
-rw-r--r--tests/config/keyfile/nonexist_keyfile2.returncode1
-rw-r--r--tests/config/keyfile/nonexist_keyfile2.test.lua2
-rw-r--r--tests/config/keyfile/root1.keys1
-rw-r--r--tests/config/keyfile/root2.keys1
-rw-r--r--tests/config/lru.test.lua83
-rwxr-xr-xtests/config/runtest.sh23
-rw-r--r--tests/config/tapered/.travis.yml40
-rw-r--r--tests/config/tapered/.travis/platform.sh15
-rw-r--r--tests/config/tapered/.travis/setenv_lua.sh3
-rw-r--r--tests/config/tapered/.travis/setup_lua.sh122
-rw-r--r--tests/config/tapered/CHANGES.md70
-rw-r--r--tests/config/tapered/LICENSE.md27
-rw-r--r--tests/config/tapered/README.md116
-rw-r--r--tests/config/tapered/doc/changes.html104
-rw-r--r--tests/config/tapered/doc/index.html111
-rw-r--r--tests/config/tapered/doc/license.html40
-rw-r--r--tests/config/tapered/doc/normalize.css439
-rw-r--r--tests/config/tapered/doc/screen.css109
-rwxr-xr-xtests/config/tapered/make-doc.bash55
-rw-r--r--tests/config/tapered/src/tapered.lua189
-rw-r--r--tests/config/tapered/tapered-1.1-0.rockspec21
-rw-r--r--tests/config/tapered/tapered-1.2.0-1.rockspec21
-rw-r--r--tests/config/tapered/tapered-1.2.1-1.rockspec21
-rw-r--r--tests/config/tapered/tapered-2.0.0-1.rockspec21
-rw-r--r--tests/config/tapered/tapered-2.0.1-1.rockspec21
-rw-r--r--tests/config/tapered/tapered-2.1.0-1.rockspec21
-rw-r--r--tests/config/tapered/tapered-2.2.0-1.rockspec22
-rw-r--r--tests/config/tapered/tapered-2.3.0-1.rockspec22
-rw-r--r--tests/config/tapered/test/.luacov55
-rw-r--r--tests/config/tapered/test/boom-result.txt7
-rwxr-xr-xtests/config/tapered/test/boom-test.lua19
-rw-r--r--tests/config/tapered/test/done-failure-result.txt2
-rw-r--r--tests/config/tapered/test/done-failure-test.lua5
-rw-r--r--tests/config/tapered/test/done-success-result.txt2
-rw-r--r--tests/config/tapered/test/done-success-test.lua5
-rw-r--r--tests/config/tapered/test/dynamic-setup-teardown-result.txt10
-rwxr-xr-xtests/config/tapered/test/dynamic-setup-teardown-test.lua27
-rwxr-xr-xtests/config/tapered/test/exit-failure-test.lua6
-rwxr-xr-xtests/config/tapered/test/exit-success-test.lua6
-rw-r--r--tests/config/tapered/test/informational-fields-result.txt4
-rwxr-xr-xtests/config/tapered/test/informational-fields-test.lua8
-rw-r--r--tests/config/tapered/test/is-isnt-result.txt43
-rwxr-xr-xtests/config/tapered/test/is-isnt-test.lua36
-rw-r--r--tests/config/tapered/test/like-unlike-result.txt13
-rwxr-xr-xtests/config/tapered/test/like-unlike-test.lua16
-rw-r--r--tests/config/tapered/test/ok-nok-result.txt7
-rwxr-xr-xtests/config/tapered/test/ok-nok-test.lua11
-rw-r--r--tests/config/tapered/test/pass-fail-result.txt4
-rwxr-xr-xtests/config/tapered/test/pass-fail-test.lua11
-rw-r--r--tests/config/tapered/test/result_test03.txt55
-rwxr-xr-xtests/config/tapered/test/runner.bash71
-rw-r--r--tests/config/tapered/test/same-result.txt31
-rw-r--r--tests/config/tapered/test/same-test.lua74
-rw-r--r--tests/config/tapered/test/setup-teardown-result.txt4
-rwxr-xr-xtests/config/tapered/test/setup-teardown-test.lua14
-rw-r--r--tests/config/test.cfg27
-rw-r--r--tests/config/test_config.mk24
-rw-r--r--tests/config/test_utils.lua41
-rw-r--r--tests/config/tls.test.lua24
-rw-r--r--tests/config/worker_test.lua64
-rw-r--r--tests/deckard/.gitignore20
-rw-r--r--tests/deckard/.gitlab-ci.yml116
-rw-r--r--tests/deckard/.gitmodules6
-rw-r--r--tests/deckard/LICENSE23
-rw-r--r--tests/deckard/Makefile58
-rw-r--r--tests/deckard/README.rst98
-rw-r--r--tests/deckard/ci/README.rst4
-rw-r--r--tests/deckard/ci/common.sh17
-rwxr-xr-xtests/deckard/ci/compare-rplint.sh31
-rwxr-xr-xtests/deckard/ci/compare-tests.sh30
-rwxr-xr-xtests/deckard/ci/junit-compare.py37
-rwxr-xr-xtests/deckard/ci/mypy-run.sh13
-rwxr-xr-xtests/deckard/ci/pylint-run.sh12
-rwxr-xr-xtests/deckard/ci/runlocally.sh41
-rw-r--r--tests/deckard/configs/getdns.yaml12
-rw-r--r--tests/deckard/configs/knotd_master.yaml10
-rw-r--r--tests/deckard/configs/knotd_slave.yaml10
-rw-r--r--tests/deckard/configs/kresd.yaml10
-rw-r--r--tests/deckard/configs/pdns.yaml15
-rw-r--r--tests/deckard/configs/unbound.yaml13
-rw-r--r--tests/deckard/conftest.py156
-rw-r--r--tests/deckard/contrib/deckard.vim26
-rw-r--r--tests/deckard/contrib/libfaketime/.gitignore9
-rw-r--r--tests/deckard/contrib/libfaketime/COPYING339
-rw-r--r--tests/deckard/contrib/libfaketime/Makefile34
-rw-r--r--tests/deckard/contrib/libfaketime/NEWS134
-rw-r--r--tests/deckard/contrib/libfaketime/README534
-rw-r--r--tests/deckard/contrib/libfaketime/README.OSX144
-rw-r--r--tests/deckard/contrib/libfaketime/README.developers106
-rw-r--r--tests/deckard/contrib/libfaketime/TODO9
-rw-r--r--tests/deckard/contrib/libfaketime/man/Makefile14
-rw-r--r--tests/deckard/contrib/libfaketime/man/Makefile.OSX15
-rw-r--r--tests/deckard/contrib/libfaketime/man/faketime.182
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Arch/PKGBUILD-32bit.txt25
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Debian/avoid-spurious-lrt.patch30
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Debian/control40
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Debian/fix-infinite-recursion-on-real_clock_gettime.patch29
-rwxr-xr-xtests/deckard/contrib/libfaketime/packaging/Linux/Debian/libfaketime.install3
-rwxr-xr-xtests/deckard/contrib/libfaketime/packaging/Linux/Debian/rules17
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime-fix-infinite-recursion-on-real_clock_gettime.patch13
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime.spec.txt55
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/OSX/Fink/libfaketime.info53
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/OSX/Homebrew/libfaketime.rb21
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/Portfile45
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/patch-test-Makefile.OSX.diff12
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/OSX/README65
-rw-r--r--tests/deckard/contrib/libfaketime/packaging/README14
-rw-r--r--tests/deckard/contrib/libfaketime/src/Makefile118
-rw-r--r--tests/deckard/contrib/libfaketime/src/Makefile.OSX75
-rw-r--r--tests/deckard/contrib/libfaketime/src/faketime.c385
-rw-r--r--tests/deckard/contrib/libfaketime/src/faketime_common.h61
-rw-r--r--tests/deckard/contrib/libfaketime/src/libfaketime.c2646
-rw-r--r--tests/deckard/contrib/libfaketime/src/libfaketime.map21
-rw-r--r--tests/deckard/contrib/libfaketime/src/sunos_endian.h12
-rw-r--r--tests/deckard/contrib/libfaketime/src/time_ops.h104
-rw-r--r--tests/deckard/contrib/libfaketime/src/timeprivacy270
-rw-r--r--tests/deckard/contrib/libfaketime/src/uthash.h1208
-rw-r--r--tests/deckard/contrib/libfaketime/test/Makefile31
-rw-r--r--tests/deckard/contrib/libfaketime/test/Makefile.OSX30
-rw-r--r--tests/deckard/contrib/libfaketime/test/README-testframe.txt39
-rw-r--r--tests/deckard/contrib/libfaketime/test/functests/common.inc63
-rw-r--r--tests/deckard/contrib/libfaketime/test/functests/dont_test_false.sh6
-rw-r--r--tests/deckard/contrib/libfaketime/test/functests/test_exclude_mono.sh87
-rw-r--r--tests/deckard/contrib/libfaketime/test/functests/test_null.sh13
-rw-r--r--tests/deckard/contrib/libfaketime/test/functests/test_true.sh7
-rwxr-xr-xtests/deckard/contrib/libfaketime/test/functests/test_walkone.sh67
-rwxr-xr-xtests/deckard/contrib/libfaketime/test/test.sh66
-rwxr-xr-xtests/deckard/contrib/libfaketime/test/test_OSX.sh46
-rw-r--r--tests/deckard/contrib/libfaketime/test/testframe.inc55
-rwxr-xr-xtests/deckard/contrib/libfaketime/test/testframe.sh99
-rw-r--r--tests/deckard/contrib/libfaketime/test/timetest.c284
-rw-r--r--tests/deckard/contrib/libswrap/.gitignore9
-rw-r--r--tests/deckard/contrib/libswrap/AUTHORS3
-rw-r--r--tests/deckard/contrib/libswrap/CMakeLists.txt86
-rw-r--r--tests/deckard/contrib/libswrap/COPYING32
-rw-r--r--tests/deckard/contrib/libswrap/CPackConfig.cmake53
-rw-r--r--tests/deckard/contrib/libswrap/CTestConfig.cmake9
-rw-r--r--tests/deckard/contrib/libswrap/ChangeLog60
-rw-r--r--tests/deckard/contrib/libswrap/ConfigureChecks.cmake232
-rw-r--r--tests/deckard/contrib/libswrap/DefineOptions.cmake1
-rw-r--r--tests/deckard/contrib/libswrap/README21
-rw-r--r--tests/deckard/contrib/libswrap/README.install78
-rw-r--r--tests/deckard/contrib/libswrap/TODO33
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/AddCMockaTest.cmake23
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/COPYING-CMAKE-SCRIPTS22
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/CheckCCompilerFlagSSP.cmake26
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/DefineCMakeDefaults.cmake30
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/DefineCompilerFlags.cmake93
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/DefineInstallationPaths.cmake109
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/DefinePlatformDefaults.cmake32
-rw-r--r--tests/deckard/contrib/libswrap/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake17
-rw-r--r--tests/deckard/contrib/libswrap/config.h.cmake74
-rw-r--r--tests/deckard/contrib/libswrap/doc/CMakeLists.txt4
-rw-r--r--tests/deckard/contrib/libswrap/doc/README3
-rw-r--r--tests/deckard/contrib/libswrap/doc/socket_wrapper.1204
-rw-r--r--tests/deckard/contrib/libswrap/doc/socket_wrapper.1.txt95
-rwxr-xr-xtests/deckard/contrib/libswrap/example/openssh.sh66
-rw-r--r--tests/deckard/contrib/libswrap/socket_wrapper-config-version.cmake.in11
-rw-r--r--tests/deckard/contrib/libswrap/socket_wrapper-config.cmake.in1
-rw-r--r--tests/deckard/contrib/libswrap/socket_wrapper.pc.cmake4
-rw-r--r--tests/deckard/contrib/libswrap/src/CMakeLists.txt26
-rw-r--r--tests/deckard/contrib/libswrap/src/socket_wrapper.c5475
-rw-r--r--tests/deckard/contrib/libswrap/tests/CMakeLists.txt57
-rw-r--r--tests/deckard/contrib/libswrap/tests/README9
-rw-r--r--tests/deckard/contrib/libswrap/tests/echo_srv.c925
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_bind.c536
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_connect.c101
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_get_peer_sock_name.c476
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_sendmsg_recvmsg.c273
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket.c69
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket_options.c368
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_write_read.c156
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_tcp_writev_readv.c189
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_udp_send_recv.c160
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_udp_sendmsg_recvmsg.c407
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_echo_udp_sendto_recvfrom.c316
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_ioctl.c110
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_sendmsg_recvmsg_fd.c116
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_swrap_unit.c120
-rw-r--r--tests/deckard/contrib/libswrap/tests/test_tcp_listen.c115
-rw-r--r--tests/deckard/contrib/libswrap/tests/torture.c318
-rw-r--r--tests/deckard/contrib/libswrap/tests/torture.h88
-rw-r--r--tests/deckard/contrib/libswrap/tests/valgrind.supp16
-rwxr-xr-xtests/deckard/deckard.py432
-rw-r--r--tests/deckard/deckard_pytest.ini7
-rwxr-xr-xtests/deckard/deckard_pytest.py67
-rw-r--r--tests/deckard/doc/devel_guide.rst25
-rw-r--r--tests/deckard/doc/scenario_example.rst337
-rw-r--r--tests/deckard/doc/scenario_guide.rst431
-rw-r--r--tests/deckard/doc/user_guide.rst297
-rwxr-xr-xtests/deckard/getdns_run.sh63
-rwxr-xr-xtests/deckard/knotd_master_run.sh6
-rwxr-xr-xtests/deckard/knotd_slave_run.sh6
-rwxr-xr-xtests/deckard/kresd_run.sh5
-rwxr-xr-xtests/deckard/pdns_run.sh5
-rw-r--r--tests/deckard/platform.mk27
-rw-r--r--tests/deckard/pydnstest/__init__.py0
-rw-r--r--tests/deckard/pydnstest/augwrap.py227
-rw-r--r--tests/deckard/pydnstest/deckard.aug94
-rw-r--r--tests/deckard/pydnstest/empty.rpl20
-rw-r--r--tests/deckard/pydnstest/matchpart.py238
-rw-r--r--tests/deckard/pydnstest/scenario.py1058
-rw-r--r--tests/deckard/pydnstest/tests/__init__.py0
-rw-r--r--tests/deckard/pydnstest/tests/test_parse_config.py17
-rw-r--r--tests/deckard/pydnstest/tests/test_scenario.py55
-rw-r--r--tests/deckard/pydnstest/testserver.py278
-rw-r--r--tests/deckard/pylintrc26
-rw-r--r--tests/deckard/requirements.txt7
-rwxr-xr-xtests/deckard/rplint.py335
-rwxr-xr-xtests/deckard/rplint.sh5
-rw-r--r--tests/deckard/rplint_pytest.ini4
-rwxr-xr-xtests/deckard/run.sh12
-rw-r--r--tests/deckard/sets/knotd/master/example.com.zone22
-rw-r--r--tests/deckard/sets/knotd/master/iter_ns.rpl28
-rw-r--r--tests/deckard/sets/knotd/slave/iter_ns.rpl78
-rw-r--r--tests/deckard/sets/resolver/LICENSE30
-rw-r--r--tests/deckard/sets/resolver/black_data.rpl300
-rw-r--r--tests/deckard/sets/resolver/black_dnskey.rpl508
-rw-r--r--tests/deckard/sets/resolver/black_ds.rpl418
-rw-r--r--tests/deckard/sets/resolver/black_ent.rpl451
-rw-r--r--tests/deckard/sets/resolver/black_prime.rpl300
-rw-r--r--tests/deckard/sets/resolver/iter_badglue.rpl272
-rw-r--r--tests/deckard/sets/resolver/iter_badraw.rpl18699
-rw-r--r--tests/deckard/sets/resolver/iter_cname_badauth.rpl267
-rw-r--r--tests/deckard/sets/resolver/iter_cname_cache.rpl297
-rw-r--r--tests/deckard/sets/resolver/iter_cname_double.rpl294
-rw-r--r--tests/deckard/sets/resolver/iter_cname_nx.rpl288
-rw-r--r--tests/deckard/sets/resolver/iter_cname_qnamecopy.rpl331
-rw-r--r--tests/deckard/sets/resolver/iter_cycle.rpl258
-rw-r--r--tests/deckard/sets/resolver/iter_cycle_noh.rpl414
-rw-r--r--tests/deckard/sets/resolver/iter_dnsseclame_ds_ok.rpl369
-rw-r--r--tests/deckard/sets/resolver/iter_dnsseclame_ta_ok.rpl305
-rw-r--r--tests/deckard/sets/resolver/iter_domain_sale.rpl269
-rw-r--r--tests/deckard/sets/resolver/iter_domain_sale_nschange.rpl348
-rw-r--r--tests/deckard/sets/resolver/iter_donotq127.rpl196
-rw-r--r--tests/deckard/sets/resolver/iter_ds_locate_ns.rpl144
-rw-r--r--tests/deckard/sets/resolver/iter_ds_locate_ns_nosoa.rpl144
-rw-r--r--tests/deckard/sets/resolver/iter_escape_bailiwick.rpl218
-rw-r--r--tests/deckard/sets/resolver/iter_formerr.rpl83
-rw-r--r--tests/deckard/sets/resolver/iter_hint_lame.rpl160
-rw-r--r--tests/deckard/sets/resolver/iter_lame_aaaa.rpl178
-rw-r--r--tests/deckard/sets/resolver/iter_lame_noaa.rpl124
-rw-r--r--tests/deckard/sets/resolver/iter_lame_nosoa.rpl291
-rw-r--r--tests/deckard/sets/resolver/iter_lame_root.rpl33
-rw-r--r--tests/deckard/sets/resolver/iter_lamescrub.rpl150
-rw-r--r--tests/deckard/sets/resolver/iter_minim_a.rpl93
-rw-r--r--tests/deckard/sets/resolver/iter_minim_a_nxdomain.rpl104
-rw-r--r--tests/deckard/sets/resolver/iter_minim_nonempty.rpl132
-rw-r--r--tests/deckard/sets/resolver/iter_minim_ns.rpl126
-rw-r--r--tests/deckard/sets/resolver/iter_minmaxttl.rpl191
-rw-r--r--tests/deckard/sets/resolver/iter_mod.rpl217
-rw-r--r--tests/deckard/sets/resolver/iter_multiple_A.rpl170
-rw-r--r--tests/deckard/sets/resolver/iter_ns_badaa.rpl174
-rw-r--r--tests/deckard/sets/resolver/iter_ns_badglue.rpl238
-rw-r--r--tests/deckard/sets/resolver/iter_ns_badip.rpl261
-rw-r--r--tests/deckard/sets/resolver/iter_ns_noglue.rpl220
-rw-r--r--tests/deckard/sets/resolver/iter_ns_spoof.rpl274
-rw-r--r--tests/deckard/sets/resolver/iter_pc_a.rpl230
-rw-r--r--tests/deckard/sets/resolver/iter_pc_aaaa.rpl230
-rw-r--r--tests/deckard/sets/resolver/iter_pcdiff.rpl208
-rw-r--r--tests/deckard/sets/resolver/iter_pcdirect.rpl311
-rw-r--r--tests/deckard/sets/resolver/iter_pcname.rpl276
-rw-r--r--tests/deckard/sets/resolver/iter_pcnamech.rpl421
-rw-r--r--tests/deckard/sets/resolver/iter_pcnamechrec.rpl400
-rw-r--r--tests/deckard/sets/resolver/iter_pcnamerec.rpl274
-rw-r--r--tests/deckard/sets/resolver/iter_pcttl.rpl353
-rw-r--r--tests/deckard/sets/resolver/iter_reclame_one.rpl316
-rw-r--r--tests/deckard/sets/resolver/iter_reclame_two.rpl355
-rw-r--r--tests/deckard/sets/resolver/iter_recurse.rpl312
-rw-r--r--tests/deckard/sets/resolver/iter_refuse.rpl191
-rw-r--r--tests/deckard/sets/resolver/iter_req_qname.rpl120
-rw-r--r--tests/deckard/sets/resolver/iter_resolve.rpl219
-rw-r--r--tests/deckard/sets/resolver/iter_tcbit.rpl87
-rw-r--r--tests/deckard/sets/resolver/iter_timeouted_ns.rpl316
-rw-r--r--tests/deckard/sets/resolver/iter_unexpectedrrtype.rpl59
-rw-r--r--tests/deckard/sets/resolver/iter_validate.rpl209
-rw-r--r--tests/deckard/sets/resolver/iter_validate_child_zone_noaddr.rpl207
-rw-r--r--tests/deckard/sets/resolver/iter_validate_extradata.rpl212
-rw-r--r--tests/deckard/sets/resolver/iter_validate_nsec_nxdomain.rpl152
-rw-r--r--tests/deckard/sets/resolver/module_dns64.rpl204
-rw-r--r--tests/deckard/sets/resolver/module_hint_static.rpl43
-rw-r--r--tests/deckard/sets/resolver/module_policy_deny_all.rpl96
-rw-r--r--tests/deckard/sets/resolver/module_policy_deny_suff_comm.rpl148
-rw-r--r--tests/deckard/sets/resolver/module_policy_deny_suff_patt.rpl148
-rw-r--r--tests/deckard/sets/resolver/module_policy_drop.rpl24
-rw-r--r--tests/deckard/sets/resolver/module_policy_forward.rpl38
-rw-r--r--tests/deckard/sets/resolver/module_policy_pass_deny.rpl67
-rw-r--r--tests/deckard/sets/resolver/module_policy_rpz.rpl153
-rw-r--r--tests/deckard/sets/resolver/module_policy_tc.rpl24
-rw-r--r--tests/deckard/sets/resolver/module_renumber.rpl86
-rw-r--r--tests/deckard/sets/resolver/module_workarounds_disable_0x20.rpl81
-rw-r--r--tests/deckard/sets/resolver/nsec3_aggr_cache.rpl5280
-rw-r--r--tests/deckard/sets/resolver/nsec3_wildcard_no_data_response.rpl110
-rw-r--r--tests/deckard/sets/resolver/nsec_aggr_cache.rpl6355
-rw-r--r--tests/deckard/sets/resolver/nsec_name_error_response-part2.rpl227
-rw-r--r--tests/deckard/sets/resolver/nsec_name_error_response.rpl240
-rw-r--r--tests/deckard/sets/resolver/nsec_no_data_response.rpl201
-rw-r--r--tests/deckard/sets/resolver/nsec_ref_to_unsigned1.rpl196
-rw-r--r--tests/deckard/sets/resolver/nsec_ref_to_unsigned2.rpl197
-rw-r--r--tests/deckard/sets/resolver/nsec_ref_to_unsigned3.rpl197
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_answer_response.rpl418
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.key5
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.private13
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_answer_response/root.zone8
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_no_data_response-part2.rpl257
-rw-r--r--tests/deckard/sets/resolver/nsec_wildcard_no_data_response.rpl282
-rw-r--r--tests/deckard/sets/resolver/rfc5011/README5
-rwxr-xr-xtests/deckard/sets/resolver/rfc5011/dns2rpl.py182
-rw-r--r--tests/deckard/sets/resolver/rfc5011/empty.rpl20
-rwxr-xr-xtests/deckard/sets/resolver/rfc5011/genkeyszones.sh90
-rw-r--r--tests/deckard/sets/resolver/rfc5011/knot.root.conf26
-rw-r--r--tests/deckard/sets/resolver/rfc5011/unsigned.db8
-rw-r--r--tests/deckard/sets/resolver/val_ad_qtype_ds.rpl196
-rw-r--r--tests/deckard/sets/resolver/val_adbit.rpl172
-rw-r--r--tests/deckard/sets/resolver/val_adcopy.rpl164
-rw-r--r--tests/deckard/sets/resolver/val_anchor_nx_nosig.rpl218
-rw-r--r--tests/deckard/sets/resolver/val_ans_dsent.rpl246
-rw-r--r--tests/deckard/sets/resolver/val_ans_nx.rpl248
-rw-r--r--tests/deckard/sets/resolver/val_cname_loop1.rpl142
-rw-r--r--tests/deckard/sets/resolver/val_cname_loop1_3.rpl182
-rw-r--r--tests/deckard/sets/resolver/val_cname_loop3.rpl164
-rw-r--r--tests/deckard/sets/resolver/val_cname_new_signer.rpl239
-rw-r--r--tests/deckard/sets/resolver/val_cname_oob.rpl181
-rw-r--r--tests/deckard/sets/resolver/val_cname_to_unsigned.rpl202
-rw-r--r--tests/deckard/sets/resolver/val_cname_to_unsigned_fake_rrsig.rpl213
-rw-r--r--tests/deckard/sets/resolver/val_cname_trust_domains.rpl438
-rw-r--r--tests/deckard/sets/resolver/val_cnamenx_dblnsec.rpl178
-rw-r--r--tests/deckard/sets/resolver/val_cnameqtype.rpl230
-rw-r--r--tests/deckard/sets/resolver/val_deleg_nons.rpl271
-rw-r--r--tests/deckard/sets/resolver/val_ds_afterprime.rpl181
-rw-r--r--tests/deckard/sets/resolver/val_ds_cname.rpl204
-rw-r--r--tests/deckard/sets/resolver/val_ds_cnamesub.rpl277
-rw-r--r--tests/deckard/sets/resolver/val_faildnskey.rpl171
-rw-r--r--tests/deckard/sets/resolver/val_mal_wc.rpl151
-rw-r--r--tests/deckard/sets/resolver/val_minimal_anotherdomainsignature.rpl99
-rw-r--r--tests/deckard/sets/resolver/val_minimal_anotherrrtypesignature.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddnskeyalgorithm.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddnskeyflags.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddnskeyprotocol.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddsalgorithm.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddsdigest.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddsdigesttype.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_baddskeytag.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badpublickey.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsigalgorithm.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsigexpiration.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsiginception.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsiglabels.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsigsignature.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsigtag.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_badrrsigttl.rpl88
-rw-r--r--tests/deckard/sets/resolver/val_minimal_beforeinception.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_expiredsignature.rpl87
-rw-r--r--tests/deckard/sets/resolver/val_minimal_noerror.rpl89
-rw-r--r--tests/deckard/sets/resolver/val_negcache_ds.rpl215
-rw-r--r--tests/deckard/sets/resolver/val_noadwhennodo.rpl151
-rw-r--r--tests/deckard/sets/resolver/val_nodata_hasdata.rpl163
-rw-r--r--tests/deckard/sets/resolver/val_nodata_zonecut.rpl161
-rw-r--r--tests/deckard/sets/resolver/val_nodatawc_badce.rpl163
-rw-r--r--tests/deckard/sets/resolver/val_nokeyprime.rpl164
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b1_nameerror.rpl161
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b1_nameerror_noce.rpl145
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nonc.rpl147
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nowc.rpl152
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b21_nodataent.rpl116
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b21_nodataent_wr.rpl136
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b2_nodata.rpl117
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b2_nodata_nons.rpl142
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b3_optout.rpl206
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b3_optout_negcache.rpl209
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b3_optout_noce.rpl255
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b3_optout_nonc.rpl256
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b4_wild.rpl174
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b5_wcnodata.rpl155
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_noce.rpl165
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nonc.rpl165
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nowc.rpl165
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_cnametocnamewctoposwc.rpl242
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_entnodata_optout_badopt.rpl199
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_nods_badsig.rpl238
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_nods_soa.rpl254
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_noopt_ref.rpl230
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_optout_ad.rpl361
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_optout_ns_ad.rpl203
-rw-r--r--tests/deckard/sets/resolver/val_nsec3_optout_unsec_cache.rpl254
-rw-r--r--tests/deckard/sets/resolver/val_nx.rpl154
-rw-r--r--tests/deckard/sets/resolver/val_nx_nodeny.rpl164
-rw-r--r--tests/deckard/sets/resolver/val_nx_nowc.rpl164
-rw-r--r--tests/deckard/sets/resolver/val_pos_truncns.rpl150
-rw-r--r--tests/deckard/sets/resolver/val_positive_nosigs.rpl182
-rw-r--r--tests/deckard/sets/resolver/val_qds_oneanc.rpl222
-rw-r--r--tests/deckard/sets/resolver/val_qds_twoanc.rpl223
-rw-r--r--tests/deckard/sets/resolver/val_referral_nods.rpl205
-rw-r--r--tests/deckard/sets/resolver/val_root_ds.rpl86
-rw-r--r--tests/deckard/sets/resolver/val_rrsig.rpl169
-rw-r--r--tests/deckard/sets/resolver/val_secds.rpl213
-rw-r--r--tests/deckard/sets/resolver/val_secds_nosig.rpl233
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel.rpl586
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.key5
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.private13
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel/root.db61
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel_insecure.rpl376
-rw-r--r--tests/deckard/sets/resolver/val_ta_sentinel_nokey.rpl361
-rw-r--r--tests/deckard/sets/resolver/val_unalgo_ds.rpl202
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure.rpl161
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.key5
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.private13
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure/root_unknown_ds_algo_and_digest.db11
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test.db5
-rw-r--r--tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test2.db5
-rw-r--r--tests/deckard/sets/resolver/val_unsecds.rpl193
-rw-r--r--tests/deckard/sets/resolver/val_unsecds_negcache.rpl194
-rw-r--r--tests/deckard/sets/resolver/val_unsecds_qtypeds.rpl209
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos.rpl161
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi.rpl239
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.key5
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.private13
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi/dsset-.2
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi/root.zone10
-rw-r--r--tests/deckard/sets/resolver/val_wild_pos_multi/root.zone.signed114
-rw-r--r--tests/deckard/sets/resolver/world_cz_lidovky_www.rpl910
-rw-r--r--tests/deckard/sets/resolver/world_cz_rhybar.rpl294
-rw-r--r--tests/deckard/sets/resolver/world_cz_turris_api.rpl323
-rw-r--r--tests/deckard/sets/resolver/world_cz_vutbr_www.rpl296
-rw-r--r--tests/deckard/sets/resolver/world_mx_nic_www.rpl272
-rw-r--r--tests/deckard/sets/resolver/zone.rpz10
-rw-r--r--tests/deckard/setup.py36
-rw-r--r--tests/deckard/template/dnssec_getdns.j23
-rw-r--r--tests/deckard/template/getdns.j26
-rw-r--r--tests/deckard/template/hints_zone.j29
-rw-r--r--tests/deckard/template/knotd_master.j229
-rw-r--r--tests/deckard/template/knotd_slave.j228
-rw-r--r--tests/deckard/template/kresd.j2111
-rw-r--r--tests/deckard/template/pdns_dnssec.j25
-rw-r--r--tests/deckard/template/pdns_recursor.j2312
-rw-r--r--tests/deckard/template/unbound.j2780
-rw-r--r--tests/deckard/template/unbound_dnssec.j23
-rw-r--r--tests/deckard/tests/__init__.py0
-rw-r--r--tests/deckard/tests/test_deckard.py30
-rw-r--r--tests/deckard/tools/divide_tests.sh77
-rw-r--r--tests/deckard/tools/invalid_dsa.py83
-rw-r--r--tests/deckard/tools/parse.py21
-rwxr-xr-xtests/deckard/unbound_run.sh5
-rw-r--r--tests/dnstap/src/dnstap-test/config11
-rw-r--r--tests/dnstap/src/dnstap-test/dnstap.mk19
-rw-r--r--tests/dnstap/src/dnstap-test/main.go245
-rw-r--r--tests/dnstap/src/dnstap-test/vendor/manifest55
-rw-r--r--tests/hints_zone.j29
-rw-r--r--tests/kresd_config.j253
-rw-r--r--tests/mock_cmodule.c33
-rw-r--r--tests/pytests/README.rst54
-rwxr-xr-xtests/pytests/certs/tt-certgen-expired.sh18
-rwxr-xr-xtests/pytests/certs/tt-certgen.sh4
-rw-r--r--tests/pytests/certs/tt-expired.cert.pem80
-rw-r--r--tests/pytests/certs/tt-expired.key.pem27
-rw-r--r--tests/pytests/certs/tt.cert.pem22
-rw-r--r--tests/pytests/certs/tt.conf353
-rw-r--r--tests/pytests/certs/tt.key.pem28
-rw-r--r--tests/pytests/conftest.py78
-rw-r--r--tests/pytests/conn_flood.py83
-rw-r--r--tests/pytests/kresd.py305
-rw-r--r--tests/pytests/pylintrc29
-rw-r--r--tests/pytests/rehandshake/Makefile28
-rw-r--r--tests/pytests/rehandshake/array.h166
-rw-r--r--tests/pytests/rehandshake/tcp-proxy.c336
-rw-r--r--tests/pytests/rehandshake/tcp-proxy.h12
-rw-r--r--tests/pytests/rehandshake/tcproxy.c25
-rw-r--r--tests/pytests/rehandshake/tls-proxy.c848
-rw-r--r--tests/pytests/rehandshake/tls-proxy.h14
-rw-r--r--tests/pytests/rehandshake/tlsproxy.c31
-rw-r--r--tests/pytests/requirements.txt5
-rw-r--r--tests/pytests/templates/kresd.conf.j242
-rw-r--r--tests/pytests/test_conn_mgmt.py213
-rw-r--r--tests/pytests/test_prefix.py113
-rw-r--r--tests/pytests/test_rehandshake.py87
-rw-r--r--tests/pytests/test_tls.py77
-rw-r--r--tests/pytests/utils.py131
-rw-r--r--tests/test.h123
-rw-r--r--tests/test_array.c111
-rw-r--r--tests/test_cache.c395
-rw-r--r--tests/test_integration.mk48
-rw-r--r--tests/test_lru.c123
-rw-r--r--tests/test_map.c131
-rw-r--r--tests/test_module.c51
-rw-r--r--tests/test_pack.c82
-rw-r--r--tests/test_queue.c77
-rw-r--r--tests/test_rplan.c87
-rw-r--r--tests/test_set.c220
-rw-r--r--tests/test_trie.c165
-rw-r--r--tests/test_utils.c123
-rw-r--r--tests/test_zonecut.c70
-rw-r--r--tests/testdata_notimpl/iter_class_any.rpl150
-rw-r--r--tests/testdata_notimpl/iter_dnsseclame_bug.rpl465
-rw-r--r--tests/testdata_notimpl/iter_dnsseclame_ds.rpl414
-rw-r--r--tests/testdata_notimpl/iter_dnsseclame_ds_ok.rpl367
-rw-r--r--tests/testdata_notimpl/iter_dnsseclame_ta.rpl327
-rw-r--r--tests/testdata_notimpl/iter_dnsseclame_ta_ok.rpl303
-rw-r--r--tests/testdata_notimpl/iter_dp_turnsuseless.rpl166
-rw-r--r--tests/testdata_notimpl/iter_ds_locate_ns.rpl145
-rw-r--r--tests/testdata_notimpl/iter_ds_locate_ns_cname.rpl155
-rw-r--r--tests/testdata_notimpl/iter_ds_locate_ns_detach.rpl296
-rw-r--r--tests/testdata_notimpl/iter_ds_locate_ns_nosoa.rpl145
-rw-r--r--tests/testdata_notimpl/iter_emptydp.rpl263
-rw-r--r--tests/testdata_notimpl/iter_emptydp_for_glue.rpl493
-rw-r--r--tests/testdata_notimpl/iter_fwdfirst.rpl157
-rw-r--r--tests/testdata_notimpl/iter_fwdfirstequal.rpl157
-rw-r--r--tests/testdata_notimpl/iter_fwdstub.rpl218
-rw-r--r--tests/testdata_notimpl/iter_fwdstubroot.rpl175
-rw-r--r--tests/testdata_notimpl/iter_got6only.rpl135
-rw-r--r--tests/testdata_notimpl/iter_pcdiff.rpl210
-rw-r--r--tests/testdata_notimpl/iter_pcnamerec.rpl275
-rw-r--r--tests/testdata_notimpl/iter_primenoglue.rpl383
-rw-r--r--tests/testdata_notimpl/iter_privaddr.rpl285
-rw-r--r--tests/testdata_notimpl/iter_ranoaa_lame.rpl293
-rw-r--r--tests/testdata_notimpl/iter_scrub_cname_an.rpl181
-rw-r--r--tests/testdata_notimpl/iter_scrub_dname_insec.rpl250
-rw-r--r--tests/testdata_notimpl/iter_scrub_dname_sec.rpl212
-rw-r--r--tests/testdata_notimpl/iter_scrub_ns.rpl103
-rw-r--r--tests/testdata_notimpl/iter_scrub_ns_fwd.rpl103
-rw-r--r--tests/testdata_notimpl/iter_scrub_ns_side.rpl103
-rw-r--r--tests/testdata_notimpl/iter_stub_noroot.rpl64
-rw-r--r--tests/testdata_notimpl/iter_stubfirst.rpl157
-rw-r--r--tests/testdata_notimpl/iter_stublastresort.rpl259
-rw-r--r--tests/testdata_notimpl/iter_timeout_ra_aaaa.rpl244
-rw-r--r--tests/tests.mk33
-rw-r--r--tests/unit.mk43
1037 files changed, 260705 insertions, 0 deletions
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..fa191dd
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,11 @@
+---
+Checks: 'bugprone-*,cert-*,-clang-analyzer-unix.Malloc,-clang-analyzer-deadcode.DeadStores,-clang-analyzer-valist.Uninitialized,readability-*,-readability-braces-*,-readability-else-after-return,-readability-redundant-declaration,-readability-non-const-parameter,google-readability-casting,misc-*,-misc-macro-parentheses,-misc-unused-parameters'
+WarningsAsErrors: 'cert-*,misc-*,readability-*,clang-analyzer-*,-readability-non-const-parameter'
+HeaderFilterRegex: 'contrib/ucw/*.h'
+CheckOptions:
+ - key: readability-identifier-naming
+ value: 'lower_case'
+ - key: readability-function-size.StatementThreshold
+ value: '400'
+ - key: readability-function-size.LineThreshold
+ value: '500' \ No newline at end of file
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..f5cba39
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,9 @@
+;; emacs local configuration settings for knot-resolver source
+;; surmised by dkg on 2016-04-02 23:46:50-0300
+
+((c-mode
+ (indent-tabs-mode . t)
+ (tab-width . 8)
+ (c-basic-offset . 8)
+ (c-file-style . "linux"))
+ )
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3e92ac9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,71 @@
+*.o
+*.a
+*.so
+*.so.*
+*.dylib
+*.dylib.*
+*.lo
+*.la
+*.Plo
+*.swp
+*~
+*.d
+*.db
+*.out
+*.6
+*.log
+*.mdb
+*.gcno
+*.gcda
+*.gcov
+*.info
+luacov.*.out
+.dirstamp
+.libs
+.deps
+_obj
+/.build-depend
+/autom4te.cache/*
+/bench/bench_lru
+/config.log
+/config.h
+/config.status
+/config.guess
+/config.sub
+/configure
+/ar-lib
+/libtool
+/missing
+/compile
+/compile_commands.json
+/depcomp
+/distro/tests/*/.vagrant
+/install-sh
+/stamp-h1
+/aclocal.m4
+/ltmain.sh
+/ylwrap
+/client/kresc
+/doc/doxyxml
+/doc/html
+/daemon/kresd
+/daemon/lua/*.inc
+/daemon/lua/trust_anchors.lua
+/tests/test_array
+/tests/test_lru
+/tests/test_map
+/tests/test_module
+/tests/test_pack
+/tests/test_set
+/tests/test_utils
+/tests/test_zonecut
+/tests/dnstap/src/dnstap-test/vendor/github.com/
+/tests/dnstap/src/github.com/
+.pytest_cache
+kresd.amalg.c
+libkres.amalg.c
+/doc/kresd.8
+/libkres.pc
+/tags
+/coverage
+/coverage.stats
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..ae4ac0b
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,645 @@
+image: $CI_REGISTRY/knot/knot-resolver/ci/debian-stable:knot-2.7
+
+variables:
+ DEBIAN_FRONTEND: noninteractive
+ LC_ALL: C.UTF-8
+ GIT_SUBMODULE_STRATEGY: recursive
+ GIT_STRATEGY: clone # sometimes unclean submodule dirs otherwise
+ PREFIX: $CI_PROJECT_DIR/.local
+ LD_LIBRARY_PATH: $CI_PROJECT_DIR/.local/lib
+ RESPDIFF_PRIORITY: 5
+ RESPDIFF_COUNT: 1
+ RESPDIFF_FORCE: 0
+ RESPERF_FORCE: 0
+
+stages:
+ - build
+ - test
+ - coverage
+ - extended
+ - deploy
+
+.build: &build
+ variables:
+ CFLAGS: -ggdb
+ stage: build
+ except:
+ - master
+ script:
+ - rm daemon/lua/kres-gen.lua
+ - make -k all
+ - STATUS="$(git status --untracked-files=normal --porcelain)"
+ - test -n "${STATUS}" && echo "${STATUS}" && echo "Build + install made working tree dirty, did you forget to update something?" && exit 2
+ - make install
+ artifacts:
+ untracked: true
+ tags:
+ - docker
+ - linux
+ - amd64
+
+build:linux:amd64:
+ <<: *build
+
+
+build:asan:linux:amd64:
+ <<: *build
+ variables:
+ CFLAGS: -ggdb3 -O0 -fsanitize=address -fno-omit-frame-pointer
+
+lint:pedantic:
+ stage: test # could be in build already, but let's not block the test stage if this fails
+ dependencies: [] # do not download build artifacts
+ except:
+ - master
+ image: $CI_REGISTRY/knot/knot-resolver/ci/debian-unstable:knot-2.7 # newer Debian for newer compilers
+ variables:
+ CFLAGS: -Werror -Wall -Wpedantic -ggdb -std=gnu11
+ script:
+ - make -k all
+ - make clean
+ - make -k all CC=clang CXX=clang++ \
+ CFLAGS="$CFLAGS -Wno-newline-eof -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-folding-constant"
+ tags:
+ - docker
+ - linux
+ - amd64
+
+srpm:
+ stage: build
+ except:
+ - master
+ allow_failure: true # don't block testing pipeline in case of failure
+ image: $CI_REGISTRY/knot/knot-resolver/ci/fedora
+ script:
+ - scripts/make-srpm.sh
+ artifacts:
+ when: always
+ expire_in: '1 week'
+ paths:
+ - "*.src.rpm"
+ tags:
+ - docker
+ - linux
+ - amd64
+
+lint:lua:
+ stage: test
+ except:
+ - master
+ dependencies: [] # do not download build artifacts
+ script:
+ - make lint-lua
+ tags:
+ - docker
+
+lint:c:
+ stage: test
+ except:
+ - master
+ image: $CI_REGISTRY/knot/knot-resolver/ci/debian-unstable:knot-2.7 # newer Debian for newer Clang
+ dependencies: [] # do not download build artifacts
+ script:
+ - make lint-c CLANG_TIDY="clang-tidy -quiet"
+ tags:
+ - docker
+
+lint:clang-scan-build:
+ stage: test
+ except:
+ - master
+ image: $CI_REGISTRY/knot/knot-resolver/ci/debian-unstable:knot-2.7 # newer Debian for newer Clang
+ dependencies: [] # do not download build artifacts
+ script:
+ - MAKEFLAGS="-k -j$(nproc)" SCAN_BUILD="scan-build -o scan-results --status-bugs -no-failure-reports" ./tests/clang_scan_build.sh make || true
+ - test "$(ls scan-results/*/report-*.html | wc -l)" = 6 # we have this many errors ATM :-)
+ artifacts:
+ when: on_failure
+ expire_in: '1 day'
+ paths:
+ - scan-results
+ tags:
+ - docker
+
+test:linux:amd64:
+ stage: test
+ except:
+ - master
+ script:
+ # recompile everything otherwise lcov will bark because Git files will be "newer" than gcda files
+ # this is caused by interaction between Git approach to timestamps and Gitlab artifacts
+ - git clean -xdf
+ - make
+ - MAKEFLAGS="--jobs $(nproc)" make -k check
+ - MAKEFLAGS="--jobs $(nproc)" test "${COVERAGE:-0}" -eq 1 && make coverage-c COVERAGE_STAGE=gcov-check || echo "code coverage skipped"
+ dependencies: []
+ artifacts:
+ expire_in: 1 hour
+ paths:
+ - ./*.info
+ tags:
+ - docker
+ - linux
+ - amd64
+
+
+docker:build:
+ stage: test
+ image: docker:latest
+ except:
+ - master
+ tags:
+ - dind
+ dependencies: []
+ variables:
+ DOCKER_IMAGE_NAME: knot-resolver-test:${CI_COMMIT_SHA}
+ script:
+ - docker build --no-cache -t ${DOCKER_IMAGE_NAME} .
+ - echo "quit()" | docker run -i ${DOCKER_IMAGE_NAME}
+ after_script: # remove dangling images to avoid running out of disk space
+ - docker rmi ${DOCKER_IMAGE_NAME}
+ - docker rmi $(docker images -f "dangling=true" -q)
+
+
+installcheck:linux:amd64:
+ stage: test
+ except:
+ - master
+ script:
+ # recompile everything otherwise lcov will bark because Git files will be "newer" than gcda files
+ # this is caused by interaction between Git approach to timestamps and Gitlab artifacts
+ - git clean -xdf
+ - make install
+ - MAKEFLAGS="--jobs $(nproc) --keep-going" make -k installcheck
+ - MAKEFLAGS="--jobs $(nproc)" test "${COVERAGE:-0}" -eq 1 && make coverage-c coverage-lua COVERAGE_STAGE=gcov-installcheck || echo "code coverage skipped"
+ dependencies: []
+ artifacts:
+ expire_in: 1 hour
+ paths:
+ - ./*.info
+ tags:
+ - docker
+ - linux
+ - amd64
+
+doc:
+ stage: test
+ except:
+ - master
+ script:
+ - SPHINXFLAGS="-W" make doc
+ dependencies: []
+ artifacts:
+ expire_in: 1 hour
+ paths:
+ - ./doc/*
+ tags:
+ - docker
+
+deckard:linux:amd64:
+ stage: test
+ except:
+ refs:
+ - master
+ variables:
+ # prevent unstable test from cancelling nightly OBS build
+ - $SKIP_DECKARD == "1"
+ variables:
+ TMPDIR: $CI_PROJECT_DIR
+ script:
+ - DECKARDFLAGS="-n $(nproc)" PATH="$PREFIX/sbin:$PATH" make check-integration
+ # these errors are side-effect of Git way of handling file timestamps
+ - MAKEFLAGS="--jobs $(nproc)" test "${COVERAGE:-0}" -eq 1 && make coverage-c coverage-lua COVERAGE_STAGE=gcov-deckard 2>&1 | grep -vE '(source file is newer than notes file)|(the message is displayed only once per source file)' || echo "code coverage skipped"
+ dependencies:
+ - build:linux:amd64
+ artifacts:
+ when: always
+ paths:
+ - ./*.info
+ - tmpdeckard*
+ expire_in: 1 week
+ tags:
+ - docker
+ - linux
+ - amd64
+
+installcheck:valgrind:linux:amd64:
+ stage: test
+ except:
+ - master
+ script:
+ - DEBUGGER="valgrind --leak-check=full --trace-children=yes --quiet --suppressions=/lj.supp" make -k installcheck
+ dependencies:
+ - build:linux:amd64
+ tags:
+ - docker
+ - linux
+ - amd64
+
+osx:build:
+ stage: test
+ except:
+ - master
+ script:
+ - ci/travis.py ${CI_COMMIT_REF_NAME}
+ dependencies: []
+ tags:
+ - docker
+
+
+# temporarily disabled - we need to fix issues first
+#deckard:linux:amd64:valgrind:
+# stage: test
+# script:
+# # TODO: valgrind missing parameter --error-exitcode=1 to fail make on error
+# - cd tests/deckard && DAEMON=valgrind ADDITIONAL="--leak-check=full --trace-children=yes --quiet --suppressions=/lj.supp $PREFIX/sbin/kresd -f 1" MAKEFLAGS="-j $(nproc) --keep-going" make
+# artifacts:
+# when: on_failure
+# expire_in: 1 week
+# paths:
+# - tmpdeckard*
+# dependencies:
+# - build:linux:amd64
+# tags:
+# - docker
+# - linux
+# - amd64
+
+
+test:linux:amd64:valgrind:
+ stage: test
+ except:
+ - master
+ variables:
+ TMPDIR: $CI_PROJECT_DIR
+ script:
+ - DEBUGGER="valgrind --error-exitcode=1 --leak-check=full --trace-children=yes --quiet --suppressions=/lj.supp" make -k check
+ dependencies:
+ - build:linux:amd64
+ tags:
+ - docker
+ - linux
+ - amd64
+
+pytests:lint:
+ stage: test
+ dependencies: []
+ except:
+ - master
+ script:
+ - ./ci/pytests/lint.sh
+ tags:
+ - docker
+ - linux
+ - amd64
+
+pytests:run:
+ stage: test
+ dependencies:
+ - build:asan:linux:amd64
+ except:
+ - master
+ script:
+ - pushd tests/pytests/rehandshake
+ - make all
+ - popd
+ - PATH="$PREFIX/sbin:$PATH" ./ci/pytests/run.sh &> pytests.log.txt
+ after_script:
+ - tail -1 pytests.log.txt
+ - echo "See pytests.html or pytests.log.txt for full report."
+ artifacts:
+ when: always
+ expire_in: 1 week
+ paths:
+ - pytest*
+ tags:
+ - docker
+ - linux
+ - amd64
+
+pytests:extended:
+ stage: extended
+ dependencies:
+ - build:asan:linux:amd64
+ except:
+ - master
+ script:
+ - PATH="$PREFIX/sbin:$PATH" ./ci/pytests/run-extended.sh
+ tags:
+ - docker
+ - linux
+ - amd64
+
+
+.respdiff: &respdiff
+ stage: extended
+ dependencies: []
+ only: # trigger job only in repos under our control
+ - branches@knot/knot-resolver
+ - branches@knot/knot-resolver-security
+ except:
+ - master
+ script:
+ - git diff-index --name-only origin/master | grep -qEv '^(AUTHORS|ci/|config.mk|COPYING|distro/|doc/|etc/|NEWS|README.md|scripts/|tests/|\.gitignore|\.gitlab-ci\.yml|\.travis\.yml)' || test $RESPDIFF_FORCE -gt 0 || exit 0
+ - export LABEL=gl$(date +%s)
+ - export COMMITDIR="/var/tmp/respdiff-jobs/$(git rev-parse --short HEAD)-$LABEL"
+ - export TESTDIR="$COMMITDIR/$RESPDIFF_TEST"
+ - ln -s $COMMITDIR respdiff_commitdir
+ - >
+ sudo -u respdiff /var/opt/respdiff/contrib/job_manager/submit.py -w
+ -p $RESPDIFF_PRIORITY
+ -c $RESPDIFF_COUNT
+ $(sudo -u respdiff /var/opt/respdiff/contrib/job_manager/create.py
+ "$(git rev-parse --short HEAD)" -l $LABEL -t $RESPDIFF_TEST
+ --respdiff-stats /var/tmp/respdiff-jobs/ref_current/*_${RESPDIFF_TEST}_stats.json)
+ - for f in $TESTDIR/*.json; do test -s "$f" || (cat $TESTDIR/*stderr*; exit 1); done
+ - sudo -u respdiff /var/opt/respdiff/contrib/job_manager/plot_ref.sh $TESTDIR/.. /var/tmp/respdiff-jobs/ref_current $RESPDIFF_TEST
+ after_script:
+ - 'cp -t . respdiff_commitdir/$RESPDIFF_TEST/j* ||:'
+ - 'cp -t . respdiff_commitdir/*$RESPDIFF_TEST*.png ||:'
+ artifacts:
+ when: always
+ expire_in: 1 week
+ paths:
+ - ./j*
+ - ./*.png
+ tags:
+ - respdiff
+
+respdiff:fwd-tls6-kresd.udp6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.fwd-tls6-kresd.udp6.j256
+
+respdiff:fwd-udp6-kresd.udp6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.fwd-udp6-kresd.udp6.j384
+
+respdiff:iter.udp6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.iter.udp6.j384
+
+respdiff:iter.tls6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.iter.tls6.j384
+
+respdiff:fwd-udp6-unbound.udp6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.fwd-udp6-unbound.udp6.j256
+
+respdiff:fwd-udp6-unbound.tcp6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.fwd-udp6-unbound.tcp6.j256
+
+respdiff:fwd-udp6-unbound.tls6:
+ <<: *respdiff
+ variables:
+ RESPDIFF_TEST: shortlist.fwd-udp6-unbound.tls6.j256
+
+
+respdiff:iter:udp:linux:amd64:
+ stage: test
+ except:
+ - master
+ script:
+ - source <(./scripts/coverage_env.sh "$(pwd)" "$(pwd)/coverage.stats/respdiff" "iter/udp" --export)
+ - ulimit -n "$(ulimit -Hn)" # applies only for kresd ATM
+ - ./ci/respdiff/start-resolvers.sh
+ - ./ci/respdiff/run-respdiff-tests.sh udp
+ - cat results/respdiff.txt
+ - echo 'test if mismatch rate < 1.0 %'
+ - grep -q '^target disagrees.*0\.[0-9][0-9] %' results/respdiff.txt
+ - killall --wait kresd
+ - MAKEFLAGS="--jobs $(nproc)" test "${COVERAGE:-0}" -eq 1 && make coverage-c coverage-lua COVERAGE_STAGE=gcov-respdiff-iter-udp | grep -vE '(source file is newer than notes file)|(the message is displayed only once per source file)' || echo "code coverage skipped"
+ dependencies:
+ - build:asan:linux:amd64
+ artifacts:
+ when: always
+ expire_in: '1 week'
+ paths:
+ - kresd.log.xz
+ - results/*.txt
+ - results/*.png
+ - results/respdiff.db/data.mdb.xz
+ - ./*.info
+ tags:
+ - docker
+ - linux
+ - amd64
+
+
+.resperf: &resperf
+ stage: extended
+ dependencies: []
+ only: # trigger job only in repos under our control
+ - branches@knot/knot-resolver
+ - branches@knot/knot-resolver-security
+ except:
+ - master
+ script:
+ - git diff-index --name-only origin/master | grep -qEv '^(AUTHORS|ci/|config.mk|COPYING|distro/|doc/|etc/|NEWS|README.md|scripts/|tests/|\.gitignore|\.gitlab-ci\.yml|\.travis\.yml)' || test $RESPERF_FORCE -gt 0 || exit 0
+ - export LABEL=gl$(date +%s)
+ - export COMMITDIR="/var/tmp/respdiff-jobs/$(git rev-parse --short HEAD)-$LABEL"
+ - export TESTDIR="$COMMITDIR/$RESPERF_TEST"
+ - ln -s $COMMITDIR resperf_commitdir
+ - >
+ sudo -u respdiff /var/opt/respdiff/contrib/job_manager/submit.py -w
+ $(sudo -u respdiff /var/opt/respdiff/contrib/job_manager/create.py
+ "$(git rev-parse --short HEAD)" -l $LABEL --asan -t $RESPERF_TEST)
+ - export EXITCODE=$(cat $TESTDIR/j*_exitcode)
+ - if [[ "$EXITCODE" == "0" ]]; then cat $TESTDIR/j*_resperf.txt; else cat $TESTDIR/j*_kresd.docker.txt; fi
+ - exit $EXITCODE
+ after_script:
+ - 'cp -t . resperf_commitdir/$RESPERF_TEST/j* ||:'
+ artifacts:
+ when: always
+ expire_in: 1 week
+ paths:
+ - ./j*
+ tags:
+ - respdiff
+
+resperf:fwd-tls6.udp-asan:
+ <<: *resperf
+ variables:
+ RESPERF_TEST: resperf.fwd-tls6.udp
+
+resperf:fwd-udp6.udp-asan:
+ <<: *resperf
+ variables:
+ RESPERF_TEST: resperf.fwd-udp6.udp
+
+resperf:iter.udp-asan:
+ <<: *resperf
+ variables:
+ RESPERF_TEST: resperf.iter.udp
+
+
+distro:fedora-29:
+ stage: test
+ except:
+ - master
+ image: $CI_REGISTRY/knot/knot-resolver/ci/fedora
+ only: # trigger job only in repos under our control
+ - branches@knot/knot-resolver
+ - branches@knot/knot-resolver-security
+ dependencies:
+ - srpm
+ script:
+ - mock --no-clean --old-chroot -r fedora-29-x86_64 --rebuild *.src.rpm || (cat /var/lib/mock/fedora-29-x86_64/result/build.log; false)
+ after_script:
+ - mv /var/lib/mock/fedora-29-x86_64/result fedora-29-x86_64
+ artifacts:
+ when: always
+ expire_in: '1 week'
+ paths:
+ - fedora-29-x86_64/
+ tags:
+ - privileged # mock requires additional capabilities (e.g. mount)
+
+distro:epel-7:
+ stage: test
+ except:
+ - master
+ image: $CI_REGISTRY/knot/knot-resolver/ci/fedora
+ only: # trigger job only in repos under our control
+ - branches@knot/knot-resolver
+ - branches@knot/knot-resolver-security
+ dependencies:
+ - srpm
+ script:
+ - mock --no-clean --dnf --old-chroot -r epel-7-x86_64 --rebuild *.src.rpm || (cat /var/lib/mock/epel-7-x86_64/result/build.log; false)
+ after_script:
+ - mv /var/lib/mock/epel-7-x86_64/result epel-7-x86_64
+ artifacts:
+ when: always
+ expire_in: '1 week'
+ paths:
+ - epel-7-x86_64/
+ tags:
+ - privileged # mock require additional capabilities (e.g. mount)
+
+# compute coverage for runs with COVERAGE=1
+coverage:
+ stage: coverage
+ except:
+ - master
+ - branches@knot/knot-resolver-security
+ only:
+ variables:
+ - $COVERAGE == "1"
+ script:
+ - make coverage
+ artifacts:
+ expire_in: '1 week'
+ paths:
+ - coverage
+ coverage: '/lines\.+:\s(\d+.\d+\%)/'
+ dependencies:
+ - build:linux:amd64
+ - test:linux:amd64
+ - installcheck:linux:amd64
+ - deckard:linux:amd64
+ - respdiff:iter:udp:linux:amd64
+ tags:
+ - docker
+ - linux
+ - amd64
+
+# publish coverage only for master branch
+pages:
+ stage: deploy
+ only:
+ refs:
+ - nightly@knot/knot-resolver
+ variables:
+ - $COVERAGE == "1"
+ dependencies:
+ - coverage
+ script:
+ - mv coverage/ public/
+ artifacts:
+ expire_in: '30 days'
+ paths:
+ - public
+
+# trigger obs build for master branch
+obs:devel:
+ stage: deploy
+ only:
+ variables:
+ - $OBS_BUILD == "1"
+ refs:
+ - nightly@knot/knot-resolver
+ dependencies: []
+ script:
+ - scripts/make-archive.sh
+ - scripts/make-distrofiles.sh
+ - echo -e "[general]\napiurl = https://api.opensuse.org\n\n[https://api.opensuse.org]\nuser = CZ-NIC-automation\npass = $OBS_PASSWORD" > /root/.oscrc
+ - scripts/build-in-obs.sh knot-dns-devel # build against latest development version of knot
+ - scripts/build-in-obs.sh knot-resolver-devel # build against knot in knot-resolver-latest
+
+pkg:debian:symbols:libkres:
+ variables:
+ LIB_NAME: libkres
+ LIB_ABI: 9
+ stage: deploy
+ only:
+ variables:
+ - $OBS_BUILD == "1"
+ refs:
+ - nightly@knot/knot-resolver
+ except:
+ - master
+ script:
+ - ln -s distro/deb debian
+ - sed -i "s/__VERSION__/99/g" distro/deb/changelog
+ - dpkg-gensymbols -c4 -elib/$LIB_NAME.so.$LIB_ABI -P. -p$LIB_NAME$LIB_ABI
+ allow_failure: true
+ dependencies:
+ - build:linux:amd64
+
+
+# copy snapshot of current master to nightly branch for further processing
+# (this is workaround for missing complex conditions for job limits in Gitlab)
+nightly:copy:
+ stage: deploy
+ only:
+ variables:
+ - $CREATE_NIGHTLY == "1"
+ refs:
+ - master@knot/knot-resolver
+ dependencies: []
+ script:
+ # delete nightly branch
+ - 'curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly/unprotect"'
+ - 'curl --request DELETE --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly"'
+ # recreate nightly branch from current master
+ - 'curl --request POST --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches?branch=nightly&ref=master"'
+ - 'curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" "https://gitlab.labs.nic.cz/api/v4/projects/147/repository/branches/nightly/protect"'
+
+
+#arm_build:
+# image: cznic/armhf-ubuntu:16.04
+# stage: build
+# script:
+# - make -k all
+# tags:
+# - docker
+# - linux
+# - arm
+
+#arm_test:
+# image: armv7/armhf-ubuntu:16.04
+# stage: test
+# script:
+# - make -k check
+# tags:
+# - docker
+# - linux
+# - arm
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..0a80981
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "tests/deckard"]
+ path = tests/deckard
+ url = https://gitlab.labs.nic.cz/knot/deckard.git
+[submodule "modules/policy/lua-aho-corasick"]
+ path = modules/policy/lua-aho-corasick
+ url = https://github.com/cloudflare/lua-aho-corasick.git
+[submodule "tests/config/tapered"]
+ path = tests/config/tapered
+ url = https://github.com/telemachus/tapered.git
diff --git a/.luacheckrc b/.luacheckrc
new file mode 100644
index 0000000..992011f
--- /dev/null
+++ b/.luacheckrc
@@ -0,0 +1,83 @@
+std = 'luajit'
+new_read_globals = {
+ 'help',
+ 'quit',
+ 'hostname',
+ 'package_version',
+ 'moduledir',
+ 'user',
+ 'verbose',
+ 'resolve',
+ 'tojson',
+ 'todname',
+ 'map',
+ 'net',
+ 'cache',
+ 'modules',
+ 'trust_anchors',
+ 'worker',
+ 'event',
+ '_hint_root_file',
+ -- Sandbox declarations
+ 'kB',
+ 'MB',
+ 'GB',
+ 'sec',
+ 'second',
+ 'minute',
+ 'min',
+ 'hour',
+ 'day',
+ 'panic',
+ 'warn',
+ 'log',
+ 'mode',
+ 'trust_anchors',
+ 'reorder_RR',
+ 'option',
+ 'env',
+ 'kres',
+ 'trustanchor',
+ 'libknot_SONAME',
+ 'libzscanner_SONAME',
+ 'table_print',
+ '__engine',
+ '_ENV',
+ '_SANDBOX',
+}
+
+new_globals = {
+ -- Modules are allowed to be set and accessed from global namespace
+ 'policy',
+ 'view',
+ 'stats',
+ 'http',
+ 'trust_anchors',
+ 'bogus_log',
+}
+
+-- Luacheck < 0.18 doesn't support new_read_globals
+for _, v in ipairs(new_read_globals) do
+ table.insert(new_globals, v)
+end
+
+-- Ignore test files
+exclude_files = {
+ 'modules/policy/lua-aho-corasick', -- Vendored
+ 'tests/config/tapered',
+}
+
+-- Ignore some pedantic checks
+ignore = {
+ '4.1/err', -- Shadowing err
+ '4.1/.', -- Shadowing one letter variables
+}
+
+-- Sandbox can set global variables
+files['daemon/lua'].ignore = {'111', '121', '122'}
+files['daemon/lua/kres-gen.lua'].ignore = {'631'} -- Allow overly long lines
+-- Tests and scripts can use global variables
+files['scripts'].ignore = {'111', '112', '113'}
+files['tests'].ignore = {'111', '112', '113'}
+files['modules/**/*.test.lua'].ignore = {'111', '112', '113', '121', '122'}
+files['daemon/**/*.test.lua'].ignore = {'111', '112', '113', '121', '122'}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..4eac7a0
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,36 @@
+language: c
+os:
+ - osx
+addons:
+ homebrew:
+ packages:
+ - cmocka
+ - luajit
+ - libuv
+compiler:
+ - clang
+notifications:
+ email:
+ on_success: never
+ on_failure: never
+matrix:
+ fast_finish: true
+env:
+ global:
+ - KNOT_DNS_VERSION=v2.7.2
+ - DYLD_LIBRARY_PATH="${HOME}/.local/lib"
+ - MALLOC_CHECK_=3
+ - MALLOC_PERTURB_=223
+before_script:
+ - git clone -b ${KNOT_DNS_VERSION} https://gitlab.labs.nic.cz/knot/knot-dns.git
+ - cd knot-dns
+ - autoreconf -fi
+ - ./configure --disable-static --disable-fastparser --disable-documentation --disable-daemon --disable-utilities --with-lmdb=no
+ - make -j2 install
+ - cd ..
+script:
+ - CFLAGS="-O2 -g -fno-omit-frame-pointer -DDEBUG" make -j2 install check V=1 PREFIX=${HOME}/.local DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}
+ - ./daemon/kresd -h
+ - ./daemon/kresd -V
+ - echo "quit()" | ./daemon/kresd -a 127.0.0.1@53535 .
+sudo: false
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..35ecb09
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,12 @@
+Marek Vavrusa <marek@vavrusa.com>
+Ondřej Surý <ondrej.sury@nic.cz>
+Jan Vcelak <jan.vcelak@nic.cz>
+Grigorii Demidov <grigorii.demidov@nic.cz>
+Karel Slany <karel.slany@nic.cz>
+Daniel Salzman <daniel.salzman@nic.cz>
+Pavel Valach <valach.pavel@gmail.com>
+Tomas Hozza <thozza@redhat.com>
+Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Vladimír Čunát <vladimir.cunat@nic.cz>
+Štěpán Balážik <stepan.balazik@nic.cz>
+Petr Å paÄek <petr.spacek@nic.cz>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..fb0c9a2
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,687 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+ In addition, as a special exception, the copyright holders give
+permission to link the code of portions of this program with the
+OpenSSL library under certain conditions as described in each
+individual source file, and distribute linked combinations including
+the two.
+ You must obey the GNU General Public License in all respects for all
+of the code used other than OpenSSL. If you modify file(s) with this
+exception, you may extend this exception to your version of the
+file(s), but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. If you delete
+this exception statement from all source files in the program, then
+also delete it here.
diff --git a/CodingStyle b/CodingStyle
new file mode 100644
index 0000000..004c65b
--- /dev/null
+++ b/CodingStyle
@@ -0,0 +1,5 @@
+# Style
+
+Linux kernel [coding style][lkstyle], same practices for API documentation.
+
+[lkstyle]: https://www.kernel.org/doc/Documentation/process/coding-style.rst
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..e4c53c9
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,76 @@
+# Intermediate container for Knot DNS build (not persistent)
+FROM debian:stable AS knot-dns-build
+ARG KNOT_DNS_VERSION=v2.7.2
+
+# Build dependencies
+ENV KNOT_DNS_BUILD_DEPS git-core build-essential libtool autoconf pkg-config \
+ libgnutls28-dev libprotobuf-dev libprotobuf-c-dev libfstrm-dev
+ENV KNOT_RESOLVER_BUILD_DEPS build-essential pkg-config bsdmainutils liblmdb-dev \
+ libluajit-5.1-dev libuv1-dev libprotobuf-dev libprotobuf-c-dev \
+ libfstrm-dev luajit lua-sec lua-socket
+ENV BUILDENV_DEPS ${KNOT_DNS_BUILD_DEPS} ${KNOT_RESOLVER_BUILD_DEPS}
+RUN apt-get update -qq && \
+ apt-get -y -qqq install ${BUILDENV_DEPS}
+
+# Install Knot DNS from sources
+RUN git clone -b $KNOT_DNS_VERSION --depth=1 https://gitlab.labs.nic.cz/knot/knot-dns.git /tmp/knot-dns && \
+ cd /tmp/knot-dns && \
+ autoreconf -if && \
+ ./configure --disable-static --disable-fastparser --disable-documentation \
+ --disable-daemon --disable-utilities --with-lmdb=no && \
+ make -j4 install && \
+ ldconfig
+
+# Copy libknot, libdnssec, libzscanner to runtime
+RUN mkdir -p /tmp/root/usr/local/include /tmp/root/usr/local/lib /tmp/root/usr/local/lib/pkgconfig && \
+ cp -rt /tmp/root/usr/local/include /usr/local/include/libknot /usr/local/include/libdnssec /usr/local/include/libzscanner && \
+ cp -rt /tmp/root/usr/local/lib /usr/local/lib/libknot* /usr/local/lib/libdnssec* /usr/local/lib/libzscanner* && \
+ cp -rt /tmp/root/usr/local/lib/pkgconfig /usr/local/lib/pkgconfig/libknot.pc /usr/local/lib/pkgconfig/libdnssec.pc /usr/local/lib/pkgconfig/libzscanner.pc
+
+
+# Intermediate container with runtime dependencies
+FROM debian:stable-slim AS runtime
+
+# Install runtime dependencies
+ENV KNOT_DNS_RUNTIME_DEPS libgnutls30
+ENV KNOT_RESOLVER_RUNTIME_DEPS liblmdb0 luajit libluajit-5.1-2 libuv1 lua-sec lua-socket
+ENV KNOT_RESOLVER_RUNTIME_DEPS_HTTP libjs-bootstrap libjs-d3 libjs-jquery lua-http lua-mmdb
+ENV KNOT_RESOLVER_RUNTIME_DEPS_EXTRA libfstrm0 lua-cqueues
+ENV RUNTIME_DEPS ${KNOT_DNS_RUNTIME_DEPS} ${KNOT_RESOLVER_RUNTIME_DEPS} ${KNOT_RESOLVER_RUNTIME_DEPS_HTTP} ${KNOT_RESOLVER_RUNTIME_DEPS_EXTRA}
+RUN apt-get update -qq && \
+ apt-get install -y -qqq ${RUNTIME_DEPS} && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+
+# Intermediate container for Knot Resolver build
+FROM knot-dns-build AS build
+
+# Get Knot Resolver code from current directory
+COPY . /tmp/knot-resolver
+
+# Build Knot Resolver
+ARG CFLAGS="-O2 -fstack-protector -g"
+ENV LDFLAGS -Wl,--as-needed
+RUN cd /tmp/knot-resolver && \
+ make "-j$(nproc)" && \
+ make install DESTDIR=/tmp/root && \
+ mkdir -p /tmp/root/etc/knot-resolver && \
+ cp ./etc/config.docker /tmp/root/etc/knot-resolver/kresd.conf && \
+ cp ./distro/common/root.keys /tmp/root/etc/knot-resolver/
+
+
+# Final container
+FROM runtime
+LABEL cz.knot-resolver.vendor="CZ.NIC"
+LABEL maintainer="knot-resolver-users@lists.nic.cz"
+
+# Export DNS over UDP & TCP, DNS-over-TLS, web interface
+EXPOSE 53/UDP 53/TCP 853/TCP 8053/TCP
+
+# Fetch Knot Resolver + Knot DNS libraries from build image
+COPY --from=build /tmp/root/ /
+RUN ldconfig
+
+ENTRYPOINT ["/usr/local/sbin/kresd"]
+CMD ["-c", "/etc/knot-resolver/kresd.conf"]
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..82221e9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,188 @@
+SHELL=/bin/bash -o pipefail -o errexit
+
+include config.mk
+include platform.mk
+
+# Targets
+all: info lib daemon client modules etc
+install: lib-install daemon-install client-install modules-install etc-install
+check: all tests
+clean: contrib-clean lib-clean daemon-clean client-clean modules-clean \
+ tests-clean doc-clean bench-clean coverage-clean
+doc: doc-html
+lint: lint-lua lint-c
+lint-c: libkres-lint kresd-lint kresc-lint
+lint-lua: $(patsubst %.lua.in,%.lua,$(wildcard */*/*.lua.in))
+ luacheck --codes --formatter TAP .
+
+.PHONY: all install check clean doc info lint
+
+# Dependencies
+KNOT_MINVER := 2.7.2
+$(eval $(call find_lib,libknot,$(KNOT_MINVER),yes))
+$(eval $(call find_lib,libdnssec,$(KNOT_MINVER),yes))
+$(eval $(call find_lib,libzscanner,$(KNOT_MINVER),yes))
+$(eval $(call find_lib,lmdb))
+$(eval $(call find_lib,libuv,1.0,yes))
+$(eval $(call find_lib,nettle,,yes))
+$(eval $(call find_alt,lua,luajit))
+$(eval $(call find_luapkg,ltn12))
+$(eval $(call find_luapkg,ssl.https))
+$(eval $(call find_lib,cmocka))
+$(eval $(call find_bin,doxygen))
+$(eval $(call find_bin,sphinx-build))
+$(eval $(call find_pythonpkg,breathe))
+$(eval $(call find_lib,socket_wrapper))
+$(eval $(call find_lib,libsystemd,227))
+$(eval $(call find_lib,gnutls))
+$(eval $(call find_lib,libedit))
+$(eval $(call find_lib,libprotobuf-c,1))
+$(eval $(call find_lib,libfstrm,0.2))
+$(eval $(call find_bin,protoc-c))
+$(eval $(call find_bin,lcov))
+$(eval $(call find_bin,luacov))
+
+# Lookup SONAME
+$(eval $(call find_soname,libknot))
+$(eval $(call find_soname,libzscanner))
+
+ifeq ($(libknot_SONAME),)
+ $(error "Unable to resolve libknot_SONAME, update find_soname in platform.mk")
+endif
+ifeq ($(libzscanner_SONAME),)
+ $(error "Unable to resolve libzscanner_SONAME, update find_some in platform.mk")
+endif
+
+# Find Go version and platform
+GO_VERSION := $(shell $(GO) version 2>/dev/null)
+ifeq ($(GO_VERSION),)
+ GO_VERSION := 0
+else
+ GO_PLATFORM := $(word 2,$(subst /, ,$(word 4,$(GO_VERSION))))
+ GO_VERSION := $(subst .,,$(subst go,,$(word 3,$(GO_VERSION))))
+endif
+$(eval $(call find_ver,go,$(GO_VERSION),16))
+
+# Check if Go is able to build shared libraries
+ifeq ($(HAS_go),yes)
+ifneq ($(GO_PLATFORM),$(filter $(GO_PLATFORM),amd64 386 arm arm64))
+HAS_go := no
+endif
+else
+$(eval $(call find_ver,go,$(GO_VERSION),15))
+ifeq ($HAS_go,yes)
+ifneq ($(GO_PLATFORM),$(filter $(GO_PLATFORM),arm amd64))
+HAS_go := no
+endif
+endif
+endif
+
+# check for fstrm and protobuf for dnstap
+ifeq ($(HAS_libfstrm)|$(HAS_libprotobuf-c)|$(HAS_protoc-c),yes|yes|yes)
+ENABLE_DNSTAP := yes
+endif
+
+# Overview
+info:
+ $(info Target: Knot Resolver $(VERSION)-$(PLATFORM))
+ $(info Compiler: $(CC) $(BUILD_CFLAGS))
+ $(info Linker: $(CCLD) $(BUILD_LDFLAGS))
+ $(info )
+ $(info Variables)
+ $(info ---------)
+ $(info HARDENING: $(HARDENING))
+ $(info BUILDMODE: $(BUILDMODE))
+ $(info PREFIX: $(PREFIX))
+ $(info PREFIX: $(PREFIX))
+ $(info DESTDIR: $(DESTDIR))
+ $(info BINDIR: $(BINDIR))
+ $(info SBINDIR: $(SBINDIR))
+ $(info LIBDIR: $(LIBDIR))
+ $(info ETCDIR: $(ETCDIR))
+ $(info INCLUDEDIR: $(INCLUDEDIR))
+ $(info MODULEDIR: $(MODULEDIR))
+ $(info )
+ $(info Core Dependencies)
+ $(info ------------)
+ $(info [$(HAS_libknot)] libknot (lib))
+ $(info [yes] $(if $(filter $(HAS_lmdb),yes),system,embedded) lmdb (lib))
+ $(info [$(HAS_lua)] luajit (daemon))
+ $(info [$(HAS_libuv)] libuv (daemon))
+ $(info [$(HAS_gnutls)] libgnutls (daemon))
+ $(info )
+ $(info Optional)
+ $(info --------)
+ $(info [$(HAS_doxygen)] doxygen (doc))
+ $(info [$(HAS_sphinx-build)] sphinx-build (doc))
+ $(info [$(HAS_breathe)] python-breathe (doc))
+ $(info [$(HAS_go)] go (modules/go, Go buildmode=c-shared support))
+ $(info [$(HAS_cmocka)] cmocka (tests/unit))
+ $(info [$(HAS_libsystemd)] systemd (daemon))
+# $(info [$(HAS_nettle)] nettle (modules/cookies))
+ $(info [$(HAS_ltn12)] Lua socket ltn12 (trust anchor bootstrapping))
+ $(info [$(HAS_ssl.https)] Lua ssl.https (trust anchor bootstrapping))
+ $(info [$(HAS_libedit)] libedit (client))
+ $(info [$(HAS_libfstrm)] libfstrm (modules/dnstap))
+ $(info [$(HAS_libprotobuf-c)] libprotobuf-c (modules/dnstap))
+ $(info [$(HAS_protoc-c)] proto-c (modules/dnstap))
+ $(info [$(HAS_lcov)] lcov (code coverage))
+ $(info [$(HAS_luacov)] luacov (code coverage))
+ $(info )
+
+# Verify required dependencies are met, as listed above
+ifeq ($(HAS_libknot),no)
+ $(error libknot >= $(KNOT_MINVER) required)
+endif
+ifeq ($(HAS_libzscanner),no)
+ $(error libzscanner >= $(KNOT_MINVER) required)
+endif
+ifeq ($(HAS_libdnssec),no)
+ $(error libdnssec >= $(KNOT_MINVER) required)
+endif
+ifeq ($(HAS_lua),no)
+ $(error luajit required)
+endif
+ifeq ($(HAS_libuv),no)
+ $(error libuv >= 1.0 required)
+endif
+ifeq ($(HAS_gnutls),no)
+ $(error gnutls required)
+endif
+
+
+BUILD_CFLAGS += $(libknot_CFLAGS) $(libuv_CFLAGS) $(nettle_CFLAGS) $(cmocka_CFLAGS) $(lua_CFLAGS) $(libdnssec_CFLAGS) $(libsystemd_CFLAGS)
+BUILD_CFLAGS += $(addprefix -I,$(wildcard contrib/ccan/*) contrib/murmurhash3)
+
+# Work around luajit on OS X
+ifeq ($(PLATFORM), Darwin)
+ifneq (,$(findstring luajit, $(lua_LIBS)))
+ lua_LIBS += -pagezero_size 10000 -image_base 100000000
+endif
+endif
+
+# Check if it has nettle to support DNS cookies
+
+# temporarily turn off cookies
+#ifeq ($(HAS_nettle), yes)
+#BUILD_CFLAGS += -DENABLE_COOKIES
+#ENABLE_COOKIES := yes
+#endif
+ENABLE_COOKIES := no
+
+# Installation directories
+$(DESTDIR)$(MODULEDIR):
+ $(INSTALL) -d $@
+$(DESTDIR)$(ETCDIR):
+ $(INSTALL) -m 0755 -d $@
+
+# Sub-targets
+include contrib/contrib.mk
+include coverage.mk
+include lib/lib.mk
+include client/client.mk
+include daemon/daemon.mk
+include modules/modules.mk
+include tests/tests.mk
+include doc/doc.mk
+include etc/etc.mk
+include bench/bench.mk
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..d54bb03
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,701 @@
+Knot Resolver 3.2.1 (2019-01-10)
+================================
+
+Bugfixes
+--------
+- trust_anchors: respect validity time range during TA bootstrap (!748)
+- fix TLS rehandshake handling (!739)
+- make TLS_FORWARD compatible with GnuTLS 3.3 (!741)
+- special thanks to Grigorii Demidov for his long-term work on Knot Resolver!
+
+Improvements
+------------
+- improve handling of timeouted outgoing TCP connections (!734)
+- trust_anchors: check syntax of public keys in DNSKEY RRs (!748)
+- validator: clarify message about bogus non-authoritative data (!735)
+- dnssec validation failures contain more verbose reasoning (!735)
+- new function trust_anchors.summary() describes state of DNSSEC TAs (!737),
+ and logs new state of trust anchors after start up and automatic changes
+- trust anchors: refuse revoked DNSKEY even if specified explicitly,
+ and downgrade missing the SEP bit to a warning
+
+
+Knot Resolver 3.2.0 (2018-12-17)
+================================
+
+New features
+------------
+- module edns_keepalive to implement server side of RFC 7828 (#408)
+- module nsid to implement server side of RFC 5001 (#289)
+- module bogus_log provides .frequent() table (!629, credit Ulrich Wisser)
+- module stats collects flags from answer messages (!629, credit Ulrich Wisser)
+- module view supports multiple rules with identical address/TSIG specification
+ and keeps trying rules until a "non-chain" action is executed (!678)
+- module experimental_dot_auth implements an DNS-over-TLS to auth protocol
+ (!711, credit Manu Bretelle)
+- net.bpf bindings allow advanced users to use eBPF socket filters
+
+Bugfixes
+--------
+- http module: only run prometheus in parent process if using --forks=N,
+ as the submodule collects metrics from all sub-processes as well.
+- TLS fixes for corner cases (!700, !714, !716, !721, !728)
+- fix build with -DNOVERBOSELOG (#424)
+- policy.{FORWARD,TLS_FORWARD,STUB}: respect net.ipv{4,6} setting (!710)
+- avoid SERVFAILs due to certain kind of NS dependency cycles, again
+ (#374) this time seen as 'circular dependency' in verbose logs
+- policy and view modules do not overwrite result finished requests (!678)
+
+Improvements
+------------
+- Dockerfile: rework, basing on Debian instead of Alpine
+- policy.{FORWARD,TLS_FORWARD,STUB}: give advantage to IPv6
+ when choosing whom to ask, just as for iteration
+- use pseudo-randomness from gnutls instead of internal ISAAC (#233)
+- tune the way we deal with non-responsive servers (!716, !723)
+- documentation clarifies interaction between policy and view modules (!678, !730)
+
+Module API changes
+------------------
+- new layer is added: answer_finalize
+- kr_request keeps ::qsource.packet beyond the begin layer
+- kr_request::qsource.tcp renamed to ::qsource.flags.tcp
+- kr_request::has_tls renamed to ::qsource.flags.tls
+- kr_zonecut_add(), kr_zonecut_del() and kr_nsrep_sort() changed parameters slightly
+
+
+Knot Resolver 3.1.0 (2018-11-02)
+================================
+
+Incompatible changes
+--------------------
+- hints.use_nodata(true) by default; that's what most users want
+- libknot >= 2.7.2 is required
+
+Improvements
+------------
+- cache: handle out-of-space SIGBUS slightly better (#197)
+- daemon: improve TCP timeout handling (!686)
+
+Bugfixes
+--------
+- cache.clear('name'): fix some edge cases in API (#401)
+- fix error handling from TLS writes (!669)
+- avoid SERVFAILs due to certain kind of NS dependency cycles (#374)
+
+
+Knot Resolver 3.0.0 (2018-08-20)
+================================
+
+Incompatible changes
+--------------------
+- cache: fail lua operations if cache isn't open yet (!639)
+ By default cache is opened *after* reading the configuration,
+ and older versions were silently ignoring cache operations.
+ Valid configuration must open cache using `cache.open()` or `cache.size =`
+ before executing cache operations like `cache.clear()`.
+- libknot >= 2.7.1 is required, which brings also larger API changes
+- in case you wrote custom Lua modules, please consult
+ https://knot-resolver.readthedocs.io/en/latest/lib.html#incompatible-changes-since-3-0-0
+- in case you wrote custom C modules, please see compile against
+ Knot DNS 2.7 and adjust your module according to messages from C compiler
+- DNS cookie module (RFC 7873) is not available in this release,
+ it will be later reworked to reflect development in IEFT dnsop working group
+- version module was permanently removed because it was not really used by users;
+ if you want to receive notifications abou new releases please subscribe to
+ https://lists.nic.cz/cgi-bin/mailman/listinfo/knot-resolver-announce
+
+Bugfixes
+--------
+- fix multi-process race condition in trust anchor maintenance (!643)
+- ta_sentinel: also consider static trust anchors not managed via RFC 5011
+
+Improvements
+------------
+- reorder_RR() implementation is brought back
+- bring in performace improvements provided by libknot 2.7
+- cache.clear() has a new, more powerful API
+- cache documentation was improved
+- old name "Knot DNS Resolver" is replaced by unambiguous "Knot Resolver"
+ to prevent confusion with "Knot DNS" authoritative server
+
+
+Knot Resolver 2.4.1 (2018-08-02)
+================================
+
+Security
+--------
+- fix CVE-2018-10920: Improper input validation bug in DNS resolver component
+ (security!7, security!9)
+
+Bugfixes
+--------
+- cache: fix TTL overflow in packet due to min_ttl (#388, security!8)
+- TLS session resumption: avoid bad scheduling of rotation (#385)
+- HTTP module: fix a regression in 2.4.0 which broke custom certs (!632)
+- cache: NSEC3 negative cache even without NS record (#384)
+ This fixes lower hit rate in NSEC3 zones (since 2.4.0).
+- minor TCP and TLS fixes (!623, !624, !626)
+
+
+Knot Resolver 2.4.0 (2018-07-03)
+================================
+
+Incompatible changes
+--------------------
+- minimal libknot version is now 2.6.7 to pull in latest fixes (#366)
+
+Security
+--------
+- fix a rare case of zones incorrectly dowgraded to insecure status (!576)
+
+New features
+------------
+- TLS session resumption (RFC 5077), both server and client (!585, #105)
+ (disabled when compiling with gnutls < 3.5)
+- TLS_FORWARD policy uses system CA certificate store by default (!568)
+- aggressive caching for NSEC3 zones (!600)
+- optional protection from DNS Rebinding attack (module rebinding, !608)
+- module bogus_log to log DNSSEC bogus queries without verbose logging (!613)
+
+Bugfixes
+--------
+- prefill: fix ability to read certificate bundle (!578)
+- avoid turning off qname minimization in some cases, e.g. co.uk. (#339)
+- fix validation of explicit wildcard queries (#274)
+- dns64 module: more properties from the RFC implemented (incl. bug #375)
+
+Improvements
+------------
+- systemd: multiple enabled kresd instances can now be started using kresd.target
+- ta_sentinel: switch to version 14 of the RFC draft (!596)
+- support for glibc systems with a non-Linux kernel (!588)
+- support per-request variables for Lua modules (!533)
+- support custom HTTP endpoints for Lua modules (!527)
+
+
+Knot Resolver 2.3.0 (2018-04-23)
+================================
+
+Security
+--------
+- fix CVE-2018-1110: denial of service triggered by malformed DNS messages
+ (!550, !558, security!2, security!4)
+- increase resilience against slow lorris attack (security!5)
+
+New features
+------------
+- new policy.REFUSE to reply REFUSED to clients
+
+Bugfixes
+--------
+- validation: fix SERVFAIL in case of CNAME to NXDOMAIN in a single zone (!538)
+- validation: fix SERVFAIL for DS . query (!544)
+- lib/resolve: don't send unecessary queries to parent zone (!513)
+- iterate: fix validation for zones where parent and child share NS (!543)
+- TLS: improve error handling and documentation (!536, !555, !559)
+
+Improvements
+------------
+- prefill: new module to periodically import root zone into cache
+ (replacement for RFC 7706, !511)
+- network_listen_fd: always create end point for supervisor supplied file descriptor
+- use CPPFLAGS build environment variable if set (!547)
+
+
+Knot Resolver 2.2.0 (2018-03-28)
+================================
+
+New features
+------------
+- cache server unavailability to prevent flooding unreachable servers
+ (Please note that caching algorithm needs further optimization
+ and will change in further versions but we need to gather operational
+ experience first.)
+
+Bugfixes
+--------
+- don't magically -D_FORTIFY_SOURCE=2 in some cases
+- allow large responses for outbound over TCP
+- fix crash with RR sets with over 255 records
+
+
+Knot Resolver 2.1.1 (2018-02-23)
+================================
+
+Bugfixes
+--------
+- when iterating, avoid unnecessary queries for NS in insecure parent.
+ This problem worsened in 2.0.0. (#246)
+- prevent UDP packet leaks when using TLS forwarding
+- fix the hints module also on some other systems, e.g. Gentoo.
+
+
+Knot Resolver 2.1.0 (2018-02-16)
+================================
+
+Incompatible changes
+--------------------
+- stats: remove tracking of expiring records (predict uses another way)
+- systemd: re-use a single kresd.socket and kresd-tls.socket
+- ta_sentinel: implement protocol draft-ietf-dnsop-kskroll-sentinel-01
+ (our draft-ietf-dnsop-kskroll-sentinel-00 implementation had inverted logic)
+- libknot: require version 2.6.4 or newer to get bugfixes for DNS-over-TLS
+
+Bugfixes
+--------
+- detect_time_jump module: don't clear cache on suspend-resume (#284)
+- stats module: fix stats.list() returning nothing, regressed in 2.0.0
+- policy.TLS_FORWARD: refusal when configuring with multiple IPs (#306)
+- cache: fix broken refresh of insecure records that were about to expire
+- fix the hints module on some systems, e.g. Fedora (came back on 2.0.0)
+- build with older gnutls (conditionally disable features)
+- fix the predict module to work with insecure records & cleanup code
+
+
+Knot Resolver 2.0.0 (2018-01-31)
+================================
+
+Incompatible changes
+--------------------
+- systemd: change unit files to allow running multiple instances,
+ deployments with single instance now must use `kresd@1.service`
+ instead of `kresd.service`; see kresd.systemd(7) for details
+- systemd: the directory for cache is now /var/cache/knot-resolver
+- unify default directory and user to `knot-resolver`
+- directory with trust anchor file specified by -k option must be writeable
+- policy module is now loaded by default to enforce RFC 6761;
+ see documentation for policy.PASS if you use locally-served DNS zones
+- drop support for alternative cache backends memcached, redis,
+ and for Lua bindings for some specific cache operations
+- REORDER_RR option is not implemented (temporarily)
+
+New features
+------------
+- aggressive caching of validated records (RFC 8198) for NSEC zones;
+ thanks to ICANN for sponsoring this work.
+- forwarding over TLS, authenticated by SPKI pin or certificate.
+ policy.TLS_FORWARD pipelines queries out-of-order over shared TLS connection
+ Beware: Some resolvers do not support out-of-order query processing.
+ TLS forwarding to such resolvers will lead to slower resolution or failures.
+- trust anchors: you may specify a read-only file via -K or --keyfile-ro
+- trust anchors: at build-time you may set KEYFILE_DEFAULT (read-only)
+- ta_sentinel module implements draft ietf-dnsop-kskroll-sentinel-00,
+ enabled by default
+- serve_stale module is prototype, subject to change
+- extended API for Lua modules
+
+Bugfixes
+--------
+- fix build on osx - regressed in 1.5.3 (different linker option name)
+
+
+Knot Resolver 1.5.3 (2018-01-23)
+================================
+
+Bugfixes
+--------
+- fix the hints module on some systems, e.g. Fedora.
+ Symptom: `undefined symbol: engine_hint_root_file`
+
+
+Knot Resolver 1.5.2 (2018-01-22)
+================================
+
+Security
+--------
+- fix CVE-2018-1000002: insufficient DNSSEC validation, allowing
+ attackers to deny existence of some data by forging packets.
+ Some combinations pointed out in RFC 6840 sections 4.1 and 4.3
+ were not taken into account.
+
+Bugfixes
+--------
+- memcached: fix fallout from module rename in 1.5.1
+
+
+Knot Resolver 1.5.1 (2017-12-12)
+================================
+
+Incompatible changes
+--------------------
+- script supervisor.py was removed, please migrate to a real process manager
+- module ketcd was renamed to etcd for consistency
+- module kmemcached was renamed to memcached for consistency
+
+Bugfixes
+--------
+- fix SIGPIPE crashes (#271)
+- tests: work around out-of-space for platforms with larger memory pages
+- lua: fix mistakes in bindings affecting 1.4.0 and 1.5.0 (and 1.99.1-alpha),
+ potentially causing problems in dns64 and workarounds modules
+- predict module: various fixes (!399)
+
+Improvements
+------------
+- add priming module to implement RFC 8109, enabled by default (#220)
+- add modules helping with system time problems, enabled by default;
+ for details see documentation of detect_time_skew and detect_time_jump
+
+
+Knot Resolver 1.5.0 (2017-11-02)
+================================
+
+Bugfixes
+--------
+- fix loading modules on Darwin
+
+Improvements
+------------
+- new module ta_signal_query supporting Signaling Trust Anchor Knowledge
+ using Keytag Query (RFC 8145 section 5); it is enabled by default
+- attempt validation for more records but require it for fewer of them
+ (e.g. avoids SERVFAIL when server adds extra records but omits RRSIGs)
+
+
+Knot Resolver 1.99.1-alpha (2017-10-26)
+=======================================
+This is an experimental release meant for testing aggressive caching.
+It contains some regressions and might (theoretically) be even vulnerable.
+The current focus is to minimize queries into the root zone.
+
+Improvements
+------------
+- negative answers from validated NSEC (NXDOMAIN, NODATA)
+- verbose log is very chatty around cache operations (maybe too much)
+
+Regressions
+-----------
+- dropped support for alternative cache backends
+ and for some specific cache operations
+- caching doesn't yet work for various cases:
+ * negative answers without NSEC (i.e. with NSEC3 or insecure)
+ * +cd queries (needs other internal changes)
+ * positive wildcard answers
+- spurious SERVFAIL on specific combinations of cached records, printing:
+ <= bad keys, broken trust chain
+- make check
+- a few Deckard tests are broken, probably due to some problems above
+- also unknown ones?
+
+
+
+Knot Resolver 1.4.0 (2017-09-22)
+================================
+
+Incompatible changes
+--------------------
+- lua: query flag-sets are no longer represented as plain integers.
+ kres.query.* no longer works, and kr_query_t lost trivial methods
+ 'hasflag' and 'resolved'.
+ You can instead write code like qry.flags.NO_0X20 = true.
+
+Bugfixes
+--------
+- fix exiting one of multiple forks (#150)
+- cache: change the way of using LMDB transactions. That in particular
+ fixes some cases of using too much space with multiple kresd forks (#240).
+
+Improvements
+------------
+- policy.suffix: update the aho-corasick code (#200)
+- root hints are now loaded from a zonefile; exposed as hints.root_file().
+ You can override the path by defining ROOTHINTS during compilation.
+- policy.FORWARD: work around resolvers adding unsigned NS records (#248)
+- reduce unneeded records previously put into authority in wildcarded answers
+
+
+Knot Resolver 1.3.3 (2017-08-09)
+================================
+
+Security
+--------
+- Fix a critical DNSSEC flaw. Signatures might be accepted as valid
+ even if the signed data was not in bailiwick of the DNSKEY used to
+ sign it, assuming the trust chain to that DNSKEY was valid.
+
+Bugfixes
+--------
+- iterate: skip RRSIGs with bad label count instead of immediate SERVFAIL
+- utils: fix possible incorrect seeding of the random generator
+- modules/http: fix compatibility with the Prometheus text format
+
+Improvements
+------------
+- policy: implement remaining special-use domain names from RFC6761 (#205),
+ and make these rules apply only if no other non-chain rule applies
+
+
+Knot Resolver 1.3.2 (2017-07-28)
+================================
+
+Security
+--------
+- fix possible opportunities to use insecure data from cache as keys
+ for validation
+
+Bugfixes
+--------
+- daemon: check existence of config file even if rundir isn't specified
+- policy.FORWARD and STUB: use RTT tracking to choose servers (#125, #208)
+- dns64: fix CNAME problems (#203) It still won't work with policy.STUB.
+- hints: better interpretation of hosts-like files (#204)
+ also, error out if a bad entry is encountered in the file
+- dnssec: handle unknown DNSKEY/DS algorithms (#210)
+- predict: fix the module, broken since 1.2.0 (#154)
+
+Improvements
+------------
+- embedded LMDB fallback: update 0.9.18 -> 0.9.21
+
+
+Knot Resolver 1.3.1 (2017-06-23)
+================================
+
+Bugfixes
+--------
+- modules/http: fix finding the static files (bug from 1.3.0)
+- policy.FORWARD: fix some cases of CNAMEs obstructing search for zone cuts
+
+
+Knot Resolver 1.3.0 (2017-06-13)
+================================
+
+Security
+--------
+- Refactor handling of AD flag and security status of resource records.
+ In some cases it was possible for secure domains to get cached as
+ insecure, even for a TLD, leading to disabled validation.
+ It also fixes answering with non-authoritative data about nameservers.
+
+Improvements
+------------
+- major feature: support for forwarding with validation (#112).
+ The old policy.FORWARD action now does that; the previous non-validating
+ mode is still available as policy.STUB except that also uses caching (#122).
+- command line: specify ports via @ but still support # for compatibility
+- policy: recognize 100.64.0.0/10 as local addresses
+- layer/iterate: *do* retry repeatedly if REFUSED, as we can't yet easily
+ retry with other NSs while avoiding retrying with those who REFUSED
+- modules: allow changing the directory where modules are found,
+ and do not search the default library path anymore.
+
+Bugfixes
+--------
+- validate: fix insufficient caching for some cases (relatively rare)
+- avoid putting "duplicate" record-sets into the answer (#198)
+
+
+Knot Resolver 1.2.6 (2017-04-24)
+================================
+
+Security
+--------
+- dnssec: don't set AD flag for NODATA answers if wildcard non-existence
+ is not guaranteed due to opt-out in NSEC3
+
+Improvements
+------------
+- layer/iterate: don't retry repeatedly if REFUSED
+
+Bugfixes
+--------
+- lib/nsrep: revert some changes to NS reputation tracking that caused
+ severe problems to some users of 1.2.5 (#178 and #179)
+- dnssec: fix verification of wildcarded non-singleton RRsets
+- dnssec: allow wildcards located directly under the root
+- layer/rrcache: avoid putting answer records into queries in some cases
+
+
+Knot Resolver 1.2.5 (2017-04-05)
+================================
+
+Security
+--------
+- layer/validate: clear AD if closest encloser proof has opt-outed
+ NSEC3 (#169)
+- layer/validate: check if NSEC3 records in wildcard expansion proof
+ has an opt-out
+- dnssec/nsec: missed wildcard no-data answers validation has been
+ implemented
+
+Improvements
+------------
+- modules/dnstap: a DNSTAP support module
+ (Contributed by Vicky Shrestha)
+- modules/workarounds: a module adding workarounds for known
+ DNS protocol violators
+- layer/iterate: fix logging of glue addresses
+- kr_bitcmp: allow bits=0 and consequently 0.0.0.0/0 matches in view
+ and renumber modules.
+- modules/padding: Improve default padding of responses
+ (Contributed by Daniel Kahn Gillmor)
+- New kresc client utility (experimental; don't rely on the API yet)
+
+Bugfixes
+--------
+- trust anchors: Improve trust anchors storage format (#167)
+- trust anchors: support non-root TAs, one domain per file
+- policy.DENY: set AA flag and clear AD flag
+- lib/resolve: avoid unnecessary DS queries
+- lib/nsrep: don't treat servers with NOIP4 + NOIP6 flags as timeouted
+- layer/iterate: During packet classification (answer vs. referral)
+ don't analyze AUTHORITY section in authoritative answer if ANSWER
+ section contains records that have been requested
+
+
+Knot Resolver 1.2.4 (2017-03-09)
+================================
+
+Security
+--------
+- Knot Resolver 1.2.0 and higher could return AD flag for insecure
+ answer if the daemon received answer with invalid RRSIG several
+ times in a row.
+
+Improvements
+------------
+- modules/policy: allow QTRACE policy to be chained with other
+ policies
+- hints.add_hosts(path): a new property
+- module: document the API and simplify the code
+- policy.MIRROR: support IPv6 link-local addresses
+- policy.FORWARD: support IPv6 link-local addresses
+- add net.outgoing_{v4,v6} to allow specifying address to use for
+ connections
+
+Bugfixes
+--------
+- layer/iterate: some improvements in cname chain unrolling
+- layer/validate: fix duplicate records in AUTHORITY section in case
+ of WC expansion proof
+- lua: do *not* truncate cache size to unsigned
+- forwarding mode: correctly forward +cd flag
+- fix a potential memory leak
+- don't treat answers that contain DS non-existance proof as insecure
+- don't store NSEC3 and their signatures in the cache
+- layer/iterate: when processing delegations, check if qname is at or
+ below new authority
+
+
+Knot Resolver 1.2.3 (2017-02-23)
+================================
+
+Bugfixes
+--------
+- Disable storing GLUE records into the cache even in the
+ (non-default) QUERY_PERMISSIVE mode
+- iterate: skip answer RRs that don't match the query
+- layer/iterate: some additional processing for referrals
+- lib/resolve: zonecut fetching error was fixed
+
+
+Knot Resolver 1.2.2 (2017-02-10)
+================================
+
+Bugfixes:
+---------
+- Fix -k argument processing to avoid out-of-bounds memory accesses
+- lib/resolve: fix zonecut fetching for explicit DS queries
+- hints: more NULL checks
+- Fix TA bootstrapping for multiple TAs in the IANA XML file
+
+Testing:
+--------
+- Update tests to run tests with and without QNAME minimization
+
+
+Knot Resolver 1.2.1 (2017-02-01)
+====================================
+
+Security:
+---------
+- Under certain conditions, a cached negative answer from a CD query
+ would be reused to construct response for non-CD queries, resulting
+ in Insecure status instead of Bogus. Only 1.2.0 release was affected.
+
+Documentation
+-------------
+- Update the typo in the documentation: The query trace policy is
+ named policy.QTRACE (and not policy.TRACE)
+
+Bugfixes:
+---------
+- lua: make the map command check its arguments
+
+
+Knot Resolver 1.2.0 (2017-01-24)
+====================================
+
+Security:
+---------
+- In a policy.FORWARD() mode, the AD flag was being always set by mistake.
+ It is now cleared, as the policy.FORWARD() doesn't do DNSSEC validation yet.
+
+Improvements:
+-------------
+- The DNSSEC Validation has been refactored, fixing many resolving
+ failures.
+- Add module `version` that checks for updates and CVEs periodically.
+- Support RFC7830: EDNS(0) padding in responses over TLS.
+- Support CD flag on incoming requests.
+- hints module: previously /etc/hosts was loaded by default, but not anymore.
+ Users can now actually avoid loading any file.
+- DNS over TLS now creates ephemeral certs.
+- Configurable cache.{min,max}_tll option, with max_ttl defaulting to 6 days.
+- Option to reorder RRs in the response.
+- New policy.QTRACE policy to print packet contents
+
+Bugfixes:
+---------
+- Trust Anchor configuration is now more robust.
+- Correctly answer NOTIMPL for meta-types and non-IN RR classes.
+- Free TCP buffer on cancelled connection.
+- Fix crash in hints module on empty hints file, and fix non-lowercase hints.
+
+Miscellaneous:
+--------------
+- It now requires knot >= 2.3.1 to link successfully.
+- The API+ABI for modules changed slightly.
+- New LRU implementation.
+
+
+Knot Resolver 1.1.1 (2016-08-24)
+================================
+
+Bugfixes:
+---------
+ - Fix 0x20 randomization with retransmit
+ - Fix pass-through for the stub mode
+ - Fix the root hints IPv6 addresses
+ - Fix dst addr for retries over TCP
+
+Improvements:
+-------------
+ - Track RTT of all tried servers for faster retransmit
+ - DAF: Allow forwarding to custom port
+ - systemd: Read EnvironmentFile and user $KRESD_ARGS
+ - systemd: Update systemd units to be named after daemon
+
+
+Knot Resolver 1.1.0 (2016-08-12)
+================================
+
+Improvements:
+-------------
+ - RFC7873 DNS Cookies
+ - RFC7858 DNS over TLS
+ - HTTP/2 web interface, RESTful API
+ - Metrics exported in Prometheus
+ - DNS firewall module
+ - Explicit CNAME target fetching in strict mode
+ - Query minimisation improvements
+ - Improved integration with systemd
+
+
+Knot Resolver 1.0.0 (2016-05-30)
+================================
+
+Initial release:
+----------------
+ - The first initial release
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..32bf526
--- /dev/null
+++ b/README.md
@@ -0,0 +1,74 @@
+# Knot Resolver
+
+[![Build Status](https://gitlab.labs.nic.cz/knot/knot-resolver/badges/nightly/pipeline.svg?x)](https://gitlab.labs.nic.cz/knot/knot-resolver/commits/nightly)
+[![Coverage Status](https://gitlab.labs.nic.cz/knot/knot-resolver/badges/nightly/coverage.svg?x)](https://knot.pages.labs.nic.cz/knot-resolver/)
+[![Documentation Status](https://readthedocs.org/projects/knot-resolver/badge/?version=latest)](https://readthedocs.org/projects/knot-resolver/?badge=latest)
+
+Knot Resolver is a caching full resolver implementation written in C and [LuaJIT][luajit], both a resolver library and a daemon. The core architecture is tiny and efficient, and provides a foundation and
+a state-machine like API for extensions. There are three modules built-in - *iterator*, *validator*, *cache*, and a few more are loaded by default. Most of the [rich features](https://knot-resolver.readthedocs.io/en/latest/modules.html) are written in Lua(JIT) and C. Batteries are included, but optional.
+
+The LuaJIT modules, support DNS privacy and DNSSEC, and persistent cache with low memory footprint make it a great personal DNS resolver or a research tool to tap into DNS data. TL;DR it's the [OpenResty][openresty] of DNS.
+
+Strong filtering rules, and auto-configuration with etcd make it a great large-scale resolver solution.
+
+The server adopts a [different scaling strategy][scaling] than the rest of the DNS recursors - no threading, shared-nothing architecture (except MVCC cache that may be shared) that allows you to pin instances on available CPU cores and grow by self-replication. You can start and stop additional nodes depending on the contention without downtime.
+
+It also has strong support for DNS over TCP, notably TCP Fast-Open, query pipelining and deduplication, and response reordering.
+
+### Packages
+
+The latest stable packages for various distributions are available in our
+[upstream repository](https://build.opensuse.org/package/show/home:CZ-NIC:knot-resolver-latest/knot-resolver).
+Follow the
+[installation instructions](https://software.opensuse.org//download.html?project=home%3ACZ-NIC%3Aknot-resolver-latest&package=knot-resolver)
+to add this repository to your system.
+
+Knot Resolver is also available from the following distributions' repositories.
+
+* [Fedora and Fedora EPEL](https://apps.fedoraproject.org/packages/knot-resolver)
+* [Debian stable](https://packages.debian.org/stable/knot-resolver),
+ [Debian testing](https://packages.debian.org/testing/knot-resolver),
+ [Debian unstable](https://packages.debian.org/sid/knot-resolver)
+* [Ubuntu](https://packages.ubuntu.com/bionic/knot-resolver)
+* [Arch Linux (AUR)](https://aur.archlinux.org/packages/knot-resolver)
+
+### Building from sources
+
+Knot Resolver mainly [depends][depends] on Knot DNS libraries, [LuaJIT][luajit] and [libuv][libuv].
+See the [Building project][depends] documentation page for more information.
+
+### Docker image
+
+This is simple and doesn't require any dependencies or system modifications, just run:
+
+```
+$ docker run -Pit cznic/knot-resolver
+```
+
+See the build page [hub.docker.com/r/cznic/knot-resolver](https://hub.docker.com/r/cznic/knot-resolver/) for more information and options.
+The images are meant as an easy way to try knot-resolver, and they're not designed for production use.
+
+### Running
+
+The project builds a resolver library in the `lib` directory, and a daemon in the `daemon` directory. It requires no configuration or parameters to run a server on localhost.
+
+```
+$ kresd
+```
+
+See the documentation at [knot-resolver.readthedocs.io][doc] for more options.
+
+[depends]: https://knot-resolver.readthedocs.io/en/stable/build.html
+[doc]: https://knot-resolver.readthedocs.io/en/stable/index.html
+[scaling]: https://knot-resolver.readthedocs.io/en/stable/daemon.html#scaling-out
+[deckard]: https://gitlab.labs.nic.cz/knot/deckard
+[luajit]: https://luajit.org/
+[libuv]: http://libuv.org
+[openresty]: https://openresty.org/
+
+### Contacting us
+
+- [GitLab issues](https://gitlab.labs.nic.cz/knot/knot-resolver/issues) (you may authenticate via GitHub)
+- [mailing list](https://lists.nic.cz/cgi-bin/mailman/listinfo/knot-resolver-users)
+- [![Join the chat at https://gitter.im/CZ-NIC/knot-resolver](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/CZ-NIC/knot-resolver?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
diff --git a/bench/bench.mk b/bench/bench.mk
new file mode 100644
index 0000000..e010039
--- /dev/null
+++ b/bench/bench.mk
@@ -0,0 +1,28 @@
+bench_BIN := \
+ bench_lru
+
+# Dependencies
+bench_DEPEND := $(libkres)
+bench_LIBS := $(libkres_TARGET) $(libkres_LIBS)
+
+# Make bench binaries
+define make_bench
+$(1)_CFLAGS := -fPIE
+$(1)_SOURCES := bench/$(1).c
+$(1)_LIBS := $(bench_LIBS)
+$(1)_DEPEND := $(bench_DEPEND)
+$(call make_bin,$(1),bench)
+endef
+
+$(foreach bench,$(bench_BIN),$(eval $(call make_bench,$(bench))))
+
+# Targets
+.PHONY: bench bench-clean
+bench-clean: $(foreach bench,$(bench_BIN),$(bench)-clean)
+bench: $(foreach bench,$(bench_BIN),bench/$(bench))
+ @echo "Test LRU with increasing overfill, misses should increase ~ linearly" >&2
+ $(preload_syms) ./bench/bench_lru 23 bench/bench_lru_set1.tsv - 65536 # fill ~ 1
+ $(preload_syms) ./bench/bench_lru 23 bench/bench_lru_set1.tsv - 32768 # fill ~ 2
+ $(preload_syms) ./bench/bench_lru 23 bench/bench_lru_set1.tsv - 16384 # fill ~ 4
+ $(preload_syms) ./bench/bench_lru 23 bench/bench_lru_set1.tsv - 8192 # fill ~ 8
+ $(preload_syms) ./bench/bench_lru 23 bench/bench_lru_set1.tsv - 4096 # fill ~ 16
diff --git a/bench/bench_lru.c b/bench/bench_lru.c
new file mode 100644
index 0000000..63bbeeb
--- /dev/null
+++ b/bench/bench_lru.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "contrib/ucw/lib.h"
+#include "daemon/engine.h"
+#include "lib/nsrep.h"
+
+typedef kr_nsrep_lru_t lru_bench_t;
+
+#define p_out(...) do { \
+ printf(__VA_ARGS__); \
+ fflush(stdout); \
+ } while (0)
+#define p_err(...) fprintf(stderr, __VA_ARGS__)
+
+static int die(const char *cause)
+{
+ fprintf(stderr, "%s: %s\n", cause, strerror(errno));
+ exit(1);
+}
+
+static void time_get(struct timeval *tv)
+{
+ if (gettimeofday(tv, NULL))
+ die("gettimeofday");
+}
+static void time_print_diff(struct timeval *tv, size_t op_count)
+{
+ struct timeval now;
+ time_get(&now);
+ now.tv_sec -= tv->tv_sec;
+ now.tv_usec -= tv->tv_usec;
+ if (now.tv_usec < 0) {
+ now.tv_sec -= 1;
+ now.tv_usec += 1000000;
+ }
+
+ size_t speed = round((double)(op_count) / 1000
+ / (now.tv_sec + (double)(now.tv_usec)/1000000));
+
+ p_out("%ld.%06d", now.tv_sec, (int)now.tv_usec);
+ p_err(" s"); p_out(","); p_err("\t");
+ p_out("%zd", speed);
+ p_err(" kops/s"); p_out(","); p_err("\n");
+}
+
+/// initialize seed for random()
+static int ssrandom(char *s)
+{
+ if (*s == '-') { // initialize from time
+ struct timeval now;
+ time_get(&now);
+ srandom(now.tv_sec * 1000000 + now.tv_usec);
+ return 0;
+ }
+
+ // initialize from a string
+ size_t len = strlen(s);
+ if (len < 12)
+ return(-1);
+ unsigned seed = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ initstate(seed, s+4, len-4);
+ return 0;
+}
+
+struct key {
+ size_t len;
+ char *chars;
+};
+
+/// read lines from a file and reorder them randomly
+static struct key * read_lines(const char *fname, size_t *count, char **pfree)
+{
+ // read the file at once
+ int fd = open(fname, O_RDONLY);
+ if (fd < 0)
+ die("open");
+ struct stat st;
+ if (fstat(fd, &st) < 0)
+ die("stat");
+ size_t flen = (size_t)st.st_size;
+ char *fbuf = malloc(flen + 1);
+ *pfree = fbuf;
+ if (fbuf == NULL)
+ die("malloc");
+ if (read(fd, fbuf, flen) < 0)
+ die("read");
+ close(fd);
+ fbuf[flen] = '\0';
+
+ // get pointers to individual lines
+ size_t lines = 0;
+ for (size_t i = 0; i < flen; ++i)
+ if (fbuf[i] == '\n') {
+ fbuf[i] = 0;
+ ++lines;
+ }
+ *count = lines;
+ size_t avg_len = (flen + 1) / lines - 1;
+
+ p_err("lines read: ");
+ p_out("%zu,", lines);
+ p_err("\taverage length ");
+ p_out("%zu,", avg_len);
+
+ struct key *result = calloc(lines, sizeof(struct key));
+ result[0].chars = fbuf;
+ for (size_t l = 0; l < lines; ++l) {
+ size_t i = 0;
+ while (result[l].chars[i])
+ ++i;
+ result[l].len = i;
+ if (l + 1 < lines)
+ result[l + 1].chars = result[l].chars + i + 1;
+ }
+
+ //return result;
+ // reorder the lines randomly (via "random select-sort")
+ // note: this makes their order non-sequential *in memory*
+ if (RAND_MAX < lines)
+ die("RAND_MAX is too small");
+ for (size_t i = 0; i < lines - 1; ++i) { // swap i with random j >= i
+ size_t j = i + random() % (lines - i);
+ if (j != i) {
+ struct key tmp = result[i];
+ result[i] = result[j];
+ result[j] = tmp;
+ }
+ }
+
+ return result;
+}
+
+// compatibility layer for the oler lru_* names; it's more compler with lru_create
+#ifndef lru_create
+ #define lru_get_new lru_set
+ #define lru_get_try lru_get
+#endif
+
+static void usage(const char *progname)
+{
+ p_err("usage: %s <log_count> <input> <seed> [lru_size]\n", progname);
+ p_err("The seed must be at least 12 characters or \"-\".\n"
+ "Standard output contains csv-formatted lines.\n");
+ exit(1);
+}
+
+
+int main(int argc, char ** argv)
+{
+ if (argc != 4 && argc != 5)
+ usage(argv[0]);
+ if (ssrandom(argv[3]) < 0)
+ usage(argv[0]);
+
+ p_out("\n");
+ size_t key_count;
+ char *data_to_free = NULL;
+ struct key *keys = read_lines(argv[2], &key_count, &data_to_free);
+ size_t run_count;
+ {
+ size_t run_log = atoi(argv[1]);
+ assert(run_log < 64);
+ run_count = 1ULL << run_log;
+ p_err("\ntest run length:\t2^");
+ p_out("%zd,", run_log);
+ }
+
+ struct timeval time;
+ const int lru_size = argc > 4 ? atoi(argv[4]) : LRU_RTT_SIZE;
+
+ lru_bench_t *lru;
+ #ifdef lru_create
+ lru_create(&lru, lru_size, NULL, NULL);
+ #else
+ lru = malloc(lru_size(lru_bench_t, lru_size));
+ if (lru)
+ lru_init(lru, lru_size);
+ #endif
+ if (!lru)
+ die("malloc");
+ p_err("\nLRU capacity:\t");
+ p_out("%d,",
+ #ifdef lru_capacity
+ lru_capacity(lru) // report real capacity, if provided
+ #else
+ lru_size
+ #endif
+ );
+
+ size_t miss = 0;
+ p_err("\nload everything:\t");
+ time_get(&time);
+ for (size_t i = 0, ki = key_count - 1; i < run_count; ++i, --ki) {
+ unsigned *r = lru_get_new(lru, keys[ki].chars, keys[ki].len, NULL);
+ if (!r || *r == 0)
+ ++miss;
+ if (r)
+ *r = 1;
+ if (unlikely(ki == 0))
+ ki = key_count;
+ }
+ time_print_diff(&time, run_count);
+ p_err("LRU misses [%%]:\t");
+ p_out("%zd,",(miss * 100 + 50) / run_count);
+ p_err("\n");
+
+ unsigned accum = 0; // compute something to make sure compiler can't remove code
+ p_err("search everything:\t");
+ time_get(&time);
+ for (size_t i = 0, ki = key_count - 1; i < run_count; ++i, --ki) {
+ unsigned *r = lru_get_try(lru, keys[ki].chars, keys[ki].len);
+ if (r)
+ accum += *r;
+ if (unlikely(ki == 0))
+ ki = key_count;
+ }
+ time_print_diff(&time, run_count);
+ p_err("ignore: %u\n", accum);
+
+ // free memory, at least with new LRU
+ #ifdef lru_create
+ lru_free(lru);
+ #endif
+ free(keys);
+ free(data_to_free);
+
+ return 0;
+}
+
diff --git a/bench/bench_lru_set1.tsv b/bench/bench_lru_set1.tsv
new file mode 100644
index 0000000..7cb2351
--- /dev/null
+++ b/bench/bench_lru_set1.tsv
@@ -0,0 +1,65536 @@
+thumbs2.ebaystatic.com.
+mountaineerpublishing.com.
+www.mediafire.com.
+s-static.ak.fbcdn.net.
+lachicabionica.com.
+www.freemarket.com.
+sip.hotmail.com.
+www.cangrejas.com.
+google.com.
+cache.defamer.com.
+developers.facebook.com.
+www.eucarvet.eu.
+mail.mobilni-telefony.biz.
+microsoft-powerpoint-2010.softonic.it.
+profile.ak.fbcdn.net.
+www.zunescene.mobi.
+ads.smowtion.com.
+196.127.197.94.in-addr.arpa.
+armandi.ru.
+solofarandulaperu.blogspot.com.
+m.addthisedge.com.
+ssl.google-analytics.com.
+243.35.149.83.in-addr.arpa.
+105.138.138.201.in-addr.arpa.
+www.reuters.com.
+mail.sodoit.com.
+www.download.windowsupdate.com.
+resquare.ca.
+photos-e.ak.fbcdn.net.
+csi.gstatic.com.
+www.darty.lu.
+6138.7370686f746f73.616b.666263646e.6e6574.80h3f617b3a.webcfs00.com.
+frycomm.com.s9b2.psmtp.com.
+www.apple.com.
+www.haacked.com.
+www.jujiaow.com.
+170.44.153.187.in-addr.arpa.
+a1007.w43.akamai.net.
+api.facebook.com.
+dns.msftncsi.com.
+sageinc.com.
+a.root-servers.net.
+google.com.
+photos-a.ak.fbcdn.net.
+developers.facebook.com.
+a995.mm1.akamai.net.
+a.root-servers.net.
+api.twitter.com.
+a.root-servers.net.
+pub.reggaefrance.com.
+an.d.chango.com.
+mogesa.com.mx.
+0.11-a3092481.20483.1518.18a4.3ea1.410.0.ezg6u89nikkw32n9ssr1pcd8ei.avqs.mcafee.com.
+www.gossiponthis.com.
+www.asil.com.ar.
+mail.mastertex.com.
+www.foxsportsla.com.
+profile.ak.fbcdn.net.
+picture.immobilienscout24.de.
+138.191.114.187.in-addr.arpa.
+71.209.110.187.in-addr.arpa.
+education.idoneos.com.
+api.twitter.com.
+photos-c.ak.fbcdn.net.
+kepco.co.kr.
+developers.facebook.com.
+i2.ytimg.com.
+202.160.142.190.in-addr.arpa.
+blogparts.okwave.jp.
+3.254.244.201.in-addr.arpa.
+edge.quantserve.com.
+a6.sphotos.ak.fbcdn.net.
+hi-in.facebook.com.
+cjqxdgoea.q61b6c1l.
+google.com.mx.
+profile.ak.fbcdn.net.
+233.252.0.201.in-addr.arpa.
+local-bay.contacts.msn.com.
+www.facebook.com.
+creative.ak.fbcdn.net.
+ad.afy11.net.
+es-es.facebook.com.
+175.130.35.186.in-addr.arpa.
+ares.jsc.nasa.gov.
+madewithluv.com.
+252.0.168.192.in-addr.arpa.
+iztvkxdza.z57y1u5n.
+quakerfabric.com.
+s306.videobb.com.
+washeen91.writingjob.hop.clickbank.net.
+155.56.250.190.in-addr.arpa.
+1.0.0.127.in-addr.arpa.
+iguanas.mex.tl.
+habbo.com.mx.
+es-es.facebook.com.
+www.gossipsauce.com.
+251.206.15.201.in-addr.arpa.
+trk.paid-surveys-at-home.com.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+andrewsullivan.com.
+i499.photobucket.com.
+www.hotelelreymoro.com.
+www.microsoft.com.
+www.gonelocal.com.
+rad.msn.com.
+tienda.imperioh2.cl.
+a.root-servers.net.
+img.apnanalytics.com.
+apps.facebook.com.
+www.shareyouritems.com.
+yog34.games.ac4.yahoo.com.
+www.man-engines.com.
+translate.google.com.mx.
+aoqrf2:by.v75i0e0a.
+26.250.168.189.in-addr.arpa.
+_156_03_7.
+a.root-servers.net.
+sbsio.coast.ru.
+nothirst.com.
+64.193.75.85.in-addr.arpa.
+asktoolbar.weather.com.
+160.204.126.216.in-addr.arpa.
+a.root-servers.net.
+img.youtube.com.
+a.root-servers.net.
+cn.pool.ntp.org.
+www.facebook.com.
+s1.wp.com.
+tcpl.ca.
+3d.angrybirds.name.
+s.youtube.com.
+gma.yahoo.com.
+lh3.ggpht.com.
+fistintheair.com.
+_ldap._tcp.
+connect.facebook.net.
+hackingetico.com.
+static.xvideos.com.
+blog.mobango.com.
+st.chatango.com.
+marketingdesdelaromana.blogspot.com.
+www.juegospara.com.
+toolbarqueries.google.com.
+chinamoly.com.
+160.140.6.186.in-addr.arpa.
+a.root-servers.net.
+143.133.213.201.in-addr.arpa.
+different-love.foroactivo.com.
+data-recovery-free-help.blogspot.com.
+stores.ebay.es.
+darkanime.mforos.com.
+cs.cornell.edu.
+206.62.154.189.in-addr.arpa.
+i2.ytimg.com.
+a.root-servers.net.
+dmse.com.
+mediacdn.disqus.com.
+profile.ak.fbcdn.net.
+2.200.126.85.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+cityvillefb0.static.zgncdn.com.
+laplumadebarro.blogspot.com.
+www.feelthesteel.biz.
+84.178.30.190.in-addr.arpa.
+www.google.com.
+client66.dropbox.com.
+t2.gstatic.com.
+cdn.mediafire.com.
+urls.api.twitter.com.
+sanlasar.ru.
+serialnumber.in.
+tech-whitepapers.manta.com.
+tsuki-yaoi.blogspot.com.
+123mail.cl.
+imap.gmail.com.
+58.213.21.89.in-addr.arpa.
+246.254.24.95.in-addr.arpa.
+mychemhelena.obolog.com.
+lbpdmsmsa01.d.r.dfait-maeci.gc.ca.
+84.235.75.201.in-addr.arpa.
+lhuhbu.com.
+www.humorpower.com.
+a1.sphotos.ak.fbcdn.net.
+mn.wikipedia.org.
+eu4.stvid.com.
+www.difasa.net.
+www.ct-7ob.com.
+novp.spb.su.
+video.xnxx.com.
+mindspring.net.
+142.190.65.95.in-addr.arpa.
+ssl.gstatic.com.
+www.cinemanow.com.
+www.nolimitweb.nl.
+ducs.millsshirley.com.
+setting3.yeahost.com.
+www.solo.aqui.creatusfrases.net.
+static.ak.fbcdn.net.
+6bf8e:23q.b92o9u1a.
+developers.facebook.com.
+a.root-servers.net.
+butovo.com.
+host1.dia.net.
+lg-phones.org.
+www.birdseye.com.
+www.inpolitics.ro.
+abajate.blogspot.com.
+134.18.23.186.in-addr.arpa.
+www.blackberry.com.
+rodina-kino.ru.
+91.233.90.2.in-addr.arpa.
+ib.adnxs.com.
+39.152.29.186.in-addr.arpa.
+email.com.
+0.11-270f7081.c120081.1518.195c.3ea0.210.0.rgc396q1h2icmzvnthlvztdn7v.avqs.mcafee.com.
+static.ak.fbcdn.net.
+_963_91_2.
+zagsmoscow.ru.
+37.50.93.200.in-addr.arpa.
+sport.allyoubet.com.
+www.facebook.com.
+mt1.googleapis.com.
+l.yimg.com.
+a.root-servers.net.
+t7.tagstat.com.
+books.google.com.mx.
+ucs.query.yahoo.com.
+i4.ytimg.com.
+rylandhomes.com.
+google.com.
+49.147.220.66.in-addr.arpa.
+sfdr-cisd.com.
+9-1.qlty.finarea.ch.
+goodereader.disqus.com.
+ch.tudelft.nl.
+1496354998.mail.outlook.com.
+landrover.tagworldwide.com.
+87.197.160.201.in-addr.arpa.
+_ldap._tcp.
+i4.ytimg.com.
+s1-excel.vo.msecnd.net.
+download884.avast.com.
+www.unrunescape.com.
+hi-in.facebook.com.
+translate.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.google.com.
+www.bigearl.org.
+www.bridedressup.net.
+external.ak.fbcdn.net.
+155.0.14.212.in-addr.arpa.
+tpc.googlesyndication.com.
+176.155.145.201.in-addr.arpa.
+www.soho.com.co.
+blog.seattlecoffeegear.com.
+153.151.143.187.in-addr.arpa.
+noticias.lainformacion.com.
+www.facebook.com.
+166.25.15.187.in-addr.arpa.
+a.root-servers.net.
+www.copytrans.jp.
+www.michell.com.pe.
+descargararesgratis.disqus.com.
+redirector.c.youtube.com.
+photos-f.ak.fbcdn.net.
+i366.photobucket.com.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+api-read.facebook.com.
+widgets.amung.us.
+kjtafdhws.com.domain.local.
+listino.omniauto.it.
+time.nist.gov.
+docs.google.com.
+209.57.228.71.in-addr.arpa.
+m.addthisedge.com.
+img.mediaplex.com.
+login.live.com.
+afrozeprinting.com.
+youtube-ui.l.google.com.
+pohmtk.com.
+57.30.47.189.in-addr.arpa.
+145.87.17.85.in-addr.arpa.
+apps.facebook.com.
+www.google.com.
+sponsoredcdn.speedbit.com.
+a1.twimg.com.
+www.xn--cabaasmazamitla-1qb.com.
+181.45.24.125.in-addr.arpa.
+176.17.24.190.in-addr.arpa.
+developers.facebook.com.
+idealcalor.com.
+clients1.google.com.
+mail.lab.comcor.ru.
+a355.phobos.apple.com.
+mail2lucky.com.
+www.facebook.com.
+www.bmag.org.uk.
+mendozabieninforma.com.ar.
+www.webtogs.co.uk.
+api.twitter.com.
+a.root-servers.net.
+el.y8.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a771.da1.akamai.net.
+zynga2-a.akamaihd.net.
+dlpiper.com.
+canadianislamiccongress.com.
+webmail-ru.bul.net.
+175.81.81.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+gmaseven.blogspot.com.
+a.root-servers.net.
+52.67.250.189.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tijuana-kei.com.
+versn.ru.
+142.36.59.200.in-addr.arpa.
+partted.com.
+homey.ru.
+cdn.api.twitter.com.
+ns3.molehand.eu.
+foxnews.sl.advertising.com.
+www.reverbnation.com.
+i3.ytimg.com.
+2.1.168.192.in-addr.arpa.
+www.fotosrarasgratis.com.
+h-app01-06.hamachi.cc.
+enblogs.com.
+g.ceipmsn.com.
+suggestqueries.google.com.
+www.nuts.co.uk.
+db._dns-sd._udp.lan.
+www.msftncsi.com.
+api.facebook.com.
+rz5oq7:zr.72bo.
+liduvinacarrera.blogspot.com.
+cdn4.fmylife.com.
+a.root-servers.net.
+encrypted-tbn1.google.com.
+msnportal.112.2o7.net.
+a.root-servers.net.
+need2bfit.com.
+www.iegallery.com.
+a.root-servers.net.
+s2.youtube.com.
+117.183.127.187.in-addr.arpa.
+www.sqm.microsoft.com.
+googlehosted.l.googleusercontent.com.
+23.200.186.189.in-addr.arpa.
+kuban-service.ru.
+www.youtube.com.
+sn1msg2010640.sn1.gateway.edge.messenger.live.com.
+view.atdmt.com.
+c-0.19-210fa081.8020081.1518.19d4.3ea1.410.0.c4b819z5a5p2j1wbcnuecanzp5.avqs.mcafee.com.
+a.root-servers.net.
+mail.landbank.com.
+cuda.csystems.com.
+mail.kwreferred.com.
+www.google.com.
+www.macgeneration.com.
+www.youngcloseup.com.
+www.youtube.com.
+c0551612.cdn.cloudfiles.rackspacecloud.com.
+snj-us-bkwp-712-att.kodak.com.home.
+unijuris.fr.
+147.149.168.192.in-addr.arpa.
+_131_85_2.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+www.facebook.com.
+xodusgroup.com.
+download675.avast.com.lan.
+party-games.zaural.ru.
+26.1.237.78.in-addr.arpa.
+_957_43_2.
+www.winamp.com.
+217.35.0.10.in-addr.arpa.
+www.facebook.com.
+images03.olx-st.com.
+236.158.78.190.in-addr.arpa.
+www.claro.com.pe.
+photos-g.ak.fbcdn.net.
+theflatland.com.
+www.bocareydecopas.com.ar.
+www.mmaaxx.com.
+gswebhost.com.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+158.120.16.177.in-addr.arpa.
+s3.amazonaws.com.
+slmclaw.com.s6b1.psmtp.com.
+www.google.com.
+css.wlxrs.com.
+ns1.facebook.com.
+xwt.ru.
+a995.mm1.akamai.net.
+dinastia-stv.ru.
+www.gayteacher.net.
+a6.sphotos.ak.fbcdn.net.
+audio-sv5-t1-1.pandora.com.
+www.facebook.com.
+www.swtorguidehq.com.
+video01.ifeng.com.
+petsafe.net.inbound15.mxlogicmx.net.
+www.youtube.com.
+teredo.ipv6.microsoft.com.
+blog.gypsy05.com.
+_ldap._tcp.
+u20.eset.com.
+a.root-servers.net.
+sukellushaaja.fi.
+cdn-5.moviebox.com.
+196.103.232.189.in-addr.arpa.
+74.115.44.83.in-addr.arpa.
+sr.wikipedia.org.
+cs10.chatropolis.com.
+mx.games.yahoo.com.
+www.roperscientific.com.
+dwmailgate.delwestusa.com.
+gfx4.hotmail.com.
+www.itxchaos.co.uk.
+132.176.56.92.in-addr.arpa.
+es.safely.yahoo.com.
+safebrowsing.clients.google.com.
+b-0.19-22094008.61081.1518.19d4.3ea1.410.0.cfqf8cl1gw829ff7ctuvqcsszi.avqs.mcafee.com.
+236.174.85.200.in-addr.arpa.
+151.220.11.67.in-addr.arpa.
+res2.windows.microsoft.com.
+api.facebook.com.
+207.56.65.217.in-addr.arpa.
+a.root-servers.net.
+sp.cwfservice.net.
+a.root-servers.net.
+pattygopez-mileycyrusprettycool.buzznet.com.
+pixel.facebook.com.
+a-0.19-a309d000.2170092.1518.19d4.3ea1.210.0.mjcu9aaeb23cpducliwh1wip8j.avqs.mcafee.com.
+www.blinklist.com.
+www.laughenough.com.
+youtube-ui.l.google.com.
+fugigreenwood.com.
+ssl.google-analytics.com.
+images.amazon.com.
+a.root-servers.net.
+202.1.0.192.in-addr.arpa.
+www.desmotivaciones.es.
+mmrrg.com.s8b1.psmtp.com.
+proinfo.pandasoftware.com.
+ns.dipmap.com.
+stats.norton.com.
+a.root-servers.net.
+www.grupotelfor.com.
+static.ak.connect.facebook.com.
+fxfeeds.mozilla.com.
+remote.infopark.ru.
+fbcdn-profile-a.akamaihd.net.
+gbnet.com.
+www.theamazingspiderman.com.
+136.179.71.74.in-addr.arpa.
+a.root-servers.net.
+a-0.19-a3007008.10092.1518.19d4.3ea1.410.0.31jpecqc8hl6humr2z82g26p46.avqs.mcafee.com.
+apis.google.com.
+www.gameark.com.
+109.240.97.186.in-addr.arpa.
+tracking.usage.app.conduit-services.com.
+mail.samara.alice.ru.
+a3.twimg.com.
+photos-c.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+profile.ak.fbcdn.net.
+www3.geosc.psu.edu.
+playerservices.streamtheworld.com.
+www.fb.com.
+244.173.172.190.in-addr.arpa.
+534-async.olark.com.
+external.ak.fbcdn.net.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+bstrlo51u.71zv.
+babich.spb.ru.
+ingameads.gameloft.com.
+ein.gtkg.net.
+kotonoha.monkey-pirate.com.
+mail.marstu.net.
+moricoli.com.mx4.mxtoolbox.com.
+6.136.192.190.in-addr.arpa.
+163.123.114.186.in-addr.arpa.
+www.facebook.com.
+hitext.ru.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+213.9.122.190.in-addr.arpa.
+www.volviendoalabiblia.com.mx.
+d1.media.v4.skyrock.net.
+quality.ru.
+pixel.facebook.com.
+static.ak.fbcdn.net.
+maria-truecolours.blogspot.com.
+www.japonesasgratis.com.ar.
+_654_58_5.
+csc.beap.ad.yieldmanager.net.
+127.222.42.186.in-addr.arpa.
+lb._dns-sd._udp.lan.
+.
+www.gaymovieking.com.
+xrjwye.com.
+ns2.webland.ch.
+20.48.25.190.in-addr.arpa.
+developers.facebook.com.
+de.answers.yahoo.com.
+quitarverrugasylunares.net.
+ytogmowi9.64ke.
+0-jj-w.channel.facebook.com.
+e24.tns-cs.net.
+grincheux.irislink.com.
+a.root-servers.net.
+a.root-servers.net.
+3d3nynsfk.h79x8v5n.
+maps.gstatic.com.
+assets.gamersunite.com.
+completemortgageservice.com.
+109.79.167.189.in-addr.arpa.
+es.wikipedia.org.
+www.oxygenez-vous.com.
+row.bc.yahoo.com.
+102.16.158.189.in-addr.arpa.
+a.root-servers.net.
+www.elamalta.com.
+co.catawba.nc.us.
+amorvida.bligoo.com.
+locia.omega.mplik.ru.
+79.18.158.187.in-addr.arpa.
+fitnessatlantic.com.
+a5.sphotos.ak.fbcdn.net.
+gemmhomes.com.
+52.90.44.190.in-addr.arpa.
+dictionary.lunaescence.com.
+accounts.google.com.
+a8.sphotos.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+2acyxlnqn.73ih.
+246.122.128.189.in-addr.arpa.
+www.limited-uk.de.
+static.ak.fbcdn.net.
+343cyb7n5.87sv.
+profile.ak.fbcdn.net.
+wyikyf.com.
+safebrowsing-cache.google.com.
+secure.shared.live.com.edgekey.net.
+time.chttl.com.tw.
+photos-c.ak.fbcdn.net.
+time.chttl.com.tw.
+google.com.
+hi-in.facebook.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+trueslant.com.
+data.mobclix.com.
+teredo.ipv6.microsoft.com.
+xvideos-390.vo.llnwd.net.
+www.blogger.com.
+www.kaskus.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+auth.np.ac.playstation.net.
+decentral-0.vo.llnwd.net.
+mail.sura.ru.
+lvpei.org.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+kccinter.net.
+wirelessplanetusa.com.
+www.google.com.
+s4.histats.com.
+119.216.63.189.in-addr.arpa.
+cablevision.com.ar.
+www.laurelcatering.com.
+photos-e.ak.fbcdn.net.
+barracuda.acgmedia.com.
+www.mercerbears.com.
+171.48.52.186.in-addr.arpa.
+thepinoy.com.
+login.yahoo.com.
+support.ins.dell.com.
+1.bp.blogspot.com.
+mailin11mx.groovy.gr.
+profile.ak.fbcdn.net.
+www.kitco.com.
+chicaskm.com.
+engine.influads.com.
+external.ak.fbcdn.net.
+cgibin.erols.com.
+98.178.244.190.in-addr.arpa.
+kapel-la.ru.
+www.ftalk.com.
+clients1.google.com.
+curryandco.com.
+106.48.179.190.in-addr.arpa.
+iesealarcos.es.
+creative.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+dns.msftncsi.com.
+adserving.cpxinteractive.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+www.gastrox.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+68.146.52.201.in-addr.arpa.
+r._dns-sd._udp.lan.
+a5.sphotos.ak.fbcdn.net.
+mail.parishepiscopal.org.
+pcstudents.us.
+c.atdmt.com.
+mail.tp.kurgan.ru.
+wd-edge.sharethis.com.
+s3pr.shoptowin.net.
+ugc.ducati.kontain.com.
+dns.msftncsi.com.
+photos-e.ak.fbcdn.net.
+optimized-by.rubiconproject.com.
+www.ebay.es.
+thumbs1.ebaystatic.com.
+213.217.245.189.in-addr.arpa.
+www.samsungpresenter.com.
+www.bancomer.com.
+ingeterra.espacioblog.com.
+147.29.26.201.in-addr.arpa.
+133.16.168.192.in-addr.arpa.
+p01-calendarws.icloud.com.
+adserver.adtech.de.
+216.125.76.190.in-addr.arpa.
+elrellano.co.
+a1108.da1.akamai.net.
+www.bravotube.co.
+cdn.api.twitter.com.
+mve8kjmk9.94qi.
+accounts.google.com.
+toyota-tsusho.com.
+magaltc.com.inbound15.mxlogic.net.
+hotmail.com.
+metrics.el-mundo.net.
+waldan.com.
+144.187.132.189.in-addr.arpa.
+www.hasrawy.net.
+apps.facebook.com.
+www.mapp-oea.net.
+bluehillfarm.com.
+fr-fr.facebook.com.
+a.root-servers.net.
+sp.cwfservice.net.
+rehbaum.net.
+www.rdanielstudios.com.
+200.32.94.189.in-addr.arpa.
+sites.google.com.
+58.200.65.190.in-addr.arpa.
+voipa.sip.yahoo.com.
+tag.admeld.com.
+d2n8p8eh14pae1.cloudfront.net.
+db._dns-sd._udp.0.129.37.10.in-addr.arpa.
+252.92.80.98.in-addr.arpa.
+download.windowsupdate.com.
+77.44.112.114.in-addr.arpa.
+s-static.ak.facebook.com.
+8.131.23.217.in-addr.arpa.
+foothealth.about.com.
+123.71.52.186.in-addr.arpa.
+246.242.62.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+www.cityvox.co.uk.
+a.root-servers.net.
+preventionnetwork.info.
+links4media.blogspot.com.
+78.71.181.186.in-addr.arpa.
+www.mayadstudios.com.
+a.root-servers.net.
+mail.slam.com.
+crl.comodoca.com.
+search.conduit.com.
+museotextildeoaxaca.wordpress.com.
+www.iglesialatina.org.
+7.52.100.190.in-addr.arpa.
+feeds.bbci.co.uk.
+www.alz.org.
+a1.sphotos.ak.fbcdn.net.
+connect.facebook.net.
+es.landing.playnik.com.
+www.facebook.com.
+192.207.15.187.in-addr.arpa.
+mx1.educom.ru.
+www2.winavi.com.
+profile.ak.fbcdn.net.
+89.237.69.190.in-addr.arpa.
+18.232.69.186.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+ph.answers.yahoo.com.
+_177_16_3.
+www.telegraph.co.uk.
+www.yswhosting.com.
+www.metodologiamad.cl.
+i2.ytimg.com.
+time.chttl.com.tw.
+westerntraffic.com.
+dalisigloxx.wordpress.com.
+view.asiae.co.kr.
+google.com.
+co.nacogdoches.tx.us.s9b2.psmtp.com.
+www.amazon.com.
+hillevans.com.s7b2.psmtp.com.
+historiasextraordinarias.files.wordpress.com.
+a1.sphotos.ak.fbcdn.net.
+bsf.smowtion.com.
+24.media.tumblr.com.
+a7.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+time.chttl.com.tw.
+chsi.ru.
+111.32.171.201.in-addr.arpa.
+a.root-servers.net.
+updatekeepalive.mcafee.com.
+iu1l8ddxm.57kv.
+download797.avast.com.
+searchqutoolbar.imesh.wizard.applicationstat.com.
+a4.da1.akamai.net.
+xf_com_update_doctor.qq.com.
+ads2.msads.net.
+shwaish.com.
+www.facebook.com.
+9q2xe4p38.78hv.
+es-la.facebook.com.
+isearch.avg.com.
+i4.ytimg.com.
+141.134.233.190.in-addr.arpa.
+636f6c.7374623030.732d6d736e.636f6d.80h413650e6.webcfs00.com.
+a-0.19-309f081.8000033.1518.19d4.2f1c.10.0.bzi1cbn28dc16k8idwcb7lck5t.avqs.mcafee.com.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+sn18.mailshell.net.
+www.facebook.com.
+s42.undefined.home.
+ajax.googleapis.com.
+prog-net.com.
+pharmfab.com.
+80.171.246.85.in-addr.arpa.
+66.26.211.81.in-addr.arpa.
+id.google.com.mx.
+i3.ytimg.com.
+static.ak.fbcdn.net.
+www.sexomax.net.
+pixel.facebook.com.
+srx.main.ebayrtm.com.
+mangacan1.ucoz.com.
+dalek.softonic.com.
+lpadvisors.com.
+content.yieldmanager.edgesuite.net.
+api.facebook.com.
+ar-ar.facebook.com.
+img704.imageshack.us.
+a1.sphotos.ak.fbcdn.net.
+fr-fr.facebook.com.
+a.root-servers.net.
+123.36.93.200.in-addr.arpa.
+tv.hir24.hu.
+www.livesicilia.it.
+_357_99_0.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+12.176.15.186.in-addr.arpa.
+a.root-servers.net.
+191.164.138.190.in-addr.arpa.
+strappadometalblog.blogspot.com.
+7.169.185.187.in-addr.arpa.
+www.google.com.
+www.kids-pages.com.
+www.utj.edu.mx.
+seychellegabrielfan.com.
+a.root-servers.net.
+ad.yieldmanager.com.
+hosting.lockhosts.com.
+mvzmil.ru.
+al-nabaa.net.
+www.struat.com.
+www.mslitigationreview.com.
+wg6jw1g4r.p41z2x6m.
+ja.wikipedia.org.
+ocsp.entrust.net.
+a.root-servers.net.
+www.aa.com.
+www.sara-freder.com.
+v1.sftcdn.net.
+www.psp.wa.gov.
+2040.ecarlist.com.
+8.232.143.175.in-addr.arpa.
+facebookcheating.com.
+incanto.ru.
+livingair-74.ru.
+pagead2.googlesyndication.com.
+time.windows.com.
+www.google.com.
+244.107.226.190.in-addr.arpa.
+aaugonline.net.
+family-home.ru.
+www.youtube.com.
+vel-com.ru.
+go.microsoft.com.
+imagenes-estaticas.elmercadona.es.
+22.214.21.190.in-addr.arpa.
+deporteyautismo.blogspot.com.
+www.ed9101d8.com.
+www.unonoticias.com.mx.
+mail.gmail.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+loading3.widdit.com.
+199.68.0.187.in-addr.arpa.
+elcorillord.org.
+itunes.com.
+mail.globalinetbiz.net.
+ads.bluelithium.com.
+www.google.com.
+under-your-skin.com.
+7myjx2fjl.a36n3c9y.
+ar-ar.facebook.com.
+www.forosdelweb.com.
+polldaddy.com.
+doc.mbalib.com.
+i67.servimg.com.
+a.root-servers.net.
+mesadtvm.com.br.
+nflsoup.com.
+checkip.dyndns.org.
+photos-b.ak.fbcdn.net.
+www.frbsf.org.
+6ige7n4r7.w18s0b7x.
+de.tynt.com.
+boitaullresort.es.
+download.windowsupdate.com.
+95.146.220.66.in-addr.arpa.
+id.google.com.mx.
+hi-in.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+mx.groups.yahoo.com.
+www.providencenightlife.net.
+video.google.com.mx.
+15.26.254.190.in-addr.arpa.
+prod1.rest-notify.msg.yahoo.com.
+www.google.com.
+83.85.182.189.in-addr.arpa.
+s-static.ak.facebook.com.
+pwi-forum.fr.perfectworld.eu.
+yahoo.com.sg.
+hbflarch.com.
+odnoklassniki.com.
+forum.fiance.com.
+skateboard-trick-tips.com.
+_ldap._tcp.
+static.punishtube.com.
+img846.imageshack.us.
+x3w.zapto.org.
+wilsonco.com.
+www.yahoo.com.
+gdjf.com.
+filter.radersolutions.com.
+profile.ak.fbcdn.net.
+mailgate.cabair.com.
+hotrodgrills.com.
+www.crazy-tattoo-designs.com.
+specialtycakecreations.com.
+169.235.141.201.in-addr.arpa.
+clock.fmt.he.net.
+lh4.ggpht.com.
+www.apple.com.
+ratings-wrs.symantec.com.
+ycmt-cdn.s3.amazonaws.com.
+dc378.4shared.com.
+cdn.api.twitter.com.
+real.theoffside.com.
+qetytug.com.
+wpad.
+a.root-servers.net.
+sites.google.com.
+shop.safewalls.org.
+pics.ebaystatic.com.
+googleads.g.doubleclick.net.
+shoujo-s.livejournal.com.
+104.76.51.190.in-addr.arpa.
+31.190.63.69.in-addr.arpa.
+efrtz24jq.p51y3m4p.
+97.7.18.99.in-addr.arpa.
+realtyexecutivesjulian.com.
+content.ak.metrogames.com.
+a1052.g.akamai.net.
+cdn.api.twitter.com.
+onlineaccess.mycreditcard.cc.
+www.shemaletushy.com.
+trexrb.ru.
+106.108.102.189.in-addr.arpa.
+ads.adk2.com.
+bogotaku.mejorforo.net.
+i4.ytimg.com.
+b47nb2tdo.87dv.
+www.lesbilicious.co.uk.
+axiome.info.
+gmail.com.
+d18txuuu339yuz.cloudfront.net.
+www.google.com.
+152.49.50.174.in-addr.arpa.
+59.240.57.83.in-addr.arpa.
+mozilla.cdn.leaseweb.com.
+www.google.com.
+c-ak.static-rootmusic.com.
+time.nist.gov.
+beauty-women.ru.
+s-static.ak.fbcdn.net.
+102.87.142.79.in-addr.arpa.
+136.253.77.190.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+feeds.delicious.com.
+www.imdb.com.
+young-topmodels.info.
+binatel.ru.
+105.89.210.98.in-addr.arpa.
+se.magadan.su.
+static.ak.fbcdn.net.
+www.natuzzi.com.
+133.191.58.189.in-addr.arpa.
+creativecommons.org.
+outcampmail006.snc7.facebook.com.
+1f7yqor1v.j89b6t2o.
+video.mx.msn.com.
+www.keaneshaped.
+google.com.
+gtaonline.com.ar.
+accounts.google.com.
+static.ak.fbcdn.net.
+www.adobe.com.
+cn1.redswoosh.akadns.net.
+gamerandroide.blogspot.com.
+wolseley.at.
+41.197.46.201.in-addr.arpa.
+www.scrapbook.com.
+www.lancommand.co.uk.
+86.59.250.111.in-addr.arpa.
+214.162.73.190.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+a4.mzstatic.com.
+uccebszps.biz.
+159.183.58.99.in-addr.arpa.
+203.1.108.99.in-addr.arpa.
+30.205.201.108.in-addr.arpa.
+c.atdmt.com.
+160.68.90.186.in-addr.arpa.
+carpet-rug.com.
+www.hctc.com.
+nts-0nline.net.
+www.taxmann.com.
+www.copine-coquine.com.
+lagunasecagolf.com.
+ads.bluelithium.com.
+a3.sphotos.ak.fbcdn.net.
+tools.google.com.
+dr._dns-sd._udp.0.55.211.10.in-addr.arpa.
+mmoga.de.
+165.179.254.201.in-addr.arpa.
+jjszo4ss1.72wq.
+pagead2.googlesyndication.com.
+external.ak.fbcdn.net.
+154.4.26.190.in-addr.arpa.
+ad.yieldmanager.com.
+lh6.googleusercontent.com.
+www.update.microsoft.com.
+external.ak.fbcdn.net.
+243.251.209.112.in-addr.arpa.
+fileshare704.depositfiles.com.
+www.gstatic.com.
+i1fxw5q2d.83pc.
+i.ytimg.com.
+profil-furnitura.ru.
+hidheadlightconversion.com.
+a.root-servers.net.
+e461.b.akamaiedge.net.
+photos-g.ak.fbcdn.net.
+www.facebook.com.
+weichertacclaim.com.
+www.google.com.mx.
+ads.bluelithium.com.
+a.root-servers.net.
+soundcloud.com.
+realtyplacement.com.
+dns.msftncsi.com.
+mx4.future.net.uk.
+s.youtube.com.
+feeds.bbci.co.uk.
+234.77.153.187.in-addr.arpa.
+dns.msftncsi.com.
+mobilesources.net.
+_951_93_2.
+cdn.joomla.org.
+tracker.ilibr.org.
+iq7:vctbr.55ni.
+lasd.org.
+tour-foto.ru.
+3636.313735.313233.313032.80h42af7b66.webcfs00.com.
+www.escortvipbayan.com.
+a.root-servers.net.
+video327.myfreecams.com.
+video.xnxx.com.
+www.google.com.
+api.twitter.com.
+godleyfarms.com.
+liveupdate.symantecliveupdate.com.
+a.root-servers.net.
+195.122.209.77.in-addr.arpa.
+smtp2.halfen.com.
+javadl-esd.sun.com.
+chernobrovin.ru.
+sertel2k.vtrbandaancha.net.
+www.googleadservices.com.
+www.thethreadexchange.com.
+a.root-servers.net.
+twitter.com.
+www.123rf.com.
+hotmail.com.
+www.google-analytics.com.
+www.pallcare.asn.au.
+api.facebook.com.
+a.root-servers.net.
+billing.sharo4ka.ru.
+gkudqnwrt.12mv.
+www.facebook.com.
+www.bestlaidschemes.com.
+47.46.155.85.in-addr.arpa.
+d2105651.xoom.it.
+msc.wlxrs.com.
+es-la.facebook.com.
+fb-520.com.
+billing.sharo4ka.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+oluvwjgph.96zi.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+google.com.
+cdn.stumble-upon.com.
+ad.doubleclick.net.
+hi-in.facebook.com.
+musicjacker.com.
+fishinggonewild.com.
+alerts.conduit-services.com.
+photos-b.ak.fbcdn.net.
+yo.wikipedia.org.
+static.ak.fbcdn.net.
+188.8.32.201.in-addr.arpa.
+vp.sip.messenger.msn.com.
+facebook.com.
+40.111.105.190.in-addr.arpa.
+www.manhunt.net.
+www.freexxxdot.com.
+carwale.com.
+mail.laserlightengines.com.
+um16.eset.com.
+www.googleadservices.com.
+miscritscdn.brokenbulbstudios.com.
+ssl.gstatic.com.
+plus.google.com.
+denver.bbb.org.
+a7.sphotos.ak.fbcdn.net.
+www.fulltono.com.
+www.hqudc.org.
+photos-e.ak.fbcdn.net.
+google.com.
+es-es.facebook.com.
+mailserver2.techint.it.
+hqwhtk8k:.89ii.
+lwt.com.
+248.12.4.189.in-addr.arpa.
+www.takethewalk.net.
+www.whatsapp.com.
+spaces.live.com.
+b._dns-sd._udp.0.81.168.192.in-addr.arpa.
+142.41.241.201.in-addr.arpa.
+t7.tagstat.com.
+www.chilincasita.blogspot.com.
+ns2.dnspod.net.
+www.udec.com.mx.
+www.parkinggames365.com.
+cnfg.facemoods.com.
+www.speakersblog.info.
+0.gravatar.com.
+suggestqueries.google.com.
+mscca.mscgva.ch.
+237.151.178.186.in-addr.arpa.
+10.212.1.201.in-addr.arpa.
+.
+lwsa.mlb.com.
+www.facebook.com.
+sunvestusa.com.
+a.root-servers.net.
+www.amateurs-videos.net.
+micros.co.za.
+www.google.com.
+a1005.w42.akamai.net.
+i.t-mobile-favourites.net.
+www.tagged.com.
+getsu.zapto.org.
+sevelina.ru.
+www.appsmitten.com.
+a3.sphotos.ak.fbcdn.net.
+msn.foxsports.com.
+c5.zedo.com.
+177.164.77.190.in-addr.arpa.
+a.root-servers.net.
+fiorellabotteri.blogspot.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ns.smartec.ru.
+www.brucelipton.com.
+89.244.107.190.in-addr.arpa.
+r.openx.net.
+mail.n-u-c.ru.
+6.246.26.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+www.hojadeosaschool.org.
+94.70.41.189.in-addr.arpa.
+omniproductions.com.
+isatap.wag160n.
+apps.facebook.com.
+28.161.168.192.in-addr.arpa.
+226.19.23.187.in-addr.arpa.
+vitamind3info.blogspot.com.
+rotorrentmania.lx.ro.
+s-static.ak.fbcdn.net.
+vincotte.be.
+static.ak.facebook.com.
+is.mixmarket.biz.
+a947.phobos.apple.com.
+ssl.gstatic.com.
+static.ak.fbcdn.net.
+hotmail.com.
+www.acer-euro.com.
+pixer.meaningtool.com.
+photos-a.ak.fbcdn.net.
+dvdcovers.vidz.com.
+mcneal.com.s7b2.psmtp.com.
+b.static.ak.fbcdn.net.
+mail.hmconsultores.pt.
+moorcroftcs.co.uk.
+www.osvdailytake.com.
+motoxtreme.ru.
+reporter.es.msn.com.
+google.com.
+nationalstrategy.com.
+a.root-servers.net.
+ci.national-city.ca.us.inbound15.mxlogic.net.
+74.241.123.188.in-addr.arpa.
+www.advocateclassic.com.
+117.254.214.81.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+bfjoy.com.s5a1.psmtp.com.
+dr._dns-sd._udp.0.11.168.192.in-addr.arpa.
+smtp.dnsexit.com.
+a.root-servers.net.
+free-es-cf.softonic.com.
+20.122.66.190.in-addr.arpa.
+www.steam-sauna-benefits.com.
+www.brad.ac.uk.
+128.105.109.186.in-addr.arpa.
+cdn2.widdit.com.
+www.bywifi.com.
+blog.vampirethemasquerade.com.
+x9tfj3pby.60kv.
+js2.wlxrs.com.
+cs10398.vk.com.
+www.facebook.com.
+www.jenniferrizzo.com.
+www.slstoredisplays.com.
+cs10663.vk.com.
+.
+71.86.252.189.in-addr.arpa.
+www.medellinmiempresa.com.
+www.naturalmiscarriage.org.
+www.acmoc.org.
+b._dns-sd._udp.6.0.8.10.in-addr.arpa.
+_394_90_5.
+andiamo-tel.com.
+a1132.da1.akamai.net.
+150.246.198.190.in-addr.arpa.
+www.adserver.bz.
+lbjclinic.com.
+platform.ak.fbcdn.net.
+www.facebook.com.
+www.msftncsi.com.
+profile.ak.fbcdn.net.
+124.59.155.187.in-addr.arpa.
+a.root-servers.net.
+130.171.158.187.in-addr.arpa.
+ubs.ch.
+jayse.us.
+user.easycam.hk.
+172.153.42.186.in-addr.arpa.
+feedburner.google.com.
+dnl-01.geo.kaspersky.com.
+islamentrehermanas.forumactif.com.
+instagram.com.
+a6.sphotos.ak.fbcdn.net.
+www.facebook.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+www.alessibici.com.
+www.cuantarazon.com.
+98.184.190.58.in-addr.arpa.
+oakland.athletics.mlb.com.
+www.google.com.
+groups.live.com.
+share.lockerz.com.
+www.ghostrecon.es.
+profile.ak.fbcdn.net.
+o-o.preferred.ord08s03.v10.lscache8.c.youtube.com.
+margalates.wordpress.com.
+www.googleadservices.com.
+ffin.com.
+mx.septen.com.
+wilsontechnologies.net.inbound15.mxlogicmx.net.
+www.lasrecetasdetriana.com.
+plusone.google.com.
+mail04.hgc.ch.
+adbucks.brandreachsys.com.
+a5.sphotos.ak.fbcdn.net.
+150.155.13.201.in-addr.arpa.
+a.root-servers.net.
+zynga2-a.akamaihd.net.
+mail.gsdllc.com.
+academiavascadegastronomia.com.
+227.25.243.168.in-addr.arpa.
+a.root-servers.net.
+www.camzap.com.
+a6.sphotos.ak.fbcdn.net.
+87.17.41.177.in-addr.arpa.
+upload.xvideos.com.
+teredo.ipv6.microsoft.com.
+profile.ak.fbcdn.net.
+cmgp.ru.
+leica-geosystems.com.s201b2.psmtp.com.
+60.224.38.187.in-addr.arpa.
+smokeinmycloset.blogspot.com.
+www.emailapple.com.
+a2.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+galleries.nascar.com.
+static.ak.fbcdn.net.
+desdemimejana.blogspot.com.
+194.102.173.189.in-addr.arpa.
+:2o9depq3.l11o7j1x.
+etzion.org.il.
+mail.google.com.
+mail.hardingmarketing.com.
+photos-b.ak.fbcdn.net.
+174.192.172.71.in-addr.arpa.
+ksn1-12-part2.kaspersky-labs.com.
+egoadmins.com.
+o2mhaafyl.39hk.
+liceopaillaco.bligoo.cl.
+www3.discovirtual.com.ar.
+a.root-servers.net.
+179.35.166.81.in-addr.arpa.
+static.ak.fbcdn.net.
+cdn.lfstmedia.com.
+docs.google.com.
+mainc.rr.com.
+a8.sphotos.ak.fbcdn.net.
+msn.co.jp.
+9aks9fdzi.59ly.
+id.google.com.mx.
+ffpaorg.com.
+evsecure-ocsp.verisign.com.
+curtmfg.com.s9b1.psmtp.com.
+21.243.173.218.in-addr.arpa.
+plus.google.com.
+www.facebook.com.
+alertasios.mundodeportivo.com.
+chat.wibiya.com.
+67.216.102.189.in-addr.arpa.
+mail.sintondairyfoods.com.
+www.voo.com.
+129.3.19.186.in-addr.arpa.
+_561_54_4.
+74tf.ru.
+a7.sphotos.ak.fbcdn.net.
+g.ceipmsn.com.
+springwood.net.bak-mx.na0107.smtpbak.com.
+www.taringa.net.
+a998.mm1.akamai.net.
+elecomsoftware.com.
+sites.google.com.
+login.commbiz.commbank.com.au.
+truelightproductions.com.
+bestastrology.net.
+88.52.203.62.in-addr.arpa.
+pubads.g.doubleclick.net.
+profile.ak.fbcdn.net.
+247.75.80.68.in-addr.arpa.
+qns.com.
+kitchen-design-studio.com.
+def.net.
+www.schooltimegames.com.
+gfx3.hotmail.com.
+groups.google.com.mx.
+api.twitter.com.
+www.grupoindi.com.
+85.206.80.208.in-addr.arpa.
+o2.hit.gemius.pl.
+horoscope.charlesayoub.com.
+carmella-bing.crocostars.com.
+photos-c.ak.fbcdn.net.
+moneytreefsi.com.
+creative.ak.fbcdn.net.
+images.shaggybevo.com.
+teredo.ipv6.microsoft.com.
+228.242.193.173.in-addr.arpa.
+208.169.179.190.in-addr.arpa.
+dp.prisacom.com.
+13.19.80.201.in-addr.arpa.
+oldmotorclassic.blogspot.com.
+lz.club.cul.sohu.com.
+1.bp.blogspot.com.
+meneame.net.
+a6.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+obbit.net.
+evoke.com.
+114.168.138.187.in-addr.arpa.
+sp.cwfservice.net.
+www.militaryclothing.com.
+www.wind-energy-the-facts.org.
+smtp.cbi.com.
+equa-net.com.
+media.scanscout.com.
+apis.google.com.
+billing.sharo4ka.ru.
+164.55.27.190.in-addr.arpa.
+secure.baa.com.
+time.windows.com.
+www.mimejoorfrase.com.
+130.75.168.192.in-addr.arpa.
+apps.facebook.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+f.e.redbox.com.
+cincodemayo.bicentenario.gob.mx.
+healthprorecruiting.com.
+41.146.62.186.in-addr.arpa.
+235.216.226.189.in-addr.arpa.
+dsn6.d.skype.net.
+apis.google.com.
+www.tribulus.tv.
+sj-r.mycapture.com.
+207.163.248.189.in-addr.arpa.
+www.bbc.co.uk.
+developers.facebook.com.
+support.google.com.
+37.230.44.90.in-addr.arpa.
+180.94.167.78.in-addr.arpa.
+apps.facebook.com.
+www.nexiumresearch.com.
+32.63.168.192.in-addr.arpa.
+223.182.9.46.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+deltamobile.ru.
+app.appatyze.com.
+u.zhinei.com.
+139.224.47.190.in-addr.arpa.
+me.effectivemeasure.net.
+mntr.babcdn.com.
+64.118.31.190.in-addr.arpa.
+apps.facebook.com.
+zh-cn.facebook.com.
+photos-f.ak.fbcdn.net.
+guilbeauxlawfirm.net.
+elementscanner.com.
+www2.blogblog.com.
+learnerbrown.hubpages.com.
+ps4releasedate.net.
+weather.service.msn.com.
+30.10.62.186.in-addr.arpa.
+www.bing.com.
+www.jwwaterhouse.com.
+www.facebook.com.
+75.78.51.72.in-addr.arpa.
+agatha.folhasp.com.br.
+178.9.76.190.in-addr.arpa.
+234.176.89.201.in-addr.arpa.
+sitedown.concursolutions.com.
+_565_63_1.
+a.root-servers.net.
+google.com.
+g-rc.ru.
+www.google-analytics.com.
+www.youtube.com.
+www.frankthomastheoriginalone.com.
+a5.sphotos.ak.fbcdn.net.
+www.dodgeram.dk.
+www.zapaday.com.
+smtp3.iho.ru.
+kalvos.org.
+pca-llc.com.
+www.club24mainstreet.com.
+on-ramp.net.
+gb2k.deviantart.com.
+snixykitchen.wordpress.com.
+developers.facebook.com.
+mx.saxquest.com.
+a.root-servers.net.
+rover.ebay.com.
+i.ytimg.com.
+o.sa.aol.com.
+ad.yieldmanager.com.
+www.estadao.com.br.
+76.110.192.91.in-addr.arpa.
+web.goldenspikesaward.com.
+139.114.133.187.in-addr.arpa.
+update.batterycare.net.
+sepr.fr.
+peru.com.
+77.94.214.189.in-addr.arpa.
+10.182.77.151.in-addr.arpa.
+google-voice-and-video.softonic.com.
+osirus.casarta.com.
+coleman-bh.com.inbound15.mxlogic.net.
+autoboerse-emsland.de.
+ox.adjunky.com.
+mail2.gudanggaramtbk.com.
+baltimore.orioles.mlb.com.
+heartutilities.com.
+www.anzeigenannahme.mediapilot.de.dns.boreus.de.
+radioweb4.com.
+hugedl.com.
+a4.sphotos.ak.fbcdn.net.
+b._dns-sd._udp.lan.
+www.facebook.com.
+www.google-analytics.com.
+escltd.ru.
+www.lan.com.
+182.74.149.187.in-addr.arpa.
+www.facebook.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+dr._dns-sd._udp.0.245.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+165.118.177.124.in-addr.arpa.
+gnebu.es.
+bam.on.ca.
+kerki.de.
+196.173.33.65.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.sellingantiques.co.uk.
+ar-ar.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+s.ytimg.com.
+goped.com.s5a1.psmtp.com.
+www.google.com.
+canyonhill.org.
+hosting2.nifty.com.
+109.120.102.201.in-addr.arpa.
+androidsdk.ads.mp.mydas.mobi.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+erieco.com.mail7.psmtp.com.
+gfx2.hotmail.com.
+iringer.softonic.com.br.
+www.facebook.com.
+photos-b.ak.fbcdn.net.
+tags.w55c.net.
+tour.clubalexis.com.
+hulkshare.com.
+search.twitter.com.
+dns.msftncsi.com.
+image23.bannch.com.
+im11.gulfup.com.
+photos-a.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+www.searchqu.com.
+pogievendors.com.
+eprints.ulster.ac.uk.
+tig.com.
+r5ohfqj7o.99ws.
+mail.anandjon.com.
+a.root-servers.net.
+www.yahoo.com.
+teredo.ipv6.microsoft.com.
+allrecipes.com.
+api.twitter.com.
+www.myhdd.ro.
+www.amazon.com.
+gdata.youtube.com.
+britecomputers.com.s8b1.psmtp.com.
+googleads.g.doubleclick.net.
+3.84.0.173.in-addr.arpa.
+www.brothersoft.com.
+posta.indire.it.
+photos-h.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+_269_40_8.
+js.casalemedia.com.
+nomodels.com.ua.
+static.ak.fbcdn.net.
+blog.japantimes.co.jp.
+conflict-global-storm.softonic.com.
+www.huishoudbeurs.nl.
+a5.sphotos.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+china-media-ad.en.alibaba.com.
+www.androiddevices.com.au.
+mx1.okehosting.net.
+www.upwallpapers.net.
+transformers-the-game.softonic.com.
+swupmf.adobe.com.
+plus.google.com.
+developers.facebook.com.
+medifirst.ru.
+www.guias11811.es.
+external.ak.fbcdn.net.
+www.anierm.org.mx.
+apple.imap.mail.yahoo.com.
+galant-cosmetic.ru.
+ad.yieldads.com.
+a2.sphotos.ak.fbcdn.net.
+www.google.com.
+www.facebook.com.
+gocsg.net.
+cgs.cz.
+a4.sphotos.ak.fbcdn.net.
+d2094047.xoom.it.
+47.135.188.24.in-addr.arpa.
+distilleryimage7.instagram.com.
+185.43.108.99.in-addr.arpa.
+google.com.
+vex.wildtangent.com.
+crafts.shop.ebay.com.
+pixel.facebook.com.
+110.150.105.186.in-addr.arpa.
+ut7.xhamster.com.
+azalis.org.ru.
+laidesigngroup.com.inbound15.mxlogic.net.
+dvd-decrypter.programas-gratis.net.
+photos-f.ak.fbcdn.net.
+apps.facebook.com.
+noviosfelices.com.
+zjnizub9i.v03y1f7r.
+56.97.153.189.in-addr.arpa.
+69.13.127.71.in-addr.arpa.
+0af2d87b0af12c898897744f51c37b7f.co.cc.
+v3.nonxt7.c.youtube.com.
+www.epicgameads.com.
+rcm.amazon.com.
+teredo.ipv6.microsoft.com.
+244.31.244.98.in-addr.arpa.
+www.setyoufreenews.com.
+chat.facebook.com.
+bibliotecadeloselefantes.blogspot.com.
+250.115.63.200.in-addr.arpa.
+mail.design-logix.com.
+view.atdmt.com.
+32.135.249.186.in-addr.arpa.
+api.conduit.com.
+212.177.151.190.in-addr.arpa.
+throneofroses.blogspot.com.
+ati-catalyst-drivers-vista-7.softonic.com.
+www.bdtonline.com.
+3.44.78.201.in-addr.arpa.
+royalholidaypress.com.
+nwjdns40.innodata-isogen.com.
+mail.municode.com.
+s-static.ak.facebook.com.
+valleyimpressions.com.
+48.234.10.92.in-addr.arpa.
+ajax.googleapis.com.
+hellofest.com.
+jtsports.com.2.arsmtp.com.
+escookie.mystarworld.net.
+160.119.127.201.in-addr.arpa.
+cloudcell.com.
+www.grogono.com.
+d1r9j5rytlayy8.cloudfront.net.
+121.119.204.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.mybrowserbar.com.
+mindsize.deviantart.com.
+wpad.
+ponyrama.browsergamez.com.
+connect.facebook.net.
+connect.facebook.net.
+www.comofaz.org.
+belltechlogix.com.
+246.58.169.173.in-addr.arpa.
+174.237.13.190.in-addr.arpa.
+p04-btmmdns.icloud.com.
+a6.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+cult.cu.
+gates.shapeservices.net.
+a7.sphotos.ak.fbcdn.net.
+matcher-rbc.bidder7.mookie1.com.
+www.adobe.com.
+top.qiyi.com.
+apps.facebook.com.
+smtp.iwaynet.net.
+photos-g.ak.fbcdn.net.
+vtsfpvpz.net.
+photos-c.ak.fbcdn.net.
+113.65.156.201.in-addr.arpa.
+api.webrep.avast.com.
+182.134.230.201.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+correodeinocentescapitulo.blogspot.com.
+ad-g.doubleclick.net.
+247.66.171.201.in-addr.arpa.
+android.amberfog.com.
+11.91.227.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+pathwaytoascension.wordpress.com.
+accounts.google.com.
+www.rockford-industrial.com.
+www.peliculasfox.com.
+ad.yieldmanager.com.
+27.229.171.69.in-addr.arpa.
+appldnld.apple.com.
+iowatelecom.net.com.
+www.youtube.com.
+cache.www.universalhidefclub.com.
+144.218.177.190.in-addr.arpa.
+_402_42_5.
+192.176.179.190.in-addr.arpa.
+www.googleadservices.com.
+uksystem.co.kr.
+stats.wordpress.com.
+2.pool.ntp.org.
+anime-dusk.activoforo.com.
+photos-b.ak.fbcdn.net.
+checkip.dyndns.org.
+mail.google.com.
+36.94.57.62.in-addr.arpa.
+a1332.g.akamai.net.
+www.eby.org.ar.
+us.mg5.mail.yahoo.com.
+shasta-rrs.symantec.com.
+s0.2mdn.net.
+140.78.252.189.in-addr.arpa.
+136.43.166.190.in-addr.arpa.
+sp.cwfservice.net.
+update1.jdownloader.org.
+www9.effectivemeasure.net.
+kromprint.ru.
+22.32.153.201.in-addr.arpa.
+244.211.164.189.in-addr.arpa.
+t.usnews.com.
+cekuaces.blogspot.com.
+208.157.227.2.in-addr.arpa.
+img.animalsexmania.net.
+esc10.ednet10.net.
+apkiss.com.
+orcart.facebook.com.
+ninjago.lego.com.
+isp.volgaonline.ru.
+g.microsoft.com.
+145.200.37.190.in-addr.arpa.
+135.22.74.190.in-addr.arpa.
+index.rpg.net.
+a1490.g.akamai.net.
+coolwebbies.googlepages.com.
+romainbjames.com.
+mianimex.org.
+chevismo.disqus.com.
+ac.babsrv.com.
+www.antena3.com.
+mail.google.com.
+avisooportuno.mx.
+picapinocarpinteria.blogspot.com.
+photos-h.ak.fbcdn.net.
+twitter.com.
+en-maktoob.yahoo.com.
+sdn2.clearsdn.com.
+a.tribalfusion.com.
+www.ppaproperties.com.
+www.facebook.com.
+billing.sharo4ka.ru.
+accordcard.ru.
+static2.drtuber.com.
+a7.sphotos.ak.fbcdn.net.
+by2msg4020309.gateway.messenger.live.com.
+botones.blogalaxia.com.
+google.com.
+chester-nj.org.s5a2.psmtp.com.
+cis-i.ru.
+profiles.google.com.
+m.adnxs.com.
+ds.serving-sys.com.
+carwheels.ru.
+messenger.hotmail.com.
+static.ak.fbcdn.net.
+ghs.l.google.com.
+time.nist.gov.
+a.root-servers.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tc19.easythumbhost.com.
+cakeciamik.blogspot.com.
+teredo.ipv6.microsoft.com.
+pb.blabbers.com.
+129.233.171.187.in-addr.arpa.
+platform.ak.fbcdn.net.
+www.olympia-verlag.de.
+67.81.179.189.in-addr.arpa.
+malahache.blogspot.com.
+img299.imageshack.us.
+dns.msftncsi.com.
+a2.sphotos.ak.fbcdn.net.
+64.91.138.187.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+www.google-analytics.com.
+support.google.com.
+wssq9o13d.n92v4s1i.
+cdbn.com.
+67.146.215.84.in-addr.arpa.
+_ldap._tcp.
+ow.ly.
+5.249.52.186.in-addr.arpa.
+ws1.tapjoyads.com.
+clayesmore.com.
+geoiplookup.wikimedia.org.
+bellsouthpwp.net.
+dfdfh.com.
+www.google.com.
+mail.trans-k.ru.
+jailbreak-j13.blogspot.com.
+propagandacatolica.blogspot.com.
+forums.vwvortex.com.
+smtp.ebrandz.com.
+173.130.231.89.in-addr.arpa.
+maui.hawaii.edu.
+www.facebook.com.
+fxfeeds.mozilla.com.
+63.129.190.186.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+86.171.172.190.in-addr.arpa.
+twitter.com.
+66eoaijft.66ae.
+latam.msn.com.
+www.alan-g.me.uk.
+www.google.com.
+i2.ytimg.com.
+a.root-servers.net.
+108.245.23.50.in-addr.arpa.
+www.siri.com.
+www.t-shirttimes.com.
+www.cvs.saude.sp.gov.br.
+rapidshare.com.
+www.pecentral.org.
+smi66gn42.88uc.
+news.google.com.mx.
+fxfeeds.mozilla.com.
+api.twitter.com.
+d3ojfab0q2dwum.cloudfront.net.
+www.datafull.com.
+agendadelpescador.blogspot.com.
+tpopworld.blogspot.com.
+mail.segeplan.gob.gt.
+res3.windowsmedia.com.
+csi.gstatic.com.
+a.root-servers.net.
+111.182.224.189.in-addr.arpa.
+86lqs32zs.77ta.
+rachael.foodnetwork.mobi.
+ksn2-12.kaspersky-labs.com.
+api.twitter.com.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.telurica.com.
+36.179.170.201.in-addr.arpa.
+b.scorecardresearch.com.
+lifehealthpro.disqus.com.
+plusone.google.com.
+253.156.6.189.in-addr.arpa.
+www.google-analytics.com.
+teredo.ipv6.microsoft.com.
+static.ak.fbcdn.net.
+ad-g.doubleclick.net.
+lgencove.k12.ny.us.
+www.mercadolibre.com.co.
+0-188.channel.facebook.com.
+secure.shared.live.com.
+s-static.ak.facebook.com.
+signup.netflix.com.
+d-0.19-a30f80b1.2d1031.1518.19d3.3ea1.210.0.iud63l4d8rput6efjed6dcljpj.avqs.mcafee.com.
+pagead2.googlesyndication.com.
+titanium30-en.url.trendmicro.com.
+_360_57_4.
+ridiculojustin.info.
+photos-b.ak.fbcdn.net.
+acommodity.com.
+www.facebook.com.
+203.64.166.190.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+yoow.com.
+futurespros.websol.barchart.com.
+dessy.com.
+a.root-servers.net.
+posvetim.ru.
+18.67.222.31.in-addr.arpa.
+rad.msn.com.
+www.bitcount.com.
+155.12.101.187.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+magazine.jungle.co.kr.
+131.38.67.201.in-addr.arpa.
+time.chttl.com.tw.
+profile.ak.fbcdn.net.
+muff-web.com.
+d1j68ux4ukg4g1.cloudfront.net.
+181.125.101.86.in-addr.arpa.
+hdubtpvottklleq.mn.
+79.191.150.189.in-addr.arpa.
+www.spainselecta.com.
+gillfordlm.com.
+teredo.ipv6.microsoft.com.
+cprpr1.wordpress.com.
+_747_06_9.
+240.131.48.186.in-addr.arpa.
+gfx6.hotmail.com.
+sp.cwfservice.net.
+155.181.7.189.in-addr.arpa.
+199.230.176.213.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+164.176.171.189.in-addr.arpa.
+22.138.22.186.in-addr.arpa.
+www.msnbc.msn.com.
+72.161.88.186.in-addr.arpa.
+geo.messenger.services.live.com.
+donbenitovillanueva.es.
+162.28.140.200.in-addr.arpa.
+199.206.17.50.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+m1.nsimg.net.
+teredo.ipv6.microsoft.com.
+themes2.gptop.com.
+168.236.152.69.in-addr.arpa.
+30.178.137.187.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+www.estadiosports.com.
+www.google.com.
+www.amazon.com.
+205.200.79.190.in-addr.arpa.
+uth.tmc.edu.
+perfectgirls.cdn-z4.globecorp.net.
+sucw:qb8m.d92e4c6m.
+searchjs.s3.amazonaws.com.
+safebrowsing-cache.google.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+uchicago.ru.
+nederman.com.
+rest-img.msg.yahoo.com.
+i5.7kimg.cn.
+crazybrush.ru.
+safebrowsing-cache.google.com.
+www.boxingnewsonline.net.
+www.failimages.com.
+p06-caldav.icloud.com.
+www.kayfabenews.com.
+a2.sphotos.ak.fbcdn.net.
+img3.hotteengayboys.com.
+billing.sharo4ka.ru.
+a.root-servers.net.
+_707_31_4.
+processpipe.com.
+static.ak.fbcdn.net.
+mccradio.com.s8b2.psmtp.com.
+account.netflix.com.
+profile.ak.fbcdn.net.
+ad.doubleclick.net.
+api.facebook.com.
+cv28.net.
+119.93.27.216.bl.spamcop.net.
+alchimiaweb.com.
+www.bing.com.
+omicrontech.net.mail6.psmtp.com.
+tpibaltimore.com.
+clipstyle.de.
+149.138.232.190.in-addr.arpa.
+20.151.206.90.in-addr.arpa.
+free-smith-video-player.softonic.com.
+zynga1-a.akamaihd.net.
+tobolsk.info.
+upgrade.bitdefender.com.
+88.79.55.65.in-addr.arpa.
+shop.magstore.com.au.
+2.bp.blogspot.com.
+242.114.222.137.in-addr.arpa.
+251.76.61.186.in-addr.arpa.
+platform.twitter.com.
+teredo.ipv6.microsoft.com.
+mail2.colorresourcesintl.com.
+32.190.63.69.in-addr.arpa.
+46.198.139.187.in-addr.arpa.
+8.15.125.186.in-addr.arpa.
+www.google.com.mx.
+translate.google.com.
+133.113.50.24.in-addr.arpa.
+a5.mzstatic.com.
+189.53.58.186.in-addr.arpa.
+www.cdn.viber.com.
+www.prabalgurung.com.
+148.44.139.187.in-addr.arpa.
+pagead2.googlesyndication.com.
+prludmila.ru.
+a.root-servers.net.
+158.55.10.95.in-addr.arpa.
+www.cambio.bo.
+0-257.channel.facebook.com.
+www.grabarz.net.
+104.98.160.189.in-addr.arpa.
+secon.nl.
+www.uderzo.it.
+17.208.154.83.in-addr.arpa.
+www.cpxadspace.com.
+a5.sphotos.ak.fbcdn.net.
+218.200.203.68.in-addr.arpa.
+d1.openx.org.
+mail.rosttreid.ru.
+s.youtube.com.
+workingwithrails.com.
+ludgate.nxtbook.com.
+at-lan.ru.
+images.google.com.
+35.151.22.71.in-addr.arpa.
+www.hammondindiana.com.
+www.gstatic.com.
+www.in.be.
+www.descargakaraokegratis.com.
+hotellid.reisiguru.ee.
+mecssgprnqbmginn.org.
+84.1.168.192.in-addr.arpa.
+gfx4.hotmail.com.
+54.249.137.189.in-addr.arpa.
+static.ak.fbcdn.net.
+hi-in.facebook.com.
+22.27.159.187.in-addr.arpa.
+a-0.19-a3092081.200b3.1518.19d4.3ea1.210.0.frdt39tm35rfzava51dg6fkzg5.avqs.mcafee.com.
+www.google.com.mx.
+facebookanime.com.
+i.ytimg.com.
+www.youtube.com.
+66c9i6pj32d33-c.c.yom.mail.yahoo.com.
+a.root-servers.net.
+www.google.com.
+report.freemake.com.
+www.google-analytics.com.
+3cw7l58k5.e05w6e8p.
+www.cjmillisock.com.
+www.gloria-pat.com.
+www.averias.eu.
+og.tvteam.info.
+a.root-servers.net.
+smtp.yellowbananas.com.
+millavon.fsnet.co.uk.
+tomsfoods.com.
+profile.ak.fbcdn.net.
+www.newmusicreviews.net.
+_875_57_7.
+diper.com.
+feeds.feedburner.com.
+a.root-servers.net.
+metallp.ru.
+adsfront.iminent.com.
+sp.ask.com.
+227.3.108.190.in-addr.arpa.
+prohibidoleer.com.
+www.reignonline.net.
+gfx4.hotmail.com.
+tandt-materials.com.
+181.0.0.10.in-addr.arpa.
+ar.wikipedia.org.
+cmgmpyu.biz.
+iphone.elnorte.com.
+.
+ocsp.digicert.com.
+ssl.google-analytics.com.
+i.w.inmobi.com.
+mail.rkconst.com.
+.
+www.babyshowersinvitations.com.au.
+static.ak.connect.facebook.com.
+www.osh.net.
+www.autemo.com.
+www.neverthelessnation.com.
+a.root-servers.net.
+www.google.com.
+ldkjflds.com.
+mail.asmor.ru.
+1601.live.streamtheworld.com.
+www.sonnerie.net.
+78.50.250.190.in-addr.arpa.
+tc.v13.cache7.c.youtube.com.
+7.30.72.46.in-addr.arpa.
+vulgarization.com.
+a.root-servers.net.
+2.4.2.198.in-addr.arpa.
+fujihunt.com.sg.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+208.153.141.189.in-addr.arpa.
+100.153.14.201.in-addr.arpa.
+www.swannysmodels.com.
+h.live.com.
+rad.msn.com.
+adimpact.com.au.
+www.gearreview.com.
+nauta360.expansion.com.
+108.240.162.78.in-addr.arpa.
+api.facebook.com.
+jabber.intellicontact.com.
+rospres.com.
+236.109.138.175.in-addr.arpa.
+106.8.218.186.in-addr.arpa.
+252.38.49.96.in-addr.arpa.
+91.255.132.189.in-addr.arpa.
+static01.videostream4u.com.
+e5237.g.akamaiedge.net.
+202.1.168.192.in-addr.arpa.
+primeconstructions.gr.
+btownmasti.com.
+40.48.140.187.in-addr.arpa.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+zonabarranquilla.com.
+www.sedo.com.
+co101ds.mail.services.live.com.
+www.elmendorf.af.mil.
+www.charlamania.com.
+darkorbit.browsergames.de.
+inbound.washworldinc.com.netsolmail.net.
+prod2.rest-notify.msg.yahoo.com.
+www.facebook.com.
+mxhost1.fni-stl.com.
+images.builderhouseplans.com.
+a.root-servers.net.
+27.101.194.187.in-addr.arpa.
+www.rassegna.it.
+analytic.gatewayinterface.com.
+photos-a.ak.fbcdn.net.
+124.163.72.190.in-addr.arpa.
+mymail.bright.net.
+176.208.6.189.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+autos.starmedia.com.
+clan-world-wide.foroa.org.
+plusone.google.com.
+time.stdtime.gov.tw.
+i.ytimg.com.
+download.windowsupdate.com.
+www.modashop.it.
+80.47.11.187.in-addr.arpa.
+fxfeeds.mozilla.com.
+ksn3-11.part1.kaspersky-labs.com.
+www.sting.co.jp.
+jsu.dt07.net.
+windowssecrets.com.
+www.grabmp3.org.
+profile.ak.fbcdn.net.
+img41.imageshack.us.
+photos-f.ak.fbcdn.net.
+es.wikipedia.org.
+0-jj-w.channel.facebook.com.
+googleads.g.doubleclick.net.
+get.adobe.com.
+nesma.net.sa.
+www.autos.com.
+pubads.g.doubleclick.net.
+p0b.ru.
+x8a.xanga.com.
+www.filmyfair.com.
+mail.penair.org.
+124.190.245.87.in-addr.arpa.
+s7.addthis.com.
+goo.gl.
+a4.sphotos.ak.fbcdn.net.
+inca-gmbh.de.
+l.longtailvideo.com.
+images.hi5.com.
+44.221.143.187.in-addr.arpa.
+pagead2.googlesyndication.com.
+posta74a.mailbeta.libero.it.
+20.75.242.189.in-addr.arpa.
+inbound.citizenscommunitybank.com.netsolmail.net.
+a7.sphotos.ak.fbcdn.net.
+matcinv1.matcin.net.
+www.mondomacabrodvd.com.
+94.211.141.201.in-addr.arpa.
+62.68.206.190.in-addr.arpa.
+orangehills.net.
+deep.crocmovies.com.
+blog.qmerdesign.net.
+google.com.
+139.206.23.189.in-addr.arpa.
+millionaire-city-money-rewardss.blogspot.com.
+webdesignburn.disqus.com.
+44.32.118.190.in-addr.arpa.
+a.root-servers.net.
+filter.eclickz.com.
+service.gc.apple.com.akadns.net.
+toldiacosiendo.blogspot.com.
+d1marr3m5x4iac.cloudfront.net.
+razyr.cz.
+t2.gstatic.com.
+maeslunau.com.
+dnl-18.geo.kaspersky.com.
+inbound.ksenterprisesonline.com.netsolmail.net.
+anime.about.com.
+www.ebay.com.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+www.youtube.com.
+5.133.86.187.in-addr.arpa.
+i4.ytimg.com.
+0.11-2309e081.c020083.1518.1982.3ea1.210.0.rsh5s2r6smr3phe6pk85h9qpeb.avqs.mcafee.com.
+photos-e.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+radionicaaplicada.blogspot.com.
+a.root-servers.net.
+www.studioverissimo.net.
+ksn1-11-part2.kaspersky-labs.com.
+www.facebook.com.
+photos-d.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+www.forodecine.com.
+static.ak.fbcdn.net.
+j.imagehost.org.
+tracker.torrentbay.to.
+fb.link.nokia.com.
+ksrryc:r7.12ks.
+rp.gwallet.com.
+pagead2.googlesyndication.com.
+204.207.95.201.in-addr.arpa.
+tarus.com.
+www.srisurf.com.
+_ldap._tcp.
+api.mixpanel.com.
+power-rangers.chulojuegos.com.
+pagead2.googlesyndication.com.
+www.facebook.com.
+166.27.14.187.in-addr.arpa.
+explotar-mistico-en-la-india.juegosipo.com.
+wffw.info.
+homedecorbytpt.com.
+letras.terra.com.
+65.168.164.187.in-addr.arpa.
+seriesid.com.
+aerotrim.co.uk.
+a1.sphotos.ak.fbcdn.net.
+api.skype.com.
+external.ak.fbcdn.net.
+decoracion.de.
+clients1.google.com.
+206.183.90.186.in-addr.arpa.
+s7.addthis.com.
+gruqtwp.com.
+70.53.173.112.in-addr.arpa.
+www.kalpiko.com.
+accounts.google.com.
+mta7.am0.yahoodns.net.
+www.littleabout.com.
+www.youtube.com.
+halmstad.net.
+www.adobe.com.
+245.105.42.177.in-addr.arpa.
+www.business-in-asia.com.
+a.root-servers.net.
+s2abrd19b.n59g1o6d.
+151.134.67.201.in-addr.arpa.
+innerlink.net.mx1.rcimx.com.
+a.l.yimg.com.
+www.myspace.com.
+106.249.205.109.in-addr.arpa.
+apen-audio-cd-burner.softbull.com.
+api-read.facebook.com.
+api.facebook.com.
+184.80.50.212.in-addr.arpa.
+123.0.0.10.in-addr.arpa.
+www.umoloda.kiev.ua.
+119.37.212.201.in-addr.arpa.
+hgfhj.com.
+71.6.106.186.in-addr.arpa.
+i3.ytimg.com.
+9.193.168.192.in-addr.arpa.
+243.183.157.93.in-addr.arpa.
+www.esesli.com.
+aujlntqh2.k06f6t0t.
+_227_14_3.
+127.0.0.1.
+widget.gigatools.com.
+a.root-servers.net.
+71.142.106.58.in-addr.arpa.
+a.root-servers.net.
+131.160.66.187.in-addr.arpa.
+static.ak.fbcdn.net.
+57.194.102.200.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+goo.gl.
+ssl.gstatic.com.
+d5nxst8fruw4z.cloudfront.net.
+cervantes.uah.es.
+specsavers.com.s200b2.psmtp.com.
+billing.sharo4ka.ru.
+mail.cablek.com.
+www.amazon.fr.
+www.vh1la.com.
+time.windows.com.
+s.ytimg.com.
+img3.etsystatic.com.
+s2.youtube.com.
+230.84.177.195.in-addr.arpa.
+geminipartners.com.
+photos-c.ak.fbcdn.net.
+www.tremendo.com.
+i4.ytimg.com.
+ntp.glb.nist.gov.
+199.48.40.201.in-addr.arpa.
+20.197.59.90.in-addr.arpa.
+metacafe.buscatube.org.
+www.google.com.
+m.addthisedge.com.
+www.ofertasdeviajesbaratos.com.
+zone28.hotwords.com.br.
+webcache.googleusercontent.com.
+sloac.stanford.edu.
+www.familiasodalite.org.
+mx1.cardiacspecialists.com.
+www.myvoicenation.com.
+checkip.dyndns.org.
+176.131.5.174.in-addr.arpa.
+49.149.220.66.in-addr.arpa.
+seher.es.
+photos-b.ak.fbcdn.net.
+collegiumpharmaceuticals.com.
+go.microsoft.com.
+www.adxpansion.com.
+smtp1.polyglass-com.fabbricadigitale.it.
+mx2.e107.ru.
+190.143.73.121.in-addr.arpa.
+profile.ak.fbcdn.net.
+mauriciogochez.wordpress.com.
+www.google.com.
+glassstreaminc.com.
+144.107.49.190.in-addr.arpa.
+static.ak.fbcdn.net.
+clients1.google.com.
+ask.com.
+gravatar.com.
+a.root-servers.net.
+i.xiaomi.net.
+ylmemphis.com.
+svky722aq.g47y2u3b.
+www.enceinte.com.
+clk.secureintl.com.
+rcp.na.blackberry.com.
+pixel.quantserve.com.
+titanium30-en.url.trendmicro.com.
+d2058748.instant.xoom.it.
+www.facebook.com.
+mail.st10.ru.
+creative.ak.fbcdn.net.
+pixel.facebook.com.
+ssl.gstatic.com.
+www.bittorrent.com.
+1.presence.emsc-csem.org.
+lietest.ru.
+a1209.phobos.apple.com.
+a995.mm1.akamai.net.
+ukrbiznes.com.
+dns.msftncsi.com.
+js2.wlxrs.com.
+relay2.interexc.com.
+s-static.ak.facebook.com.
+feeds2.feedburner.com.
+www.rapid.duareka.net.
+154.71.100.190.in-addr.arpa.
+182.137.137.201.in-addr.arpa.
+www.tequilaelgranjurado.com.
+tc21.easythumbhost.com.
+cismdesign.com.
+static.ak.facebook.com.
+saltillo.olx.com.mx.
+romancethelove.blogspot.com.
+safebrowsing.clients.google.com.
+transfire.transwitch.com.
+tunnel.cfw.trustedsource.org.
+books.google.com.
+photos-a.ak.fbcdn.net.
+mx.deportes.yahoo.com.
+219.160.206.112.in-addr.arpa.
+jpscu.com.
+softwaregate.net.
+126.197.17.177.in-addr.arpa.
+seatgeek.com.
+byfiles.storage.msn.com.
+bloggingwomen.blogspot.com.
+a3.twimg.com.
+106.9.211.217.in-addr.arpa.
+86yweeqdz.87th.
+a.root-servers.net.
+www.facebook.com.
+users.ucom.net.
+interspar.at.
+login.yahoo.com.
+vmx.alumni.iwu.edu.redcondor.net.
+saintedwards.net.
+dns.msftncsi.com.
+www.facebook.com.
+apps.facebook.com.
+238.169.119.112.in-addr.arpa.
+rnt.over-blog.com.
+ecoart-group.ru.
+db2.stb.s-msn.com.
+jerimmio.com.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+zh-cn.facebook.com.
+schools.naperville203.org.
+www.vungtrom.com.
+a1.sphotos.ak.fbcdn.net.
+translate.google.com.
+bs.serving-sys.com.
+132.225.60.85.in-addr.arpa.
+o-o.preferred.dfw06s10.v24.lscache5.c.youtube.com.
+mx1.mail.eu.yahoo.com.
+155.90.35.189.in-addr.arpa.
+www.lge.com.
+www.google.com.
+xvideos.net.
+97.48.173.186.in-addr.arpa.
+clients2.google.com.
+hdlpg.com.
+b-0.19-21069008.60081.1518.19d4.2f4a.410.0.p4c4upl48i7g9jqs1u4ppgcikj.avqs.mcafee.com.
+csi.gstatic.com.
+baixartemplatesnovos.webs.com.
+c.msn.com.tw.
+googlemapsdirectory.com.
+volgograd.gs.ru.
+a3.sphotos.ak.fbcdn.net.
+.
+122.175.89.85.in-addr.arpa.
+latasybotellasdejuancruz.blogspot.com.
+37.233.114.201.in-addr.arpa.
+svcs.cnn.com.
+songsfrompaul.tumblr.com.
+mail.condotteamerica.com.
+zoomointernet.net.
+ns1.purple-hosting.com.
+ec.atdmt.com.
+ville.mons.be.
+js.revsci.net.
+allegacyfcu.org.s5a2.psmtp.com.
+www.20minutos.es.
+gfas.com.
+rjtcreative.com.
+profile.ak.fbcdn.net.
+www.bna.com.ar.
+koa4x23zh.n34d6h5g.
+121.3.234.190.in-addr.arpa.
+4048971.frasesinolvidables1.com.ar.
+wadmag.com.
+resources.search.conduit.com.
+www.chinaontrade.com.
+a7.sphotos.ak.fbcdn.net.
+chat.facebook.com.
+www.zapreader.com.
+.
+mx2.deitron.de.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+safebrowsing-cache.google.com.
+minicatalog.bandoo.com.
+www.gotabletennis.com.
+8.64.43.186.in-addr.arpa.
+store.yahoo.com.
+hugdablock.com.
+api.twitter.com.
+ui.skype.com.
+a2.sphotos.ak.fbcdn.net.
+38.242.49.116.in-addr.arpa.
+tpebb.hanjin.com.
+db._dns-sd._udp.0.177.168.192.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+a3.sphotos.ak.fbcdn.net.
+g7qrj152p.07dq.
+microjuris.com.
+www.animalamigo.com.
+photos-h.ak.fbcdn.net.
+l.yimg.com.
+cdn.lfstmedia.com.
+beastpdx.com.
+tsm04.eset.com.
+a3.twimg.com.
+simonsulca.blogspot.com.
+static.ak.fbcdn.net.
+6sbacyrhg.z15j4m9h.
+apps.facebook.com.
+156.155.214.189.in-addr.arpa.
+www.lipsod.com.
+imagenes.telematica.net.
+broekhuisjuweliers.nl.
+shared.live.com.
+www.youtube.com.
+angelaliguori.com.
+google.com.
+luminopress.com.
+a.root-servers.net.
+ajax.googleapis.com.
+teredo.ipv6.microsoft.com.
+126.64.219.108.in-addr.arpa.
+lh4.ggpht.com.
+www.semana.com.
+215.117.99.177.in-addr.arpa.
+cdnma.com.
+_118_30_9.
+odsgirl.com.
+www.californiasar.org.
+orthopa.com.
+platform.twitter.com.
+91.193.12.189.in-addr.arpa.
+www.billingsupport.com.
+accountservices.msn.com.
+stun.client.akadns.net.
+dns.msftncsi.com.
+d2092087.xoom.it.
+music.wikia.com.
+46.72.4.186.in-addr.arpa.
+pubads.g.doubleclick.net.
+ejabat.google.com.
+www.cnna.gob.ec.
+www.facebook.com.
+l5.zedo.com.
+s7.addthis.com.
+capitalhgroup.com.s200a1.psmtp.com.
+olypen.com.s6b1.psmtp.com.
+cs5096.vk.com.
+greekave.com.
+224.49.0.172.in-addr.arpa.
+www.enigmasymisterios.net.
+b.scorecardresearch.com.
+tytut.com.
+17.171.19.178.in-addr.arpa.
+www.cari.net.
+www.mentesdeacido.net.
+7p18hlsar.x73g2g4i.
+a.root-servers.net.
+foss.com.s6b2.psmtp.com.
+www.google.com.
+178.12.186.190.in-addr.arpa.
+lib.enmuros.cc.nm.us.
+cs5984.vk.com.
+ads.contentabc.com.
+102.126.19.190.in-addr.arpa.
+ghmslaw.com.
+i1.ytimg.com.
+dx.doi.org.
+www.google.com.
+itunes.apple.com.
+avico.ru.
+tacuru.ourproject.org.
+228.115.103.177.in-addr.arpa.
+col.stc.s-msn.com.
+140.196.165.46.in-addr.arpa.
+b.scorecardresearch.com.
+45-courier.push.apple.com.
+91.131.122.190.in-addr.arpa.
+www.hell-yes-clothing.com.
+csi.gstatic.com.
+76188.hittail.com.
+sync.mathtag.com.
+kaydet.com.
+dps.msg.yahoo.com.
+www.alexnolan.net.
+c0014159.ssl.cf1.rackcdn.com.
+mail.craigandlori.com.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.facebook.com.
+1804289383.localhost.
+wrzuta.pl.
+teredo.ipv6.microsoft.com.
+www.youtube.com.
+11.176.58.187.in-addr.arpa.
+go.microsoft.com.
+kamsanes.ru.
+mail.live.com.
+97.205.177.190.in-addr.arpa.
+a1334.phobos.apple.com.
+241.115.138.190.in-addr.arpa.
+api.twitter.com.
+ontika.net.
+yonoestuvealli.blogspot.com.
+it.html.net.
+www.facebook.com.
+mail.acegaming.ru.
+profile.ak.fbcdn.net.
+img1.blogblog.com.
+a2.sphotos.ak.fbcdn.net.
+83.100.245.190.in-addr.arpa.
+a.root-servers.net.
+pop.gmail.com.
+profile.ak.fbcdn.net.
+om.co.
+pixel.quantserve.com.
+alton.k12.nh.us.s5a2.psmtp.com.
+s.ytimg.com.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.tecnomaq.com.mx.
+www.bingomingoreklam.com.
+odcons.com.
+_584_15_0.
+a.ads2.msads.net.
+18.50.86.85.in-addr.arpa.
+mail.epasa.com.
+www.leipzig-sachsen.de.
+abcgr.ru.
+t0.gstatic.com.
+www.facebook.com.
+stage.traffiliate.com.
+um12.eset.com.
+www.youtube.com.
+fbcdn-sphotos-a.akamaihd.net.
+voipc.sip.yahoo.com.
+mail.realestate-redding.com.
+166.22.244.189.in-addr.arpa.
+pixel.quantserve.com.
+215.150.250.190.in-addr.arpa.
+smtp2.eprod.com.
+g.microsoft.com.
+a.root-servers.net.
+www.canalava.org.mx.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mail.wescottlaw.com.
+linksfolders.disqus.com.
+16.140.37.177.in-addr.arpa.
+nordkapp.ru.
+23.146.182.189.in-addr.arpa.
+mscrl.microsoft.com.
+159.209.13.201.in-addr.arpa.
+22.155.210.201.in-addr.arpa.
+h.atdmt.com.
+81.222.195.187.in-addr.arpa.
+kreslatimo.ru.
+mail.live.com.
+api.webrep.avast.com.
+4.99.24.189.in-addr.arpa.
+i1.ytimg.com.
+35.180.71.201.in-addr.arpa.
+edctr.scdsb.on.ca.
+166.190.174.189.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.livejasmin.com.
+s.youtube.com.
+pixel.quantserve.com.
+2leep.com.
+mail.liasa.com.
+www.tecowestinghouse.com.mx.
+drmorley.net.s7b1.psmtp.com.
+www.tusdiscosgratis.com.
+apis.google.com.
+a2.sphotos.ak.fbcdn.net.
+ad-emea.doubleclick.net.
+115.16.147.186.in-addr.arpa.
+secure.shared.live.com.
+a2.sphotos.ak.fbcdn.net.
+m.google.com.
+apps.facebook.com.
+www.clipartlab.com.
+p1t.ru.
+184.204.10.68.in-addr.arpa.
+frivcar.blogspot.com.
+161.177.204.94.in-addr.arpa.
+mail.bigguy.com.
+mx.youtube.com.
+teredo.ipv6.microsoft.com.
+56.135.104.189.in-addr.arpa.
+1m62:9zzv.05lv.
+86.137.88.186.in-addr.arpa.
+sprosidoctora.ru.
+105.50.8.200.in-addr.arpa.
+www.appleaks.com.
+wpad.
+burnhamonline.com.s7b2.psmtp.com.
+a6.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+uig1saply.z78a3x8p.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+um13.eset.com.
+10.rarbg.com.
+p3old8fsi.z28s2c9q.
+static.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+woofbyte.com.
+www.addthis.com.
+sn1msg3030109.gateway.messenger.live.com.
+b.scorecardresearch.com.
+b.scorecardresearch.com.
+time.chttl.com.tw.
+mx8.mail.ru.
+monc.net.
+stats.avg.com.
+blog.ellegirl.com.
+160.195.10.216.in-addr.arpa.
+hiltonsanantonioap.com.1.arsmtp.com.
+www.adobe.com.
+www.gaysex.com.
+api.ning.com.
+135.82.76.187.in-addr.arpa.
+www.guitarsound.net.
+161.99.117.200.in-addr.arpa.
+a.root-servers.net.
+www.seizurechicken.com.
+pagead2.googlesyndication.com.
+i1.ytimg.com.
+c7.zedo.com.
+iavggug.info.
+whoami.akamai.net.
+ozconnect.net.
+a.root-servers.net.
+baymsg1020311.gateway.messenger.live.com.
+translate.googleapis.com.
+ns2.art-host.ru.
+franklinfavorite.com.
+www.youtube.com.
+www.gstatic.com.
+www.photovaco.com.
+mario.chulojuegos.com.
+61.112.39.77.in-addr.arpa.
+a.root-servers.net.
+windemo.deckadance.com.
+god-vs-human.free-opinion.com.
+halcobaca.min-saude.pt.
+sitecheck2.opera.com.
+www.youtube-nocookie.com.
+alerts.conduit-services.com.
+astound.net.
+earthlinjk.net.
+frogmans.net.
+fonts.googleapis.com.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+146.141.208.201.in-addr.arpa.
+www.smule.com.
+tw.apple.com.
+rad.msn.com.
+highexpert.ru.
+www.soumaya.com.mx.
+bajaxtreme.com.
+88.241.104.186.in-addr.arpa.
+www.managua.gob.ni.
+213.155.26.79.in-addr.arpa.
+s7.addthis.com.
+autos.mercadolibre.com.ar.
+jabber13.liveprofile.com.
+counterb.statcounter.com.
+www.plcsim.com.
+a.root-servers.net.
+ats.tumri.net.
+a3.da1.akamai.net.
+mail-gw.bcp.com.
+api.twitter.com.
+i1.ytimg.com.
+nova937.com.au.
+221.126.224.80.in-addr.arpa.
+250.91.10.187.in-addr.arpa.
+l.addthiscdn.com.
+dl5.torrentzap.com.
+tinyprints.widget.custhelp.com.
+itunes.apple.com.
+21.133.222.201.in-addr.arpa.
+covpatlaw.com.mx4.aantispam.rcimx.net.
+www.parcs-naturels-regionaux.tm.fr.
+us.tracker.worldofwarcraft.com.
+pixel.facebook.com.
+www.youtube.com.
+ytimg.l.google.com.
+ocsp.verisign.com.
+api.facebook.com.
+11-courier.push.apple.com.
+a.root-servers.net.
+admissions.arizona.edu.
+a1.twimg.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+clkads.com.
+a8.sphotos.ak.fbcdn.net.
+17.2.60.186.in-addr.arpa.
+www.youtube.com.
+www.abibids.com.
+ns2.makeshop.jp.
+weboutlook.beiersdorfgroup.com.
+google.com.
+s.youtube.com.
+www.webtoolol.com.
+vy8uzdb5z.t24g0u8l.
+57.225.172.186.in-addr.arpa.
+a.root-servers.net.
+5483.live.streamtheworld.com.
+mail.webcapades.net.
+1channel.ch.
+www.rinconjuegos.com.
+a.root-servers.net.
+trade-futures.com.
+www.telemundoeventos.com.
+d5k8r31tz.69xz.
+lemamed.ru.
+googleads.g.doubleclick.net.
+97.181.165.201.in-addr.arpa.
+bay.gateway.messenger.live.com.
+221.138.180.189.in-addr.arpa.
+cox.net.
+uk.yahoo.com.
+facebook.com.
+90.251.160.190.in-addr.arpa.
+a.root-servers.net.
+187.247.30.189.in-addr.arpa.
+mail.fountain.ru.
+support.google.com.
+sturehof.com.
+153.155.220.66.zen.spamhaus.org.
+pixel.rubiconproject.com.
+s.ytimg.com.
+s1-onenote.vo.msecnd.net.
+cdn1.certified-apps.com.
+www.machinediagnostics.com.
+ca.wikipedia.org.
+mwcdn.50cubes.com.
+clients1.google.com.
+lenoxhomeloans.com.
+www.medicalteams.org.
+www.likepagebuilder.com.
+j22mnely2.30yf.
+apis.google.com.
+shockbolt.deviantart.com.
+a.root-servers.net.
+pcf-ironmail01.wusm-pcf.wustl.edu.
+profile.ak.fbcdn.net.
+ads.lfstmedia.com.
+www.amatuer-pics.net.
+ytstatic.l.google.com.
+googleads.g.doubleclick.net.
+a-0.19-2709e071.d0d0083.1518.19d3.3ea1.410.0.wqgt8tgc81eq48q14ca4dz2tfb.avqs.mcafee.com.
+dopplershift.net.
+rts.fling.doublepimp.com.
+245.98.184.186.in-addr.arpa.
+60.128.45.186.in-addr.arpa.
+evintl-aia.verisign.com.
+tuned.mobi.
+ds.addthis.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+88.27.230.119.in-addr.arpa.
+g.espncdn.com.
+81.123.168.189.in-addr.arpa.
+183.207.39.187.in-addr.arpa.
+tchimb.spb.su.
+45.111.248.201.in-addr.arpa.
+safebrowsing-cache.google.com.
+226.172.138.201.in-addr.arpa.
+dubai.isnuts.googlepages.com.
+profiles.google.com.
+sp.cwfservice.net.
+r._dns-sd._udp.lan.
+50.214.191.64.in-addr.arpa.
+connect.facebook.net.
+www.facebook.com.
+hma.org.
+maps.googleapis.com.
+wiki.answers.com.
+181.178.97.92.in-addr.arpa.
+229.3.63.151.in-addr.arpa.
+msc.wlxrs.com.
+157.220.29.189.in-addr.arpa.
+rad.msn.com.
+googleads.g.doubleclick.net.
+www.merchantselect.com.
+a7.sphotos.ak.fbcdn.net.
+u47.eset.com.
+www.google.com.
+9.174.251.190.in-addr.arpa.
+boltamps.com.
+static.pbc.com.
+a.root-servers.net.
+aterminus.files.wordpress.com.
+tienda.jasani.es.
+mail.google.com.
+www.googleadservices.com.
+a.root-servers.net.
+images.ip.com.
+tickets.musicbrainz.org.
+searchclient.live.net.
+echinoblog.blogspot.com.
+mail.peaceful.com.
+avtoperevozki.com.
+safebrowsing.clients.google.com.
+www.bywifi.com.
+anastasiamexico.com.
+prostimenya.com.
+cw3.com.
+inbound.fastener-express.com.netsolmail.net.
+crl.microsoft.com.
+pixel.facebook.com.
+comune.savignone.ge.it.
+smtp3.etssi.com.
+lh6.googleusercontent.com.
+members.livejasmin.com.
+30.courier-push-apple.com.akadns.net.
+profile.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+aforestfrolic.com.
+www.rpmrcproducts.com.
+252.165.91.186.in-addr.arpa.
+apis.google.com.
+wn5iftq5l.g50d2e9u.
+www.easy-down.net.
+www.atunexpress.com.
+a.root-servers.net.
+212.226.174.189.in-addr.arpa.
+stores.ebay.com.
+pilotmedia.ru.
+cpk9p5jqy.52vj.
+msn.com.
+queer.com.
+check6.facebook.com.
+www.businessenglishebook.com.
+my.msn.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.highboost.com.
+rad.dsc.ru.
+www.descuentocity.com.
+es.wikipedia.org.
+8.0.168.192.in-addr.arpa.
+www.grist.org.
+search.powersportsplus.com.
+documentales.videosyonkis.com.
+10-async.olark.com.
+a.root-servers.net.
+ssl.gstatic.com.
+samsungmobilemoments.com.
+a.root-servers.net.
+memorva.jp.
+www.facebook.com.
+5nlkw2x23.c14b8o7y.
+touhycjbkh.net.
+va1en.sftcdn.net.
+a4.sphotos.ak.fbcdn.net.
+t1.gstatic.com.
+translate.google.com.
+txads.buzzcity.net.
+twitter.com.
+207.169.14.186.in-addr.arpa.
+a.root-servers.net.
+dns.msftncsi.com.
+tcpv4.easythumbhost.com.
+c707977.r77.cf2.rackcdn.com.
+ncshkkoipm01.ap.jnj.com.
+www.bmf.co.uk.
+wfcgjjov9.v91b6e5y.
+g.ceipmsn.com.
+static03.boobytwister.com.
+www.microsoft.com.
+neuroskills.com.
+ssl.gstatic.com.
+google.com.
+a.root-servers.net.
+dns.msftncsi.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+download351.avast.com.
+www.facebook.com.
+api.webrep.avast.com.
+kangas.no.
+image.epost.go.kr.
+213.73.135.187.in-addr.arpa.
+twitter.com.
+pop.advecs.com.
+www.weebirdy.com.
+highslide.com.
+e5016.b.akamaiedge.net.
+a-0.19-230fe081.a0e0580.1518.19d4.2f4a.400.0.smgql7jzk5g8d9zff4tq7njzcj.avqs.mcafee.com.
+a.root-servers.net.
+ages-collection.ru.
+www.gstatic.com.
+google.com.
+bleachadventurerol.foroactivo.net.
+falda.fr.
+bioserv.de.
+css1.beoo.com.
+i3.ytimg.com.
+checkip.dyndns.org.
+105.240.51.190.in-addr.arpa.
+www.banddirector.com.
+www.stat-togo.org.
+192.70.15.186.in-addr.arpa.
+mx.queensborofarms.com.
+www.checkers.com.
+www.riveonline.com.
+135.34.236.200.in-addr.arpa.
+globalcontctsinc.com.
+7.17.230.190.in-addr.arpa.
+static.ak.fbcdn.net.
+i.ytimg.com.
+193.188.176.190.in-addr.arpa.
+media.a1.com.mk.
+wilky.co.uk.
+17.192.139.175.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+i4.ytimg.com.
+www.sigrealm.com.
+dibblyfresh1.blogspot.com.
+2xixvsj9q.36lc.
+i1.gatewayinterface.com.
+humor.mundodescargas.com.
+translate.googleapis.com.
+freestylebmx.org.
+translation.engine.conduit-services.com.
+www.chulojuegos.com.
+photos-f.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+gurux.net.
+mail.eland-energy.com.
+28.8.57.186.in-addr.arpa.
+www.pdf-lib.ru.
+patrimonio.com.mx.
+a.root-servers.net.
+configuration.apple.com.
+www.zerorc.com.
+jagerbar.ru.
+plus.google.com.
+www.facebook.com.
+ajax.googleapis.com.
+mortgages4solutions.com.
+support.google.com.
+6.20.191.91.in-addr.arpa.
+teympd:og.26jb.
+www.iheartplayzynga.com.
+ds.addthis.com.
+_477_63_2.
+mailserver.holidayinn-batam.com.
+twitter.com.
+www.morhipo.com.
+sasib-na.com.
+37.124.226.201.in-addr.arpa.
+s3.amazonaws.com.
+blu.stb.s-msn.com.
+video.l3.fbcdn.net.
+planetasigarra.blogspot.com.
+0-44.channel.facebook.com.
+lh4.googleusercontent.com.
+_dns-llq._udp.push.apple.com.
+4.11.31.211.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.perfil.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+69.33.248.189.in-addr.arpa.
+s2.youtube.com.
+www.update.microsoft.com.
+www.mediawiki.org.
+store.millerheiman.com.
+blogs.eset-la.com.
+a6.sphotos.ak.fbcdn.net.
+a724.phobos.apple.com.
+140cc.v.fwmrm.net.
+db._dns-sd._udp.lan.
+vh14.ppstream.com.
+xcalabaja.com.
+74.43.98.66.in-addr.arpa.
+www.stick-up-kids.de.
+www.juegos.com.
+iphone.gogii.com.
+static.ak.fbcdn.net.
+latino.msn.com.
+ilmiopensiero.forumcommunity.net.
+www.update.microsoft.com.
+mbcc.com.
+www.recycling-machine.com.
+csi.gstatic.com.
+profile.ak.fbcdn.net.
+accounts.l.google.com.
+o-o.preferred.pz.www.google.com.
+cscsrvnew1app30.amer.csc.com.
+s10.histats.com.
+profile.ak.fbcdn.net.
+chromejs.s3.amazonaws.com.
+a.root-servers.net.
+2.30.231.201.in-addr.arpa.
+royal-trading.jp.
+www.google-analytics.com.
+33.52.174.190.in-addr.arpa.
+i1.ytimg.com.
+photos-d.ak.fbcdn.net.
+160.111.229.189.in-addr.arpa.
+ergogroup.no.
+9z772drlt.89ys.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+16.101.220.201.in-addr.arpa.
+load.monohrome.com.
+a1406.w42.akamai.net.
+content.yieldmanager.edgesuite.net.
+anemofilm.ru.
+www.alexa.com.
+mdawmdewotaxmjaxmg.org.
+espanol.weather.com.
+thumbs1.ebaystatic.com.
+content.dl-rms.com.
+no.hotels.com.
+dailymaverick.co.za.
+www.kurims.kyoto-u.ac.jp.
+api.conduit.com.
+179.28.214.66.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+serviceimg.pricegong.com.
+86.176.19.83.in-addr.arpa.
+sp.cwfservice.net.
+justscandinavian.com.
+medsos.ru.
+zefone.com.
+mail2.colibri.krsk.ru.
+c-0.19-a309f481.483.1518.19d4.3ea1.210.0.cj1um18aa3789ls947agauibjb.avqs.mcafee.com.
+s4.argim.net.
+admin.mshome.net.
+static02.olx-st.com.
+h.live.com.
+ksn2-12.kaspersky-labs.com.
+www.go.microsoft.akadns.net.
+gs-loc.apple.com.
+aquariablog.wordpress.com.
+www.kisseo.de.
+126.207.40.114.in-addr.arpa.
+hi-in.facebook.com.
+104.0.0.192.in-addr.arpa.
+cs510102.vkontakte.ru.
+www.google.com.
+99.153.60.183.in-addr.arpa.
+www.roughcooking.com.
+photos-e.ak.fbcdn.net.
+sitepointbroadcast.createsend4.com.
+60.39.191.95.in-addr.arpa.
+165.213.186.189.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+assuretec.com.
+static.ak.fbcdn.net.
+arendatr.ru.
+googleads.g.doubleclick.net.
+images.movielink.com.
+acriacao.com.
+www.youtube.com.
+photos-g.ak.fbcdn.net.
+dogtraining.com.
+personal.avira-update.com.
+theenvelope.latimes.com.
+www.redefiningpiano.com.
+kikkut.no.
+a0.twimg.com.
+nvsslassets.msnbc.msn.com.
+a6.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.krs.baltimore.ru.
+_995_87_4.
+gfx2.hotmail.com.
+v20.nonxt2.c.youtube.com.
+static.ak.fbcdn.net.
+167.59.126.71.in-addr.arpa.
+pop.jocrf.org.
+www.lanvin.com.
+www.hammervision.com.tr.
+telbarato.net.
+m.addthisedge.com.
+_759_41_4.
+vevo.ly.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+safebrowsing-cache.google.com.
+xxy.com.
+7.189.251.190.in-addr.arpa.
+www.forever-christies.com.
+profile.ak.fbcdn.net.
+sisar4k.com.
+198.86.168.192.in-addr.arpa.
+dns.msftncsi.com.
+couponbuddy.s3.amazonaws.com.
+conduit.anybodyoutthere.com.
+snsgw.samsungmobile.com.
+apps.facebook.com.
+www.naltqi.com.
+www.google-analytics.com.
+photos-g.ak.fbcdn.net.
+250.254.243.190.in-addr.arpa.
+69.227.51.173.in-addr.arpa.
+chriss2d.deviantart.com.
+musica.itematika.com.
+us.lrd.yahoo.com.
+189.147.13.187.in-addr.arpa.
+166.98.232.189.in-addr.arpa.
+83.104.130.85.in-addr.arpa.
+www.cosmeticclub.es.
+photos-a.ak.fbcdn.net.
+www.losbackyardiganss.blogspot.com.
+dynamicdialogs.alert.conduit-services.com.
+241.195.137.186.in-addr.arpa.
+log.adap.tv.
+bathcc.com.s8a1.psmtp.com.
+krisknits.blogspot.com.
+www.chicashi5.org.
+vtr.net.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+maps.gstatic.com.
+a.root-servers.net.
+203.211.82.95.in-addr.arpa.
+redaktion-bahamas.org.
+ms-frontend.hse.ru.
+teredo.ipv6.microsoft.com.
+app.rounds.com.
+187.92.107.200.in-addr.arpa.
+connect.facebook.net.
+71.143.5.184.in-addr.arpa.
+167.108.24.83.in-addr.arpa.
+www.facebook.com.
+slipknotla.blogspot.com.
+242.146.102.94.in-addr.arpa.
+www.cintegral.cl.
+campaignjobs.asia.
+fb.37cs.com.
+google.com.
+a3.sphotos.ak.fbcdn.net.
+brightsideofthesun.com.
+www.carascorridas.com.
+www.facebook.com.
+a718.g.akamai.net.
+www.siteadvisor.com.
+px.smowtion.com.
+a3.sphotos.ak.fbcdn.net.
+www.orangetree.co.uk.
+courterco.com.s8a2.psmtp.com.
+6-0.qlty.finarea.ch.
+www.scvtv.com.
+ing-things.blogspot.com.
+deals.timeoutnewyorkkids.com.
+i4.ytimg.com.
+tc.v9.cache6.c.youtube.com.
+www.bywifi.com.
+cs9439.vk.com.
+a.root-servers.net.
+www.facebook.com.
+eberspacher-russia.ru.
+www.youtube.com.
+_255_86_5.
+muonline.biz.
+safebrowsing.clients.google.com.
+osnews.com.
+www.gstatic.com.
+243.131.110.123.in-addr.arpa.
+pop3.live.com.
+bostonrehab.com.
+malah.biz.
+mail.google.com.
+static.ak.facebook.com.
+support.google.com.
+l35.member.mud.yahoo.com.
+video-6.filmix.net.
+b.scorecardresearch.com.
+connect.facebook.net.
+www.guardiantickets.co.uk.
+support.google.com.
+thumbnails46.imagebam.com.
+a8.sphotos.ak.fbcdn.net.
+www.businesssearchengine.com.au.
+ad.doubleclick.net.
+profile.ak.fbcdn.net.
+174.244.240.201.in-addr.arpa.
+www.facebook.com.
+www.tmz.com.
+www.xxxsexymilfs.com.
+107.197.242.189.in-addr.arpa.
+sites.google.com.
+ad.yieldmanager.com.
+feeds.cnet.com.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+ads2.msads.net.
+www.bigchestedbabes.com.
+making50fabulous.blogspot.com.
+www.vbauctions.net.
+creative.ak.fbcdn.net.
+141.138.193.173.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+blog.naver.com.
+css3.info.
+142.192.186.24.in-addr.arpa.
+gfx2.hotmail.com.
+kcstar.com.
+_ldap._tcp.
+ads.bluelithium.com.
+a.root-servers.net.
+249.180.204.190.in-addr.arpa.
+scientxp.com.
+132.199.55.96.in-addr.arpa.
+www.google-analytics.com.
+rosivg25.wordpress.com.
+www.iamshekhar.co.cc.
+99dn7z72y.43rs.
+ads.adbrite.com.
+whitecointerra.com.
+251.42.156.201.in-addr.arpa.
+technologie.gazeta.pl.
+3.ns1631263.info.
+ats.tumri.net.
+aventuras.isladejuegos.es.
+yourgamersparadise.com.
+l.addthiscdn.com.
+www.addthis.com.
+twitter.com.
+8.165.137.175.in-addr.arpa.
+accugenix.com.s10a2.psmtp.com.
+aliner.com.
+safebrowsing-cache.google.com.
+clients1.google.com.
+s-static.ak.fbcdn.net.
+a.root-servers.net.
+uprl.kandk.ru.
+www.download.windowsupdate.com.
+www.hpwebos.com.
+www.bigbuttslikeitbig.org.
+www.facebook.com.
+181.225.215.173.in-addr.arpa.
+support.google.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+api.twitter.com.
+www.nycgo.com.
+236.251.171.200.in-addr.arpa.
+www.aviransplace.com.
+static.ak.fbcdn.net.
+hospiceheart.org.s8a1.psmtp.com.
+static.ak.fbcdn.net.
+192.140.138.187.in-addr.arpa.
+202.104.1.201.in-addr.arpa.
+502.talkgadget.google.com.
+t1.gstatic.com.
+ksn3-11.part2.kaspersky-labs.com.
+157.113.250.190.in-addr.arpa.
+listen.cinemix.fr.
+accountservices.msn.com.
+sn104w.snt104.mail.live.com.
+teredo.ipv6.microsoft.com.
+www.draftfcb.com.mx.
+l.yimg.com.
+id.wikipedia.org.
+218.239.84.59.in-addr.arpa.
+members.ansi.org.
+168.7.56.92.in-addr.arpa.
+200.2.168.192.in-addr.arpa.
+dcpff.tumblr.com.
+a7.sphotos.ak.fbcdn.net.
+swellwatch.wetsand.com.
+adors.com.
+www.rugsyd.com.au.
+www.facebook.com.
+www.aemultimedia.es.
+ddpc.com.s5b2.psmtp.com.
+240.196.197.68.in-addr.arpa.
+geo.tp-cdn.com.
+entergy.com.
+met.no.
+www.didacmania.com.
+rar-repair.nsware.com.
+www.easy.lv.
+www.wheels-and-wings.org.uk.
+89.140.112.200.in-addr.arpa.
+apps.facebook.com.
+kiteboard.ru.
+s2.youtube.com.
+54.96.72.202.in-addr.arpa.
+136.137.232.24.in-addr.arpa.
+www.belkin.com.
+v4.nonxt3.c.youtube.com.
+www.bridgepub.mx.
+widgets.amung.us.
+hyundai-info.ru.
+ksn2-12.kaspersky-labs.com.
+he.wikipedia.org.
+archives.chennaionline.com.
+20minutos.feedsportal.com.
+p05-keyvalueservice.icloud.com.akadns.net.
+google.com.
+237.subnet118-97-164.static.astinet.telkom.net.id.
+hybrydica.ru.
+audiodrums.com.
+3.203.183.189.in-addr.arpa.
+100.141.121.74.in-addr.arpa.
+col.stb00.s-msn.com.
+www.c64-wiki.de.
+bloggerplugins.org.
+pixel.facebook.com.
+m.addthisedge.com.
+teredo.ipv6.microsoft.com.
+jigsaw.w3.org.
+a1725.l.akamai.net.
+mail.google.com.
+profile.ak.fbcdn.net.
+alvarsoft.com.
+pixel.facebook.com.
+m.facebook.com.
+manulifesecurities.com.
+www.lazoblanco.org.
+244.27.146.99.in-addr.arpa.
+21.30.143.187.in-addr.arpa.
+51.77.2.195.in-addr.arpa.
+zsxifmeksub.org.
+136.111.93.186.in-addr.arpa.
+kumr.lns.com.
+js.wlxrs.com.
+www.levimage.com.
+adhitzads.com.
+cargo2000.dk.
+safebrowsing-cache.google.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.l.google.com.
+www.al-anonuk.org.uk.
+creative.ak.fbcdn.net.
+228.219.132.190.in-addr.arpa.
+www.campaignjobs.asia.
+www.secreto-chino.com.
+www.google.com.
+a.root-servers.net.
+s1.wp.com.
+fbcdn-profile-a.akamaihd.net.
+r._dns-sd._udp.lan.
+105.240.234.81.in-addr.arpa.
+socpixel.bidsystem.com.
+connect.facebook.net.
+hysexch07.hye.co.il.
+i140.photobucket.com.
+174.162.108.186.in-addr.arpa.
+137.142.243.147.in-addr.arpa.
+courchevel.su.
+wbns.com.s7b2.psmtp.com.
+28.207.221.87.in-addr.arpa.
+196.15.46.90.in-addr.arpa.
+uwbfyc.com.
+pixel.facebook.com.
+www.threeweb.ad.jp.
+profile.ak.fbcdn.net.
+i1.tagstat.com.
+www.youtube.com.
+www.addingsite.com.
+50.156.220.66.in-addr.arpa.
+i4.ytimg.com.
+45.31.168.192.in-addr.arpa.
+146.131.177.189.in-addr.arpa.
+srv.srvdomain.com.
+apps.filestube.com.
+yfrog.com.
+www.monumentalgames.com.
+174.196.91.186.in-addr.arpa.
+images.emusic.com.
+alimentosweb.galeon.com.
+installer.frostwire.com.
+connect.facebook.net.
+ksn2-12.kaspersky-labs.com.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+dialtone.com.
+tts.orel.ru.
+assets.t.popupbooster.com.
+www.facebook.com.
+vk.com.
+cdn1.xamez.inxy-host.com.
+_546_20_1.
+a.root-servers.net.
+mosenergo.ru.
+eltamborrugiente.blogspot.com.
+www2.esmas.com.
+www.latbus.com.
+www.transl.net.
+vgmanager.no.
+kojyyj.com.
+barracuda.montereyclub.com.
+tools.google.com.
+a.root-servers.net.
+d2090462.xoom.it.
+www.deskdivers.com.
+tcacdn-3.thecelebarchive.net.
+twitter.com.
+usb.relaxunix.net.
+69.204.152.201.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+ildesign.ru.
+profile.ak.fbcdn.net.
+www.beyzacases.com.
+tein.net.
+www.igorbass.com.
+www.escape.ws.
+199.64.139.189.in-addr.arpa.
+privetsochi.ru.
+188.104.248.189.in-addr.arpa.
+c144101.memecenter.com.
+a.root-servers.net.
+wdw2.wdpromedia.com.
+static.ak.fbcdn.net.
+242.146.52.187.in-addr.arpa.
+blvgroup.ru.
+osuno.no-ip.biz.
+29.203.238.190.in-addr.arpa.
+www.all4myspace.de.
+www.premiumhdv.com.
+hmag.disqus.com.
+entretenimiento.wikia.com.
+www.laobesidad.net.
+www.cesarcancino.com.
+photos-g.ak.fbcdn.net.
+money.cnn.com.
+www.facebook.com.
+your.net.com.
+_080_52_9.
+www.motors.ebay.com.
+18.225.12.212.in-addr.arpa.
+l.addthiscdn.com.
+www.about-recipes.com.
+js.parabebes.com.
+11.105.168.189.in-addr.arpa.
+www.funnythingsmykidsaid.com.
+clockwatchers.net.
+156.150.33.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.marcandangel.com.
+ares.dl.playstation.net.
+www.politraductor.com.
+191.68.237.188.in-addr.arpa.
+174.45.174.190.in-addr.arpa.
+www.star-advertising.com.
+profile.ak.fbcdn.net.
+maxrealty.co.jp.s9a1.psmtp.com.
+suivi.evenko.ca.
+www.youtube.com.
+banks2banks.ru.
+i4.ytimg.com.
+cdn2.image.tube8.phncdn.com.
+photos-a.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+ddn:ak6vw.d84n0a5m.
+164.131.138.187.in-addr.arpa.
+29.media.tumblr.com.
+www.youtube.com.
+storage.conduit.com.
+111.176.153.95.in-addr.arpa.
+gratisxjuegos.com.
+s-static.ak.fbcdn.net.
+pennwoods.net.
+a1351.v.phobos.apple.com.
+196.137.175.208.in-addr.arpa.
+www.grupo-sm.com.
+download315.avast.com.
+6.35.104.186.in-addr.arpa.
+133.71.160.190.in-addr.arpa.
+tr.adinterax.com.
+d7.zedo.com.
+apps.facebook.com.
+eurostroygroup.ru.
+a10.t26.net.
+www.google-analytics.com.
+9.a.4.d.7.2.6.8.9.b.9.0.1.9.c.1.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+media.etoro.com.
+a.root-servers.net.
+146.127.142.189.in-addr.arpa.
+b4.
+mail.dbamlg.com.
+ec2.images-amazon.com.
+s7.addthis.com.
+dejardefumar2.blogspot.com.
+107.26.157.157.in-addr.arpa.
+www.24log.es.
+66.71.167.24.in-addr.arpa.
+ahfc.state.ak.us.
+upload.wikimedia.org.
+camcom.net.
+175.193.174.190.in-addr.arpa.
+chromeunderground.blogspot.com.
+help.weheartit.com.
+compilr.com.
+www.premiosarpa.com.
+www.amazon.co.uk.
+www.pixsblog.com.
+131.140.37.190.in-addr.arpa.
+sakura-no-tamashii.deviantart.com.
+optimized-by.rubiconproject.com.
+www.pritzkermilitarylibrary.org.
+crl.globalsign.net.
+mail.levelsaudio.com.
+hdjlaw.com.
+doba.si.
+nanyang.com.
+pole59.ru.
+ms0.dfi.com.tw.
+a3.sphotos.ak.fbcdn.net.
+au.download.windowsupdate.com.
+www.megauploadbay.com.
+3.10.56.186.in-addr.arpa.
+www.bestonlinerpggames.com.
+www.google.com.
+fibrespa.ru.
+www.pwpthemes.com.
+api.twitter.com.
+www.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+csi.gstatic.com.
+twitter.com.
+www.msn.com.
+www.supertop100.com.
+www.housingaforest.com.
+www.facebook.com.
+222.210.78.190.in-addr.arpa.
+hotmail.com.
+198.138.166.109.in-addr.arpa.
+view.atdmt.com.
+mx.youtube.com.
+dr._dns-sd._udp.home.
+platform.ak.fbcdn.net.
+ciclusgroup.net.
+www.facebook.com.
+2.hsup.poczta.onet.pl.
+a6.sphotos.ak.fbcdn.net.
+prod2.rest-notify.msg.yahoo.com.
+stats.adengage.com.
+a.root-servers.net.
+www.colorsound.com.
+mail.gilfusa.com.
+cadsa.com.
+atmserver1.alibaba.com.
+klit.startnow.com.
+zarina.ru.
+centrointegramurcia.blogspot.com.
+assassin.nexon.com.au.
+kabelspeed.at.
+atphagraphics.com.
+a5.sphotos.ak.fbcdn.net.
+s0.2mdn.net.
+83.209.192.187.in-addr.arpa.
+view.atdmt.com.
+shatim-trade.ru.
+73.134.213.201.in-addr.arpa.
+www.theyellowcommunity.com.
+dsl-384-gw.architectsde.com.
+online.no.
+twitter.com.
+groups.live.com.
+www.google.com.
+www.hoteldeca.com.
+google.com.
+www.myybiz.net.
+no.wikipedia.org.
+www.imanhearts.com.
+www.facebook.com.
+groups.google.com.mx.
+a7.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+chermet-s.ru.
+www.njstar.com.
+mail.ashnet.it.
+a968yfanx.12pc.
+145.74.125.200.in-addr.arpa.
+a.root-servers.net.
+3.127.36.186.in-addr.arpa.
+136.224.145.201.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+developers.facebook.com.
+dbcmail02.ca.debeersgroup.com.
+i3.ytimg.com.
+www.samsung.com.
+googleads.g.doubleclick.net.
+static.ads.crakmedia.com.
+static.hi5.com.
+ads.dotomi.com.
+a288.phobos.apple.com.
+aol.com.
+badoo.com.
+photos-b.ak.fbcdn.net.
+ad.xtendmedia.com.
+site.delain.nl.
+www.wweshop.com.
+nass-sa.net.
+studentlink.net.
+msa.biglobe.ne.jp.
+_sipinternal._tcp.quintiles.com.quintiles.net.
+db.local.clamav.net.
+217.188.57.186.in-addr.arpa.
+partyrockpeople.com.
+thebas.homelinux.com.
+248.176.100.122.in-addr.arpa.
+22.4.171.201.in-addr.arpa.
+i1.ytimg.com.
+profile.ak.fbcdn.net.
+fb-0.hidden.zynga.com.
+ar-ar.facebook.com.
+smtp.unhsinc.com.
+a1005.w42.akamai.net.
+154.240.111.216.in-addr.arpa.
+chdarchitects.com.inbound25.mxlogic.net.
+81.213.249.70.in-addr.arpa.
+226.198.137.190.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+www.womensoccer.com.au.
+174.175.152.189.in-addr.arpa.
+whos.amung.us.
+globalmortgagecc.com.
+www.mediawiki.org.
+www.playwaitressgames.com.
+playerusersvc.play.it.
+www.ubilapaz.edu.bo.
+86.180.70.71.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+www.lux.org.uk.
+steelmart.com.
+www.groundcontrol.com.
+api.twitter.com.
+i1.ytimg.com.
+132.19.147.187.in-addr.arpa.
+52.186.176.189.in-addr.arpa.
+cmedia-business.ru.
+matthewcoxantiques.com.
+mx-24-75-128-158.rivonline.net.
+abeoidii4.38hn.
+www.links-web.net.
+97.240.110.201.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+diseasesconditions-articledirectoryon.blogspot.com.
+kemana.com.
+poll.hotlayouts2u.com.
+6wveoklwe.g27z5d6j.
+www.facebook.com.
+www.facebook.com.
+194.1.131.187.in-addr.arpa.
+a.root-servers.net.
+www.ninoycancer.cl.
+www.academie-francaise.fr.
+69.187.213.91.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+appworld.blackberry.com.
+secure.wlxrs.com.
+akhal-teke.ru.
+a.root-servers.net.
+www.desertspeak.com.
+sup.live.com.
+a.root-servers.net.
+www.mgar.net.
+images.99bb.com.
+57.117.42.201.in-addr.arpa.
+a0.twimg.com.
+www.ellabellaphotos.com.
+fbcdn-profile-a.akamaihd.net.
+www.campvslab.cl.
+a.root-servers.net.
+cdn.cartown.com.
+teredo.ipv6.microsoft.com.
+dnqkzyzxnstsvu.biz.
+elkom.ru.
+profile.ak.fbcdn.net.
+ocsp.usertrust.com.
+www.rasta-man.co.uk.
+ptrv.ru.
+arsenalmusic.ru.
+ochnews.com.
+login.yahoo.com.
+juju.lt.
+0-161.channel.facebook.com.
+a.root-servers.net.
+a.root-servers.net.
+41.179.242.201.in-addr.arpa.
+lazonadelosgraffitis.foroactivo.com.
+a2.sphotos.ak.fbcdn.net.
+gg.google.com.
+crashboombangmusic.com.
+static.ak.facebook.com.
+www.sexreaction.com.
+wpad.
+www.abstractlogix.com.
+storage.conduit.com.
+api.mapabc.com.
+geeksquads.goes2u.com.
+photos-b.ak.fbcdn.net.
+pernodricard-uk.com.s200b2.psmtp.com.
+movies.gigantits.com.
+.
+169.101.89.186.in-addr.arpa.
+ad-g.doubleclick.net.
+www.netretina.com.
+a7.sphotos.ak.fbcdn.net.
+40.133.252.190.in-addr.arpa.
+mail1.nadams.k12.in.us.
+www.pmis.co.uk.
+.
+dpdartnbo.72ke.
+255.197.231.69.in-addr.arpa.
+librecinefilo.com.
+c.msn.com.
+t0.gstatic.com.
+alexa.cn.
+0-if-w.channel.facebook.com.
+exp02.eset.com.
+gfx4.hotmail.com.
+www.abnertrujillo.com.
+a1.twimg.com.
+nextwave.universia.net.
+134.199.40.65.in-addr.arpa.
+stone-systems.com.
+228.23.207.186.in-addr.arpa.
+secure.military.com.
+h.live.com.
+www.stumbleupon.com.
+gcwaeiddepudijfokaanpqja.mu.
+photos-b.ak.fbcdn.net.
+nbd.com.
+46.106.18.190.in-addr.arpa.
+images.google.com.
+photos-h.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+accountservices.msn.com.
+tconl.com.
+34.141.181.190.in-addr.arpa.
+ad.xtendmedia.com.
+accor-mail.com.rbl2.mcafee.com.
+img.rincondelvago.com.
+a.root-servers.net.
+d2060586.instant.xoom.it.
+ad.yieldmanager.com.
+csi.gstatic.com.
+a.root-servers.net.
+www.apartamentos-medellin.com.
+canariolandia.mforos.com.
+networkroadrunner.disqus.com.
+dns2.dcsi.de.
+tacata.com.
+www.youtube.com.
+9.32.209.201.in-addr.arpa.
+www.google-analytics.com.
+www.facebook.com.
+gavan-invest.ru.
+99.29.207.190.in-addr.arpa.
+smtp.zoomtown.com.
+www.jamienelson.com.
+media.scholarshippoints.com.
+profile.ak.fbcdn.net.
+veneziaassociates.com.
+www.google.com.
+71.105.65.71.in-addr.arpa.
+cbk1.google.com.
+www.facebook.com.
+pubads.g.doubleclick.net.
+instagr.am.
+cloud-search-msgplus.linkury.com.
+www.woodturningonline.com.
+38.181.235.189.in-addr.arpa.
+google.com.
+plug-in.com.br.
+mail1.in2focus.com.
+csdnimg.cn.
+i.ytimg.com.
+s-static.ak.facebook.com.
+cti.gr.
+24.151.244.189.in-addr.arpa.
+client.akamai.com.
+78.35.213.201.in-addr.arpa.
+audience.netavenir.com.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+4nodbmbq1kg3jfkhn7m4ua4bn329jbnf-a-sites-opensocial.googleusercontent.com.
+bebebaratisimo.com.
+50.56.124.69.in-addr.arpa.
+mail.ttknet.ru.
+236.168.51.190.in-addr.arpa.
+moberg.com.
+a1725.l.akamai.net.
+b._dns-sd._udp.0.129.37.10.in-addr.arpa.
+ehovpfsnszg.net.company.com.
+162.2.72.189.in-addr.arpa.
+a.root-servers.net.
+hb.whatsapp.net.
+login.live.com.
+www.comunidadpymes.com.
+blog.bibliothek.kit.edu.
+22.247.137.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+221.132.118.217.in-addr.arpa.
+vvebcams.spb.ru.
+deti.bazar.sk.
+ksn1-11-part2.kaspersky-labs.com.
+m.yahoo.co.jp.
+123.16.0.10.in-addr.arpa.
+mail2.fire.org.nz.
+www.hotsassy.net.
+137.73.82.200.in-addr.arpa.
+sites.google.com.
+echo.edge.messenger.live.com.
+10.96.250.190.in-addr.arpa.
+a1506.phobos.apple.com.
+www.mbc.net.
+apps.facebook.com.
+165.33.186.201.in-addr.arpa.
+imagenesangeles.com.
+comunidad.semana.com.
+www.informatique.com.mx.
+chanokaqh.deviantart.com.
+www.dejatuempleo.com.
+mback.csgny.com.
+21.122.136.175.in-addr.arpa.
+18.73.51.24.in-addr.arpa.
+mailbox.pircher.at.
+www.rae.com.
+38.147.220.66.in-addr.arpa.
+a.root-servers.net.
+netdark.files.wordpress.com.
+coxhanson.ca.
+249.79.112.190.in-addr.arpa.
+www.facebook.com.
+holmesproducts.com.
+br.weather.com.
+photos-g.ak.fbcdn.net.
+client-software.real.com.
+168.110.114.200.in-addr.arpa.
+www.9gag.com.
+safebrowsing-cache.google.com.
+140.184.139.187.in-addr.arpa.
+a-0.19-2209d081.c040082.1518.19d4.3ea1.410.0.uprtfjst5crek8qge2qz1693sb.avqs.mcafee.com.
+www.belkin.com.
+translate.google.com.mx.
+www.domainit.com.
+191.36.31.82.in-addr.arpa.
+81.194.78.201.in-addr.arpa.
+developers.facebook.com.
+a.root-servers.net.
+sc21.rules.mailshell.net.
+148.157.201.190.in-addr.arpa.
+:smz1pynj.a72l9r3t.
+www.fashiontoast.com.
+a4.mzstatic.com.
+static.ak.fbcdn.net.
+ad.xtendmedia.com.
+www.pharmacyathand.co.uk.
+a.root-servers.net.
+stereoplus.com.
+developers.facebook.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+inbound.advantech-inc.com.netsolmail.net.
+hi-in.facebook.com.
+searchvip1.sli-systems.net.
+aol.com.
+mundomoto.bligoo.com.
+italiano.softmyhard.com.
+s2.youtube.com.
+video-g19.proxad.net.
+22.43.111.174.in-addr.arpa.
+fxfeeds.mozilla.com.
+8cbnuqbnb.39sk.
+chromejs.s3.amazonaws.com.
+87.73.134.187.in-addr.arpa.
+www.0.com.
+blufiles.storage.msn.com.
+126.166.91.91.in-addr.arpa.
+localhost.
+n003-000-000-000.static.ge.com.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+clients2.google.com.
+www.youtube.com.
+developers.facebook.com.
+telinvest.com.
+i4.ytimg.com.
+salemchamber.org.
+defis.kis.ru.
+images.barchart.com.
+news.google.com.mx.
+graph.facebook.com.
+pagead2.googlesyndication.com.
+www.sorbita.com.
+sr.jailbreak-me.info.
+quality-tour.com.
+a5.sphotos.ak.fbcdn.net.
+www.20minutos.es.
+cdn1.static.tube8.phncdn.com.
+www.jongales.com.
+pagead2.googlesyndication.com.
+search.jp.wsj.com.
+steel.nsk.su.
+clients2.google.com.
+703.coll.ning.com.
+_808_68_5.
+www.cybermonday2011.com.
+www.filemakertrial.com.
+58.26.133.187.in-addr.arpa.
+www.stc.com.sa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+37.128.16.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+150.137.98.76.in-addr.arpa.
+www.youtube.com.
+mail.homelocatorsrealty.com.
+ad-g.doubleclick.net.
+www.newz-premium.com.
+mkz33xw:y.57ua.
+www.peliculasfox.com.
+googleads.g.doubleclick.net.
+135.15.255.201.in-addr.arpa.
+a.root-servers.net.
+plantx.com.
+www.twink-guys.com.
+162.158.115.189.in-addr.arpa.
+now.org.
+heidegger.x-y.net.
+google.com.
+62.34.178.190.in-addr.arpa.
+vdovichenko.ru.
+time.chttl.com.tw.
+playball.eluniversal.com.
+yahoo.ytsa.net.
+streamlfree.live-onweb.com.
+photos-e.ak.fbcdn.net.
+237.62.17.177.in-addr.arpa.
+tracker.thepiratebay.org.
+www.findyourfamilytree.com.
+nortonsecurity.blinkweb.com.
+dns.msftncsi.com.
+teredo.ipv6.microsoft.com.
+voydat.com.
+156.112.28.83.in-addr.arpa.
+56.15.182.189.in-addr.arpa.
+espndeportes-assets.espn.go.com.
+_784_41_7.
+m.addthisedge.com.
+mckechnie.com.
+a.root-servers.net.
+www.esedark.com.
+tsm01.eset.com.
+js.chatsend.com.
+livingliberally.org.
+gigantioempresarios.blogspot.com.
+32.155.119.222.in-addr.arpa.
+time-nw.nist.gov.
+resolver3.ipsw.ctmail.com.
+223.94.158.201.in-addr.arpa.
+www.nvgopcaucus.com.
+photos-e.ak.fbcdn.net.
+no.wikipedia.org.
+mx01.puc.rediris.es.
+187.85.32.177.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.bromleybike.co.uk.
+eurostar.voyages-sncf.com.
+laposte.net.
+_696_32_1.
+hrndva-smtpin02.mail.rr.com.
+cmmeiers.com.
+www.videojuegos.com.
+authenticpress.com.
+www.update.microsoft.com.
+62.158.220.66.in-addr.arpa.
+192.172.152.187.in-addr.arpa.
+css.wlxrs.com.
+www.ipsca.com.
+a.root-servers.net.
+alerts.conduit-services.com.
+adoftheyear.com.
+www.videox2424.com.
+remaxcolonial.com.
+directimports.co.uk.
+vid2c.disqus.com.
+www.adobe.com.
+5.175.77.219.in-addr.arpa.
+tin.hongkong1.com.
+a3.sphotos.ak.fbcdn.net.
+static.ak.facebook.com.
+228.143.71.77.in-addr.arpa.
+apps.facebook.com.
+lermanlaw.com.s8b1.psmtp.com.
+194.32.82.190.in-addr.arpa.
+jjjkc5h9v.07tp.
+devices.live.com.
+apps.facebook.com.
+www.buenosairesdelivery.com.
+253.239.186.93.in-addr.arpa.
+gayshow.blogsome.com.
+securemail.novartis.net.
+yahoo.com.
+rad.msn.com.
+d1j68ux4ukg4g1.cloudfront.net.
+ftp.porcupine.org.
+img.feb-search.com.
+rct395f5z.z62y4p9w.
+profile.ak.fbcdn.net.
+yourmayflower.com.
+www.musica-online.org.
+external.ak.fbcdn.net.
+69.52.55.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+whinuxkern.executablychewi.fm.
+destylesenaiguilles.wordpress.com.
+fairfaxis.com.
+fxfeeds.mozilla.com.
+www.facebook.com.
+104.6.73.219.in-addr.arpa.
+oss-survey.securestudies.com.
+169.94.6.189.in-addr.arpa.
+au.download.windowsupdate.com.
+www.google.com.mx.
+www.youtube-nocookie.com.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+23.35.52.186.in-addr.arpa.
+www.paratucuidado.com.ar.
+apps.facebook.com.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+apis.google.com.
+2oqe9qij7.56iy.
+content.yieldmanager.edgesuite.net.
+facemoods.com.
+_585_54_6.
+a.root-servers.net.
+www.google-analytics.com.
+231.92.80.190.in-addr.arpa.
+1st-premier.com.s7a2.psmtp.com.
+211.32.234.189.in-addr.arpa.
+gujeha7d3.31el.
+www.google.com.
+a9xozbfz1.47mw.
+home.costhelper.com.
+qcode.us.
+zopugiwepehowyj.info.
+www.ceddet.org.
+jestro.com.
+www.eurocommuseum.com.
+fbcdn-photos-a.akamaihd.net.
+32.courier-push-apple.com.akadns.net.
+laprincesacaprichosa.blogspot.com.
+164.173.125.190.in-addr.arpa.
+evintl-ocsp.verisign.com.
+www.gladiatus.lv.
+a.root-servers.net.
+b.scorecardresearch.com.
+b._dns-sd._udp.lan.
+cmgtcontent.ahold.com.kpnis.nl.
+www.teamovercome.net.
+static.ak.fbcdn.net.
+api.conduit.com.
+24.media.tumblr.com.
+fbcdn-profile-a.akamaihd.net.
+www.facebook.com.
+www.clocklink.com.
+naacy.org.
+d2111274.xoom.it.
+www.lmolnar.com.
+www.zynga.com.
+todoaudio.cl.
+a7.sphotos.ak.fbcdn.net.
+lus.net.
+hipstamaticapp.com.
+a8.sphotos.ak.fbcdn.net.
+isatap.belkin.
+time.chttl.com.tw.
+clock.fmt.he.net.
+mail.bwrogers.com.
+ksn2-12.kaspersky-labs.com.
+photos-d.ak.fbcdn.net.
+66.36.45.189.in-addr.arpa.
+www.gruposyv.com.
+mx1.martinlitho.com.
+www.risorsegeek.net.
+mail1.ingles-markets.com.
+13.166.110.76.in-addr.arpa.
+82.145.105.186.in-addr.arpa.
+www.piadasnet.com.
+www.royalsuitesturquesaresort.com.
+sites.google.com.
+mail.streamline-ops.com.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+d2055107.instant.xoom.it.
+90.154.88.186.in-addr.arpa.
+www.rotaterra.com.
+0612com3s2a.freehostia.com.
+216.128.112.128.in-addr.arpa.
+cositphotography.com.
+.
+www.linkleak.org.
+www.otherthings.com.
+rad.msn.com.
+addons.mozilla.org.
+a.root-servers.net.
+pubads.g.doubleclick.net.
+centerpointvp.com.
+m.detik.com.
+adult-img02.olx.com.mx.
+www.seasite.niu.edu.
+s-static.ak.facebook.com.
+simon1.me.uk.
+platform.linkedin.com.
+www.foofighters.fm.
+oxgw7mx54.58an.
+a5.sphotos.ak.fbcdn.net.
+www.ggi.com.mx.
+textad.xxxmatch.com.
+streaming.mediamatters.org.
+143.53.154.186.in-addr.arpa.
+68.148.49.49.in-addr.arpa.
+mx.youtube.com.
+creative.ak.fbcdn.net.
+tag.admeld.com.
+123.4.10.85.in-addr.arpa.
+www.hamptons.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.thinkteens.com.
+163.127.6.189.in-addr.arpa.
+mountainkeeper.org.
+www.bloghissimo.com.
+dist.divx.com.
+www.piercingbible.com.
+76.31.9.76.in-addr.arpa.
+image2.cecash.com.
+i1.ytimg.com.
+155.170.88.200.in-addr.arpa.
+www.info.lncc.br.
+skins.gmodules.com.
+nyc2k155.ameca.panorg.com.
+lvrewelju.u52m3o9v.
+mob.adwhirl.com.
+t3.baidu.com.
+ocsp.godaddy.com.
+www.plena507.org.
+zh-cn.facebook.com.
+www.adxpansion.com.
+coldngrey.blogspot.com.
+qfj:95oem.r43l1a5h.
+tetc1.ceryxefw.com.
+112.126.106.189.in-addr.arpa.
+53.153.206.200.in-addr.arpa.
+platform.ak.fbcdn.net.
+masabadell.wordpress.com.
+mail.live.com.
+i2.ytimg.com.
+init.ess.apple.com.
+evintl-ocsp.verisign.com.
+i2.ytimg.com.
+dc263.4shared.com.
+sandesh.ganeshaspeaks.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+3.gvt0.com.
+joinexpedia.com.
+translate.googleapis.com.
+stenske.kiev.ua.
+um12.eset.com.
+84.47.43.186.in-addr.arpa.
+105.238.1.118.in-addr.arpa.
+s.ytimg.com.
+www.mochiads.com.
+68.242.100.190.in-addr.arpa.
+modnoe-mecto.ru.
+130.154.128.190.in-addr.arpa.
+mail.arzamarket.ru.
+developer.ean.com.
+www.shueisha.co.jp.
+212.116.59.82.in-addr.arpa.
+ns1.apk.net.
+fbcdn-photos-a.akamaihd.net.
+clients2.google.com.
+musicandmore.bligoo.com.mx.
+mail.capebouvard.com.
+safebrowsing-cache.google.com.
+csi.gstatic.com.
+uspeh24.ru.
+store.apolisglobal.com.
+download326.avast.com.
+a7.sphotos.ak.fbcdn.net.
+9.47.21.201.in-addr.arpa.
+beckersasc.com.
+246.202.209.201.in-addr.arpa.
+www.balashov.san.ru.
+joplinfamilyy.org.
+danielpowter.ru.
+ad.doubleclick.net.
+pixel.facebook.com.
+www.stumbleupon.com.
+241.61.154.187.in-addr.arpa.
+www.tolaymat.com.
+www.woodcrafter.com.
+netvigator.com.
+mail.google.com.
+www.bulgaria-travel-guide.com.
+gally.hellfiresex.com.
+itaka-fan.los-foros.com.
+lh3.googleusercontent.com.
+www.facebook.com.
+www.dotster.com.
+171.19.251.190.in-addr.arpa.
+a.root-servers.net.
+www.absolutemadonna.com.
+d1af033869koo7.cloudfront.net.
+google.com.
+mx.youtube.com.
+www.facebook.com.
+titanium30-en.url.trendmicro.com.
+www.vidaabundante.com.mx.
+a6.sphotos.ak.fbcdn.net.
+www.hiyoko-g.com.
+6.226.10.186.in-addr.arpa.
+modder.net.
+a34.g.akamai.net.
+.
+a.root-servers.net.
+img03.taobaocdn.com.
+lb._dns-sd._udp.lan.
+www.fc.com.
+ctzujo.com.
+www.sohuads.com.
+brisajuvenil.blogspot.com.
+ar.thefreedictionary.com.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ocsp.verisign.com.
+59.218.95.201.in-addr.arpa.
+9-courier.push.apple.com.
+202.144.131.63.in-addr.arpa.
+149.115.69.190.in-addr.arpa.
+developers.facebook.com.
+a2.twimg.com.
+177.231.34.186.in-addr.arpa.
+cmxr.com.s7b1.psmtp.com.
+msvqdoq19.83ti.
+secure.globalsign.net.
+f.facemoods.com.
+ad.doubleclick.net.
+photos-f.ak.fbcdn.net.
+youtu.be.
+202.250.34.2.in-addr.arpa.
+_054_09_1.
+profile.ak.fbcdn.net.
+shuttleworth-uk.co.uk.inbound10.mxlogic.net.
+www.make-fabulous-cakes.com.
+kanrou.net.
+shelf-life.ew.com.
+www.mundoanuncio.com.sv.
+photos-f.ak.fbcdn.net.
+hypesrus.com.
+www.facebook.com.
+daemon-tools.softonic.com.
+bestbetting.sesmazing.com.
+mystartantiphishing.com.
+photos-g.ak.fbcdn.net.
+63.124.226.190.in-addr.arpa.
+www.be2.co.uk.
+_381_41_3.
+amsdocs.com.
+twitter.com.
+4.map.pop6.com.
+gpc.ru.
+mail.tellus.nl.
+222.162.229.88.in-addr.arpa.
+www-proxy.ericsson.se.
+maxneutra.com.
+liveupdate.symantecliveupdate.com.
+www.groupon.com.ar.
+6.190.172.201.in-addr.arpa.
+spam2.e-land.gov.tw.
+aidps.atdmt.com.
+forum.aheadworks.com.
+hotforex.com.hypestat.com.
+carestream.ru.
+www.facebook.com.
+231.37.56.186.in-addr.arpa.
+gye.hoy.net.
+vip.mlstatic.com.
+113.246.213.201.in-addr.arpa.
+tools.google.com.
+addons.mozilla.org.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.gogotorrent.com.
+candocareer.com.
+img844.imageshack.us.
+tempomusic.com.
+apis.google.com.
+20.225.132.190.in-addr.arpa.
+www.dorma-interior.com.
+141.190.43.190.in-addr.arpa.
+100.247.253.189.in-addr.arpa.
+22.61.74.190.in-addr.arpa.
+mail02.bg-group.com.
+www.pimientaycanela.com.
+zh-cn.facebook.com.
+ns.magnetism.ru.
+qpsisbest.com.m2.mx-route.com.
+a1402.w40.akamai.net.
+stacksvinyl.com.
+photos-h.ak.fbcdn.net.
+15.167.50.201.in-addr.arpa.
+www.google-analytics.com.
+wstat.wibiya.com.
+js2.wlxrs.com.
+store.dll-files.com.
+www.facebook.com.
+a.root-servers.net.
+www.informationhospitaliere.com.
+a.root-servers.net.
+forelskelse.com.
+static.ak.fbcdn.net.
+clients4.google.com.
+241.188.249.188.in-addr.arpa.
+nobreastsnorequests.tumblr.com.
+a.root-servers.net.
+babcom4.lnc.net.
+mccafferyinterests.com.s5a2.psmtp.com.
+176.cim.meebo.com.
+aquascene.com.au.
+picasaweb.google.com.
+graph.facebook.com.
+profile.ak.fbcdn.net.
+wpad.
+233.124.241.189.in-addr.arpa.
+www.zobo.ca.
+gmfcollect.com.
+www.google-analytics.com.
+www.audiencescience.com.
+a.root-servers.net.
+twitter.com.
+plusone.google.com.
+mail.cfmcgroup.com.
+_093_08_2.
+hammond.org.
+www.jvcpro.eu.
+220.149.224.190.in-addr.arpa.
+82.44.168.192.in-addr.arpa.
+photos.americanlemans.com.
+192.209.3.190.in-addr.arpa.
+131.94.79.201.in-addr.arpa.
+google.ail.com.
+174.177.204.190.in-addr.arpa.
+csi.gstatic.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+weather.bigspeedpro.com.
+rerih.ru.
+ssl.gstatic.com.
+user.home.
+thelongboardblog.com.
+aspenbuilders.co.uk.
+five.tefgame.com.
+m.youtube.com.
+www.wdc.com.
+api.twitter.com.
+italiacampersud.it.
+214.51.229.189.in-addr.arpa.
+219.101.194.186.in-addr.arpa.
+189.111.22.71.in-addr.arpa.
+lh4.googleusercontent.com.
+ssl.gstatic.com.
+i3.msdn.microsoft.com.
+65.203.205.218.in-addr.arpa.
+v17.lscache7.c.bigcache.googleapis.com.
+new-rap.ru.
+173.245.53.200.in-addr.arpa.
+twitter.com.
+sa-live.com.
+www.shy22.com.
+pagead2.googlesyndication.com.
+profile.ak.fbcdn.net.
+smtp1.ppcc.edu.
+_784_28_0.
+av1.tnz.myschools.net.
+js2.wlxrs.com.
+217.35.168.192.in-addr.arpa.
+ussd.ru.
+2f6508c4.allanalpass.com.
+up.uchc.edu.
+creative.ak.fbcdn.net.
+hash.orbitdownloader.com.
+ksn2-12.kaspersky-labs.com.
+coachhousecraftingonabudget.blogspot.com.
+economictimes.feedsportal.com.
+t1.gstatic.com.
+a2.sphotos.ak.fbcdn.net.
+laprendizdechef.blogspot.com.
+api202e.thefilter.com.
+www.holidaycityflash.com.
+252.26.0.181.in-addr.arpa.
+image.web.cyberimg.com.
+mta2.am0.yahoodns.net.
+a4.sphotos.ak.fbcdn.net.
+_572_46_2.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+igor.facemoods.com.
+lioninthesunps.com.
+col.stb01.s-msn.com.
+www18.officedepot.com.
+mail.sakurabloom.com.
+d1j68ux4ukg4g1.cloudfront.net.
+paynoattention.kicks-ass.net.
+a4.sphotos.ak.fbcdn.net.
+apix.iminent.com.
+elsingular.com.
+mail2.interyuna.ru.
+yahoo.com.
+www.freelearn110.com.
+lc.mcafee.com.
+www.cerur.org.
+it-it.facebook.com.
+i.ytimg.com.
+a1.sphotos.ak.fbcdn.net.
+www.cfmaroc.com.
+210.238.143.187.in-addr.arpa.
+www.dick.com.
+dataage.blogspot.com.
+safebrowsing-cache.google.com.
+252.115.149.187.in-addr.arpa.
+www.turquoise-voyages.fr.
+www.mochiads.com.
+121.78.126.71.in-addr.arpa.
+v.gatcdn.com.
+a.root-servers.net.
+a.root-servers.net.
+fisifvg.org.
+dns.msftncsi.com.
+tech.teachmyass.com.
+site.beltoutlet.com.
+rob2tall1.newsvine.com.
+profile.ak.fbcdn.net.
+orcart.facebook.com.
+crittercorral.com.
+blogantiheroes.files.wordpress.com.
+www.demotores.es.
+www.google-analytics.com.
+api.facebook.com.
+wukesha.k12.wi.us.
+clients4.google.com.
+a.root-servers.net.
+71.90.216.150.in-addr.arpa.
+mx.electricentertainment.com.
+lacasaeuropa.blogspot.com.
+quicktime.uptodown.com.
+0-if-w.channel.facebook.com.
+google.com.
+sup.live.com.
+at.7digital.com.
+torresvedras.olx.pt.
+42.33.145.189.in-addr.arpa.
+pixel.quantserve.com.
+static2.avast.com.
+www.koolkiz.com.
+www.dumcoach.com.
+47.43.117.74.in-addr.arpa.
+dx3723.tinyurl.com.
+inferno.demonoid.me.
+251.1.238.190.in-addr.arpa.
+www.blowjobpimps.com.
+admiralplc.com.
+teredo.ipv6.microsoft.com.
+ad.eqsv.jp.
+www.strictlyreptiles.com.
+wrapcritic.com.
+sbnbox.com.
+www.youtube.com.
+pueblo-insurance.com.
+quazy4quakers.com.
+232.128.210.201.in-addr.arpa.
+www.miniclip.com.
+a.root-servers.net.
+167.26.236.77.in-addr.arpa.
+secure.shared.live.com.
+gdata.youtube.com.
+www.nlm.nih.gov.
+a.root-servers.net.
+www.socialgrowthtechnologies.com.
+73.102.249.190.in-addr.arpa.
+58.125.40.190.in-addr.arpa.
+\(none\).
+mail1.colmanagement.com.
+mono.ximian.com.
+www.bywifi.com.
+evintl-ocsp.verisign.com.
+200.91.248.189.in-addr.arpa.
+hi-in.facebook.com.
+photos-f.ak.fbcdn.net.
+relay.voice.edge.messenger.live.com.
+www.cooldictionary.com.
+profile.ak.fbcdn.net.
+43.208.33.177.in-addr.arpa.
+www.dspdoctor.com.
+photos-b.ak.fbcdn.net.
+heavenlysweet.blogspot.com.
+hi-in.facebook.com.
+client29.dropbox.com.
+photos-e.ak.fbcdn.net.
+wzeu.ask.com.
+developers.facebook.com.
+www.print-gakufu.com.
+eimail.com.
+developers.facebook.com.
+www.asiaticos.org.
+twitter.com.
+festoolownersgroup.com.
+a.root-servers.net.
+watsonreltycorp.com.
+41.130.225.212.in-addr.arpa.
+mgurxvgtykkrpqg.net.
+billing.sharo4ka.ru.
+a.root-servers.net.
+imagine-graphics.net.
+_767_24_0.
+100.16.75.187.in-addr.arpa.
+www9.effectivemeasure.net.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+25.97.48.190.in-addr.arpa.
+www.viptickets.com.
+emoticons.msn-beta.com.
+adscachable.nfl.mobitv.com.
+136.120.55.190.in-addr.arpa.
+fr.webrep.avast.com.
+19.201.168.192.in-addr.arpa.
+a.root-servers.net.
+external.ak.fbcdn.net.
+24.188.35.201.in-addr.arpa.
+mss.api.getjar.com.
+touch.facebook.com.
+partner.googleadservices.com.
+www.imanmaleki.com.
+ow2ryx7ij.58hy.
+developers.facebook.com.
+api.facebook.com.
+blackmarketbikes.com.
+dermadoctor.tt.omtrdc.net.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mysecretceres.com.
+swcdn.apple.com.
+topcosales.com.
+cdn.api.twitter.com.
+d2095752.xoom.it.
+150.17.16.206.in-addr.arpa.
+www.wikimapia.org.
+22.164.179.190.in-addr.arpa.
+external.ak.fbcdn.net.
+static.ak.fbcdn.net.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+94.152.117.200.in-addr.arpa.
+safebrowsing-cache.google.com.
+feeds.bbci.co.uk.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a2.twimg.com.
+zynga1-a.akamaihd.net.
+44.165.56.186.in-addr.arpa.
+img.dukascopy.com.
+tools.google.com.
+sealns5.nstld.net.
+220.224.45.190.in-addr.arpa.
+wisconsinbenefits.com.
+static.ak.fbcdn.net.
+www.google.com.mx.
+creative.ak.fbcdn.net.
+twitter.com.
+time.chttl.com.tw.
+www.kickload.com.
+opi.yahoo.com.
+dem0003.in.
+59.120.209.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+safebrowsing.clients.google.com.
+b.static.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+games.yahoo.com.
+a.root-servers.net.
+mail.creamyradio.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.badboyonline.com.
+av.ru.s200b1.psmtp.com.
+_ldap._tcp.
+stores.guitarcenter.com.
+lb.wordpress.com.
+www.718c.com.
+t1.gstatic.com.
+blog.penyubiru.com.
+revolucionindustrialrosana.blogspot.com.
+234.40.172.109.in-addr.arpa.
+www.carinos.com.
+prch.org.
+profile.ak.fbcdn.net.
+a1.da1.akamai.net.
+amer.rel.msn.com.
+www.arcat.com.
+creative.ak.fbcdn.net.
+cqwmw8qzr.v77g6s3s.
+31.63.229.78.in-addr.arpa.
+bin-short.whatsapp.net.
+youtube-5th.softonic.com.
+inbound.icdcoc.com.netsolmail.net.
+accesorioshp.com.
+www.absolutefigures.com.
+www.kalipedia.com.
+a2.sphotos.ak.fbcdn.net.
+m.facebook.com.
+i2.cdn.turner.com.
+apps.facebook.com.
+244.208.88.201.in-addr.arpa.
+feeds.bbci.co.uk.
+119.10.168.192.in-addr.arpa.
+51.16.235.99.in-addr.arpa.
+juanmanuel-vivenciasinteriores.blogspot.com.
+panelogic.com.
+108.206.243.41.in-addr.arpa.
+www.mrbigler.com.
+11.29.229.190.in-addr.arpa.
+search.imesh.com.
+www.bing.com.
+a.root-servers.net.
+79.216.231.212.in-addr.arpa.
+autos.divendo.mx.
+db._dns-sd._udp.0.129.37.10.in-addr.arpa.
+44993amailer.net.
+ssl.gstatic.com.
+i3.ytimg.com.
+au.answers.yahoo.com.
+s2.youtube.com.
+login.oscar.aol.com.
+stretchmarkinstitute.com.
+www.chinabusinessworld.com.
+kgtzu68yo.j56g6y2b.
+dc261.4shared.com.
+mx.oceanlakes.com.
+118.181.153.109.in-addr.arpa.
+platform.ak.fbcdn.net.
+www.theinnovationdiaries.com.
+11.231.195.190.in-addr.arpa.
+kzbwk7r7h.h45l9n0f.
+cdn.smosh.com.
+211.175.138.187.in-addr.arpa.
+4.25.168.192.in-addr.arpa.
+x.tagstat.com.
+i2.ytimg.com.
+rodajes.net.
+s1-word-view.vo.msecnd.net.
+191.208.36.190.in-addr.arpa.
+awck.com.
+13.124.236.98.in-addr.arpa.
+www.facebook.com.
+assets4.castle.zgncdn.com.
+ad.yieldmanager.com.
+76.190.248.213.in-addr.arpa.
+twitter.com.
+136.243.168.189.in-addr.arpa.
+a.root-servers.net.
+_481_28_2.
+www.congratulationstext.com.
+hxenmd382.88tt.
+ssl.gstatic.com.
+p18-buy.itunes.apple.com.
+journals.lww.com.
+inbound.phoenixgroup.org.netsolmail.net.
+_695_16_7.
+152.151.192.187.in-addr.arpa.
+154.230.132.190.in-addr.arpa.
+itech.fgcu.edu.
+tm.dp.yieldmanager.net.
+www.youtube.com.
+puertorico.koalatrends.com.
+www.google.com.
+www.google.com.
+vt2000.ru.
+hotmail.com.
+tc.v2.cache3.c.youtube.com.
+oaid.uab.es.
+ssl.gstatic.com.
+descargarpeliculasgratis.ziflo.net.
+cdn.api.twitter.com.
+static.ak.fbcdn.net.
+240.111.104.87.in-addr.arpa.
+s2.googleusercontent.com.
+a-tsb.ru.
+specialolympicswisconsin.org.
+sync.imob2.com.
+31.204.226.201.in-addr.arpa.
+ad.doubleclick.net.
+a5.sphotos.ak.fbcdn.net.
+platform.twitter.com.
+a.root-servers.net.
+19.134.60.213.in-addr.arpa.
+59.211.222.189.in-addr.arpa.
+forum.gamesports.net.
+www.embeddedpc.net.
+b.z.eset.rs.
+platform.twitter.com.
+www.models.or.kr.
+adaneslaberinto.espacioblog.com.
+api-read.facebook.com.
+u44b9qf:y.94wa.
+s.mobclix.com.
+blog.online-convert.com.
+a4.sphotos.ak.fbcdn.net.
+madcoyote.com.
+apis.google.com.
+a1.sphotos.ak.fbcdn.net.
+brand-yourself-blog.disqus.com.
+www.adobe.com.
+book-with-pictures.blogspot.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+apps.facebook.com.
+pnrws.skype.com.
+18.82.165.58.in-addr.arpa.
+vetlearn.com.s7b1.psmtp.com.
+about.tagged.com.
+153.144.167.190.in-addr.arpa.
+www.google.com.
+47.38.181.220.in-addr.arpa.
+in1.msg.vip.re2.yahoo.com.
+premieroutdoorproperties.com.
+ajax.googleapis.com.
+www.algzar99.com.
+8.36.75.190.in-addr.arpa.
+195.89.17.71.in-addr.arpa.
+41.23.19.186.in-addr.arpa.
+cc-codi.fr.
+www.borne.cc.
+dragonet.es.
+3.29.34.187.in-addr.arpa.
+a489.ac-images.myspacecdn.com.
+echo.edge.messenger.live.com.
+28.247.3.89.in-addr.arpa.
+s7.addthis.com.
+i4-img3.mangachapter.net.
+external.ak.fbcdn.net.
+erwbtkidthetcwerc.com.
+naval.mforos.com.
+images6.cuantocabron.com.
+download851.avast.com.
+hartmannhouse.ru.
+aka-cdn-ns.adtechus.com.
+www.techadmirer.com.
+www.tutorialsgarden.com.
+26.49.196.190.in-addr.arpa.
+static.pcomperf.com.
+233.34.158.187.in-addr.arpa.
+offers.veer.com.
+mail.niia.net.
+0.5475251.com.
+telezhka.com.ru.
+idpix.media6degrees.com.
+kvs.be.
+16.147.220.66.in-addr.arpa.
+loading6.widdit.com.
+_921_97_7.
+vopyzyk.com.
+74.234.47.189.in-addr.arpa.
+www.20minutos.es.
+mail.planning.gov.sa.
+apps.104.6rtl.com.
+plusone.google.com.
+mail.platbank.com.
+www.logitravel.com.br.
+photos-h.ak.fbcdn.net.
+bing.com.
+_219_24_2.
+a1505.l.akamai.net.
+clients1.google.com.mx.
+.
+www.gastroanthropology.com.
+www.google.com.
+mail.efdgroup.net.
+creative.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+ajax.googleapis.com.
+trans.in-freight.spb.ru.
+102.138.45.83.in-addr.arpa.
+nudt.edu.cn.
+6.25.68.189.in-addr.arpa.
+members.dyndns.org.
+ocsp.verisign.com.
+mgmt.beta.toolbar.msn.com.
+diosaladyruby.blogspot.com.
+exchange.thebeverageworks.com.
+a6.sphotos.ak.fbcdn.net.
+cuantocabron.com.
+teredo.ipv6.microsoft.com.
+87.35.31.190.in-addr.arpa.
+524r1tqe3.r96w0c5a.
+www.harrenmediatools.com.
+b.scorecardresearch.com.
+avante.net.mx.
+btq26vmu9.87yu.
+concienciacristiana.blogspot.com.
+nautilus.scene7.com.
+121.164.139.98.dnsbl.sorbs.net.
+75.23.0.192.in-addr.arpa.
+b.scorecardresearch.com.
+static.99widgets.com.
+secure.wlxrs.com.
+time.chttl.com.tw.
+mail.sinosure.com.cn.
+sannicolasdelosgarza.olx.com.mx.
+server4.web-stat.com.
+go.srvnow.com.
+197.242.185.201.in-addr.arpa.
+hootsuite.com.
+fbcdn-profile-a.akamaihd.net.
+elainemeinelsupkis.typepad.com.
+a.root-servers.net.
+a.root-servers.net.
+fieldforce.cz.
+market.android.com.
+www.facebook.com.
+www.experiencewa.com.
+safebrowsing-cache.google.com.
+60.194.87.115.in-addr.arpa.
+www.puppiesforsalecheap.net.
+bigeast.org.
+www2.scjn.gob.mx.
+_609_47_3.
+254.208.68.98.in-addr.arpa.
+mcgrigors.com.
+121.177.225.123.in-addr.arpa.
+0.11-a70ea079.2.1518.18a4.3ea1.210.0.2ft7kv1rbn483wbvsuclmwjhtb.avqs.mcafee.com.
+clients1.google.com.
+www.ncbi.nlm.nih.gov.
+euro.mediotiempo.com.
+google.com.
+a.root-servers.net.
+nfrr.ru.
+dns.msftncsi.com.
+exgf4bz4z.h73d0p2s.
+a1.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+bit.ly.
+mafiascum.net.
+photos-c.ak.fbcdn.net.
+allprosupplements.com.
+starrtincup.com.
+iijmio-mail.jp.
+photos-b.ak.fbcdn.net.
+sn1msg1010620.gateway.messenger.live.com.
+a6.sphotos.ak.fbcdn.net.
+www.miga.org.
+zea.com.
+vodkaonly.com.
+fbcdn-profile-a.akamaihd.net.
+imkontext.at.
+172.55.221.216.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+books.google.com.mx.
+portalde.info.
+100.206.143.201.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ksn3-11.part1.kaspersky-labs.com.
+ubiqq.com.
+kmlafilm.com.
+boroughmarket.org.uk.
+google.com.
+sp.fieldhealth.com.
+img1.blogblog.com.
+healthywaterman.com.
+www.altromercato.it.
+www.google.com.mx.
+nicregi.hubpages.com.
+customwebdesigners.com.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+geox.ru.
+snt0-omc3-s18.snt0.hotmail.com.
+48.1.65.50.in-addr.arpa.
+i4.ytimg.com.
+144.224.250.99.in-addr.arpa.
+wu-international.com.
+fbcdn-sphotos-a.akamaihd.net.
+88.gt2.vkadre.ru.
+del.icio.us.
+www.google.com.mx.
+images.speedbit.com.
+86.254.70.190.in-addr.arpa.
+84.73.57.62.in-addr.arpa.
+131.52.79.184.in-addr.arpa.
+1.bp.blogspot.com.
+video.xnxx.com.
+www.ant.com.
+2.55.89.120.in-addr.arpa.
+www.clickamateur.es.
+nightclassmembers.blogspot.com.
+www.afsvlaanderen.be.
+mobile.twitter.com.
+162.84.84.200.in-addr.arpa.
+129.212.11.201.in-addr.arpa.
+s-static.ak.fbcdn.net.
+85g4jaxbq.l92r1l1h.
+mail.brighterdaysent.com.
+162.55.66.212.in-addr.arpa.
+articleslot.info.
+124.50.248.201.in-addr.arpa.
+pod.xxxmatch.com.
+68.160.72.78.in-addr.arpa.
+api.facebook.com.
+www.goojue.com.
+theframeproblem.wordpress.com.
+teredo.ipv6.microsoft.com.
+clu-in.org.
+206.183.66.201.in-addr.arpa.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+sp.ask.com.
+29.media.tumblr.com.
+3dhelpcenter.com.
+rxvwf5b7m.c62m8i2j.
+api.twitter.com.
+a.root-servers.net.
+www.ipcos.com.
+a7.sphotos.ak.fbcdn.net.
+maukdesign.com.inbound15.mxlogic.net.
+perigree.net.
+a7.sphotos.ak.fbcdn.net.
+yaahoo.co.uk.
+static.chartbeat.com.
+244.66.19.186.in-addr.arpa.
+vuz2006.ru.
+losyvr5z6.24uo.
+mujer.latercera.com.
+ilchildcare.org.
+photos-b.ak.fbcdn.net.
+juancamef.blogspot.com.
+a4.sphotos.ak.fbcdn.net.
+check6.facebook.com.
+mail-2.netbauds.net.
+i3.ytimg.com.
+images02.olx.com.
+gta-san-andreas-homeboys.softonic.com.br.
+photos-g.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+www.neverthirsty.org.
+218.18.155.109.in-addr.arpa.
+miportal.att.net.
+eruptedale.mcentcoughwith.tm.
+www.infolinks.com.
+149.172.109.200.in-addr.arpa.
+smurfs.capcomcanada.com.
+ioatelecom.net.
+roljoc.cl.
+befrikimyfriend.blogspot.com.
+caballonegroeditora.com.ar.
+www.unsystem.org.
+i1202.photobucket.com.
+baitassawadah.com.
+7.127.230.201.in-addr.arpa.
+www.google.com.
+zvpyn58u5.04cu.
+0-jx-w.channel.facebook.com.
+mail-attachment.googleusercontent.com.
+exp.msn.com.
+csi.gstatic.com.
+www.youtube.com.
+17.240.45.203.in-addr.arpa.
+cash2track.com.
+19.0.234.96.in-addr.arpa.
+notes.pcoa.com.
+a.root-servers.net.
+163.85.153.201.in-addr.arpa.
+225.218.84.108.in-addr.arpa.
+mxmail.diverseoptics.com.
+213.209.29.151.in-addr.arpa.
+www.upsjobs.com.
+a6.sphotos.ak.fbcdn.net.
+apps.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+117.3.18.108.in-addr.arpa.
+peruahora.wordpress.com.
+creative.ak.fbcdn.net.
+mx.terraempresas.com.br.
+photos-g.ak.fbcdn.net.
+terminal29.ru.
+a.root-servers.net.
+251.224.177.189.in-addr.arpa.
+mwbankers.com.
+amertech.com.
+fr.answers.yahoo.com.
+a8.sphotos.ak.fbcdn.net.
+ro66ljmob.37tb.
+a.root-servers.net.
+rospres.com.
+tkprok.ru.
+106.133.224.190.in-addr.arpa.
+altavistagraphics.com.
+cesblogfeed.thinkpyxl.com.
+www.intel.com.
+www.gaybaires.net.
+www.ambito.com.
+20minutos.feedsportal.com.
+fr-fr.facebook.com.
+developers.facebook.com.
+mx.ppiseattle.com.
+tandem.spb.su.
+www.facebook.com.
+mail.gvan.ru.
+andreas.com.
+ssl.google-analytics.com.
+mail.gciframing.com.
+108.27.168.192.in-addr.arpa.
+ladamadelnilo.blogspot.com.
+253.191.136.189.in-addr.arpa.
+s-external.ak.fbcdn.net.
+littleowlski.wordpress.com.
+syndication.traffichaus.com.
+platform.ak.fbcdn.net.
+cv-extreme.chatango.com.
+36.147.220.66.in-addr.arpa.
+www.facebook.com.
+pixerloadbalancer-126298269.us-east-1.elb.amazonaws.com.
+img2.blogblog.com.
+booking.ihotelier.com.akadns.net.
+mx20.mame-imprimeurs.com.
+s-external.ak.fbcdn.net.
+twitter.com.
+mail.prendergast.net.
+149.83.23.186.in-addr.arpa.
+www.youtube.com.
+va.starcat.ne.jp.
+a4.sphotos.ak.fbcdn.net.
+qswkrjd:h.n09e8i6c.
+profile.ak.fbcdn.net.
+bcl.wikipedia.org.
+facemoods.com.
+231.31.245.189.in-addr.arpa.
+_854_29_5.
+a.root-servers.net.
+gohongkong.about.com.
+151.159.168.192.in-addr.arpa.
+s.ytimg.com.
+106.112.186.189.in-addr.arpa.
+60.80.193.123.in-addr.arpa.
+www.googleadservices.com.
+www.update.microsoft.com.
+cs506204.vk.com.
+sfis.k12.nm.us.
+raisingzona.com.
+mail2ray.com.
+repo.beyoip.com.
+plainview.k12.mn.us.
+tarea-escolar.blogspot.com.
+www.osrami.com.
+i2.ytimg.com.
+e5413.g.akamaiedge.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sergecote.net.
+ncpennysaver.com.
+ssl.gstatic.com.
+api.conduit.com.
+ack-exchange.ask.ru.
+xads.zedo.com.
+ac3filter.en.softonic.com.
+k-e-s.ru.
+external.ak.fbcdn.net.
+ar-ar.facebook.com.
+bmc.org.
+astronomy.com.s8a1.psmtp.com.
+27.212.254.88.in-addr.arpa.
+26.216.193.62.in-addr.arpa.
+ajax.googleapis.com.
+10.190.119.79.in-addr.arpa.
+twitter.com.
+youtube.com.
+api.twitter.com.
+profile.ak.fbcdn.net.
+www.woozworld.com.
+www.ashtead-technology.com.
+tmss.trendmicro.com.
+233.57.132.190.in-addr.arpa.
+208.16.10.201.in-addr.arpa.
+ar-ar.facebook.com.
+www.oemdirtbikeparts.com.
+init.ess.apple.com.
+download4.dreamstime.com.
+www.facebook.com.
+igreen.net.
+g14755.chrome.funnygames.org.
+glennloomis.tcaps.net.
+www.discovirtual.com.ar.
+healtubgrant.com.
+sovereigngroup.com.
+monpetitmoment.blogspot.com.
+spacingmontreal.ca.
+fexea.com.
+30.83.111.189.in-addr.arpa.
+m.youtube.com.
+www.gotibia.com.
+photos-d.ak.fbcdn.net.
+legatarm.in.
+checkip.dyndns.com.
+assuredenvironments.com.s9a1.psmtp.com.
+i1.ytimg.com.
+www.hotelpiacenza.com.
+crl.verisign.com.
+a.root-servers.net.
+.
+help.trillian.im.
+v4.sftcdn.net.
+pixel.quantserve.com.
+api.twitter.com.
+www.google.com.
+worldoflya.blogspot.com.
+apis.google.com.
+hud93j8wi.47lv.
+165.191.10.187.in-addr.arpa.
+voxcast.oyunlar1.com.
+www.gamer.ne.jp.
+www.pinklolita.com.br.
+81.24.23.187.in-addr.arpa.
+a.ads2.msads.net.
+s-static.ak.fbcdn.net.
+100.187.58.186.in-addr.arpa.
+facebook.conduitapps.com.
+itd.pns.com.my.
+www.celeb-king.com.
+graph.facebook.com.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+www.msftncsi.com.
+reomobile.com.
+19.224.171.69.in-addr.arpa.
+2.0.168.192.in-addr.arpa.
+www.egos.co.za.
+platform.twitter.com.
+174.193.166.81.in-addr.arpa.
+server-6.reportgoogle.com.
+www.google.com.
+fonts.googleapis.com.
+hgarden.org.2.0001.arsmtp.com.
+b.scorecardresearch.com.
+pda-bes.amazon.com.
+a.root-servers.net.
+38.109.223.189.in-addr.arpa.
+ad-g.doubleclick.net.
+adwhirllb-473732162.us-east-1.elb.amazonaws.com.
+time.nist.gov.
+www.youtube.com.
+60.247.212.89.in-addr.arpa.
+i.ebayimg.com.
+profile.ak.fbcdn.net.
+96.32.88.69.in-addr.arpa.
+pixel.facebook.com.
+mail.disqus.net.
+s-static.ak.fbcdn.net.
+mva.oryol.ru.
+config.conduitapps.com.
+www.scootergalleri.dk.
+forum.kijiji.ca.
+a8.sphotos.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+minduertex.com.
+bleedingespresso.com.
+245.102.55.157.in-addr.arpa.
+americanmaint.net.
+www.yohandry.com.
+www.carspluscash.com.
+bit.ly.
+api.twitter.com.
+it-it.facebook.com.
+photos-e.ak.fbcdn.net.
+44.140.173.114.in-addr.arpa.
+api.twitter.com.
+lighbound.com.
+i.ytimg.com.
+anubis.iseclab.org.
+accountservices.msn.com.
+facebook.com.
+corp.iminent.com.
+44.228.171.69.in-addr.arpa.
+tonio.com.
+www.quelocura.net.
+108.175.235.190.in-addr.arpa.
+56.248.159.110.in-addr.arpa.
+presents.lolapps.com.
+21.36.182.189.in-addr.arpa.
+197.206.229.189.in-addr.arpa.
+www.msftncsi.com.
+netflix887.pop3.la.nflximg.com.edgesuite.net.
+northfox.uw.hu.
+sammrat.com.
+a.root-servers.net.
+cdn.plugrush.com.
+d2057192.instant.xoom.it.
+www.theliquidateher.com.
+newsrss.bbc.co.uk.
+179.29.52.83.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+rcp.na.blackberry.com.
+238.91.139.98.bl.spamcop.net.
+www.div3x.com.
+fls.doubleclick.net.
+3ie33cpgj6dhi-c.c.yom.mail.yahoo.com.
+groups.google.com.mx.
+misrmedical.com.
+megadresses.com.
+info.yahoo.com.
+ml.fb.telaxo.com.
+76.186.137.189.in-addr.arpa.
+www.bywifi.com.
+nokec.nkz.ru.
+koreanair.com.
+swa.mail.ru.
+70.146.38.77.in-addr.arpa.
+www.sublimepussy.com.
+omp1039.mail.ird.yahoo.com.
+photos-c.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+angel-dark.ps.ztod.com.
+a.root-servers.net.
+ari-texelectric.net.
+store.widdit.com.
+gfx8.hotmail.com.
+www.hoygan.info.
+nazer26.blogspot.com.
+www.eknigu.org.
+ad-emea.doubleclick.net.
+www.fjhuari.com.
+www.kibagames.com.
+a1407.phobos.apple.com.
+351.coll.ning.com.
+login.live.com.
+www.domainmastertools.com.
+m1.zedo.com.
+notifam.net.
+levenger.com.
+s1-powerpoint.vo.msecnd.net.
+foreca.palmaryservice.com.
+a4.sphotos.ak.fbcdn.net.
+www.bloomberg.co.jp.
+wa7edzah2an.blogspot.com.
+us-w1.rockmelt.com.
+hotmail.com.
+128.201.36.186.in-addr.arpa.
+d2059982.instant.xoom.it.
+29.219.23.186.in-addr.arpa.
+api.twitter.com.
+a1.sphotos.ak.fbcdn.net.
+97.95.78.190.in-addr.arpa.
+74819mailb.com.
+www.mydarkcirclesblog.com.
+dsn9.d.skype.net.
+services.addons.mozilla.org.
+a.root-servers.net.
+a.root-servers.net.
+altayvitamin.com.
+4wc24wv8u.68sg.
+billing.sharo4ka.ru.
+47.149.220.66.in-addr.arpa.
+ecn.dev.virtualearth.net.
+ocsp.digicert.com.
+91.169.214.201.in-addr.arpa.
+static.ak.fbcdn.net.
+api.facebook.com.
+233.90.55.65.bl.spamcop.net.
+searchclient.live.net.
+53.98.122.212.in-addr.arpa.
+books.google.com.
+farforest.btinternet.com.
+88.76.74.189.in-addr.arpa.
+www.mobileboner.com.
+gallys.nastydollars.com.
+seeyourimpact.org.
+islam.maktoob.com.
+www.mrskincdn.com.
+19.223.203.81.in-addr.arpa.
+kleyt.ru.
+127.0.0.1.
+www.google.com.
+_261_67_3.
+61.212.141.201.in-addr.arpa.
+worldofenglish.com.
+icode.renren.com.
+a1.sphotos.ak.fbcdn.net.
+highgate.k12.vt.us.
+pixel.facebook.com.
+chat2.doook.com.
+celeberitypictures.blogspot.com.
+cdn1.s.saboom.com.
+static.ak.fbcdn.net.
+et9.xhamster.com.
+safebrowsing.clients.google.com.
+evsecure-ocsp.verisign.com.
+twister.nyroc.rr.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+4.189.173.189.in-addr.arpa.
+twobyhomes.com.
+3.170.158.157.in-addr.arpa.
+miconstruct.com.au.
+leglue.com.
+119.50.0.10.in-addr.arpa.
+mypixcontest.cotssl.net.
+igoogle.ca.
+57.11.53.201.in-addr.arpa.
+boomers.com.
+pixel.facebook.com.
+yeee.com.
+t3.gstatic.com.
+eventomundial.com.
+regallen.files.wordpress.com.
+telecomllc.net.
+stribling.com.
+offcars.blogspot.com.
+ir.ebaystatic.com.
+photos-b.ak.fbcdn.net.
+ns4.rambler.ru.
+ads.handycafe.com.
+rad.msn.com.
+.
+api.twitter.com.
+www.google.com.
+creative.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+xv3uyxra3.70jq.
+developers.facebook.com.
+161.221.52.201.in-addr.arpa.
+www.losfotologs.com.
+home.mywebsearch.com.
+156.185.138.189.in-addr.arpa.
+a995.mm1.akamai.net.
+a.root-servers.net.
+www.googletagservices.com.
+a.root-servers.net.
+www.mafiavirtual.com.ar.
+ferchillgroup.com.
+www.theaudiophile.net.
+mail.nycap.rr.com.
+yahoo.com.
+a.root-servers.net.
+142.56.151.187.in-addr.arpa.
+rad.msn.com.
+www.youtube-nocookie.com.
+nlh.nl.ca.
+pixel.33across.com.
+market.android.com.
+37.165.149.187.in-addr.arpa.
+184.39.32.189.in-addr.arpa.
+box2.pc51.com.
+api.applifier.com.
+tour.cinamuse.com.
+www.bywifi.com.
+belarus.by.com.
+cyclonecom.com.
+111.105.104.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+91.184.239.189.in-addr.arpa.
+lhsystems.hu.
+torrentz.eu.
+www.ibervideos.es.
+mail.cmc-jobs.com.
+193.244.68.66.in-addr.arpa.
+yahoo.ca.
+65.206.166.81.in-addr.arpa.
+s-static.ak.facebook.com.
+dnl-01.geo.kaspersky.com.
+metronorthnews.com.
+illiweb.com.
+etzatlan.mundoanuncio.com.mx.
+41.193.183.24.in-addr.arpa.
+www.camelback.net.
+fbcdn-sphotos-a.akamaihd.net.
+a.root-servers.net.
+169.110.50.190.in-addr.arpa.
+79.240.47.114.in-addr.arpa.
+alt2.gmail-smtp-in.l.google.com.
+black-byte.com.
+elonigiri.blogspot.com.
+214.165.10.187.in-addr.arpa.
+157.10.40.196.in-addr.arpa.
+www.cylex.com.co.
+news.l.google.com.
+photos-f.ak.fbcdn.net.
+nicola.com.s8b2.psmtp.com.
+11.rarbg.com.
+abacus.tumblr.com.
+tr.y8.com.
+ad.reachjunction.com.
+200.137.106.186.in-addr.arpa.
+www.conclavist.com.
+hotmail.com.
+www.facebook.com.
+155.98.193.82.in-addr.arpa.
+www.panasiabeauty.com.
+132.182.168.192.in-addr.arpa.
+content.yieldmanager.edgesuite.net.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+i2.ytimg.com.
+media.trafficjunky.net.
+www.globalbx.com.
+relay2.elcom.ru.
+a4.sphotos.ak.fbcdn.net.
+www.alignment2012.com.
+c.prodigy.msn.com.
+mail4.bizland-inc.net.
+d2090520.xoom.it.
+profile.ak.fbcdn.net.
+cjmoto.com.
+mail.hhicorp.com.
+iwkwhuplspkkpmbc.info.
+www.zentosa.com.
+photos-h.ak.fbcdn.net.
+datavis.com.inbound15.mxlogic.net.
+star.facebook.com.
+clients1.google.com.
+a.root-servers.net.
+198.78.162.31.in-addr.arpa.
+167.190.51.190.in-addr.arpa.
+rospres.com.
+dbupd281f.u94d5u6c.
+profile.ak.fbcdn.net.
+www.desirablebody.co.uk.
+cheezburger.com.
+pontodefuga.deviantart.com.
+165.93.188.186.in-addr.arpa.
+laclasedetercero-carmen.blogspot.com.
+bit.ly.
+cdn.content.sweetim.com.
+googleads.g.doubleclick.net.
+www.sosoni.com.
+voipc.sip.yahoo.com.
+27.57.59.186.in-addr.arpa.
+www.thestrapsmith.com.
+c2.glitch.bz.
+www.hotel-s.es.
+plus.google.com.
+pagead2.googlesyndication.com.
+tlhenterprisesin.com.
+www.uniongang.tv.
+moneycontrol.net.
+77.0.135.91.in-addr.arpa.
+www.youtube.com.
+a114.w23.akamai.net.
+a-1imaging.com.
+livel.co.uk.
+74.47.51.203.in-addr.arpa.
+bmi-md.com.
+istana.ru.
+aus2.mozilla.org.
+144.136.173.187.in-addr.arpa.
+static.ak.fbcdn.net.
+t3.gstatic.com.
+fra01-video4-2.justin.tv.
+67.33.215.108.in-addr.arpa.
+chahue.umar.mx.
+www.kaskus.com.
+ent.163.com.
+sun-garden.ch.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+station.com.
+www.marias-santafe.com.
+pemper.sulit.com.ph.
+87.148.59.199.in-addr.arpa.
+forotopeleven.forofutbol.biz.
+issue2.show-star.biz.
+aloha.viber.com.
+g.ceipmsn.com.
+gualtiero.com.
+www.webactus.net.
+ocsp.godaddy.com.
+photos-g.ak.fbcdn.net.
+t.co.
+ksn1.kaspersky-labs.com.
+54.62.201.187.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+ads17056.hotwords.es.
+api-read.facebook.com.
+www.youtube.com.
+157.70.111.189.in-addr.arpa.
+www.backgroundsforpowerpoint.net.
+117.34.84.200.in-addr.arpa.
+s1.assets.howtospendit.com.
+feedback.weather.com.
+st.chatango.com.
+api18.thetrafficstat.net.
+img693.imageshack.us.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+www.cineplane.com.
+www.nsfcentc.org.
+dr._dns-sd._udp.lan.
+a.root-servers.net.
+www.montealban.org.mx.
+www.google-analytics.com.
+121.58.255.201.in-addr.arpa.
+www.google.com.
+155.11.0.192.in-addr.arpa.
+a.hikebike.gpsies.com.
+www.nguys.com.
+132.191.145.187.in-addr.arpa.
+a.root-servers.net.
+229.78.93.76.in-addr.arpa.
+i49.host%20no%20permitido.
+38.143.253.159.in-addr.arpa.
+mbc-law.com.
+imageup.liveasianwebcams.com.
+www.rosadesaron.net.
+www.industriasvargas.com.
+www.google-analytics.com.
+www.hassinen.eu.
+www.rbs.co.uk.
+a.root-servers.net.
+www.mujeres-guapas.com.
+a3.sphotos.ak.fbcdn.net.
+www.materialmontessori.com.
+fetch.yixingguanggao.trendcr002.com.
+vjzyuqpqq.k88x1x3f.domain.name.
+incub.ru.
+api.zynga.com.
+www.facebook.com.
+i1.ytimg.com.
+a7.sphotos.ak.fbcdn.net.
+inbound.markfrink.com.netsolmail.net.
+140.61.142.186.in-addr.arpa.
+_055_03_6.
+ksn1-11-part2.kaspersky-labs.com.
+photos-d.ak.fbcdn.net.
+154.71.43.208.in-addr.arpa.
+secure.quamm.net.
+golf-tees-story.info.
+svr4.hotweb.dk.
+103.19.253.190.in-addr.arpa.
+amer.rel.msn.com.
+i.ytimg.com.
+comdpx01.banacol.com.co.
+154.179.199.213.in-addr.arpa.
+creative.ak.fbcdn.net.
+cascaderaft.com.
+41.222.37.174.in-addr.arpa.
+airwis.com.
+246.231.38.189.in-addr.arpa.
+www.grannyflash.com.
+253.66.31.180.in-addr.arpa.
+a.root-servers.net.
+directory.services.live.com.
+www.blogextremo.com.
+231.157.74.187.in-addr.arpa.
+56.13.91.2.in-addr.arpa.
+www.sinhogar.org.
+bff-games.com.
+10.53.74.187.in-addr.arpa.
+css.wlxrs.com.
+www.cyberstep.com.
+blog.sina.com.tw.
+a5.sphotos.ak.fbcdn.net.
+www.google.es.
+fuyagil.blogspot.com.
+www.web-site-scripts.com.
+11.176.253.189.in-addr.arpa.
+175.22.158.189.in-addr.arpa.
+mail.modernspanish.com.
+patolinx.files.wordpress.com.
+www.empleosh.co.
+www.facebook.com.
+s-static.ak.fbcdn.net.
+a.root-servers.net.
+google.com.
+fr-fr.facebook.com.
+sky.766.com.
+photos-c.ak.facebook.com.edgesuite.net.
+i2.ytimg.com.
+bing.com.
+bluelaguna.net.
+files.myopera.com.
+mail.thethinkpad.com.
+s2.youtube.com.
+a.root-servers.net.
+mail.foxrunorchardpark.com.
+ads.tlvmedia.com.
+125.53.54.85.in-addr.arpa.
+cdn.thefreshxpress.com.
+photos-e.ak.fbcdn.net.
+plus.google.com.
+dc341.4shared.com.
+perumusic-entreteiment.blogspot.com.
+twitter.com.
+www.birdclipart.com.
+www.google.com.
+a.root-servers.net.
+a6.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+121.245.19.204.in-addr.arpa.
+www.adobe.com.
+waterworth.org.uk.
+ad.clickotmedia.com.
+sport1hbl.neopoly.com.
+40.34.254.165.in-addr.arpa.
+platform.twitter.com.
+mail.topshelf-construction.com.
+craftworkinc.com.inbound15.mxlogic.net.
+8kcj2ge41.36hi.
+119.49.87.121.in-addr.arpa.
+www.laiting.com.
+www.fjx.co.jp.
+a.root-servers.net.
+accounts.google.com.
+polaris.vo.llnwd.net.
+books.google.com.
+mvcdmirror.webasyst.net.
+cdn.rockyou.com.
+schoedon.nl.
+mx.mg4.mail.yahoo.com.
+a.root-servers.net.
+mail.realprof.ru.
+runic.ru.
+www.recettes-de-cuisine-de-chef.fr.
+photos-b.ak.fbcdn.net.
+a.espncdn.com.
+haring.com.
+wzipkkjry.z22o1s3b.
+www.sikharchives.com.
+foreverwrap.net.
+o1.t26.net.
+www.facebook.com.
+250.10.134.189.in-addr.arpa.
+titofilm.com.
+static.ak.fbcdn.net.
+historia-sf.blogspot.com.
+160.31.152.189.in-addr.arpa.
+a.root-servers.net.
+www.fictionratings.com.
+www.library.mohdy.com.
+e-olam.com.
+ihiar9aj:.45rx.
+drainc.net.
+ja.wikipedia.org.
+jazzartistas.com.
+226.95.18.190.in-addr.arpa.
+external.ak.fbcdn.net.
+97.214.188.189.in-addr.arpa.
+nexdimension.net.
+i3.ytimg.com.
+a.root-servers.net.
+www.shiloh-fernandez.com.
+pt-br.facebook.com.
+dc417.4shared.com.
+14.249.122.84.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+ecom.be.
+www.myriahsbazaar.com.
+k4:7jxg9m.t76l9a0e.
+174.26.34.156.in-addr.arpa.
+phox.de.
+www.msn.com.
+d2060676.instant.xoom.it.
+ae.adserver.yahoo.com.
+dns.msftncsi.com.
+a.root-servers.net.
+bbswefong.myweb.hinet.net.
+153.127.4.31.in-addr.arpa.
+mail.airschool.ru.
+content.yieldmanager.edgesuite.net.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+html.rincondelvago.com.
+242.47.137.190.in-addr.arpa.
+169.36.80.69.in-addr.arpa.
+banners.point2.com.
+a.root-servers.net.
+212.242.142.187.in-addr.arpa.
+www.google.com.
+www.facebook.com.
+ntp1.dlink.com.
+6tsgsc1y7.78ct.
+www.youtube-nocookie.com.
+217.124.93.178.in-addr.arpa.
+mail.production-systems.com.
+profile.ak.fbcdn.net.
+125.134.255.201.in-addr.arpa.
+youtube-global.blogspot.com.
+www.msftncsi.com.
+www.reunion-parcnational.fr.
+cdn.api.twitter.com.
+static2.shufuni.com.
+35.154.165.83.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.aljahraa.com.
+l.yimg.com.
+210.53.176.190.in-addr.arpa.
+transfer.ivwbox.de.
+api-read.facebook.com.
+blogergadgets.googlecode.com.
+www.linkedin.com.
+m.google.com.
+mozilla.cdn.leaseweb.com.
+adserver.adtechus.com.
+shirgie-story.blogspot.com.
+243.13.53.186.in-addr.arpa.
+search.yahoo.com.
+209.185.204.112.in-addr.arpa.
+212.209.32.174.in-addr.arpa.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.rhythmism.com.
+montreal.stepbystep.com.
+220.78.167.78.in-addr.arpa.
+www.joomfactory.com.
+127.75.163.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.youtube.com.
+s0.2mdn.net.
+www.facebook.com.
+a1650.g.akamai.net.
+mx02.realvestcorp.com.
+buyback.letsbuy.com.
+board.u18chan.com.
+a6.sphotos.ak.fbcdn.net.
+pfifilter.com.
+imguser.pandora.tv.
+flamenco.com.
+gfx1.hotmail.com.
+qlibykkydx.info.
+www.hydroasis.com.
+t.co.
+south-park-super-mario-bros.softonic.com.
+63.131.144.189.in-addr.arpa.
+www.italiannis.com.
+akteamsters.com.s8a1.psmtp.com.
+wwwimages.adobe.com.
+www.nightmarefactory.com.
+98.50.224.88.in-addr.arpa.
+ut5.xhamster.com.
+static.ak.fbcdn.net.
+a1343.phobos.apple.com.edgesuite.net.
+webeffective.keynote.com.
+clipartspot.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+209.154.86.201.in-addr.arpa.
+www.google.com.
+mail1.sig.com.
+mp3muffin.com.
+waps.net.
+hi-in.facebook.com.
+0123456789nonexistent.corn.
+lindsayhuffman.tumblr.com.
+clients1.google.com.
+photos-e.ak.fbcdn.net.
+www.bhbenz.com.
+www.cheapcoachmall.com.
+photos-c.ak.fbcdn.net.
+www.google.com.
+ocsp.thawte.com.
+csscript.com.
+trinitycatering.com.inbound10.mxlogicmx.net.
+config.acc.sogou.com.
+petshop.teamlava.com.
+photos-a.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+www.update.microsoft.com.
+111.251.113.186.in-addr.arpa.
+accountservices.msn.com.
+55.44.100.190.in-addr.arpa.
+222.125.69.190.in-addr.arpa.
+pagesinxt.com.
+126.0.202.87.in-addr.arpa.
+atenas-librosyenciclopedias.espacioblog.com.
+ukravto.kiev.ua.
+db._dns-sd._udp.0.234.168.192.in-addr.arpa.
+p15-buy.itunes.apple.com.
+photos2.hi5.com.
+216.199.182.189.in-addr.arpa.
+external.ak.fbcdn.net.
+woho-nails.blogspot.com.
+z8bt1wxv4.y35c9z6g.
+chromejs.s3.amazonaws.com.
+www.lingeriebbwtgp.com.
+a6.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+www.cristoparalasnaciones.com.
+ema-2009.mtvnimages.com.
+checkip.dyndns.org.
+www.amateurdumper.com.
+mariaeugeniasandin.blogspot.com.
+herring.south-west-water.co.uk.
+tag.admeld.com.
+www.elnuevodiario.com.ni.
+www.supercars.com.
+60.255.253.77.in-addr.arpa.
+www.bywifi.com.
+tuvlnqzjy.75nq.
+253.99.52.186.in-addr.arpa.
+106.255.34.177.in-addr.arpa.
+pathofgrowth.altervista.org.
+vwebhost.com.
+i4.ytimg.com.
+201.62.159.189.in-addr.arpa.
+ads.smowtion.com.
+s02.s3c.es.
+ve.starmedia.com.
+249.77.3.181.in-addr.arpa.
+alias.cyberpass.net.
+khairul-syahir.com.
+connect.facebook.net.
+connect.facebook.net.
+www.google.com.
+webassets3.sparkybee.com.
+netusa1.net.
+c.atdmt.com.
+code.jquery.com.
+google.com.
+platform.twitter.com.
+www.abchoy.com.ar.
+www.flasharcade.com.
+a2.sphotos.ak.fbcdn.net.
+181.9.23.67.zen.spamhaus.org.
+cn1.kaboodle.com.
+www.facebook.com.
+a.root-servers.net.
+promoscopio.com.
+im10.gulfup.com.
+api.search.us-west-1.iminent.com.
+www.derechoteca.com.
+photos-e.ak.fbcdn.net.
+s.mobclix.com.
+a.root-servers.net.
+tr.y8.com.
+api.twitter.com.
+www.addonsnetwork.com.
+client-software.real.com.
+s.youtube.com.
+www.iamburaot.com.
+wellfed.net.
+teredo.ipv6.microsoft.com.
+ac2farm.ign.com.
+136.198.242.201.in-addr.arpa.
+auersteel.com.s7a2.psmtp.com.
+static.ak.fbcdn.net.
+a.root-servers.net.
+toolbar.skype.com.
+www.facebook.com.
+www.facebook.com.
+graph.facebook.com.
+wooff1.com.
+edge.quantserve.com.
+musicaserver5.info.
+img.mediaplex.com.
+fbcdn-profile-a.akamaihd.net.
+233.16.61.128.in-addr.arpa.
+static.ak.fbcdn.net.
+a.root-servers.net.
+www.google-analytics.com.
+a.root-servers.net.
+casa.univision.com.
+www.consejodehombresbuenos.es.
+worldofbraiding.wordpress.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+emptydream.tistory.com.
+usd.de.fx-exchange.com.
+www.facebook.com.
+uvuhwxanqn.com.
+_954_98_1.
+www.gstatic.com.
+firststringent.com.
+photos-f.ak.fbcdn.net.
+vcs2.msg.yahoo.com.
+www.body-perfect-fitness.com.
+u20.eset.com.
+nray.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+counter.yadro.ru.
+loading321.com.
+www.youtube.
+blogdelectoescritura.blogspot.com.
+136.158.48.65.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+img-cdn.mediaplex.com.
+a4.da1.akamai.net.
+salud.latam.msn.com.
+i3.ytimg.com.
+apis.google.com.
+i2.ytimg.com.
+www.bizar-media.com.
+dtboot.orbitdownloader.com.
+b-0.19-a3008089.11481.1518.19d4.3ea1.210.0.lrvg7fljw5s2ze5phskpfk98jb.avqs.mcafee.com.
+livefiles19.vo.msecnd.net.
+44.195.117.121.in-addr.arpa.
+s1-word-edit.vo.msecnd.net.
+60.11.11.186.in-addr.arpa.
+mx3.axiomainc.com.
+time.nist.gov.
+hif.wikipedia.org.
+mi.hsbc.com.hk.
+b.scorecardresearch.com.
+mail.elbosco.ru.
+www.trouvelamour.com.
+usoakf01.pr-ury.pr-rcsa.org.
+benefitcorp.com.mx3.viyu.rcimx.net.
+encheres.nouvelles-frontieres.fr.
+sports.gaeatimes.com.
+sz4.tencent.com.
+by153w.bay153.mail.live.com.
+www.googleadservices.com.
+v3.lscache5.googlevideo.com.
+www.facebook.com.
+fbcdn-sphotos-a.akamaihd.net.
+qzone-music.qq.com.
+www.breakeven.org.
+a1092.g.akamai.net.
+mta6.am0.yahoodns.net.
+rmgelectrical.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.crazywisdomthemovie.com.
+www.slate.com.
+mijuchipila.com.
+238.191.236.77.in-addr.arpa.
+facial-neuralgia.org.
+www.googleadservices.com.
+118.158.13.189.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+um14.eset.com.
+ppp85-140-31-73.pppoe.mtu-net.ru.
+194.231.90.74.in-addr.arpa.
+download.windowsupdate.com.
+margu5.galeon.com.
+dasolutions.us.
+www9.effectivemeasure.net.
+prod.rest-core.msg.yahoo.com.
+www.moneyville.ca.
+mobileage.com.
+i4.ytimg.com.
+www.google-analytics.com.
+i4.tagstat.com.
+s-static.ak.fbcdn.net.
+sakura.japanphilly.org.
+agestado.com.br.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+musifthiasno.tm.
+109.40.237.189.in-addr.arpa.
+www.youtube.com.
+a.root-servers.net.
+www.noticias-de-hoy.com.
+conquistar-al-hombre.info.
+www.luerzersarchive.net.
+136.45.128.189.in-addr.arpa.
+mail.ci.lynn.ma.us.
+3g.quick.com.
+i4.ytimg.com.
+photos-b.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+giglogo.com.
+113.72.219.201.in-addr.arpa.
+www.strengthcoach.com.
+websitesmakeover.com.
+www.google-analytics.com.
+www.cuc.edu.co.
+tinyurl.com.
+smtp.electricpenis.com.
+plusone.google.com.
+pioneerbuildersinc.com.
+fr.wikinews.org.
+125.132.205.190.in-addr.arpa.
+160.107.201.190.in-addr.arpa.
+10.112.46.196.in-addr.arpa.
+167.32.1.181.in-addr.arpa.
+www.facebook.com.
+15.209.19.186.in-addr.arpa.
+www.dvdvideosoft.com.
+sns.nskes.ru.
+174.0.159.189.in-addr.arpa.
+db._dns-sd._udp.0.10.168.192.in-addr.arpa.
+www.mercurytheatre.info.
+api.facebook.com.
+73.234.130.41.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+spam.dixie.edu.
+google.com.
+csi.gstatic.com.
+my248nqay.l83x5m5n.
+thunder-nba.com.
+adedy.com.
+graph.facebook.com.
+diana.dti.ne.jp.
+559.coll.ning.com.
+a771.da1.akamai.net.
+168.8.31.88.in-addr.arpa.
+niaeeq.com.
+177.8.41.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+dingtao333.3322.org.
+h1.flashvortex.com.
+s.youtube.com.
+inbound.thepentadgroup.com.netsolmail.net.
+a.root-servers.net.
+didier.longueville.free.fr.
+mundomatematicas.blogspot.com.
+tdandh.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+twitter.com.
+www.downloadhelper.net.
+aol.com.
+21.45.4.186.in-addr.arpa.
+sb-ssl.google.com.
+circavintageclothing.com.au.
+a3.sphotos.ak.fbcdn.net.
+chronicleholic.wordpress.com.
+239.2.30.186.in-addr.arpa.
+a1.mzstatic.com.
+subwaynw.com.
+a.root-servers.net.
+bayertechnology.com.
+fxfeeds.mozilla.com.
+_594_48_2.
+a995.mm1.akamai.net.
+a3.sphotos.ak.fbcdn.net.
+www.googleadservices.com.
+176.203.239.189.in-addr.arpa.
+41.158.220.66.in-addr.arpa.
+i2.ytimg.com.
+166.100.79.189.in-addr.arpa.
+70.83.101.189.in-addr.arpa.
+connect.facebook.net.
+14.174.210.201.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.yousaytoo.com.
+redir.uol.com.br.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+76.153.231.67.in-addr.arpa.
+www.dish.com.mx.
+a.root-servers.net.
+mail.abodehome.com.
+iveracity.com.
+teredo.ipv6.microsoft.com.
+167.36.153.24.in-addr.arpa.
+sr01-sf02.stratixcorp.com.
+118.4.93.186.in-addr.arpa.
+www.carsampaf.org.
+ar.myspace.com.
+www.bing.com.
+smtp3.intermedia.net.
+zzkn5k1t9.80eg.
+cgw.download.nokia.com.
+sapopositivevibes.podomatic.com.
+185.122.250.190.in-addr.arpa.
+kayros.com.ar.
+translate.googleapis.com.
+p0b.ru.
+ads1.msads.net.
+18.128.135.117.in-addr.arpa.
+60.210.129.186.in-addr.arpa.
+feeds.bbci.co.uk.
+safebrowsing-cache.google.com.
+teredo.ipv6.microsoft.com.
+s10.histats.com.
+137.35.138.220.in-addr.arpa.
+ca.idoget.me.
+geogebreando.blogspot.com.
+agromex.de.
+i.w55c.net.
+195.212.139.98.dnsbl.sorbs.net.
+2cb3g5w24.j01g2r7u.
+safebrowsing-cache.google.com.
+diccionario.babylon.com.
+acercadeorange.orange.es.
+rainhaecuckold.blogspot.com.
+fbcdn-photos-a.akamaihd.net.
+pop001.masterhost.ru.
+photos-e.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+2.pool.ntp.org.
+www.dogtipper.com.
+www.auditionsfinder.com.
+67.139.210.201.in-addr.arpa.
+a1764.phobos.apple.com.
+www.startopnews.com.
+194.29.95.201.in-addr.arpa.
+b.scorecardresearch.com.
+encinerados.blogspot.com.
+1.bp.blogspot.com.
+www.jamacareercenter.com.
+terralliance.com.2.0001.arsmtp.com.
+233.63.170.201.in-addr.arpa.
+a998.mm1.akamai.net.
+iphone-ld.apple.com.
+datatrakpharmaceuticals.com.
+paperwise.com.1.0001.arsmtp.com.
+briz.com.ru.
+www.dahotre.com.
+_389_87_1.
+a.root-servers.net.
+wpad.
+sinbad.se.
+mailgate1.royalchacehotel.co.uk.
+central.cardomain.com.
+suggest.infospace.com.
+www.hardsextube.com.
+apps.facebook.com.
+google.com.
+www.facebook.com.
+31.167.252.190.in-addr.arpa.
+a1.s6img.com.
+profile.ak.fbcdn.net.
+rbsmail.rutgers.edu.
+ijet.com.
+www.casinoesdinero.com.
+9to5mac.com.
+pjgitnik.com.
+www.edsitement.neh.gov.
+caserver.china.huawei.com.
+s1-excel.vo.msecnd.net.
+developers.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+evsecure-ocsp.verisign.com.
+inbound.prix.com.netsolmail.net.
+search.twitter.com.
+streetlegal.co.uk.
+sites.google.com.
+www.blogger.com.
+socpixel.bidsystem.com.
+ticker.conduit.com.
+unb.ca.
+185.215.52.186.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+r._dns-sd._udp.lan.
+facemoods.com.
+www.google.com.
+antiplaneta.ru.
+qorpak.com.s7a2.psmtp.com.
+twitter.com.
+22flowavenue.com.
+konntiwa.ranks1.apserver.net.
+secure.smflorida.com.
+digitaldatatrust.com.
+174.250.102.201.in-addr.arpa.
+148.88.92.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.google-analytics.com.
+89.168.184.111.in-addr.arpa.
+44.28.138.187.in-addr.arpa.
+jameique.com.
+d2102520.xoom.it.
+powerclip.ru.
+a1404.w41.akamai.net.
+www.michalkotek.com.
+160.225.42.177.in-addr.arpa.
+thebrothersz.com.
+photos-g.ak.fbcdn.net.
+dns.msftncsi.com.
+foro.naruto-fans.net.
+12.224.171.69.in-addr.arpa.
+it-it.facebook.com.
+bios-repair.co.uk.
+ads2.msads.net.
+profile.ak.fbcdn.net.
+s.youtube.com.
+www.konami-pes2011.com.
+www.facebook.com.
+www.gaybcn.com.ar.
+maslibres.org.
+tools.google.com.
+tucodigo.mx.
+mothernewyork.com.
+khm1.google.com.
+76.143.140.190.in-addr.arpa.
+omp1057.mail.ne1.yahoo.com.
+.
+www.jamestaylor.com.
+i2.ytimg.com.
+a3.da1.akamai.net.
+evsecure-ocsp.verisign.com.
+www.dietpillrating.com.
+time.chttl.com.tw.
+dl.qt.nokia.com.
+aserver.jp.ru.
+www.facebook.com.
+img.mexat.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+110.106.53.75.in-addr.arpa.
+www.update.microsoft.com.
+update.wildtangent.com.
+76.216.152.85.in-addr.arpa.
+agebottom.com.
+www.google.com.
+211.2.0.192.in-addr.arpa.
+124.89.156.189.in-addr.arpa.
+pixel.quantserve.com.
+a6.sphotos.ak.fbcdn.net.
+landing.widdit.com.
+vaughanrealtors.com.
+evsecure-crl.verisign.com.
+kdc.uas.aol.com.
+damagents.com.inbound30.mxlogicmx.net.
+developers.facebook.com.
+api.conduit.com.
+umfa.ca.
+photos-h.ak.fbcdn.net.
+rz4:eo8vt.i20i9r3a.
+p.twimg.com.
+hotmail.com.
+pop3.live.com.
+146.208.94.190.in-addr.arpa.
+haptonstahl.org.
+s-static.ak.fbcdn.net.
+ar-ar.facebook.com.
+136.86.163.189.in-addr.arpa.
+voipb.sip.yahoo.com.
+remote.wras.co.uk.
+1zioube8g.24kh.
+tw8:u6nq7.92bj.
+cust20020-2.in.mailcontrol.com.
+mail.crwf.com.
+76.37.89.83.in-addr.arpa.
+77.8.181.186.in-addr.arpa.
+www.google.com.
+cs11261.vk.com.
+simages.artofthetrench.com.
+data.flurry.com.
+sitesbrasil.com.
+149.96.155.81.in-addr.arpa.
+i3.ytimg.com.
+2.75.150.201.in-addr.arpa.
+5.61.50.190.in-addr.arpa.
+www.google.com.
+mail.pcisynthesis.com.
+photos-d.ak.fbcdn.net.
+100.146.220.66.in-addr.arpa.
+242.67.42.24.in-addr.arpa.
+mail2.endosolutions.net.
+a7.sphotos.ak.fbcdn.net.
+1xbzfvc1l.p34f1h4z.
+cs11125.vk.com.
+www.sfdi.com.
+shop.lenovo.com.
+itunes.apple.com.
+static.pkt.pl.
+fuller-ve.com.
+fotos.videochaterotico.com.
+www.songstraducidas.com.
+img1.blogblog.com.
+siteground160.com.
+ma90-r.analytics.edgesuite.net.
+static.ak.fbcdn.net.
+www.foxsportsla.com.
+gab2.sub.ru.
+8.65.173.190.in-addr.arpa.
+www.hupo.com.
+tracker.publicbt.com.
+forums.land-and-sea.com.
+www.trigosubs.org.
+www.editorial.udg.mx.
+th822.photobucket.com.
+www.leadershipdigital.com.
+benefitmall.com.s7a2.psmtp.com.
+pixel.rubiconproject.com.
+kayser-photography.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+jewelry-and-watches.become.com.
+www.google.com.
+www.satakore.com.
+plus.google.com.
+rec.eprice.it.
+grics.net.
+rs39tl2.rapidshare.com.
+photos-e.ak.fbcdn.net.
+www.nintendo.it.
+a.root-servers.net.
+cdn.fastclick.net.
+167.180.236.81.in-addr.arpa.
+blogverde.com.
+marmidicarrara.com.
+www.plusnetwork.com.
+nissan-avtogrand.ru.
+226.216.139.189.in-addr.arpa.
+dns.msftncsi.com.
+www.musicboxtheatre.com.
+18.98.205.190.in-addr.arpa.
+static.ak.fbcdn.net.
+hotmail.com.
+www.nemosvjerovat.com.
+itunes.apple.com.
+graph.facebook.com.
+profile.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+39.180.250.88.in-addr.arpa.
+www.silverpricepergram.net.
+a1.mzstatic.com.
+thriftmeblog.com.
+www.chemicalelements.com.
+profile.ak.fbcdn.net.
+liveupdate.symantecliveupdate.com.
+photos-f.ak.fbcdn.net.
+mail7.digitalwaves.co.nz.
+bigwheels.ru.
+get.adobe.com.
+mt0.google.com.
+google.com.
+cs5103.vkontakte.ru.
+inca.com.
+183.172.191.186.in-addr.arpa.
+www.imdb.com.
+lakhanijordan.com.2.0001.arsmtp.com.
+www.bajadvd.com.
+sip.gmail.com.
+wext.ru.
+droidexpyoudroid.appspot.com.
+a8.sphotos.ak.fbcdn.net.
+mail.appframeworks.com.
+liveupdate.symantecliveupdate.com.
+video.google.com.mx.
+88.31.119.177.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+199.140.175.187.in-addr.arpa.
+perlasdelfutbol.blogspot.com.
+pixel.facebook.com.
+www.classicmarry.com.
+carica.com.
+external.ak.fbcdn.net.
+mail.propanecentral.com.
+www.fundacionorange.es.
+www.cadeus.blogspot.com.
+a.root-servers.net.
+www.betajeux.com.
+www.specwarnet.net.
+partner.googleadservices.com.
+stats.qalabs.symantec.com.
+www.nicso.com.ar.
+static.ak.fbcdn.net.
+www.fmoriente.com.ar.
+d15be99dzjsmyn.cloudfront.net.
+www.camlive.com.
+help.vestax.co.jp.
+dns.msftncsi.com.
+mail.kazan-n.ru.
+dns.msftncsi.com.
+triplexqueens.wordpress.com.
+content.yieldmanager.edgesuite.net.
+crl.microsoft.com.
+cookex.amp.gapx.yahoodns.net.
+www.facebook.com.
+1.gravatar.com.
+google.com.mx.
+safebrowsing-cache.google.com.
+www.bucorp.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+connect.facebook.net.
+sp.cwfservice.net.
+au.download.windowsupdate.com.
+www.google.com.
+photos-e.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+o1.t26.net.
+kworp:25z.32gt.
+a5.sphotos.ak.fbcdn.net.
+norsk-data.com.
+a2.sphotos.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+cdngw.ustream.tv.
+mail.employeeconnect.com.
+cnfg.toolbarservices.com.
+a.root-servers.net.
+q1byqqepe.r48x2g9y.
+ads.adtiger.de.
+s.ytimg.com.
+tpb.tracker.thepiratebay.org.
+static.ak.fbcdn.net.
+www.facebook.com.
+teredo.ipv6.microsoft.com.
+197.68.7.189.in-addr.arpa.
+65.61.166.184.in-addr.arpa.
+a.ads2.msads.net.
+googleads.g.doubleclick.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+db._dns-sd._udp.lan.
+9.4.79.190.in-addr.arpa.
+s7.chatango.com.
+mx.ekipage.sp.ru.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+smtp3.masergy.com.
+compassgroup-nad.com.
+maps.google.com.
+gmmxc.imr.gm.com.
+hipay.com.
+85.192.185.93.in-addr.arpa.
+mx.studiolegalemarzano.com.
+www.imss.gob.mx.
+www.risk.net.
+orcart.facebook.com.
+branco.com.s9b1.psmtp.com.
+i2.ytimg.com.
+siteslegais.com.
+atomic-vfx.com.
+128.186.183.88.in-addr.arpa.
+widgets.amung.us.
+91.169.120.186.in-addr.arpa.
+_492_16_1.
+profile.ak.fbcdn.net.
+gol.grosseto.it.
+139.195.152.190.in-addr.arpa.
+autos.yahoo.com.
+32.171.160.187.in-addr.arpa.
+cdn.toolstation.com.
+maestrodelacomputacion.blogspot.com.
+timmsmot.freeserve.co.uk.
+65.227.193.190.in-addr.arpa.
+digsin.com.
+fjpoemas.soopbook.es.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+mail4.emagister.com.
+204.76.44.187.in-addr.arpa.
+portugaltradicionalista.blogspot.com.
+bluelfs.files.wordpress.com.
+photos-f.ak.fbcdn.net.
+divxrepair.softonic.com.
+www.google.com.
+a1513.oadz.com.
+98b7nkh7s.h49e5t6e.
+uniqsolutions.ru.
+gdata.youtube.com.
+photos-g.ak.fbcdn.net.
+av1.ibm.com.
+csi.gstatic.com.
+www.setbook.org.
+picasaweb.google.com.
+assets3.castle.zgncdn.com.
+a1402.w40.akamai.net.
+static.adsender.us.
+ksn1-11-part1.kaspersky-labs.com.
+84.87.17.190.in-addr.arpa.
+www.biglinks.com.br.
+notify3.dropbox.com.
+choose-language.ru.
+www.facebook.com.
+instagr.am.
+hylinecruises.com.s7a1.psmtp.com.
+mechel-bank-msk.ru.
+a1726.b.akamai.net.
+59.98.170.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.gamecompare.com.
+42.90.233.213.in-addr.arpa.
+92.12.52.186.in-addr.arpa.
+xxzgfpxn8.25xx.
+safebrowsing-cache.google.com.
+sport.se.msn.com.
+netflix360.pop3.la.nflximg.com.edgesuite.net.
+vitoria.campusanuncios.com.
+www.sensible.com.
+medimax.org.
+nats.seemybucks.com.
+sp.cwfservice.net.
+a.root-servers.net.
+nikita.dod.ru.
+utm9.apn.ask.com.
+172.2.35.174.in-addr.arpa.
+ads.intergi.com.
+api.twitter.com.
+static.ak.fbcdn.net.
+www.lynxeffect.com.
+photos-h.ak.fbcdn.net.
+cdn59.atkingdom-network.com.
+177.195.18.186.in-addr.arpa.
+ssl.gstatic.com.
+a995.mm1.akamai.net.
+147.100.205.112.in-addr.arpa.
+osterdowjones.net.
+o.xbox.com.
+protk.com.inbound15.mxlogic.net.
+76.208.30.50.in-addr.arpa.
+alliance1.com.
+developers.facebook.com.
+melodi.ru.
+secureninja.com.
+udg.com.
+247.104.9.177.in-addr.arpa.
+ad.doubleclick.net.
+mail2.andreevsoft.ru.
+www.belkin.com.
+photos-a.ak.fbcdn.net.
+ohxasi.com.
+www.facebook.com.
+lh3.ggpht.com.
+7368656c6c.77696e646f7773.636f6d.80h4137e259.webcfs00.com.
+tracker.istole.it.
+www.seuatdigital.edu.mx.
+ksn2-12.kaspersky-labs.com.
+254.1.253.201.in-addr.arpa.
+ads.wicked.com.
+146.43.174.190.in-addr.arpa.
+tomclemente.com.
+_836_16_7.
+109.229.2.173.in-addr.arpa.
+googleads.g.doubleclick.net.
+morehod.com.
+cathotmail.com.
+hotguitarist.com.
+p0b.ru.
+www.halosweet.com.
+35.92.249.77.in-addr.arpa.
+www.bitbest.ru.
+mail.reefdevelopment.com.
+static3.educaedu.com.mx.
+129.129.140.189.in-addr.arpa.
+adwhirllb-473732162.us-east-1.elb.amazonaws.com.
+5.64.112.189.in-addr.arpa.
+www.dragonflygame.com.
+33.50.169.118.in-addr.arpa.
+www.fanfarlo.com.
+sp.cwfservice.net.
+mgb.minutebuzz.com.
+img1.imagilive.com.
+224.241.191.89.in-addr.arpa.
+profile.ak.fbcdn.net.
+pixel.facebook.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+ar.voicefive.com.
+karen.
+www.sitc.ru.
+164.60.0.10.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+www.bookclub.kodansha.co.jp.
+217.224.48.60.in-addr.arpa.
+emirnewusenglish.112.2o7.net.
+eslprintables.ourtoolbar.com.
+support.google.com.
+222.206.195.187.in-addr.arpa.
+172.77.37.46.in-addr.arpa.
+ebookbrowse.com.
+8.153.190.186.in-addr.arpa.
+183.122.5.181.in-addr.arpa.
+clients.sidesmedia.com.
+urs.microsoft.com.
+scfafsbfs.com.
+monsterone.netease.net.
+zh-cn.facebook.com.
+tracker21.970dbf83-5db6-4e8f-9c50-678fcc4b29a3.automated.snxd.com.
+www.pelislatino.com.
+a.root-servers.net.
+ajax.googleapis.com.
+226.139.101.187.in-addr.arpa.
+mail.lordflex.com.
+yoghismo.org.
+preppyplayer.blogspot.com.
+teredo.ipv6.microsoft.com.
+inbound.cai-value.com.netsolmail.net.
+mail.eoffice-virtualassist.com.
+www.autopenhosting.org.
+www.adobe.com.
+www.stopusa.be.
+www.hotelnjoy.com.
+blackstartube.com.
+yahoo.com.
+www.rugby.invescoperpetual.co.uk.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+theeconomist.com.
+www.musica-online.org.
+hi-in.facebook.com.
+126.213.11.109.in-addr.arpa.
+www.xtoolspro.com.
+a1.da1.akamai.net.
+80.89.145.64.in-addr.arpa.
+www.vocibo.com.
+im2.b.qq.com.
+a8.sphotos.ak.fbcdn.net.
+58.129.6.189.in-addr.arpa.
+plusone.google.com.
+multistreaminghost.com.
+sn1msg1010831.gateway.messenger.live.com.
+www.tagorormusic.com.
+mail.impauto.com.
+wron.net.
+youtu.be.
+i-69ee300c.us-east-1b.service.amazonsilk.com.
+sender1.critsend.com.
+a8.sphotos.ak.fbcdn.net.
+158.23.130.181.in-addr.arpa.
+rpc.ant.com.
+api.nanigans.com.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+gimp.nl.softonic.com.
+accugenix.com.
+btopenworld.com.
+s0.2mdn.net.
+www.crocschile.cl.
+arstravelgroup.com.
+d2094296.xoom.it.
+a.tribalfusion.com.
+www.periodistasenlinea.org.
+ib.adnxs.com.
+www.alquz.com.
+safebrowsing-cache.google.com.
+lagrimasdescarcha.blogspot.com.
+horsemart.co.uk.
+gmail.com.
+0.11-a30f6081.80410b1.1518.19d4.3ea1.410.0.61kaku9epkicp1kh283n94tccv.avqs.mcafee.com.
+photos-h.ak.fbcdn.net.
+www.google-analytics.com.
+s.youtube.com.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+games.metaservices.microsoft.com.
+www.html.am.
+8888123.com.
+tlk.tc.
+mp3magic.ru.
+api.bing.com.
+static3.carsablanca.de.
+time.windows.com.
+53.107.170.189.in-addr.arpa.
+254.55.153.81.in-addr.arpa.
+242.175.28.187.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+www.turtlemax.com.
+otcopymadrid.wordpress.com.
+90.23.191.186.in-addr.arpa.
+blu.stj.s-msn.com.
+profiles.google.com.
+48-courier.push.apple.com.
+freelaptops4you.net.
+59.115.36.186.in-addr.arpa.
+www.guittard.com.
+api.search.iminent.com.
+touch.facebook.com.
+infoterra.com.
+profile.ak.fbcdn.net.
+beacon.shazam.com.
+rustel.ru.
+creative.ak.fbcdn.net.
+flyvar28.33x.com.
+ajax.googleapis.com.
+ksn2-12.kaspersky-labs.com.
+www.postcardchess.com.
+es.answers.yahoo.com.
+apps.facebook.com.
+evsecure-crl.verisign.com.
+tractors.com.sg.
+c1.softonicads.com.
+pixel.facebook.com.
+feldchevrolet.com.
+168.12.56.188.in-addr.arpa.
+wweenvivo.com.mx.
+64.189.59.186.in-addr.arpa.
+www.iegallery.com.
+photos-a.ak.fbcdn.net.
+p07-keyvalueservice.icloud.com.
+apps.skype.com.
+a8.sphotos.ak.fbcdn.net.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+147.9.165.189.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+www.expertosensalarios.com.
+plus.google.com.
+119.22.254.201.in-addr.arpa.
+172.93.48.190.in-addr.arpa.
+s1-excel.vo.msecnd.net.
+fbcdn-profile-a.akamaihd.net.
+a.rad.msn.com.
+articulosinformativos.com.mx.
+developers.facebook.com.
+notepad2.en.softonic.com.
+canvasli.com.
+www.facebook.com.
+mail.avrupaholding.com.tr.
+www.igaymobile.com.
+zpay.static.zynga.com.
+kick.com.
+mx.yahoo.com.
+photos.end.com.ni.
+ads5.speedbit.com.
+gorna.net.
+polar.dyndns.tv.
+daricemichelle.com.
+www.sumospeed.com.
+www.aroundphilly.com.
+189.142.149.189.in-addr.arpa.
+75.28.168.192.in-addr.arpa.
+www.tumejorindirecta.com.
+servizi.tiscali.it.
+assets2.castle.zgncdn.com.
+a5.sphotos.ak.fbcdn.net.
+134.16.132.187.in-addr.arpa.
+www.lesbuan.com.
+215.19.113.187.in-addr.arpa.
+nextel.tv.
+ie9cvlist.ie.microsoft.com.
+www.metropolisweddingdress.com.
+me1sifs30001.unilever.com.
+42.204.15.187.in-addr.arpa.
+194.176.22.190.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.kat.ph.
+yahoo.co.uk.
+api.yontoo.com.
+profile.ak.fbcdn.net.
+www.riegl.com.
+bizarringa.blogspot.com.
+217.163.139.110.in-addr.arpa.
+adtech.habbo.com.
+165.60.168.200.in-addr.arpa.
+local.
+www.ntteuropeonline.es.
+bcmls2.glpals.com.
+kimmymanga.deviantart.com.
+weldstar.com.
+eq.leadtrks.com.
+idols-rock.blogspot.com.
+pollstar.com.
+www.visjonnorge.com.
+www.dinsdoc.com.
+www.facebook.com.
+dns.msftncsi.com.
+connect.facebook.net.
+www.viacom.com.
+platform.twitter.com.
+180.97.0.190.in-addr.arpa.
+info-depresion.blogspot.com.
+invisiblemente.blogspot.com.
+www.facebook.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+deimagenesnaruto.blogspot.com.
+ad-g.doubleclick.net.
+t3.gstatic.com.
+google.com.mx.
+connect.facebook.net.
+www.revista-wicca.com.ar.
+a.root-servers.net.
+tap.rubiconproject.com.
+www.facebook.com.
+photos-b.ak.fbcdn.net.
+www.papelenblanco.com.
+nopalinaeuropa.com.
+notaria93.com.
+fourstaradvertising.com.
+www.google.com.
+login.bearshare.com.
+sec-consulting.com.
+130.108.182.175.in-addr.arpa.
+a.root-servers.net.
+maps.l.google.com.
+enpathmedical.com.
+cxi1asjvv.87iq.
+a-0.19-3109e001.a040082.1518.19d3.36d4.210.0.nhhqd33j1qiwjll937r7qq7acv.avqs.mcafee.com.
+a.root-servers.net.
+searchclient.live.net.
+audibleuk.tt.omtrdc.net.
+www.pbk.org.
+a17.x-traceur.com.
+www.chatcasero.com.
+zelenb.com.
+mail.communityservicescouncil.ca.
+services.tvkaista.fi.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+pixel.facebook.com.
+www.textsrv.com.
+www.arezzo.com.br.
+0-jw-w.channel.facebook.com.
+.
+253.98.224.71.in-addr.arpa.
+www.runescape-private-server.info.
+bestworldprofit.com.
+www.megacockcravers.com.
+tripadvice.ru.
+a.root-servers.net.
+215.159.0.189.in-addr.arpa.
+108.90.145.175.in-addr.arpa.
+wpad.
+profile.ak.fbcdn.net.
+196.234.132.190.in-addr.arpa.
+hotamatuermoms.com.
+103.166.131.187.in-addr.arpa.
+blackmetal.co.uk.
+www.avimont.com.
+uhzdkco1y.81th.
+classic.weezer.com.
+_643_82_0.
+boosted.com.
+67.185.164.189.in-addr.arpa.
+r13.lhr14g01.c.youtube.com.
+smtp.vallivue.org.
+safebrowsing.clients.google.com.
+rcp.na.blackberry.com.
+c.atdmt.com.
+sdafds.com.
+economia.gob.mx.
+rcxbgprpl.b58f1z0c.
+42.148.126.186.in-addr.arpa.
+108.226.82.81.in-addr.arpa.
+s7.addthis.com.
+206.14.235.123.in-addr.arpa.
+smtp.uggc.com.
+97.73.127.200.in-addr.arpa.
+canalcocina.es.
+profile.ak.fbcdn.net.
+albion.net.
+ocsp.digicert.com.
+fbcdn-photos-a.akamaihd.net.
+realtyventurecap.com.
+aebersold.ch.
+webunlp.unlp.edu.ar.
+mymodernmet.mobify.me.
+css.wlxrs.com.
+a6.sphotos.ak.fbcdn.net.
+www.outline.it.
+cercopdf.com.
+mail.wyobuilds.com.
+a.root-servers.net.
+childers-construction.com.
+games.espn.go.com.
+www.compromisorse.com.
+a1404.w41.akamai.net.
+scholar.google.com.
+mail.coralcadillac.com.
+www.stellaoflondon.co.uk.
+mail.whessoe.co.uk.
+ak-media.soundcloud.com.
+28.47.255.201.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+lensylproducts.com.s9a2.psmtp.com.
+homeserve.com.
+mail.bca.ru.
+www.aitfa.org.
+40.232.86.74.in-addr.arpa.
+www.thetoshibatablet.com.
+www.autonotel.es.
+www.ciafp.com.
+27.media.tumblr.com.
+48.100.11.190.in-addr.arpa.
+h.live.com.
+11.248.230.190.in-addr.arpa.
+alterglobalizacion.wordpress.com.
+market.android.com.
+102.243.47.189.in-addr.arpa.
+www.facebook.com.
+www.pulug.com.
+fc60.deviantart.com.
+www.koala.net.
+www.lavidasegunxime.com.
+119.217.239.201.in-addr.arpa.
+broekhuisjuweliers.nl.
+ping3.teamviewer.com.
+learningexchange.ptc.com.
+162.220.159.82.in-addr.arpa.
+www.viamujer.com.
+0.1887503.com.
+a367.phobos.apple.com.edgesuite.net.
+picasaweb.google.com.
+farm3.static.flickr.com.
+static.ak.fbcdn.net.
+hotmail.co.uk.
+antropologiadelareligion.blogspot.com.
+206.16.122.24.in-addr.arpa.
+www.einicio.com.
+fashionscandal.com.
+ads.revsci.net.
+modulstroy.ru.
+news.google.com.mx.
+creative.ak.fbcdn.net.
+234.33.88.186.in-addr.arpa.
+cache5.bbs.cn.yahoo.com.
+vf.cloud.avg.com.
+64.78.178.95.in-addr.arpa.
+watchdrama24.com.
+adm.citytlt.ru.
+clients1.google.com.
+207.236.35.177.in-addr.arpa.
+40.4.235.178.in-addr.arpa.
+cf.addthis.com.
+209.37.136.190.in-addr.arpa.
+www.apple.com.
+rjins.com.
+mail.dmlp.net.
+av-desk.ru.
+www.hellas-jet.com.
+www.hoteldeturistas.net.
+a2.sphotos.ak.fbcdn.net.
+cm.ac3.msn.com.
+ktones.us.
+20.165.32.188.in-addr.arpa.
+fstkrahwrq.org.
+photos-a.ak.fbcdn.net.
+.
+chat.facebook.com.
+212.63.33.62.in-addr.arpa.
+mntr.babcdn.com.
+lascosicasdeange.blogspot.com.
+rk:d7p136.27bn.
+www.google.com.
+172.7.127.200.in-addr.arpa.
+protaxservices.com.
+privacy.io.
+jalateqla.blogspot.com.
+es-la.facebook.com.
+golfetc.com.
+23.122.226.98.in-addr.arpa.
+119.50.74.190.in-addr.arpa.
+www.youtube.com.
+www.google-analytics.com.
+118.28.148.109.in-addr.arpa.
+canalbruselas.blogspot.com.
+accounts.google.com.
+l68dqdzmrcyj16j56pudqgup22n50iuoqmwfr.com.
+albassfed.org.
+fs579.uploading.com.
+iv:c7dnvp.s42e5m6y.
+226.151.203.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+mainonta.jatkoaika.com.
+179.40.116.99.in-addr.arpa.
+dr._dns-sd._udp.lan.
+a.root-servers.net.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+dsn1.d.skype.net.
+a7.sphotos.ak.fbcdn.net.
+bsf.smowtion.com.
+ww2.clothingshowroom.com.
+www.google.com.
+www.strengtheningmarriage.com.
+clients1.google.com.
+21.211.171.201.in-addr.arpa.
+altavista.su.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+cooksign.com.
+ads2.msads.net.
+92.158.26.46.in-addr.arpa.
+bpt.net.
+mail.imageriedigitale.com.
+graph.facebook.com.
+80.91.139.98.sa-accredit.habeas.com.
+m.facebook.com.
+smtp-gw.qti.com.
+177.13.51.190.in-addr.arpa.
+victortabernero.wordpress.com.
+www.microsoft.com.
+65.137.113.186.in-addr.arpa.
+www.aado.org.
+mgtracker.org.
+35.100.241.189.in-addr.arpa.
+i1159.photobucket.com.
+143.157.8.78.in-addr.arpa.
+nuts-and-bolts-of-cakephp.com.
+www.google-analytics.com.
+6.236.171.118.in-addr.arpa.
+platform.ak.fbcdn.net.
+specath.ru.
+a.root-servers.net.
+154.60.58.186.in-addr.arpa.
+rs742tl.rapidshare.com.
+mail.warris.com.
+ksn3-11.part1.kaspersky-labs.com.
+acumetrics-com.mail.eo.outlook.com.
+terpsys.com.
+w671.photobucket.com.
+etalon-centre.ru.
+www.stopbadware.org.
+www.femdomnirvana.com.
+s-external.ak.fbcdn.net.
+anki.ichi2.net.
+bsnav9vog.h10m0z1y.
+craneplasticsmfg.com.s5b1.psmtp.com.
+na3sys010aog103.obsmtp.com.
+ds.serving-sys.com.
+twitter.com.
+www.greenfeet.com.
+irc.kelebekmafia.com.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.google.com.
+mail.
+gnuworldorder.info.
+taxi-profi.ru.
+www.texasonline.state.tx.us.
+sea.liveatc.net.
+www.nobel.unam.mx.
+creative.ak.fbcdn.net.
+hipay.com.
+pcimagenetwork.com.
+ad.harrenmedianetwork.com.
+hotmail.com.
+www.supporter.com.
+us.data.toolbar.yahoo.com.
+clients1.google.com.
+europa.meteoconsult.es.
+dwiex402.mumc.nl.
+a-0.19-220f0001.590.1518.19d4.3ea1.410.0.261uh4tz9r79h32int7h8u92it.avqs.mcafee.com.
+agoldenworld.files.wordpress.com.
+facebook.com.
+ad.yieldmanager.com.
+www.aspeneducation.com.
+websearch.ask.com.
+a.root-servers.net.
+cityvillefb0.static.zgncdn.com.
+ad.yieldmanager.com.
+sp.cwfservice.net.
+photos-b.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+170.94.5.190.in-addr.arpa.
+akko.es.
+www.gn4me.com.
+fr-fr.facebook.com.
+392327.r.msn.com.
+es-la.facebook.com.
+www.rodatec.com.
+s0.2mdn.net.
+www.indonesiacommerce.com.
+orcart.facebook.com.
+201.1.60.68.in-addr.arpa.
+profile.ak.fbcdn.net.
+translate.google.com.mx.
+www.pokemontcg.com.
+mitchhedberg.net.
+logc214.xiti.com.
+sp.cwfservice.net.
+www.crecenegocios.com.
+127.86.21.107.in-addr.arpa.
+csc3-2004-crl.verisign.com.
+t3.gstatic.com.
+www.mediawiki.org.
+t4ft.de.
+trailw.dealply.com.
+shared.live.com.
+30.188.77.189.in-addr.arpa.
+24.15.107.76.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+173.23.255.190.in-addr.arpa.
+ox-d.appprizes.com.
+128.148.163.190.in-addr.arpa.
+86.73.43.190.in-addr.arpa.
+73.138.146.195.in-addr.arpa.
+www.markdom.de.
+xvideos-176.vo.llnwd.net.
+a.root-servers.net.
+www.groovybookmarks.com.
+65.151.59.174.in-addr.arpa.
+profile.ak.fbcdn.net.
+relay.gt66.ru.
+39.220.112.186.in-addr.arpa.
+virtualdubmod.en.softonic.com.
+zierkecompany.com.
+toolbarqueries.clients.google.com.
+csc3-2004-crl.verisign.com.
+google.com.
+s-static.ak.fbcdn.net.
+80.119.101.76.in-addr.arpa.
+developer.amazonwebservices.com.
+sms-group.net.
+www.facebook.com.
+133.80.158.79.in-addr.arpa.
+jewelleryrussia.ru.
+43.60.93.200.in-addr.arpa.
+mepunoonaker.ws.
+www.facebook.com.
+bloggergadgets.googlecode.com.
+www.as.com.
+global.wetter.com.
+a1375.g.akamai.net.
+ad.yieldmanager.com.
+www.superior-replica.com.
+ad-g.doubleclick.net.
+a.ads1.msads.net.
+mms602.whatsapp.net.
+apix.iminent.com.
+clients1.google.com.
+demsandemir.com.
+mbspares.chance.ru.
+igor.facemoods.com.
+bmx.burg-gmbh.de.
+27.16.229.89.in-addr.arpa.
+prl.res.in.
+www.stetina.com.
+26.158.33.83.in-addr.arpa.
+glorycycles.csell.store.yahoo.net.
+ut9.xhamster.com.
+a.root-servers.net.
+connect.facebook.net.
+photos-a.ak.fbcdn.net.
+cy.wikipedia.org.
+141.8.165.142.in-addr.arpa.
+arkleh.state.ar.us.
+twitter.com.
+safebrowsing-cache.google.com.
+hi-in.facebook.com.
+www.shopper.pk.
+www.gstatic.com.
+www.google.com.
+a.root-servers.net.
+189.25.111.95.in-addr.arpa.
+www.andamanadventures.com.
+18733.ua.all.biz.
+www.mindennapok.hu.
+uny2.com.
+photos-c.ak.fbcdn.net.
+111.165.195.190.in-addr.arpa.
+nigmahon.blogspot.com.
+www.yout.
+apps.facebook.com.
+profile.ak.fbcdn.net.
+159.147.239.190.in-addr.arpa.
+avalera.net.
+mail2.oblgazeta.ru.
+sanfranciscogym.info.
+38.12.137.82.in-addr.arpa.
+bogpost.dk.
+45.52.222.189.in-addr.arpa.
+www.artrabbit.com.
+blog.baomoi.com.
+static.ak.fbcdn.net.
+www.belkin.com.
+creative.ak.fbcdn.net.
+a1408.w43.akamai.net.
+profile.ak.fbcdn.net.
+isb-sib.ch.
+cdn.api.twitter.com.
+7f4b6f993392711663fac8b835e717f5.dnsbl7.mailshell.net.
+www.website-monitoring.com.
+row.bc.yahoo.com.
+vinossingulares.wordpress.com.
+carloslugo2008.blogspot.com.
+photos-a.ak.fbcdn.net.
+s2.youtube.com.
+www.cookbakelove.com.
+google.com.
+campusconnect.depaul.edu.
+dns.msftncsi.com.
+itunes.apple.com.
+www.pocketpcthoughts.com.
+ksn2-12.kaspersky-labs.com.
+www.blogmond.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+profile.live.com.
+73.107.64.109.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.barcelonatv.com.
+es.888.com.
+www.maturesexual.com.
+a1.sphotos.ak.fbcdn.net.
+4na5h:8x6.29jg.
+plusone.google.com.
+ds.addthis.com.
+www.sonography.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+nortwork.com.br.
+specialflorist.com.
+21.228.171.69.in-addr.arpa.
+crl.microsoft.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail2.amarahotels.com.
+digg.com.
+www.nude-imps.biz.
+photos-f.ak.fbcdn.net.
+cdtorg.ru.
+bbti7po78.b85o3p3m.
+mf.ebfarm.com.
+www.frenchculturenow.com.
+a6.sphotos.ak.fbcdn.net.
+mail.duxpond.com.
+connect.facebook.net.
+www.animationconnection.com.
+videos.flv2.redtubefiles.com.
+104.30.148.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+www.lamborghini-energy.com.
+170.165.40.177.in-addr.arpa.
+youtube.com.
+dc.tvteam.info.
+a.root-servers.net.
+93.11.143.188.in-addr.arpa.
+ujktmlmbmj.tv.
+blu0-omc4-s35.blu0.hotmail.com.
+pubads.g.doubleclick.net.
+c.live.com.
+137.126.17.177.in-addr.arpa.
+taosbooks.com.
+prov.us.mydlink.com.
+pop3.live.com.
+static.ak.fbcdn.net.
+www.elephanttube.com.
+www.contracorriente.eu.
+97.240.114.186.in-addr.arpa.
+ilovemiamispice.com.
+0.162.198.187.in-addr.arpa.
+www.1st-milkshake-n-smoothie-recipes.com.
+39.204.189.12.in-addr.arpa.
+mailbox.rudebecks.se.
+maps.gstatic.com.
+safelistmailbox.net.
+ratings-wrs.symantec.com.
+t.co.
+connect.facebook.net.
+17.63.169.88.in-addr.arpa.
+bjsjzf.en.alibaba.com.
+allanjwilkinson.co.uk.
+www.youtube.com.
+a.root-servers.net.
+row.bc.yahoo.com.
+photos-f.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+www.hennieviljoensafaris.com.
+127.19.224.77.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+178.31.55.186.in-addr.arpa.
+casa-de-patinhos.blogspot.com.
+pagead2.googlesyndication.com.
+pixel.facebook.com.
+photos-h.ak.fbcdn.net.
+197.158.142.189.in-addr.arpa.
+www.usafed.org.
+www.bbc.co.uk.
+community.ebay.com.
+217.198.34.189.in-addr.arpa.
+s0.2mdn.net.
+68.194.98.99.in-addr.arpa.
+alt4.gmail-smtp-in.l.google.com.
+s7.addthis.com.
+agora-gallery.com.s8b1.psmtp.com.
+orcart.facebook.com.
+js2.wlxrs.com.
+photos-a.ak.fbcdn.net.
+www.endsmugenmexico.com.
+a7.sphotos.ak.fbcdn.net.
+236.150.17.213.in-addr.arpa.
+h.live.com.nsatc.net.
+a.root-servers.net.
+static.onemodelplace.com.
+sanalofis.net.
+a.root-servers.net.
+180.130.155.184.in-addr.arpa.
+www.talkfast.com.br.
+a.root-servers.net.
+support.google.com.
+summitfx.com.
+killallhippies.ru.
+lawstlouis.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+142.132.8.90.in-addr.arpa.
+csl99f4ht.t60z1i1g.
+l.yimg.com.
+css.wlxrs.com.
+afontive.fileave.com.
+translate.google.com.
+ads.adap.tv.
+174.44.235.88.in-addr.arpa.
+orienta.universia.net.mx.
+sp.cwfservice.net.
+groups.google.com.mx.
+photos-c.ak.fbcdn.net.
+mail.redhillnetworks.com.
+dbg400.homeip.net.
+accounts.google.com.
+eltrajeyelmundo.files.wordpress.com.
+www.vercapitulo.com.
+216.228.122.187.in-addr.arpa.
+dc504.4shared.com.
+terabitwarez.net.
+www.google.com.
+97.57.123.200.in-addr.arpa.
+maps.l.google.com.
+lehuaorchids.com.
+www.crit-iq.com.au.
+a8.sphotos.ak.fbcdn.net.
+20.94.253.88.in-addr.arpa.
+static.ak.fbcdn.net.
+mail.1991.ru.
+www.btparadise.com.
+a1.sphotos.ak.fbcdn.net.
+m.addthisedge.com.
+61.7.188.189.in-addr.arpa.
+xhcdn.com.
+0-ji-w.channel.facebook.com.
+21.133.124.190.in-addr.arpa.
+t2.gstatic.com.
+developers.facebook.com.
+i1.ytimg.com.
+h.live.com.
+s0.2mdn.net.
+p.l.qq.com.
+accounts.google.com.
+msfs.nspmotion.com.
+r._dns-sd._udp.0.160.168.192.in-addr.arpa.
+safebrowsing-cache.google.com.
+a323.yahoofs.com.
+static.ak.fbcdn.net.
+download343.avast.com.
+time.stdtime.gov.tw.
+65.250.132.189.in-addr.arpa.
+akcontent.ebuddy.com.
+www.findingmyforest.org.
+204.244.189.190.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+kendallharmon.net.
+www.angrybird.biz.
+barclayproducts.com.
+calculatusemisiones.com.
+255.218.26.98.in-addr.arpa.
+tc26.easythumbhost.com.
+req1.appads.com.
+74.80.225.190.in-addr.arpa.
+db._dns-sd._udp.lan.
+t0.gstatic.com.
+a.root-servers.net.
+plus.google.com.
+ru-promo.ru.
+ixlbp78k3.99tb.
+182.95.92.186.in-addr.arpa.
+exchange.alacare.com.
+img2.blogblog.com.
+liveupdate.symantecliveupdate.com.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+ecologiasomosnaturaleza.blogspot.com.
+40.104.214.189.in-addr.arpa.
+28.253.34.174.in-addr.arpa.
+seeklogo.com.
+186.66.178.190.in-addr.arpa.
+ad57.feeldmc.com.
+sites.google.com.
+stamps.shop.ebay.com.
+www.outstandingnudes.com.
+fmcicesports.com.s5a1.psmtp.com.
+72.110.110.201.in-addr.arpa.
+post.andertons.co.uk.
+146.27.242.201.in-addr.arpa.
+2.54.200.91.in-addr.arpa.
+baymsg1010710.gateway.messenger.live.com.
+www.hardcoreposts.com.
+rdh-env.com.inbound15.mxlogicmx.net.
+mail.assets-school.net.
+renewconcrete.org.
+_935_41_1.
+www.4shared.com.
+photos-e.ak.fbcdn.net.
+idleaire.com.s9a1.psmtp.com.
+154.30.216.89.in-addr.arpa.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+gostore.3g.cn.
+www.elosopanda.com.
+135.228.132.190.in-addr.arpa.
+www.patagoniavirgin.com.
+rreloj.files.wordpress.com.
+www.scribd.com.
+photos-f.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+.
+mx.easynet.nl.
+www.google.com.
+www.coedsneedcashlive.com.
+g.ceipmsn.com.
+maxwells.co.uk.
+tl.answers.com.
+252.216.103.190.in-addr.arpa.
+0-jj-w.channel.facebook.com.
+139.189.160.187.in-addr.arpa.
+230.225.82.71.in-addr.arpa.
+dbz-los-rivales-mas-poderosos-cooler1.blogspot.com.
+csi.gstatic.com.
+7b7e9eaa.allanalpass.com.
+dns.msftncsi.com.
+googleads.g.doubleclick.net.
+voipb.sip.yahoo.com.
+www.fonttester.com.
+static.ak.connect.facebook.com.
+a.root-servers.net.
+157.159.53.83.in-addr.arpa.
+pixel.facebook.com.
+time.windows.com.
+a1.sphotos.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+stats.wordpress.com.
+blog.tv2.dk.
+photos-f.ak.fbcdn.net.
+sn2files.storage.msn.com.
+content.yieldmanager.edgesuite.net.
+euro.mediotiempo.com.
+www.milftits.net.
+subtitledmusic.blogspot.com.
+sp.ask.com.
+i.dailymail.co.uk.
+matefinacierab1.galeon.com.
+jcjdatacomm.co.uk.
+marbelle.ru.
+photos-e.ak.fbcdn.net.
+grandhotelrodina.ru.
+jred.co.
+www.update.microsoft.com.
+vcs1.msg.yahoo.com.
+a.root-servers.net.
+pdgraphic.com.
+address.yahoo.com.
+au.answers.yahoo.com.
+time-b.nist.gov.
+tracker.bittorrent.am.
+netype.com.
+110.101.212.201.in-addr.arpa.
+a.root-servers.net.
+53.93.156.187.in-addr.arpa.
+a.root-servers.net.
+www.taringa.net.
+a2.sphotos.ak.fbcdn.net.
+thebarongroup.com.
+mercurymetalcraft.com.
+65.3.224.186.in-addr.arpa.
+mail.live.com.
+photos-g.ak.fbcdn.net.
+developers.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+en.wikipedia.org.
+cdn.wibiya.com.
+bmx.com.
+a.root-servers.net.
+a.root-servers.net.
+appldnld.apple.com.
+224.1.200.94.in-addr.arpa.
+master3342.servehttp.com.
+_543_45_8.
+79.215.141.190.in-addr.arpa.
+dynamicdialogs.toolbar.conduit-services.com.
+zoomer2.hc1.ca.
+placidayeye.blogia.com.
+t3.gstatic.com.
+cdn-colo-ch-10.mbt.com.
+pixel.facebook.com.
+jobs.topusajobs.com.
+_840_95_5.
+www.simoniddol.com.
+default01.static.socialpointgames.com.
+softdl2.360.cn.
+a.root-servers.net.
+193.120.108.186.in-addr.arpa.
+i.ytimg.com.
+www.pspublicidad.com.
+40.209.54.189.in-addr.arpa.
+log.opentracker.net.
+www.chistesbuenos.com.mx.
+www.microsoft.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+gpcom.com.mx2.gpcom.rcimx.net.
+www.bikeland.ru.
+translate.google.com.mx.
+teredo.ipv6.microsoft.com.
+localhost.
+photos-e.ak.fbcdn.net.
+ts.videosz.com.
+butlerrubin.com.inbound10.mxlogicmx.net.
+mx10.activator.com.
+wsh.gamib.com.
+a.root-servers.net.
+images8.sextubestore.com.
+ulearngolf.com.
+old.aliste.info.
+cdn.g.promosrv.com.
+www.amazingbridalshowers.com.
+www.facebook.com.
+photos-f.ak.fbcdn.net.
+y1hm6bqc:.v26o0y7v.
+profile.ak.fbcdn.net.
+twitter.com.
+kerosin13.ru.
+p08-caldav.icloud.com.akadns.net.
+translate.google.es.
+disqus.com.
+44.212.230.190.in-addr.arpa.
+es-es.facebook.com.
+www.luisxl.com.
+cloud-q.duba.net.
+a1.sphotos.ak.fbcdn.net.
+apps.facebook.com.
+data.coremetrics.com.
+apis.google.com.
+platform.ak.fbcdn.net.
+www.cichlidforums.com.
+cdn.wsi.com.c.footprint.net.
+photos-a.ak.fbcdn.net.
+78.236.87.95.in-addr.arpa.
+rochellegirl.polyvore.com.
+benta.spb.ru.
+ic.tynt.com.
+www.premier-tools.com.
+joomla16.siteground.com.
+www.textsrv.com.
+i.imwx.com.
+pixel.facebook.com.
+lh3.googleusercontent.com.
+88.188.134.187.in-addr.arpa.
+u21.eset.com.
+17.27.33.90.in-addr.arpa.
+spaces.live.com.
+innotec.ru.
+accountservices.msn.com.
+h4kurd.com.
+a.root-servers.net.
+www.tracert.org.
+al-ramady.com.
+www.john-cena.net.
+ksn1-11-part1.kaspersky-labs.com.
+mail.safali.ru.
+cookex.amp.yahoo.com.
+hawaiiusafcu.com.inbound10.mxlogicmx.net.
+profile.live.com.
+134.235.76.178.in-addr.arpa.
+omega-press.ru.
+unicam-studio.ru.
+e-ternaltreasures.com.
+photos-g.ak.fbcdn.net.
+avatarthelastairbenderonline.com.
+wgtot45.digitalriver.com.
+m.addthisedge.com.
+mx.westbrook-village.com.
+bs.serving-sys.com.
+166.4.106.186.in-addr.arpa.
+15.53.193.187.in-addr.arpa.
+clients1.google.com.
+thomas-hardye.dorset.sch.uk.
+photos-e.ak.fbcdn.net.
+ns1.yandex.net.
+cn1.redswoosh.akadns.net.
+220.186.138.201.in-addr.arpa.
+mail.indiatravel.ru.
+www.taskforceapp.com.
+picture.cdn.pixmac.com.
+blufiles.storage.msn.com.
+107.49.87.62.in-addr.arpa.
+safebrowsing-cache.google.com.
+dns.msftncsi.com.
+www.juegosdiarios.com.
+mail.ibew110.org.
+altresactivitatsproductives.blogspot.com.
+28.8.16.190.in-addr.arpa.
+113.24.115.187.in-addr.arpa.
+www.google-analytics.com.
+www.google-analytics.com.
+157.181.173.201.in-addr.arpa.
+www.ioha.fgv.br.
+mgs17.acecounter.com.
+c.iogous.com.
+dr._dns-sd._udp.lan.
+132.33.86.186.in-addr.arpa.
+platform.twitter.com.
+143.244.84.200.in-addr.arpa.
+imap.gmail.com.
+venus.grires.com.
+214.3.62.186.in-addr.arpa.
+zh-cn.facebook.com.
+dns.msftncsi.com.
+126.17.254.8.in-addr.arpa.
+www.google.com.
+www.googleadservices.com.
+8-courier.push.apple.com.
+ajax.googleapis.com.
+195.233.160.190.in-addr.arpa.
+americapgroup.com.
+ads2.msads.net.
+misc.blogsmith.aol.com.aol.akadns.net.
+c7.zedo.com.
+airgchatinfo.blogspot.com.
+a.root-servers.net.
+readinglessons.com.
+www.facebook.com.
+pics03.adooscore.com.
+ib.adnxs.com.
+empleos-temporarios.vivavisos.com.ar.
+yahll.com.
+clients1.google.com.
+iz:hnafgl.q71e7o2c.
+a.root-servers.net.
+wsl.cotas.com.
+13.120.105.190.in-addr.arpa.
+rsntqiqbhykc.net.
+rexee-11.vo.llnwd.net.
+profile.spb.ru.
+mail.google.com.
+www.chinabusinessworld.com.
+profile.ak.fbcdn.net.
+m.facebook.com.
+rssocapps.rosettastone.com.
+225.186.234.190.in-addr.arpa.
+www.google-analytics.com.
+upgrade.bitdefender.com.
+244.231.35.189.in-addr.arpa.
+a.root-servers.net.
+197.17.5.88.in-addr.arpa.
+a569.g.akamai.net.
+watermill.com.inbound10.mxlogic.net.
+talewis.com.
+sepetibatecon.com.br.
+manaranews1.blogspot.com.
+av.vimeo.com.
+sites.google.com.
+51.213.51.201.in-addr.arpa.
+_517_23_8.
+r.openx.net.
+fbogsecendrrr.mp.
+s.youtube.com.
+131.92.158.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.macizorras.com.
+developers.facebook.com.
+graphicbook.com.
+www.todaycal.com.
+ravefeca.tv.
+www.facebook.com.
+lacataratadelsanisidoro.blogspot.com.
+eluneknights.latin-foro.net.
+202.65.254.201.in-addr.arpa.
+anal-forum.com.
+js.dmtry.com.
+spam01.wiredmedium.com.
+photos-g.ak.fbcdn.net.
+nsx.np.dl.playstation.net.
+static.ak.fbcdn.net.
+4.courier-push-apple.com.akadns.net.
+digg.com.
+s-static.ak.fbcdn.net.
+217.215.228.190.in-addr.arpa.
+www.webgrafics.es.
+178.54.51.190.in-addr.arpa.
+a.root-servers.net.
+91.121.55.65.in-addr.arpa.
+plusone.google.com.
+www.gas-servei.com.
+gfx3.hotmail.com.
+www.entertoinet.com.
+google.com.
+a1.sphotos.ak.fbcdn.net.
+informika.ru.
+ns2.otys.nl.
+calearth.org.
+fr-fr.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+mail.obeetee.com.
+ts04.eset.com.
+a7.sphotos.ak.fbcdn.net.
+210.104.53.186.in-addr.arpa.
+138.211.172.78.in-addr.arpa.
+infodepot.wikia.com.
+park2.dns.im.
+safebrowsing.clients.google.com.
+113.68.125.186.in-addr.arpa.
+studychacha.com.
+fbib6nsj4.06hh.
+pixel.facebook.com.
+pr.starmedia.com.
+www.greatsuccessfulpeople.com.
+weather.service.msn.com.
+86.56.171.216.in-addr.arpa.
+www.filipina88.com.
+mail.tribiq.net.
+sii.fr.
+a7.sphotos.ak.fbcdn.net.
+162.251.97.176.in-addr.arpa.
+data.flurry.com.
+ustre.am.
+rad.msn.com.
+dustbowl.wordpress.com.
+s2.youtube.com.
+146.39.31.173.in-addr.arpa.
+www.bywifi.com.
+www.facebook.com.
+www.weather.com.
+www.terra.com.
+k-soya.ru.
+mail.belfastmediagroup.com.
+www.ecomagazin.ro.
+202.175.218.186.in-addr.arpa.
+www.cwdomination.com.
+getprof.es.np.community.playstation.net.
+www.suburban.com.mx.
+csi.gstatic.com.
+www.fishjava.com.
+csi.gstatic.com.
+disneylatino.com.
+google.com.
+www.chicasgames.com.
+geoiplookup.wikimedia.org.
+dx3723.tinyurl.com.
+a.root-servers.net.
+api-secure.solvemedia.com.
+photos-e.ak.fbcdn.net.
+edge.quantserve.com.
+cheatsbysuperlegends.chatango.com.
+aa.net.
+fb-0.hidden.zynga.com.
+a2.sphotos.ak.fbcdn.net.
+eamail1.unisys.com.
+external.ak.fbcdn.net.
+tools.google.com.
+41.114.160.187.in-addr.arpa.
+125.217.34.186.in-addr.arpa.
+1.0.168.192.in-addr.arpa.
+boltax.blogspot.com.
+apps.facebook.com.
+dnl-01.geo.kaspersky.com.
+skotos.net.
+www.gstatic.com.
+srcaccess.net.s9b1.psmtp.com.
+0-292.channel.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.infinitypublishing.com.
+goldenbow.com.
+eiastillero.blogspot.com.
+30.88.105.186.in-addr.arpa.
+mailserver.limohire.com.
+www.bestprideparades.com.
+151.37.32.189.in-addr.arpa.
+smtp.shk-group.com.
+mail.mainstreetmediainc.com.
+photarium.com.
+usyd.edu.au.
+77.73.86.67.in-addr.arpa.
+www.tango.hagaselamusica.com.
+adserving.cpxinteractive.com.
+www.facebook.com.
+242.137.124.186.in-addr.arpa.
+ssl.gstatic.com.
+www.xvideos.com.
+a.root-servers.net.
+31dlth2z2.o78o2y1i.
+pop3.hot.glbdns.microsoft.com.
+botones.blogalaxia.com.
+a2.sphotos.ak.fbcdn.net.
+126.213.217.196.in-addr.arpa.
+a749.g.akamai.net.
+www.facicons.com.
+www.facebook.com.
+adadvisor.net.
+elsurdelafrontera.blogdiario.com.
+mx1.darkorbit.bigpoint.com.
+s-static.ak.fbcdn.net.
+plusone.google.com.
+www.celebrationideasonline.com.
+3.1.168.192.in-addr.arpa.
+time.nist.gov.
+www.freshrapidlinks.com.
+249.39.236.190.in-addr.arpa.
+msbmo.com.
+204.45.158.187.in-addr.arpa.
+bayimg.com.
+snecma.ru.
+fr-fr.facebook.com.
+www.frecuenciadigital.es.
+coinworld.com.inbound15.mxlogicmx.net.
+adsfront.iminent.com.
+tcyonline.com.
+teredo.ipv6.microsoft.com.
+40.216.74.187.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.rememberthemilk.com.
+jasusa.com.2.arsmtp.com.
+a.root-servers.net.
+buckshare.com.
+101.165.173.189.in-addr.arpa.
+t3.gstatic.com.
+docs.google.com.
+recursos.promocionesweb.com.
+youtube-espanol.blogspot.com.
+medkrug.ru.
+mch-pllp.com.mail8.psmtp.com.
+checkip.dyndns.com.
+45.122.155.200.in-addr.arpa.
+accounts.google.com.
+fuelingcomponents.com.pri-mx.na0104.smtproutes.com.
+external.ak.fbcdn.net.
+samhouston.army.mil.
+peregrinesolutions.com.
+_744_96_9.
+fbcdn-photos-a.akamaihd.net.
+snsgw.samsungmobile.com.
+suggestqueries.google.com.
+a1.sphotos.ak.fbcdn.net.
+69.63.250.201.in-addr.arpa.
+81.187.137.190.in-addr.arpa.
+es.wikiquote.org.
+www.kayak.com.
+dns.msftncsi.com.
+photos-g.ak.fbcdn.net.
+www.letsgosago.net.
+supersat.net.
+bellsouth.net.
+corporacionpro.com.
+apple-mobile.query.yahooapis.com.
+segment-pixel.invitemedia.com.
+profile.ak.fbcdn.net.
+203.20.190.189.in-addr.arpa.
+support.maktoob.com.
+galaxylife.digitalchocolate.com.
+host-delay.logmein-gateway.com.
+time.windows.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+besitosdeosopolar.blogspot.com.
+static.ak.fbcdn.net.
+lvs.com.ru.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+android.holfeld.com.
+clkads.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+212.25.179.190.in-addr.arpa.
+flasuncoast.net.
+view.atdmt.com.
+secure.wlxrs.com.
+1.115.112.190.in-addr.arpa.
+212.102.45.39.in-addr.arpa.
+porokov.net.
+213.218.69.200.in-addr.arpa.
+img.imgsmail.ru.
+www.facebook.com.
+a.root-servers.net.
+_146_03_1.
+grantenguisito.nu.
+usue.ru.
+analytics.pch.com.
+correointeligente.com.
+www.1accesshost.com.
+253.219.22.186.in-addr.arpa.
+120.175.209.201.in-addr.arpa.
+torrentdealer.ath.cx.
+c0058712.cdn.cloudfiles.rackspacecloud.com.
+viroc.pt.
+www.google.com.
+master4.teamviewer.com.
+crl.microsoft.com.
+www.cupcakerecipes.com.
+m3.rvsanmiguel.com.
+support.google.com.
+na.blackberry.com.
+creative.ak.fbcdn.net.
+f4999.mail.yahoo.com.
+av.aaomembers.org.
+mail.saletour.ru.
+ksn7-12.kaspersky-labs.com.
+eross-666.hi5.com.
+pixel.invitemedia.com.
+a2.sphotos.ak.fbcdn.net.
+abitoldernow.tumblr.com.
+www.clubhaleysweet.com.
+www.portada-online.com.
+www.minhaconexao.com.br.
+addons.mozilla.org.
+silvergroup.com.
+u.zillow.com.
+www.tj-archivo.org.
+m.facebook.com.
+3.149.39.190.in-addr.arpa.
+echo7.bluehornet.com.
+a1015.g.akamai.net.
+cpl.biz.
+a.root-servers.net.
+api.twitter.com.
+clients2.google.com.
+ravtograf.ru.
+81.102.114.186.in-addr.arpa.
+pix04.revsci.net.
+inversedelirium.libsyn.com.
+_899_72_2.
+a.root-servers.net.
+cdn.bid-tag.com.
+wey.icritical.com.
+www.folkebevaegelsen.dk.
+api.conduit.com.
+external.ak.fbcdn.net.
+cdn.api.twitter.com.
+psicotecnopatas.com.
+cdn.xvideoswatch.com.
+profile.ak.fbcdn.net.
+instrumedinc.com.
+66.29.188.90.in-addr.arpa.
+www.twitter.com.
+books.google.com.
+www.sport.org.
+teredo.ipv6.microsoft.com.
+i3.ytimg.com.
+233.244.167.190.in-addr.arpa.
+160.248.156.24.in-addr.arpa.
+27.186.49.190.in-addr.arpa.
+103.59.69.190.in-addr.arpa.
+www.open-mind.vc.
+translate.google.com.
+www.google.com.
+graphicsleader.pt.
+mail1.rs-it.co.uk.
+www.verenettawarner.com.
+design-incentives.com.
+edge.quantserve.com.
+adelphia.net.
+www.gamefaqs.com.
+16.167.102.99.in-addr.arpa.
+www.horrorsquad.com.
+www.orbeezone.com.
+www.arrihanpress.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+106.49.232.91.in-addr.arpa.
+api-read.facebook.com.
+www.facebook.com.
+linkurywebservices-msgplus.trafficmanager.net.
+connect.facebook.net.
+illy.com.
+a5.sphotos.ak.fbcdn.net.
+d1ae3bdqlkjebx.cloudfront.net.
+fusion.google.com.
+static.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+office-point.ru.
+www.lindisima.com.
+seancronanphotography.com.
+www.google.com.
+billing.sharo4ka.ru.
+122.45.78.189.in-addr.arpa.
+lafxpills.ru.dob.sibl.support-intelligence.net.
+faup.ucentral.cl.
+131.174.25.190.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+167.8.55.189.in-addr.arpa.
+plus.google.com.
+102.14.124.70.in-addr.arpa.
+a.root-servers.net.
+nhansuvietnam.vn.
+creative.ak.fbcdn.net.
+155.48.172.81.in-addr.arpa.
+s0.2mdn.net.
+_424_85_9.
+230.239.104.187.in-addr.arpa.
+ceritanafsuku.co.cc.
+a7.sphotos.ak.fbcdn.net.
+www.graffititextlive.com.
+sw-rec.ru.
+pedazosdecarbono.blogspot.com.
+148.144.220.66.combined.njabl.org.
+mediadesignprogram.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+g0.gstatic.com.
+pagead2.googlesyndication.com.
+icompass.insightexpressai.com.
+navgw2.usxpress.com.
+www.facebook.com.
+sites.google.com.
+a.root-servers.net.
+ssl.gstatic.com.
+www.showmyweather.com.
+piedraconsupieldecebolla.blogspot.com.
+i4.ytimg.com.
+ajax.googleapis.com.
+my.igain.com.
+170.204.172.201.in-addr.arpa.
+adspaces.ero-advertising.com.
+www.angermanagementresource.com.
+video.google.com.mx.
+\(none\).
+time.nist.gov.
+47.147.220.66.in-addr.arpa.
+www.nccam.nih.gov.
+a1725.l.akamai.net.
+167.57.161.77.in-addr.arpa.
+52.42.225.189.in-addr.arpa.
+36.46.122.187.in-addr.arpa.
+81.127.47.190.in-addr.arpa.
+time-nw.nist.gov.
+twitter.com.
+c-0.19-230f4000.a260011.1518.19d1.3ea1.210.0.um5jqsq46s93587gpv5kkiqkpt.avqs.mcafee.com.
+a.root-servers.net.
+a.root-servers.net.
+www.poetas.com.
+vardy.me.
+c-0.19-a30f1081.8000081.1518.19d4.3ea1.210.0.v7f5m9tctl8k377dvvzj5bs74t.avqs.mcafee.com.
+bit.ly.
+l.yimg.com.
+www.google.com.
+9.10.168.187.in-addr.arpa.
+www.open-speech.com.
+131.100.10.200.in-addr.arpa.
+nbalakershistory.blogspot.com.
+196.78.71.190.in-addr.arpa.
+upyachka.ru.
+www.drpenafiel.com.
+_018_76_7.
+photos-c.ak.fbcdn.net.
+mfeeds.economictimes.indiatimes.com.
+profile.ak.fbcdn.net.
+www.gstatic.com.
+teamtechinc.net.s8a1.psmtp.com.
+www.facebook.com.
+photos-g.ak.fbcdn.net.
+mw2.google.com.
+ads1.msads.net.
+uk-bm.ru.
+www.4realamateurs.net.
+insider.msg.yahoo.com.
+api.tweetdeck.com.
+users.cs.fiu.edu.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+186.45.132.81.in-addr.arpa.
+dreamthebiggestdream.com.
+db.useful-apps.com.
+translate.googleapis.com.
+78.13.181.99.in-addr.arpa.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+rover.ebay.com.
+www.merlinbeats.com.
+161.13.34.68.in-addr.arpa.
+salmanonline.net.
+msnportal.112.2o7.net.
+api.twitter.com.
+keshmuney.com.
+secure.shared.live.com.
+ntp1.dlink.com.
+a.root-servers.net.
+smtp.mooreauto.com.
+a1.da1.akamai.net.
+152.34.204.130.in-addr.arpa.
+files.prays.webnode.es.
+syndication.traffichaus.com.
+150.234.104.186.in-addr.arpa.
+_968_82_6.
+s.youtube.com.
+www.paulstips.com.
+www.unipromo.es.
+img100.xvideos.com.
+86.109.148.46.in-addr.arpa.
+sportboats.apolloduck.com.
+www.2cutepartybags.com.au.
+ssl.gstatic.com.
+fbcdn-profile-a.akamaihd.net.
+mensfitnessmagazine.uk.intellitxt.com.
+acroipm.adobe.com.
+skv-telecom.ru.
+15.2.168.192.in-addr.arpa.
+www.facebook.com.
+caipadova.it.
+piano.net.ru.
+chavismasonry.com.
+eng.krx.co.kr.
+developers.facebook.com.
+.
+m.addthisedge.com.
+www.countrysidemag.com.
+parenthetically.blogspot.com.
+www.google.com.
+external.ak.fbcdn.net.
+apis.google.com.
+www.submarinoviagens.com.br.
+safebrowsing-cache.google.com.
+www.extremetube.com.
+a3.sphotos.ak.fbcdn.net.
+qm.net.
+253.102.141.201.in-addr.arpa.
+www.orl.ucla.edu.
+t3.gstatic.com.
+toolbar.google.com.
+smx.asurams.edu.redcondor.net.
+www.sexogratiswebcams.com.
+blacklady1.blogspot.com.
+www.pacmoore.com.
+6.98.190.189.in-addr.arpa.
+sp.cwfservice.net.
+the-order-of-cupcake.blogspot.com.
+ad.yieldmanager.com.
+static.ak.fbcdn.net.
+ksn4.kaspersky-labs.com.
+241.101.35.177.in-addr.arpa.
+a1402.w40.akamai.net.
+www.jcreport.com.
+monsters-inc-2-trailers.blogspot.com.
+ksn6-12.kaspersky-labs.com.
+99.67.135.189.in-addr.arpa.
+28.144.149.190.in-addr.arpa.
+www.gstatic.com.
+ja.wikipedia.org.
+64.230.31.190.in-addr.arpa.
+dns.msftncsi.com.
+guptaequities.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.exgftube.net.
+apple3.musicdna-interface.com.
+cyberfretbass.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.responsesource.com.
+etvdupood.b11w9m4x.
+ns.vegatele.com.
+176.202.78.94.in-addr.arpa.
+clients1.google.com.
+fb-fb-0.castle.zynga.com.
+138.138.172.190.in-addr.arpa.
+rad.msn.com.
+a.root-servers.net.
+a.root-servers.net.
+a.root-servers.net.
+www.smartcampaign.co.kr.
+www.santillanaele.com.
+www.filmaciones.unlugar.com.
+static.ak.fbcdn.net.
+email.grammarly.com.
+107.146.220.66.in-addr.arpa.
+feeds.bbci.co.uk.
+mail.irondequoit.org.
+dns.msftncsi.com.
+94.225.31.190.in-addr.arpa.
+ie9.discoverbing.com.
+mail.thesimonsgroup.net.
+mailgatensw1.fairfax.com.au.
+creative.ak.fbcdn.net.
+mail2.atlanticsales.com.
+d3lvr7yuk4uaui.cloudfront.net.
+wieson.com.
+mail.google.com.
+www.onak.cl.
+16.51.248.201.in-addr.arpa.
+nicalis.com.
+a.root-servers.net.
+o2kilie47.r49l5v8w.
+isap.sejm.gov.pl.
+lavidaessilbar.blogspot.com.
+228.169.106.220.in-addr.arpa.
+www.cruelforcedsex.com.
+104.187.81.186.in-addr.arpa.
+accounts.google.com.
+owa.macpapers.com.
+profile.ak.fbcdn.net.
+mtalk.google.com.
+cdn.api.twitter.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+hb.cloud.avg.com.
+mail.kansascommerce.com.
+creative.ak.fbcdn.net.
+85.35.68.111.in-addr.arpa.
+www.randyrun.es.
+_551_04_1.
+17.94.175.189.in-addr.arpa.
+www.tudakozo.t-com.hu.
+135.13.160.189.in-addr.arpa.
+www.ima.umn.edu.
+_378_24_3.
+99.195.240.85.in-addr.arpa.
+login.toolbar.conduit-services.com.
+themes.googleusercontent.com.
+178.237.37.178.in-addr.arpa.
+cs13464.vkontakte.ru.
+img688.imageshack.us.
+download822.avast.com.
+www.mariacamilamesa.com.
+www.facebook.com.
+shinamall.ru.
+www.medgle.es.
+cmylaw.com.
+photos-h.ak.fbcdn.net.
+julied.bsofivectteiat.tm.
+t3.gstatic.com.
+mail2.gundermann.com.
+120.47.108.85.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+212.161.60.213.in-addr.arpa.
+webmaster.drtuber.com.
+www.facebook.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mail3.hunterdouglas.ru.
+pentagramas.files.wordpress.com.
+a-0.19-83096081.10033.1518.19d4.2f1c.10.0.4ntf88pba9hhdjt7vhm5spjl35.avqs.mcafee.com.
+mx.mujer.yahoo.com.
+211.44.228.76.in-addr.arpa.
+www.comicstale.com.
+m2pnaper.com.
+a1.sphotos.ak.fbcdn.net.
+mx.gbcarch.com.cust.b.hostedemail.com.
+5ngm:uvux.r33w6b0u.
+www.profantasyrodeo.com.
+google.com.
+saltymilk.com.
+mx01.filter.magicmail.co.uk.
+xfactor.spb.ru.
+southernx.ne.jp.
+60.33.53.173.in-addr.arpa.
+_934_54_9.
+chart.apis.google.com.
+www.google.com.
+www.smartthinkingbook.com.
+profile.ak.fbcdn.net.
+d.yimg.com.
+inbound.ithacah-d.com.netsolmail.net.
+w.sharethis.com.
+www.regionesartificiales.com.
+b._dns-sd._udp.lan.
+db._dns-sd._udp.lan.
+a.root-servers.net.
+fbcdn-sphotos-a.akamaihd.net.
+walmartstores.com.
+evo-tour.ru.
+160.12.48.190.in-addr.arpa.
+gradient-ltd.com.ua.
+1.0.0.223.lbl7.mailshell.net.
+150.20.227.188.in-addr.arpa.
+lildolliedaily.com.
+es.wikipedia.org.
+mail.cornerstonehealthcare.net.
+54.13.105.189.in-addr.arpa.
+143.124.133.190.in-addr.arpa.
+846-car.net.
+commonwealthtowers.com.
+bbcore.cloudapp.net.
+www.cpxadspace.com.
+profile.ak.fbcdn.net.
+www.hilltopglossy.com.
+o3lbcqq2p.55to.
+254.106.189.90.in-addr.arpa.
+www.facebook.com.
+news.gree.jp.
+mitologia4.blogspot.com.
+8.17.22.187.in-addr.arpa.
+www.adobe.com.
+view.atdmt.com.
+kviltstina.blogspot.com.
+www.bing.com.
+unicentrooccidente.com.
+joindiaspora.com.
+jordicastell.blog.terra.cl.
+www.alabanzascristianas.blogspot.com.
+smtp.ofsy.net.
+ktvbzqi7y.p47a4h3n.
+clima.msn.com.
+img.quemensajes.com.
+demilovato-argentina.blogspot.com.
+plusone.google.com.
+dn-serv.com.
+sp.cwfservice.net.
+31.166.185.190.in-addr.arpa.
+img2.blogblog.com.
+external.ak.fbcdn.net.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+luisenriquemusic.com.
+hits.e.cl.
+api.twitter.com.
+www.myhottube.com.
+dr._dns-sd._udp.lan.
+i1.ytimg.com.
+www.solidnijistota.cz.
+accounts.google.com.
+a1028.g.akamai.net.
+smtp1.spameater.net.
+sip.ipvideotalk.com.
+194.43.165.178.in-addr.arpa.
+www.almitra.com.
+www.911truth.org.
+heartbeat.belkin.com.
+en-us.fxfeeds.mozilla.com.
+4.bp.blogspot.com.
+google.com.
+a2.sphotos.ak.fbcdn.net.
+mekcztylfg.net.
+sites.google.com.
+215.114.141.201.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+www.180south.com.
+s135.cnzz.com.
+profile.ak.fbcdn.net.
+153.144.220.121.in-addr.arpa.
+210.25.249.199.in-addr.arpa.
+interlinq.com.
+a2.sphotos.ak.fbcdn.net.
+sites.google.com.
+eizij:z93.r41x1t6h.
+ingdirect.com.au.
+fp.enter.net.
+94.118.255.201.in-addr.arpa.
+65.177.29.201.in-addr.arpa.
+rs712l34.rapidshare.com.
+www.facebook.com.
+dr._dns-sd._udp.0.2.0.10.in-addr.arpa.
+155.212.130.190.in-addr.arpa.
+mt1.google.com.
+creative.ak.fbcdn.net.
+_792_76_7.
+i3.ytimg.com.
+4pz7:un2w.x56k4m7i.
+www.businesslist.sg.
+67.152.213.201.in-addr.arpa.
+it-it.facebook.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+ecaustria.at.
+secure.wlxrs.com.
+erols.com.
+deanfoods.com.s8a2.psmtp.com.
+mail.jhb.wbs.co.za.
+www.google.com.
+www.fabricwarehouse.co.uk.
+mx1.task.com.br.
+www.bijuegos.com.
+pdf.dirale.com.
+www.belkin.com.
+dvdp3eqjh.57we.
+tap2-cdn.rubiconproject.com.
+fbcdn-photos-a.akamaihd.net.
+_061_57_3.
+www.trucoteca.com.
+i3.ytimg.com.
+a.root-servers.net.
+laposada.rockresorts.com.
+59.64.64.1.in-addr.arpa.
+45.112.168.192.in-addr.arpa.
+xylon.asfh-berlin.de.
+45.122.172.201.in-addr.arpa.
+login.live.com.
+121.189.231.125.in-addr.arpa.
+115.43.170.189.in-addr.arpa.
+mailsrv11.hartrodt.com.
+chromejs.s3.amazonaws.com.
+matcher.bidder8.mookie1.com.
+86.19.251.189.in-addr.arpa.
+16.147.102.220.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+fo-eu-ec.ay1.b.yahoodns.net.
+apir.webrep.avast.com.
+hooping.net.
+www.google-analytics.com.
+www.philips.pl.
+103.253.40.92.in-addr.arpa.
+www.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mediacdn.disqus.com.
+128.48.8.88.in-addr.arpa.
+www.google-analytics.com.
+yours.com.
+www.facebook.com.
+o1.t26.net.
+photos-g.ak.fbcdn.net.
+911.talk4free.com.
+news.google.com.mx.
+ksn3-12.part1.kaspersky-labs.com.
+log.goodnetads.org.lan.
+netspape.net.
+michaelkors.com.
+primaryfocalpoints.net.
+www.savspeed.co.za.
+www.davidsbridal.ca.
+www.granpick.com.
+news.google.com.
+mail.nbzs.com.
+mail.flappellatelaw.com.
+dailydujour.com.
+caracolasfem.blogspot.com.
+94.119.239.189.in-addr.arpa.
+evsecure-ocsp.geotrust.com.
+mail.trepel.com.
+17.43.85.186.in-addr.arpa.
+mail.imrtest.com.
+a2.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+153.156.6.210.in-addr.arpa.
+static.exoclick.com.
+chicago.cubs.mlb.com.
+www.mineralweb.com.
+17.213.178.190.in-addr.arpa.
+a.root-servers.net.
+www.google.com.
+photos-b.ak.fbcdn.net.
+a.root-servers.net.
+imagesrv.adition.com.
+27-courier.push.apple.com.
+proxy-55.dailymotion.com.
+img25.imageshack.us.
+conseilsdeco.net.
+voipc.sip.yahoo.com.
+www.google.com.
+a2.sphotos.ak.fbcdn.net.
+ad.yieldmanager.com.
+iphone-wu.apple.com.
+secure-uk.imrworldwide.com.
+photos-b.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+static.exoclick.com.
+alerts.conduit-services.com.
+hawthornfarm.wanadoo.co.uk.
+mail.cascpa.net.
+clock.fmt.he.net.
+alajmy.com.
+www.guitarjapan.com.
+www.google.com.
+external.ak.fbcdn.net.
+vicioadictos.blogspot.com.
+netzdero.com.
+emob1089.photobucket.com.
+sentence-extractor.googlecode.com.
+dsjlondon.com.
+thebranfordgroup.com.s8b1.psmtp.com.
+a2.sphotos.ak.fbcdn.net.
+b-0.19-270e9219.b1081.1518.19d4.3ea1.210.0.9win1zdcdhpc8qvz14k5gi6l5v.avqs.mcafee.com.
+registration.ess.apple.com.akadns.net.
+a5.sphotos.ak.fbcdn.net.
+col.stb01.s-msn.com.
+photos-a.ak.fbcdn.net.
+www.facebook.com.
+227.89.208.82.in-addr.arpa.
+www.energydelta.org.
+a.root-servers.net.
+133.86.22.201.in-addr.arpa.
+www.spermbankcalifornia.com.
+cs.wikipedia.org.
+clkads.com.
+www.histats.com.
+a7.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+spicnic.com.
+s10.flagcounter.com.
+114.216.191.186.in-addr.arpa.
+bs2.yokacdn.com.
+accounts.google.com.
+406.cim.meebo.com.
+kkpfaq.bay.livefilestore.com.
+omnipure.com.
+millercenter.org.
+155.219.192.173.in-addr.arpa.
+multi21.thumb.edenflirt.com.
+125.116.204.190.in-addr.arpa.
+y2le2vcbd.y77z1m5m.
+antiguaguatemata.olx.com.gt.
+seq.es.
+www.google.com.
+safebrowsing-cache.google.com.
+plus.google.com.
+www.apple.com.
+concert-casse.de.
+voipb.sip.yahoo.com.
+4.218.15.189.in-addr.arpa.
+studiemetro.au.dk.
+www.linodriegheart.com.
+www.opselect.com.
+136.7.104.187.in-addr.arpa.
+r.mzstatic.com.
+mx.risotech.com.
+a2.sphotos.ak.fbcdn.net.
+underhile.blogspot.com.
+a.root-servers.net.
+socialsciences.uchicago.edu.
+jers2.info.
+foianasnoiansoim.blogspot.com.
+mail.fgisp.com.
+night-at-the-museum-3-trailer.blogspot.com.
+unarespuestaparacadapregunta.blogspot.com.
+www.cenetec.salud.gob.mx.
+a4.sphotos.ak.fbcdn.net.
+fxfeeds.mozilla.com.
+instagramers.com.
+smtp01.usccg.com.
+email-thewhitecompany.com.
+hotmail.com.
+profile.ak.fbcdn.net.
+about.tagged.com.
+forums.imore.com.
+176.0.195.108.in-addr.arpa.
+dns.msftncsi.com.
+favorites.live.com.
+idolbloglive.com.
+time.nist.gov.
+echo.edge.messenger.live.com.
+benbarnesfansite.blogspot.com.
+www.yumyume.com.
+google.com.
+duluxaddingcolourtopeopleslives.ru.
+sefora.b-rail.be.
+aka-cdn-ns.adtechus.com.
+photos-c.ak.fbcdn.net.
+www.bywifi.com.
+www.blogmktg.com.
+a.root-servers.net.
+mail-attachment.googleusercontent.com.
+friends.spy-from-sky.com.
+249.114.137.201.in-addr.arpa.
+66.197.168.192.in-addr.arpa.
+www.automoto.com.sv.
+www.investoronline.info.
+pruebas.amman.cervantes.es.
+sp.cwfservice.net.
+a.root-servers.net.
+nubuk.info.
+photos.merinews.com.
+90.64.50.182.in-addr.arpa.
+a.root-servers.net.
+lb._dns-sd._udp.belkin.
+www.sunrainly.com.
+unikomerc.ba.
+google.com.
+www.youtube.com.
+a.root-servers.net.
+partner.googleadservices.com.
+212.63.0.186.in-addr.arpa.
+surferbear.net.
+resolver4.pand.ctmail.com.
+18.133.159.201.in-addr.arpa.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+226.38.13.88.in-addr.arpa.
+yahoo.com.
+mail.dellen.com.
+221.90.113.186.in-addr.arpa.
+u.ytbbs.com.
+a.root-servers.net.
+teredo.ipv6.microsoft.com.
+67.113.174.109.in-addr.arpa.
+m.addthisedge.com.
+www.facebook.com.
+maygurney.co.uk.
+musicaclaro.com.
+www34.zippyshare.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+belindalove.com.
+www.mentalhealthy.co.uk.
+79.8.162.190.in-addr.arpa.
+ofmtrx381.20zs.
+www.microsoft.com.
+37.26.52.186.in-addr.arpa.
+cdn.krxd.net.
+www.packerchatters.com.
+demo.chevereto.com.
+i.imgur.com.
+m.addthisedge.com.
+ad-g.doubleclick.net.
+a.prisacom.com.
+rlcallahan.com.
+js.wlxrs.com.
+millerfh.com.
+f-passage.net.ru.lan.
+88.114.134.187.in-addr.arpa.
+14.65.146.187.in-addr.arpa.
+pbmnutritionals.com.s7b1.psmtp.com.
+mothernature.com.
+get.adobe.com.
+c.bing.com.
+www.facebook.com.
+107.113.51.190.in-addr.arpa.
+fxfeeds.mozilla.com.
+www.tenso.es.
+earthtech.co.uk.
+85.247.75.151.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+martinlibre.blogspot.com.
+210.176.250.190.in-addr.arpa.
+searchjs.s3.amazonaws.com.
+_120_46_5.
+bow.juegosfriv.us.
+_339_43_1.
+www.falomirjuegos.com.
+pato.ienter.net.
+lion-t.ru.
+www.facebook.com.
+www.escueladepadresprimerizos.com.
+www.subcarrie.com.
+weather.wapp.wii.com.
+time.windows.com.
+s-static.ak.facebook.com.
+104.75.176.190.in-addr.arpa.
+rv.ginyas.com.
+www.google.com.
+www.facebook.com.
+oceanparadise.com.
+168.179.50.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+ejabat.google.com.
+ax.init.itunes.apple.com.
+photos-f.ak.fbcdn.net.
+jacobsons.com.
+www.dentaldeml.com.
+fromportlandtopeonies.blogspot.com.
+redirector.c.youtube.com.
+129.50.168.192.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+p6y.ru.
+elfish-and-chips.learnenglishonline.yuku.com.
+ssl.gstatic.com.
+rss.news.yahoo.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mf1.bestbuy.selectionassistant.com.
+a.root-servers.net.
+a.root-servers.net.
+www.ipodnews.com.ar.
+profile.ak.fbcdn.net.
+www.provisum-illumina.com.
+microsoftwllivemkt.112.2o7.net.
+www.google-analytics.com.
+static.ak.fbcdn.net.
+www.aspoonfulofsugardesigns.com.
+a4.sphotos.ak.fbcdn.net.
+www.facebook.com.
+ie9cvlist.ie.microsoft.com.
+sp.cwfservice.net.
+c1.researchgate.net.
+webassets.sparkybee.com.
+ua.bname.ru.
+38.34.48.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+a1132.da1.akamai.net.
+233.241.88.2.in-addr.arpa.
+s-static.ak.fbcdn.net.
+147.197.165.190.in-addr.arpa.
+_362_64_1.
+www.ashidakim.com.
+teredo.ipv6.microsoft.com.
+www.megghy.com.
+:as3fwc5v.00zn.
+175.216.60.213.in-addr.arpa.
+122.124.179.190.in-addr.arpa.
+a.root-servers.net.
+clipfish.de.
+carmenmarques.blogspot.com.
+36.60.5.187.in-addr.arpa.
+j35i1w8gj.j19t9k7s.
+a.root-servers.net.
+19.77.228.67.in-addr.arpa.
+translateru.livejournal.com.
+sidewinder.makedesignnotwar.com.
+mm.admob.com.
+elpormsabb.tm.
+lefcobank.ru.
+www.starpirates.net.
+css.lainformacionalsegundo.com.
+otmail.com.
+oligoi.com.
+204.70.93.186.in-addr.arpa.
+dark-neo.cc.
+windows.microsoft.com.
+a2.sphotos.ak.fbcdn.net.
+197.16.18.186.in-addr.arpa.
+player.gametreat.com.
+www.update.microsoft.com.
+s-static.ak.facebook.com.
+www.trailertrashwhores.com.
+db._dns-sd._udp.lan.
+isatap.home.
+www.facebook.com.
+i2.ytimg.com.
+mail.netscape.everyone.net.
+hpinnigleek.polyvore.com.
+birdman.seriespepito.com.
+www.google.com.
+38-courier.push.apple.com.
+moritz.si.
+www.caepe.org.ar.
+photos-a.ak.fbcdn.net.
+214.18.168.192.in-addr.arpa.
+www.aurn.com.
+a.root-servers.net.
+deweysquare.com.s200b2.psmtp.com.
+ksn5-12.kaspersky-labs.com.
+teredo.ipv6.microsoft.com.
+crl.globalsign.net.
+static.ak.fbcdn.net.
+124.44.59.85.in-addr.arpa.
+www.google.com.
+cert-commerce.zune.net.
+idcindia.com.s7a2.psmtp.com.
+145.244.193.187.in-addr.arpa.
+mscrl.microsoft.com.
+photos-d.ak.fbcdn.net.
+www.mlfnt.com.
+wpad.
+_431_27_2.
+a3.sphotos.ak.fbcdn.net.
+vis.stanford.edu.
+ecpics.hardsextube.com.
+static.slide.com.
+124.54.209.190.in-addr.arpa.
+c2h1-roc.smtp.bti.net.ph.
+www.jmydm.com.
+pixel.facebook.com.
+mypacks.net.
+thethingsgirlslove.tumblr.com.
+spamhunter.attend.jp.
+m.facebook.com.
+246.54.42.201.in-addr.arpa.
+69.161.253.190.in-addr.arpa.
+us.data.toolbar.yahoo.com.
+a8.sphotos.ak.fbcdn.net.
+weather.services.conduit.com.
+time.chttl.com.tw.
+ro.wikipedia.org.
+americasbestlending.com.
+rsoserv.ru.
+www.google.com.
+a.root-servers.net.
+15.149.220.66.in-addr.arpa.
+a.root-servers.net.
+ec.atdmt.com.
+saabplus.ru.
+lead2net.net.
+coll.ning.com.
+www.nintendowifi.com.
+sgsp02.jvc-asia.com.sg.
+www.idiomaydeporte.com.
+tourshow.ru.
+qnkwpkntu.44dl.
+apis.google.com.
+193.67.139.190.in-addr.arpa.
+apps.facebook.com.
+es.dilandau.eu.
+www.weightlosseasytoday.com.
+90.210.160.201.in-addr.arpa.
+cdn-http.audio-bible.api.youversion.com.
+www.facebook.com.
+barbie-doll.programas-gratis.net.
+htri.net.s9a2.psmtp.com.
+googleads.g.doubleclick.net.
+plusone.google.com.
+a1.sphotos.ak.fbcdn.net.
+link.camelino.ca.
+www.facebook.com.
+8.130.194.190.in-addr.arpa.
+139.120.204.186.in-addr.arpa.
+accounts.google.com.
+st1.helpmycash.net.
+certifier.ru.
+translate.googleapis.com.
+83.235.177.190.in-addr.arpa.
+time-a.nist.gov.
+www.youtube.com.
+medexfol-online.ru.
+tatoogallery.info.
+i1.ytimg.com.
+215.221.139.216.zen.spamhaus.org.
+www.scootertechno.com.
+s0.2mdn.net.
+204.190.54.65.sbl-xbl.spamhaus.org.
+e-2dj6wdmigocjiho.stats.esomniture.com.
+120.145.170.201.in-addr.arpa.
+unpunto.com.
+dns.msftncsi.com.
+29.79.191.67.in-addr.arpa.
+209.157.121.200.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+ds.serving-sys.com.
+tnb3.4gayfetish.com.
+spktech.ru.
+platform.ak.fbcdn.net.
+2.bp.blogspot.com.
+csi.gstatic.com.
+eerie-cuties-italian.blogspot.com.
+44.13.148.189.in-addr.arpa.
+thetruthbehindthescenes.files.wordpress.com.
+www.celebrityhousepictures.com.
+169.57.237.204.in-addr.arpa.
+cdn3.picadmedia.com.
+static.genericlink.com.
+games.yahoo.com.
+a8.sphotos.ak.fbcdn.net.
+gravityjack.com.
+static.ak.fbcdn.net.
+platform.twitter.com.
+d15gt9gwxw5wu0.cloudfront.net.
+www.gstatic.com.
+a4.sphotos.ak.fbcdn.net.
+www.youtube.com.
+www.youtube.com.
+10.148.204.187.in-addr.arpa.
+ntp.glb.nist.gov.
+theshowguide.co.uk.
+223.243.35.189.in-addr.arpa.
+manfredi.ru.
+mail.mepc-consultants.com.
+static.ak.fbcdn.net.
+quatrx.com.
+profile.ak.fbcdn.net.
+2leep.com.
+www.pulpinternational.com.
+www.searchqu.com.
+mscrl.microsoft.com.
+www.rollingcounters.com.
+albavideo.blogspot.com.
+bouislendlease.com.
+fxfeeds.mozilla.com.
+nanmckay.com.
+fbcdn-profile-a.akamaihd.net.
+www.umi.com.co.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+211.219.103.190.in-addr.arpa.
+7072697361636f6d.313132.326f37.6e6574.80h42eb8ba6.webcfs00.com.
+a.root-servers.net.
+svali.ru.
+dnl-01.geo.kaspersky.com.
+www.google.com.
+cnfg.montiera.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+ax.init.itunes.apple.com.
+a1.sphotos.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+www.terapia-fisica.com.
+advoconsult.com.
+117.222.26.96.in-addr.arpa.
+client5.dropbox.com.
+3d.qdq.com.
+cs.wikipedia.org.
+0-56.channel.facebook.com.
+.
+122.164.100.177.in-addr.arpa.
+csmx5.sover.net.
+lgbp.podbean.com.
+safebrowsing-cache.google.com.
+www.operacarolina.org.
+time.chttl.com.tw.
+99.2.207.186.in-addr.arpa.
+prensaciudadana.com.
+maximonline.com.s7b1.psmtp.com.
+dns.msftncsi.com.
+binupdate.mail.ru.
+denis.stalker.h3q.com.
+wsubompxa.n29p1m0j.
+9.229.118.85.in-addr.arpa.
+tvtodo.com.
+wconect.com.br.
+fonts.googleapis.com.
+11.164.132.109.in-addr.arpa.
+eu.dockers.com.
+a5.sphotos.ak.fbcdn.net.
+www.elpuertodesantamaria.es.
+a6.sphotos.ak.fbcdn.net.
+_900_39_1.
+www.coches-es.com.
+relay-logs-p-1.oxigen.net.
+4.140.177.216.in-addr.arpa.
+bs.serving-sys.com.
+delta2.tatungmx.com.
+diantzdesign.info.
+en.wikipedia.org.
+www.deltares.nl.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+mail.santarosasells.com.
+wpad.corp.ipgnetwork.com.
+endtimespropheticwords.wordpress.com.
+kingsfurniture.co.uk.
+us.i1.yimg.com.
+gritton-com.mail.eo.outlook.com.
+174.203.39.190.in-addr.arpa.
+google.com.
+imap.gmail.com.
+lindson.com.
+www.phoenixpermaculture.org.
+pixel.facebook.com.
+245.244.28.120.in-addr.arpa.
+apps.facebook.com.
+twitter.com.
+photos-c.ak.fbcdn.net.
+167.236.174.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+c.msn.com.
+_603_12_1.
+www.youtube.com.
+db._dns-sd._udp.0.129.37.10.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+k7eku:l7b.e79p7f4d.
+insecta.isladejuegos.es.
+interaseo.com.co.
+amx.blueridgecarpet.com.redcondor.net.
+kissing-games.dressup.me.
+i2.ytimg.com.
+googleads.g.doubleclick.net.
+a7.sphotos.ak.fbcdn.net.
+47.181.240.216.in-addr.arpa.
+about-chinesefood.com.
+134.244.226.189.in-addr.arpa.
+buzzhunt.co.uk.
+www.facebook.com.
+s20.vuclip.com.
+af.avg.com.
+maturescreenshots.blogspot.com.
+www.googletagservices.com.
+domino.automation.rockwell.com.
+longisland.newsday.com.
+21.87.51.190.in-addr.arpa.
+whos.amung.us.
+202.82.184.201.in-addr.arpa.
+96.114.229.190.in-addr.arpa.
+alt1.gmail-smtp-in.l.google.com.
+a.root-servers.net.
+www.core-learning.com.
+samaratoday.ru.
+photos-f.ak.fbcdn.net.
+www.adobe.com.
+s4.histats.com.
+www.google.com.
+39.12.29.83.in-addr.arpa.
+agglo-lepuyenvelay.fr.
+cellbio.com.
+mail.honoe.com.
+artsyspot.disqus.com.
+www.can-global.com.
+static.ak.fbcdn.net.
+www.pickupsplus.com.
+a3.twimg.com.
+landingpages.bpcdn.net.
+go.srvnow.com.
+ntp.glb.nist.gov.
+cfh.wapp.wii.com.
+a6.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+surfcheap.com.
+uu1.orbitdownloader.com.
+mx.zwebtech.com.
+danlent.com.
+a.root-servers.net.
+3fdzznnil.74gj.
+59.214.38.187.in-addr.arpa.
+listas.20minutos.es.
+53.38.174.189.in-addr.arpa.
+a2.da1.akamai.net.
+www.google.com.
+www.facebook.com.
+248.232.187.186.in-addr.arpa.
+103.23.84.188.in-addr.arpa.
+mx1.triera.net.
+a.root-servers.net.
+cgey.com.
+blog.coquipr.com.
+gft-us.s3.amazonaws.com.
+rs992tl5.rapidshare.com.
+m.youtube.com.
+vertvdeportes.chatango.com.
+www.googleadservices.com.
+clients1.google.com.
+63.130.171.189.in-addr.arpa.
+gallery.clickthecity.com.
+static.ak.fbcdn.net.
+138.130.52.186.in-addr.arpa.
+secure-uk.imrworldwide.com.
+tag.admeld.com.
+12.63.6.189.in-addr.arpa.
+gmail.com.
+www.pixazza.com.
+adspaces.ero-advertising.com.
+comcast.net.
+pathway.net.com.
+141.196.8.200.in-addr.arpa.
+www.tetovani66.cz.
+www.eyesskyward.com.
+www.pantiesflash.com.
+img39.ownskin.com.
+google.com.
+graph.facebook.com.
+127.51.175.187.in-addr.arpa.
+thinbrowser.net.
+my.yahoo.com.
+a.root-servers.net.
+60.126.110.87.in-addr.arpa.
+www.televisa.com.ar.
+158.110.172.187.in-addr.arpa.
+www.empresaexterior.com.
+www.luismiguelsite.com.
+mass10.massmulti.hop.clickbank.net.
+133.184.68.67.in-addr.arpa.
+45.coll.ning.com.
+ax.init.itunes.apple.com.
+audrinaxo.celebuzz.com.
+bug.report.url.
+www.nimsoft.com.
+www.alltimemedical.com.
+195.26.36.186.in-addr.arpa.
+sun.idiom.com.
+profile.ak.fbcdn.net.
+27.243.132.190.in-addr.arpa.
+www.hi.is.
+19.10.73.190.in-addr.arpa.
+productads.amazon.com.
+toc.music.metaservices.microsoft.com.
+www.google.com.
+www.tubepleasure.com.
+feedburner.google.com.
+hhgo.com.
+apps.facebook.com.
+www.carlberry.co.uk.
+tiger.apscc.nau.edu.
+103.122.32.83.in-addr.arpa.
+www.google.com.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+www.belkin.com.
+a.root-servers.net.
+a.root-servers.net.
+fogeli.co.il.
+api.webrep.avast.com.
+safebrowsing-cache.google.com.
+googleads.g.doubleclick.net.
+mx.dreambuilderspr.com.
+fr-fr.facebook.com.
+232.103.158.109.in-addr.arpa.
+25.218.72.190.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+spam3.fpinet.net.
+safebrowsing-cache.google.com.
+110.253.206.173.in-addr.arpa.
+56.216.73.190.in-addr.arpa.
+www.imdb.com.
+yahoo.ccom.
+8.174.115.66.in-addr.arpa.
+pagead2.googlesyndication.com.
+digitalcommons.pace.edu.
+kamalballan.ru.
+212.92.159.189.in-addr.arpa.
+220.10.183.189.in-addr.arpa.
+168.61.87.186.in-addr.arpa.
+clients1.google.com.
+thedottedi.net.
+download.skype.com.
+90.92.255.190.in-addr.arpa.
+personal.de.avira-update.net.
+news.google.nl.
+webcache.googleusercontent.com.
+google.com.mx.
+a1.mzstatic.com.
+srtravel.com.
+d37saox78.s55w4m9r.
+translate.googleapis.com.
+utilestoonix.wordpress.com.
+www.rsagroup.com.ar.
+pjpur.tripod.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.treadmill-ratings-n-reviews.net.
+a5.sphotos.ak.fbcdn.net.
+col.stb00.s-msn.com.
+photos-g.ak.fbcdn.net.
+www.dasa.mod.uk.
+pixel.facebook.com.
+www.humansciences.mq.edu.au.
+9nl37njin.m42h4c9p.
+tc.v4.cache4.c.pack.google.com.
+diamondgame.com.s9a1.psmtp.com.
+fmc8jixpr.39vi.
+b.scorecardresearch.com.
+www.facebook.com.
+photos-d.ak.fbcdn.net.
+12.142.121.95.in-addr.arpa.
+67.220.49.71.in-addr.arpa.
+as.cd.impact-ad.jp.
+ksn1-11-part1.kaspersky-labs.com.
+ksn3-11.part2.kaspersky-labs.com.
+smtp.evidence.com.
+www.usrecallnews.com.
+63.112.212.201.in-addr.arpa.
+55.15.237.189.in-addr.arpa.
+231.252.24.72.in-addr.arpa.
+plusone.google.com.
+a2.sphotos.ak.fbcdn.net.
+www.bywifi.com.
+elcaballerodelaluna2.blogspot.com.
+clients1.google.com.
+dolarhoy.com.
+csi.gstatic.com.
+www.apple.com.
+web.de.
+s.ytimg.com.
+sedty.com.
+a6.sphotos.ak.fbcdn.net.
+ws.faad.co.
+86.120.189.24.in-addr.arpa.
+e3353.c.akamaiedge.net.
+www.cidra.com.
+sundogfirearms.com.
+a995.mm1.akamai.net.
+pix.speedbit.com.
+platform.linkedin.com.
+dns.msftncsi.com.
+www.diariopyme.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+guidosfreshmaretplace.com.
+mail.mcewancpa.com.
+a.root-servers.net.
+227.212.171.189.in-addr.arpa.
+248.216.82.200.in-addr.arpa.
+nist1-sj.ustiming.org.
+corplodging.com.2.0001.arsmtp.com.
+87.100.93.201.in-addr.arpa.
+a.root-servers.net.
+www.maximhuerta.com.
+www.gmail.google.com.
+_ldap._tcp.
+wnu.naughtyamerica.com.
+www.googleadservices.com.
+p02-mobilebackup.icloud.com.akadns.net.
+www.update.microsoft.com.
+www.kingmax.com.
+secure.shared.live.com.
+mtalk.google.com.
+i3.tagstat.com.
+mail.megasila.ru.
+www.boom.ge.
+my.bureauveritas.com.
+profile.ak.fbcdn.net.
+ess.khhq.net.
+www.diaryofstyleblog.com.
+us.tomsgames.com.
+91.68.152.81.in-addr.arpa.
+clients2.google.com.
+www.germanshepherdrescue.co.uk.
+profile.ak.fbcdn.net.
+91.253.164.85.in-addr.arpa.
+mail2.adcohvac.com.
+21.27.26.201.in-addr.arpa.
+eanes.k12.tx.us.
+164.81.135.187.in-addr.arpa.
+media.photobucket.com.
+218.224.227.61.in-addr.arpa.
+172.192.138.174.in-addr.arpa.
+243.77.7.75.in-addr.arpa.
+rad.msn.com.
+www.collegepartyhouse.com.
+apps.facebook.com.
+sad-stone.com.
+www.iwdeepblowjob.com.
+55.33.220.186.in-addr.arpa.
+a.root-servers.net.
+ca.answers.yahoo.com.
+profile.ak.fbcdn.net.
+listorbit.net.
+201.51.21.190.in-addr.arpa.
+19.246.215.201.in-addr.arpa.
+cdn.api.twitter.com.
+ausdcx64amer19.amer.dell.com.
+i3.ytimg.com.
+elpoderdelpensamientopositivo.over-blog.es.
+a8.sphotos.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+invision-studios.com.
+c0013979.ssl.cf1.rackcdn.com.
+samzas.ru.
+shadow.atkingdom.com.
+corporateapartmentsinbrazil.com.
+adornatusolapa.blogspot.com.
+rock799.no-ip.biz.
+static.ak.connect.facebook.com.
+139.154.171.189.in-addr.arpa.
+time.chttl.com.tw.
+sa.bbc.com.
+220.122.146.189.in-addr.arpa.
+widgets.montiera.com.
+www.rdistore.com.
+mx.medwell.us.
+ads2.msads.net.
+creative.ak.fbcdn.net.
+i1.ytimg.com.
+mail.red-wagon.com.
+mozilla.cdn.leaseweb.com.
+search2.fcc.gov.
+intelisyscorp.com.inbound10.mxlogic.net.
+a.root-servers.net.
+englishpod.com.
+b.c-0.19-21095008.30081.1518.19d3.3ea1.410.0.rqw7f386mgq5i2vj71kkslquhj.avqs.mcafee.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+212.23.87.190.in-addr.arpa.
+skype.com.multi.surbl.org.
+alerts.conduit-services.com.
+www.facebook.com.
+s.ytimg.com.
+e3353.c.akamaiedge.net.
+p.twimg.com.
+time.chttl.com.tw.
+static.ak.fbcdn.net.
+www.undecimahora.org.
+www.cronistasoficiales.com.
+cid-a602674d8489e429.users.storage.live.com.
+cs10095.vk.com.
+b.scorecardresearch.com.
+i4.ytimg.com.
+www.abc.es.
+www.laprovinciadicremona.it.
+a.root-servers.net.
+store.urge.com.
+a3.sphotos.ak.fbcdn.net.
+urs.microsoft.com.
+bioguide.congress.gov.
+65.65.204.187.in-addr.arpa.
+harbingermortgage.com.
+a1.sphotos.ak.fbcdn.net.
+phx-sync552.services.mozilla.com.
+plusone.google.com.
+4105616.frasesinolvidables1.com.ar.
+plus.google.com.
+www.adidasrunningday.com.
+a0.twimg.com.
+tracker.thepiratebay.org.
+tinypets.tinyco.com.
+external.ak.fbcdn.net.
+203.96.51.190.in-addr.arpa.
+gs-loc.isg-apple.com.akadns.net.
+a3.sphotos.ak.fbcdn.net.
+instagr.am.
+thinkitsystems.net.
+nefteport.ru.
+a.root-servers.net.
+a3.twimg.com.
+elite-servers.com.ua.
+www.ps2-fate.com.
+imap-ssl.mail.yahoo.com.
+img.atwiki.jp.
+creative.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+prada-love.tumblr.com.
+inbound.onecallcom.net.netsolmail.net.
+www.coverjunkie.com.
+www.remediar.gov.ar.
+221.150.71.93.in-addr.arpa.
+www.itescam.edu.mx.
+www.cumtobun.com.
+static.ak.fbcdn.net.
+google.com.
+es.wikipedia.org.
+.
+relay.voice.edge.messenger.live.com.
+246.202.58.186.in-addr.arpa.
+s-static.ak.facebook.com.
+151.60.104.86.in-addr.arpa.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+144.251.27.190.in-addr.arpa.
+download.windowsupdate.com.
+schomburg.ru.s200a2.psmtp.com.
+www.scanalert.com.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+grim.bungie.org.
+photos-h.ak.fbcdn.net.
+www.kktanhp.com.
+mailserver.pacificlifegroup.com.
+199.192.176.189.in-addr.arpa.
+170.19.230.189.in-addr.arpa.
+antropologia-online.blogspot.com.
+ccbill.com.
+live-receptionist.com.
+i1118.photobucket.com.
+dipaul.ru.
+meta.charlesworks.com.
+mail.yimg.com.
+s0.2mdn.net.
+rcanoevents.com.1.0001.arsmtp.com.
+lb._dns-sd._udp.0.224.16.172.in-addr.arpa.
+shtoryizabel.ru.
+186.99.152.187.in-addr.arpa.
+thumbs1.ebaystatic.com.
+68.95.82.203.in-addr.arpa.
+a.root-servers.net.
+ntp.glb.nist.gov.
+allenskenpojujitsu.com.
+subs.sams.bw.semcs.net.
+api.twitter.com.
+www.waynegraham.com.
+sovitas.ru.
+crl.microsoft.com.
+lindsey.edu.
+106.249.143.201.in-addr.arpa.
+30.100.217.166.in-addr.arpa.
+wonder-shop.ru.
+cloud-search.linkury.com.
+138.76.22.113.in-addr.arpa.
+www.mayhemuk.co.uk.
+www.clubmaxmikita.com.
+www.bollywoodsamachar.com.
+www.calibex.com.
+v1.cache2.c.youtube.com.
+ajax.googleapis.com.
+xyte4aqlg.m68c7c4h.
+a1408.w43.akamai.net.
+wy.com.
+kiel.de.
+dns.msftncsi.com.
+2ab7t4h6m.k78x4b0y.
+api.conduit.com.
+a.root-servers.net.
+ocsp.dpwn.net.
+claritycvc.com.
+www.facebook.com.
+ingdirect.com.au.
+picasaweb.google.ca.
+clients2.google.com.
+mi-technologies.com.2.0001.arsmtp.com.
+www.skankazoid.com.
+mail2.micci.com.
+221.209.223.201.in-addr.arpa.
+www.xvideosdecul.com.
+e-press.ru.
+apps.facebook.com.
+tracking.traviangames.com.
+assets.dealply.com.
+s-static.ak.fbcdn.net.
+jbtfoodtech.ru.
+s0.2mdn.net.
+message.real.com.
+eo.wikipedia.org.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+mail2.sw-hk.com.
+wow.lk.
+google.com.
+upload.wikimedia.org.
+h.live.com.
+www.facebook.com.
+caifane.blogspot.com.
+col.stb00.s-msn.com.
+savoia.net.
+steveelling.blogs.cbssports.com.
+13.222.149.186.in-addr.arpa.
+109.221.29.99.in-addr.arpa.
+1.bp.blogspot.com.
+204.228.40.83.in-addr.arpa.
+www.google-analytics.com.
+mitmproxy.org.
+s1016.photobucket.com.
+getaway-travel.com.
+231.241.19.176.in-addr.arpa.
+si0.twimg.com.
+a.root-servers.net.
+www.graduatearchitecture.com.
+a.root-servers.net.
+s-static.ak.facebook.com.
+katolicamusic.blogspot.com.
+edge.quantserve.com.
+treocapitalgroup.com.inbound10.mxlogicmx.net.
+pixel.facebook.com.
+204.122.253.189.in-addr.arpa.
+bmx.waseca.k12.mn.us.redcondor.net.
+a8.sphotos.ak.fbcdn.net.
+s.youtube.com.
+apps.facebook.com.
+www.arquimov.com.ar.
+bton.ac.uk.
+138.104.114.87.in-addr.arpa.
+ad.where.com.
+pagead2.googlesyndication.com.
+orcart.facebook.com.
+pubads.g.doubleclick.net.
+ak.imgfarm.com.
+a.root-servers.net.
+r._dns-sd._udp.lan.
+www.proyectar.com.mx.
+mtalk.google.com.
+latin.technetium.be.
+mail.eastwardho.net.
+g8ajzzxh9.94pm.
+ssl.gstatic.com.
+www.maxgxl.com.
+jamesdot.com.
+53.224.89.186.in-addr.arpa.
+www.googletagservices.com.
+bonzacards.com.
+gei.net.
+ordrmopmmiihqhhe.com.
+www.youtube.com.
+217.160.41.200.in-addr.arpa.
+es.sizegainplus.com.
+www.facebook.com.
+m7j3m1z4j.77nz.
+corelmania.com.
+s.ytimg.com.
+104.173.110.189.in-addr.arpa.
+indore.quikr.com.
+lasmilcancionesdel2000.blogspot.com.
+photos-f.ak.fbcdn.net.
+static.app.widdit.com.
+inbound.sonicvision.com.netsolmail.net.
+google.com.
+mx.ce.net.cust.a.hostedemail.com.
+jytv5afi4.u78b4g3g.
+photos-c.ak.fbcdn.net.
+spritelight.com.
+b.mouseflow.com.
+194.71.119.46.in-addr.arpa.
+o2ejza2hs.s86w6c5a.
+external.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+login.live.com.
+etown.k12.ky.us.
+www.setyourtiming.com.
+mke-inc.com.inbound25.mxlogic.net.
+huntergathererer.blogspot.com.
+net.philsite.net.
+register.hp.com.
+bluelight.net.
+32.250.228.190.in-addr.arpa.
+plusone.google.com.
+blcomp.co.uk.
+api.twitter.com.
+chilloutpoint.com.
+yui.yahooapis.com.
+dc-mail-f01.quelle.ru.
+a4.sphotos.ak.fbcdn.net.
+ad-g.doubleclick.net.
+mx6.me.com.akadns.net.
+vidavet.es.
+227.201.69.173.in-addr.arpa.
+0.tqn.com.
+xetgs.xboxlive.com.
+ikoo.zedo.com.
+blackberryforums.pinstack.com.
+apps.facebook.com.
+www.elimperiodelsexo.com.
+kb2.adobe.com.
+algebraweb.net.
+ashes-to-ashes.seriespepito.com.
+113.37.198.190.in-addr.arpa.
+mail.alivegames.com.
+theiphonewiki.com.
+ssl.gstatic.com.
+teredo.ipv6.microsoft.com.
+198.78.122.84.in-addr.arpa.
+www.thecopiercompany.com.au.
+www.10wallpaper.com.
+bmlfuw.gv.at.
+www.googletagservices.com.
+14.179.192.187.in-addr.arpa.
+www.google.com.
+www.adobe.com.
+238.163.230.85.in-addr.arpa.
+cdn.api.twitter.com.
+www.fat-sex.net.
+www.adidaswings-au.com.
+a.root-servers.net.
+www.flowersfoods.com.
+www.qw.com.
+loading5.widdit.com.
+xmpp003.hpeprint.com.
+www.flowelectro.net.
+b._dns-sd._udp.lan.
+statse.webtrendslive.com.
+156.165.86.201.in-addr.arpa.
+252.143.159.189.in-addr.arpa.
+affiliation.qcnscruise.com.
+rcp.na.blackberry.com.
+s-static.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+nerienlouper.tv-replay.fr.
+photos-a.ak.fbcdn.net.
+home.mywebsearch.com.
+googleads.g.doubleclick.net.
+www.maturebritish.com.
+api-read.facebook.com.
+fr-fr.facebook.com.
+creative.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+www.kanjukulive.com.
+a.root-servers.net.
+video.dailynylongalleries.com.
+ktpae.gr.
+www.wallcreate.com.
+homta.ajaxpong.com.
+arms.kazan.su.
+a.root-servers.net.
+www.regaloselescaparate.com.
+gogil.com.
+photos-d.ak.fbcdn.net.
+www.update.microsoft.com.
+www.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+14.118.74.189.in-addr.arpa.
+plus.google.com.
+a.root-servers.net.
+world3.knightfight.se.
+nickzucc.blogspot.com.
+www.google.com.
+www.neoreviews.org.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+lifestyle.allwomenstalk.com.
+google.com.
+.
+platform.twitter.com.
+okmbui.com.
+a8.sphotos.ak.fbcdn.net.
+s.ytimg.com.
+5mkqtnqxl.15db.
+a3.sphotos.ak.fbcdn.net.
+www.epoxyproducts.com.
+ymcabra.org.
+mail.abix.ch.
+www.arrowofmorality.com.
+images.dragspecialties.com.
+232.45.1.201.in-addr.arpa.
+89.167.195.190.in-addr.arpa.
+www.rareflora.com.
+sn1msg1010720.gateway.messenger.live.com.
+www.movietome.com.
+a4.sphotos.ak.fbcdn.net.
+www.wupload.com.
+110.158.89.201.in-addr.arpa.
+yui.yahooapis.com.
+guzzoni.apple.com.
+www.tusconfesiones2.com.ar.
+30.178.241.201.in-addr.arpa.
+tynan-darcy.com.s200a2.psmtp.com.
+accounts.google.com.
+arorafashions.com.
+wikisource-lb.pmtpa.wikimedia.org.
+239.7.137.118.in-addr.arpa.
+.
+rpig-ltd.com.
+107.197.148.189.in-addr.arpa.
+messenger.hotmail.com.
+bg.stylem.com.
+a.root-servers.net.
+3.186.242.200.in-addr.arpa.
+static.cyworld.com.cn.
+updatekeepalive.mcafee.com.
+www.ge.com.
+www.aynax.com.
+griffin.co.uk.
+profile.ak.fbcdn.net.
+87lf3f6hh.11xi.
+theplazaregency.com.
+nordfarm.se.
+ad.yieldmanager.com.
+aol.com.
+217.199.165.141.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+1.189.35.187.in-addr.arpa.
+toolbarqueries.google.com.
+94.151.55.189.in-addr.arpa.
+1.gravatar.com.
+fs19.formsite.com.
+ajax.googleapis.com.
+rts.phn.doublepimp.com.
+graph.facebook.com.
+mmi.explabs.net.
+www.podtropolis.com.
+ads.mbendi.com.
+ssl.gstatic.com.
+ad19.feeldmc.com.
+polynext.ru.
+hotmail.com.
+pagead2.googlesyndication.com.
+ajax.googleapis.com.
+a.root-servers.net.
+_ldap._tcp.
+mx1.overline.com.
+artion.dk.
+www.mediatoday.co.kr.
+ask.scriptmafia.org.
+kay.cantonrep.com.
+pixel.quantserve.com.
+182.156.136.190.in-addr.arpa.
+secure.wlxrs.com.
+files.discountechnology.com.
+oascentral.stackmag.com.
+i3.ytimg.com.
+www.dcx.co.kr.
+external.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+bbb.at.
+assets1.procpr.org.
+internet.sbi.com.
+ii7kgap58.n62f8h9a.
+zynga1-a.akamaihd.net.
+c14.smaato.net.
+inbound.sbmelectronics.com.cust.comcastmailservice.com.
+a5.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+inbound.theangelus.com.netsolmail.net.
+id.google.com.mx.
+safebrowsing-cache.google.com.
+171.20.58.186.in-addr.arpa.
+www.hippiecamper.com.
+6-courier.sandbox.push.apple.com.
+ssl.google-analytics.com.
+vcm.cz.
+dev.
+mail.rootcom.net.
+a.root-servers.net.
+b._dns-sd._udp.lan.
+photos-d.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+randbrentals.com.
+a.root-servers.net.
+m.addthisedge.com.
+a.root-servers.net.
+166.81.68.201.in-addr.arpa.
+ludys.com.
+tgppsd2.triad-group.net.
+powerspan.com.s8b2.psmtp.com.
+d2100078.xoom.it.
+m.adnxs.com.
+a.analytics.yahoo.com.
+c-0.19-230f1041.40081.1518.19d3.3ea1.410.0.kn9e331jip5d71gr69pjl3h56t.avqs.mcafee.com.
+www.pandora.com.
+www.foxsportsla.com.
+.
+apis.google.com.
+psdresources.com.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+media.wix.com.
+www.milksmartmama.com.
+www.bywifi.com.
+229.19.167.187.in-addr.arpa.
+internet.downv.com.
+portal9.7803986842.com.
+a.root-servers.net.
+pixel.facebook.com.
+121.199.247.92.in-addr.arpa.
+pcim-02.psohealth.com.
+pix04.revsci.net.
+32-courier.push.apple.com.
+gate.ygi.msk.ru.
+www.drtubercams.com.
+wpqsl2zh6.24zh.
+clients1.google.com.
+s.sharecare.com.
+www.everycollegegirl.com.
+pixel.facebook.com.
+s0.2mdn.net.
+113.184.30.190.in-addr.arpa.
+a.root-servers.net.
+3.189.31.83.in-addr.arpa.
+msc.wlxrs.com.
+dsflash.es.
+boq.com.
+ssl.gstatic.com.
+storage.conduit.com.
+a8.sphotos.ak.fbcdn.net.
+static1.spilcdn.com.
+fbcdn-profile-a.akamaihd.net.
+i4.ytimg.com.
+mail.advancebankus.com.
+joequispe.com.
+www.ic.daad.de.
+www.rackspace.com.
+connect.facebook.net.
+mail.mced.com.
+125.189.176.66.in-addr.arpa.
+w7fwzaaue.22iq.
+clients1.google.com.
+cgi1.ebay.com.
+acs.manuscriptcentral.com.
+www.humor1.net.
+139.197.86.200.in-addr.arpa.
+www.wordreference.com.
+139.105.47.211.in-addr.arpa.
+piola.it.
+a2.sphotos.ak.fbcdn.net.
+es.kioskea.net.
+berry71bleu.blogspot.com.
+user.ipcam.hk.
+i55.tinypic.com.
+transword.ru.
+veronicascornucopia.com.
+common.retronyms.com.
+vestidosdenovia.ybodas.com.
+sc2.rules.mailshell.net.
+free-math.ru.
+euro2012.interia.pl.
+kumisenshi.cl.
+a.root-servers.net.
+google.com.
+garaj.ru.
+a.root-servers.net.
+crl.thawte.com.
+www.investir.fr.
+a7.sphotos.ak.fbcdn.net.
+246.162.250.201.in-addr.arpa.
+140.14.0.181.in-addr.arpa.
+145.230.211.201.in-addr.arpa.
+join.tissuequeens.com.
+support.google.com.
+tap2-cdn.rubiconproject.com.
+freewebdesigntutorials.com.
+134.105.232.24.in-addr.arpa.
+fr-fr.facebook.com.
+www.pigeonelite.com.
+84.7.35.81.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+v7f61npcy.87gs.
+t2.gstatic.com.
+csi.gstatic.com.
+hotmail.com.
+tick.stdtime.gov.tw.
+a.root-servers.net.
+a.root-servers.net.
+a.root-servers.net.
+co.portage.wi.us.
+www.anastasianielsen.com.
+g.live.com.
+i4.ytimg.com.
+184.156.183.189.in-addr.arpa.
+sites.google.com.
+apps.facebook.com.
+124.56.167.187.in-addr.arpa.
+www.varieteguineenne.com.
+i41.tinypic.com.
+neilpeart.net.
+mail.philadelphiasign.com.
+i3.ytimg.com.
+ss7g3r43p.x26f9p9g.
+mail.cvproducts.com.
+a.root-servers.net.
+www.cepesju.org.
+144.84.90.186.in-addr.arpa.
+197.12.122.187.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.luna-maya.com.
+m.ak.fbcdn.net.
+bicycling.about.com.
+m4.licdn.com.
+alertas.wikio.es.
+content.yieldmanager.edgesuite.net.
+partner.googleadservices.com.
+artisticaccentsonline.com.
+zynga2-a.akamaihd.net.
+29.61.224.190.in-addr.arpa.
+platform.ak.fbcdn.net.
+www.adultsitelaw.com.
+m.google.com.
+www.medicalfashioncollection.com.
+profile.ak.fbcdn.net.
+fotos.muyzorras.com.
+maricarmensalas.blogspot.com.
+www.bsef.com.
+46.99.139.112.in-addr.arpa.
+checkip.dyndns.org.
+61.125.234.95.in-addr.arpa.
+ocsp.thawte.com.
+www.milfgfs.com.
+111.206.152.189.in-addr.arpa.
+socinforum.ru.
+orig-10006.conduit.cotcdn.net.
+orosucio.madryn.com.
+1.203.159.189.in-addr.arpa.
+udc.msn.com.
+photos-e.ak.fbcdn.net.
+inbound.advancedidcorp.com.netsolmail.net.
+182.82.37.81.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+www.youtube.com.
+a4.sphotos.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+ad.yieldmanager.com.
+69.180.29.183.in-addr.arpa.
+www.mundoforo.com.
+ajax.googleapis.com.
+connect.facebook.net.
+chatenabled.mail.google.com.
+clients1.google.com.
+98.1.56.157.in-addr.arpa.
+accentlights.com.
+cdn.api.twitter.com.
+vocypyt.com.
+182.125.168.192.in-addr.arpa.
+pflanigan.com.
+sites.google.com.
+zman22674.u.yuku.com.
+hulkshare.com.
+imgn.dt07.net.
+motors.shop.ebay.com.
+iframes.wildfireapp.com.
+static.ak.fbcdn.net.
+gfx5.hotmail.com.
+plusone.google.com.
+a.root-servers.net.
+www.colby-sawyer.edu.
+kiss.crimea.ua.
+tc26.easythumbhost.com.
+js.wlxrs.com.
+40.154.192.187.in-addr.arpa.
+loading.retry.widdit.com.
+fsedistffalal.mp.
+www.gstatic.com.
+msc.wlxrs.com.
+a.c.2s-0.19-a70f0211.5140081.1518.19d4.3ea1.210.0.v1gz6g6fhcftq9amdt4ssmde7v.avqs.mcafee.com.
+intellanetad.com.
+piclist.friendfinder.com.
+115.214.30.78.in-addr.arpa.
+iphone-wu.apple.com.
+world76.runescape.com.
+google.com.
+etehplus.ru.
+gillmorgang.techcrunch.com.
+www.google-analytics.com.
+www.smartbuyglasses.co.uk.
+boolable.ca.
+developers.facebook.com.
+www.bambi.de.
+www.shantaram.com.
+photos-g.ak.fbcdn.net.
+cluster8.eu.messagelabs.com.
+a.root-servers.net.
+services.winamp.com.
+photo-tech.com.
+www.backlink.de.lv.
+www.facebook.com.
+ygj32yzri.k84m7d4c.
+www.wikimapia.com.
+a1.sphotos.ak.fbcdn.net.
+120.204.195.187.in-addr.arpa.
+mlocate.spotlife.net.
+agmennox.ru.
+quickpay.carmunity.de.
+www.yobt.com.
+templatesaver.com.
+webcache.googleusercontent.com.
+www.curious-straight-boys.com.
+75.67.199.190.in-addr.arpa.
+facebook.com.
+realtracks.com.
+hulkshare.com.
+142.249.82.200.in-addr.arpa.
+mailserver.knebworthhouse.com.
+www.derechopenalenlared.com.
+s-static.ak.facebook.com.
+www9.effectivemeasure.net.
+t1.pdanet.co.
+www.facebook.com.
+daviscollege.edu.inbound25.mxlogicmx.net.
+mail.iwlink.net.
+c76.altospam.com.
+time.chttl.com.tw.
+supl.nokia.com.
+neuffr.lan.
+xmjbyvveu.j52d7p9s.
+mx.quartz.synacor.com.
+93.95.243.189.in-addr.arpa.
+www.bitdefender.com.
+id.google.com.
+ib.adnxs.com.
+pop.gmx.de.
+238.166.172.189.in-addr.arpa.
+24.147.161.189.in-addr.arpa.
+102.151.28.75.in-addr.arpa.
+newtab.conduit-hosting.com.
+mail.kiwa.nl.
+s-static.ak.fbcdn.net.
+85.168.120.200.in-addr.arpa.
+96.167.30.46.in-addr.arpa.
+www.creaturespot.com.
+141.16.158.190.in-addr.arpa.
+us.bc.yahoo.com.
+52.221.165.122.in-addr.arpa.
+mail.triwarp.com.
+bo.portalmundos.com.
+download808.avast.com.
+u6790.96.spylog.com.
+teredo.ipv6.microsoft.com.
+www.futbolgesdeport.com.
+touch.facebook.com.
+bh.contextweb.com.
+101.239.49.190.in-addr.arpa.
+cinema.gallery.net.pluzmedia.com.
+28.213.141.201.in-addr.arpa.
+hurkens.iae-csic.org.
+mailx1.iitm.ac.in.
+a.root-servers.net.
+144.178.43.190.in-addr.arpa.
+www.nelsonautonews.com.
+wpad.home.
+www.tifozi.info.
+interact.com.
+28.18.17.190.in-addr.arpa.
+t1:gss52f.14dg.
+127.120.145.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+folkloremiperu.com.
+mail.minowitz.com.
+123.37.229.189.in-addr.arpa.
+ax.init.itunes.apple.com.
+213.121.57.71.in-addr.arpa.
+6.130.164.81.in-addr.arpa.
+www.bdsm365.net.
+ur2mkumun.z98p4i6l.
+s-3.com.
+js.revsci.net.
+fusion.google.com.
+75.208.2.88.in-addr.arpa.
+ad.doubleclick.net.
+macbeth.com.
+quienmemandabaami.blogspot.com.
+westarfunds.com.
+narcosphere.narconews.com.
+a5.sphotos.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+www.earningdiary.com.
+67.53.212.201.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+fxfeeds.mozilla.com.
+157.57.210.178.in-addr.arpa.
+a1920.g.akamai.net.
+a180.v.phobos.apple.com.
+a.root-servers.net.
+bay.messenger.services.live.com.
+www.golinker.com.
+84.233.28.190.in-addr.arpa.
+www.google-analytics.com.
+photos-h.ak.fbcdn.net.
+i2.ytimg.com.
+www.dirtydatinglive.com.
+s.ytimg.com.
+apis.google.com.
+tracker.torrentbox.com.
+a4.sphotos.ak.fbcdn.net.
+d1j68ux4ukg4g1.cloudfront.net.
+_625_60_6.
+www.facebook.com.
+aglobal.go.com.
+113.246.140.220.in-addr.arpa.
+widgets.twimg.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+static.ak.fbcdn.net.
+252.187.250.201.in-addr.arpa.
+i4.ytimg.com.
+pixel.facebook.com.
+eaamericas.ecolab.com.
+25.204.58.95.in-addr.arpa.
+twitter.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+vu57aqmik.48mp.
+semivrat.ru.
+www.ikenvape.com.
+db5:3:3qv.25wf.
+www.moviequotesandmore.com.
+chorrol.com.
+mail.wingscc.com.
+cdn.api.twitter.com.
+i3.ytimg.com.
+de-de.facebook.com.
+t1.softonicads.com.
+pubads.g.doubleclick.net.
+smtp.xcountry.tv.
+240.12.166.71.in-addr.arpa.
+profile.ak.fbcdn.net.
+237.17.126.188.in-addr.arpa.
+www.mcanime.net.
+content.yieldmanager.edgesuite.net.
+imagos.escortsite.com.
+monster.frivmini.com.
+98.250.219.80.in-addr.arpa.
+connect.facebook.net.
+78.225.90.84.in-addr.arpa.
+irohe.blogspot.com.
+apture.com.
+q1sx3dd:r.70jg.
+www.nptdiy.com.
+metric.starz.com.
+profile.ak.fbcdn.net.
+webres4.pand.ctmail.com.
+photos-d.ak.fbcdn.net.
+208.244.158.189.in-addr.arpa.
+tottuas.com.
+s-static.ak.facebook.com.
+tyler.newsvine.com.
+www.youpron.com.
+mail.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mailserver.s21.com.
+creative.ak.fbcdn.net.
+vuelohotel.airfrance.es.
+s7.addthis.com.
+rhyason.com.
+www.bankresearch.org.
+cdn.api.twitter.com.
+restat.com.s9a1.psmtp.com.
+apis.google.com.
+cn1.redswoosh.akadns.net.
+static.ak.fbcdn.net.
+groups.live.com.
+113.154.134.186.in-addr.arpa.
+www.facebook.com.
+rad.msn.com.
+www.facebook.com.
+80.74.141.201.in-addr.arpa.
+vlcr9ii:2.01cs.
+dns.msftncsi.com.
+www.netlog.com.
+a47.photo.store.qq.com.
+youtu.be.
+37.21.154.189.in-addr.arpa.
+s1.trrsf.com.
+34-courier.push.apple.com.
+img.mediaplex.com.
+141.16.174.190.in-addr.arpa.
+www.googleadservices.com.
+jo.countrysearch.tradekey.com.
+mail.google.com.
+networld.com.
+www.wowjobs.co.nz.
+a.root-servers.net.
+mscrl.microsoft.com.
+_312_06_2.
+isvw2.rurallink.gov.my.
+a7.sphotos.ak.fbcdn.net.
+crl.microsoft.com.
+ksde.org.
+tenesol-al.com.
+sites.google.com.
+mail2open.com.
+www.allposters.nl.
+brigadadesaludpopular.blogspot.com.
+200.26.68.108.in-addr.arpa.
+mx1.ynemail.com.
+_790_51_8.
+174.108.193.200.in-addr.arpa.
+support.google.com.
+www.msftncsi.com.
+rmonline.actionsystems.com.
+106.24.195.210.in-addr.arpa.
+es.answers.yahoo.com.
+www.cadaver.org.
+170.2.250.111.in-addr.arpa.
+www.google.com.
+64.107.24.98.in-addr.arpa.
+drcranton.com.
+www.disenowebenmexico.com.
+folkartmuseum.org.
+i1.ytimg.com.
+clock.fmt.he.net.
+g.msn.com.
+mail.rfpl.org.
+discoverwaterfront.com.
+44.73.231.78.in-addr.arpa.
+mandiloves.wordpress.com.
+az15112.vo.msecnd.net.
+cfefd.com.
+tc.v2.cache6.c.youtube.com.
+netzero.net.
+googleads.g.doubleclick.net.
+46.232.50.200.in-addr.arpa.
+rhpoultry.com.
+.
+accounts.google.com.
+photos-e.ak.fbcdn.net.
+www.tweetc.com.
+ajax.googleapis.com.
+v3.nonxt8.c.pack.google.com.
+a8.sphotos.ak.fbcdn.net.
+plusone.google.com.
+www.teamr.com.
+lists.cs.columbia.edu.
+ca.wikipedia.org.
+a.root-servers.net.
+shop.mudshop.com.
+1.map.pop6.com.
+154.98.54.121.in-addr.arpa.
+bbcmundo.com.
+twitter.com.
+www.ingenico-us.com.
+www.evs.ee.
+ns02.sumicol.com.
+smarticon.geotrust.com.
+fido.vsi.ru.
+212.24.192.99.in-addr.arpa.
+www.goojue.com.
+b-0.19-a3096008.481.1518.19d4.3ea1.410.0.gw4z1h94peialrfff35risskvj.avqs.mcafee.com.
+ksn2-12.kaspersky-labs.com.
+zh-cn.facebook.com.
+digrouparchitecture.com.s6a1.psmtp.com.
+profile.ak.fbcdn.net.
+180.76.113.186.in-addr.arpa.
+181.171.56.186.in-addr.arpa.
+pixel.facebook.com.
+profile.ak.fbcdn.net.
+console-ssl.service.playfish.com.
+att.wellphone.com.
+190.51.7.199.in-addr.arpa.
+de.wikipedia.org.
+www.creacionenglobo.com.mx.
+www.sqm.microsoft.com.
+time.chttl.com.tw.
+www.max-johnson.blogspot.com.
+148.200.29.201.in-addr.arpa.
+kmet.ee.
+a5.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+plusone.google.com.
+sn3.mailshell.net.
+fbmessenger2.crispapp.com.
+apps.facebook.com.
+www.facebook.com.
+dotmena.com.
+ad-g.doubleclick.net.
+29.210.171.189.in-addr.arpa.
+pt-br.facebook.com.
+alert.services.conduit.com.
+bt.peerseed.ru.
+250.225.89.186.in-addr.arpa.
+izlence.mbirgin.com.
+a2.sphotos.ak.fbcdn.net.
+uhdu2qejt.09qr.
+css.wlxrs.com.
+api.facebook.com.
+30.167.53.85.in-addr.arpa.
+api.webrep.avast.com.
+www.ntdtv.jp.
+clarin.feedsportal.com.
+www.youtube.com.
+dubaicountryclub.com.
+www.msftncsi.com.
+carddav.address.yahoo.com.
+absolutelyangie.blogspot.com.
+sukinson.ru.
+www.primerasexperiencias.com.
+9.31.165.90.in-addr.arpa.
+a.root-servers.net.
+static.aupeo.com.
+www.juegos.com.
+thegranitegroup.com.
+mkportal.net.ru.
+android.l.google.com.
+226.210.77.200.in-addr.arpa.
+www6.inscription.tn.
+a.root-servers.net.
+crowndiamond.net.
+isatap.home.
+platform.twitter.com.
+holeditk.com.
+content.yieldmanager.edgesuite.net.
+aa.avg.com.
+189.27.125.186.in-addr.arpa.
+google.com.
+photos-g.ak.fbcdn.net.
+public.krasnet.ru.
+almibarimposible.files.wordpress.com.
+www.purotorrent.com.
+img717.imageshack.us.
+mail.reiffmolding.com.
+17.159.232.77.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.c-0.19-230f7081.d110081.1518.19c2.3ea0.210.0.189i4g7wtbdgc4m6kmvbg52kf6.avqs.mcafee.com.
+api.twitter.com.
+static.ak.fbcdn.net.
+107.16.23.187.in-addr.arpa.
+rol.net.
+xn--strike-37dbbbbb.ws.
+dwexchange.dongwon.com.
+www.faceboo.co.
+_108_93_8.
+u4cesos:c.55vl.
+www.nudeslutpics.net.
+a2.sphotos.ak.fbcdn.net.
+27.137.173.187.in-addr.arpa.
+ksn1-11-part1.kaspersky-labs.com.
+m.facebook.com.
+www.facebook.com.
+addictedtothai.ru.
+fb-tc-1.farmville.com.
+214.246.49.186.in-addr.arpa.
+yahoosbc.com.
+shiki-comunity.activoforo.com.
+rq2.com.s5a2.psmtp.com.
+i.imwx.com.
+211.234.161.190.in-addr.arpa.
+trophy01.np.community.playstation.net.
+fox21online.com.
+a3.sphotos.ak.fbcdn.net.
+www.youtube.com.
+214.20.168.192.in-addr.arpa.
+www.youtube.com.
+cacfrealty.com.
+instagr.am.
+lexaudit.khn.ru.
+a.rad.msn.com.
+ads.adxpansion.com.
+aspmx.l.google.com.
+cuentosyfabulas.wordpress.com.
+creative.ak.fbcdn.net.
+123.24.167.190.in-addr.arpa.
+5.145.57.200.combined.njabl.org.
+photos-f.ak.fbcdn.net.
+school1415.ru.
+pinkchocolate-break.blogspot.com.
+buscandoellook.blogspot.com.
+external.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+www.trafficshop.com.
+www.facebook.com.
+search.conduit.com.
+wwba1040.com.
+www.theflowermart.com.
+www.ladysonia.org.
+srv.prozess.ru.
+i.ytimg.com.
+manila.com.
+teredo.ipv6.microsoft.com.
+34.195.252.115.in-addr.arpa.
+www.movies-city.com.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+init.gc.apple.com.
+f.doodlemobile.com.\027.
+a.root-servers.net.
+ntp.glb.nist.gov.
+profile.ak.fbcdn.net.
+ruagro.ru.
+springdaleark.org.
+66.206.42.201.in-addr.arpa.
+pagead2.googlesyndication.com.
+149.83.111.95.in-addr.arpa.
+www.stumbleupon.com.
+www.lauraingallswilder.com.
+140.53.106.186.in-addr.arpa.
+media.tumblr.com.
+twitter.com.
+pop.gmail.com.
+twitter.com.
+m2.nsimg.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+inmigracionenestadosunidosenelsigloxix.files.wordpress.com.
+bxo3p2sok.k14p7o9n.
+s.ytimg.com.
+googleads.g.doubleclick.net.
+msghouasg02.bhi-net.com.
+robertwhitehead.com.
+profacebookfanpage.com.
+ib.adnxs.com.
+goshaka.com.
+a5.sphotos.ak.fbcdn.net.
+rs529tl.rapidshare.com.
+data.flurry.com.
+92.1.253.201.in-addr.arpa.
+164.102.75.190.in-addr.arpa.
+board.km.ua.
+content.yieldmanager.edgesuite.net.
+es-la.facebook.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+thecelebritycafe.disqus.com.
+static.ak.fbcdn.net.
+www.theagitator.net.
+photos-g.ak.fbcdn.net.
+cigar.com.
+www.computerrelatedsites.com.
+ads2.msads.net.
+www.antoniodepinto.com.
+platform.twitter.com.
+ikui5t7qe.b09e7h5l.
+opentorrent.ru.
+v2.nonxt1.c.youtube.com.
+ksn7.kaspersky-labs.com.
+75.39.194.187.in-addr.arpa.
+7.96.175.190.in-addr.arpa.
+www.trustlogo.com.
+heartbeat.belkin.com.
+d3l3lkinz3f56t.cloudfront.net.
+237.74.167.189.in-addr.arpa.
+j34s11ort.04kt.
+11.1.168.192.in-addr.arpa.
+feeds.intoday.in.
+www.regenwald.org.
+119.114.69.219.in-addr.arpa.
+diaryofananny.naughtyamerica.com.
+mscrl.microsoft.com.
+179.181.139.93.in-addr.arpa.
+195.233.10.187.in-addr.arpa.
+fesnak.com.inbound30.elephantoutlook.com.
+dc.tvteam.info.
+221.25.150.200.in-addr.arpa.
+50.34.173.189.in-addr.arpa.
+gelert.5.com1.ru.
+www.facebook.com.
+139.144.56.186.in-addr.arpa.
+tgpvideos.dvdbox.com.
+albaniaonline.net.
+msc.wlxrs.com.
+a.root-servers.net.
+connect.facebook.net.
+www.aro.com.au.
+guide-paris-france.ru.
+194.88.127.201.in-addr.arpa.
+astronpc.com.
+annewatkins.com.
+images.google.com.
+img.i.yunduan.cn.
+tudwal.orangehome.co.uk.
+www.medibolics.com.
+a.root-servers.net.
+avidinc.com.inbound10.mxlogicmx.net.
+hootcourse.com.
+zkolos.ru.
+wpad.
+spravedlivo-online.ru.
+img853.imageshack.us.
+adsformula.sitescout.netdna-cdn.com.
+apps.facebook.com.
+nxcache.nexon.net.
+198.15.120.200.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+nwjustice.org.
+www.simicondon.com.
+243.11.6.186.in-addr.arpa.
+228.206.59.200.in-addr.arpa.
+hotmail.com.
+yui.yahooapis.jp.
+track-hub.appspot.com.
+toolbarqueries.google.com.
+a.root-servers.net.
+tc.v2.cache8.c.youtube.com.
+relay1.cityline.ru.
+www.face.net.
+www.netvibes.com.
+ad.yieldmanager.com.
+profile.ak.fbcdn.net.
+krwetatnt.net.
+weather.service.msn.com.
+84.220.147.213.in-addr.arpa.
+xvideos-466.vo.llnwd.net.
+cnfg.facemoods.com.
+236.179.117.76.in-addr.arpa.
+www.univision.com.
+24.173.240.201.in-addr.arpa.
+secure.social-server.com.
+um12.eset.com.
+directorym.com.
+www.nometoqueslashelveticas.com.
+ib.adnxs.com.
+maila.cosmetique.com.
+time.stdtime.gov.tw.
+www.facebook.com.
+www.google.com.mx.
+fbcdn-profile-a.akamaihd.net.
+evolutiongroove.com.
+haasjr.org.
+49.53.131.187.in-addr.arpa.
+38.125.99.41.in-addr.arpa.
+a.root-servers.net.
+www.sg8.info.
+www.guatevoluntaria.org.
+secure.wlxrs.com.
+artesanias-decoracion.blogspot.com.
+esc.rr.com.
+safebrowsing-cache.google.com.
+dns.msftncsi.com.
+mx.nhplace.com.
+vikesfan.com.
+apps.facebook.com.
+209.14.158.190.in-addr.arpa.
+143.203.219.90.in-addr.arpa.
+kabbalahgroup.info.
+c.brightcove.com.
+alpha-proff.ru.
+.
+107.146.220.66.in-addr.arpa.
+barbie.es.
+www.facebook.com.
+www.inkfrog.com.
+ladyluck13.net.
+old.pixmac.com.
+profile.ak.fbcdn.net.
+235.206.183.189.in-addr.arpa.
+a.root-servers.net.
+scholar.l.google.com.
+profile.ak.fbcdn.net.
+petardylandia.blogspot.com.
+content.yieldmanager.edgesuite.net.
+s-static.ak.facebook.com.
+32.226.28.190.in-addr.arpa.
+weplay.com.
+a1402.w40.akamai.net.
+www.alegsa.com.ar.
+s-static.ak.facebook.com.
+yonan.en.alibaba.com.
+deserttreasurez.com.
+profile.ak.fbcdn.net.
+www.glutenfree.com.au.
+m-w.com.
+i4.ytimg.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+instagr.am.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+orcart.facebook.com.
+www.cargamimovil.com.
+srx.befr.ebayrtm.com.
+www.auxmoney-blog.de.
+api.twitter.com.
+a.root-servers.net.
+www.ole.clarin.com.
+33.115.20.201.in-addr.arpa.
+www.trucoteca.com.
+highcountrysurveyors.com.
+castanuelasychurros.blogspot.com.
+mail2.home8.ru.
+cdn.cpmstar.com.
+142.48.11.201.in-addr.arpa.
+udawggraphics.com.s7b2.psmtp.com.
+a-0.19-230fe001.580.1518.19d4.3ea1.410.0.i31f462m9abipbegahw5czg3si.avqs.mcafee.com.
+photos-c.ak.fbcdn.net.
+api.facebook.com.
+gateway-press.com.
+download735.avast.com.
+www.google.com.
+au.download.windowsupdate.com.
+104.52.18.89.zz.countries.nerd.dk.
+www.skipunx.com.
+sp.cwfservice.net.
+www.positivos.com.
+i.minus.com.
+maximaf.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+97.91.18.24.in-addr.arpa.
+tsm05.eset.com.
+www.bramjnet.com.
+forums.fatakat.com.
+static.ak.connect.facebook.com.
+www.newhentai.com.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+54.120.245.69.in-addr.arpa.
+www.sergiocortes.es.
+a5.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+anuncie.taringa.net.
+183.121.69.190.in-addr.arpa.
+210.134.16.190.in-addr.arpa.
+www.enterfactory.com.
+www.autopressnews.com.
+img.cruelzoo.com.
+pixel.facebook.com.
+eatsleepdraw.com.
+130.39.0.10.in-addr.arpa.
+www.facebook.com.
+fl01.ct2.comclick.com.
+tammy.webegirls.biz.
+baby.163.com.
+www.scorpionmezcal.com.
+i.ytimg.com.
+echo.edge.messenger.live.com.
+165.250.30.137.in-addr.arpa.
+soq:noz64.64ey.
+ads.adgator.co.za.
+a1003.w41.akamai.net.
+ec.atdmt.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+224.129.248.201.in-addr.arpa.
+observadorvirtual.blogspot.com.
+www.facebook.com.
+www.facebook.com.
+skillpod.com.
+www.facebooks.com.mx.
+jsonip.appspot.com.
+86.195.253.201.in-addr.arpa.
+s-static.ak.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+208.61.122.186.in-addr.arpa.
+static.ifa.camads.net.
+s.ytimg.com.
+www.fantastigames.com.
+teredo.ipv6.microsoft.com.
+sethigherstandards.com.
+cinnabar.cc.
+eu-st.xhamster.com.
+usgs.com.
+us.lrd.yahoo.com.
+www.facebook.com.
+dns.msftncsi.com.
+tocahistoria.blogspot.com.
+cfile66.uf.daum.net.
+www.googleadservices.com.
+blog.educaedu.com.
+gdata.youtube.com.
+www.w3.org.
+copticorphans.org.
+i4.ytimg.com.
+i6.tagstat.com.
+82.137.203.190.in-addr.arpa.
+mail.cad-net.com.
+a.c-0.19-a30fa000.30011.1518.19d4.3ea1.210.0.2ua9b1g27pez7vahzjw2dsb2dq.avqs.mcafee.com.
+frasebook.net.
+cssmixer.com.
+p.imgci.com.
+www.idownloadbox.com.
+a.root-servers.net.
+skoda-auto.co.in.
+a.root-servers.net.
+msc.wlxrs.com.
+winkel.vpro.nl.
+151.119.244.85.in-addr.arpa.
+oseltd.ru.
+www.veodetodotv.com.
+dns.msftncsi.com.
+view.atdmt.com.
+cm.g.doubleclick.net.
+i.cdn.turner.com.
+mail.northeastdigestive.com.
+dragonballforever-goku6384.blogspot.com.
+energyinnovation.net.
+www.magicdust.com.au.
+swannhadley.com.
+tzt9sk3ku.f10t7w7p.
+atravesadasporlacultura.wordpress.com.
+www.strongchicks.com.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+www.being.com.
+www3.smartadserver.com.
+cakewalknews.cakewalk.com.
+172.53.106.189.in-addr.arpa.
+166.86.217.217.in-addr.arpa.
+a.root-servers.net.
+www.azalyrics.net.
+a6.sphotos.ak.fbcdn.net.
+barracuda.burns-scalo.com.
+2000charge.com.
+profile.ak.fbcdn.net.
+www.xmaduras.com.
+ad.doubleclick.net.
+www.adultswimla.com.
+photos-g.ak.fbcdn.net.
+apps.facebook.com.
+www.crunchbase.com.
+b.scorecardresearch.com.
+alteradosdemercedes.blogspot.com.
+www.yourirondisciples.net.
+www.mrc-hnr.cam.ac.uk.
+ironcita.blogspot.com.
+81.14.250.189.in-addr.arpa.
+32.48.132.187.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+rad.msn.com.
+163.36.250.201.in-addr.arpa.
+gamesforxperiaplay.com.
+titanium30-en.url.trendmicro.com.
+www.crouchingdragon.com.
+safebrowsing.clients.google.com.
+158.236.141.201.in-addr.arpa.
+mail.prince.com.
+checkip.dyndns.org.
+justdancegame.au.ubi.com.
+empleo.mitula.mx.
+www.dimofinf.net.
+a.root-servers.net.
+fbcdn-video-a.akamaihd.net.
+news.gohome.com.hk.
+software.canon-europe.com.
+a7.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+mail.google.com.
+www.farmville.com.
+0-74.channel.facebook.com.
+a.root-servers.net.
+.
+www.similares.net.
+9gibtn6v5.30su.
+energyunited.com.
+www.scribd.com.
+73.37.168.192.in-addr.arpa.
+a.root-servers.net.
+extratorrent.com.
+6.246.7.187.in-addr.arpa.
+aldrinchavarria.wordpress.com.
+ibmafia.com.
+208.188.170.201.in-addr.arpa.
+eddea-emontoya.blogspot.com.
+vqta1sjkl.h08n4z7y.
+ads1.msads.net.
+photos-f.ak.fbcdn.net.
+e2ci.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+plus.google.com.
+profile.ak.fbcdn.net.
+translate.google.com.mx.
+91.187.159.189.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+v2qgm2mlf.s76z3f5f.
+wpc.0c28.edgecastcdn.net.
+www.explosiongay.com.ar.
+media.ladbrokes.com.
+dns.msftncsi.com.
+a.root-servers.net.
+blowfishunlocks.com.
+a1.sphotos.ak.fbcdn.net.
+swf.extensionfile.net.
+aa.online-metrix.net.
+www.hospitalangelespedregal.com.mx.
+abc.csar.go.com.
+mulfordconcreteinc.com.
+www.drogaconsulta.com.ar.
+facemoods.com.
+a8.sphotos.ak.fbcdn.net.
+google.com.
+87.48.141.201.in-addr.arpa.
+182.74.160.187.in-addr.arpa.
+193.51.167.190.in-addr.arpa.
+35.7.2.187.in-addr.arpa.
+www.google.com.
+photos-a.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+182.49.48.108.in-addr.arpa.
+www.hp.com.
+apis.google.com.
+google.com.
+fbcdn-profile-a.akamaihd.net.
+www.trfirmaekle.com.
+www.gigisapparel.com.
+189.223.228.189.in-addr.arpa.
+apps.facebook.com.
+119.14.108.76.in-addr.arpa.
+hi-in.facebook.com.
+cctupgrades.com.
+s0.2mdn.net.
+pangiatech.com.
+nataliaseweryn.buzznet.com.
+photos-g.ak.fbcdn.net.
+pixel.facebook.com.
+161.28.77.190.in-addr.arpa.
+a1725.l.akamai.net.
+mabeslor.com.
+es-la.facebook.com.
+20.180.95.109.in-addr.arpa.
+img69.imageshack.us.
+photos-g.ak.fbcdn.net.
+clients1.google.com.
+ad.doubleclick.net.
+www.google-analytics.com.
+gruporahn.com.
+mail.cacoon.ru.
+adq.nextag.com.
+swaab.net.
+kube.en.muxxu.com.
+185.174.171.189.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+correctcryogenics.com.
+jfriend.smugmug.com.
+.
+raywal.com.
+www.belkin.com.
+mx2.glr.nl.
+www.kartfinder.com.
+secure.wlxrs.com.
+www.google.com.
+ns2.p15.dynect.net.
+cs5353.vkontakte.ru.
+me.effectivemeasure.net.
+i1.ytimg.com.
+eduardoguille.artelista.com.
+ds.serving-sys.com.
+content-cdn.walmart.com.
+atyt.net.
+f9d5q6kc2.28ug.
+hbf.cloud.avg.com.
+21.174.168.192.in-addr.arpa.
+vcs2.msg.yahoo.com.
+teredo.ipv6.microsoft.com.
+155.184.217.85.in-addr.arpa.
+loveday.getmylove.net.
+a1.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+onthepin.com.
+mitsloanexperts.com.
+www.mcleodgaming.com.
+pop3.live.com.
+u.4f61a6b43bfdf105.com.
+www.diigo.com.
+i3.ytimg.com.
+api.twitter.com.
+update.utorrent.com.local.
+ads.trafficjunky.net.
+profile.ak.fbcdn.net.
+viva.gr.
+118.249.192.190.in-addr.arpa.
+www.google.com.
+profile.ak.fbcdn.net.
+mebeletta.ru.
+252.133.132.187.in-addr.arpa.
+42.142.49.96.in-addr.arpa.
+www.tribalwars.ae.
+google.com.
+www.mujeresdesnudas.com.es.
+54.164.145.201.in-addr.arpa.
+webcache.googleusercontent.com.
+dns.msftncsi.com.
+s-static.ak.facebook.com.
+ji.zh.ch.
+safebrowsing.clients.google.com.
+api.facebook.com.
+oxfordpolymers.com.
+sp.cwfservice.net.
+market.android.com.
+members.dyndns.org.
+www.actosdeamor.com.
+a5.sphotos.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cdn.emily18.com.
+a5.sphotos.ak.fbcdn.net.
+188.14.245.78.in-addr.arpa.
+fxfeeds.mozilla.com.
+combatarms.nexon.net.
+a.root-servers.net.
+www.revistaneurocirugia.com.
+ucs.query.yahoo.com.
+poetsofthefallargentina.wordpress.com.
+innsofcourt.org.
+xcdn.xgraph.net.
+13.3.185.31.in-addr.arpa.
+www.infinityflashgames.com.
+us.mc464.mail.yahoo.com.
+g:gjvrs7d.m21s4q7v.
+images.apple.com.
+platform.ak.fbcdn.net.
+agrupacionexconscriptos.blogspot.com.
+130.33.56.186.in-addr.arpa.
+legendabeatles.blogspot.com.
+i4.ytimg.com.
+mail.fitaihi.com.sa.
+msc.wlxrs.com.
+dis.criteo.com.
+usodelarazon.blogspot.com.
+a.root-servers.net.
+108.1.168.192.in-addr.arpa.
+134.184.142.175.in-addr.arpa.
+ipcanswers.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+28.media.tumblr.com.
+vfbinsurance.com.
+cdn4.theigroup.co.uk.
+www.zynga.com.
+www.iloveblackgirls.net.
+armmf.adobe.com.
+lh6.googleusercontent.com.
+1.117.166.118.in-addr.arpa.
+www.facebook.com.
+153.154.114.190.in-addr.arpa.
+45.229.26.125.in-addr.arpa.
+36.196.191.72.in-addr.arpa.
+p05-keyvalueservice.icloud.com.
+28.ape.bigmuscle.com.
+94.187.100.189.in-addr.arpa.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+by2msg3020414.gateway.messenger.live.com.
+business-prof.ru.
+www.getfirefox.com.
+itunes.apple.com.
+es-es.facebook.com.
+108.42.214.201.in-addr.arpa.
+czechmat.ru.
+www.azul.com.ec.
+www.segurosrossi.com.ar.
+lawrencemandel.com.
+profile.ak.fbcdn.net.
+picasaweb.l.google.com.
+safebrowsing.clients.google.com.
+1272039.r.msn.com.
+photos-e.ak.fbcdn.net.
+uptowntruckingdisposal.com.
+ib.adnxs.com.
+www.legislation.qld.gov.au.
+stomatsamara.ru.
+fbcdn-profile-a.akamaihd.net.
+200.69.169.87.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+accounts.google.com.
+ad-g.doubleclick.net.
+a.root-servers.net.
+www.facebook.com.
+s-external.ak.fbcdn.net.
+co116w.col116.mail.live.com.
+www.3ddgames.com.
+photos-f.ak.fbcdn.net.
+google.com.
+download983.avast.com.
+www.asianborderlands.net.
+platform.ak.fbcdn.net.
+246.221.57.187.in-addr.arpa.
+a1402.w40.akamai.net.
+111.100.62.189.in-addr.arpa.
+accounts.google.com.
+a-0.19-a309d081.d8f0082.1518.19d4.3ea0.210.0.b7gkhu4wutrenl222ip5f7zh6q.avqs.mcafee.com.
+www.iphone4.fr.
+news.google.com.mx.
+teredo.ipv6.microsoft.com.
+24.119.111.189.in-addr.arpa.
+161.169.59.186.in-addr.arpa.
+androidpost.net.
+www.facebook.com.
+www.apple.com.
+idcmstask.app.joy.cn.
+191.237.74.187.in-addr.arpa.
+adocean-by.hit.gemius.pl.
+www.cbd-habitat.com.
+ssl.gstatic.com.
+ronan-parke.org.
+www.google.es.
+rkthb.co.
+123.220.74.212.in-addr.arpa.
+touch.facebook.com.
+garexdoors.ru.
+a.root-servers.net.
+b.thumbs.redditmedia.com.
+apps.facebook.com.
+144.36.167.201.in-addr.arpa.
+telus-updates.radialpoint.net.
+www.creditcardsguidance.com.
+locaporlaluna.lacoctelera.net.
+101.236.69.114.in-addr.arpa.
+a.root-servers.net.
+xxxl-cash.net.
+78.21.67.190.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+84.129.50.189.in-addr.arpa.
+i1.ytimg.com.
+pim.raz.htcsense.com.
+stargen.com.
+29.15.237.189.in-addr.arpa.
+dns.msftncsi.com.
+aviva-giles.blogspot.com.
+gtssl-crl.geotrust.com.
+23.143.106.186.in-addr.arpa.
+col.stb.s-msn.com.
+cdn.data.mobilytrip.com.
+a.root-servers.net.
+mail-in-a.mx.xnet.hr.
+performance-suspension.eibach.de.
+a.root-servers.net.
+bay.messenger.services.live.com.
+cf.addthis.com.
+simai.ru.
+0.0.0.0.in-addr.arpa.
+spa-resources-international.com.
+www.google.com.mx.
+external.ak.fbcdn.net.
+mtsmail.org.
+ratings-wrs.symantec.com.
+74.27.150.190.in-addr.arpa.
+smtaextrwc02.gene.com.
+scholar.google.es.
+59.172.138.201.in-addr.arpa.
+mail.tydex.ru.
+croftmotors.co.uk.
+urs.microsoft.com.
+groups.google.com.mx.
+10.246.197.204.in-addr.arpa.
+big.assets.huffingtonpost.com.
+fbcdn-photos-a.akamaihd.net.
+197.205.1.201.in-addr.arpa.
+53.106.223.201.in-addr.arpa.
+www.macromedia.com.
+rtsi.wemfbox.ch.
+ad.xtendmedia.com.
+252.109.224.1.in-addr.arpa.
+a.root-servers.net.
+www.mercadolibre.com.pe.
+sp.cwfservice.net.
+a.root-servers.net.
+www.jscount.com.
+www.medicinatndr.com.
+apps.facebook.com.
+www.campbells.com.mx.
+www.bmwusa.com.
+www.digitalfieldguide.com.
+www.peruwptravelthemes.com.
+g.live.com.
+185.249.30.189.in-addr.arpa.
+skyscape.sky.com.
+a3.sphotos.ak.fbcdn.net.
+155.75.104.71.in-addr.arpa.
+bi1uy6trk.u09l3r0u.
+a1402.w40.akamai.net.
+125.153.40.187.in-addr.arpa.
+afsdv.ru.
+www.appsleak.com.
+007sz.net.
+www.peeperz.com.
+167.60.23.94.in-addr.arpa.
+www.mapsfordesign.com.
+apis.google.com.
+www.facebook.com.
+0.11-230f8081.c120081.1518.17f8.3ea0.210.0.6sildrlmua1jhig1sfve2se1fi.avqs.mcafee.com.
+_782_46_6.
+84.63.99.190.in-addr.arpa.
+empiredistrict.com.
+cinecero.blogspot.com.
+82.46.53.201.in-addr.arpa.
+asas.ru.
+www.mk12.com.
+www.urovirtual.net.
+24.62.236.190.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+221.134.231.125.in-addr.arpa.
+mx1.aragon.es.
+29.media.tumblr.com.
+iscreative.com.
+45.170.254.169.in-addr.arpa.
+thirdtribemarketing.com.
+64.89.62.151.in-addr.arpa.
+155.85.9.186.in-addr.arpa.
+136.215.8.186.in-addr.arpa.
+www.ucolick.org.
+14.128.52.96.in-addr.arpa.
+maps.google.com.om.
+www.bing.com.
+70.180.57.186.in-addr.arpa.
+exch-w.atdmt.com.
+sum-tech.ru.
+docs.google.com.
+talismgmt.com.inbound10.mxlogic.net.
+rd.rlcdn.com.
+ksn2-12.kaspersky-labs.com.
+gilchristconst.com.
+www.mindvalleyhispano.com.
+pensamientoexperimental.blogspot.com.
+jasnetworks.net.
+agricol.e.telefonica.net.
+piv.pivpiv.dk.
+165.143.172.189.in-addr.arpa.
+231.179.244.190.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+cs10008.vkontakte.ru.
+www.descargar-youtube.com.
+205.22.101.99.in-addr.arpa.
+tommti-systems.de.
+m.facebook.com.
+b-0.19-220a4008.91081.1518.19d4.3ea1.410.0.j5iruwmdnhcmblwaj57k9gcj55.avqs.mcafee.com.
+www.gamesandgeeks.com.
+112.23.132.187.in-addr.arpa.
+accounts.google.com.
+71.59.52.201.in-addr.arpa.
+www.paypalobjects.com.
+www.facebook.com.
+123.130.233.189.in-addr.arpa.
+checkip.dyndns.org.
+www.igirlsgames.com.
+ns1.root.ru.
+kgiswx1bb.62gz.
+mail1.rhcc.com.
+www.facebook.com.
+nielsenfineart.com.
+profile.ak.fbcdn.net.
+assets.tumblr.com.
+support.live.com.
+profile.ak.fbcdn.net.
+coffeetime.de.
+acmilan.ru.
+www.facebook.com.
+www.etruth.com.
+a7.sphotos.ak.fbcdn.net.
+www.serviwebrd.com.
+www.hollywoodreporter.com.
+um14.eset.com.
+a.root-servers.net.
+152.67.213.83.in-addr.arpa.
+pics.haircutshairstyles.com.
+244.50.230.67.in-addr.arpa.
+gs-loc.apple.com.
+54.153.25.187.in-addr.arpa.
+ssl.gstatic.com.
+a.root-servers.net.
+diglib.auburn.edu.
+183.66.59.186.in-addr.arpa.
+recursos.fotocajon.com.
+a.root-servers.net.
+cdn-colo-ch-3.mbt.com.
+tonycolamarino.com.
+rikain.com.
+photos-a.ak.fbcdn.net.
+41-courier.push.apple.com.
+mail.ci.missoula.mt.us.
+facebook.com.
+187.204.237.64.in-addr.arpa.
+a.root-servers.net.
+pubads.g.doubleclick.net.
+ocsp.verisign.com.
+twitter.com.
+mx.suddenlink.net.
+www.cnfl.go.cr.
+www.hollywoodgothique.com.
+8.8.217.63.in-addr.arpa.
+srv.ubplastik.ru.
+email.radcliffe.in.
+ocio.superdeporte.es.
+bl148w.blu148.mail.live.com.
+yofuidel4delinea.blogspot.com.
+dns.msftncsi.com.
+mta1.am0.yahoodns.net.
+teredo.ipv6.microsoft.com.
+gamecheats.com.
+ads.adxpansion.com.
+m.addthisedge.com.
+hyp12hvotnrh14eumxp42jvozjti15mzg43c49.info.
+s.youtube.com.
+photos-a.ak.fbcdn.net.
+dc353.4shared.com.
+sup.live.com.
+g.ceipmsn.com.
+arttaste.ru.
+rivaldofans.ifrance.com.
+mail.ard-kazan.ru.
+lekstore.ru.
+k.kuwo.cn.
+photos-h.ak.fbcdn.net.
+www.microsoft.com.
+143.49.104.88.in-addr.arpa.
+yingjunjiu.deviantart.com.
+sbeton.ru.
+www.greginhollywood.com.
+fr.wikipedia.org.
+a.root-servers.net.
+pocketcents.com.
+225.154.144.189.in-addr.arpa.
+www.1channel.ch.
+aol.com.
+static-resource.np.community.playstation.net.
+99.218.23.203.in-addr.arpa.
+newswander.com.
+www.viharjelzes.hu.
+newsrss.bbc.co.uk.
+ikelite.com.
+bitly.com.
+yui.yahooapis.com.
+_carddavs._tcp.yahoo.com.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+db._dns-sd._udp.enhwi-n3.
+eshops.mercadolibre.com.mx.
+mail-server2.profiseti.ru.
+www.google-analytics.com.
+hylinx.com.
+dns.msftncsi.com.
+www.facebook.com.
+nmcpas-com.mail.eo.outlook.com.
+94.51.122.190.in-addr.arpa.
+165.55.141.189.in-addr.arpa.
+email-us.huawei.com.
+maps.google.com.
+www.diablos.
+100500.tv.
+search.twitter.com.
+web1.designerapparel.com.
+230.235.148.190.in-addr.arpa.
+fe1.cgp.21ctl.com.
+travel.france24.com.
+112.230.49.190.in-addr.arpa.
+www.socialgrowthtechnologies.com.
+57.113.104.200.in-addr.arpa.
+248.101.4.189.in-addr.arpa.
+www.ooyala.com.
+www.tripadvisor.com.
+noos.fr.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+www.google.com.
+expedia.fr.
+apps.facebook.com.
+246.129.121.189.in-addr.arpa.
+zercustoms.com.
+plus.google.com.
+gearsofwar.wikia.com.
+204.128.128.186.in-addr.arpa.
+www.gigisapparel.com.
+imgs.gamesbannernet.com.
+platform.ak.fbcdn.net.
+mx4.evzo.org.
+dns.msftncsi.com.
+ads.youmago.ro.
+apps.facebook.com.
+photos-c.ak.fbcdn.net.
+ds.addthis.com.
+yahoo.com.
+mxs.valuehost.ru.
+shout.dk.
+www.koliscar.si.
+i1.ytimg.com.
+a4.sphotos.ak.fbcdn.net.
+fb.statusking.net.
+pixel.facebook.com.
+go.microsoft.com.
+time.stdtime.gov.tw.
+riceboy.jho-tan.com.
+sblincoln.com.s8a1.psmtp.com.
+oncewest.com.
+a.root-servers.net.
+www.tia.org.
+a.collective-media.net.
+up.absba.com.
+fbcdn-photos-a.akamaihd.net.
+www.globostuky.com.ar.
+kentuckysportsradio.com.
+www.sport365.com.
+a.root-servers.net.
+www.lpdedicated.com.
+image2.tailieu.vn.
+hi-in.facebook.com.
+www.mcanime.net.
+a.root-servers.net.
+d1j68ux4ukg4g1.cloudfront.net.
+www.jscount.com.
+pruittgushee.com.
+external.ak.fbcdn.net.
+b.scorecardresearch.com.
+12173.ua.all.biz.
+100.236.67.201.in-addr.arpa.
+www.facebook.com.
+ytimg.l.google.com.
+120.148.168.192.in-addr.arpa.
+rs991l34.rapidshare.com.
+panelnaranja.rpxnow.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+dtboot.orbitdownloader.com.
+api.facebook.com.
+americanheritageins.com.bak-mx.na0106.smtpbak.com.
+go.srvnow.com.
+45.237.108.186.in-addr.arpa.
+pagead2.googlesyndication.com.
+www.bing.com.
+ku2.ru.
+mx.yakuel.com.
+www.toptanciyiz.net.
+api.twitter.com.
+lite.ebuddy.com.
+www.imdb.com.
+www.6565.cn.
+5w.ru.
+.
+a.root-servers.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+api.mingscape.com.
+www.cnf.gob.mx.
+2.56.230.190.in-addr.arpa.
+a.ads2.msads.net.
+laserdrive.com.s5a2.psmtp.com.
+maitlandrealty.com.
+de-de.facebook.com.
+www.expoplasticos.com.mx.
+gcp.es.
+www.legalleadersblog.com.
+freddiemqueen.forumfree.it.
+www.luifil.com.
+www.activeherb.com.
+www.facebook.com.
+www.mediafire.com.
+113.84.181.213.in-addr.arpa.
+api.viglink.com.
+www.gazetalubuska.pl.
+a7.sphotos.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+159.177.82.177.in-addr.arpa.
+googleads.g.doubleclick.net.
+thisisf1.com.
+kokotovich.com.
+a.root-servers.net.
+_ldap._tcp.
+adf.ly.
+pt-br.facebook.com.
+mail.celebrityintl.com.
+209.187.154.186.in-addr.arpa.
+lowest-rate-loans.com.
+www.crimesofwar.org.
+19.91.248.189.in-addr.arpa.
+img.gotomeeting.com.
+53.106.235.186.in-addr.arpa.
+www.professionisti.bticino.it.
+xlqgtsk26.h17q5k2i.
+spc.edu.s10a2.psmtp.com.
+134.25.212.201.in-addr.arpa.
+195.184.142.187.in-addr.arpa.
+secure-us.imrworldwide.com.
+a5.sphotos.ak.fbcdn.net.
+www.duckload.com.
+19.237.50.96.in-addr.arpa.
+user.easyn.cn.
+52.104.172.201.in-addr.arpa.
+s-static.ak.fbcdn.net.
+3.bp.blogspot.com.
+sp.cwfservice.net.
+chicago.cbslocal.com.
+167.113.231.189.in-addr.arpa.
+clients1.google.com.
+www.facebook.com.
+neonisi.com.
+thefoodaddicts.com.
+google.com.
+rospres.com.
+166.7.216.201.in-addr.arpa.
+groups.google.com.ar.
+152.153.158.205.in-addr.arpa.
+58.255.205.186.in-addr.arpa.
+152.253.134.187.in-addr.arpa.
+t0.gstatic.com.
+sp.cwfservice.net.
+26.161.168.192.in-addr.arpa.
+support.google.com.
+202.151.249.92.in-addr.arpa.
+titanium30-en.url.trendmicro.com.
+114.208.96.174.in-addr.arpa.
+kalifbanane.deviantart.com.
+15.252.53.200.in-addr.arpa.
+smfc.thescore.com.
+www.machineryzone.es.
+ping3.teamviewer.com.
+23.59.168.192.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+apps.facebook.com.
+a.root-servers.net.
+www.chicaswebcam.eu.
+96.12.214.176.in-addr.arpa.
+dgsr3tffm.f23z5d6w.
+228.10.74.180.in-addr.arpa.
+cs10030.vkontakte.ru.
+signin.ebay.com.
+theatre.ru.
+88.119.51.190.in-addr.arpa.
+www.tesolconvention.org.
+www.subiegal.com.
+spamfilter.kier.re.kr.
+creative.ak.fbcdn.net.
+www.aqps.info.
+geo.yahoo.com.
+forum.lyrsense.com.
+www.piel-sana-vida-sana.com.
+a.root-servers.net.
+www222.pair.com.
+t3.gstatic.com.
+mx1.brickit.com.
+www.yahoo.com.
+43.169.1.120.in-addr.arpa.
+touch.facebook.com.
+mail.jjranchpro.com.
+a2.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.iguoguo.net.
+www.google.com.
+nubiagroup-powerpoint-collection.blogspot.com.
+15.4.80.69.in-addr.arpa.
+221.199.105.77.in-addr.arpa.
+att-mail.com.dnsbl7.mailshell.net.
+profile.ak.fbcdn.net.
+upload.facebook.com.
+194.140.23.187.in-addr.arpa.
+mobileads.nimbuzz.com.
+mexico.ilww.com.
+musica.
+_374_14_1.
+login.live.com.
+www.gm.tv.
+www.google.es.
+mail.samui-island.ru.
+rs607l36.rapidshare.com.
+a2.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+www.cenerick.com.ar.
+img3.teddy-girls.com.
+25.156.230.190.in-addr.arpa.
+www.solosalta.com.
+email1-east.aero.org.
+202.189.218.195.in-addr.arpa.
+c.prodigy.msn.com.
+72.100.151.67.in-addr.arpa.
+ssl.google-analytics.com.
+206.36.192.108.in-addr.arpa.
+img100.xvideos.com.
+mail.urfc.ru.
+blog.gisuser.com.
+www.factsaboutanimals.net.
+view.atdmt.com.
+108.135.138.187.in-addr.arpa.
+webres4.pand.ctmail.com.
+es-la.facebook.com.
+external.ak.fbcdn.net.
+38.15.82.200.in-addr.arpa.
+ajax.googleapis.com.
+rrcvexydh.l33z2r2a.
+flowdebarrio.com.
+dr._dns-sd._udp.lan.
+plus.google.com.
+webcache.googleusercontent.com.
+entertainer.mvourtown.com.
+www.weather.com.
+mail3.volny.cz.
+cts.channelintelligence.com.
+ts.videosz.com.
+zynga2-a.akamaihd.net.
+7.201.31.80.in-addr.arpa.
+207.172.75.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+cdn-7.pics.t8premium.com.
+exch-w.atdmt.com.
+api.facebook.com.
+43.84.8.190.in-addr.arpa.
+www.broknes.net.
+photos-d.ak.fbcdn.net.
+www.shemale-comics.net.
+mail.wselectronics.com.
+industrycasting.com.au.
+bmzojkdspg.ru.
+www.goats.com.
+sagastumes.mypressonline.com.
+www.facebook.com.
+unitedtitleservices.com.inbound10.mxlogic.net.
+i1.ytimg.com.
+ns2.ulink.ru.
+227.228.59.99.in-addr.arpa.
+www.dieslermusic.com.
+ads.contentabc.com.
+gipat.ru.
+6.38.61.99.in-addr.arpa.
+swsb3guoh.g48b1g2u.
+www.youtube-nocookie.com.
+homes.onlineathens.com.
+www.facebook.com.
+www.somoto.com.
+secure-au.imrworldwide.com.
+m8fu78fnc.08vw.
+mail2.checkfree.com.
+publicstorage.com.
+dnl-01.geo.kaspersky.com.
+pop3.live.com.
+www.facebook.com.
+252.218.132.187.in-addr.arpa.
+1.3.168.192.in-addr.arpa.
+3.201.107.193.in-addr.arpa.
+graph.facebook.com.
+193.111.159.69.in-addr.arpa.
+www.hispanicmarketweekly.com.
+superdeportes.com.
+time.windows.com.
+207.12.250.189.in-addr.arpa.
+almeria.guia.hola.com.
+crashteams.com.
+s-static.ak.fbcdn.net.
+a.root-servers.net.
+a.root-servers.net.
+27.media.tumblr.com.
+atgcompanies.com.
+hoosiertimescoupons.com.
+_537_03_1.
+xslt.alexa.com.
+3.bp.blogspot.com.
+www.bing.com.
+56.132.251.190.in-addr.arpa.
+static.ak.fbcdn.net.
+212.200.249.111.in-addr.arpa.
+mirror.alfredstate.edu.
+l2.zedo.com.
+162.1.168.192.in-addr.arpa.
+nomail1.circulomexico.com.
+no.wikipedia.org.
+acsc.com.
+pattersonresearch.net.
+morganlawohio.com.
+armmf.adobe.com.
+mail.msihoa.com.
+a.root-servers.net.
+mensajesatucorazon.blogspot.com.
+hergoodybag.com.
+dnl-01.geo.kaspersky.com.
+peliculas2.com.
+external.ak.fbcdn.net.
+x439.com.
+a1725.l.akamai.net.
+90.147.219.62.in-addr.arpa.
+muzikalia.com.
+190.102.138.187.in-addr.arpa.
+e-markit.info.
+www.youtube.com.
+fandeloup.centerblog.net.
+a.root-servers.net.
+slamit.net.
+mbj.nifty.co.
+www.lacare.org.
+dnl-06.geo.kaspersky.com.
+www.firm-consult.de.
+api.conduit.com.
+213.127.122.200.in-addr.arpa.
+www.facebook.com.
+www.postcefalu.blogspot.com.
+time.chttl.com.tw.
+bg.rhenus.com.
+wpad.
+amer.rel.msn.com.
+mail.kktooldesign.com.
+71.101.197.84.in-addr.arpa.
+relay.partout.it.
+denis.stalker.h3q.com.
+search.babylon.com.
+byrnemedia.co.uk.
+unlease.ru.
+tempo.folha.com.br.
+corntoromyout.nu.
+a.root-servers.net.
+221.85.198.190.in-addr.arpa.
+check6.facebook.com.
+gfx4.hotmail.com.
+www.trisomy.org.
+iphone-wu.apple.com.
+connect.facebook.net.
+rapidshare.com.
+lh3.ggpht.com.
+images.thecandidforum.com.
+www.womensweightgain.com.
+r2now.com.
+s-static.ak.facebook.com.
+klinger.ru.
+midmaine.com.
+www.fullquimica.com.
+cs5683.vk.com.
+www.gamecetera.com.
+a3.sphotos.ak.fbcdn.net.
+waynefarms.com.
+rmd.atdmt.com.
+a.root-servers.net.
+www.facebook.com.
+profile.ak.fbcdn.net.
+www.tannan-fm.com.
+platform.twitter.com.
+cbr.digitalinsight.com.
+www.searchqu.com.
+a.root-servers.net.
+feeds.bbci.co.uk.
+_437_58_9.
+194.189.195.187.in-addr.arpa.
+jers2.info.
+blog.facebook.com.
+74.115.57.71.in-addr.arpa.
+d2095542.xoom.it.
+www.techfever.net.
+payment.6waves.com.
+pioneerelectronics.com.
+time.nist.gov.
+www.real-bikini-beach.com.
+24.69.124.189.in-addr.arpa.
+ejabat.google.com.
+support.google.com.
+mntr.babcdn.com.
+a2.sphotos.ak.fbcdn.net.
+226.59.14.195.in-addr.arpa.
+hi-in.facebook.com.
+irepvm.com.
+www.1aria.com.
+shoppas.com.
+www.laruinaoculta.com.
+ad.yieldmanager.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+203.103.105.189.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+cnnespanol.wordpress.com.
+www.salt-themovie.com.
+sherlock-holmes-nemesis.softonic.com.
+safebrowsing-cache.google.com.
+tc.v11.cache5.c.youtube.com.
+rooadrunner.com.
+google.com.
+2012taiwanlantern.net.
+adserving.cpxinteractive.com.
+cecytneza2.galeon.com.
+a.root-servers.net.
+www.vsp.state.va.us.
+assets.tumblr.com.
+i4.ytimg.com.
+www.cosmos.com.mx.
+d2054836.instant.xoom.it.
+rad.msn.com.
+img5.ranchoweb.com.
+www.blogoozle.com.
+www.adobe.com.
+cardsharing.us.
+aloha.viber.com.
+153.74.164.190.in-addr.arpa.
+alt4.gmail-smtp-in.l.google.com.
+211.50.83.62.in-addr.arpa.
+caw.ny.us.criteo.com.
+www.facebook.com.
+www.ebaygivingworks.com.
+www.turuo.com.
+sitemail.everyone.net.
+www.jvc.com.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+104.146.185.190.in-addr.arpa.
+equitylinepa.com.
+apps.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+fehth5u8x.83kc.
+www.google-analytics.com.
+nmusd.k12.ca.us.
+133.0.87.66.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+omnimetal.com.
+princesasailormoon.blogspot.com.
+www.facebook.com.
+thebilgepumps.com.
+wakefieldreutlinger.com.inbound15.mxlogic.net.
+207.109.39.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.dayendra.web.id.
+idreseller.ru.
+sp.cwfservice.net.
+safebrowsing.clients.google.com.
+baymsg1020431.by2.gateway.edge.messenger.live.com.
+app.net.
+router.infolinks.com.
+syndication.mmismm.com.
+www.dainbinder.com.
+224.175.150.200.in-addr.arpa.
+ad-g.doubleclick.net.
+www.adobe.com.
+104.248.204.199.in-addr.arpa.
+128.20.34.110.in-addr.arpa.
+www.4shared.com.
+www.google.com.
+aberdeen-chamber.com.
+42.49.138.98.in-addr.arpa.
+sp.cwfservice.net.
+assets1.mynewsdesk.com.
+secure.dominio.com.
+toomeycustoms.us.intellitxt.com.
+www.youtube.com.
+dbmmgt.com.
+simssoc.game.playfish.com.
+www.googleadservices.com.
+gatekeeperus.trintech.com.
+_596_67_3.
+mail.leader-panama.com.
+5ballov.com.ru.
+en.foodlexicon.org.
+a.c-0.19-250f8081.c140081.1518.19d2.3ea1.210.0.5zfq4hzzfe4k2efksc2whfpj8t.avqs.mcafee.com.
+by2msg4010610.gateway.messenger.live.com.
+mynationlink.net.
+nspmotion.com.
+173.228.225.190.in-addr.arpa.
+www.seoindonesiaku.com.
+photos-h.ak.fbcdn.net.
+cdn.api.twitter.com.
+vermeerdir.com.
+www.ticketek.com.ar.
+dr._dns-sd._udp.0.92.16.172.in-addr.arpa.
+googleads.g.doubleclick.net.
+openlead.bankimia.com.
+guestbooks.fotki.com.
+ar.answers.yahoo.com.
+apps.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+126.205.52.83.in-addr.arpa.
+img39.imageshack.us.
+es1w1.tw.innogames.net.
+static.ak.facebook.com.
+246.22.139.175.in-addr.arpa.
+sro.whatsapp.net.
+www.newstyledirect.com.au.
+www.15a20.com.mx.
+www.smartbusinesscorp.com.
+www.linuxinsight.com.
+176.179.17.201.in-addr.arpa.
+myfotojournal.com.
+zynga2-a.akamaihd.net.
+crochets-emi.blogspot.com.
+166.96.86.74.in-addr.arpa.
+58.109.87.186.in-addr.arpa.
+www.autozine.org.
+ad.adtegrity.net.
+wunderlist.com.
+www.globe-info.org.
+creative.ak.fbcdn.net.
+ad.doubleclick.net.
+209.144.218.188.in-addr.arpa.
+.
+profile.ak.fbcdn.net.
+freezebomb.bigcartel.com.
+s.ytimg.com.
+www.kidsclick.com.
+151.222.165.83.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+t3.tagstat.com.
+cosplay-play.blogspot.com.
+ozarkcoop.com.
+agirlsguidetoshoes.blogspot.com.
+sp.cwfservice.net.
+brap.org.uk.
+www.beachcalifornia.com.
+agtc.com.s5b2.psmtp.com.
+s-static.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+heartbeat.belkin.com.
+photos-d.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+career.dol.ru.
+caceres.cope.es.
+www.buruo.com.
+aspmx2.googlemail.com.
+www.revenge.com.
+rembrandts.com.
+.
+www.google.com.
+wow-recons.foroactivo.org.
+d2060296.instant.xoom.it.
+119.229.90.200.in-addr.arpa.
+155.19.25.190.in-addr.arpa.
+ads.yimg.com.
+poddonn.ru.
+77.142.56.186.in-addr.arpa.
+www.gifmania.com.co.
+dowacousticsinc.com.
+localhost.
+www.palco-vip.com.
+.
+www.tirian.com.
+a7.sphotos.ak.fbcdn.net.
+vayda.ru.
+www.bbvanetoffice.com.
+191.210.202.84.in-addr.arpa.
+apix.iminent.com.
+lampiweb.com.
+50.25.85.85.in-addr.arpa.
+ocsp.thawte.com.
+weddings.alltop.com.
+mail.bitwisepublishing.com.
+bfis.fis.ru.
+gwqsbvbnj.info.
+www.grapeshot-media.net.
+a4.sphotos.ak.fbcdn.net.
+153.133.132.217.in-addr.arpa.
+245.240.67.174.in-addr.arpa.
+8vco9o7nuj5c2siebikqjj1a53konthn-a-fc-opensocial.googleusercontent.com.
+9qrk4a9hb.u79n3m6r.
+85.243.17.198.in-addr.arpa.
+121.244.245.190.in-addr.arpa.
+i2.ytimg.com.
+s.youtube.com.
+a.root-servers.net.
+l.sharethis.com.
+forums.utherverse.com.
+www.facebook.com.
+home.live.com.
+85.229.33.201.in-addr.arpa.
+www.kaltura.com.
+winznews.blog98.fc2.com.
+ad.yieldmanager.com.
+spb.top-kniga.ru.
+s2.youtube.com.
+sp.cwfservice.net.
+static.searchya.com.
+www.rinconsantafesino.net.
+a.root-servers.net.
+67.92.81.83.in-addr.arpa.
+s.ytimg.com.
+ocsp.digicert.com.
+www.google.com.
+nioxinhair.ru.
+static.ak.fbcdn.net.
+91.224.233.118.in-addr.arpa.
+itsystemsgroup.com.s5a1.psmtp.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+static.rpxnow.com.
+70.22.183.209.in-addr.arpa.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+186.95.2.187.in-addr.arpa.
+rs433tl4.rapidshare.com.
+gustinadvertising.net.
+186.51.171.201.in-addr.arpa.
+ad.yieldmanager.com.
+port75.mx16.sps.mxfw.net.
+u10933.29.spylog.com.
+noteprobable.com.
+ramon.rwlynch.com.
+millennianet.com.
+in.getclicky.com.
+l.yimg.com.
+login.givemepink.com.
+88.95.46.184.in-addr.arpa.
+shared.live.com.
+upmhvgmnnltgfurm.biz.
+ad.harrenmedianetwork.com.
+adserving.cpxinteractive.com.
+d2106904.xoom.it.
+thuule.pair.com.
+static.ak.fbcdn.net.
+s-static.ak.facebook.com.
+a.root-servers.net.
+time.chttl.com.tw.
+nelleke.deviantart.com.
+newversion.epyte.com.
+transitk2000.ru.
+www.googletagservices.com.
+exchange.caosco.com.
+mw.tn.ru.
+sites.google.com.
+aol.com.
+www.clickestetica.com.
+osiprint.com.
+instagr.am.
+v7.cache6.c.youtube.com.
+21.148.59.199.in-addr.arpa.
+xvizxie21.89dz.
+twitter.com.
+capitolcreag.com.
+r._dns-sd._udp.lan.
+_848_24_6.
+developers.facebook.com.
+44.20.86.186.in-addr.arpa.
+mail1.sterlingethanol.com.
+time.chttl.com.tw.
+33.103.222.189.in-addr.arpa.
+www.youtube.com.
+www.pohlarchitekten.de.
+top100sexiestwomen.com.
+platform.ak.fbcdn.net.
+accounts.google.com.
+googthis.tk.
+gfx3.hotmail.com.
+smtp2.transource.com.
+img5.xooimage.com.
+www.detikfood.com.
+s2.youtube.com.
+getprof.us.np.community.playstation.net.
+_144_55_2.
+www.institutoalma.org.
+news.google.com.mx.
+mail.indharness.com.
+26.48.173.201.in-addr.arpa.
+h.live.com.
+www.rainydaymagazine.com.
+167.131.42.201.in-addr.arpa.
+mypaleokitchen.blogspot.com.
+globalmar.ru.
+rss.allaboutwindowsphone.com.
+www.ubalert.com.
+platform.twitter.com.
+tsprints.com.
+static.ak.fbcdn.net.
+dns.msftncsi.com.
+211.188.104.189.in-addr.arpa.
+www.qwa3ed.i8.com.
+ns2.h17.domen.com.ua.
+cdn1.inner-active.mobi.
+mail.matthewbarney.com.
+flowenglish.dev01.atlanticbt.net.
+e5153.b.akamaiedge.net.
+samrphotography.blogspot.com.
+a7.sphotos.ak.fbcdn.net.
+254.52.28.186.in-addr.arpa.
+www.elprisma.com.
+mail.tpwh.com.
+photos-h.ak.fbcdn.net.
+34.132.146.186.in-addr.arpa.
+www.feriadesanmarcos.gob.mx.
+photos-f.ak.fbcdn.net.
+wj8.so-net.ne.jp.
+a749.g.akamai.net.
+www.mt-box.org.
+mail.google.com.
+216.185.186.189.in-addr.arpa.
+profile.live.com.
+247.170.13.180.in-addr.arpa.
+www.facebook.com.
+www.uisg.org.
+jack-cole.com.
+cache.pack.google.com.
+89.168.227.61.in-addr.arpa.
+216.151.152.186.in-addr.arpa.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.tormenttube.com.
+photos-d.ak.fbcdn.net.
+82.199.229.190.in-addr.arpa.
+deloitte.fr.s200b2.psmtp.com.
+221.58.139.187.in-addr.arpa.
+199.234.109.24.in-addr.arpa.
+d3lvr7yuk4uaui.cloudfront.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+bay-labels.com.
+emergency-boot-cd-rom.softonic.com.
+54.73.42.186.in-addr.arpa.
+245.149.130.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.trampolinesystems.com.
+ecn.t2.tiles.virtualearth.net.
+170.113.92.186.in-addr.arpa.
+mail.conduit-ventures.com.
+a.i.blip.tv.
+google.com.
+v1.cache2.c.youtube.com.
+resources.search.conduit.com.
+www.urbaks.com.
+teredo.ipv6.microsoft.com.
+9ncitkxzf.27cy.
+www.l.google.com.
+www.luwaran.com.
+secure.wlxrs.com.
+jvm.ing.onored.com.
+time.nist.gov.
+mtalk.google.com.
+sites.google.com.
+_845_62_9.
+181.161.153.89.in-addr.arpa.
+mail.edu.rocmn.nl.
+104.73.156.187.in-addr.arpa.
+www.google.com.mx.
+api.conduit.com.
+massman.net.mail5.psmtp.com.
+sn1msg1010616.gateway.messenger.live.com.
+myaccount.kelloggs.com.
+210.134.253.99.in-addr.arpa.
+static.ak.fbcdn.net.
+37-courier.push.apple.com.
+www.facebook.com.
+laserhosts.com.
+webcache.googleusercontent.com.
+styleline.us.
+www.thedivinemercy.org.
+nl.vandermoolen.com.
+g.live.com.
+www.youtube.com.
+a.root-servers.net.
+onespot.wsj.com.
+photos-g.ak.fbcdn.net.
+51.157.82.189.in-addr.arpa.
+clients1.google.com.
+mx-1.naver.com.
+www.histats.com.
+www.oya-es.net.
+google.com.mx.
+ads.lfstmedia.com.
+47.95.122.84.in-addr.arpa.
+www.facebook.com.
+stats.pokerist.com.
+d2103064.xoom.it.
+clients2.google.com.
+www.4shared.com.
+s-static.ak.fbcdn.net.
+apps.facebook.com.
+ad.bannerconnect.net.
+www.lyngsat-logo.com.
+api.twitter.com.
+www.bulkblacksex.com.
+chroniclesmagazine.org.
+a6.sphotos.ak.fbcdn.net.
+www.lipdub.eu.
+ssl.gstatic.com.
+www.facebook.com.
+www.negrasdelbronx.com.
+bayfiles.com.
+a.root-servers.net.
+241.245.13.187.in-addr.arpa.
+secure.shared.live.com.
+tfgrtezqnfkewpchzgyronljweoyop.nl.
+www.egopixel.com.
+a7.sphotos.ak.fbcdn.net.
+e-2dj6aelyqgc5igp.stats.esomniture.com.
+www.howtotranslatepdf.com.
+sp.cwfservice.net.
+davainksth.ordingslil.nu.
+138.52.55.46.in-addr.arpa.
+profile.ak.fbcdn.net.
+201.95.127.93.in-addr.arpa.
+www.facebook.com.
+ctar.ru.
+pds.catholic.or.kr.
+www.naesv.org.
+download346.avast.com.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+ynetnvjhr.76fz.
+blst.msn.com.
+a7.sphotos.ak.fbcdn.net.
+www.verfutbolhd.net.
+ungewitter.de.
+profile.ak.fbcdn.net.
+180.24.230.201.in-addr.arpa.
+www.fimkastore.com.
+blog.jaredcompany.com.
+secure.applifier.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+img.movieberry.com.
+rentshark.com.
+_487_21_5.
+apis.google.com.
+101.63.253.189.in-addr.arpa.
+static.pbc.com.
+billing.sharo4ka.ru.
+prudentialcresfl.com.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+post.telecom-f.ru.
+tuongphong2.com.
+tbr.ask.com.
+textad.xxxmatch.com.
+crl.microsoft.com.
+a.root-servers.net.
+smtp.ci.hayward.ca.us.
+ksn7.kaspersky-labs.com.
+3.146.222.189.in-addr.arpa.
+savetheroots.com.
+ads1.msads.net.
+mail1.humed.com.
+o.nimbuzz.com.
+www.airbridgecargo.com.
+themes.truethemes.net.
+www.gorestruly.com.
+themartletshospice.co.uk.
+mail.pinocchiosplace.com.
+dns.msftncsi.com.
+a.root-servers.net.
+time.windows.com.
+www.esmusicagratis.com.
+siemens.co.
+profootball.scout.com.
+winmedms.com.
+63.251.229.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+cdn.publicidad.net.
+81.146.192.187.in-addr.arpa.
+mail.welhuis.com.
+teamdemilovatoptonatales.blogspot.com.
+c-0.19-430cc069.20001.1518.19d3.2f4a.210.0.j8sccva3btb8ua63e31zf9hgtj.avqs.mcafee.com.
+.
+mksol.dseg.ti.com.
+248.225.45.93.in-addr.arpa.
+101.16.109.83.in-addr.arpa.
+mail.trufina.com.
+titanium30-en.url.trendmicro.com.
+foreveryounglala.wordpress.com.
+external.ak.fbcdn.net.
+divinecnatraining.com.
+rad.msn.com.
+weather.services.conduit.com.
+a-0.19-a309e081.c0b0082.1518.19d2.3ea1.210.0.f6gh2675ft2wdhqj6nbmrsj136.avqs.mcafee.com.
+38.249.10.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+federaldirect.net.
+56nq4nu82.87ba.
+_758_24_0.
+122.204.222.201.in-addr.arpa.
+www.aving.co.kr.
+cdn.applifier.com.
+www.yahoo.com.
+249.95.51.201.in-addr.arpa.
+mxs.mail.ru.
+www.facebook.com.
+ak.imgfarm.com.
+safebrowsing.clients.google.com.
+dns.msftncsi.com.
+mscrl.microsoft.com.
+92.215.159.189.in-addr.arpa.
+248.248.115.85.in-addr.arpa.
+www.facebook.com.
+cu018.www.duba.net.home.
+197.185.150.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+accounts.google.com.
+adfarm.mediaplex.com.
+imap.mail.yahoo.com.
+download.windowsupdate.com.
+www.goldenchile.cl.
+123.186.172.178.zz.countries.nerd.dk.
+www.confezionicrosby.com.
+s.ytimg.com.
+blog.iconshock.com.
+www.interbiu.com.
+soundcloud.tumblr.com.
+ic.tynt.com.
+a.root-servers.net.
+www.belkin.com.
+static.ak.fbcdn.net.
+grc.mx.
+nypd.org.
+166.251.182.95.in-addr.arpa.
+_558_82_9.
+tools.google.com.
+229.219.250.190.in-addr.arpa.
+platform.ak.fbcdn.net.
+ad-emea.doubleclick.net.
+checkip.dyndns.org.
+crl.microsoft.com.
+209.127.47.190.in-addr.arpa.
+reedbusiness.com.au.
+newtoseeblog.info.
+ad.yieldmanager.com.
+id.google.com.
+www.google.com.
+xwjdciibb.99yy.
+c14.zedo.com.
+vmwebfe.voice.yahoo.com.
+bfrwkzqj.info.
+ksn3-11.part1.kaspersky-labs.com.
+144.220.68.99.in-addr.arpa.
+jarvis.net.
+lpi.msk.su.
+s348256632.mialojamiento.es.
+pool.ntp.org.
+a771.da1.akamai.net.
+197.35.214.67.in-addr.arpa.
+a.root-servers.net.
+234.193.121.95.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+m.addthisedge.com.
+www.google-analytics.com.
+60.66.226.189.in-addr.arpa.
+129.157.221.108.in-addr.arpa.
+htmlbook.ru.
+api-read.facebook.com.
+80.34.251.201.in-addr.arpa.
+blufiles.storage.msn.com.
+businessplus.com.
+195.2.0.192.in-addr.arpa.
+mail.eidnet.org.
+zqvxxwkwh.q11p1a3r.
+dns.msftncsi.com.
+fgb.net.s5a2.psmtp.com.
+139.122.196.190.in-addr.arpa.
+a.root-servers.net.
+2.159.169.189.in-addr.arpa.
+6.101.138.187.in-addr.arpa.
+yahoo.com.
+lobnya.ru.
+www.acubens.com.ar.
+external.ak.fbcdn.net.
+www.ngopulse.org.
+z5hbstzvi.82en.
+www.big-pub.com.
+113.128.177.190.in-addr.arpa.
+msc.wlxrs.com.
+politicalinsider.com.
+i1.ytimg.com.
+www.juaneslavagalan.com.
+presentesausencias.blogspot.com.
+support.google.com.
+235.247.137.189.in-addr.arpa.
+www.crouzet.com.
+photos-b.ak.fbcdn.net.
+inbound.deck2.com.netsolmail.net.
+haefeles.com.
+i4.ytimg.com.
+0-ie-w.channel.facebook.com.
+commons.wikimedia.org.
+157.114.25.89.in-addr.arpa.
+mailsputnik.mail.ru.
+time.windows.com.
+mail.columbus.rr.com.lan.
+s.ytimg.com.
+msn.com.
+login.yahoo.com.
+popdynamite.com.
+www.myshoptoday.co.za.
+nylim.com.
+a.root-servers.net.
+gccnj.edu.
+creative.ak.fbcdn.net.
+mor3ben.com.
+creative.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+116s.pl.
+www.leeyora.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tdy.prodigy.msn.com.
+58.116.4.24.in-addr.arpa.
+www.casadellibro.com.
+16.134.234.190.in-addr.arpa.
+dns.msftncsi.com.
+w88.go.com.
+166.93.209.201.in-addr.arpa.
+merck.websitesampling.com.
+dns.msftncsi.com.
+www4.esu.edu.
+sn3.mailshell.net.
+profile.ak.fbcdn.net.
+rdee-ont.ca.
+plus.google.com.
+isatap.domain.name.
+a6.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.facebook.com.
+100.16.109.186.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.ehas.org.
+sn3.mailshell.net.
+es.lanoire.wikia.com.
+www.facebook.com.
+www.syfyuniversal.es.
+ceups.contabilidad.unmsm.edu.pe.
+c-0.19-23098481.483.1518.19d4.3ea1.410.0.l6rt2gtgmcst4e8d6pu8zqmhrb.avqs.mcafee.com.
+web.knotice.com.
+parana2003.galeon.com.
+28.71.68.201.in-addr.arpa.
+mail.g-ss.ru.
+_ldap._tcp.
+d3lvr7yuk4uaui.cloudfront.net.
+104.31.39.187.in-addr.arpa.
+gateway.messenger.hotmail.com.
+windsongtherapy.com.
+handwriting.shuru.qq.com.
+a8.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+clarkstonconsulting.com.mail10.psmtp.com.
+tools.google.com.
+mnpsmail2.nashville.gov.
+user.baofeng.com.
+i1.ytimg.com.
+i5.createsend4.com.
+a2.sphotos.ak.fbcdn.net.
+static11.juegosoka.com.
+i1.ytimg.com.
+a.root-servers.net.
+platform.ak.fbcdn.net.
+www.getfoundingoogle.com.au.
+worldpress.org.
+apps.facebook.com.
+toolbarqueries.google.com.
+www.telenovelasgratis.com.
+blogger-loader.googlecode.com.
+akvamarin.ru.
+jiandan3.34245.com.
+imagenarium.ru.
+224.199.218.83.in-addr.arpa.
+2.61.204.72.in-addr.arpa.
+rt.legolas-media.com.
+fbcdn-profile-a.akamaihd.net.
+convad.net.
+putty.softonic.de.
+widenetwork.ning.com.
+254.74.134.189.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+ksn2-12.kaspersky-labs.com.
+xvideos-738.vo.llnwd.net.
+www.latribunadelahistoria.es.
+aptoverde.info.
+developers.facebook.com.
+manta.harrisinteractive.com.
+www.youtube.com.
+a3.sphotos.ak.fbcdn.net.
+everythingtoshare.com.
+sogospel.com.
+dns.msftncsi.com.
+suddenlink.net.
+a.root-servers.net.
+doomadgee.qld.gov.au.
+thumbs4.ebaystatic.com.
+support.game321.com.
+a995.mm1.akamai.net.
+248.30.252.189.in-addr.arpa.
+toolbarqueries.google.com.
+api.configar.org.
+a5.sphotos.ak.fbcdn.net.
+90.129.68.189.in-addr.arpa.
+voxgraeca.blogspot.com.
+www.oldnavy.gap.com.
+73.63.122.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+205.43.233.189.in-addr.arpa.
+www.skills2lead.com.
+google.com.
+quincyrehab.com.
+docs.google.com.
+www.ocsmedia.net.
+a.root-servers.net.
+fbcdn-profile-a.akamaihd.net.
+91.243.77.190.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+97.221.10.187.in-addr.arpa.
+yahoo.match.com.
+a4.sphotos.ak.fbcdn.net.
+198.148.240.111.in-addr.arpa.
+www.imakenews.com.
+www.miniclip.co.
+www.msftncsi.com.
+boards.gandreas.com.
+armdl.adobe.com.
+scullypacking.com.
+mint.yes.fm.
+zynga2-a.akamaihd.net.
+www.nethunter.cl.
+reedbusiness.com.au.
+p05-bookmarks.icloud.com.
+www.orlworld.com.
+a.root-servers.net.
+hook.yieldbuild.com.
+152.41.215.189.in-addr.arpa.
+thirdmaritime.com.
+a.root-servers.net.
+es-es.facebook.com.
+118.114.233.190.in-addr.arpa.
+www.ciudadaniaestudiantil.com.
+www.torrenteros.org.
+yamaguchi-u.ac.jp.
+www.update.microsoft.com.
+www.youtube.de.
+52.132.97.212.in-addr.arpa.
+www.isidrosobrino.com.
+nendo.softonic.com.
+pagead2.googlesyndication.com.
+_876_98_3.
+www.uptodown.com.
+235.225.166.189.in-addr.arpa.
+stlamerican.com.
+r._dns-sd._udp.0.10.168.192.in-addr.arpa.
+art.123seguro.com.ar.
+crl.microsoft.com.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+mx01.pathcom.com.
+messiahmauldin.org.
+sn104w.snt104.mail.live.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.update.microsoft.com.
+www.slideshare.net.
+www.ptdf.org.mx.
+auto.drom.ru.
+platform.ak.fbcdn.net.
+pagead2.googleadservices.com.
+imp.ad-plus.cn.
+a2.sphotos.ak.fbcdn.net.
+www.facebook.com.
+169.29.58.186.in-addr.arpa.
+p.visualrevenue.com.
+groups.google.com.mx.
+webcache.googleusercontent.com.
+46.16.49.190.in-addr.arpa.
+extendedvision.com.au.
+a.root-servers.net.
+midmac.net.
+zbar.zynga.com.
+198.179.0.201.in-addr.arpa.
+203.238.228.190.in-addr.arpa.
+b._dns-sd._udp.lan.
+www.symantec.com.
+www.adobe.com.
+255.162.140.120.in-addr.arpa.
+fb-zc1.cityville.zynga.com.
+tock.usno.navy.mil.
+ssibr.com.
+i7.tagstat.com.
+ci.camas.wa.us.
+a4.sphotos.ak.fbcdn.net.
+127.0.0.1.
+lb._dns-sd._udp.lan.
+photos-f.ak.fbcdn.net.
+bernco.com.
+5aawh4y3x.v08r7e0m.
+googleads.g.doubleclick.net.
+megaasesoriainmobiliaria.blogdiario.com.
+a.root-servers.net.
+appsmetadata.toolbar.conduit-services.com.
+ifw.com.
+s-static.ak.facebook.com.
+153.21.83.201.in-addr.arpa.
+comtonduling.com.
+proof.hsifin.com.
+efd8zvfdi.78jy.
+www.toneitupdiet.com.
+www.sportdiver.com.
+www.madison.k12.wi.us.
+mini5.opera-mini.net.
+dwuinc.com.pri-mx.na0109.smtproutes.com.
+158.66.55.174.in-addr.arpa.
+ad.adtegrity.net.
+google.com.
+mail.co.wayne.ny.us.
+ogo9mh::a.52vn.
+dl3.avgate.net.
+platform.ak.fbcdn.net.
+203.94.77.190.in-addr.arpa.
+wpad.
+devilon-m.msk.ru.
+iliack4mr.s63j6v7y.
+azloans4you.com.
+s9.addthis.com.
+a3.twimg.com.
+google.com.
+suffragan.com.
+11.25.69.189.in-addr.arpa.
+dingtao333.3322.org.
+pattencpa.net.
+callofduty.filefront.com.
+mmaweekly.performancemma.com.
+218.196.173.119.in-addr.arpa.
+.
+dss1.siteadvisor.com.
+v-lazer.magadan.ru.
+r.admob.com.
+ctcn.com.
+mail.jbl1.com.
+external.ak.fbcdn.net.
+51.137.91.95.in-addr.arpa.
+c33.ru.
+thumbs3.ebaystatic.com.
+www.facebook.com.
+jedineka.com.
+www.facebook.com.
+mail.mailcontractors.com.
+mail2.dahlmotors.com.
+23.229.171.69.in-addr.arpa.
+em.adpro-ads.com.
+dns.msftncsi.com.
+a7.sphotos.ak.fbcdn.net.
+www.vipstreamservice.com.
+mail.e-salt.ru.
+ax.init.itunes.apple.com.
+a.root-servers.net.
+www.onlinedatingsafetytips.com.
+rv.coupish.com.
+230.173.49.190.in-addr.arpa.
+nutzworld.com.
+109.179.164.186.in-addr.arpa.
+static.jisiklog.com.
+colegioelhayaenglishcorner.blogspot.com.
+www.fal.com.co.
+6.96.84.200.in-addr.arpa.
+m.addthisedge.com.
+goodsonauto.com.
+46.158.76.188.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+de-de.facebook.com.
+a.root-servers.net.
+73.24.144.189.in-addr.arpa.
+search.iminent.com.
+196.237.235.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+a1051.b.akamai.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.enladisco.com.
+localhost.
+apps.facebook.com.
+_075_21_2.
+cdn.api.twitter.com.
+c0013512.r32.cf1.rackcdn.com.
+54.63.73.46.in-addr.arpa.
+218.166.36.114.in-addr.arpa.
+www.ncbi.nlm.nih.gov.
+api.twitter.com.
+voipc.sip.yahoo.com.
+fbcdn-profile-a.akamaihd.net.
+static.ak.fbcdn.net.
+a.root-servers.net.
+careers.digitaldomain.com.
+www.29arabicletters.com.
+a.root-servers.net.
+87.25.65.93.in-addr.arpa.
+relay.voice.messenger.msn.com.
+e2756.b.akamaiedge.net.
+www.torquecars.com.
+mx.images.search.yahoo.com.
+u:ym6bwws.v62b7m9d.
+44.207.72.84.in-addr.arpa.
+dns.msftncsi.com.
+www.gronkcomic.com.
+m.addthisedge.com.
+time.chttl.com.tw.
+photos-b.ak.fbcdn.net.
+www.planning.wa.gov.au.
+bicentenario.unc.edu.ar.
+decorarts.files.wordpress.com.
+cdn.viglink.com.
+www.telegraph.co.uk.
+152.246.171.24.in-addr.arpa.
+52.21.129.158.in-addr.arpa.
+pbimail3.prodigy.net.
+17.192.177.190.in-addr.arpa.
+a.root-servers.net.
+baade.dba.dk.
+aspelle.com.
+www.turkodesigns.com.
+a1.twimg.com.
+220.241.152.187.in-addr.arpa.
+mail.sportsonesource.com.
+mx1.grattanproperty.com.
+71.193.34.60.in-addr.arpa.
+s.ytimg.com.
+www.blogazos.com.
+2.13.111.189.in-addr.arpa.
+www.bullsfloor.com.
+231.199.201.190.in-addr.arpa.
+228.94.55.174.in-addr.arpa.
+m.xp1.ru4.com.
+ib.adnxs.com.
+113.191.15.189.in-addr.arpa.
+a.root-servers.net.
+localhost.
+a.blip.tv.
+164.3.226.190.in-addr.arpa.
+mail.kroog.ru.
+secure.fishgame3d.com.
+7xko:62o9.15gk.
+www.honeybee.com.au.
+outreachconnect.org.
+a.l.yimg.com.
+2.19.149.186.in-addr.arpa.
+www.styleandpepperblog.com.
+anycast-europe.quantserve.com.akadns.net.
+www.apple.com.
+smilesandflirts.com.
+29.26.109.84.in-addr.arpa.
+s1-word-edit.vo.msecnd.net.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+apps.facebook.com.
+yahoo.com.
+191.146.122.77.in-addr.arpa.
+es.elderscrolls.wikia.com.
+scribe.twitter.com.
+msgr.updates.yahoo.com.
+wsoulrc.com.
+www.14ers.com.
+www.google-analytics.com.
+google.com.
+9h371za7k.84ml.
+www.youtube.com.
+agothsphere.com.
+consumerone.com.
+www.ziaruldebacau.ro.
+connect.facebook.net.
+wfa4l9tu2.35sk.
+_855_17_2.
+a.root-servers.net.
+www.realgirlglam.com.
+storage.store2phone.com.
+www.cheapnbajerseys.biz.
+newsrss.bbc.co.uk.
+amer.rel.msn.com.
+blogdelfuturo.com.
+verybigdays.net.
+sulima.org.
+a.root-servers.net.
+8nl1r99e6.r35f1v6r.
+tr.com.s5a2.psmtp.com.
+myallamericanlending.com.
+doug1izaerwt3.cloudfront.net.
+images.nokiagate.com.
+2.71.155.189.in-addr.arpa.
+cf.addthis.com.
+ma156-r.analytics.edgesuite.net.
+mail.thefrontierproject.com.
+googleads.g.doubleclick.net.
+m.facebook.com.
+cz-user.he.cninfo.net.
+a.root-servers.net.
+news.kmdevantagens.com.br.
+www.uvvu.com.
+profile.ak.fbcdn.net.
+static.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+moddys.com.
+p18-buy.itunes.apple.com.
+www.layeredtech.com.
+rs3.scribd.com.
+pds2.miclub.com.
+158.121.12.86.in-addr.arpa.
+graph.facebook.com.
+a.root-servers.net.
+celinedion.com.
+www.clubsnap.com.
+ad.yieldmanager.com.
+photos-f.ak.fbcdn.net.
+adserving.cpxinteractive.com.
+peloterotv.blogspot.com.
+251.25.111.95.in-addr.arpa.
+www.arcatapet.com.
+static.xvideos.com.
+profile.ak.fbcdn.net.
+b.scorecardresearch.com.
+www.facebook.com.
+a.root-servers.net.
+c-0.19-a309f481.20483.1518.19d4.3ea1.410.0.7mq42g1burzz6enmpeuv8t3lh5.avqs.mcafee.com.
+boi.perfectworld.com.
+www.moviereplicasdirect.com.
+a7.sphotos.ak.fbcdn.net.
+th07.deviantart.net.
+mec.deviantclip.com.
+a.root-servers.net.
+syncservices.me.com.
+2.0.168.192.in-addr.arpa.
+102.226.32.177.in-addr.arpa.
+www.facebook.com.
+yui.yahooapis.com.
+a.root-servers.net.
+www.l.google.com.
+img.msg.yahoo.com.
+32.127.71.86.in-addr.arpa.
+update.sanasecurity.com.
+180.175.168.192.in-addr.arpa.
+p50-buy.itunes.apple.com.akadns.net.
+www.conduit.com.
+cdn2.grupos.emagister.com.
+secure.wlxrs.com.
+a5.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+clients2.google.com.
+15minutefashion.about.com.
+sp.cwfservice.net.
+61.164.34.189.in-addr.arpa.
+www.stormwise.com.
+ebookbrowse.com.
+onsenjikan.dreamwidth.org.
+www.google.com.
+4.bp.blogspot.com.
+creative.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+84.223.160.187.in-addr.arpa.
+lh4.ggpht.com.
+www.l.google.com.
+beta.stun.voice.yahoo.com.
+xowneisrh.h25d6r7s.
+mx2.actsyuma.net.
+_524_58_5.
+www.msanet.com.mx.
+www.adobe.com.
+114.241.225.190.in-addr.arpa.
+a.root-servers.net.
+www.4shared.com.
+a.root-servers.net.
+auth.leonardo.it.
+mmorales.diarioeldia.cl.
+gateway.messenger.hotmail.com.
+ads.yimg.com.
+www.sickbeard.com.
+profile.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+140.140.134.186.in-addr.arpa.
+reviews.singerco.com.
+118.188.189.78.in-addr.arpa.
+tc21.easythumbhost.com.
+fbcdn-profile-a.akamaihd.net.
+directory.services.live.com.
+99.139.175.189.in-addr.arpa.
+6.123.30.189.in-addr.arpa.
+console-ssl.service.playfish.com.
+pixel.mathtag.com.
+a.root-servers.net.
+ocsp.verisign.com.
+a.root-servers.net.
+128.38.110.189.in-addr.arpa.
+ydyb7ga1u.g11y8v8k.
+18.185.233.94.in-addr.arpa.
+www.euroresidentes.com.
+rs667tl2.rapidshare.com.
+46.201.173.190.in-addr.arpa.
+47.28.158.17.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+107.224.225.190.in-addr.arpa.
+essalud.gob.pe.
+directfurniture.com.
+a5.sphotos.ak.fbcdn.net.
+egate.net56.com.
+photos-a.ak.fbcdn.net.
+articulossobrebelleza.blogspot.com.
+a.root-servers.net.
+u20.eset.com.
+ejabat.google.com.
+gd5.ru.
+242.248.130.186.in-addr.arpa.
+47.198.78.189.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+250.207.167.190.in-addr.arpa.
+wallst.jpmorganchase.com.
+39.200.209.201.in-addr.arpa.
+1internet.com.
+eset-la.com.dnsbl7.mailshell.net.
+a.root-servers.net.
+www.lfpslebanon.com.
+_ldap._tcp.
+clients4.google.com.
+158.90.127.201.in-addr.arpa.
+crl.microsoft.com.
+webcache.googleusercontent.com.
+a8.sphotos.ak.fbcdn.net.
+smtp.wanadoo.fr.
+photos-c.ak.fbcdn.net.
+vofydac.com.
+admin.loading321.com.
+ciitlahore.edu.pk.
+flol.sabayacafe.com.
+thefluffingtonpost.com.
+asamblea.gob.ni.
+www.argladou.com.
+19.248.90.187.in-addr.arpa.
+ksn1-11-part2.kaspersky-labs.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+_790_26_3.
+adamwhiles.com.
+ssl.gstatic.com.
+cyberrelief.com.
+assets3.castle.zgncdn.com.
+61.5.157.201.in-addr.arpa.
+194.205.232.76.in-addr.arpa.
+251.91.106.200.in-addr.arpa.
+log.video.mail.ru.
+175.82.137.201.in-addr.arpa.
+australia.urbansketchers.org.
+124.156.181.175.in-addr.arpa.
+midi-pyrenees.cci.fr.
+crimecitymafiacodes.com.
+242.152.161.142.in-addr.arpa.
+ph9rfx8j6.13ni.
+radar.cedexis.com.
+142.149.106.85.in-addr.arpa.
+112.125.168.192.in-addr.arpa.
+js.admeld.com.
+bridge1.admarketplace.net.
+thumbs.hotmature.in.
+248.41.52.186.in-addr.arpa.
+gilat.com.
+cdn.api.twitter.com.
+clat99yq7.k30g3x3d.
+lsum.com.
+www.getansweronline.com.
+xxlcc.com.
+jbjs.org.
+www.cag.es.
+a.root-servers.net.
+prudentialatlantic.com.
+photos-a.ak.fbcdn.net.
+36c:a7gcs.l56k5z0d.
+227.137.19.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+m78mnt884.96ig.
+login.only10.com.
+_746_57_9.
+g.msn.com.
+vp.sip.messenger.msn.com.
+www.kitcosilver.com.
+ads.neighborhoodnotes.com.
+ejkbi2tdz.f31m9l0f.
+a.root-servers.net.
+personalitypedagogy.arcadia.edu.
+profile.ak.fbcdn.net.
+p9u.ru.
+a.root-servers.net.
+245.104.131.41.in-addr.arpa.
+mtalk.google.com.
+makemeunder.blogspot.com.
+50cubes-a.akamaihd.net.
+photos-f.ak.fbcdn.net.
+www.socialgrowthtechnologies.com.
+shared.live.com.
+googleads.g.doubleclick.net.
+external.ak.fbcdn.net.
+p072.ezboard.com.
+227.47.106.27.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+cta-service.cms.hubspot.com.
+a1.sphotos.ak.fbcdn.net.
+.
+jcqkm:zim.80db.
+10.img.v4.skyrock.net.
+cs12814.vk.com.
+blog.facebook.com.
+169.webim0214.webim.myspace.com.
+www.webcamxtc.com.
+mail.twobest.com.
+mn.com.
+www.av.com.
+photos-b.ak.fbcdn.net.
+34.243.35.187.in-addr.arpa.
+time.windows.com.
+_978_73_3.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+36.138.91.186.in-addr.arpa.
+www.buzzbinmagazine.com.
+udencuar.com.domain_not_set.invalid.
+advisor.fidelity.com.
+dvln.com.
+tvwebfamosos.blogspot.com.
+a.root-servers.net.
+55.187.24.201.in-addr.arpa.
+fthr.com.s7b2.psmtp.com.
+www.20min.ch.
+d15gt9gwxw5wu0.cloudfront.net.
+a-0.19-a20fd081.a060131.1518.19d4.3ea1.410.0.555215vife6tps7czkhjhiiz15.avqs.mcafee.com.
+ubst.dk.
+29.159.209.190.in-addr.arpa.
+www.thughunter.com.
+www.liveroof.com.
+172.50.189.201.in-addr.arpa.
+ksn1-11-part2.kaspersky-labs.com.
+c.lomadee.com.
+www.italianmoda.com.es.
+www.google.com.
+ad-g.doubleclick.net.
+apps.facebook.com.
+www.whyimcatholic.com.
+254.70.51.173.in-addr.arpa.
+www.youtube.com.
+www.frivy8games.com.
+twitter.com.
+cfpinsurance.com.
+s.youtube.com.
+relay.i-gorod.com.
+developers.facebook.com.
+xf:riuj5v.c97d6b9c.
+boss.com.s201a1.psmtp.com.
+stats.buysellads.com.
+mail.disneinc.com.
+lh5.googleusercontent.com.
+mail.scalando.com.
+www.findtubes.com.
+helifax-web.com.
+c2i.net.
+sullana.amarillasperu.net.
+www.facebook.com.
+i2.ytimg.com.
+cgil.brescia.it.
+d261sv3xac0f7i.cloudfront.net.
+ad.foxnetworks.com.
+www.galleries.lilkelly.com.
+craftsmanmold.com.2.arsmtp.com.
+ece.uic.edu.
+231.119.105.190.in-addr.arpa.
+musica.itematika.com.
+www.customquillingbydenise.com.
+a.root-servers.net.
+rbscorp.net.
+www.facebook.com.
+www.aspaym.org.
+cshoppingbox.partner.leguide.com.
+cuttingnyc.com.
+protesen.dk.
+clicktrack3.ziyu.net.
+loading.widdit.com.
+amserv.ru.
+1klik.com.
+v14.nonxt3.c.bigcache.googleapis.com.
+36.0.108.116.in-addr.arpa.
+safepla.net.
+weather.service.msn.com.
+csi.gstatic.com.
+bc41b2bjhrjwem9m6m9d3dll3t.hop.clickbank.net.
+mail2.digitalfoundation.net.
+platform.ak.fbcdn.net.
+tallerdeelectricidadelespinillo.blogspot.com.
+www.youtube.com.
+m.addthisedge.com.
+a.root-servers.net.
+i.dailymail.co.uk.
+a.root-servers.net.
+j.local.
+smith-gibson.com.
+jcenter.ru.
+smgplaw.com.s5a2.psmtp.com.
+amsystem.es.
+254.141.234.189.in-addr.arpa.
+bcp.crwdcntrl.net.
+www.metainstaller.com.
+yahoo.com.
+228.77.250.189.in-addr.arpa.
+apis.google.com.
+b3.123show.com.
+mail1.bagroup.com.
+mail.sendero.cl.
+www.numberjacks.co.uk.
+www.lenodown.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+4cventures.com.
+d:6pmofe7.l39g0z0b.
+s-static.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+relay3.aeroflot.ru.
+www.youtube.com.
+a.root-servers.net.
+www.snoopdogg.com.
+2.6.167.213.in-addr.arpa.
+safebrowsing.clients.google.com.
+211.42.134.188.in-addr.arpa.
+0-250.channel.facebook.com.
+stoke.gov.uk.
+199.47.159.189.in-addr.arpa.
+api.facebook.com.
+www.buenastareas.com.
+5.50.220.189.in-addr.arpa.
+www.vestirjogos.com.
+uni-sys.com.inbound15.mxlogic.net.
+photos-f.ak.fbcdn.net.
+api-read.facebook.com.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+cyclope.auto-futura.ru.
+80.16.118.187.in-addr.arpa.
+71.25.92.86.in-addr.arpa.
+pagead2.googlesyndication.com.
+inbound.adamtravel.net.netsolmail.net.
+www.pcpowerspeed.com.
+alyrica.net.
+blogcindad.com.
+www.ectaco-store.com.
+ja-jp.facebook.com.
+a1725.l.akamai.net.
+www.librosgratisweb.com.
+performersoft.s3.amazonaws.com.
+paragonrea.com.s9b2.psmtp.com.
+246.112.159.78.in-addr.arpa.
+pagead2.googlesyndication.com.
+pop3.sitek.net.
+twitter.com.
+www.google.com.
+mx2.luukku.com.
+www.caciquecapoeira.com.
+www.kissafattie.com.
+www.hugetitspicture.com.
+8.150.93.201.in-addr.arpa.
+bosonweb.com.
+www.mercurynews.com.
+pubmirrors.reflected.net.
+apps.facebook.com.
+a.rad.msn.com.
+0-jj-w.channel.facebook.com.
+mobile.twitter.com.
+weima.com.
+static.ak.fbcdn.net.
+orig-10006.europapress.cotcdn.net.
+6-0.qlty.finarea.ch.
+v18.ou.sdo.com.
+fitocracy.com.
+widgets.amung.us.
+www.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+tinhoc.net.vn.
+alt1.v6.cache5.c.pack.google.com.
+176.237.240.210.in-addr.arpa.
+plaza1.net.
+www.google.com.
+a.root-servers.net.
+www.towing.co.uk.
+twitter.com.
+arkitekt-christiansen.dk.
+gramafacil.softonic.com.
+plus.google.com.
+www.cam4premium.com.
+a1.sphotos.ak.fbcdn.net.
+p99-imap.mail.me.com.
+fimm4825d.v41j1m1a.
+215.80.170.201.in-addr.arpa.
+16.147.220.66.in-addr.arpa.
+coronadopaint.com.
+developers.facebook.com.
+www.biodegradable.com.mx.
+appsec.eniro.com.
+adokin66.blogspot.com.
+www.musicsonglyrics.com.
+mail2.martinyale.com.
+www.michael-pratt.com.
+ads.mopub.com.
+253.24.71.75.in-addr.arpa.
+nglgdczcxk.net.
+108.241.143.201.in-addr.arpa.
+208.136.115.186.in-addr.arpa.
+disneyland.disney.go.com.
+www.script-tutorials.com.
+dns.msftncsi.com.
+www.decoz.com.
+profile.ak.fbcdn.net.
+manualidades.chiquipedia.com.
+photos-d.ak.fbcdn.net.
+mx2.kulturit.no.
+136.234.251.189.in-addr.arpa.
+heroesxsiempre.wordpress.com.
+www.yolandaadamslive.com.
+_031_71_4.
+vmtubes.com.br.
+winwin.ift.fr.
+casema.nl.
+a3.sphotos.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+parishilton.fansitio.com.
+checkip.dyndns.org.
+www.google.com.
+l.yimg.com.
+photos-a.ak.fbcdn.net.
+mailer.cherus.ru.
+rus-reshenie.ru.
+sentimientos-leydy1006.blogspot.com.
+photos-d.ak.fbcdn.net.
+devices.live.com.
+3yqrensot.15ci.
+157.246.250.201.in-addr.arpa.
+ssl.gstatic.com.
+accounts.google.com.
+www.nobelcom.com.
+www.google.com.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+darkesthourmovie.com.
+nspmotion.com.
+fbcdn-profile-a.akamaihd.net.
+www.geosyr.com.ar.
+mail.yimg.com.
+www.explorenaples.com.
+photos-d.ak.fbcdn.net.
+love.zinzanni.org.
+api2.4shared.com.
+gfx4.hotmail.com.
+creative.ak.fbcdn.net.
+appad.gamevil.com.
+school.net.
+collector7.netgamesusa.com.
+www.manosegunda.com.mx.
+www.gomestic.com.
+gdyn.cnn.com.
+a.root-servers.net.
+3dprinters.ru.
+20minutos.feedsportal.com.
+api.webrep.avast.com.
+roland-oldala.mindenkilapja.hu.
+caps.fool.com.
+jjo.ru.
+_065_35_0.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a3.twimg.com.
+cville.net.
+developers.facebook.com.
+safebrowsing.clients.google.com.
+acoustica.softonic.com.
+profile.ak.fbcdn.net.
+pop3.live.com.
+messagebusiness.ru.
+143.173.62.177.in-addr.arpa.
+616e616a73.656c6d756e646f.6573.80hc16e80c3.webcfs00.com.
+liveupdate.symantecliveupdate.com.
+m.addthisedge.com.
+creative.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+101.122.51.190.in-addr.arpa.
+dl3.jvckenwood.com.
+si0.twimg.com.
+pdtm.blarg.net.
+sp.qbyrd.com.
+166.102.174.190.in-addr.arpa.
+a.root-servers.net.
+www.gstatic.com.
+i1.ytimg.com.
+aktakom.ru.
+tvenvivogratis.teleserviciosperu.com.
+maresco.gr.
+a5.sphotos.ak.fbcdn.net.
+www.bladder-surgery.net.
+medivisor.com.
+46-164-112-222.maxnet.ir.
+40.243.26.189.in-addr.arpa.
+espanol.yahoo.com.
+87.52.63.186.in-addr.arpa.
+tfnkm:phd.44xn.
+gfx4.hotmail.com.
+rojoblog.wordpress.com.
+s2000.spb.ru.
+st.chatango.com.
+www.facebook.com.
+www.facebook.com.
+bayyinah.com.
+omh.state.us.
+145.169.237.64.in-addr.arpa.
+e2umail.com.
+photos-e.ak.fbcdn.net.
+www.oxan.com.
+euro.mediotiempo.com.
+developers.facebook.com.
+41-courier.push.apple.com.
+quoteassociate.com.
+mcccharlotte.com.
+70.126.151.178.in-addr.arpa.
+header.vacationsmadeeasy.com.
+cs301806.vk.com.
+update.alot.com.
+img.widgets.video.s-msn.com.
+a.c-0.19-309b000.10033.1518.19d4.2f1c.10.0.wkj94emevza8c94129h2db22fi.avqs.mcafee.com.
+www.ctnewsjunkie.com.
+www.l.google.com.
+embassysuitesaz.com.
+adserver.juicyads.com.
+photos-e.ak.fbcdn.net.
+s-external.ak.fbcdn.net.
+136.233.3.190.in-addr.arpa.
+www.facebook.com.
+plus.google.com.
+19-courier.push.apple.com.
+mgz.cl.
+www.msftncsi.com.
+s0.2mdn.net.
+i3.ytimg.com.
+strangeglue.com.
+interop.com.multi.surbl.org.
+accounts.google.com.
+a8.sphotos.ak.fbcdn.net.
+44-courier.push.apple.com.
+it-it.facebook.com.
+tools.google.com.
+fbcdn-photos-a.akamaihd.net.
+rosenblatt-law.co.uk.
+med.greatviews.de.
+www.icdp.org.co.
+hostalaquimequedo.com.
+www.redtube.com.
+v0rak3.net.
+112.235.43.190.in-addr.arpa.
+227.76.93.186.in-addr.arpa.
+translate.google.com.mx.
+es-es.fxfeeds.mozilla.com.
+232.159.253.189.in-addr.arpa.
+usersamara.ru.
+cdn.api.twitter.com.
+163.184.32.180.in-addr.arpa.
+googleads.g.doubleclick.net.
+90.60.185.186.in-addr.arpa.
+134.42.24.189.in-addr.arpa.
+usam.edu.sv.
+m.google.com.vn.
+mvhrkvaekw.net.
+a.root-servers.net.
+a.root-servers.net.
+gg.google.com.
+50.29.204.223.in-addr.arpa.
+www.electricsupercharger.com.
+a.root-servers.net.
+bochsa.site.voila.fr.
+241.57.192.173.in-addr.arpa.
+www.google.com.mx.
+dfgdfgdf.com.
+localization.maktoob.com.
+fxfeeds.mozilla.com.
+a-0.19-a3090081.d030082.1518.19d4.3ea1.410.0.n37zcitfvmd9sl8h1z9j597jl6.avqs.mcafee.com.
+pbimail9.prodigy.net.
+lokotronicprincezz.blogspot.com.
+timne.ru.
+www.google.com.
+a.root-servers.net.
+_005_01_8.
+csc3-2010-crl.verisign.com.
+www.bflix.info.
+gumilla.org.
+overtopropetorrents.com.
+b-0.19-23006089.8251081.1518.19c7.3ea1.210.0.4qu8elj1p4riw36ub52iebr9uq.avqs.mcafee.com.
+blu.rr.msn.com.
+static.ak.connect.facebook.com.
+mail.pst-net.ru.
+profile.ak.fbcdn.net.
+furries.ru.
+www.imj.gob.mx.
+www.pixel2life.com.
+animegamusic.blogspot.com.
+hg1sddx19.57qn.
+eldec.com.
+a.root-servers.net.
+www.truebrutalmovies.com.
+fingrp.com.
+img.hotwords.com.br.
+predatorperformance.com.
+mx.dca.untd.com.
+101.61.240.189.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+189.69.203.200.in-addr.arpa.
+peru.amarillaslatinas.net.
+channelonetv.com.
+s.ytimg.com.
+mail.ccronline.com.
+www.arabia-ms.com.
+117.122.114.186.in-addr.arpa.
+sgw02.mtr.com.hk.
+photos-c.ak.fbcdn.net.
+m.eukanuba.es.
+avantgarde.com.
+teredo.ipv6.microsoft.com.
+smtp.acmebros.com.
+www.appstrip.com.
+pagead2.googlesyndication.com.
+19thcentury.wordpress.com.
+249.41.29.186.in-addr.arpa.
+www.zylomgames.com.
+reddingtank.com.
+netzero.com.
+clients1.google.com.
+app.appatyze.com.
+www.voanews.com.
+www.google-analytics.com.
+ex7.stingraytackle.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+223.118.176.78.in-addr.arpa.
+s225.meetrics.net.
+platform.ak.fbcdn.net.
+g.promosrv.com.
+www.facebook.com.
+blogcristiano.net.
+172.94.201.190.in-addr.arpa.
+twitter-any.s3.amazonaws.com.
+www.facebook.com.
+ontera.net.
+sierramonitor.com.
+elmaanareynos.disqus.com.
+hosting.live-e.tv.
+culpinak.blogspot.com.
+anka.ru.
+tunnel.cfw.trustedsource.org.
+whos.amung.us.
+photos-h.ak.fbcdn.net.
+arte-history.blogspot.com.
+www.motorcheck.ie.
+ping3.dyngate.com.
+230.180.42.60.in-addr.arpa.
+time.nist.gov.
+www.usmagazine.com.
+100.131.103.201.in-addr.arpa.
+99.20.0.192.in-addr.arpa.
+learn.caim.yale.edu.
+69.3.168.192.in-addr.arpa.
+mail.live.com.
+mail-carlc.gillhotels.com.
+zulu.tweetmeme.com.
+meeker.k12.co.us.s9b1.psmtp.com.
+a248.e.akamai.net.
+www.google-analytics.com.
+mail.nashbroselectrical.com.
+24.124.46.99.in-addr.arpa.
+s.ytimg.com.
+twimg0-a.akamaihd.net.
+luisalberto941.wordpress.com.
+robbiewilliamsradio.com.
+138.69.34.156.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+connect.facebook.net.
+nullmx.div.net.
+mail.ufoc.org.
+style.alibaba.com.
+static.ak.fbcdn.net.
+my-stats.info.
+u22.eset.com.
+www.catholicfraternity.net.
+photos-c.ak.fbcdn.net.
+www.gm.com.
+orcart.facebook.com.
+250.179.137.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.green.com.
+daggertools.com.
+tc.v6.cache6.c.youtube.com.
+photos-d.ak.fbcdn.net.
+www.thaimed.us.
+cdn.adslfaqs.com.ar.
+pagead2.googlesyndication.com.
+entrecard.com.
+profile.ak.fbcdn.net.
+arts.mitrasites.com.
+www.buenosaires.com.ar.
+computerkiddoswiki.pbwiki.com.
+122.109.8.200.in-addr.arpa.
+www.croatia.hr.
+.
+24.183.171.201.in-addr.arpa.
+anetstv.ru.
+clock.nyc.he.net.
+a8.sphotos.ak.fbcdn.net.
+slatoninsurance.com.1.arsmtp.com.
+connect.facebook.net.
+www-google-analytics.l.google.com.
+pt-br.facebook.com.
+mail3.infomart2000.com.
+123.244.92.186.in-addr.arpa.
+www.bing.com.
+6to4.ipv6.microsoft.com.
+112.214.232.190.in-addr.arpa.
+zbar2.zynga.com.
+a1324.da1.akamai.net.
+www.facebook.com.
+f86j.myhome.tv.
+224.133.124.201.in-addr.arpa.
+c.www.endless.com.
+diariodeunmiope.lacoctelera.net.
+www.xvideoslive.com.
+api.twitter.com.
+developers.facebook.com.
+livlifetoo.blogspot.com.
+geecsrztk.z02b7x4y.
+234.42.116.174.in-addr.arpa.
+apix.iminent.com.
+www.peope.mx.
+232.68.220.189.in-addr.arpa.
+giuj.com.
+g.ceipmsn.com.
+photos-d.ak.fbcdn.net.
+.
+apps.facebook.com.
+teredo.ipv6.microsoft.com.
+mail.crazycarrot.com.au.
+api.twitter.com.
+142.49.128.190.in-addr.arpa.
+mx18.comquatro.com.br.
+mail.primate.net.
+configuration.apple.com.
+css.wlxrs.com.
+a.root-servers.net.
+159.213.141.201.in-addr.arpa.
+sysna.com.
+www.guarras.com.
+a.root-servers.net.
+fbcdn-profile-a.akamaihd.net.
+_363_27_6.
+205.57.4.46.in-addr.arpa.
+i1.ytimg.com.
+a3.sphotos.ak.fbcdn.net.
+235.187.83.200.in-addr.arpa.
+image.usedvictoria.com.
+hayfork.net.
+103.111.238.41.in-addr.arpa.
+facebook.com.
+pt-br.www.mozilla.com.
+40.162.255.173.in-addr.arpa.
+platform.ak.fbcdn.net.
+api.twitter.com.
+67.170.57.186.in-addr.arpa.
+pixel.facebook.com.
+samplast.ru.
+www.espaces.ca.
+s.youtube.com.
+enter.racksandblacks.com.
+mail.blomsma.net.
+d3.c2.b7.a1.top.mail.ru.
+sp.cwfservice.net.
+86.191.34.186.in-addr.arpa.
+clients1.google.com.mx.
+52.174.203.190.in-addr.arpa.
+peru.paginasamarillas.com.
+language-reader.softonic.com.
+zknwrqbcrm.ru.
+theshadowconspiracy.tumblr.com.
+6.103.224.190.in-addr.arpa.
+cust2916-2.in.mailcontrol.com.
+www.nationaloutdoors.net.
+api.twitter.com.
+todoovni.bligoo.cl.
+by120fd.bay120.hotmail.msn.com.
+goo.gl.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+text.kcl.ac.uk.
+m.addthisedge.com.
+tsm04.eset.com.
+naifandtastic.blogspot.com.
+41.240.87.212.in-addr.arpa.
+23.217.78.190.in-addr.arpa.
+110.27.239.77.in-addr.arpa.
+mail2.besttransformer.com.
+at160.com.
+number-32.magazine-fashion.net.
+178.250.121.109.in-addr.arpa.
+rssgov.windows.microsoft.com.
+142.227.198.190.in-addr.arpa.
+_192_63_1.
+www.izucar.info.
+media.trafficjunky.net.
+longnosecelebs.hoxpedaje.com.
+davisequip.com.s5a1.psmtp.com.
+creative.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+netmag.com.mx.
+a.root-servers.net.
+www.taringa.net.
+89.163.95.200.in-addr.arpa.
+seter.com.mx.
+60.79.151.186.in-addr.arpa.
+m.addthisedge.com.
+tradewindtours.com.
+53.221.170.90.in-addr.arpa.
+www.fondationtf1.fr.
+content.yieldmanager.edgesuite.net.
+www.techawards.org.
+www.google.com.
+adm.fwmrm.net.
+9.9.192.190.in-addr.arpa.
+a.root-servers.net.
+a1015.g.akamai.net.0.1.cn.akamaitech.net.
+www.mercadolibre.com.ar.
+7.206.1.181.in-addr.arpa.
+dns.msftncsi.com.
+88.27.219.85.in-addr.arpa.
+ns2.mokr.ru.
+mx.youtube.com.
+biztv.ru.
+ad.yieldmanager.com.
+60.175.15.201.in-addr.arpa.
+bit.ly.
+resolver5.wguard.ctmail.com.
+pjallseasons.blogspot.com.
+63.32.133.186.in-addr.arpa.
+_618_22_9.
+dnl-18.geo.kaspersky.com.
+apis.google.com.
+219.73.168.192.in-addr.arpa.
+pixel.facebook.com.
+ar-ar.facebook.com.
+sc.cc.wy.us.
+fbcdn-photos-a.akamaihd.net.
+a.root-servers.net.
+orajydoh4.08ri.
+liveupdate.symantecliveupdate.com.
+244.255.146.216.in-addr.arpa.
+img3.annuncicdn.it.
+www.geotaku-no-fansub.com.
+www.devenir-rentier.fr.
+www.zehnders.com.
+wnnfans.com.
+mail.renta-auto.ru.
+64.173.231.190.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.gaypaycheck.com.
+a3.sphotos.ak.fbcdn.net.
+.
+www.ofertas-ocasion-mercedes.com.
+google.com.
+36.179.70.217.in-addr.arpa.
+s.youtube.com.
+ssl.gstatic.com.
+i3.ytimg.com.
+clansunset.files.wordpress.com.
+a1820.phobos.apple.com.
+a.root-servers.net.
+api.nanigans.com.
+metrics.news.co.uk.
+www.powerslaverecords.com.
+smtp.dvinaland.ru.
+cloud.rovio.com.
+www.gamecdkey.org.
+irizrb:dw.e95p5k2h.
+creative.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+segurosencasa.com.
+a.root-servers.net.
+www.interactivestuff.org.
+122.166.130.189.in-addr.arpa.
+217.26.121.186.in-addr.arpa.
+a.root-servers.net.
+7.17.135.187.in-addr.arpa.
+api.facebook.com.
+www.facebook.com.
+174.84.176.187.in-addr.arpa.
+i1237.photobucket.com.
+nyhbpr.com.
+hostgrantor.org.
+a.root-servers.net.
+magnacarta.surrey.sch.uk.
+45.193.42.62.in-addr.arpa.
+peoplepc.com.
+20.16.43.186.in-addr.arpa.
+a.root-servers.net.
+www.gamer.ne.jp.
+a.root-servers.net.
+a.root-servers.net.
+yahoo.download.vmn.net.
+www.google.com.
+rs501tl5.rapidshare.com.
+relay.voice.edge.messenger.live.com.
+encuadernacion.realbiblioteca.es.
+210.65.122.84.in-addr.arpa.
+byfiles.storage.msn.com.
+61.42.201.190.in-addr.arpa.
+api-read.facebook.com.
+mx.ptmail.sapo.pt.
+dns.msftncsi.com.
+a8.sphotos.ak.fbcdn.net.
+www.wdc.com.
+236.194.78.186.in-addr.arpa.
+229.0.55.157.in-addr.arpa.
+pagead2.googlesyndication.com.
+pagead2.googlesyndication.com.
+eastoregonian.com.
+www.mangolanguages.com.
+mail.cognisurf.com.
+www.gstatic.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+download346.avast.com.
+192.12.68.189.in-addr.arpa.
+e1463.b.akamaiedge.net.
+231.36.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+230.20.20.67.in-addr.arpa.
+i29.servimg.com.
+vingan.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+www.google-analytics.com.
+a6.sphotos.ak.fbcdn.net.
+12.229.127.201.in-addr.arpa.
+48.196.243.201.in-addr.arpa.
+smtp.telelogix.net.
+twitter.com.
+www.facebook.com.
+webcache.googleusercontent.com.
+photos-c.ak.fbcdn.net.
+www.interpanama.com.
+mx4.etrn.canit4.3d.net.uk.
+developers.facebook.com.
+endling.deviantart.com.
+promo.msgpluslive.net.
+a.root-servers.net.
+www.directbigboobsreloaded.net.
+sites.google.com.
+www.facebook.com.
+93.68.73.186.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+os.ning.com.
+a.root-servers.net.
+bigdealutah.kostizi.com.
+support.google.com.
+notify19.dropbox.com.
+s-static.ak.fbcdn.net.
+cinci.rr.com.
+plusmall.golfsky.com.
+crl.microsoft.com.
+www.mixx.com.
+ovv7ckhrk.s14s9c3m.
+22-courier.push.apple.com.
+ksn2-12.kaspersky-labs.com.
+activesync.hot.glbdns.microsoft.com.
+pixel.facebook.com.
+sp.cwfservice.net.
+sailinghawks.com.
+a.root-servers.net.
+mail.insomnia-sales.com.
+76.252.160.201.in-addr.arpa.
+a.root-servers.net.
+pixel.quantserve.com.
+feralon.blogspot.es.
+ana-marin.blogspot.com.
+a1505.l.akamai.net.
+estaticosak1.tuenti.com.
+a.root-servers.net.
+www.ratteb.com.
+colegiala-informe-11-parte-del-pudin-esta-en-estudio.planetadepeliculas.com.
+204.236.7.95.in-addr.arpa.
+a.sigalert.com.
+ar2006.emcdda.europa.eu.
+www.mexicosmagazine.com.
+s-static.ak.fbcdn.net.
+aol.com.
+www.bookmarksbookshop.co.uk.
+marlerclark.com.s9b2.psmtp.com.
+nsiadvisors.com.
+a5.sphotos.ak.fbcdn.net.
+97.172.31.190.in-addr.arpa.
+static.ak.fbcdn.net.
+neude.tumblr.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.rickross.com.
+165.178.133.189.in-addr.arpa.
+a1725.l.akamai.net.
+gumps.com.s7a2.psmtp.com.
+gdata.youtube.com.
+ping.ginoplayer.net.
+a6.sphotos.ak.fbcdn.net.
+dss1.siteadvisor.com.
+mx.youtube.com.
+a.root-servers.net.
+forum.sky.it.
+officesm.ru.
+h.live.com.
+www.waraqat.net.
+megaconsolas.foros.bz.
+www.whitehouse.gov.
+www.amountainofcrushedice.com.
+a.root-servers.net.
+img3.catalog.video.msn.com.
+rovio1.appads.com.\224[\173\001.
+.
+a.root-servers.net.
+keithclarkephotography.com.
+64.20.54.1.in-addr.arpa.
+tmss.trendmicro.com.
+dc461.4shared.com.
+vp.sip.messenger.msn.com.
+apis.google.com.
+cableone.net.
+bolyai.cs.elte.hu.
+_230_86_4.
+passwaynet.com.
+www.fiveguys.net.
+qwar.spb.ru.
+138.188.224.125.in-addr.arpa.
+profile.ak.fbcdn.net.
+176.32.58.186.in-addr.arpa.
+api4s.dayup.org.
+brayleino.co.uk.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+210.213.38.190.in-addr.arpa.
+um12.eset.com.
+126.41.155.189.in-addr.arpa.
+twitter.com.
+www.vxsbill.com.
+pixel.facebook.com.
+recookie-767972906.us-east-1.elb.amazonaws.com.
+developers.facebook.com.
+www.androidtabletpcsupport.com.
+www.bicimotor.com.
+i.yimg.jp.
+www.earthakittfanclub.com.
+www.goutremoval.com.
+x26.xanga.com.
+hortigas.org.
+mscrl.microsoft.com.
+checkip.dyndns.org.
+external.ak.fbcdn.net.
+svrintl-g3-crl.verisign.com.
+80.85.38.68.in-addr.arpa.
+cody.wtp.net.
+p03-contacts.icloud.com.
+ocsp.verisign.com.
+108.31.193.108.in-addr.arpa.
+www.superdelivery.com.ar.
+cuauhtemocsuarez.tumblr.com.
+mail.agency-legion.ru.
+help.weheartit.com.
+fbcdn-photos-a.akamaihd.net.
+external.ak.fbcdn.net.
+cdn.api.twitter.com.
+loading5.widdit.com.
+psgw.t-mobilesgws.com.
+www.shemaleladys.com.
+c.bing.com.
+ssl.gstatic.com.
+_671_21_1.
+fs438.uploading.com.
+voipc.sip.yahoo.com.
+urs.microsoft.com.
+photos-a.ak.fbcdn.net.
+www.irememberjfk.com.
+www.addthis.com.
+15.149.220.66.in-addr.arpa.
+yui.yahooapis.com.
+www.afroonblondes.com.
+shopperinc.com.
+146.4.75.200.in-addr.arpa.
+packman.links2linux.org.
+v7.cache2.c.youtube.com.
+a.root-servers.net.
+9.248.113.71.in-addr.arpa.
+inscapllc.com.
+www.keep-project.eu.
+v3.nonxt2.c.pack.google.com.
+0-56.channel.facebook.com.
+webcache.googleusercontent.com.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.videosmaduras.org.
+cart.taobao.com.
+insider.msg.yahoo.com.
+javadl-esd.sun.com.
+vf.cloud.avg.com.
+a.root-servers.net.
+gateway.deiser.es.
+mail2.keybuild.com.
+bryansk.ru.
+www.modernwallcompany.com.
+comprarcreatina.net.
+public.liss.slidesharecdn.com.edgesuite.net.
+201.212.44.200.in-addr.arpa.
+noble-empire.com.
+ads.yimg.com.
+eshop.infobel.com.
+photos-g.ak.fbcdn.net.
+rekam-auto.ru.
+enfrentalaverdad.activo.mx.
+tc.v23.cache4.c.youtube.com.
+www.studiocalico.com.
+bit.ly.
+dns.msftncsi.com.
+a954.phobos.apple.com.
+news.bbc.co.uk.
+www.mileycyrusgames.net.
+sapiens.ya.com.
+orcart.facebook.com.
+39.62.215.189.in-addr.arpa.
+listserv.repp.org.
+mail.google.com.
+a7.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+dns.msftncsi.com.
+www.walletshop.com.au.
+a.root-servers.net.
+ad.bannerconnect.net.
+cn1.redswoosh.akadns.net.
+8.163.10.186.in-addr.arpa.
+tick.stdtime.gov.tw.
+miraflores.gob.pe.
+129.168.230.190.in-addr.arpa.
+www.servoprax.com.
+a8.sphotos.ak.fbcdn.net.
+maybones.polyvore.com.
+www.800mainstreet.com.
+www.p1q.eu.
+rutafreak.blogspot.com.
+www.aerobic-online.com.
+dc350.4shared-china.com.
+168.169.28.190.in-addr.arpa.
+tobolsk.info.
+apis.google.com.
+ipswebfilter.molindia.com.
+7.213.43.200.in-addr.arpa.
+api.facebook.com.
+vp.sip.messenger.msn.com.
+www.gtliens.fr.
+www.ign.com.
+73.114.168.192.in-addr.arpa.
+www.google.com.
+243.114.106.177.in-addr.arpa.
+bt1.divalium.com.
+feeds.bbci.co.uk.
+138.34.60.186.in-addr.arpa.
+autocadprojects.blogspot.com.
+70.139.163.90.in-addr.arpa.
+baptisthealh.net.
+mail.kudlow.com.
+photos-g.ak.fbcdn.net.
+www.trpk.net.
+ad.yieldmanager.com.
+www.nylon-xxx.com.
+it-demo.com.ua.
+valiumchat.chatango.com.
+www.bookfinder.com.
+s-external.ak.fbcdn.net.
+www.twinkspicsorgasm.com.
+denis.stalker.h3q.com.
+tracker.ktxp.com.
+www.svpg.com.
+a.root-servers.net.
+tc.v6.cache8.c.youtube.com.
+126.73.88.200.in-addr.arpa.
+s2.youtube.com.
+madonna.connexion.free.fr.
+email.houcon.com.
+fei9988.3322.org.
+_547_98_4.
+fs433.uploading.com.
+www.cuartodecomunicaciones.com.
+f0.img.v4.skyrock.net.
+127.0.0.1.
+www.internethealthlibrary.com.
+www.thomsonscientific.com.
+www.esperanzanews.com.ar.
+m.hotmail.com.
+router.bitcomet.net.
+um18.eset.com.
+a.root-servers.net.
+234.16.39.190.in-addr.arpa.
+mail.highklass.ru.
+.
+sp.cwfservice.net.
+o-o.preferred.lga15s20.v10.lscache1.c.youtube.com.
+_535_07_7.
+a8.sphotos.ak.fbcdn.net.
+vicclap.hu.
+mstu.redu.ru.
+s2.youtube.com.
+www.4mybaby.ch.
+ogil.files.wordpress.com.
+tw.burberry.com.
+147.8.94.189.in-addr.arpa.
+mailer.cimesa.net.
+www.radanpro.com.
+222.200.233.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+google.com.
+teredo.ipv6.microsoft.com.
+www.jorudan.co.jp.
+inferno.demonoid.com.
+static.ak.facebook.com.
+static.ak.facebook.com.
+datawingsff.monbe.be.
+169.157.253.201.in-addr.arpa.
+a921.phobos.apple.com.
+apps.facebook.com.
+a.root-servers.net.
+41.32.216.190.in-addr.arpa.
+l.sscdn.co.
+a.root-servers.net.
+api-read.facebook.com.
+a.root-servers.net.
+three-part-harmony.com.
+mail.saratov.su.
+55.180.47.31.in-addr.arpa.
+www.bddlgroup.com.
+itunes.com.
+www.googleadservices.com.
+www.dotcr.ost.dot.gov.
+plus.google.com.
+im-from-wasteland.tumblr.com.
+www.mylovedtranny.com.
+www.msftncsi.com.
+ar.babel.com.
+adc.bmjjournals.com.
+www.lucialapiedradesnuda.com.
+www.manhelper.com.
+x5ah2rbgj.95wi.
+xrpvt59gh.o63y7w1b.
+katzenlaw.net.
+mail.bushtracksafrica.com.
+img7.imageshack.us.
+ksn1-12-part2.kaspersky-labs.com.
+156.33.66.187.in-addr.arpa.
+commons.wikimedia.org.
+sp.cwfservice.net.
+heartbeat.belkin.com.
+a.root-servers.net.
+g.microsoft.com.
+cableone.net.mail5.psmtp.com.
+images.intl.match.com.
+picnic.com.
+196.91.52.94.in-addr.arpa.
+mx.tcrcd.net.
+www.textsrv.com.
+www.simplysupersoft.com.
+9-1.qlty.finarea.ch.
+mail.aeronauticalelectric.com.
+tolteca-guillermomarin.blogspot.com.
+ajax.cloudflare.com.
+db2.stb00.s-msn.com.
+www.facebook.com.
+api.geo.kontagent.net.
+salonesoterico.com.
+a4.sphotos.ak.fbcdn.net.
+check.sanasecurity.com.
+0-250.channel.facebook.com.
+9-courier.push.apple.com.
+zh-cn.facebook.com.
+google.com.
+pravbrat.ru.
+www.bodydragon.com.
+0-ig-w.channel.facebook.com.
+ads.traffichaus.com.
+platform.ak.fbcdn.net.
+www.bookdepository.com.
+chunsreef.globalhost.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+t5.tagstat.com.
+www.dvbviewer.com.
+a1920.g.akamai.net.
+mail.sofaselections.com.
+managedindustrial.com.
+www.monsterdivx.com.
+www.adobe.com.
+6to4.ipv6.microsoft.com.
+accounts.google.com.
+charter.net.
+174.16.110.68.in-addr.arpa.
+comicsinvasion.blogspot.com.
+rospres.com.
+mail.pavcol.com.
+s.youtube.com.
+c.wb.mapbox.com.
+a5.sphotos.ak.fbcdn.net.
+forsuccess.ru.
+triaid.rr.com.
+arlenegoldbard.com.
+bw33xoel:.z73d3n9o.
+s.youtube.com.
+google.com.
+29.27.176.189.in-addr.arpa.
+www.forosdelweb.com.
+10.1.168.192.in-addr.arpa.
+155.213.69.190.in-addr.arpa.
+www.youtube.com.
+map.secondlife.com.s3.amazonaws.com.
+www.indeed.com.
+russadventures.ru.
+185.78.244.189.in-addr.arpa.
+toolbarqueries.clients.google.com.
+crl.microsoft.com.
+pixel.facebook.com.
+hydrogen.yatho.de.
+youtu.be.
+a.root-servers.net.
+lb._dns-sd._udp.belkin.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.4girlsfingerpaint.com.
+uwpho.to.
+29.200.230.188.in-addr.arpa.
+cdn1.ads.brazzers.com.
+thumbnails.infolinks.com.
+crossword-forge.uptodown.com.
+daytona.backpage.com.
+a.root-servers.net.
+192.248.167.184.in-addr.arpa.
+www.softonic.com.
+rdmail.com.
+jjegonzalezf.files.wordpress.com.
+mundotdc.bancomer.com.mx.
+a.root-servers.net.
+counterb.statcounter.com.
+4benchmark.com.
+d2o307dm5mqftz.cloudfront.net.
+180.144.130.201.in-addr.arpa.
+webex.com.rbl2.mcafee.com.
+deliriosdemuekitacat.blogspot.com.
+www.equipo63.com.
+_530_88_0.
+www8.incredimail.com.
+xxlcc.com.
+exch2k7.npes.org.
+download.windowsupdate.com.
+creative.ak.fbcdn.net.
+ib.adnxs.com.
+23.112.144.79.in-addr.arpa.
+yoteoriento.blogspot.com.
+bcisouthwest.com.
+www.mumstuff.co.uk.
+westsoundelectric.com.
+127.0.0.1.
+external.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+22.53.218.190.in-addr.arpa.
+rmail1.aeroplan.spb.ru.
+fr.webrep.avast.com.
+static.ak.connect.facebook.com.
+groups.google.as.
+82.76.173.218.in-addr.arpa.
+rewe-brinkmann.de.
+iphonedeveloperhelp.info.
+www.listengo.com.
+b.imwx.com.
+mx.ezfloorplan.com.
+mail.medinformatix.com.
+safebrowsing.clients.google.com.
+189.39.222.186.in-addr.arpa.
+mailgw4.gnresound.com.
+flash.y9.vc.
+www.trouvetamosquee.fr.
+videos.publimetro.cl.
+a.root-servers.net.
+pagead.l.doubleclick.net.
+virtualwave.com.
+223.16.92.201.in-addr.arpa.
+globalite.com.br.
+104.0.84.186.in-addr.arpa.
+www.lineahome.com.
+_624_21_2.
+m.facebook.com.
+inglife.ru.
+marisol-espurnetes.blogspot.com.
+mtalk.google.com.
+billitall.com.
+ssl.gstatic.com.
+viniloseroticos.blogspot.com.
+fisica.net.
+forum.kismac-ng.org.
+www.hispanicfund.org.
+60.100.8.99.in-addr.arpa.
+100500.tv.
+feeds.bbci.co.uk.
+114.18.152.189.in-addr.arpa.
+cuda1.tcworks.net.
+27.0.1.10.in-addr.arpa.
+qnr6pa2:l.81xy.
+id.google.com.mx.
+shared.live.com.
+a.root-servers.net.
+clients1.google.com.
+a4.sphotos.ak.fbcdn.net.
+www.seccionamarilla.com.mx.
+cs13243.vkontakte.ru.
+f.facemoods.com.
+159.158.156.175.in-addr.arpa.
+ajax.googleapis.com.
+11.1.168.192.in-addr.arpa.
+44.215.85.209.rbl7.mailshell.net.
+o-o.preferred.lax04s12.v10.lscache5.c.youtube.com.
+a.root-servers.net.
+65.66.6.186.in-addr.arpa.
+108.119.13.187.in-addr.arpa.
+86.101.188.189.in-addr.arpa.
+fr.wunderman.com.s200a1.psmtp.com.
+lh4.googleusercontent.com.
+gateway.messenger.hotmail.com.
+profile.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+167.196.81.201.in-addr.arpa.
+31.240.49.186.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.google.com.
+208.30.8.200.in-addr.arpa.
+certifiedair.net.s5a2.psmtp.com.
+www.vanderlande.com.
+98.115.215.189.in-addr.arpa.
+spotcrime.com.
+www.elsotano.com.mx.
+javadl-esd.sun.com.
+celebrity-weight-loss.info.
+m.facebook.com.
+www.amazon.com.
+aenianos.wordpress.com.
+ssl.google-analytics.com.
+196.252.223.201.in-addr.arpa.
+126.17.50.190.in-addr.arpa.
+xatihujigonako.com.
+www.cuentosparacolorear.com.
+www.imdb.com.
+altacosta.ru.
+google.com.
+fr-fr.facebook.com.
+www.fighterplanegames.net.
+www.naviopirata.com.
+ws-cloud-msgplus.linkury.com.
+jp.yupis.org.
+pixel.facebook.com.
+blog.soluciones3f.com.ar.
+vcs2.msg.yahoo.com.
+connect.facebook.net.
+www.script-tutorials.com.
+static.ak.fbcdn.net.
+news.google.com.mx.
+settings.toolbar.conduit-services.com.
+251.121.68.189.in-addr.arpa.
+noir-gothly.blogspot.com.
+cox.net.
+www.vbsoporte.com.
+liftlab.com.
+scimail.silvercloud.com.
+181.159.253.190.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+img820.imageshack.us.
+www.kenquestmedical.com.
+www.telegraph.co.uk.
+238.45.54.208.in-addr.arpa.
+www.google.com.
+ib.adnxs.com.
+c.prodigy.msn.com.
+www.ece.byu.edu.
+a4.da1.akamai.net.
+www.sandy-xxx.com.
+a.root-servers.net.
+laborlawyers.com.s8b2.psmtp.com.
+www.google-analytics.com.
+www.paginasamarillas.com.ar.
+www4.pictures.gi.zimbio.com.
+16.147.220.66.in-addr.arpa.
+docs.google.com.
+apps.facebook.com.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+mail.newroads.org.
+lujazos.com.
+a2.sphotos.ak.fbcdn.net.
+webres1.pand.ctmail.com.
+e.yieldmanager.net.
+prev.explabs.net.
+ad.yieldmanager.com.
+samor.ru.
+feeds.bbci.co.uk.
+cableone.net.mail7.psmtp.com.
+adserving.cpxinteractive.com.
+mail.sembolferforje.com.
+ksn2-12.kaspersky-labs.com.
+ns.ett.ua.
+a2.twimg.com.
+photos-e.ak.fbcdn.net.
+abtaudit.ru.
+codeblocks.org.
+193.142.215.173.in-addr.arpa.
+youtu.be.
+mediacdn.disqus.com.
+fbbmusclegirls.blogspot.com.
+gfx1.hotmail.com.
+dynda.net.
+mail2.deis.unical.it.
+surgient.com.
+34.98.250.189.in-addr.arpa.
+msc.wlxrs.com.
+clients1.google.com.
+fishermotors.com.s9a1.psmtp.com.
+www.facebook.com.
+centromedicomty.com.
+grandcanyon.ru.
+44.82.77.219.in-addr.arpa.
+external.ak.fbcdn.net.
+sharpusa.com.
+www.gapa.de.
+a1.sphotos.ak.fbcdn.net.
+www.youtube.com.
+ajax.googleapis.com.
+www.facebook.com.
+rwpike.deviantart.com.
+orcart.facebook.com.
+bernatcomas.com.
+translate.googleapis.com.
+tncu.org.
+_429_57_2.
+a7.sphotos.ak.fbcdn.net.
+c-0.19-a30f1081.60081.1518.19d2.3ea0.210.0.9z5w4fe9kicv8b19mbh6svh7ui.avqs.mcafee.com.
+a.root-servers.net.
+loquelacomidasellevo.blogspot.com.
+sitemap.gamefaqs.com.
+b.scorecardresearch.com.
+matcher-rbc.bidder7.mookie1.com.
+51.56.112.186.in-addr.arpa.
+156.219.192.173.in-addr.arpa.
+icons.cubics.com.
+213.44.0.10.in-addr.arpa.
+fugazyintl.com.
+welcometobaltimorehon.com.
+www.institutoasegurador.com.ar.
+www.htmlgraphic.com.
+191.163.245.189.in-addr.arpa.
+231.120.69.190.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.kisscleveland.com.
+wewecity.s3.amazonaws.com.
+es.disney.wikia.com.
+1.bp.blogspot.com.
+22.1.111.186.in-addr.arpa.
+96.250.115.186.in-addr.arpa.
+creative.ak.fbcdn.net.
+brightonpainting.com.
+i1.ytimg.com.
+olsten.com.
+229.21.192.187.in-addr.arpa.
+24.145.228.84.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+mobileblogmoney.com.
+www.allpsychologyschools.com.
+mail.gadaletoramsby.com.
+62.108.173.118.in-addr.arpa.
+201.127.172.67.in-addr.arpa.
+ijfdiiuvirghdlkqrdapq.cc.
+www.tebca.com.
+www.avkube.ru.
+s2.youtube.com.
+jywuua.com.
+207.196.51.190.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+18.70.133.189.in-addr.arpa.
+fr.onehourtranslation.com.
+photos-a.ak.fbcdn.net.
+static.ak.fbcdn.net.
+media.adxpansion.com.
+msgr.updates.yahoo.com.
+mail.bristol.mass.edu.
+safebrowsing-cache.google.com.
+a1768.g.akamai.net.
+psgw.t-mobilesgws.com.
+wtabfgempt.info.
+telecom.cz.
+a.root-servers.net.
+img216.imageshack.us.
+ad.ifwcash.com.
+www.courts.state.ny.us.
+time.nist.gov.
+delanteroizquierdo.blogspot.com.
+gfjdyrfcb.net.
+www.facebook.com.
+dnl-02.geo.kaspersky.com.
+.
+www.bylatino.mx.
+loading.retry.widdit.com.
+chat009.vs.com.
+forums.opalauctions.com.
+twitter.com.
+www.olx.com.do.
+m.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+mail.btk.ru.
+usf.com.
+nwcoughlin.com.
+m.facebook.com.
+alt2.gmail-smtp-in.l.google.com.
+click.sandglass.tv.
+61.10.89.183.in-addr.arpa.
+mail.owzw.com.
+131.235.88.200.in-addr.arpa.
+a.root-servers.net.
+phpfusion.org.
+8.0.168.192.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+www.cljhealth.com.
+www.facebook.com.
+photos-d.ak.fbcdn.net.
+mail.satlinker.com.
+fi.wikipedia.org.
+www.facebook.com.
+apis.google.com.
+images.apple.com.
+155.138.189.189.in-addr.arpa.
+videosjustinbieber.com.ar.
+www.20minutos.es.
+lykwrwb65.y20y7r0v.
+i2.ytimg.com.
+ejabat.google.com.
+centroidcnc.com.
+www.wise.edu.jo.
+hyperiontechnologies.com.
+rtlnow.de.
+30-courier.push.apple.com.
+weather.bigmir.net.
+photos-e.ak.fbcdn.net.
+channeltechno.com.
+www.unbeatablesale.com.
+adsc.com.
+144.148.85.209.in-addr.arpa.
+asap-utilities.en.softonic.com.
+www.nursery.com.au.
+skateboardmsm.mpora.de.
+19.208.247.92.in-addr.arpa.
+199.97.75.65.in-addr.arpa.
+gmx.at.
+a.root-servers.net.
+87.210.2.201.in-addr.arpa.
+ads.adxpansion.com.
+itu.int.s201a2.psmtp.com.
+openx-adserver-balancer-2134199362.us-west-1.elb.amazonaws.com.
+promarkit.com.
+dikomp.saratov.ru.
+www.facebook.com.
+www.ftp8.co.uk.
+ugij8vgz3.01ui.
+googleads.g.doubleclick.net.
+spider-wl023.proxy.aol.com.
+jjlennon.com.
+www.facebook.com.
+a1132.da1.akamai.net.
+a.root-servers.net.
+42.112.55.187.in-addr.arpa.
+183.37.55.92.in-addr.arpa.
+q2sg6c68:.70si.
+clients4.google.com.
+www.twifansadnet.com.
+tmss.trendmicro.com.
+thirdwavepartners.net.
+blogs.tudiscovery.com.
+www.perfectdiva.ro.
+182.55.198.187.in-addr.arpa.
+112.230.29.189.in-addr.arpa.
+gmt.nl.
+www.google.com.
+153.149.233.189.in-addr.arpa.
+abcfamily.go.com.
+62.178.130.186.in-addr.arpa.
+213.129.204.186.in-addr.arpa.
+14.136.206.190.in-addr.arpa.
+cbsystem.fr.
+121.24.93.97.in-addr.arpa.
+247.44.79.94.in-addr.arpa.
+twitter.com.
+www.vuelosbaratos.com.mx.
+a8.sphotos.ak.fbcdn.net.
+www.iwanttostopsnoring.com.
+straight.com.
+photos-f.ak.fbcdn.net.
+any-latamrc.a01.yahoodns.net.
+i.w55c.net.
+gitrust.com.
+s7.addthis.com.
+a1108.da1.akamai.net.
+ic.tynt.com.
+5.194.242.201.in-addr.arpa.
+6.125.158.187.in-addr.arpa.
+www.google-analytics.com.
+www.furl.net.
+a4.sphotos.ak.fbcdn.net.
+bs.serving-sys.com.
+195.189.255.201.in-addr.arpa.
+www.multicam.com.
+196.98.193.173.in-addr.arpa.
+71.193.39.187.in-addr.arpa.
+a.root-servers.net.
+55.0.46.190.in-addr.arpa.
+s7.addthis.com.
+www.facebook.com.
+201.139.34.177.in-addr.arpa.
+tracker.openbittorrent.com.
+www.bkrtx.com.
+149.148.10.187.in-addr.arpa.
+apps.facebook.com.
+att.net.
+docs.google.com.
+db._dns-sd._udp.0.55.211.10.in-addr.arpa.
+205.217.19.190.in-addr.arpa.
+_789_63_3.
+34.35.32.186.in-addr.arpa.
+rvmconstrucion.com.
+login.netgame.com.
+firstclassbuilders.com.
+www.scatmodelpower.com.
+wyattfirm.com.mail6.psmtp.com.
+thetwistfamily.blogspot.com.
+16.54.119.200.in-addr.arpa.
+img9.ask.fm.
+gossipgirls.episodeseason.com.
+221.121.224.190.in-addr.arpa.
+ds.serving-sys.com.
+www.bathmate.ca.
+profile.ak.fbcdn.net.
+www.santuariock.com.ar.
+ib.adnxs.com.
+barracuda.tulsarealtors.com.
+bigond.com.
+cm.g.doubleclick.net.
+fbcdn-profile-a.akamaihd.net.
+clock.fmt.he.net.
+rad.msn.com.
+fbcdn-profile-a.akamaihd.net.
+www.gaportal.org.
+padgk93gf.q08g1d7w.
+197.83.97.93.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+228.50.59.186.in-addr.arpa.
+www.hungryhappenings.com.
+0.2.0.e.1.7.4.e.8.2.f.6.b.8.c.1.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+partner.googleadservices.com.
+pixel.quantserve.com.
+a.root-servers.net.
+adm-skhodnya.ru.
+external.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.adobe.com.
+t2.gstatic.com.
+www.abc.com.py.
+254.119.236.92.in-addr.arpa.
+204.87.56.187.in-addr.arpa.
+gisy.com.inbound25.mxlogic.netet.
+bgs.bethsoft.com.
+star.facebook.com.
+165.72.232.189.in-addr.arpa.
+static.ak.fbcdn.net.
+homepage.mac.com.
+www.larips.com.
+equityrisk.com.inbound15.mxlogicmx.net.
+pricelist.skype.com.
+www.fallinginreversestore.com.
+www.orcius.com.
+images.intellitxt.com.
+cs301713.vk.com.
+adscdn.avalonsunsplash.com.
+api.twitter.com.
+pixel.facebook.com.
+static.sl.lumosity.com.
+_924_10_1.
+222.103.222.189.in-addr.arpa.
+api.twitter.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.google.com.
+a.root-servers.net.
+vcs1.msg.yahoo.com.
+a5.sphotos.ak.fbcdn.net.
+11.249.233.190.in-addr.arpa.
+220.188.7.88.in-addr.arpa.
+www.appsomniac.com.
+bs.serving-sys.com.
+b._dns-sd._udp.lan.
+webcache.googleusercontent.com.
+10.211.16.190.in-addr.arpa.
+desionlinemovies.blogspot.com.
+www.amor-yaoi.com.
+107.112.2.190.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+247.102.55.157.in-addr.arpa.
+www.vicor-china.com.
+196.217.230.190.in-addr.arpa.
+pixel.facebook.com.
+195.156.129.78.in-addr.arpa.
+_477_58_0.
+_767_13_7.
+www.gilligansisle.com.
+xabantech.files.wordpress.com.
+bfr.com.
+www.melindasweet.com.
+www.intel.com.
+gardnerfoxremodeling.files.wordpress.com.
+24.135.93.186.in-addr.arpa.
+ad.yieldmanager.com.
+www.bestbreakfast.ca.
+119.37.191.201.in-addr.arpa.
+search.vuze.com.
+2highstudios.com.
+www.cope.es.
+sn2files.storage.msn.com.
+73.237.171.201.in-addr.arpa.
+www.mylanguageexchange.com.
+www.miantojo.com.mx.
+0-undefined.facebook.com.
+www.loni.ucla.edu.
+entretenimiento.latam.msn.com.
+112.6.165.46.in-addr.arpa.
+www.facebook.com.
+a.root-servers.net.
+mail.satinbedding.com.
+83.135.28.190.in-addr.arpa.
+translate.google.com.mx.
+a2.da1.akamai.net.
+static.ak.fbcdn.net.
+ce.lijit.com.
+thompsonflanagan.com.
+couponbuddy.s3.amazonaws.com.
+56.128.212.24.in-addr.arpa.
+api.facebook.com.
+164.162.11.92.in-addr.arpa.
+8.121.210.201.in-addr.arpa.
+www.l.google.com.
+fxfeeds.mozilla.com.
+148.111.72.94.in-addr.arpa.
+zimmerli-wagner.ch.
+info.xvideos.com.
+126.132.149.186.in-addr.arpa.
+mt0.google.com.
+apps.facebook.com.
+www.fybeca.com.
+251.58.214.81.in-addr.arpa.
+a.root-servers.net.
+i1184.photobucket.com.
+crl.geotrust.com.
+csi.gstatic.com.
+a.root-servers.net.
+ed3q65m:n.l56p8c6w.
+jessicalk.com.
+117.122.183.180.in-addr.arpa.
+6.75.174.189.in-addr.arpa.
+fantasy.footbo.com.
+google.com.
+106.199.106.78.in-addr.arpa.
+206.163.30.186.in-addr.arpa.
+www.youtube.com.
+_812_59_5.
+xhcdn.com.
+earnings.ru.
+mail.tempinbox.com.
+www.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+mail.trak.spb.ru.
+hq.rt.ru.
+www.testiphone.com.
+connect.facebook.net.
+dmtjuo.com.
+www.youtube.com.
+yujh77.dg0.cn.
+www.google-analytics.com.
+teredo.ipv6.microsoft.com.
+www.mariopilato.com.
+66.141.56.186.in-addr.arpa.
+versioncheck.addons.mozilla.org.
+58.52.0.10.in-addr.arpa.
+176.210.164.189.in-addr.arpa.
+static.mp3bear.com.
+ahtm.wordpress.com.
+mail.
+www.mbvmusic.com.
+www.imdb.com.
+162.48.168.213.in-addr.arpa.
+www.facebook.com.
+i4.ytimg.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tvphotosandmore.blogspot.com.
+www.facebook.com.
+a.root-servers.net.
+172.201.134.46.in-addr.arpa.
+caribbeaneco-living.blogspot.com.
+upay-cdn1.playspan.com.
+mx.omegatech.ru.
+50.213.93.59.in-addr.arpa.
+212.69.207.223.in-addr.arpa.
+img02.s-msn.com.
+jayco.net.
+eresources.loc.gov.
+20minutos.feedsportal.com.
+mature.wantvids.com.
+mx.technicatech.com.
+www.fudefs.com.
+lh5.googleusercontent.com.
+mscrl.microsoft.com.
+vlmx00.secure.ne.jp.
+a.root-servers.net.
+pixel.quantserve.com.
+info.infotecstt.ru.
+a4.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.fotosmujeresbellas.com.
+ilovegelcandles.com.
+d1.openx.org.
+checklists.com.
+rikardoelterrible.blogspot.com.
+240.208.245.201.in-addr.arpa.
+218.127.180.71.in-addr.arpa.
+videojuegos.yo-anime.com.ar.
+www.lyrics-house.com.
+cloudsindo.files.wordpress.com.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.toplinestrategies.com.
+eradio.ust.edu.ph.
+74.71.58.186.in-addr.arpa.
+google.com.
+7.228.36.81.in-addr.arpa.
+www.ontheedgeblog.com.
+57.133.200.98.in-addr.arpa.
+goneoffdeep.com.
+translate.googleapis.com.
+sdweddinginsider.com.
+rterybrstutnrsbberve.com.
+et6.xhamster.com.
+clients1.google.com.
+api.facebook.com.
+universal-downloader.softonic.com.
+www.tirateunpalo.com.
+www.burladero.com.
+164.88.33.178.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+prod2.rest-notify.msg.yahoo.com.
+www.bettamx.com.
+www.facebook.com.
+mail.rosactive.com.
+visitfayettevillenc.com.inbound10.mxlogicmx.net.
+www.karlscalculus.org.
+static.ak.fbcdn.net.
+www.islamhouse.com.
+time.chttl.com.tw.
+photos-d.ak.fbcdn.net.
+serendipitouschat.com.
+a6.sphotos.ak.fbcdn.net.
+mail.coffmans.com.
+de-de.facebook.com.
+mail.prairietitle.com.
+www.artelectronico.com.
+req1.appads.com.
+shared.live.com.
+www.gstatic.com.
+www.420science.com.
+uomjkh.com.lan.
+www.psicolibroswaslala.com.
+external.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.zumiez.com.
+wpad.mshome.net.
+creative.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+pastebay.com.
+240.10.210.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+agency.com.
+instagr.am.
+i.t.net.ar.
+bubber.tv2.dk.tv2.dk.
+kimi-raikkonen.ru.
+21.16.14.95.in-addr.arpa.
+a.root-servers.net.
+167.101.215.201.in-addr.arpa.
+25.203.238.190.in-addr.arpa.
+extreme-sochi.ru.
+www.kazdey.co.uk.
+a.root-servers.net.
+copymasters.ru.
+s.ytimg.com.
+profile.ak.fbcdn.net.
+a1567.phobos.apple.com.
+3grenouilles.blogspot.com.
+dsient.com.
+mlocate.spotlife.net.
+191.6.58.186.in-addr.arpa.
+fotocvetov.ru.
+www.freepatternsonline.com.
+lnmmc3m7i.q55k9m3c.
+external.ak.fbcdn.net.
+asd.su.
+tools.google.com.
+safebrowsing.clients.google.com.
+smtp.kunstlaw.com.
+www.channel.com.
+profile.ak.fbcdn.net.
+blufiles.storage.msn.com.
+sitestart.net.
+www.publipaginas.net.
+teredo.ipv6.microsoft.com.
+pinpoint-transportation.com.
+mail.oplink.net.
+cust17503-2.in.mailcontrol.com.
+teamsters631.com.2.0001.arsmtp.com.
+curriclumconnection.net.
+d3k9hgzf8ej9hc.cloudfront.net.
+myfcc.frederick.edu.
+91.145.154.89.in-addr.arpa.
+www.youtube.com.
+www.tuslesbianas.es.
+www.newspaperdirect.com.
+34-courier.push.apple.com.
+static.ak.fbcdn.net.
+mx02.register.com.
+kachina-semi.com.
+blog.assparade.com.
+iluminandotierra.blogspot.com.
+model.susu.ru.
+plus.google.com.
+arrivo.br.
+en.wikipedia.org.af.mk.gd.
+poll-as06.kyte.tv.
+csi.gstatic.com.
+162.189.87.203.in-addr.arpa.
+67.97.172.81.in-addr.arpa.
+145.28.135.190.in-addr.arpa.
+cdn-de-c-142.heias.com.
+plan-espana.org.
+10.193.141.63.in-addr.arpa.
+store.digitalstores.co.uk.
+puertorico.countrytoolbox.com.
+www.rastreamento.org.
+a.analytics.yahoo.com.
+www.kingmantraining.com.
+api.twitter.com.
+dc454.4shared.com.
+dns.msftncsi.com.
+s.youtube.com.
+a1294.w20.akamai.net.
+www.auto-ping.com.
+mgw1.asb.dk.
+www.update.microsoft.com.
+media.adxpansion.com.
+a.root-servers.net.
+www.google-analytics.com.
+static.ak.facebook.com.
+mx.foratec.net.
+ar-ar.facebook.com.
+a2.sphotos.ak.fbcdn.net.
+v2.nonxt1.c.youtube.com.
+a0.twimg.com.
+chrometheme.tumblr.com.
+mail.google.com.
+b-0.19-2300b008.11001.1518.19d4.3ea1.410.0.zhfh1t3w3a82d254pc5c8gdqab.avqs.mcafee.com.
+www.google.com.
+download.xbox.com.
+developers.facebook.com.
+spymouse.cloudcell.com.
+photos-d.ak.fbcdn.net.
+bvdlawfirm.com.
+33.65.122.76.in-addr.arpa.
+potency.lbl.gov.
+crl.verisign.net.
+www.spilgames.com.
+11.28.31.190.in-addr.arpa.
+kbl8psban.f58i2b1r.
+hhwnclaw.com.
+gca.net.s8b2.psmtp.com.
+www.alutec.es.
+www.gimnasiolee.com.
+114.188.43.202.in-addr.arpa.
+www.anahionline.com.
+www.microsoft.com.
+m.facebook.com.
+210.195.146.189.in-addr.arpa.
+yubil.com.
+emob93.photobucket.com.
+i-cf508eaa.us-east-1b.service.amazonsilk.com.
+www.facebook.com.
+fallout3.nexusmods.com.
+javiastudillo.tumblr.com.
+service.lazywormapps.com.
+a5.sphotos.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+i4.ytimg.com.
+googleads.g.doubleclick.net.
+docs.google.com.
+a1404.w41.akamai.net.
+a.root-servers.net.
+m.facebook.com.
+184.35.1.190.in-addr.arpa.
+www.google.com.
+taylorfloyd.newsvine.com.
+slogin.oscar.aol.com.
+www.youtube.com.
+13.160.22.64.in-addr.arpa.
+apis.google.com.
+theolivebranch.net.
+ts1.mm.bing.net.
+unepaix.blogspot.com.
+fearlessfathers.wordpress.com.
+qolsze22k.77av.
+safebrowsing.clients.google.com.
+a.root-servers.net.
+www.slashattack.com.
+180.186.123.186.in-addr.arpa.
+gs-loc.apple.com.
+156.5.134.190.in-addr.arpa.
+123.44.105.124.in-addr.arpa.
+apps.facebook.com.
+akabodyart.co.uk.
+www.dubai-worldislands.com.
+pixel.quantserve.com.
+17.164.9.186.in-addr.arpa.
+229.152.68.201.in-addr.arpa.
+73.19.237.77.in-addr.arpa.
+mqnj.com.
+www.google.com.mx.
+agma.ru.
+www.portarrivals.com.
+csi.gstatic.com.
+zezao.com.
+mail.upyourcredits.com.
+34.108.50.189.in-addr.arpa.
+www.gtaseries.com.
+www.reglasdecalculo.com.
+www.ualrtrojans.com.
+www.kagi.fo.
+mx.kraft-s.net.
+boss.blogs.nytimes.com.
+a8.sphotos.ak.fbcdn.net.
+directorio.pixelmod.net.
+mail.mitchellsonline.com.
+b._dns-sd._udp.lan.
+personal.nl.avira-update.net.
+csi.gstatic.com.
+www.animal-sex-library.com.
+www.caracolinternacional.com.
+vintage-hardcore.mrvoyeur.net.
+214.228.206.167.in-addr.arpa.
+design2u.loc.ru.
+photos-d.ak.fbcdn.net.
+names2.businessserve.co.uk.
+162.157.136.175.in-addr.arpa.
+hc.pcw.dk.
+sbcglobal.prodigy.net.
+support.msi.com.
+192.79.167.59.in-addr.arpa.
+static.ak.fbcdn.net.
+www.formarse.com.ar.
+iaie.net.
+fbcdn-profile-a.akamaihd.net.
+121.206.104.70.in-addr.arpa.
+evsecure-ocsp.verisign.com.
+apps.facebook.com.
+dinero.univision.com.
+m.facebook.com.
+app2.neulion.com.
+petitpren.com.
+clients1.google.com.
+110.36.104.186.in-addr.arpa.
+www.id2tag.com.
+www.wtp101.com.
+mail.filasur.com.
+7.77.60.194.in-addr.arpa.
+www.capsis.cl.
+252.210.194.74.in-addr.arpa.
+clients1.google.com.
+87.175.15.201.in-addr.arpa.
+anakena.ru.
+isatap.domain.name.
+threadic.com.
+plus.l.google.com.
+www.sweetim.com.
+blogs.avid.com.
+www.angrybirds.com.
+136.13.16.68.in-addr.arpa.
+bh.contextweb.com.
+erinbuenger.blogspot.com.
+www.facebook.com.
+106.187.46.72.in-addr.arpa.
+www.benet.org.
+www.amateur-indian-girls.com.
+www.amazon.com.
+ntp.glb.nist.gov.
+newsrss.bbc.co.uk.
+cracked.hopto.org.
+opinion-tenerife.vlex.es.
+ad.yieldmanager.com.
+nfdqftxxtuetsn.net.
+www.bloggertipandtrick.net.
+21.8.98.177.in-addr.arpa.
+touchmusic.ru.
+a1.sphotos.ak.fbcdn.net.
+ar-ar.facebook.com.
+megasfiles.com.
+70.60.98.217.in-addr.arpa.
+www.seabreeltelon.es.
+pop.gmail.com.
+www.google.com.
+www.margaretwheatley.com.
+108.252.56.184.in-addr.arpa.
+www.facebook.com.
+produktinfo.conrad.com.
+images.google.com.
+a8.sphotos.ak.fbcdn.net.
+mpcstatic.com.
+www.rusegame.com.
+a.root-servers.net.
+www.entrepreneur.com.
+relay.voice.messenger.msn.com.
+th.nyklogistics.com.
+fonts.googleapis.com.
+aaffd0e4.linkbucks.com.
+d12079a.ess.barracudanetworks.com.
+guardianproject.info.
+www.facebook.com.
+www.elcoto.com.
+profile.ak.fbcdn.net.
+www.swglff.com.
+www.eaglepub.com.
+6.184.152.201.in-addr.arpa.
+a1007.w43.akamai.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+community.sba.gov.
+duplicadoweb.reniec.gob.pe.
+www.aglasshalffull.org.
+it21.ru.
+novascotialeo.org.
+toolbarqueries.google.com.
+woodbridge-va.patch.com.
+rt.liftdna.com.
+uchilishe.ru.
+www.myspace.com.
+darkc.foroactivo.com.
+ksn1-11-part2.kaspersky-labs.com.
+other.friv2.org.
+101.142.55.65.in-addr.arpa.
+ds.serving-sys.com.
+11.228.171.69.in-addr.arpa.
+sp.cwfservice.net.
+www.astroglide.com.
+a2.sphotos.ak.fbcdn.net.
+smtp.queensbury.com.
+image2.pubmatic.com.
+forums.visual-paradigm.com.
+vip.radioexitolatino.com.
+98.45.113.187.in-addr.arpa.
+114.178.15.84.in-addr.arpa.
+profile.ak.fbcdn.net.
+maccosmetics.tumblr.com.
+external.ak.fbcdn.net.
+www.vertigomagazine.co.uk.
+islacanela.costasur.com.
+ax.init.itunes.apple.com.
+expressandstar.com.
+124.29.251.190.in-addr.arpa.
+tracker.blazing.de.
+dns.msftncsi.com.
+mx25.valuehost.ru.
+232.186.13.201.in-addr.arpa.
+di104.shopping.com.
+img1.blogblog.com.
+122.213.137.186.in-addr.arpa.
+kitart.ru.
+s1-onenote.vo.msecnd.net.
+plus.google.com.
+www.google.com.
+sup.live.com.
+194.78.166.189.in-addr.arpa.
+partner.googleadservices.com.
+139.158.245.189.in-addr.arpa.
+www.ndctz.com.
+bmxplusmag.com.
+mshop.ionroad.com.
+www.facebook.com.
+yulon-nissan.com.tw.
+142.243.167.118.in-addr.arpa.
+marshsedge.net.
+www.gaerneshoes.com.
+pixel.facebook.com.
+108.28.28.186.in-addr.arpa.
+apps.facebook.com.
+www.fundaciontarpuy.org.ar.
+ec.atdmt.com.
+org.saferpage.com.
+181.51.168.192.in-addr.arpa.
+digitalforum.com.
+www.facebook.com.
+smtp.alleghenyfinancial.com.
+cataclysmguide.ru.
+33-courier.push.apple.com.
+dbskcafe.co.nr.
+65.74.236.190.in-addr.arpa.
+201.212.139.98.bl.spamcop.net.
+hcfsinc.com.
+this.id.
+243.123.58.216.in-addr.arpa.
+dns.msftncsi.com.
+freearticlesubmissionsdirectory.com.
+col.stb00.s-msn.com.
+buxsmb.com.
+www.bello.gov.co.
+mlogin.yahoo.com.
+clients1.google.com.
+ltgc.com.s5b1.psmtp.com.
+inspiration.alltop.com.
+futbol.univision.com.
+44.35.57.186.in-addr.arpa.
+i2.ytimg.com.
+graph.facebook.com.
+img100.xvideos.com.
+21.242.171.69.in-addr.arpa.
+renderscope.com.
+234.28.112.186.in-addr.arpa.
+3-courier.push.apple.com.
+creative.ak.fbcdn.net.
+property.
+a.root-servers.net.
+a.root-servers.net.
+cerillion.com.
+www.lemontroyal.qc.ca.
+1pehva4w8.88tk.
+4.113.50.85.in-addr.arpa.
+ns-912.amazonaws.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+loading3.widdit.com.
+45-courier.push.apple.com.
+kapriol.com.
+a.root-servers.net.
+i2.ytimg.com.
+12.2.54.60.in-addr.arpa.
+5.164.59.199.in-addr.arpa.
+v15.nonxt3.c.youtube.com.
+www.brazzerscafe.com.
+profile.ak.fbcdn.net.
+47.106.87.187.in-addr.arpa.
+180.220.176.187.in-addr.arpa.
+google.com.
+ajax.googleapis.com.
+www.accurate-target.com.
+apps.facebook.com.
+realclimate.org.
+dressesmania.com.
+static.ak.fbcdn.net.
+210.131.254.190.in-addr.arpa.
+10.184.60.184.in-addr.arpa.
+_244_92_7.
+maomelody.wordpress.com.
+es-la.facebook.com.
+img3.imageshack.us.
+lcmcompany.com.s5a2.psmtp.com.
+hges.oao-ntek.ru.
+a3.sphotos.ak.fbcdn.net.
+fyeahforeveralone.tumblr.com.
+rewardchannelcenter.com.
+_472_30_1.
+air-review.ru.
+m.addthisedge.com.
+60.85.160.201.in-addr.arpa.
+82.188.49.190.in-addr.arpa.
+41.70.168.192.in-addr.arpa.
+google.com.
+smtp1.xentrisllc.com.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+_339_84_5.
+a.root-servers.net.
+a.root-servers.net.
+mscrl.microsoft.com.
+a2.sphotos.ak.fbcdn.net.
+cdn.bidsystem.com.
+es.ponetelaroja.com.
+www.bendicioness.com.
+sp.cwfservice.net.
+i1.ytimg.com.
+ar-ar.facebook.com.
+handels.gu.se.
+widgets.twimg.com.
+sunnet.com.br.
+sj88p6fyi.a13l8z7b.
+222.11.65.66.in-addr.arpa.
+www.onpointdigital.com.
+_454_04_3.
+docs.google.com.
+ajaxhttpheaders2.appspot.com.
+s1-word-edit.vo.msecnd.net.
+bauldelafamiliaingalls.blogspot.com.
+2101093106605581157-a-1802744773732722657-s-sites.googlegroups.com.
+android.clients.google.com.
+tools.google.com.
+virtultech.com.
+g.ceipmsn.com.
+156.199.162.189.in-addr.arpa.
+www.immigrazioneoggi.it.
+mercadeoprofesional.com.
+gamingzone.dk.msn.com.
+tobolsk.info.
+179.9.138.24.in-addr.arpa.
+www.colombiaenunsolopunto.com.
+in.answers.yahoo.com.
+static.ak.fbcdn.net.
+download340.avast.com.
+www.eng.mcmaster.ca.
+71.48.154.186.in-addr.arpa.
+a248.e.akamai.net.
+60.253.82.190.in-addr.arpa.
+www.facebook.com.
+32.136.152.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+static.socialvi.be.
+xyzxaon53.35do.
+www.statefarm.com.
+www.facebook.com.
+www.solrojo.org.
+view.atdmt.com.
+checkip.dyndns.org.
+av40.hls1.vimeocdn.com.
+www.pauldotcom.com.
+a.root-servers.net.
+www.videosearch.tv.
+de.ufc.com.
+a.root-servers.net.
+scooter.mforos.com.
+wpad.
+ca.reuters.com.
+teredo.ipv6.microsoft.com.
+scholar.google.com.
+www.effectmatrix.com.
+bitacoras.com.
+141.3.0.151.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+x73.cc.
+a1.sphotos.ak.fbcdn.net.
+m.addthisedge.com.
+googleads.g.doubleclick.net.
+www.facebook.com.
+www.google.com.
+www.webmujeractual.com.
+ib.adnxs.com.
+www.whichfranchise.net.au.
+www.clasicooo.com.
+mx02.ecn.purdue.edu.
+cdn.wibiya.com.
+static.ak.facebook.com.
+www.livingroomfurniturenow.com.
+a1796.g.akamai.net.
+135.237.37.174.in-addr.arpa.
+www.laviejaime.com.
+blog.walter-riso.com.
+imap.gmail.com.
+mail.google.com.
+bs.serving-sys.com.
+16.85.168.192.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.formulamania.com.
+espanol.yahoo.com.
+csi.gstatic.com.
+a.root-servers.net.
+mtalk.google.com.
+dpmail01.doteasy.com.
+www.universalaccess.it.
+204.156.222.201.in-addr.arpa.
+locaboat.com.
+riodb01.ibase.aist.go.jp.
+search.conduit.cm.
+www.igroup.co.za.
+irc.purchaseservice.com.
+bjr.sagepub.com.
+172.179.149.187.in-addr.arpa.
+ads.admarvel.com.
+ajax.googleapis.com.
+vwiy83tle.65ys.
+e906.g.akamaiedge.net.
+i1.ytimg.com.
+www.cuevana.tv.
+capitolfax.com.
+www.gottransmissions.com.
+ebudy.co.
+c72khh:xe.52jj.
+us.taylorwoodrow.com.
+boringpittsburgh.com.
+mail.lincoln-associates.fr.
+89.58.171.187.in-addr.arpa.
+www.ceciliaperez.com.
+huhahi.ru.
+www.subeimagenes.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+rospres.com.
+224.5.156.187.in-addr.arpa.
+cdn.api.twitter.com.
+www.affiliateyard.com.
+lists.formoza.ru.
+versioncheck.addons.mozilla.org.
+creatives.livejasmin.com.
+a.root-servers.net.
+www.nlm.nih.gov.
+sub.ezinedirector.net.
+s-static.ak.fbcdn.net.
+mx1.hotmail.com.
+utmtrk.vimeo.com.
+accountservices.msn.com.
+static.ak.fbcdn.net.
+117.229.81.108.in-addr.arpa.
+114.188.53.60.in-addr.arpa.
+20.113.102.189.in-addr.arpa.
+read.chcm.ubc.ca.
+23.152.222.189.in-addr.arpa.
+safebrowsing-cache.google.com.
+leak-squad.ca.
+blog.opensys911.net.
+a1.sphotos.ak.fbcdn.net.
+www.sonirodban.com.
+met-inc.com.
+caminosdeayer.blogspot.com.
+127.233.170.201.in-addr.arpa.
+a.root-servers.net.
+alt1.gmail-smtp-in.l.google.com.
+113.31.221.95.in-addr.arpa.
+profile.ak.fbcdn.net.
+time.windows.com.
+www.kseba.info.
+awio.zendesk.com.
+www-google-analytics.l.google.com.
+tx.sbc.primusvoip.com.
+fbcdn-photos-a.akamaihd.net.
+profile.ak.fbcdn.net.
+www.jessicachina.net.
+google-sketchup-free.softonic.de.
+profile.ak.fbcdn.net.
+a.ads2.msads.net.
+ib.adnxs.com.
+126.224.110.186.in-addr.arpa.
+4083.live.streamtheworld.com.
+tc.v18.cache7.c.youtube.com.
+s0.2mdn.net.
+s-static.ak.fbcdn.net.
+idrc.org.
+tejiendohaciendoconelcorazon.blogspot.com.
+201.53.106.177.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+83.99.14.201.in-addr.arpa.
+h30471.www3.hp.com.
+mail.softassist.com.
+www.villaserbelloni.com.
+aol.com.
+switch.atdmt.com.
+0day.in.
+heartbeat.belkin.com.
+pobeda-cinema.ru.
+clients2.google.com.
+fusion.google.com.
+www.3-0b6f-415d-b5c7-832f0.com.
+www.alfonsosanchez.net.
+m.youtube.com.
+www.izi.fraunhofer.de.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+blst.msn.com.
+maison-otaku.net.
+ecms.net.
+focustechnologies.com.
+sp.cwfservice.net.
+webcache.googleusercontent.com.
+www.reform.co.uk.
+www.facebook.com.
+v4.cache5.c.youtube.com.
+to4vb5ak9.12vr.
+reshade.com.
+18.8.42.201.in-addr.arpa.
+lb._dns-sd._udp.lan.
+gdata.youtube.com.
+97.15.168.192.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+gandalf.webcohort.com.
+175.190.191.71.in-addr.arpa.
+37.200.10.87.in-addr.arpa.
+42.24.74.187.in-addr.arpa.
+a1804.phobos.apple.com.
+www.textsrv.com.
+www.tuslibrosgratis.net.
+www.logitech.com.
+gn.wikipedia.org.
+photos-e.ak.fbcdn.net.
+www.greenhasitalia.com.
+75.128.253.84.in-addr.arpa.
+pictaregallery.blogspot.com.
+nudebollywood.blog.com.
+mail2.energytransfer.com.
+2bcool.net.
+calendar.live.com.
+www.youtube.com.
+socialmediadaily.com.au.
+apps.facebook.com.
+www.facebook.com.
+meta.izhcom.ru.
+www.appbrain.com.
+indosharing.net.
+www.phototecnia.com.
+www.facebook.com.
+connect.facebook.net.
+mailin-03.mx.aol.com.
+www.google-analytics.com.
+www.cenex.com.
+www.elcolombiano.com.
+rcp.eu.blackberry.com.
+profile.ak.fbcdn.net.
+179.141.207.190.in-addr.arpa.
+ads.buzzcity.net.
+211.148.84.190.in-addr.arpa.
+stjeromes.wa.edu.au.
+adserver.twitpic.com.
+23.252.220.91.in-addr.arpa.
+enac.com.
+0-jx-w.channel.facebook.com.
+redblogsarquitectura.suju.eu.
+mail.northvillecsd.k12.ny.us.
+mail.google.com.
+189.240.212.217.in-addr.arpa.
+te.ru.
+mail2.megatv.com.
+www.msftncsi.com.
+mail.bgok.ru.
+www.google.com.
+connect.facebook.net.
+ballwy.com.
+n4jzv72fv.r23v0l4l.
+a7.sphotos.ak.fbcdn.net.
+253.94.57.62.in-addr.arpa.
+108.164.155.92.in-addr.arpa.
+images-na.ssl-images-amazon.com.
+itb.co.uk.
+226.25.191.189.in-addr.arpa.
+denis.stalker.h3q.com.
+mail1.cosprop.com.
+mail.
+www.gfidalex.com.
+bellfuels.com.
+ssl.apple.com.
+profile.ak.fbcdn.net.
+www.gstatic.com.
+www9.effectivemeasure.net.
+www.youtube.com.
+apps.facebook.com.
+171.206.225.190.in-addr.arpa.
+mcgin.com.
+a.root-servers.net.
+twpiano.opentech.mobi.
+connect.facebook.net.
+www.google.com.
+58.152.241.201.in-addr.arpa.
+v.giantrealm.com.
+97.20.57.85.in-addr.arpa.
+193.65.2.187.in-addr.arpa.
+fls.doubleclick.net.
+d1j68ux4ukg4g1.cloudfront.net.
+mail.featurecreeptechnology.com.
+d1j68ux4ukg4g1.cloudfront.net.
+238.45.16.187.in-addr.arpa.
+redfaceplus.com.
+pixel.facebook.com.
+www.wellsfargo.com.
+aoltech.com.
+col.stb00.s-msn.com.
+sites.google.com.
+ktc-net.ru.
+bitdefender.surveyesun.sgizmo.com.
+www.planering.org.
+muzig-prod.muzigle.com.
+www.aljsad.net.
+150.216.82.62.in-addr.arpa.
+edipresse.adocean.pl.
+www.youtube.com.
+photos-c.ak.fbcdn.net.
+api.nanigans.com.
+business.shop.ebay.com.
+urs.microsoft.com.
+a1001.w40.akamai.net.
+i4.ytimg.com.
+224.252.68.201.in-addr.arpa.
+gtaonline.com.ar.
+47.53.136.14.in-addr.arpa.
+fileham.com.
+static.ak.facebook.com.
+mart.spb.ru.
+a.root-servers.net.
+129.239.31.190.in-addr.arpa.
+www.lavilla2.com.
+www.trust-guard.com.
+ferti-val.com.
+cs5188.vkontakte.ru.
+www.youtube.com.
+61.191.34.201.in-addr.arpa.
+217.43.21.190.in-addr.arpa.
+1d2kusc:c.t11g9f7c.
+amermac.com.
+jamiexelite.ourtoolbar.com.
+95.25.130.181.in-addr.arpa.
+www.bloomberg.co.jp.
+www.uominiedonneanticipazioni.it.
+a.root-servers.net.
+tst.social.technet.microsoft.com.
+ksn2-12.kaspersky-labs.com.
+111.38.252.189.in-addr.arpa.
+56.163.160.187.in-addr.arpa.
+prov.mydlink.com.
+253.189.137.187.in-addr.arpa.
+194.240.91.27.in-addr.arpa.
+i1.ytimg.com.
+pop.secureserver.net.
+pixel.facebook.com.
+api.twitter.com.
+filter.fristampumps.com.
+cadaverlab.com.
+photos-f.ak.fbcdn.net.
+102.146.220.66.in-addr.arpa.
+enforce.com.
+dns.msftncsi.com.
+18.80.108.83.in-addr.arpa.
+www-e.uni-magdeburg.de.
+www.g.home.
+superbar.ru.
+ntp.glb.nist.gov.
+fashionvip.polyvore.com.
+www.gioie.it.
+www.inm.gob.mx.
+mail.matsongmac.com.
+tcpconn2.tencent.com.
+_517_63_5.
+sgtlaw.com.s5a2.psmtp.com.
+qomxppppudxhdfl.com.
+libromagicodeembrujo.blogspot.com.
+spreadsheets.google.com.
+www.reflexionesmarginales.com.
+www.gabrielbustamante.pe.
+a.root-servers.net.
+a.root-servers.net.
+download654.avast.com.
+teredo.ipv6.microsoft.com.
+us.data.toolbar.yahoo.com.
+blogs.sowetanlive.co.za.
+16.10.107.187.in-addr.arpa.
+archiv.fagms.de.
+ak.imgfarm.com.
+fieldale.com.
+90.174.127.201.in-addr.arpa.
+widgets.montiera.com.
+static.ak.fbcdn.net.
+webassets3.sparkybee.com.
+www.gstatic.com.
+echo.edge.messenger.live.com.
+ns1.exit109.com.
+llcrew.com.
+www.google.com.
+jwhodgespc.com.
+www.googleadservices.com.
+google.com.
+barnfield.org.
+wk.net.
+beamershop24.net.
+dr._dns-sd._udp.0.55.211.10.in-addr.arpa.
+nullmx.2extreme.net.
+a5.sphotos.ak.fbcdn.net.
+www.wiseupkids.com.
+rad.msn.com.
+systeam.ru.
+19.253.191.207.in-addr.arpa.
+3.105.93.212.in-addr.arpa.
+daydreamer0207.tumblr.com.
+a1634.phobos.apple.com.
+www.gadi-nowblog.blogspot.com.
+beautyandababy.blogspot.com.
+www.tugbbs.com.
+labitacoradehobsbawm.blogspot.com.
+budwolfchevy.com.
+profile.ak.fbcdn.net.
+www.leycosmica.org.
+admin.vpxsports.com.
+www.qzal.net.
+www.google.com.
+c.aol.com.
+wpad.
+weather.service.msn.com.
+www.addthis.com.
+login.domains.live.com.
+pix04.revsci.net.
+dinz.ru.
+radiopopper.com.
+www.arab-ency.com.
+google.com.
+registry.nafta-sec-alena.org.
+pixel.facebook.com.
+_069_15_0.
+6to4.ipv6.microsoft.com.
+carsale.uol.com.br.
+pop3.live.com.
+directoresenredlga.over-blog.es.
+ads.e-planning.net.
+i4.ytimg.com.
+149.242.212.90.in-addr.arpa.
+www.disneylatino.com.
+sickestaddictions.com.
+100.185.69.216.in-addr.arpa.
+armmf.adobe.com.
+92.204.54.108.in-addr.arpa.
+pagead2.googlesyndication.com.
+183.82.43.89.in-addr.arpa.
+insidemovies.ew.com.
+a7.sphotos.ak.fbcdn.net.
+soundcloud.com.
+photos-d.ak.fbcdn.net.
+www.newuniversity.org.
+s-static.ak.fbcdn.net.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+forums.triplezoom.com.
+5tvm8ne41.f84w6z5t.
+a-0.19-27090041.9050083.1518.19d4.2f4a.10.0.nza1ldzdki8qrtrc7upjzq5b95.avqs.mcafee.com.
+68.139.149.187.in-addr.arpa.
+intermarketandmore.finanza.com.
+fr-fr.facebook.com.
+www.ucmalumnistore.com.
+kapiolani.hawaii.edu.
+w7c6iosj3.w14g9q2q.
+www.paypal.es.
+www.thumbgenie.com.
+autos.mercadolibre.com.ar.
+www.facebook.com.
+translate.googleapis.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ja.wikipedia.org.
+www.tiendamasterhacks.com.
+profile.ak.fbcdn.net.
+www.7irtny.com.
+135.13.31.177.in-addr.arpa.
+mail2.fremuragroup.com.
+i1.ytimg.com.
+phs.org.
+cdn.api.twitter.com.
+s.ytimg.com.
+hustleruniversity.blogspot.com.
+star.facebook.com.
+213.226.2.188.in-addr.arpa.
+www.juegosdepadrinosmagicos.blogspot.com.
+181.3.149.83.in-addr.arpa.
+pacbev.sg.
+.
+hardingcreative.com.
+www.ebay.in.
+s0000090.ecdomain.net.packaging.sca.se.
+mail.gibbymedia.com.
+162.164.178.74.in-addr.arpa.
+www.anaheimoc.org.
+www.google.com.
+45.34.30.190.in-addr.arpa.
+70.138.7.221.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+sp.ask.com.
+cdn.mediafire.com.
+b._dns-sd._udp.0.11.168.192.in-addr.arpa.
+filetram.com.
+0-jf-w.channel.facebook.com.
+bibmed.ucla.edu.ve.
+csi.gstatic.com.
+safebrowsing-cache.google.com.
+untwisting.ru.
+api-read.facebook.com.
+twitter.com.
+a2.twimg.com.
+www.google.com.
+csi.gstatic.com.
+lakelly.co.uk.
+teredo.ipv6.microsoft.com.
+0.3896415.com.
+drug.now.nu.
+themixsantamonica.com.
+www.amateurnudie.com.
+www.flour.com.
+a8.sphotos.ak.fbcdn.net.
+ca.hello.dj.
+mostlybricks.com.
+social.bidsystem.com.
+82.133.253.189.in-addr.arpa.
+billing.sharo4ka.ru.
+registeridm.com.
+a.root-servers.net.
+backup-mx.wannafind.dk.
+a3.sphotos.ak.fbcdn.net.
+scholar.google.com.
+www.google.com.
+contactsullivan.com.
+ocsp.verisign.com.
+28.16.191.190.in-addr.arpa.
+bearby.us.
+da.wikipedia.org.
+profile.ak.fbcdn.net.
+aibi.ph.
+iddqd.ru.
+251.182.253.190.in-addr.arpa.
+a.root-servers.net.
+www.webpartypro.com.
+www.google.com.
+180.62.250.190.in-addr.arpa.
+198.114.30.186.in-addr.arpa.
+mw2.google.com.
+luelinks.net.
+mx7.surw.ru.
+fbcdn-photos-a.akamaihd.net.
+www.injoy.com.
+www.youtube.com.
+jsm-law.com.
+85.223.1.72.in-addr.arpa.
+a.root-servers.net.
+www.google.com.
+signin-it.g.ebay.com.
+162.49.77.64.in-addr.arpa.
+a.root-servers.net.
+casitadepapel.wordpress.com.
+85.20.76.188.in-addr.arpa.
+googleads.g.doubleclick.net.
+a2000.phobos.apple.com.
+prodika.com.
+wrma.com.inbound15.mxlogicmx.net.
+google.com.
+www.google.ch.
+214.244.253.189.in-addr.arpa.
+qnjcm71pu.z50h8i4e.
+www.mistertorrent.com.
+avatar.xboxlive.com.
+twitter.com.
+214.55.246.201.in-addr.arpa.
+zencarttemplates.info.
+calgarytunnelling.com.
+edytv.blogspot.com.
+s-static.ak.facebook.com.
+a.root-servers.net.
+extended-validation-ssl.verisign.com.
+80.6.97.190.in-addr.arpa.
+a.root-servers.net.
+bestbuyideax.com.
+sgc5vr5iq.26ta.
+ssl.gstatic.com.
+news.google.com.mx.
+a.root-servers.net.
+w.sharethis.com.
+anyonesson.com.
+pixel.quantserve.com.
+tfws.threatfire.com.
+8nacr96qu.q67n9f6f.
+26.229.171.69.in-addr.arpa.
+beautyfashiontips.net.
+alt2.aspmx.l.google.com.
+photos-b.ak.fbcdn.net.
+b.scorecardresearch.com.
+www.bing.com.
+aresline.com.
+d.yimg.com.
+41.213.90.200.in-addr.arpa.
+partner.googleadservices.com.
+areahouses.com.
+www.erantis.com.
+developers.facebook.com.
+211.11.123.186.in-addr.arpa.
+i3.ytimg.com.
+cc.usart.ru.
+mesu.apple.com.
+a.root-servers.net.
+www.cualcompro.com.
+cdn.api.twitter.com.
+131.105.158.190.in-addr.arpa.
+oss.ticketmaster1st.akadns.net.
+hrcaonline.org.
+nmetrics.samsung.com.
+hotmail.com.
+249.31.11.82.in-addr.arpa.
+144.45.36.187.in-addr.arpa.
+mx1.qwestoffice.com.
+gaom.hit.gemius.pl.
+secure.qmiles.com.
+www.google-analytics.com.
+thumbs4.ebaystatic.com.
+iskrauraltel.ru.
+es1.darkorbit.bigpoint.com.
+www.addtoany.com.
+nuestrobux.com.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+data.publishflow.com.
+server3.profileservice.movisol.com.
+www.revistaquimica.cl.
+www.cupoint.com.
+a-patch-2011.softonic.com.
+da.cb.b9.a1.top.mail.ru.
+pixel.facebook.com.
+xlocomotionchannel20x.api.channel.livestream.com.
+www.visual-basic.com.ar.
+ajax.aspnetcdn.com.
+115.120.30.186.in-addr.arpa.
+s.ytimg.com.
+www.google.com.
+www.besteducationalgrants.org.
+125.11.183.67.in-addr.arpa.
+partner.googleadservices.com.
+247.182.131.208.in-addr.arpa.
+a.root-servers.net.
+img215.imageshack.us.
+mscrl.microsoft.com.
+pagead2.googlesyndication.com.
+91.166.243.189.in-addr.arpa.
+youtube.com.
+video.l.google.com.
+53.173.174.206.in-addr.arpa.
+support.createmybb.com.
+www.amazingbizkey.com.
+ocsp.verisign.com.
+download.microsoft.com.
+historiasydemasparanoias.blogspot.com.
+98.73.196.84.in-addr.arpa.
+93.79.37.190.in-addr.arpa.
+xcelplus.com.
+grbnotes.grblaw.com.
+246.16.108.190.in-addr.arpa.
+appsmetadata.toolbar.conduit-services.com.
+19.52.78.186.in-addr.arpa.
+turtlezen.com.
+a2.sphotos.ak.fbcdn.net.
+lvs.fok.nl.
+www.casasderematemonterrey.com.
+en.data.wrapper.services.alawar.com.
+136.105.113.186.in-addr.arpa.
+yahoo.com.
+211.40.46.190.in-addr.arpa.
+94.116.255.206.in-addr.arpa.
+search.iminent.com.
+profile.ak.fbcdn.net.
+api.facebook.com.
+cs12717.vkontakte.ru.
+www.linkwithin.com.
+designs.fedmich.com.
+www.googel.com.
+232.43.168.192.in-addr.arpa.
+tiggermail.com.
+deals.dealply.com.
+www.dr-machine.com.
+a6.sphotos.ak.fbcdn.net.
+www.winamp.com.
+external.ak.fbcdn.net.
+cdn.labpixies.com.
+childrentales.org.mialias.net.
+zpay.static.zynga.com.
+158.244.3.187.in-addr.arpa.
+api-read.facebook.com.
+66.82.11.186.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+pismo.com.s8a2.psmtp.com.
+www.google.com.
+b.compunass.org.
+ads.cartrade.com.
+a8.sphotos.ak.fbcdn.net.
+38.50.45.190.in-addr.arpa.
+ethionet.et.
+adserving.cpxinteractive.com.
+triwest.net.
+www.laboiteverte.fr.
+www.conexionabierta.com.ar.
+teredo.ipv6.microsoft.com.
+www.youtube.com.
+62.15.254.201.in-addr.arpa.
+e3499.c.akamaiedge.net.
+rsemfg5bv.i36c2j2q.
+mail.isilo.com.
+ap.dasglobal.com.
+mms.whatsapp.net.
+static.yandex.st.
+aol.com.
+forthebubbles.wordpress.com.
+plusone.google.com.
+external.ak.fbcdn.net.
+www.facebook.com.
+95.238.109.84.in-addr.arpa.
+g.msn.com.
+s-static.ak.fbcdn.net.
+crl.microsoft.com.
+wpc.3adc.edgecastcdn.net.
+a.root-servers.net.
+static.ak.fbcdn.net.
+ad.z5x.net.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+www.juegosgt.com.
+www.iej.cl.
+projectfive-oh.blogspot.com.
+www.quien.com.
+42.96.212.201.in-addr.arpa.
+ims.tkmna.thyssenkrupp.com.
+a2.sphotos.ak.fbcdn.net.
+www.forexinvestments.de.
+www.youtube.com.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+lbcwre.com.
+a.root-servers.net.
+programming-tools.ab-archive.net.
+152.187.152.189.in-addr.arpa.
+lrvbokqag.cn.
+ar-ar.facebook.com.
+www.quiebrapiezas.blogspot.com.
+twitter.com.
+ajax.googleapis.com.
+a845.b.akamai.net.
+apis.google.com.
+mail.americaninterbanc.com.
+www.bilderberg.org.
+52.133.213.201.in-addr.arpa.
+bo.starmedia.com.
+gfx2.hotmail.com.
+23.184.8.186.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+www.todox.org.
+mfcllp.com.
+wiaderko.net.
+cotendo.cedexis.com.
+12meds.com.lan.
+static.ak.fbcdn.net.
+3-ps.googleusercontent.com.
+es-es.fxfeeds.mozilla.com.
+alexandertranfer.com.
+www.tuinfosoft.net.
+221.54.134.190.in-addr.arpa.
+adfiscass.nl.
+a2.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.justfashionmodels.com.
+dns.msftncsi.com.
+a.root-servers.net.
+v8.nonxt5.c.youtube.com.
+m5pqh4nwr.66vi.
+91.166.109.186.in-addr.arpa.
+116.182.136.2.in-addr.arpa.
+publicidade.abril.com.br.
+127.0.0.1.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a248.e.akamai.net.
+sites.google.com.
+86.180.105.177.in-addr.arpa.
+haaallie-.piczo.com.
+138.247.132.187.in-addr.arpa.
+google.com.
+55.115.173.190.in-addr.arpa.
+10.124.40.77.in-addr.arpa.
+lovecalculator2.com.
+ws-cloud-msgplus.linkury.com.
+profile.ak.fbcdn.net.
+t3.gstatic.com.
+www.arcticultra.de.
+time-nw.nist.gov.
+planocreativo.files.wordpress.com.
+hv2m91.tu.tv.
+pixel.facebook.com.
+shopping.search.yahoo.co.jp.
+nodes.affidirect.com.
+static.4shared.com.
+ar-ar.facebook.com.
+skydrive.live.com.
+4mostip.com.
+www.asian-pleasures-asianpleasures.com.
+escribesconmigo.blogspot.com.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+a.root-servers.net.
+www.smartadserver.com.
+54.205.50.190.in-addr.arpa.
+msn.com.
+_872_53_4.
+www.google-analytics.com.
+johnsonbodyshop.com.
+ksn2-12.kaspersky-labs.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+xqeydnuwhqt.net.
+metronews.com.s8a1.psmtp.com.vval.com.
+a.root-servers.net.
+www.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+vf.cloud.avg.com.
+yourwardrobeunlockd.com.
+s3.amazonaws.com.
+c.gigcount.com.
+69.151.241.201.in-addr.arpa.
+79.111.8.201.in-addr.arpa.
+external.ak.fbcdn.net.
+walworthcountytoday.com.
+222.9.106.186.in-addr.arpa.
+_068_02_6.
+i2.ytimg.com.
+www.facebook.com.
+photos-a.ak.fbcdn.net.
+mail.google.com.
+rd.meebo.com.
+www.emol.com.
+244.135.41.119.in-addr.arpa.
+113.190.250.189.in-addr.arpa.
+pop.mail.yahoo.com.cn.
+www.facebook.com.
+_669_83_3.
+www.youtube.com.
+www.seebiz.eu.
+www.ehea.info.
+www.loverpass.com.
+a5.sphotos.ak.fbcdn.net.
+presicom.com.
+smtp01.delhi.edu.
+7.198.98.189.in-addr.arpa.
+1979304085345356636-a-1802744773732722657-s-sites.googlegroups.com.
+www.facebook.com.
+firstamericanmortgageinc.com.
+api.twitter.com.
+www.dwinsider.com.
+whos.amung.us.
+mail.dynamicfenceinc.com.
+149.21.16.190.in-addr.arpa.
+djknight.com.
+premier.sonetpremier.com.
+www.google.com.
+ntp.glb.nist.gov.
+matcher.bidder8.mookie1.com.
+pwdsl3w71.61nf.
+www.google-analytics.com.
+garyes.stormloader.com.
+70.205.97.190.in-addr.arpa.
+www.webmoney.ru.
+time.windows.com.
+talkmarketing.com.
+www.smiles.ie.
+245.41.141.89.in-addr.arpa.
+www.amantesdeteruel.es.
+connect.facebook.net.
+sniperlandia.webcindario.com.
+farm7.static.flickr.com.
+b._dns-sd._udp.lan.
+ntp.glb.nist.gov.
+grandcyberglobal.com.
+173.114.136.190.in-addr.arpa.
+177.172.93.186.in-addr.arpa.
+www.facebook.com.
+external.ak.fbcdn.net.
+ci.lincoln.ca.us.
+companyname.122.2o7.net.
+209.125.53.186.in-addr.arpa.
+ww2.shemaleambush.com.
+radioalgarve.com.
+226.61.168.192.in-addr.arpa.
+www.swingsurgeon.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+www.googleadservices.com.
+photos.pokerplayer.co.uk.
+cbmcint-org.mail.eo.outlook.com.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+wpad.
+wwws.projectgenesis.org.
+29.51.66.187.in-addr.arpa.
+0bps664l3vqk05dj8qih0t5renri9iic.ig.ig.gmodules.com.
+checkip.dyndns.org.
+es-es.facebook.com.
+googleads.g.doubleclick.net.
+jp.tous.com.
+81.229.246.148.in-addr.arpa.
+fotos.amigate.com.
+www.fastmarkets.com.
+wickedcampers.com.au.
+62.197.88.74.in-addr.arpa.
+a.root-servers.net.
+static.ak.fbcdn.net.
+www.google.com.
+137.227.250.190.in-addr.arpa.
+w3.coh.arizona.edu.
+64.102.30.190.in-addr.arpa.
+static.exoclick.com.
+pixel.facebook.com.
+fbpanel.sourceforge.net.
+view.atdmt.com.
+3.242.114.200.in-addr.arpa.
+mx1.cboss.ru.
+photos-e.ak.fbcdn.net.
+webs.rakurs.com.
+www.extremista.com.ar.
+i.lulzimg.com.
+feeds.bbci.co.uk.
+a.root-servers.net.
+186.187.142.187.in-addr.arpa.
+mail.modernpest.com.
+217.137.145.201.in-addr.arpa.
+www.revistakronos.com.
+184.89.241.66.in-addr.arpa.
+public5.tektek.org.
+rebeccaminkoff.com.
+a.root-servers.net.
+bioware.com.
+www2.nissan.es.
+heltenkelthosmig.blogspot.com.
+gfx2.hotmail.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+certs.opera.com.
+safebrowsing.clients.google.com.
+168.187.202.190.in-addr.arpa.
+243.171.153.187.in-addr.arpa.
+donate.cwf-fcf.org.
+directorio.fandejuegos.com.
+242.82.153.189.in-addr.arpa.
+www.cabinainterestelar.com.
+www.derechoambiental.udp.cl.
+severe-caning.spanking18.com.
+prin.ru.
+a.root-servers.net.
+2.1.168.192.in-addr.arpa.
+79.48.168.192.in-addr.arpa.
+unixcommerce.com.
+www.pinkribbonstore.com.
+a4.sphotos.ak.fbcdn.net.
+65.10.171.187.in-addr.arpa.
+themes.googleusercontent.com.
+tracker.ilibr.org.
+d3.iesc.org.
+www.facebook.com.
+i3.ytimg.com.
+gfx3.hotmail.com.
+pgnzheoi.info.
+176.62.76.190.in-addr.arpa.
+leercondevoridad.blogspot.com.
+loewarch.com.
+bloggista.com.
+www.stayvillage.com.
+profile.ak.fbcdn.net.
+supports.jiaju.sina.com.cn.
+dsn8.d.skype.net.
+pubads.g.doubleclick.net.
+a1.sphotos.ak.fbcdn.net.
+hosting.lockhosts.com.
+count.pro09.iciba.com.
+www.clr.net.
+faml.ru.
+pld.com.s9b2.psmtp.com.
+www.bodyjewelry.com.
+sn21.mailshell.net.
+www.fulltubemovies.com.
+mail.who-remembers-me.com.
+www.marcorascon.org.
+external.ak.fbcdn.net.
+samson.hac.com.
+www.na7la.com.
+relay2.sptk.com.ru.
+www.therecruitmentjob.com.
+photos-h.ak.fbcdn.net.
+a06.t26.net.
+19.133.210.201.in-addr.arpa.
+www.juegosvestirchicas.com.
+partner.googleadservices.com.
+affiliate.buy.com.
+mail.samaraintour.ru.
+www.facebook.com.
+72.115.164.190.in-addr.arpa.
+zbar.zynga.com.
+fonts.googleapis.com.
+a.root-servers.net.
+rocketmail.om.
+csi.gstatic.com.
+msgr.updates.yahoo.com.
+www.heritagedaily.com.
+en.wikipedia.org.
+shankars.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a957.g.akamai.net.
+158.88.212.190.in-addr.arpa.
+jiguli.ru.
+www.aardvarkrecords.co.uk.
+haverford.edu.
+vp.sip.messenger.msn.com.
+cnna.gob.ec.
+2.203.92.201.in-addr.arpa.
+easel.ru.
+s-static.ak.fbcdn.net.
+kcnet.net.
+ragnartheraider.newgrounds.com.
+atomixmag.com.
+t-one.net.s5a1.psmtp.com.
+a7.sphotos.ak.fbcdn.net.
+bs.serving-sys.com.
+foro.ludoslegio.com.
+eccocanada.com.
+cdn-5.pics.t8premium.com.
+www.justin.tv.
+buscandouniversidad.com.
+124.102.198.190.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+sci.com.
+google.com.
+s0.2mdn.net.
+fms-eu5.panet.co.il.
+mx02.peoplepc.com.
+profile.ak.fbcdn.net.
+rvb.wikia.com.
+106.179.190.190.in-addr.arpa.
+a.root-servers.net.
+www.buraannews.com.
+weiterleitung.k1.cx.
+api.twitter.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b.scorecardresearch.com.
+touch.facebook.com.
+www.ntius.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+smtpmsa.msanet.com.
+209.199.56.85.in-addr.arpa.
+www.laira.dominarlaira.com.
+jameique.com.
+ads.iforex.com.
+s7.addthis.com.
+www.brunoymaria.com.
+www.facebook.com.
+www.troid.org.
+fbcdn-photos-a.akamaihd.net.
+sp-metal.ru.
+rwerheinbraun.com.
+counter.cnw.cz.
+estaticos04.cache.el-mundo.net.
+wac.edgecastcdn.net.
+photos-c.ak.fbcdn.net.
+ads.bluelithium.com.
+mygzytvo6.52ez.
+potugalmail.pt.
+www.fbookbanners.net.
+204.69.65.187.in-addr.arpa.
+cdn.api.twitter.com.
+lanza.chulojuegos.com.
+quintoatieneunblog.blogspot.com.
+profile.ak.fbcdn.net.
+www.wdc.com.
+photos-a.ak.fbcdn.net.
+api.twitter.com.
+mail.google.com.
+164.231.97.92.in-addr.arpa.
+translate.google.com.
+nyit.com.
+mail.urlmutual.com.
+zse.com.
+www.avis.com.ar.
+a4.sphotos.ak.fbcdn.net.
+es-la.facebook.com.
+pagead2.googlesyndication.com.
+mghribia.canalblog.com.
+dqobor.com.
+t.co.
+cdn.api.twitter.com.
+time.chttl.com.tw.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+a.root-servers.net.
+gmx.ivwbox.de.
+106.227.155.85.in-addr.arpa.
+hepburnlaw.com.
+tsm05.eset.com.
+comcs.net.
+itistimetothinkformyself.blogspot.com.
+mail1.maciraq.com.
+117.51.46.189.in-addr.arpa.
+t2.gstatic.com.
+129.186.253.189.in-addr.arpa.
+googleads.g.doubleclick.net.
+lascuentasbancarias.com.ar.
+107.15.165.189.in-addr.arpa.
+chiraltech.com.inbound15.mxlogic.net.
+ut45forvh.j60l4q7i.
+www.andaluciajunta.es.
+us.mg1.mail.yahoo.com.
+anuncios-personales.vivastreet.com.mx.
+zh-cn.facebook.com.
+techspotting.org.
+www.tungstenworld.com.
+buscador.terra.com.pe.
+www.google.com.
+a.root-servers.net.
+pt-br.facebook.com.
+s2.youtube.com.
+communities.disqus.com.
+12.139.49.81.in-addr.arpa.
+itbusiness.disqus.com.
+b.mail.google.com.
+339mbwbhs.76qa.
+a.root-servers.net.
+mail.glare-n-dazzle.com.
+optimized-by.rubiconproject.com.
+_sip._tls.wartsila.com.
+i4.ytimg.com.
+ww.pendonas.net.
+www.videostravelguide.com.
+a1.sphotos.ak.fbcdn.net.
+rss.msnbc.msn.com.
+exprintur.com.
+www.18toplay.com.
+developers.facebook.com.
+tc22.easythumbhost.com.
+www.facebook.com.
+182.126.197.201.in-addr.arpa.
+swebmail.net.
+m.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+www.avrilsforum.net.
+e.deviantart.net.
+rgzl1hp3b.b19o1w5q.
+www.urmc.rochester.edu.
+jimdo.ru.
+106.190.13.189.in-addr.arpa.
+static.ak.fbcdn.net.
+mail.gudemangroup.com.
+www.textsrv.com.
+load.exelator.com.
+pitchfork.com.
+www.update.microsoft.com.
+www.apple.com.
+:yd1wrz11.19gr.
+sijoittajaksi.blogit.kauppalehti.fi.
+se.altavista.com.
+s-static.ak.facebook.com.
+a.root-servers.net.
+img203.yfrog.com.
+cleorecs.com.
+161.109.236.204.in-addr.arpa.
+ping3.dyngate.com.
+timelapses.tv.
+crl.microsoft.com.
+customapp.golfballs.com.
+ib.adnxs.com.
+photos-c.ak.fbcdn.net.
+platform.twitter.com.
+www.facebook.com.
+orient-usa.com.inbound15.mxlogicmx.net.
+safebrowsing-cache.google.com.
+131.245.50.211.in-addr.arpa.
+trilliumcorp-com.mail.eo.outlook.com.
+www.slideshare.net.
+251.133.221.189.in-addr.arpa.
+none.
+www.guerillahost.com.
+www.facebook.com.
+mail.ravitron.com.
+cs13088.vkontakte.ru.
+astrologia.com.co.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+es-la.facebook.com.
+www.ingdirect.com.au.
+opensudoku.softonic.com.
+supertracker.flashget.com.
+paac.org.
+.
+newsrss.bbc.co.uk.
+21.57.81.173.in-addr.arpa.
+mail2.kcs.ru.
+41.0.160.189.in-addr.arpa.
+static.ak.fbcdn.net.
+feedlb2.feedsportal.com.
+ads1.msads.net.
+www.facebook.com.
+www.msdiagnosed.org.
+anthologymag.com.
+photos-g.ak.fbcdn.net.
+digg.com.
+james-camerons-avatar-the-game.en.softonic.com.
+services.vesti.ru.
+197.48.106.216.in-addr.arpa.
+hog.assets.zgncdn.com.
+pubads.g.doubleclick.net.
+101.172.168.67.in-addr.arpa.
+alerts.conduit-services.com.
+nz.video.yahoo.com.
+www.formatmag.com.
+253.224.121.200.in-addr.arpa.
+131.169.111.98.in-addr.arpa.
+236.124.136.175.in-addr.arpa.
+huevosoro.com.
+102.86.139.187.in-addr.arpa.
+lwltlvlwl.com.
+supremenola.com.
+economics.uoregon.edu.
+tweetcam.me.s3-website-us-east-1.amazonaws.com.
+pixel.facebook.com.
+hi-in.facebook.com.
+media.king5.com.
+airbrakeapp.com.
+www.sabadell.net.
+www.facebook.com.
+proxy-bay.contacts.msn.com.
+a4.sphotos.ak.fbcdn.net.
+col.stj.s-msn.com.
+voipc.sip.yahoo.com.
+zgn.static.zynga.com.
+interceptor.ridgways.com.
+googleads.g.doubleclick.net.
+mail.wood-guard.com.
+mx.s.dion.ne.jp.
+m.ak.fbcdn.net.
+dotjohn.com.
+airlineguide.org.
+upload.wikimedia.org.
+lightworker.com.
+www.pantythumbz.com.
+elkaru.ru.
+138.24.24.187.in-addr.arpa.
+adserving.cpxinteractive.com.
+rktekt.com.
+mail.the3rdlevel.com.
+scrambledbrains.net.
+pubads.g.doubleclick.net.
+www.google.com.
+a5.sphotos.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+www.pinballrebel.com.
+a1811.g.akamai.net.
+legioninsurance.com.inbound10.mxlogicmx.net.
+mailserver.newhorizonsglobal.com.
+apis.google.com.
+photos-b.ak.fbcdn.net.
+d31ahpoxjzaj3o.cloudfront.net.
+c.gigcount.com.
+cl.hilti.com.
+discoveryresourcesinc.com.
+msc.wlxrs.com.
+profile.ak.fbcdn.net.
+psimago.blogspot.com.
+toolbarqueries.google.com.
+accounts.google.com.
+49.135.107.71.in-addr.arpa.
+ds.serving-sys.com.
+a.root-servers.net.
+www.ultrafastproxy.com.
+bly.chel.rgs.ru.
+ldr.newsltd.com.au.
+googleads.g.doubleclick.net.
+tb.gooofull.com.
+ca.indeed.com.
+147.28.0.181.in-addr.arpa.
+mesu.apple.com.
+secure-uk.imrworldwide.com.
+microsoft.com.rhsbl.ahbl.org.
+community.istaria.com.
+api.demandbase.com.
+colon.com.
+cheatsoft.su.
+185.173.44.190.in-addr.arpa.
+151.0.130.66.in-addr.arpa.
+alerts.conduit-services.com.
+cdn.api.twitter.com.
+kualaterengganu.olx.com.my.
+10.240.7.50.in-addr.arpa.
+cdn.anastasiadate.com.
+a5.sphotos.ak.fbcdn.net.
+interactivos.lavanguardia.com.
+www.autodoc.ru.
+a6.sphotos.ak.fbcdn.net.
+ping.chartbeat.net.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+netlink.co.uk.
+serv.luch-pk.ru.
+waypt.com.
+get.adobe.com.
+74.9.95.190.in-addr.arpa.
+ersiko.ru.
+101.80.237.68.in-addr.arpa.
+a.root-servers.net.
+1.map.pop6.com.
+apis.google.com.
+ssl.gstatic.com.
+fuelcellsworks.com.
+a.root-servers.net.
+a.root-servers.net.
+www3.l.google.com.
+a5.sphotos.ak.fbcdn.net.
+166.148.144.187.in-addr.arpa.
+tools.google.com.
+tzlynnby.info.
+www.yo-auto.ru.
+227.110.171.187.in-addr.arpa.
+uniqsolutions.ru.
+t2.gstatic.com.
+95.181.87.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+107.167.226.189.in-addr.arpa.
+a.root-servers.net.
+143.149.134.186.in-addr.arpa.
+relay.voice.messenger.msn.com.
+123.cn.
+93.186.181.89.in-addr.arpa.
+rollshield.com.
+a8.sphotos.ak.fbcdn.net.
+members.allover30.com.
+www.hedgehogim.com.
+mail.rus01.ru.
+a.root-servers.net.
+clients1.google.com.
+lefima.net.
+messenger.services.live.com.
+c5.zedo.com.
+www.radio-electronics.com.
+www.ybonline.co.uk.
+thumbs.bondagester.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+218.180.82.200.in-addr.arpa.
+www.facebook.com.
+images.findthebestteens.com.
+www.tazaghiin.com.
+www.note4piano.com.
+a6.sphotos.ak.fbcdn.net.
+www.miningtopnews.com.
+messenger.vo.msecnd.net.
+136.92.6.189.in-addr.arpa.
+mail.carelsa.com.
+a.root-servers.net.
+connect.facebook.net.
+www.cuk.ch.
+57.197.39.46.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+121.223.84.200.in-addr.arpa.
+i1081.photobucket.com.
+220.54.106.186.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.foroclasico.com.
+superiorsoft.com.
+t.co.
+poppedculture.stumbleupon.com.
+65.216.141.79.in-addr.arpa.
+www.xntk.net.
+toolbar.zynga.com.
+sympatico.ca.
+scgi.ebay.com.
+checkip.dyndns.org.
+www.marykayintouch.com.mx.
+www.sorry.com.co.
+a.root-servers.net.
+a.root-servers.net.
+g.ceipmsn.com.
+api.partners.ezetop.com.
+54.90.14.186.in-addr.arpa.
+0bps664l3vqk05dj8qih0t5renri9iic.ig.ig.gmodules.com.
+onlinebizdirectory.com.
+a.tribalfusion.com.
+a.root-servers.net.
+mavericktv.co.uk.
+theschuckcorporation.com.
+rblns69.mailshell.net.
+www1.macys.com.
+www.facebook.com.
+static.ak.fbcdn.net.
+5ssc.com.
+a6.sphotos.ak.fbcdn.net.
+109.107.81.190.in-addr.arpa.
+a.root-servers.net.
+i.ytimg.com.
+214.186.187.79.in-addr.arpa.
+accounts.google.com.
+fresno.apartmenthomeliving.com.
+pbimail1.prodigy.net.
+csklegal.com.pri-mx.na0100.smtproutes.com.
+a.root-servers.net.
+179.149.102.218.in-addr.arpa.
+ad.app366.com.
+218.23.173.95.in-addr.arpa.
+www.tragamonedas-online.com.ar.
+clients2.google.com.
+hths.mcvsd.k12.nj.us.
+ponafotipuboduk.in.
+elrellano.com.
+i3.ytimg.com.
+61.231.252.72.in-addr.arpa.
+ilovemilkandcookies.blogspot.com.
+crl.microsoft.com.
+da.wikipedia.org.
+creative.ak.fbcdn.net.
+sionosexy.com.
+www.facebook.com.
+www.abc.es.
+www.multimediaboom.com.
+weightloss.about.com.
+c713352.r52.cf2.rackcdn.com.
+www.recettesdevalerie.com.
+football.frivcute.com.
+static.ak.fbcdn.net.
+ybinst3.ec.yimg.com.
+_237_57_7.
+a1108.da1.akamai.net.
+236.11.105.190.in-addr.arpa.
+drawdogg.blogspot.com.
+lilitmac.tumblr.com.
+29.media.tumblr.com.
+ismailia.ie-eg.com.
+a.root-servers.net.
+accounts.l.google.com.
+coloradocollege.edu.mail4.psmtp.com.
+photos-b.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+soultouchenterprisesllc.com.
+mariosonicgames.blogspot.com.
+www.hotmail-iniciarsesion.com.
+www.xtremetop100.com.
+click.infospace.com.
+3.13.93.115.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+fieldjerger.com.s7a2.psmtp.com.
+182.184.207.213.in-addr.arpa.
+koolatsafety.com.au.
+developers.facebook.com.
+www.google-analytics.com.
+zh-cn.facebook.com.
+weather.partners.msn.com.
+28.189.90.186.in-addr.arpa.
+www.flowhot.net.
+google.com.
+maps.google.es.
+mail.foss-as.no.
+mail.takneat.com.
+photos-a.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+tablero.ms.gba.gov.ar.
+accountservices.msn.com.
+t.invitemedia.com.
+kaskus.com.
+78.151.9.118.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+pix04.revsci.net.
+87.35.255.201.in-addr.arpa.
+www.diariodetuxpan.com.mx.
+167.230.109.83.in-addr.arpa.
+hpiintl.com.
+a771.da1.akamai.net.
+fab.at.
+ads.bluelithium.com.
+63.233.10.186.in-addr.arpa.
+_468_85_1.
+teredo.ipv6.microsoft.com.
+_174_62_2.
+htamerica.com.
+t2.gstatic.com.
+amer.rel.msn.com.
+150.226.44.200.in-addr.arpa.
+allisimpsonfans.com.
+images.compunoa.com.
+32.71.6.186.in-addr.arpa.
+devsgoons.com.
+232.78.240.189.in-addr.arpa.
+6.113.207.186.in-addr.arpa.
+gla1as50.aggrekonet.biz.
+photos-f.ak.fbcdn.net.
+www.googleadservices.com.
+login.live.com.
+news.google.com.mx.
+a.root-servers.net.
+a.root-servers.net.
+cdn6.liquidtelevision.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+hyperquan.com.
+m.addthisedge.com.
+209.90.251.190.in-addr.arpa.
+geo.tp-cdn.com.
+a.root-servers.net.
+xnd3dsf:u.75hx.
+karpovka.spb.ru.
+fandmbank.com.
+32.178.160.218.in-addr.arpa.
+external.ak.fbcdn.net.
+32.191.178.186.in-addr.arpa.
+db.local.clamav.net.
+135.209.251.190.in-addr.arpa.
+chi8yedhy.58gs.
+www.youtube.com.
+79.4.43.186.in-addr.arpa.
+platform.twitter.com.
+1066087.r.msn.com.
+www.bcba.sba.com.ar.
+a.root-servers.net.
+a.root-servers.net.
+plusone.google.com.
+moorti.org.ru.
+msfs.nspmotion.com.
+www.spokentoyou.com.
+transfer-net.ru.
+developers.facebook.com.
+websearch.ask.com.
+s01.divxden.com.
+23.56.101.187.in-addr.arpa.
+api-read.facebook.com.
+139.2.8.200.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+plus.google.com.
+static.ak.fbcdn.net.
+syndication.exoclick.com.
+16-courier.push.apple.com.
+live.com.
+www.whatsalary.com.
+mail.piedmontcsb.org.
+bmo.com.
+nabewise.com.
+www.google.com.
+tap2-cdn.rubiconproject.com.
+www.holisticmedicine.org.
+megatitan.ru.
+www.manhattanmedia.com.
+216.74.175.187.in-addr.arpa.
+brahms.ircam.fr.
+s-static.ak.fbcdn.net.
+es-la.facebook.com.
+s2.youtube.com.
+googleads.g.doubleclick.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ratings-wrs.symantec.com.
+srp.mtvn.com.
+safebrowsing.clients.google.com.
+s-static.ak.facebook.com.
+support.google.com.
+kurdish.sbeiy.com.
+uk.motoseller.com.
+_271_17_1.
+mx.yahoo.com.
+www.facebook.com.
+videos.softonic.com.
+mxico2022-2026.blogspot.com.
+253.115.49.190.in-addr.arpa.
+mail.autoinsuranceamerica.com.
+mdcontinentalconstruction.com.
+lovepredictions.net.
+www.150babes.com.
+a6.sphotos.ak.fbcdn.net.
+ns1.blink.ca.
+www.translate.google.es.
+static2.dmcdn.net.
+a7.sphotos.ak.fbcdn.net.
+i3.ytimg.com.
+books.google.com.mx.
+s0.2mdn.net.
+fupducktv.com.
+breath.net.
+mefas.com.
+.
+33.240.137.187.in-addr.arpa.
+www.youtube.com.
+connect.facebook.net.
+barnhartguess.com.
+yui.yahooapis.com.
+api.appshopper.com.
+www.vgf.com.
+194.52.139.98.combined.njabl.org.
+77.216.193.173.in-addr.arpa.
+hotmail.com.
+widgets.montiera.com.
+:sr1293gx.15yt.
+www.blogger.com.
+3ibe9g88l.47by.
+magazintravel.ru.
+jo4zfro63.77id.
+a8.sphotos.ak.fbcdn.net.
+dl-ssl.google.com.
+www.optionsclearing.com.
+248.196.226.190.in-addr.arpa.
+180.16.159.187.in-addr.arpa.
+download310.avast.com.
+bulrlrh14axe11gshtmwatm39kyn40ntg23gs.net.
+a-0.19-2709a081.99c0083.1518.19d2.3ea1.210.0.aktazdp51b34gma5pp33cfbhh5.avqs.mcafee.com.
+updatekeepalive.mcafee.com.
+142.8.122.190.in-addr.arpa.
+accounts.google.com.
+playmorfarm.com.
+vw2so4spb.j04k3f2x.
+api.gamatar.org.
+es.wikipedia.org.
+mrglaubitz.com.
+margotloyola.ucv.cl.
+www.wathakker.net.
+153.148.191.189.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+3.bp.blogspot.com.
+eventureevents.com.
+4food.ru.
+a.root-servers.net.
+r.mzstatic.com.
+197.45.160.187.in-addr.arpa.
+www.redpymes.org.ar.
+4minutos.es.
+photos-f.ak.fbcdn.net.
+cdcconinc.com.
+www.valinor.com.br.
+m.adnxs.com.
+creative.ak.fbcdn.net.
+73.139.130.12.bl.spamcop.net.
+www.miniclip.com.
+skydrive.live.com.
+i3.ytimg.com.
+porquesi.obolog.com.
+req.appads.com.
+gvntv.gvnstudio.com.
+it.kingdomhearts.wikia.com.
+blogacsessories.googlecode.com.
+pagead2.googlesyndication.com.
+95.196.203.190.in-addr.arpa.
+0-ih-w.channel.facebook.com.
+82.39.52.190.in-addr.arpa.
+e3191.c.akamaiedge.net.
+static-ak.vivastreet.com.
+igor.facemoods.com.
+crl.microsoft.com.
+ocsp.entrust.net.
+222.95.86.200.in-addr.arpa.
+aol.com.
+www.muzlife.com.
+pagead2.googlesyndication.com.
+www.google-analytics.com.
+renees.com.s200b2.psmtp.com.
+openx.wooga.com.
+cbs1.com.
+169.147.69.189.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+slb.liveprofile.com.
+80.249.228.189.in-addr.arpa.
+psp.ongames.com.
+bauer-at.com.
+linkhelp.clients.google.com.
+bahamas.com.
+photos-e.ak.fbcdn.net.
+b18azismxlxk67gviqf52o31n60d30k57f32eucw.com.
+www.facebook.com.
+ib.adnxs.com.
+217.13.216.15.in-addr.arpa.
+quintadoriodao.com.
+ns2.dialsprint.net.
+lospatosenlaluna.blogspot.com.
+img2.rexmag.net.
+yong0218.translatej.hop.clickbank.net.
+8.18.168.192.in-addr.arpa.
+granciasa.com.
+134.61.223.189.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+podcasts.yahoo.com.
+a4.sphotos.ak.fbcdn.net.
+www.nicholasrhea.co.uk.
+alerts.conduit-services.com.
+www.emadbaghi.com.
+169.96.69.87.in-addr.arpa.
+api.twitter.com.
+b.scorecardresearch.com.
+dentalsolo.ru.
+mail.ausonia.ru.
+clients1.google.com.
+morose.fotoplenka.users.photofile.ru.
+sp.search-results.com.
+www.sim.redee.com.
+safebrowsing.clients.google.com.
+235.3.161.189.in-addr.arpa.
+checkvist.com.
+a.root-servers.net.
+a.root-servers.net.
+dns.msftncsi.com.
+portal.ku.edu.kw.
+www.wikimediafoundation.org.
+www.rockrose.ca.
+a.root-servers.net.
+9.162.14.181.in-addr.arpa.
+dr._dns-sd._udp.lan.
+www.orc.ru.
+mail.arquetipopublicidad.net.
+78.123.180.189.in-addr.arpa.
+coca.com.
+53.194.33.187.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+69.184.188.190.in-addr.arpa.
+cbdengineering.com.
+203.34.52.71.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+vnxsolutions.com.
+dipproject.ru.
+120.223.173.190.in-addr.arpa.
+google.com.
+pretty-ditty.blogspot.com.
+49.247.156.189.in-addr.arpa.
+images01.olx.com.co.
+static.ak.fbcdn.net.
+media.fastclick.net.
+www.google.com.
+a1.sphotos.ak.fbcdn.net.
+definicion.de.
+filtre.chuq.qc.ca.
+click.email.nlg.com.
+199.67.59.186.in-addr.arpa.
+kemont.ru.
+mts-k.ru.
+db._dns-sd._udp.lan.
+.
+51.150.95.201.in-addr.arpa.
+a-0.19-a30f7000.c070081.1518.19d4.3ea1.410.0.tzin1lvkubqbfgzgrbj44qlek5.avqs.mcafee.com.
+videos.videopress.com.
+www.psrd.hawaii.edu.
+www.bancofrances.com.ar.
+alb3d.maktoobblog.com.
+profile.ak.fbcdn.net.
+tags.expo9.exponential.com.
+www.techopinions.com.
+sp.cwfservice.net.
+a.c-0.19-a309a081.c870082.1518.19d4.3ea1.210.0.gprbcpw39smc9azb9c4cbskdkq.avqs.mcafee.com.
+macabre.ru.
+a.root-servers.net.
+creative.ak.fbcdn.net.
+api.conduit.com.
+cbswzgc.files.wordpress.com.
+s-static.ak.facebook.com.
+games.m7shsh.com.
+trackermo.com.
+www.mozilla.org.
+mail.ekoteks.ru.
+microsoft-word-2011.softonic.pl.
+google.com.
+api.facebook.com.
+213.48.146.187.in-addr.arpa.
+a.root-servers.net.
+a1725.l.akamai.net.
+efacebook.in.
+apps.facebook.com.
+www.circuloastronomico.cl.
+cache.pack.google.com.
+www.facebook.com.
+developers.facebook.com.
+www.belkin.com.
+securepubads.g.doubleclick.net.
+safebrowsing-cache.google.com.
+s10.histats.com.
+dsw.quik.com.
+99.50.173.190.in-addr.arpa.
+lh5lrh2ks.g78z5q4a.
+4.113.205.189.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+bl163w.blu163.mail.live.com.
+m2.nsimg.net.
+a3.sphotos.ak.fbcdn.net.
+cdn.api.twitter.com.
+photos-h.ak.fbcdn.net.
+habeby.com.
+quidestveritas07.blogspot.com.
+vacacionesbook.com.
+cuervo-negro.blogspot.com.
+glquery.blackberry.com.
+195.171.58.82.in-addr.arpa.
+mscrl.microsoft.com.
+static.ak.fbcdn.net.
+www.hotmetart.com.
+safebrowsing.clients.google.com.
+yellowsurveys.com.
+www.vinculame.com.
+tienda.youcel.com.
+bluepearl-skins.com.
+www.canadianmedsworld.org.
+twitter.com.
+www.godlygamez.com.
+www.kasperskylab.co.kr.
+bigbloger.lidovky.cz.
+dns.msftncsi.com.
+90.66.223.189.in-addr.arpa.
+www.proveedoresturisticos.com.mx.
+image01.videobox.com.
+253.30.30.186.in-addr.arpa.
+www.grabonebottle.co.nz.
+kriss.re.kr.
+27.231.237.189.in-addr.arpa.
+pegasustransfers.com.au.
+www.ptcbox.com.
+i1.ytimg.com.
+www.fotonostra.com.
+www.gordosnuncamas.blogspot.com.
+secure.wlxrs.com.
+lolieroidol.blog79.fc2.com.
+a3.sphotos.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+www.sexfg.com.
+solar-m.ru.
+ad.yieldmanager.com.
+mail.cti.com.
+a.root-servers.net.
+www.google.com.
+odcdance.org.
+partner.googleadservices.com.
+mail.evyap.com.tr.
+www.facebook.com.
+www.opendi.mx.
+msdxmlc.dll.
+clients1.google.com.
+download.windowsupdate.com.
+profile.ak.fbcdn.net.
+mail.google.com.
+wuostc.com.
+www.aspirateur-silencieux.fr.
+www.playingbythebook.net.
+apis.google.com.
+static.muslimadnetwork.com.
+static.ak.fbcdn.net.
+synexches.synerfac.com.
+es-la.facebook.com.
+twitter.com.
+www.youtube.com.
+www.plasticsportal.net.
+static.ak.connect.facebook.com.
+time.windows.com.
+www.ehbonline.org.
+85.51.1.181.in-addr.arpa.
+jimsmash.blogspot.com.
+i2.cdn.turner.com.
+www.elorientalonline.com.
+www.televox.com.
+plus.google.com.
+131.203.177.187.in-addr.arpa.
+61.25.31.95.in-addr.arpa.
+242.129.33.187.in-addr.arpa.
+d1aivi5dp2wry5.cloudfront.net.
+storage.conduit.com.
+salud.latam.msn.com.
+switchboard.real.com.
+creative.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+coolberman.wordpress.com.
+e3353.c.akamaiedge.net.
+securesignupoffers.net.
+www.pigtronix.com.
+blackozil.blogspot.com.
+.
+60.36.153.190.in-addr.arpa.
+emediate.apmmedia.net.
+cm5.esignal.com.
+smsshkola.ru.
+a2.sphotos.ak.fbcdn.net.
+osrah.net.
+clients1.google.com.
+www.diamondcs.com.au.
+intervale.com.
+townandcountryproperties.com.
+simoncaleb.com.
+63.74.237.189.in-addr.arpa.
+babinbuildingsolutions.com.
+50-57-46-243.static.cloud-ips.com.
+developers.facebook.com.
+en-us.fxfeeds.mozilla.com.
+www.edovia.com.
+www.dailymotion.com.
+242.129.244.201.in-addr.arpa.
+208.97.84.200.in-addr.arpa.
+europe.com.
+a.root-servers.net.
+www.facebook.com.
+ddb.fr.s7b2.psmtp.com.
+planeta.gul.es.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+providian.com.
+211.123.225.78.in-addr.arpa.
+ma10104.computerhaus.net.
+pixel.facebook.com.
+couponbuddy.s3.amazonaws.com.
+abswa.com.
+bit.ly.
+photos-b.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+ec.atdmt.com.
+th4.theteenest.com.
+newmachine.com.
+125.100.233.76.in-addr.arpa.
+www.medicentro.com.co.
+images.intellitxt.com.
+www.odioentrenar.com.
+static.ak.fbcdn.net.
+:7gnvfxuw.k20q6a5l.
+hindi.babylon.com.
+www.modern-styles.net.
+www.okc.cc.ok.us.
+baxterlaw.com.
+parrotsociety.org.au.
+www.youtube-nocookie.com.
+www.google-analytics.com.
+gemini.com.
+171.146.55.87.in-addr.arpa.
+time.windows.com.
+comfitel.ru.
+m.facebook.com.
+corbettresearch.com.
+accounts.google.com.
+www.square-enix.co.jp.
+a1408.w43.akamai.net.
+www.gerardo-perez.com.ar.
+static.exoclick.com.
+94.130.242.212.in-addr.arpa.
+insidetrackcoaching.com.s5a1.psmtp.com.
+wolfblock.com.mx1.electric.net.
+www.lingopal.com.
+plus.google.com.
+www.facebook.com.
+accounts.google.com.
+mail2.demo-hmc.com.ar.
+188.92.220.189.in-addr.arpa.
+gayastrology.blogspot.com.
+175.236.127.201.in-addr.arpa.
+imgburn.softonic.cn.
+www.123jump.co.uk.
+www.gmg-entertainment.com.
+spajardin.com.
+www.editorialtaurus.com.
+echo.edge.messenger.live.com.
+api.geo.kontagent.net.
+sp.search-results.com.
+a5.sphotos.ak.fbcdn.net.
+live.gnome.org.
+s0.2mdn.net.
+static.ak.fbcdn.net.
+ax.init.itunes.apple.com.
+www.juntaflorida.gub.uy.
+static.ak.fbcdn.net.
+arch.inkom.ru.
+88.76.160.189.in-addr.arpa.
+www.tripadvisor.es.
+_ldap._tcp.
+sp.cwfservice.net.
+16.204.61.67.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+33.22.137.201.in-addr.arpa.
+228.113.166.178.in-addr.arpa.
+loading1.widdit.com.
+press.absolut.com.
+www.campus3deducacion.com.
+matroska-pack-full.softonic.com.
+www.bairesgirls.net.
+download337.avast.com.
+inotify.live.net.
+a2.twimg.com.
+a.root-servers.net.
+login.toolbar.conduit-services.com.
+116.28.178.186.in-addr.arpa.
+pagead2.googlesyndication.com.
+b-0.19-a3001008.41081.1518.19d4.3ea1.410.0.2rpliwfdaimtdteu1ia7bwlbsq.avqs.mcafee.com.
+www.honeymoonersreviewguide.com.
+googleads.g.doubleclick.net.
+www.piter-press.ru.
+ssl.gstatic.com.
+ajax.googleapis.com.
+js.blinkadr.com.
+clipat.maktoob.com.
+help.freephpbb3.com.
+darveylitho.com.
+mail.pcexchange.net.
+capgemini.ru.
+www.penesgays.com.ar.
+www.kaossoftwear.com.
+a.root-servers.net.
+www.travian.gr.
+profile.ak.fbcdn.net.
+b-0.19-23058479.10081.1518.19d4.2f4a.210.0.lwchdlgbpnlvjj7ass77a8nrvt.avqs.mcafee.com.
+photos-c.ak.fbcdn.net.
+www.nuvet.com.
+apmkzodsq.p63l7j9c.
+pixel.facebook.com.
+ad.yieldmanager.com.
+a.root-servers.net.
+www.vitralesexclusivos.com.ar.
+www.gstatic.com.
+184.21.238.83.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+ad.doubleclick.net.
+client.akamai.com.
+i2.ytimg.com.
+de.hyperionics.com.
+dns.msftncsi.com.
+external.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+www.myhabit.com.
+squote.yuanta.com.tw.
+130.120.166.190.in-addr.arpa.
+digitalcuttlefish.blogspot.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+prosportshop.ru.
+8okjz1wzv.v71w6n6r.
+sochs.com.
+profile.ak.fbcdn.net.
+31.145.170.189.in-addr.arpa.
+warez-bb.org.
+b-0.19-2200a008.11081.1518.19d3.3ea1.410.0.v1a2qe64ph7fk7393unb8z6wlb.avqs.mcafee.com.
+www.firefox.ro.
+3dedp2zth.u63z8z0p.
+sla.com.s9b1.psmtp.com.
+teredo.ipv6.microsoft.com.
+ad.jumbaexchange.com.
+showadsak.pubmatic.com.
+www.facebook.com.
+ajax.googleapis.com.
+img534.imageshack.us.
+rsconsultants.co.uk.
+clients4.google.com.
+s.youtube.com.
+112.169.123.190.in-addr.arpa.
+4121518.frasesinolvidables1.com.ar.
+imagesak.wildwestdomains.com.
+www.bloopdigital.com.
+api-read.facebook.com.
+www.google.com.
+.
+www.yahoo.com.
+birdingpal.org.
+150.25.102.201.in-addr.arpa.
+s.youtube.com.
+tcpv2.easythumbhost.com.
+dns.msftncsi.com.
+clients1.google.com.
+120.86.130.189.in-addr.arpa.
+it-it.facebook.com.
+blog.stata.com.
+calendar.live.com.
+news.google.com.mx.
+reimanpub.com.s9a1.psmtp.com.
+checkip.dyndns.com.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+connect.facebook.net.
+ssl.gstatic.com.
+86.19.176.190.in-addr.arpa.
+a.root-servers.net.
+qcc.com.sa.
+www.agava.ru.
+profile.ak.fbcdn.net.
+cdn.loading321.com.
+api.facebook.com.
+webcache.googleusercontent.com.
+170.93.249.201.in-addr.arpa.
+shocktune.com.
+79.192.57.186.in-addr.arpa.
+api.openfeint.com.
+238.66.36.176.in-addr.arpa.
+cookisgood.blogspot.com.
+www.google.com.
+content-1.emagistercdn.com.
+mihran.com.
+afproteinpharmaceuticals.com.
+37.7.130.27.in-addr.arpa.
+stun.client.akadns.net.
+uwrrwmxeexlrmwo.net.
+ardry.com.
+www.watchesseek.com.
+m5.eastlink.ca.
+176.162.126.84.in-addr.arpa.
+70.5.75.50.in-addr.arpa.
+www.el-ladies.com.
+checkip.dyndns.org.
+177.71.173.70.in-addr.arpa.
+t0.gstatic.com.
+msgr.updates.yahoo.com.
+edit.yahoo.com.
+telus.net.
+a7.sphotos.ak.fbcdn.net.
+221.6.62.186.in-addr.arpa.
+densho.com.mx.
+teredo.ipv6.microsoft.com.
+jers3.info.
+a.root-servers.net.
+187.207.145.187.in-addr.arpa.
+mail.iqpuzzles.com.
+webofdebt.wordpress.com.
+evt.collarity.com.
+smtp.sherbtel.net.
+homepages.luc.edu.
+www.digimonmasters.org.
+mail.chmelik.com.
+yaminoyukihime.blogspot.com.
+simple.wikipedia.org.
+beardedmagazine.co.uk.
+depositfiles.com.
+a.root-servers.net.
+dnl-16.geo.kaspersky.com.
+futsal1930.blogspot.com.
+dzoom.org.es.
+massivepress.com.
+wawick.net.
+crl.microsoft.com.
+129.72.131.187.in-addr.arpa.
+plusone.google.com.
+static.ak.fbcdn.net.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+r._dns-sd._udp.home.
+www.weather.gov.
+www.sptechs.com.
+_kerberos._tcp.dc._msdcs.la.jnj.com.
+i3.sinaimg.cn.
+4.148.175.190.in-addr.arpa.
+pics1.pof.com.
+profile.ak.fbcdn.net.
+231.49.235.190.in-addr.arpa.
+cdn2.widdit.com.
+d1ros97qkrwjf5.cloudfront.net.
+a1505.l.akamai.net.
+slfusco.com.inbound30.mxlogic.net.
+dns.msftncsi.com.
+www.adobe.com.
+mail.autopick.com.
+a2.sphotos.ak.fbcdn.net.
+clients1.google.com.
+support.google.com.
+www.melsdrive-in.com.
+ds.addthis.com.
+ssl.gstatic.com.
+www.textsrv.com.
+mthigh.com.
+i4.ytimg.com.
+safebrowsing.clients.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+7db1t4r::.21ac.
+blankizdat.ru.
+ipod4ladies.wordpress.com.
+ssl.gstatic.com.
+a.root-servers.net.
+iejaor.com.
+www.quehoroscopo.com.
+www.google.com.mx.
+profile.ak.fbcdn.net.
+www.pensacolaciviccenter.com.
+api.facebook.com.
+radley.me.uk.
+cerca.unita.it.
+aaaga.com.
+support.google.com.
+a7.sphotos.ak.fbcdn.net.
+utstarcom.ru.
+a.root-servers.net.
+www.addthis.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+_272_37_4.
+a.root-servers.net.
+23.99.51.190.in-addr.arpa.
+ksn3-12.part1.kaspersky-labs.com.
+o-o.preferred.atl14s01.v23.lscache8.c.youtube.com.
+i1.ytimg.com.
+classicrr.com.s8b1.psmtp.com.
+thumbs1.wetgrannysex.com.
+11.39.18.190.in-addr.arpa.
+203.113.214.189.in-addr.arpa.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+212.51.168.192.in-addr.arpa.
+platform.twitter.com.
+i0.ifrype.com.
+www.ramirezcuevas.es.
+tracker.stigalaria.org.
+www.facebook.com.
+profile.ak.fbcdn.net.
+www.zionrootswear.com.
+yhioo.com.
+otfs.net.
+pt-br.facebook.com.
+photos-b.ak.fbcdn.net.
+31-courier.push.apple.com.
+a7.sphotos.ak.fbcdn.net.
+zaitcev.mee.nu.
+77.233.52.216.in-addr.arpa.
+www.iwsmile.it.
+js.wlxrs.com.
+plus.google.com.
+puertyxdvud.info.
+50.51.173.201.in-addr.arpa.
+a.root-servers.net.
+struer.dk.
+ancalayoli.blogspot.com.
+219.131.34.186.in-addr.arpa.
+ncree.org.
+profile.ak.fbcdn.net.
+1.2.168.192.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+a1174.g.akamai.net.
+153.137.231.189.in-addr.arpa.
+mail.
+132.243.230.201.in-addr.arpa.
+www.registrar.psu.edu.
+rydata-a.akamaihd.net.
+news.mtgir.com.
+www.google.com.
+e5016.b.akamaiedge.net.
+i3.ytimg.com.
+images.hi5.com.
+u21.eset.com.
+104.126.92.201.in-addr.arpa.
+yui.yahooapis.com.
+grupozawa.com.
+165.85.192.190.in-addr.arpa.
+partner.googleadservices.com.
+www.download.windowsupdate.com.
+miangelitoespecial.blogspot.com.
+support.google.com.
+61.18.110.123.in-addr.arpa.
+e4344.g.akamaiedge.net.
+a.root-servers.net.
+www.google-analytics.com.
+28.175.186.189.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+136.133.55.189.in-addr.arpa.
+em1x-278.lhr.messaging.nokia.com.
+www.facebook.com.
+pixel.facebook.com.
+adlog.com.com.
+191.83.26.201.in-addr.arpa.
+s2.youtube.com.
+pxahzae6r.15sr.
+126.235.82.186.in-addr.arpa.
+a.root-servers.net.
+static.ak.fbcdn.net.
+www.poni.ca.
+secure.cbtnuggets.com.
+183.106.236.186.in-addr.arpa.
+www.gstatic.com.
+29.161.115.186.in-addr.arpa.
+external.ak.fbcdn.net.
+www.thereis.co.uk.
+tap2-cdn.rubiconproject.com.
+mail.yimg.com.
+www.google-analytics.com.
+www.youtube.com.
+42.153.143.201.in-addr.arpa.
+myweb.vodafone.co.uk.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+ratings-wrs.symantec.com.
+loading7.widdit.com.
+www.nmm.ac.uk.
+a.root-servers.net.
+ad.doubleclick.net.
+pagead2.googlesyndication.com.
+z-ecx.images-amazon.com.
+www.juegos-autos.com.
+156.125.142.189.in-addr.arpa.
+www.google-analytics.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+platform.twitter.com.
+a.tribalfusion.com.
+_334_96_3.
+ads.iforex.com.
+43.99.156.187.in-addr.arpa.
+78.157.200.98.in-addr.arpa.
+21.143.194.187.in-addr.arpa.
+www.google-analytics.com.
+www.juegosgratis1x.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+80.188.221.67.in-addr.arpa.
+appleglobal.112.2o7.net.
+e.f.f.f.f.f.f.f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.f.f.ip6.arpa.
+carbofer.ru.
+a7.sphotos.ak.fbcdn.net.
+translate.google.com.mx.
+mail.rabotagrad.ru.
+toolbarqueries.clients.google.com.
+7.97.24.203.in-addr.arpa.
+187.163.145.189.in-addr.arpa.
+www.nytimes.com.
+89.55.36.174.in-addr.arpa.
+unicam-studio.ru.
+fbcdn-photos-a.akamaihd.net.
+www.missindonesia.co.id.
+10.237.39.190.in-addr.arpa.
+cnfg.funmoods.com.
+apis.google.com.
+unesco.com.
+sb8z44iyo.k70w5x1y.
+230.240.133.189.in-addr.arpa.
+chat.facebook.com.
+domnapogrebah.ru.
+a.root-servers.net.
+158.60.207.200.in-addr.arpa.
+.
+www.kentelectricalservices.com.
+android.clients.google.com.
+ar.answers.yahoo.com.
+www.gstatic.com.
+mouse.latercera.cl.
+www.mundohogar.com.
+babystrology.com.
+developers.facebook.com.
+7794ietim.x15n4z7x.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+leetufrase.com.
+cdn1.widdit.com.
+cf.addthis.com.
+thumbs1.ebaystatic.com.
+62.28.94.189.in-addr.arpa.
+brambles.com.s5b2.psmtp.com.
+www.mezee.me.
+www.angelfire.com.
+js.adsonar.com.
+blogtuembarazo.com.
+mail.karavelle.co.uk.
+external.ak.fbcdn.net.
+b-0.19-230c3479.81.1518.19d4.3ea1.410.0.1mpgha3eadg4cnkstpgnth3v86.avqs.mcafee.com.
+wwwimages.adobe.com.
+10.216.22.186.in-addr.arpa.
+dsa411.com.
+apps.facebook.com.
+221.221.15.76.in-addr.arpa.
+swa.mail.ru.
+partners.gallery.live.com.
+zebarthadvisors.com.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+tavernrestaurantgroup.com.
+sp.ask.com.
+ogier.com.
+search-cdn.walmart.com.
+att.com.
+boxmail.spb.ru.
+photographytreasure.com.
+www.hawanaajd.com.
+static.ak.fbcdn.net.
+facebook.com.
+sp.cwfservice.net.
+a.root-servers.net.
+www.voiceboks.com.
+apis.google.com.
+a.root-servers.net.
+:os11aman.z59u0d0w.
+v14.nonxt6.c.youtube.com.
+www.googleadservices.com.
+pixel.33across.com.
+www.vivirguadalajara.com.
+www.quantenwelt.de.
+bay.messenger.services.live.com.
+delirios-anonimos.blogspot.com.
+www.paintbits.com.
+228.95.119.99.in-addr.arpa.
+25.media.tumblr.com.
+mvs.com.mx.
+www.smutblaster.com.
+a.root-servers.net.
+www.moneytalkvillage.com.
+2.gvt0.com.
+c0058712.cdn.cloudfiles.rackspacecloud.com.
+187.112.173.88.in-addr.arpa.
+a.root-servers.net.
+96.224.241.201.in-addr.arpa.
+rcp.na.blackberry.com.
+a.root-servers.net.
+storage.conduit.com.
+107.68.148.88.in-addr.arpa.
+129.151.127.201.in-addr.arpa.
+mx2.balanced.homie.mail.dreamhost.com.
+qc1dlpkvw.43yc.
+plusone.google.com.
+24.233.73.200.in-addr.arpa.
+mcfarlandarchitects.com.
+grafos.softonic.com.
+60.199.137.70.in-addr.arpa.
+a.root-servers.net.
+223.173.175.187.in-addr.arpa.
+grubees.aliexpress.com.
+zh-cn.facebook.com.
+carlcox.com.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+mail.kolaregion.ru.
+seexycams3.da.ru.
+sb2573.ru.
+204.93.139.187.in-addr.arpa.
+www.bombasindustriales.cl.
+rs702l35.rapidshare.com.
+php.hdcmct.com.
+b-0.19-a7096008.8030081.1518.19ce.3ea1.410.0.rpsti6q8dj1qv7cger6ab8s5fq.avqs.mcafee.com.
+a.root-servers.net.
+179.wap517.org.
+150.213.209.189.in-addr.arpa.
+www.varelaenred.com.ar.
+docs.google.com.
+185.255.150.99.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+www.manga-access.com.
+ensenadagotico.blogspot.com.
+farm3.static.flickr.com.
+mail.jgua.com.
+102.39.154.187.in-addr.arpa.
+dns.msftncsi.com.
+um12.eset.com.
+ad.yieldmanager.com.
+125.166.129.95.in-addr.arpa.
+del.icio.us.
+mx.f1123.mail.yahoo.com.
+197.21.1.181.in-addr.arpa.
+www.juegosdemates.com.
+techrepublic.custhelp.com.
+faculty.deanza.fhda.edu.
+fbnffb.s3.amazonaws.com.
+230.116.1.201.in-addr.arpa.
+a1831.g.akamai.net.
+apis.google.com.
+gsbflavorcreators.com.s8b1.psmtp.com.
+profile.ak.fbcdn.net.
+i3.ytimg.com.
+124.8.241.201.in-addr.arpa.
+171.79.216.186.in-addr.arpa.
+120.79.125.74.in-addr.arpa.
+www.vegetomania.com.
+www.chinabusinessworld.com.
+panatweb.com.
+76.93.106.186.in-addr.arpa.
+cdn.blogsmasterd.com.
+profile.ak.fbcdn.net.
+www.blogger.com.
+86.31.73.189.in-addr.arpa.
+75.9.19.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+styleflat.ru.
+harsco.com.
+clients1.google.com.
+pro-team.com.s7a1.psmtp.com.
+urs.microsoft.com.
+rsi.hotmail.com.
+218.182.5.189.in-addr.arpa.
+sherman-associates.com.inbound15.mxlogicmx.net.
+jetstreamwireless.com.
+amfbakery.com.
+photos-g.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+42.153.122.69.in-addr.arpa.
+110.172.185.190.in-addr.arpa.
+creative.ak.fbcdn.net.
+pagead.l.doubleclick.net.
+saledrug.info.lan.
+guitartricks.us1.list-manage.com.
+photos-a.ak.fbcdn.net.
+kb.cyberoam.com.
+www.endotext.com.
+232.216.210.201.in-addr.arpa.
+15.149.220.66.in-addr.arpa.
+a.root-servers.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+69.168.161.200.in-addr.arpa.
+pixel.quantserve.com.
+tracker.mightynova.com.
+www.weather.com.
+mxbackup.mail.sysonline.net.
+6965y6kzp.p06j1f5v.
+121.45.109.79.in-addr.arpa.
+jt2im267w.w33k1y7h.
+www.4ureyesonly.com.
+www.facebook.com.
+www.shoesofyourdreams.com.
+gday.ru.
+photos-c.ak.fbcdn.net.
+tv.msn.com.
+www.facebook.com.
+ja-jp.facebook.com.
+graph.facebook.com.
+argus-spectrum.ru.
+www.accountmarket.com.
+mkgallery.com.
+www.thewhiteribbon.co.uk.
+m.google.com.
+www.gmail.com.
+content.yieldmanager.edgesuite.net.
+a.root-servers.net.
+a.root-servers.net.
+.
+234.154.138.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+8.17.189.99.in-addr.arpa.
+frontal1.erenis.fr.
+time.nist.gov.
+videotronres.112.2o7.net.
+lasa.com.
+justin.multimedios.tv.
+dns.msftncsi.com.
+www.blogrelaciones.com.
+rs11tl4.rapidshare.com.
+tag.admeld.com.
+tools.google.com.
+www.google.com.
+www.thecharityhive.ca.
+4.bp.blogspot.com.
+fas.fr.
+mobile.papi.com.
+jruby.org.
+osl.ugr.es.
+profile.ak.fbcdn.net.
+www.edenred.es.
+firstmomtube.com.
+gw.roma.ua.
+sites.google.com.
+www.cuidadospediatricos.blogspot.com.
+107.173.107.186.in-addr.arpa.
+gfx1.hotmail.com.
+www.paxnet.co.kr.
+nainashville-com.mail.eo.outlook.com.
+a4.sphotos.ak.fbcdn.net.
+www.facebook.com.
+ppo1l9gbl.48hc.
+68.187.214.189.in-addr.arpa.
+csi.gstatic.com.
+mail.lbsglobal.com.
+www.mediasyndicate.in.
+org.mx.
+alilahotels.com.
+apis.google.com.
+a.root-servers.net.
+julianred.lookbook.nu.
+sonics.ru.
+mail.google.com.
+photos-f.ak.fbcdn.net.
+gcg.com.
+evolutiongroupfl.com.
+profile.ak.fbcdn.net.
+vega-h.ru.
+rs210tl4.rapidshare.com.
+graph.facebook.com.
+www.techsutram.com.
+www.google.com.
+97.46.184.89.in-addr.arpa.
+rostovauto.ru.
+creatupropiamoda.com.
+my.mail.ru.
+api.zynga.com.
+www.wordreference.com.
+19.224.171.69.in-addr.arpa.
+api.conduit.com.
+hyatts.com.
+ferroesquevedos.blogspot.com.
+cs.picjoke.net.
+es.wikipedia.org.
+aaamiamicounty.com.
+2kgam.es.
+external.ak.fbcdn.net.
+0-jg-w.channel.facebook.com.
+74.30.249.190.in-addr.arpa.
+tvfacebook.lge.com.
+h.live.com.
+s2.youtube.com.
+_885_08_4.
+primestaffusa.com.
+profile.ak.fbcdn.net.
+kusanagigirlbeautyblog.blogspot.com.
+d3j5vwomefv46c.cloudfront.net.
+www.skypesexcontacts.com.
+fc.cps.edu.
+citigateaf.com.
+www.pixgateway.com.
+dcscontracting.com.bak-mx.na0100.smtpbak.com.
+multiplayergamescom.skimlinks.com.
+external.ak.fbcdn.net.
+cumeaters.33men.com.
+pixel.facebook.com.
+todoesfarandula.bligoo.com.
+ssl.gstatic.com.
+49.38.133.115.in-addr.arpa.
+multimedia.getresponse.com.
+www.vuelo-digital.org.
+www-cctld.l.google.com.
+vcontent.ebuddy.com.
+mail.cbopc.com.
+unoracing.com.
+98.images22.51img1.com.
+derribosbajoelagua.blogspot.com.
+www.annabean.com.
+2.213.10.109.in-addr.arpa.
+thumbnails2.imagebam.com.
+www.osundefender.org.
+223.178.230.88.in-addr.arpa.
+hwzgjh4my.l08z4w0e.
+ocsp.digicert.com.
+mail.hiellesmereport.com.
+www.bing.com.
+www.siteadvisor.com.
+27.135.15.186.in-addr.arpa.
+notebooklaptopsreview.blogspot.com.
+75.157.127.201.in-addr.arpa.
+164.126.3.187.in-addr.arpa.
+blackhole.theglobe.com.
+ads.crakmedia.com.
+spysee.jp.
+www.gala-marketlaw.com.
+123.187.194.94.in-addr.arpa.
+85.225.69.77.in-addr.arpa.
+a.root-servers.net.
+wallet.google.com.
+mbakercorp.com.
+www.highdefedition.com.
+www.googletagservices.com.
+arthritis.uphero.com.
+www.detododormitorios.com.
+mailext1.mh-hannover.de.
+mail.wba-architects.com.
+cnt1.xhamster.com.
+www.nowhereelse.fr.
+tc.v11.cache5.c.youtube.com.
+dns.msftncsi.com.
+mail.atbm.ru.
+thevintagevalley.blogspot.com.
+105.196.188.189.in-addr.arpa.
+140.232.171.69.sbl-xbl.spamhaus.org.
+bp3.blogger.com.
+www.twitter.com.
+eh35zk:zq.00tn.
+0-68.channel.facebook.com.
+usebrinks.com.
+sqm.microsoft.com.
+player.vimeo.com.
+w.sharethis.com.
+profile.ak.fbcdn.net.
+legendarioantartico.blogspot.com.
+a4.sphotos.ak.fbcdn.net.
+freeangrybirdsgames.info.
+168.218.243.189.in-addr.arpa.
+external.ak.fbcdn.net.
+static.ak.fbcdn.net.
+resolver1.pand.ctmail.com.
+external.ak.fbcdn.net.
+99.152.182.189.in-addr.arpa.
+ratco.ru.
+www.google.com.
+ads.adxpose.com.
+adventurgraphics.blogspot.com.
+www.expressio.fr.
+linkhelp.clients.google.com.
+www.bigbreastchest.com.
+cdn.gigya.com.
+www.a-n.co.uk.
+a5.sphotos.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+i.blogads.com.
+www.4shared.com.
+thewillows.org.
+netmail.verizon.com.
+252.150.38.190.in-addr.arpa.
+www.facebook.com.
+224.30.125.95.in-addr.arpa.
+11.41.241.201.in-addr.arpa.
+smtp.bedsonline.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+reactnetwork.com.
+www.brspecialtuning.co.uk.
+a.root-servers.net.
+spancp.com.
+tags.expo9.exponential.com.
+www.linkstoislam.com.
+37.160.144.187.in-addr.arpa.
+145.54.26.80.in-addr.arpa.
+a1404.w41.akamai.net.
+www.facebook.com.
+11.34.11.190.in-addr.arpa.
+a1.twimg.com.
+8.251.125.79.in-addr.arpa.
+feeds.bbci.co.uk.
+177.44.194.187.in-addr.arpa.
+www.gas2.org.
+voipa.sip.yahoo.com.
+www.aclam.org.
+www.slowandsteadywinstherace.com.
+a550.g.akamai.net.
+external.ak.fbcdn.net.
+crl3.digicert.com.
+rerecognition.com.
+gupran.ru.
+external.ak.fbcdn.net.
+104.152.161.190.in-addr.arpa.
+238.49.253.201.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+_953_66_8.
+t2.gstatic.com.
+72.251.56.178.in-addr.arpa.
+mapas.guiadeuruguay.com.
+cityofmadera.ca.us.
+blogs.ancestry.com.
+149.118.143.189.in-addr.arpa.
+82.114.125.84.in-addr.arpa.
+assets.tumblr.com.
+www.yahoo.com.
+developers.facebook.com.
+wnsemergent.com.
+scribd.com.
+youtu.be.
+heymrswilson.net.
+gms.gdl.jp.
+vgs.com.
+www.freespiritualways.com.
+fbcdn-photos-a.akamaihd.net.
+photos-a.ak.fbcdn.net.
+22.191.22.186.in-addr.arpa.
+master7.teamviewer.com.
+download.windowsupdate.com.
+submitshop.com.
+photos-b.ak.fbcdn.net.
+pilu.it.
+coursyoga.net.
+lamington.wordpress.com.
+wheresmysammich.com.
+ajax.googleapis.com.
+photos-d.ak.fbcdn.net.
+apps.facebook.com.
+208.86.206.190.in-addr.arpa.
+161.172.118.70.in-addr.arpa.
+www.therespawnarmy.com.
+38.132.129.186.in-addr.arpa.
+www.hotchickswithdouchebags.com.
+dr._dns-sd._udp.lan.
+l.yimg.com.
+epistemologadelacomunicacion.blogspot.com.
+www.solotodo.net.
+w73k1ha18.55wt.
+im1.gulfup.com.
+d6537b.ess.barracudanetworks.com.
+news.google.com.mx.
+j5ituddlr.u55e5e3r.
+profile.ak.fbcdn.net.
+www.travian.ma.
+creative.ak.fbcdn.net.
+ib.adnxs.com.
+twitter.com.
+_300_37_2.
+124.214.169.88.in-addr.arpa.
+ssl.gstatic.com.
+twitter.com.
+www.turismolitoral.cl.
+250.186.124.186.in-addr.arpa.
+www.zonaktolica.com.ar.
+juris.su.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+platform.twitter.com.
+router.infolinks.com.
+apostoladoeucaristico.blogspot.com.
+xnx.ru.
+www.desotosport.com.
+2.198.109.187.in-addr.arpa.
+olympiarealestate.com.
+215.251.223.87.in-addr.arpa.
+img141.imageshack.us.
+blog.houstontexans.com.
+pbr670.photobucket.com.
+www.dailymail.co.uk.
+t0.gstatic.com.
+dtvyuk.com.
+f.chtah.com.
+chuletas.rincondelvago.com.
+direct2.anhso.net.
+billing.sharo4ka.ru.
+fbcdn-photos-a.akamaihd.net.
+22.101.172.190.in-addr.arpa.
+a.root-servers.net.
+th.y8.com.
+a3.sphotos.ak.fbcdn.net.
+bloog.pl.
+www.youtube.com.
+mi.adinterax.com.
+go2.com.
+40.162.126.84.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+a995.mm1.akamai.net.
+ocsp.godaddy.com.
+pubads.g.doubleclick.net.
+ee.net.s6a2.psmtp.com.
+30.43.58.201.in-addr.arpa.
+161.9.150.187.in-addr.arpa.
+mtalk.google.com.
+89.55.36.174.in-addr.arpa.
+comic.dl.playstation.net.
+a.root-servers.net.
+160.17.161.189.in-addr.arpa.
+www.loudguitars.com.
+dr._dns-sd._udp.lan.
+es-la.facebook.com.
+www.update.microsoft.com.
+photos-f.ak.fbcdn.net.
+platform.ak.fbcdn.net.
+151.96.186.67.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+www.dcsea.uqroo.mx.
+www.helloprojectheaven.com.
+buyperfecthealth.com.
+www.cartolinespeedy.it.
+239.234.218.190.in-addr.arpa.
+www-cctld.l.google.com.
+118.161.208.201.in-addr.arpa.
+verizon.net.
+101.7fm.ru.
+114.172.34.201.in-addr.arpa.
+mypads.net.
+208.218.168.192.in-addr.arpa.
+www.fringenyc.org.
+www.youtube.com.
+www.scotiabank.com.mx.
+124.54.236.82.in-addr.arpa.
+ws-cloud-msgplus.linkury.com.
+www.levi.com.ec.
+91.123.13.201.in-addr.arpa.
+ysrgw8pk3.73bb.
+241.119.38.81.in-addr.arpa.
+pagead.l.doubleclick.net.
+sfg2.golden-tech.com.
+www.gpedit.msc.
+cdna.static.youjizz.com.
+atlplastic.com.
+www.dirtyxxxtube.com.
+a.root-servers.net.
+pap4zjal8.s92c9q0l.
+ecatepecdemorelos.olx.com.mx.
+130.50.201.71.in-addr.arpa.
+static.ak.facebook.com.
+202.235.112.186.in-addr.arpa.
+fxfeeds.mozilla.com.
+s.ytimg.com.
+fxfeeds.mozilla.com.
+wireless.stanford.edu.
+28.talkgadget.google.com.
+ic.tynt.com.
+col.stb01.s-msn.com.
+adframes.iminent.com.
+univi.ac.at.
+photos-a.ak.fbcdn.net.
+245.169.111.189.in-addr.arpa.
+istrianet.org.
+content.yieldmanager.edgesuite.net.
+api.twitter.com.
+www.elizabethhoyt.com.
+capitalmodern.com.
+ksn1-11-part2.kaspersky-labs.com.
+banorte.com.
+b.scorecardresearch.com.
+www.belkin.com.
+espanol.weather.com.
+a.root-servers.net.
+toolbarqueries.google.com.
+120.14.94.118.in-addr.arpa.
+mtucizone.ru.
+26.37.107.186.in-addr.arpa.
+ajax.googleapis.com.
+105.253.148.79.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+inbound.mercedesofindy.com.netsolmail.net.
+toolbar.live.com.
+mozilla.mirrors.pair.com.
+josephquevedony.com.
+173.235.149.186.in-addr.arpa.
+static.ak.fbcdn.net.
+r.turn.com.
+th190.photobucket.com.
+hxidyo.com.
+developers.facebook.com.
+angelakisconstruction.com.
+sp.cwfservice.net.
+mothersbistro.com.
+69.215.225.190.in-addr.arpa.
+184.154.153.200.in-addr.arpa.
+www.christiangr.com.
+i4.ytimg.com.
+41.180.211.189.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+72.30.112.186.in-addr.arpa.
+desmond.yfrog.com.
+121.176.26.190.in-addr.arpa.
+www.sve.uan.edu.mx.
+www.listenarabic.com.
+255.199.105.186.in-addr.arpa.
+external.ak.fbcdn.net.
+www.puritanas.com.
+imgcdn.nrelate.com.
+epriorityplus.com.
+profile.ak.fbcdn.net.
+angusstone.com.
+34.6.30.189.in-addr.arpa.
+freedomhouse.org.
+www.belkin.com.
+41.211.126.186.in-addr.arpa.
+mfa.logonix.net.
+engineering.slideshare.com.
+riairwanty.multiply.com.
+t3.gstatic.com.
+s2.youtube.com.
+szjd4uwey.y13i3i6s.
+www.google.com.
+www8.0zz0.com.
+www.fazendavisconde.com.br.
+231.254.114.186.in-addr.arpa.
+l.longtailvideo.com.
+www.bravotubecams.com.
+s.youtube.com.
+101.106.231.201.in-addr.arpa.
+a.root-servers.net.
+www.twitter.com.
+hi-in.facebook.com.
+www.hondacuajimalpa.com.
+rm-steel.com.
+mail.flashki-optom.ru.
+www.brista.ca.
+6me4qds1r.a63m3l0v.
+ndt-market.ru.
+12.237.1.190.in-addr.arpa.
+digaz.ru.
+253.5.178.189.in-addr.arpa.
+mobile2.wsj.com.
+i3.ytimg.com.
+zh-cn.facebook.com.
+winners.org.
+www.wtp101.com.
+img2.amateur-tube.us.
+pedrocolmenero.wordpress.com.
+photos-h.ak.fbcdn.net.
+159.242.52.216.dnsbl.sorbs.net.
+google.com.
+safebrowsing.clients.google.com.
+teredo.ipv6.microsoft.com.
+youtu.be.
+a7.sphotos.ak.fbcdn.net.
+videos.webs.com.
+20.147.188.206.in-addr.arpa.
+a.root-servers.net.
+connect.facebook.net.
+jigsaw.w3.org.
+download319.avast.com.
+a2.sphotos.ak.fbcdn.net.
+netzero.net.
+gpsex.ru.
+files.realmusic.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+235.255.57.69.in-addr.arpa.
+bridesdiary.com.au.
+buy.gissn.com.
+www.thailand4x4.com.
+162.144.227.66.in-addr.arpa.
+55.51.53.68.in-addr.arpa.
+soundersfc.com.inbound15.mxlogic.net.
+g.ceipmsn.com.
+www.facebook.com.
+google.com.
+moshr.com.
+gfx3.hotmail.com.
+soccerfame.com.
+a1.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+mgtracker.org.
+a.root-servers.net.
+rinaco.com.
+creative.ak.fbcdn.net.
+content.yieldmanager.edgesuite.net.
+a.root-servers.net.
+a.root-servers.net.
+iknowmedia.com.
+us.mc1214.mail.yahoo.com.
+www.autosusadosenmexico.com.mx.
+pixelpnt.com.
+ad.yieldmanager.com.
+www.fisiovictoria.com.
+www.facebook.com.
+platform.twitter.com.
+downsizemyspace.com.
+a5.sphotos.ak.fbcdn.net.
+www.nyxcosmetics.com.hk.
+freenet.de.
+docs.miktex.org.
+yaponiya.ru.
+b-0.19-210ac449.8031581.1518.19d4.3ea1.410.0.6nq2knidpg7w48lng5lcdu9w1t.avqs.mcafee.com.
+i2.ytimg.com.
+aikikai.ru.
+simardelectric.com.
+www.facebook.com.
+www.sonymusic.com.
+oteropictures.blogspot.com.
+profile.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+_vlmcs._tcp.
+d2jsycj2ly2vqh.cloudfront.net.
+therapservices.net.
+answers.hackaday.com.
+www.pegandolealoseguro.com.
+www.getin2china.com.
+mx2.th.fujikura.com.
+ad.metanetwork.com.
+www.youtube.com.
+i2.ytimg.com.
+si0.twimg.com.
+52.4.123.129.in-addr.arpa.
+www.programasgratiz.com.
+mx.mvfintry.com.
+sp.cwfservice.net.
+www.facebook.com.
+natkeepalive.voice.yahoo.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+www.billionairewoman.com.
+165.2.247.109.in-addr.arpa.
+www.google-analytics.com.
+czert.org.
+feeds.bbci.co.uk.
+answer-lab.com.s7b2.psmtp.com.
+a.root-servers.net.
+ipm.avira.com.
+ctsmx.com.
+www.youtube.com.
+www.spurl.net.
+sphinx.stic.co.kr.
+rpobrien.com.
+s.youtube.com.
+accounts.google.com.
+www.everything-about-concrete.com.
+junkcharts.typepad.com.
+www.conceptoradial.com.
+163.205.113.177.in-addr.arpa.
+193.216.16.190.in-addr.arpa.
+www.bancofrances.com.ar.
+dsjkoprtr7844.biz.
+files.fatakat.com.
+a.root-servers.net.
+toymania.com.
+s-static.ak.fbcdn.net.
+server3.lengiprorechtrans.ru.
+news.google.com.mx.
+www.
+facebook.conduit-services.com.
+fieldnotes.msnbc.msn.com.
+sites.google.com.
+es-la.facebook.com.
+baita.com.
+au.travel.yahoo.com.
+a.root-servers.net.
+tdc.co.tt.
+i1.ytimg.com.
+www.adult.toonsearch.net.
+www.gritosdelibertad.org.
+127.214.165.190.in-addr.arpa.
+id.google.es.
+business.twitter.com.
+dl-client365.dropbox.com.
+photos-a.ak.fbcdn.net.
+google.com.
+www.theautomedia.com.
+b._dns-sd._udp.lan.
+clcrolla.com.
+www.google.com.
+photos-a.ak.fbcdn.net.
+hbtele.com.
+hotmail.com.
+ssl.gstatic.com.
+planettirecableties.com.
+187.197.124.84.in-addr.arpa.
+be2.int.pochta.ru.
+a.root-servers.net.
+col.stb00.s-msn.com.
+usersystem783aa.ru.
+it.rinsemymusic.com.
+buttons.googlesyndication.com.
+78.217.144.187.in-addr.arpa.
+hi-in.facebook.com.
+8.28.57.187.in-addr.arpa.
+news.google.com.mx.
+92.136.8.200.in-addr.arpa.
+titanium30-en.url.trendmicro.com.
+14.228.247.131.in-addr.arpa.
+108.87.8.201.in-addr.arpa.
+www.ubergizmo.com.
+www.grupodmrh.vagas.com.br.
+pomerleauins.com.
+forex-trading-signal-fx.kolorowa-kraina.com.pl.
+vdnryd.com.
+i4.ytimg.com.
+42.251.88.184.in-addr.arpa.
+www.thezia.edu.mx.
+idmd.com.
+checkip.dyndns.org.
+pinoylovers.com.
+165.102.68.201.in-addr.arpa.
+mx99.elive.nl.
+www.statcounter.com.
+ads.towniecentral.com.
+mail.subwayak.com.
+c.prodigy.msn.com.
+g.s.openwalls.net.
+shapkitut.ru.
+www.bilkent.edu.tr.
+.
+195.212.153.186.in-addr.arpa.
+sta.ru.
+byerlyinc.com.
+photos-d.ak.fbcdn.net.
+www.epicbot.com.
+ad.yieldmanager.com.
+labs.ebay.com.
+parroquiasanjeronimo.files.wordpress.com.
+sites.google.com.
+d7.zedo.com.
+api.geo.kontagent.net.
+vi.y8.com.
+251.41.74.187.in-addr.arpa.
+api-read.facebook.com.
+database.clamav.net.
+180.106.50.201.in-addr.arpa.
+237.248.9.201.in-addr.arpa.
+creative.ak.fbcdn.net.
+a996.mm1.akamai.net.
+www.hollyan.com.
+scribe.twitter.com.
+109.110.153.189.in-addr.arpa.
+124.17.104.41.in-addr.arpa.
+honduras.paginasamarillas.com.
+content.ak.metrogames.com.
+verizon.net.
+ocsp.verisign.com.
+isabela.olx.com.ph.
+ramsayhealth.com.
+techtribe.com.
+api-read.facebook.com.
+3-cats.ru.
+a4.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.bricopinta.com.
+138.143.240.189.in-addr.arpa.
+numerologia.euroresidentes.es.
+creatividad.espacioblog.com.
+253.76.27.187.in-addr.arpa.
+www.zentai-zentai.com.
+inbound.netwirelessllc.com.netsolmail.net.
+google.com.
+171.237.88.74.in-addr.arpa.
+2ch.net.
+external.ak.fbcdn.net.
+edinstvo62.ru.
+www.dishant.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+connect.facebook.net.
+cdn.tynt.com.
+150.238.18.186.in-addr.arpa.
+194.120.76.95.in-addr.arpa.
+av59.ru.
+creative.ak.fbcdn.net.
+gatoquepesca.blogspot.com.
+101.151.104.112.in-addr.arpa.
+s2.youtube.com.
+voipb.sip.yahoo.com.
+google.com.
+a.root-servers.net.
+smsmt.com.s9b1.psmtp.com.
+a.root-servers.net.
+www.gstatic.com.
+iou.com.
+245.143.245.92.in-addr.arpa.
+80.244.51.190.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+178.206.243.201.in-addr.arpa.
+cs5247.vk.com.
+a.root-servers.net.
+dns.msftncsi.com.
+widgets.amung.us.
+translate.googleapis.com.
+searchjs.s3.amazonaws.com.
+1.156.14.190.in-addr.arpa.
+www.evalapelicula.com.
+profile.ak.fbcdn.net.
+.
+kingedwardvi.devon.sch.uk.
+248.93.228.91.in-addr.arpa.
+d31qbv1cthcecs.cloudfront.net.
+239.6.34.189.in-addr.arpa.
+www.xenciclopedia.com.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+5.17.155.79.in-addr.arpa.
+www.ivosoftware.com.
+www.getmyspacelayouts.com.
+api.twitter.com.
+www.facebook.com.
+169.242.74.201.in-addr.arpa.
+a.root-servers.net.
+twitter.com.
+huntingdon.edu.
+gs.a.sohu.com.
+62.95.141.189.in-addr.arpa.
+luz.edu.ve.
+photos-f.ak.fbcdn.net.
+235.89.252.189.in-addr.arpa.
+sbx.com.
+login.live.com.
+firstcb.com.
+time.nist.gov.
+leonescolorados.blogspot.com.
+mail.montgranite.com.
+i3.ytimg.com.
+32.5.12.189.in-addr.arpa.
+s1-onenote.vo.msecnd.net.
+212.34.227.189.in-addr.arpa.
+gruposis.files.wordpress.com.
+t.co.
+psgw.t-mobilesgws.com.
+116.5.240.189.in-addr.arpa.
+25.23.215.89.in-addr.arpa.
+a-0.19-220990c1.c060583.1518.19d3.3ea1.210.0.5371njcfppgpmlsgm2t5aci8cv.avqs.mcafee.com.
+stun.client.akadns.net.
+tcs.wisebrother.com.
+50.83.168.189.in-addr.arpa.
+local-sn.contacts.msn.com.
+43.111.1.201.in-addr.arpa.
+ropping.tv-asahi.co.jp.
+www.jtfgtmo.southcom.mil.
+profile.ak.fbcdn.net.
+pixel.exelator.com.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+160.107.68.177.in-addr.arpa.
+xslt.alexa.com.
+54.179.59.122.in-addr.arpa.
+www.carnivalspain.com.
+pseudoplocephalus.blogspot.com.
+www.youtu.be.
+75.187.149.187.in-addr.arpa.
+ak.chat.smileycentral.com.
+m.ak.fbcdn.net.
+5.249.33.187.in-addr.arpa.
+beazsims.blogspot.com.
+rikky.spb.su.
+a1108.da1.akamai.net.
+iclub.net.ru.
+www.bluecoat.com.
+www.angiesmovies.com.
+208.68.209.190.in-addr.arpa.
+dns.msftncsi.com.
+a.root-servers.net.
+ecetia.com.
+www.facebook.com.
+24.68.167.190.in-addr.arpa.
+a.root-servers.net.
+fatmanonakeyboard.blogspot.com.
+photos-g.ak.fbcdn.net.
+real-steel.ru.
+xzeitutorialesx.api.channel.livestream.com.
+www.jugarpokerenlinea.com.
+90.121.55.65.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.es.fm.
+plusone.google.com.
+finalfantasyversusxiii.es.
+www.inpsasel.gob.ve.
+lb.wordpress.com.
+sacven.org.
+a.root-servers.net.
+jv3inks.com.
+www.pharmaton.nl.
+cf.ads.kontextua.com.
+ltdunlimited.com.
+www.midweek.com.
+loading2.widdit.com.
+r._dns-sd._udp.lan.
+.
+www.hotgames.com.
+goldrush.net.
+kb.mediatemple.net.
+173.110.101.189.in-addr.arpa.
+sim7441.agni.lindenlab.com.
+www.gfrevenge.com.
+153.126.107.190.in-addr.arpa.
+www.happysexgames.com.
+isohunt.com.
+7.123.182.186.in-addr.arpa.
+shorouknews.com.
+profile.ak.fbcdn.net.
+clock.fmt.he.net.
+www.thevipguide.net.
+after.com.mx.
+eu.wikipedia.org.
+www.blogesfera.com.
+tiweb.net.
+a1.sphotos.ak.fbcdn.net.
+isatap.mshome.net.
+media.gobackpacking.com.
+developers.facebook.com.
+redfaceplus.com.
+fec-committees.findthedata.org.
+dark-desert-highway.blogspot.com.
+www.parentalcontrolbar.org.
+omnicustomconcepts.com.
+digimarc.com.
+mothership.co.nz.
+shared.live.com.
+237.33.152.213.in-addr.arpa.
+billing.sharo4ka.ru.
+ego.ru.
+commview-for-wifi.en.softonic.com.
+s.youtube.com.
+pixel.facebook.com.
+176.232.192.199.in-addr.arpa.
+sup.live.com.
+102.108.65.74.in-addr.arpa.
+www.sapa.org.mx.
+250.13.175.71.in-addr.arpa.
+spam.advancedrecyclingtechnology.com.
+cdn.api.twitter.com.
+140.151.228.67.in-addr.arpa.
+8.133.127.200.in-addr.arpa.
+xyzeor7wn.66gy.
+www.xnxx.com.
+13.51.30.76.in-addr.arpa.
+img.babylon.com.
+www.nicolapotts.com.
+fbcdn-sphotos-a.akamaihd.net.
+s2.youtube.com.
+fxfeeds.mozilla.com.
+a8.sphotos.ak.fbcdn.net.
+182.75.245.189.in-addr.arpa.
+tunnel.cfw.trustedsource.org.
+www.limepro.org.
+www.eldesblogue.com.
+join.mywifesmom.com.
+lazurny-bereg.ru.
+www.facebook.com.
+s.youtube.com.
+64.106.55.95.in-addr.arpa.
+173.182.108.186.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+titanium30-en.url.trendmicro.com.
+alliedmedassoc.com.
+225.183.166.190.in-addr.arpa.
+newsletter.catererglobalmail.com.
+stomperauto.com.
+s10.histats.com.
+ad-g.doubleclick.net.
+a.root-servers.net.
+www.facebook.com.
+17.12.52.186.in-addr.arpa.
+www.brigite.com.
+citylifeltd.ru.
+victory.com.
+sim-im.org.
+53.248.188.203.in-addr.arpa.
+www.mujeresdeempresa.com.
+k3a.me.
+southcom.com.au.
+ship-simulator.programas-gratis.net.
+update.epyte.com.
+partner.googleadservices.com.
+alenet.com.
+sp.cwfservice.net.
+118.136.31.186.in-addr.arpa.
+tmss.trendmicro.com.
+s-static.ak.fbcdn.net.
+time.nist.gov.
+apps.facebook.com.
+www.ajodo.org.
+a.root-servers.net.
+www.update.microsoft.com.
+www.propane-generators.com.
+mail2.astri.org.
+baymsg1010825.gateway.messenger.live.com.
+mail.samzas.ru.
+extrahaus.ee.
+trophy.ww.np.community.playstation.net.
+194.186.41.177.in-addr.arpa.
+mtk.katowice.pl.
+a.root-servers.net.
+cdn.api.twitter.com.
+a.root-servers.net.
+16.23.79.190.in-addr.arpa.
+telfor.pt.
+www.juicypark.com.
+156.201.236.190.in-addr.arpa.
+souzacosta.com.br.
+74.230.195.176.in-addr.arpa.
+social.bidsystem.com.
+mail.mcmolds.com.
+www.gellnerism.de.
+rad.msn.com.
+249.170.28.190.in-addr.arpa.
+msnia.login.live.com.
+loading1.widdit.com.
+3.66.248.189.in-addr.arpa.
+blog-francia.com.
+a3.sphotos.ak.fbcdn.net.
+sim7783.agni.lindenlab.com.
+13.232.8.200.in-addr.arpa.
+mail2.mylink.co.za.
+www.movistar.com.mx.
+id.google.com.mx.
+blog.softonic.com.
+batsonassoc.com.
+_738_71_9.
+o5.
+hypem.tumblr.com.
+dterm.com.
+accounts.google.com.
+a.root-servers.net.
+telepienso.wufoo.com.
+17.13.233.201.in-addr.arpa.
+freakflakes.angelmecanico.com.
+d2104492.xoom.it.
+sp.cwfservice.net.
+j.techgsm.com.
+200.19.250.84.in-addr.arpa.
+ocsp.godaddy.com.
+herbank.com.s6b1.psmtp.com.
+cdt.org.
+www.facebook.com.
+www.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+sn3.mailshell.net.
+i273.photobucket.com.
+pic4.bai.sohu.com.cn.
+252.96.244.189.in-addr.arpa.
+www.facebook.com.
+pixel.everesttech.net.
+cabworks.com.
+a.root-servers.net.
+mm1.curtiscirc.com.
+rabota-kms.ru.
+fairy-games.dressupgames8.com.
+safebrowsing-cache.google.com.
+www.antoniograndiodopico.es.
+www.facebook.com.
+a.root-servers.net.
+241.25.82.190.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+203.21.94.208.in-addr.arpa.
+25.119.220.189.in-addr.arpa.
+www.strawberryfields.net.
+248.11.159.189.in-addr.arpa.
+pixel.facebook.com.
+vkontakte.ru.
+static.ak.fbcdn.net.
+emltrk.com.multi.surbl.org.
+2.bp.blogspot.com.
+js2.wlxrs.com.
+50.203.80.190.in-addr.arpa.
+50.36.199.71.in-addr.arpa.
+barracuda.alamo1.com.
+taconicchevrolet.com.
+b._dns-sd._udp.home.
+www.aciprensa.com.
+www.v2music.com.
+2.56.206.190.in-addr.arpa.
+www.primeraplana.com.co.
+fbcdn-photos-a.akamaihd.net.
+tc20.easythumbhost.com.
+ksn1-12-part1.kaspersky-labs.com.
+sites.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sxsoft.ru.
+www.bayheights.com.
+carltonfoster.com.
+accs-net.com.
+molehillgroup.com.
+175.175.176.114.in-addr.arpa.
+78.101.190.190.in-addr.arpa.
+www.animesv.com.
+marbiopharm.nid.ru.
+www.googleapis.com.
+_136_83_8.
+bestmanager.rags.ru.
+register.iomegacloud.com.
+static.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+36.188.218.188.in-addr.arpa.
+creative.ak.fbcdn.net.
+51.52.249.190.in-addr.arpa.
+a.root-servers.net.
+www.youlikehits.com.
+www.vb-helper.com.
+www.snapper.com.
+au.adserver.yahoo.com.
+www.vintagesexclub.com.
+13.28.14.82.in-addr.arpa.
+www.cellfun.info.
+archivoslb2.minijuegostop.com.mx.
+creative.ak.fbcdn.net.
+:kdziv:14.g44c7m1w.
+cdn.api.twitter.com.
+pixel.facebook.com.
+metrics.apple.com.
+201.215.80.80.in-addr.arpa.
+video.cloudfront.autoexpress.co.uk.
+internet.cgocable.net.
+130.24.80.69.in-addr.arpa.
+best-colon-cleanse-reviews.com.
+r1-ads.ace.advertising.com.
+usersystem783aa.ru.
+google.com.
+m.facebook.com.
+x2kcha7v3.56hk.
+mail.ammann.co.uk.
+176.218.142.190.in-addr.arpa.
+www.acasatv.ro.
+mail.sspp.ru.
+224.112.4.190.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+any-world.ngd.ysm.yahoodns.net.
+profile.ak.fbcdn.net.
+asotrack2.fluentmobile.com.
+burbankwhittemore.com.
+234.202.111.212.in-addr.arpa.
+nationwide.com.
+a.root-servers.net.
+mail.pkokprf.ru.
+forums.graaam.com.
+6.21.129.50.in-addr.arpa.
+a.root-servers.net.
+ssl.gstatic.com.
+242.242.111.190.in-addr.arpa.
+www.bravotube.net.
+www.youtube.com.
+73.233.18.177.in-addr.arpa.
+rt.legolas-media.com.
+www.sarahdavis.com.au.
+kp.incompany.ru.
+thelennoxx.files.wordpress.com.
+www.addthis.com.
+kr.yahoo.com.
+static.ak.fbcdn.net.
+18.127.4.190.in-addr.arpa.
+111.16.153.189.in-addr.arpa.
+external.ak.fbcdn.net.
+simsdescargas.com.
+lostangelesca.tumblr.com.
+a1003.w41.akamai.net.
+profile.ak.fbcdn.net.
+img3.kuwo.cn.
+dns.msftncsi.com.
+ice-watch.com.
+infieleschile.es.tl.
+0-jk-w.channel.facebook.com.
+loading321.com.
+dsn12.d.skype.net.
+67.16.190.72.in-addr.arpa.
+mail.younameitspecialties.com.
+gamebt.ali213.net.
+652.talkgadget.google.com.
+ad.smowtion.com.
+redesycominformal.blogspot.com.
+gamehall11.3g.qq.com.
+www.facebook.com.
+27.180.158.187.in-addr.arpa.
+www.winkeyfinder.com.
+update.eset.com.
+yahoo.com.
+a2.sphotos.ak.fbcdn.net.
+60.32.139.189.in-addr.arpa.
+164.147.246.201.in-addr.arpa.
+189.59.168.200.in-addr.arpa.
+crl.microsoft.com.
+90.2.235.209.in-addr.arpa.
+20.80.59.82.in-addr.arpa.
+seroesdaines.blogspot.com.
+6fdvkyhlv.09ty.
+blst.msn.com.
+72.132.176.186.in-addr.arpa.
+ad.doubleclick.net.
+0-278.channel.facebook.com.
+plus.google.com.
+katemiddletonfan.co.uk.
+time-nw.nist.gov.
+www.facebook.com.
+google.com.
+www.united-internet.com.
+gs-loc.isg-apple.com.akadns.net.
+153.113.233.118.in-addr.arpa.
+www.phpexpertsforum.com.
+dixonvision.com.
+www.refurbished-notebooks.de.
+falabella.com.pe.
+hits.e.cl.
+webcache.googleusercontent.com.
+161.2.10.187.in-addr.arpa.
+lshallmark.com.
+safebrowsing.clients.google.com.
+rapidssl-crl.geotrust.com.
+www.yout.
+s-static.ak.facebook.com.
+hexane.bluejava.net.
+2pp5qdw4w.y15f4m2x.
+www.cywex.com.
+rad.msn.com.
+wholinkstome.com.
+3.bp.blogspot.com.
+www.vspor.com.
+nniline.naver.com.
+i3.ytimg.com.
+a.root-servers.net.
+rules.securestudies.com.
+fidohitop.ca.
+hi-in.facebook.com.
+google.com.
+xxxvideos.sso9523.com.
+164.124.162.190.in-addr.arpa.
+www.google-analytics.com.
+250.219.141.62.in-addr.arpa.
+twincitygroup.com.inbound20.mxlogicmx.net.
+www.mydearjenn.com.
+cclc.com.inbound15.mxlogic.net.
+www.yahoo.com.
+www.avgthreatlabs.com.
+lugano.com.
+cri8yysa5.85fy.
+yahoo.com.
+www.loaddl.com.
+s.ist1-1.filesor.com.
+www.google.com.
+www.mvanime.com.
+51.116.126.70.in-addr.arpa.
+www.whcc.com.
+www.bdr130.net.
+cpm.biz.
+thevoice.wikia.com.
+www.m5zn.com.
+external.ak.fbcdn.net.
+elhobo.ru.
+124sjlb1p.06qy.
+clientlog.users.conduit.com.
+www.yahoo.com.
+102.101.61.99.in-addr.arpa.
+creative.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+157.139.79.187.in-addr.arpa.
+77u:w8p65.y62b4c9r.
+e-surance.ru.
+106.245.48.190.in-addr.arpa.
+apps.facebook.com.
+painewetzel.com.
+graycalhoun.com.
+mail.groupe-ldi.com.
+www.cinetux.org.
+js.admeld.com.
+translate.google.com.
+luther-veno.com.
+sm.pemex.com.
+www.ldelectura.com.
+ssl.gstatic.com.
+facebook.blurtit.com.
+s2.youtube.com.
+talk.google.com.
+bs.serving-sys.com.
+108.66.173.58.in-addr.arpa.
+www.youtube.com.
+probitycr.com.
+underground-land.blogspot.com.
+external.ak.fbcdn.net.
+static.ak.fbcdn.net.
+citigrove.com.
+pantelis.co.uk.
+s2.youtube.com.
+175.71.63.71.in-addr.arpa.
+apis.google.com.
+esp.cr.usgs.gov.
+www.encuentra.gob.mx.
+229.235.124.186.in-addr.arpa.
+67.65.213.201.in-addr.arpa.
+196.21.39.187.in-addr.arpa.
+www2.esmas.com.
+a1003.w41.akamai.net.
+215.233.90.80.in-addr.arpa.
+www.slicingpsdtohtml.com.
+www.quadratin.com.mx.
+news.keralakaumudi.com.
+download.windowsupdate.com.
+sqhkcpsmu.91cc.
+.
+www.google.com.
+www.diacono.cl.
+photos-c.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+api.cloudsponge.com.
+skynet.be.
+89.68.104.189.in-addr.arpa.
+forums.ereplacementparts.com.
+susangaer.com.
+_466_60_9.
+mtwerweb.com.
+244.171.86.74.zen.spamhaus.org.
+jailbreakmatrix.com.
+pixel.facebook.com.
+accounts.google.com.
+229.15.157.201.in-addr.arpa.
+www.sandos4u.com.
+w3fp.arizona.edu.
+auto-deflectors.com.
+226.127.63.200.in-addr.arpa.
+sites.google.com.
+surfacemag.com.
+stats.wordpress.com.
+linkhelp.clients.google.com.
+65.55.62.189.in-addr.arpa.
+s-static.ak.fbcdn.net.
+42.26.132.190.in-addr.arpa.
+user.easyn.cn.
+www.microscopy.fsu.edu.
+i.creativecommons.org.
+_891_19_1.
+analytics.binarysolutions.biz.
+fb.com.
+dns194.a.register.com.
+banners.webmasterplan.com.
+photos-a.ak.fbcdn.net.
+x.tagstat.com.
+docs.google.com.
+t0.gstatic.com.
+dns.msftncsi.com.
+44.63.111.87.in-addr.arpa.
+profile.ak.fbcdn.net.
+r._dns-sd._udp.lan.
+twitter.com.
+ftp.us.dell.com.
+t2.gstatic.com.
+a8.sphotos.ak.fbcdn.net.
+creativecommons.org.
+berrycoder.com.
+123.254.56.190.in-addr.arpa.
+www.hormiga.org.
+gentenotable.com.
+www.dmedicina.com.
+arjunaardagh.com.
+msn.toutelatele.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+44.245.172.201.in-addr.arpa.
+s-static.ak.fbcdn.net.
+nl.y8.com.
+a.erectopatentpothunter.com.
+31.179.253.201.in-addr.arpa.
+113.163.56.186.in-addr.arpa.
+safebrowsing.clients.google.com.
+infoway.ru.
+72.99.205.112.in-addr.arpa.
+pagead2.googlesyndication.com.
+evidence.uche.org.
+i1.ytimg.com.
+gayforjohnnydepp.com.
+www.drumming.com.
+www.xor-motors.com.
+0-0.qlty.finarea.ch.
+qpfhg2ucf.13jp.
+www.miedoescenico.com.mx.
+www.accequip.com.
+ocsp.verisign.com.
+a-0.19-21098081.9050583.1518.19d3.2f4a.210.0.p99c86uikwh4wwpwi6nsbf1vq6.avqs.mcafee.com.
+225.103.156.189.in-addr.arpa.
+cdn.api.twitter.com.
+alert.services.conduit.comalerts.
+photos-c.ak.fbcdn.net.
+ksn4.kaspersky-labs.com.
+236.66.81.186.in-addr.arpa.
+136.194.129.189.in-addr.arpa.
+190.243.61.200.in-addr.arpa.
+163.91.75.187.in-addr.arpa.
+www.pararegalar.com.
+mx01.ancara.net.
+www-cctld.l.google.com.
+scripts.downloadroute.com.
+actualizacionesturismo.blogspot.com.
+graph.facebook.com.
+cibcommunications.co.uk.
+photos-g.ak.fbcdn.net.
+227.24.207.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+leycite.com.
+ssl.gstatic.com.
+networld.com.
+d3lvr7yuk4uaui.cloudfront.net.
+ws.audioscrobbler.com.
+www.ador.state.al.us.
+111.111.75.201.in-addr.arpa.
+cbre.com.
+www.stadt-koeln.de.
+179.126.4.190.in-addr.arpa.
+169.82.15.74.in-addr.arpa.
+www.milonic.com.
+www.coolarcade.org.
+pixel.facebook.com.
+108.139.103.177.in-addr.arpa.
+152.140.23.187.in-addr.arpa.
+70.43.15.187.in-addr.arpa.
+www.espacioeuropa.eu.
+lh3.googleusercontent.com.
+a2.sphotos.ak.fbcdn.net.
+162.192.0.79.in-addr.arpa.
+124.31.240.201.in-addr.arpa.
+crossfitmobile.blogspot.com.
+humanitarianbowl.com.
+s.ytimg.com.
+t1.gstatic.com.
+profile.ak.fbcdn.net.
+244.132.82.190.in-addr.arpa.
+t1.gstatic.com.
+embed.dada.net.
+208.27.212.89.in-addr.arpa.
+www.thecures.info.
+ddm-payment.wooga.com.
+www.google.com.
+112.76.154.186.in-addr.arpa.
+api.megaapi.com.
+a.root-servers.net.
+a.ads2.msads.net.
+profile.ak.fbcdn.net.
+dessy.ru.
+virus-x-world.blogspot.com.
+dnl-01.geo.kaspersky.com.
+avatar.nimbuzz.com.
+a2.sphotos.ak.fbcdn.net.
+puls.omsk.su.
+jaxxmfg.com.
+fotmobapi.s3.amazonaws.com.
+www.sparkdream.net.
+126.245.36.186.in-addr.arpa.
+117.9.129.189.in-addr.arpa.
+necessitation.option.wisher.net.
+pelis8.blogspot.com.
+oceaneconsulting.com.
+dtxtngytz5im1.cloudfront.net.
+113.232.214.189.in-addr.arpa.
+ns4.p26.dynect.net.
+clients1.google.com.
+www.blogger.com.
+habichuelasmagicas.wordpress.com.
+159.188.8.200.in-addr.arpa.
+toolbar.zynga.com.
+s-static.ak.facebook.com.
+www.facebook.com.
+t0.gstatic.com.
+www.grupoalianzaempresarial.com.
+hostmyimage.org.
+ksn2-12.kaspersky-labs.com.
+api.facebook.com.
+20minutos.feedsportal.com.
+158.24.75.190.in-addr.arpa.
+google.com.
+49-courier.push.apple.com.
+a1459.phobos.apple.com.edgesuite.net.
+223.165.50.190.in-addr.arpa.
+www.escueladigital.com.uy.
+crl.globalsign.net.
+www.google.com.
+27.249.153.186.in-addr.arpa.
+a1656.phobos.apple.com.
+img168.imageshack.us.
+www.google.com.
+tuttipazziperilgossip.blogspot.com.
+time.chttl.com.tw.
+star.facebook.com.
+www.xatech.com.
+search.bearshare.com.
+mirocine.net.
+www.wildpee.com.
+fbcdn-photos-a.akamaihd.net.
+33.219.171.201.in-addr.arpa.
+soroc.com.
+www.facebook.com.
+maktoob.omg.yahoo.com.
+losangeles.craigslist.org.
+www.flickr.com.
+www.howtodownloadmusic.net.
+ksn2-12.kaspersky-labs.com.
+3.bp.blogspot.com.
+www.df.cl.
+mx.airbits.net.
+inv75-2-82-229-190-6.fbx.proxad.net.
+ec.atdmt.com.
+mx3.altour.com.
+viewer.office.naver.com.
+connect.facebook.net.
+a221.phobos.apple.com.
+a3.sphotos.ak.fbcdn.net.
+www.nanex.net.
+naw7gw:sk.v17e3g5g.
+chloesnails.blogspot.com.
+29.media.tumblr.com.
+ruinnation.com.
+www.mozilla.org.
+www.creandoprosperidad.es.
+runofeari08.blogdiario.com.
+8.64.210.201.in-addr.arpa.
+www.facebook.com.
+zh-cn.facebook.com.
+updatekeepalive.mcafee.com.
+stream-tv.softonic.com.
+rw6ekuv6i.10yj.
+66.66.170.82.in-addr.arpa.
+69.131.138.201.in-addr.arpa.
+google.com.
+hardincountybank.com.s7b1.psmtp.com.
+chubov.ru.
+119.121.142.187.in-addr.arpa.
+7.26.133.189.in-addr.arpa.
+www.zynga.com.
+51.242.79.190.in-addr.arpa.
+data1.vod.itc.cn.
+ui.skype.com.
+www.healthinnumbers.com.
+s2.youtube.com.
+ksn1-11-part1.kaspersky-labs.com.
+twitter.com.
+it-it.facebook.com.
+www.overstone57.com.
+www.kayak.com.
+151.134.252.190.in-addr.arpa.
+andymwilliams.com.
+a5.sphotos.ak.fbcdn.net.
+www.facebook.com.
+krtec.tgc-9.ru.
+197.214.204.200.in-addr.arpa.
+a756.l.akamai.net.
+orcart.facebook.com.
+safebrowsing.clients.google.com.
+217.211.64.187.in-addr.arpa.
+193.93.205.71.in-addr.arpa.
+www.newforo.org.
+a.root-servers.net.
+22.1.203.200.in-addr.arpa.
+cdn.api.twitter.com.
+pixel.facebook.com.
+time.nist.gov.
+girlytattoosforgirls.com.
+ht.com.
+eisbrecher.musicload.de.
+hash.orbitdownloader.com.
+tuxtor.shekalug.org.
+mentalized.net.
+a.root-servers.net.
+www.stopbadware.org.
+252.96.186.79.in-addr.arpa.
+hicksholdings.com.
+jlcaravias.files.wordpress.com.
+z4khime.tumblr.com.
+sedmikrasky.blogspot.com.
+a.root-servers.net.
+rospres.com.
+214.27.172.220.in-addr.arpa.
+plus.google.com.
+cr1-lon.tudor.com.
+tmx.technoratimedia.com.
+colegialashot.blogspot.com.
+143.29.206.24.in-addr.arpa.
+region-ttk.ru.
+c247723.r23.cf1.rackcdn.com.
+48.181.63.69.in-addr.arpa.
+a.root-servers.net.
+www.facebook.com.
+safebrowsing.clients.google.com.
+www.jacksonkatz.com.
+www.cheapdesignerhandbagsnow.com.
+200.1.168.192.in-addr.arpa.
+87.27.131.187.in-addr.arpa.
+a.root-servers.net.
+apps.facebook.com.
+mx1.caseware.com.
+api.twitter.com.
+a2.sphotos.ak.fbcdn.net.
+test.domainepublic.net.
+www.viajaryestudiar.com.
+ds.addthis.com.
+19.52.136.175.in-addr.arpa.
+121.122.196.205.in-addr.arpa.
+www30.us.archive.org.
+darlingtonvillage.org.
+www.themasteraccount.com.
+27.210.173.201.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+clicktrack.wnu.com.
+www.materialsuzuki.com.
+32.50.91.72.in-addr.arpa.
+video.dailymail.co.uk.
+www.shap.com.ar.
+6d9kv54u3.w54t0q1m.
+lb._dns-sd._udp.localdomain.
+www.facebook.com.
+photos-a.ak.fbcdn.net.
+d2090058.xoom.it.
+tech.by.
+safebrowsing-cache.google.com.
+rs138l3.rapidshare.com.
+yareco.ru.
+network.terra.com.mx.
+u20.eset.com.
+c7.zedo.com.
+www.google.com.
+duke.edu.
+api.twitter.com.
+www.beglar.com.
+_885_84_1.
+itunes.apple.com.
+www.oneonlinegames.com.
+rad.msn.com.
+1.108.229.91.in-addr.arpa.
+googleads.g.doubleclick.net.
+158.82.230.190.in-addr.arpa.
+www.estoesmarketing.com.
+mx.itbu.ru.
+msnads.vo.msecnd.net.
+teredo.ipv6.microsoft.com.
+m.y.
+i4.ytimg.com.
+ksn3-11.part2.kaspersky-labs.com.
+4gks1zwr:.l38g4t6w.
+163.141.88.186.in-addr.arpa.
+push.apple.com.
+a3.sphotos.ak.fbcdn.net.
+www.daleonda.com.
+193.105.85.123.in-addr.arpa.
+www.isg-apple.com.akadns.net.
+hamd.co.uk.
+amira-budur.ru.
+www.google.com.
+www.vuu.com.au.
+98.165.124.186.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+214.107.216.87.in-addr.arpa.
+wpad.mshome.net.
+youtubemusica.org.
+vip.adminzu.com.
+postmaster.ru.
+mail2.marshallinstitute.com.
+malah.biz.
+www.ag-quienessomos.com.ar.
+godfatherofgreenbay.xanga.com.
+gfx.aftonbladet-cdn.se.
+181.113.49.92.in-addr.arpa.
+xrysanthema.gr.
+194.89.103.201.in-addr.arpa.
+2.by.dnsbl7.mailshell.net.
+time.chttl.com.tw.
+108.98.96.78.in-addr.arpa.
+73.230.80.72.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+js.wlxrs.com.
+father.asahi-net.or.jp.
+118.55.22.190.in-addr.arpa.
+www.facebook.com.
+kcowdin.com.s5b2.psmtp.com.
+cineimperfecto.blogspot.com.
+img.mediaplex.com.
+a3.sphotos.ak.fbcdn.net.
+www.biologiaonline.com.ar.
+services.ticktockapps.com.
+252.45.173.201.in-addr.arpa.
+0-155.channel.facebook.com.
+soundingometersecosasporlapolla.blogspot.com.
+a5.sphotos.ak.fbcdn.net.
+www.apple.com.
+profile.ak.fbcdn.net.
+neuf.fr.
+a3.sphotos.ak.fbcdn.net.
+mail.mypostcardprinting.com.
+forums.support.roxio.com.
+2bnkgpn59.x94r2o8x.
+203.234.152.190.in-addr.arpa.
+50.1.168.192.in-addr.arpa.
+32.213.34.41.in-addr.arpa.
+210.234.152.187.in-addr.arpa.
+games.charlesayoub.com.
+51.220.71.68.in-addr.arpa.
+146.136.23.187.in-addr.arpa.
+cm.netseer.com.
+shorouknews.com.
+129.234.124.186.in-addr.arpa.
+www.youmoviz.com.
+support.microsoft.com.
+js.wlxrs.com.
+bbs.msn.com.cn.
+my-dvd-collection.ru.
+www.the-samaritans.com.
+profile.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+partedeconfirmacion.blogspot.com.
+242.7.39.82.in-addr.arpa.
+premium.mookie1.com.
+197.192.126.187.in-addr.arpa.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+www.clive-owen.org.
+manuals.makeuseof.com.s3.amazonaws.com.
+168.228.195.69.in-addr.arpa.
+api.twitter.com.
+s-external.ak.fbcdn.net.
+www.edmondmom.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+smtp.tularik.com.
+my.drujok.ru.
+158.173.130.190.in-addr.arpa.
+msn.com.
+holttester.vo.msecnd.net.
+_140_91_0.
+a.root-servers.net.
+126.142.177.189.in-addr.arpa.
+pdq1.com.
+magicdar.ru.
+us.bc.yahoo.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+heydary.com.inbound10.mxlogic.net.
+_390_86_1.
+dns.msftncsi.com.
+173.69.138.187.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+clarendon2.k12.sc.us.
+flchsk.info.
+35.92.22.190.in-addr.arpa.
+latabernadeatb.blogspot.com.
+a.root-servers.net.
+de-de.facebook.com.
+safebrowsing.clients.google.com.
+www.blogger.com.
+www.facebook.com.
+d18txuuu339yuz.cloudfront.net.
+i4.ytimg.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.youtube.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+26.245.205.87.in-addr.arpa.
+08834c26.ultrafiles.net.
+static.ak.facebook.com.
+75.25.244.62.in-addr.arpa.
+mailspool.citravel.com.
+63.122.138.89.in-addr.arpa.
+designsoftware.com.
+mail.edcspringdale.com.
+banners.adultfriendfinder.com.
+teredo.ipv6.microsoft.com.
+www.qsw11.com.
+images.adultemart.com.
+www.techsoup.org.
+mail.gereaveseng.com.
+fjbaehr.com.
+20.249.83.66.in-addr.arpa.
+196.155.209.190.in-addr.arpa.
+it.wikipedia.org.
+a.root-servers.net.
+cdnedge.bbc.co.uk.
+www.linomixandplay.com.
+sn1msg2020234.gateway.messenger.live.com.
+cdn-sec.tacoda.at.atwola.com.
+preslavaonline.com.
+smkonpunwtfsgsu.com.
+4.2.2.187.in-addr.arpa.
+fcs72-1.streamate.com.
+8.81.210.186.in-addr.arpa.
+ses.library.usyd.edu.au.
+8.70.138.200.in-addr.arpa.
+www.animewolken.nl.
+e.apsalar.com.
+pixel.facebook.com.
+xocolatco.blogspot.com.
+vyletel.com.s6b1.psmtp.com.
+51fvyq9c6.15ej.
+206.187.170.201.in-addr.arpa.
+mail.google.com.
+96.51.39.115.in-addr.arpa.
+hr.cam4.com.
+pl.business-listings.com.
+img175.imagenar.com.
+www.google.com.
+platform.twitter.com.
+38.29.203.68.in-addr.arpa.
+219.23.193.200.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+151.184.104.187.in-addr.arpa.
+www.youtube.com.
+mtalk.google.com.
+www.colemangroup.com.au.
+map.media6degrees.com.
+www.facebook.com.
+mail-relay1.dijit.net.
+www.google-analytics.com.
+168.169.132.190.in-addr.arpa.
+gualdotadinoprimo.it.
+40.227.237.85.in-addr.arpa.
+112.67.84.200.in-addr.arpa.
+16.97.92.200.in-addr.arpa.
+www.beautyundercover.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+api-read.facebook.com.
+louislautman.com.
+tracker4.finalgear.com.
+ccook1.plus.com.
+anthonyyeung.ca.
+www.softworld.com.
+39.253.14.37.in-addr.arpa.
+2.bp.blogspot.com.
+caretta.ro.
+njlwlwevrvontf.com.
+www.buscadoresdedios.es.
+mx.bowserelectronics.com.
+members.multimania.co.uk.
+www.oralb.co.uk.
+bb.xml.slide.com.
+nodropershex.in.
+calendar.live.com.
+a.root-servers.net.
+77.245.168.78.in-addr.arpa.
+static.atgsvcs.com.
+pt.veoh.com.
+www.pitstopmedia.com.
+lucidm.ru.
+www.youtube.com.
+carqueixacesaryjuan.blogspot.com.
+graph.facebook.com.
+animet-movie.blogspot.com.
+www.youtube.com.
+68.245.58.201.in-addr.arpa.
+www.moforacing.com.
+filetterpress.com.
+nt0.ggpht.com.
+ndtserver1.newdaytechnology.com.
+www.amazon.it.
+www.google.com.mx.
+trans-p2p.pandora.tv.
+google.com.
+229.143.37.190.in-addr.arpa.
+hostposter.ru.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+s.youtube.com.
+profile.ak.fbcdn.net.
+cms.abmr.net.
+mx.youtube.com.
+aol.com.
+googlemail.l.google.com.
+m.hotmail.com.
+www.facebook.com.
+a.root-servers.net.
+liveupdate.symantecliveupdate.com.
+gfx2.hotmail.com.
+www.elleinterior.se.
+246.59.58.186.in-addr.arpa.
+231.3.201.190.in-addr.arpa.
+www.johanngonzalez.com.
+data.flurry.com.
+a.root-servers.net.
+a.root-servers.net.
+230.215.119.79.in-addr.arpa.
+9.215.192.187.in-addr.arpa.
+236.224.229.78.in-addr.arpa.
+heritagetitleltd.com.inbound10.mxlogic.net.
+londoncityairport.com.
+g.live.com.
+182.64.178.186.in-addr.arpa.
+www.alan4.com.
+download116.avast.com.
+tunnel.web.trustedsource.org.
+meeder.com.
+signup.casualteensex.com.
+dns.msftncsi.com.
+253.249.107.186.in-addr.arpa.
+secure.shared.live.com.
+195.59.136.175.in-addr.arpa.
+www.joegrossberg.com.
+a.root-servers.net.
+belotti.ru.
+ocsp.entrust.net.
+tc20.easythumbhost.com.
+leshiygames.ru.
+a.ads2.msads.net.
+www.coolfreeimages.net.
+www.moldesparachocolate.com.
+164.140.74.76.in-addr.arpa.
+dlvr.it.
+132.166.52.190.in-addr.arpa.
+0-jk-w.channel.facebook.com.
+static.ak.fbcdn.net.
+103.163.107.186.in-addr.arpa.
+50.230.133.78.in-addr.arpa.
+imbui.iminent.com.
+mille-lacs.com.
+177.82.125.74.query.bondedsender.org.
+landsaver.net.
+photos-d.ak.fbcdn.net.
+nailstah.com.
+rmafhtuhqbaayejpvlsy.so.
+226.146.222.176.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+www.facebook.com.
+www.figfx.com.
+mail.cloud9.net.
+www.google-analytics.com.
+duke-enery.com.
+www.hotmail.com.
+www.jobwinner.ch.
+53.69.97.83.in-addr.arpa.
+135.72.72.190.in-addr.arpa.
+mail.fhacpa.com.
+maps.google.com.
+www.bcscta.ca.
+a996.mm1.akamai.net.
+simplynallely.blogspot.com.
+homelan.bg.
+cdn1.mundodastribos.com.
+life-of-an-architecture-student.tumblr.com.
+adwords.google.com.
+external.ak.fbcdn.net.
+sdgdthf.com.
+www.napnanny.com.
+horizonhealthcorp.com.
+a.root-servers.net.
+apis.google.com.
+die-zivilisatoren.de.
+c.speedtest.net.
+hoffstrizz.typepad.com.
+profile.ak.fbcdn.net.
+connect.facebook.net.
+dns.msftncsi.com.
+a.root-servers.net.
+bastamarine.com.
+voipb.sip.yahoo.com.
+203.17.228.89.in-addr.arpa.
+www.facebook.com.
+22.128.225.190.in-addr.arpa.
+gmailblog.blogspot.com.
+inbound.vietnamanztravel.com.netsolmail.net.
+girlgames2you.com.
+kwoff.com.
+google.com.
+56.116.223.189.in-addr.arpa.
+directory.services.live.com.
+www.terra.com.mx.
+goodvibes.com.mx2.lanxpert.rcimx.net.
+mail.tatabluescopesteel.com.
+dryope.ru.
+128.237.88.186.in-addr.arpa.
+www.beautifulmag.eu.
+rocky.com.
+sweetestpersonblog.com.
+a7.sphotos.ak.fbcdn.net.
+l.yimg.com.
+ibbgrefrathberlin.de.
+s-static.ak.fbcdn.net.
+www.facebook.com.
+blog.gamescheatdirectory.com.
+trabajo.com.mx.
+udarnik-kam.ru.
+simpsons-dvd.ru.
+_011_38_0.
+sites.google.com.
+static.ak.connect.facebook.com.
+210.5.141.188.in-addr.arpa.
+inrca.it.
+static.ak.fbcdn.net.
+fbcdn-sphotos-a.akamaihd.net.
+123.23.143.201.in-addr.arpa.
+miip.es.
+ce.lijit.com.
+www.download.windowsupdate.com.
+a.root-servers.net.
+images03.olx.com.
+www.autotrader.com.cy.
+google.com.
+ww2.asscleaners.com.
+216.143.158.82.in-addr.arpa.
+www.searchqu.com.
+r.mzstatic.com.
+189.1.168.192.in-addr.arpa.
+chillingo-crystal.appspot.com.
+lowcarbdiets.about.com.
+mscrl.microsoft.com.
+sociology.stanford.edu.
+www10.spelar.org.
+hkdmx01.flextronics.com.
+80.11.201.187.in-addr.arpa.
+www.lajollaplayhouse.com.
+mail.google.com.
+dutchlandinc.com.inbound35.mxlogicmx.net.
+android.clients.google.com.
+ffatl.com.
+incredmail.vo.llnwd.net.
+hkmdm.com.
+peptidecalculator.com.
+windowsphone.xbox.com.
+www.facebook.com.
+8gqmpgtte.63sp.
+smart.cellflirt.com.
+mail.cnbrown.com.
+mx2.coelba.com.br.
+photos-g.ak.fbcdn.net.
+merapi.iconpln.net.id.
+api-public.addthis.com.
+bligoo.com.
+47.29.95.190.in-addr.arpa.
+79.102.22.190.in-addr.arpa.
+toyotamaint.tekgroupweb.com.
+konatools.ru.
+www.facebuzz.com.look-for.us.
+a.root-servers.net.
+5-courier.push.apple.com.
+a.root-servers.net.
+www.ropa-bebe.com.
+tfaballoy.com.
+content.yieldmanager.edgesuite.net.
+148.110.31.75.in-addr.arpa.
+www.desimusic.com.
+grupogondi.com.
+bo.starmedia.com.
+www.google-analytics.com.
+teredo.ipv6.microsoft.com.
+145.108.255.201.in-addr.arpa.
+www.boobsfinder.com.
+photos-f.ak.fbcdn.net.
+menacestudios.com.
+wikoff.com.
+nfscross2010.co.cc.
+basel.int.
+download336.avast.com.
+90.48.126.187.in-addr.arpa.
+pixel.facebook.com.
+nacionvampirica.foromx.org.
+www.pni.org.
+akha.org.
+crow.ru.
+www.conaleptabasco.edu.mx.
+208.172.0.190.in-addr.arpa.
+login.live.com.
+jsu.dt07.net.
+ns2.skybeam.com.
+dns.msftncsi.com.
+a.root-servers.net.
+surtimoda.com.
+s7.addthis.com.
+ad.doubleclick.net.
+38.45.122.186.in-addr.arpa.
+yahoo.com.
+time-b.nist.gov.
+a1108.da1.akamai.net.
+tags.bluekai.com.
+gfx2.hotmail.com.
+comunidad.multimedios.com.
+44.117.95.190.in-addr.arpa.
+www.radiofides.co.cr.
+poolplayers.ca.
+www.youtube.com.
+www.google-analytics.com.
+a.root-servers.net.
+187.28.254.201.in-addr.arpa.
+www.ascodevida.com.
+seorider.ru.
+154.11.6.186.in-addr.arpa.
+r.mzstatic.com.
+ditunney.com.
+jabon-soap.blogspot.com.
+pixel.quantserve.com.
+translate.google.com.mx.
+86.158.231.77.in-addr.arpa.
+ds.serving-sys.com.
+static.ak.fb.
+static.ak.connect.facebook.com.
+server51.appriver.com.
+32.217.30.190.in-addr.arpa.
+.
+msn.com.
+netsave.ru.
+www.facebook.com.
+intercolor-ink.com.
+oneana.com.
+db11.spamcatcher.net.
+40.122.11.190.in-addr.arpa.
+7.59.29.189.in-addr.arpa.
+psgw.t-mobilesgws.com.
+46.91.9.87.in-addr.arpa.
+static.v3beta.buysellads.com.
+arbitr.chita.ru.
+16.1.168.192.in-addr.arpa.
+tracker.bittorrent.am.
+167.153.76.64.in-addr.arpa.
+slsp.manpower.usmc.mil.
+wjprx585h.y63k1m5n.
+android.tweetmeme.com.
+advertiser.doclix.com.
+upwardrealty.com.
+bestaility.monkey-sex.net.
+action.web.ca.
+www.mimejorfrase.biz.
+227.105.134.115.in-addr.arpa.
+www.peliculas-flv.com.
+academics.tjhsst.edu.
+46.191.54.65.in-addr.arpa.
+twentysomethingadvice.blogspot.com.
+ahni.com.s8a2.psmtp.com.
+revelations.seriespepito.com.
+cdn.lfstmedia.com.
+interiormagz.com.
+xvideos-395.vo.llnwd.net.
+segment-pixel.invitemedia.com.
+198.234.167.189.in-addr.arpa.
+55.16.137.187.in-addr.arpa.
+www.oppsofts.com.
+d24w6bsrhbeh9d.cloudfront.net.
+221.114.14.71.in-addr.arpa.
+www.belkin.com.
+cdn.buzznet.com.
+photos-a.ak.fbcdn.net.
+erhanmakas.blogspot.com.
+s52.radikal.ru.
+sp.cwfservice.net.
+a995.mm1.akamai.net.
+www.facebook.com.
+sites.google.com.
+consalting-secrets.ru.
+exch-e.atdmt.com.
+edition.cnn.com.
+asktoolbar.weather.com.
+twitter.com.
+safebrowsing-cache.google.com.
+accounts.google.com.
+transeuro.ru.
+csb-polimer.ru.
+67.54.10.186.in-addr.arpa.
+rockte.blogdiario.com.
+www.lansteel.com.
+s-static.ak.fbcdn.net.
+70.76.139.210.in-addr.arpa.
+google.com.
+22.79.218.188.in-addr.arpa.
+252.162.225.189.in-addr.arpa.
+a.root-servers.net.
+www.adobe.com.
+us.mg4.mail.yahoo.com.
+225.60.37.80.in-addr.arpa.
+4.1.241.189.in-addr.arpa.
+d2098285.xoom.it.
+a4.sphotos.ak.fbcdn.net.
+static.ak.connect.facebook.com.
+199.80.146.187.in-addr.arpa.
+sketchup.google.com.
+27.48.58.201.in-addr.arpa.
+www.pliactom.com.
+www.jcbinternational.com.
+static.ak.fbcdn.net.
+pubads.g.doubleclick.net.
+0.9083944.com.
+187.180.200.189.in-addr.arpa.
+www.eme-equis.com.mx.
+santosneves.ifrance.com.
+130.210.85.200.in-addr.arpa.
+179.232.241.186.in-addr.arpa.
+176.157.167.190.in-addr.arpa.
+i.ebayimg.com.
+rtb.tubemogul.com.
+apps.facebook.com.
+r._dns-sd._udp.0.3.168.192.in-addr.arpa.
+tvsalesnet3.wordpress.com.
+teredo.ipv6.microsoft.com.
+static.ak.fbcdn.net.
+51.27.189.190.in-addr.arpa.
+titanium30-en.url.trendmicro.com.
+insider.msg.yahoo.com.
+focushh.blogspot.com.
+sealine.com.s200a2.psmtp.com.
+1.38.140.186.in-addr.arpa.
+126.1.168.192.in-addr.arpa.
+facemoods.com.
+a1.sphotos.ak.fbcdn.net.
+kfml.ru.
+moscowbsl.ru.
+www.google.com.
+fbcdn-photos-a.akamaihd.net.
+google.com.
+toolbarqueries.google.com.
+160.171.250.189.in-addr.arpa.
+apps.facebook.com.
+190.241.226.189.in-addr.arpa.
+samchirnside.com.
+www.gamexchange.co.uk.
+fxfeeds.mozilla.com.
+125.93.134.189.in-addr.arpa.
+alerts.conduit-services.com.
+247.138.61.83.in-addr.arpa.
+a.root-servers.net.
+resources.search.conduit.com.
+www.soccerwallpaper.mackafe.com.
+a3.sphotos.ak.fbcdn.net.
+graph.facebook.com.
+android.clients.google.com.
+blog.macsales.com.
+75.94.91.186.in-addr.arpa.
+243.6.144.79.in-addr.arpa.
+itunes.apple.com.
+www.google.com.
+rotg.gazprom.ru.
+d2055212.instant.xoom.it.
+gm.
+ieonlinews.microsoft.com.
+disneyfanscolombia.blogspot.com.
+computerrepairservice.net.
+glow.draw.spankapps.com.
+www.belkin.com.
+caulfield-glen-eira-leader.whereilive.com.au.
+photos-h.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+bitly.com.
+a.root-servers.net.
+23.140.66.201.in-addr.arpa.
+vitaltareasdacs.files.wordpress.com.
+static.ak.fbcdn.net.
+211.208.1.187.in-addr.arpa.
+rover.ebay.com.
+a1505.l.akamai.net.
+208.215.174.190.in-addr.arpa.
+145.10.251.85.in-addr.arpa.
+negroprazers.blogspot.com.
+secure.wlxrs.com.
+podebradka.cz.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mail2.khh.com.
+apix.iminent.com.
+www.google-analytics.com.
+www.ford.com.
+bernhard.as.
+api.twitter.com.
+lzb.ac.cn.
+www.abeacha.com.
+www.google.com.uy.
+www.google.com.
+83.232.48.65.in-addr.arpa.
+a.root-servers.net.
+114.204.168.192.in-addr.arpa.
+utm.trk.mywebsearch.com.
+app9976039262.socialappspot.com.
+www.vankaizer.com.
+107.146.220.66.in-addr.arpa.
+50.90.138.98.zen.spamhaus.org.
+tpb.tracker.thepiratebay.org.
+4.220.90.186.in-addr.arpa.
+hac.datafeed.weatherbug.com.
+static.ak.fbcdn.net.
+www.youtube.com.
+pib.sagepub.com.
+194.11.0.10.in-addr.arpa.
+www.picnik.com.
+aws.amazon.com.
+a.root-servers.net.
+ar.astrology.yahoo.com.
+wingatenewtampa.com.
+fuanimes.obolog.com.
+142.6.62.186.in-addr.arpa.
+dsn1.d.skype.net.
+sormovo.ru.
+mail.bioflora.com.
+scat.nsk.su.
+sites.google.com.
+s-static.ak.fbcdn.net.
+multiply.com.
+46.218.131.187.in-addr.arpa.
+t.15yule.com.
+102.119.11.189.in-addr.arpa.
+a1402.w40.akamai.net.
+distilleryimage7.s3.amazonaws.com.
+creative.ak.fbcdn.net.
+theideabox.com.
+alertpayments.org.
+pixel.facebook.com.
+track.brighteroption.com.
+twitter.com.
+xcdn.xgraph.net.
+a1.sphotos.ak.fbcdn.net.
+aitmx6.prodigy.net.
+www.drdenimjeans.com.
+cache.pack.google.com.
+cdn1.differencebetween.com.
+tpc-usa.com.
+quadcmanagement.com.
+evsecure-crl.verisign.com.
+conntest.nintendowifi.net.
+www.google.com.
+www.thehotcars.com.
+rad.msn.com.
+facemoods.com.
+a12.t26.net.
+mx.mass.flexmail.ifxnetworks.com.
+by2msg3010614.gateway.messenger.live.com.
+uskh.com.s5a1.psmtp.com.
+bt.newfiles.ge.
+e-2dj6wjk4kicpocp.stats.esomniture.com.
+www.reddit.com.
+www.oscarvelazquez.es.
+www.paulsibley.net.
+isatap.home.
+tradersrealty.com.
+m.facebook.com.
+a.root-servers.net.
+share.meebo.com.
+www.col.org.pe.
+cineland.it.
+pagead2.googlesyndication.com.
+se2ojnn17.g88r7d7y.
+germinal.ru.
+d24elmu442q75h.cloudfront.net.
+30.117.11.189.in-addr.arpa.
+ping.chartbeat.net.
+28.183.109.84.in-addr.arpa.
+toolbarqueries.google.com.
+236.12.0.10.in-addr.arpa.
+www.belkin.com.
+profile.ak.fbcdn.net.
+likemindsearch.blogspot.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+chat.facebook.com.
+71.129.158.82.in-addr.arpa.
+api.twitter.com.
+www.smartglance.com.
+www.alliedvisiontec.com.
+mx.suddenlinkmail.com.
+it-it.facebook.com.
+229.118.206.190.in-addr.arpa.
+www.get10up.com.
+113.174.42.190.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+trace.geewa.ws.
+photos-g.ak.fbcdn.net.
+google.com.
+mobth1213.photobucket.com.
+beckson.com.
+profile.ak.fbcdn.net.
+tags.bluekai.com.
+fcss.eslamoda.com.
+t-ono.net.
+safebrowsing.clients.google.com.
+n:u2:aa6s.v73r9j6p.
+www.attarikh-alarabi.ma.
+platform.twitter.com.
+resources3.deepdiscount.com.
+76.218.35.189.in-addr.arpa.
+oildompublishing.com.inbound15.mxlogic.net.
+yahoo.com.
+.
+fbcdn-photos-a.akamaihd.net.
+a7.sphotos.ak.fbcdn.net.
+mail.greenfieldpartners.com.
+mail.ibc-rus.ru.
+sbcgloboel.net.
+mail.hitechsyringes.com.
+blr.vsnl.net.
+135.113.68.201.in-addr.arpa.
+content.yieldmanager.edgesuite.net.
+www.myspaceeditor.it.
+download828.avast.com.
+66.17.85.98.in-addr.arpa.
+165.1.172.201.in-addr.arpa.
+college.sciences-po.fr.
+apps.facebook.com.
+static.fc2.com.
+www.google.es.
+i1.ytimg.com.
+a.root-servers.net.
+apps.facebook.com.
+domobuilder.ru.
+www.kiki18blog.com.
+137.233.247.190.in-addr.arpa.
+www.tmbg.com.
+a.root-servers.net.
+feeds.tversity.com.
+www.facebook.com.
+kanztov.ru.
+barracuda.redcell.us.
+bta.kz.
+check4.facebook.com.
+mail.homeshowroom.com.tr.
+111.54.94.189.in-addr.arpa.
+musica.nexos.com.mx.
+s.youtube.com.
+www.3dtvworld.com.au.
+crl.microsoft.com.
+cdn-mkt.wooga.com.
+notlivialgreal.tk.
+images.google.com.
+localhost.
+187.11.229.109.in-addr.arpa.
+join.ruthblackwell.com.
+hbl.com.s200a1.psmtp.com.
+ajax.googleapis.com.
+smart-link.ru.
+230.102.199.190.in-addr.arpa.
+gy7phhdv5.r77f0j0g.
+api-read.facebook.com.
+nrce.com.inbound10.mxlogic.net.
+overlandwest.com.
+exchange.upsales.ru.
+s.xvideos.com.
+19.63.235.190.in-addr.arpa.
+groups.google.com.mx.
+english.stackexchange.com.
+www.google-analytics.com.
+cdn.tynt.com.
+gc76c5f21468d4c68.api.playtomic.com.
+cdn.api.twitter.com.
+sas.ru.
+de-de.facebook.com.
+skywork.ch.
+www.autos.clarin.com.
+214.174.138.187.in-addr.arpa.
+www.dressyourbodytype.com.
+ads.tlvmedia.com.
+www.cyta.com.ar.
+api.twitter.com.
+sipexternal.clariant.com.
+www.miauu.com.
+pu.rs.
+46.229.56.187.in-addr.arpa.
+www.mozilla.com.
+blog.touchmypixel.com.
+display-kim.ru.
+sjmneuro.com.s6a1.psmtp.com.
+www.flightops.sita.aero.
+www.bringitonmovie.com.
+ad.amgdgt.com.
+www.zuvik.com.
+youtu.be.
+tag.admeld.com.
+rt.legolas-media.com.
+s.ytimg.com.
+appworld.blackberry.com.
+ssl.gstatic.com.
+20minutos.feedsportal.com.
+a.root-servers.net.
+rosgold.ru.
+ds.serving-sys.com.
+b.hardcorebattle.com.
+photos-h.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+heartagramania.blogspot.com.
+www.redalyc.uaemex.mx.
+a.root-servers.net.
+_221_83_6.
+creative.ak.fbcdn.net.
+www.google.com.
+mail2.southernautogroup.com.
+cardiologygroup.com.
+www.faceboo.
+27.152.9.94.in-addr.arpa.
+es.starmedia.com.
+www.bized.co.uk.
+tools.google.com.
+richmondhabitat.org.
+prod1.rest-notify.msg.yahoo.com.
+shared.live.com.
+rs274tl5.rapidshare.com.
+rybinsk.info.
+cache.pack.google.com.
+235.112.109.75.in-addr.arpa.
+m.addthisedge.com.
+a5.sphotos.ak.fbcdn.net.
+97.18.217.196.in-addr.arpa.
+mail.google.com.
+25.42.14.201.in-addr.arpa.
+memesmansion.blogspot.com.
+85.14.141.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.umrg.com.
+hotmail.vo.msecnd.net.
+www.facebook.com.
+www.youtube.com.
+i.dailymail.co.uk.
+es-es.facebook.com.
+cdn.livestream.com.
+relay.tyre.kirov.ru.
+profile.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+dekstravel.ru.
+p.searchpreview.de.
+ia.wikipedia.org.
+www.vollversion.de.
+www.yahoo.com.
+58.187.182.188.in-addr.arpa.
+thegolfcartplaceinc.com.
+sc2.rules.mailshell.net.
+teredo.ipv6.microsoft.com.
+mail.ekonpowdercoating.com.
+r._dns-sd._udp.lan.
+133.65.69.186.in-addr.arpa.
+bslgroup.ru.
+dns.msftncsi.com.
+sugarsickness.tumblr.com.
+www.google.com.
+www.buzzflash.net.
+s661.photobucket.com.
+220.105.84.200.in-addr.arpa.
+col.stc.s-msn.com.
+couponbuddy.s3.amazonaws.com.
+dfd3ef97bb2147a3cbd6aa7aa78e17.mail.outlook.com.
+a.root-servers.net.
+21.23.216.178.in-addr.arpa.
+youtube-ui.l.google.com.
+tecnologia.starmedia.com.
+go.microsoft.com.
+www.gsistore.com.
+www.crashtest.com.
+topics.nytimes.com.
+lanashilosmania.blogspot.com.
+a6.sphotos.ak.fbcdn.net.
+frikimami.blogspot.com.
+a.root-servers.net.
+lfs-bruck.at.
+sp.cwfservice.net.
+a.root-servers.net.
+saltillo.olx.com.mx.
+arab-dance.com.
+40.15.1.190.in-addr.arpa.
+dodesign.net.
+ads.yimg.com.
+6.129.56.186.in-addr.arpa.
+by2msg3020413.gateway.messenger.live.com.
+graphicventuresinc.com.
+118.132.162.189.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.google.com.
+137.109.61.174.in-addr.arpa.
+89.1.168.192.in-addr.arpa.
+api.twitter.com.
+227.130.13.187.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+212.98.7.189.in-addr.arpa.
+mailserver.fruchthof.net.
+gw1.sektor74.ru.
+58.128.236.116.in-addr.arpa.
+translate.googleapis.com.
+_909_24_0.
+static.ak.fbcdn.net.
+postech.ac.kr.
+vcs2.msg.yahoo.com.
+live.sekindo.com.
+136.195.74.190.in-addr.arpa.
+_417_93_3.
+a1.sphotos.ak.fbcdn.net.
+tradukka.com.
+brothersoftextreme.ourtoolbar.com.
+_138_63_9.
+97.60.158.189.in-addr.arpa.
+samsungmobile.accu-weather.com.
+google.com.
+profile.ak.fbcdn.net.
+fgngztd59.62zp.
+es-es.facebook.com.
+54.48.234.189.in-addr.arpa.
+northgeorgia.edu.
+ic.tynt.com.
+s.youtube.com.
+partner.googleadservices.com.
+visitors.uxcell.com.
+www.historietasminimas.com.
+es.wikipedia.org.
+135.50.165.95.in-addr.arpa.
+ads.smowtion.com.
+t0.gstatic.com.
+a.root-servers.net.
+stainedglassa2z.com.
+www1.flashgamehq.com.
+l.addthiscdn.com.
+www.ig.gmodules.com.
+static.ak.fbcdn.net.
+fs274.uploading.com.
+herc.com.
+audiojelly.com.
+wvipctipad.ru.
+ad.yieldmanager.com.
+www.google.com.
+www.iplay.ca.
+a.root-servers.net.
+platform.twitter.com.
+googleads.g.doubleclick.net.
+mail.waccamawcardiology.com.
+static.xtravids.com.
+smbz.wikia.com.
+92.148.193.71.in-addr.arpa.
+104.170.28.180.in-addr.arpa.
+sel.ru.
+226.43.35.187.in-addr.arpa.
+cdn.mediafire.com.
+profile.ak.fbcdn.net.
+google.com.
+www.hotline.travel.
+img-cdn.mediaplex.com.
+google.com.
+nht-3.extreme-dm.com.
+_853_04_6.
+photos-g.ak.fbcdn.net.
+149.46.75.201.in-addr.arpa.
+d3lvr7yuk4uaui.cloudfront.net.
+mamatriedinc.com.
+www.facebook.com.
+76.170.161.189.in-addr.arpa.
+211.117.85.89.in-addr.arpa.
+142.32.13.180.in-addr.arpa.
+www.bankofalbania.org.
+thumbs3.ebaystatic.com.
+relay.voice.edge.messenger.live.com.
+tb2000.ru.
+apis.google.com.
+www.ara.cat.
+.
+9.90.186.189.in-addr.arpa.
+disosa-chemicals.com.
+a672.g.akamai.net.
+www.vamosapublicidad.com.
+email.tww.net.
+api.facebook.com.
+multiplos.hotwords.es.
+mail.contorgroup.ro.
+bmp.in.
+external.ak.fbcdn.net.
+ad.yieldmanager.com.
+www.7red.no.
+estaticos.marca.com.
+www.google.com.
+ksn7-12.kaspersky-labs.com.
+www.kpopgames.com.
+lrco.com.
+briarlane.ca.
+www.home-theatre-systems.net.
+dmail.com.lan.
+caster.cricinfo.com.
+249.196.160.190.in-addr.arpa.
+221.127.213.190.in-addr.arpa.
+www.google.com.mx.
+widget-2d.slide.com.
+c13.zedo.com.
+mx.unionpress.net.
+www.time.com.
+www.facebook.com.
+self-improvement.meetup.com.
+219.151.176.190.in-addr.arpa.
+www.construireenbretagne.com.
+www.herbivoracious.com.
+43.99.125.186.in-addr.arpa.
+mail.zhongshi.com.
+66zgr3ks1.y30u4p3e.
+multi.xnxx.com.
+105.191.143.187.in-addr.arpa.
+clients1.google.com.
+www.belkin.com.
+196.51.69.190.in-addr.arpa.
+imageshack.us.
+acep.org.2.arsmtp.com.
+ksdua.com.
+i42.servimg.com.
+www.fidodido.com.
+photos-e.ak.fbcdn.net.
+smtp.aol.com.
+photos-f.ak.fbcdn.net.
+www.google.com.
+235.155.26.125.in-addr.arpa.
+a.root-servers.net.
+csi.gstatic.com.
+www.blogsmithmedia.com.
+photos-b.ak.fbcdn.net.
+denverphone.com.2.0001.arsmtp.com.
+www.zaman.com.tr.
+elalijar.blogspot.com.
+169.38.168.192.in-addr.arpa.
+api-read.facebook.com.
+www.tudiscovery.com.
+sp.cwfservice.net.
+balfourbeattyus.com.
+mail.pokerodds.ru.
+babia.net.
+0.thekrazycouponlady.com.
+translate.googleapis.com.
+weather.service.msn.com.
+62.185.230.190.in-addr.arpa.
+www.stenchradio.com.
+sp.cwfservice.net.
+a.root-servers.net.
+230.174.250.186.in-addr.arpa.
+adserving.cpxinteractive.com.
+newsletter.lyleandscott.com.
+logv33.xiti.com.
+profile.ak.fbcdn.net.
+www.cph-artfestival.org.
+bmsi.org.
+heartbeat.belkin.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.blogsperu.com.
+i2qk4wq4e.l25b5b3l.
+a.root-servers.net.
+ds.serving-sys.com.
+profile.ak.fbcdn.net.
+secure.traveladvertising.com.
+creative.ak.fbcdn.net.
+5.49.140.78.in-addr.arpa.
+msc.wlxrs.com.
+www.gaurijog.com.
+smtp.live.com.
+www.aguilas.tv.
+i3.ytimg.com.
+www.caymanwireless.com.
+photos-b.ak.fbcdn.net.
+media.admob.com.
+www.google-analytics.com.
+sharethis.com.
+api.pinger.com.
+239.222.228.190.in-addr.arpa.
+bin-short.whatsapp.net.
+slb.liveprofile.com.
+markmurphycpa.com.
+85.229.40.187.in-addr.arpa.
+tools.google.com.
+htsannupponew.tm.
+novshadyan.com.
+image.globalwaronline.com.
+www.facebook.com.
+fbcdn-sphotos-a.akamaihd.net.
+178.223.184.79.in-addr.arpa.
+developers.facebook.com.
+soypichichita.blogspot.com.
+imrk.com.
+ad-dc2.adtech.de.
+www.lawlib.state.ma.us.
+www.facebook.com.
+plusone.google.com.
+apis.google.com.
+android.clients.google.com.
+www.theultimateboxingworkout.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+_032_11_2.
+s10179.netschools.com.
+wfbssvc3.icrc.trendmicro.com.
+static.ak.fbcdn.net.
+momeni.com.inbound15.mxlogicmx.net.
+www.humornegro.com.
+sup.live.com.
+wellspun-ec.com.
+www.youtube.com.
+www.ilightr.com.
+ar-ar.facebook.com.
+uu1.orbitdownloader.com.
+www.lovelyshoes.net.
+10.142.10.186.in-addr.arpa.
+www.elements4health.com.
+clients1.google.com.
+js.xcar.com.cn.
+myci.csuci.edu.
+48.149.220.66.in-addr.arpa.
+s2.youtube.com.
+a2.sphotos.ak.fbcdn.net.
+rad.msn.com.
+53.38.55.94.in-addr.arpa.
+vibratorvpope.ru.
+googleads.g.doubleclick.net.
+wpad.
+bapp.n.shifen.com.
+106.69.105.175.in-addr.arpa.
+s7.addthis.com.
+advertise.courant.com.
+profile.ak.fbcdn.net.
+potterfics.com.
+ad.doubleclick.net.
+bieberfile.tumblr.com.
+tracker.marinsm.com.
+us.data.toolbar.yahoo.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+clients2.google.com.
+196.230.135.189.in-addr.arpa.
+playerservices.streamtheworld.com.
+bs.serving-sys.com.
+twitter.com.
+www.cnnc.com.cn.
+photos-f.ak.fbcdn.net.
+126.29.139.189.in-addr.arpa.
+fyi.zerolost.org.
+189.65.203.190.in-addr.arpa.
+70.193.180.95.in-addr.arpa.
+modjeski.com.
+ucoz.com.
+screen.yahoo.com.
+img.mediaplex.com.
+www.icono-computadoras-pc.com.
+static.ak.fbcdn.net.
+31.77.228.190.in-addr.arpa.
+v6.cache5.c.youtube.com.
+direct.weatherbug.com.
+thermomt.com.
+login.emlak.net.
+mail.didacware.ch.
+mafiaconnection.ru.
+platform.twitter.com.
+asset3.skimble.com.
+www.latrache.com.
+241.34.3.187.in-addr.arpa.
+a.root-servers.net.
+158.172.120.186.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.tumblr.com.
+ssl.gstatic.com.
+www.archenergy.com.
+www.guj.com.br.
+cdptpa-smtpin01.houston.rr.com.
+photos-h.ak.fbcdn.net.
+cdr-software.softonic.com.
+b-0.19-23066089.80110b1.1518.19d4.3ea1.410.0.hllbgf7zr53c248br15qke4gmv.avqs.mcafee.com.
+a5.sphotos.ak.fbcdn.net.
+msn.foxsports.com.
+smtp.srv.ualberta.ca.
+www.frangipane.org.
+stainless-steel.ru.
+c799491.r91.cf2.rackcdn.com.
+127.0.0.1.
+external.ak.fbcdn.net.
+d2105616.xoom.it.
+a1005.w42.akamai.net.
+139.255.214.98.in-addr.arpa.
+99.183.140.203.in-addr.arpa.
+218.25.122.190.in-addr.arpa.
+gmail.com.
+www.adservitrack.com.
+t1.gstatic.com.
+a.root-servers.net.
+www.facebook.com.
+jralert05.emailsp.it.
+5-1.qlty.finarea.ch.
+b.scorecardresearch.com.
+kidshealth.org.
+134.136.105.186.in-addr.arpa.
+deframx24.softcom.dk.
+sn104w.snt104.mail.live.com.
+pjjkp.com.
+www.youtube.com.
+30.video.mystreamservice.com.
+newsrss.bbc.co.uk.
+www.enlightenedbeings.com.
+ia700200.us.archive.org.
+epaenlinea.empleate.com.
+eldiariony.com.s8b2.psmtp.com.
+float-spacer.ru.
+static.ak.fbcdn.net.
+forums.petfinder.my.
+d2102338.xoom.it.
+shipwreck.me.
+inbound.truly.com.netsolmail.net.
+165.82.149.189.in-addr.arpa.
+www.adobe.com.
+8drs:mii7.26yr.
+img2.submanga.com.
+secure-uk.imrworldwide.com.
+c.live.com.
+ec.atdmt.com.
+_849_80_1.
+www.tommys.co.nz.
+pueblo.net.
+69.181.185.190.in-addr.arpa.
+a.root-servers.net.
+au-au.ru.
+photos-h.ak.fbcdn.net.
+43.196.209.91.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+secure-us.imrworldwide.com.
+www.finalteens.com.
+goodvibes.com.
+photos-a.ak.fbcdn.net.
+widgets.twimg.com.
+payment.socialgamenet.com.
+calculator-online.org.
+bstat.mywebsearch.com.
+pop001.masterhost.ru.
+google.com.
+spamsafe2.sctsystems.co.uk.
+20-courier.push.apple.com.
+akinator.co.
+johnmoltarealty.com.
+189.172.173.187.in-addr.arpa.
+ssl.google-analytics.com.
+a.root-servers.net.
+mgnet.com.
+213.58.49.186.in-addr.arpa.
+alico.com.np.
+join.gloryhole-initiations.com.
+a.root-servers.net.
+udc.msn.com.
+ssl.gstatic.com.
+developers.facebook.com.
+external.ak.fbcdn.net.
+parus.nsk.su.
+www.vphairstyles.com.
+debevec.org.
+www.google-analytics.com.
+m.facebook.com.
+98.103.170.201.in-addr.arpa.
+40.135.69.217.in-addr.arpa.
+c.prodigy.msn.com.
+rdmgmtllc.com.s10a1.psmtp.com.
+85.79.41.79.in-addr.arpa.
+cacherito.msk.ru.
+pages.ebay.com.
+www.magisterio.com.co.
+33.16.51.189.in-addr.arpa.
+24.157.220.189.in-addr.arpa.
+cgi5.ebay.com.
+82.127.213.201.in-addr.arpa.
+146.62.207.200.in-addr.arpa.
+s.youtube.com.
+eventosenlinea.blogspot.com.
+ccfamilyhc.com.
+www.dream-crane.com.
+0-staging.channel.facebook.com.
+d2106850.xoom.it.
+a7.sphotos.ak.fbcdn.net.
+m.ak.fbcdn.net.
+comcoupons.com.
+sender5.critsend.com.
+www.facebook.com.
+j.clickdensity.com.
+ksn2-12.kaspersky-labs.com.
+www.juegosdecocina.co.
+fbcdn-photos-a.akamaihd.net.
+www.facebook.com.
+gazdefrance.es.
+platform.twitter.com.
+billing.sharo4ka.ru.
+54.43.212.201.in-addr.arpa.
+www3.virtualedge.com.
+a7.sphotos.ak.fbcdn.net.
+premiertruckcenter.com.
+1ee2f.v.fwmrm.net.
+www.ideal-school.com.
+woin.ru.
+js-kit.com.
+www.dvdvideotool.com.
+hat.net.
+62.0.100.82.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+elegance.ru.
+22.56.6.186.in-addr.arpa.
+www.portalubuntu.com.
+www.google.com.
+kr.kpost.search.yahoo.com.
+a.root-servers.net.
+www.canaanfairtrade.com.
+32.0.59.186.in-addr.arpa.
+upload.facebook.com.
+csi.gstatic.com.
+alerts.conduit-services.com.
+199.193.253.190.in-addr.arpa.
+www.facebook.com.
+a995.mm1.akamai.net.
+l.yimg.com.
+dns.msftncsi.com.
+010d3230302e392e3132382e3231300000.lbl8.mailshell.net.
+wa.virgilio.it.
+www.google.com.
+www.elnashrafan.com.
+ssl.gstatic.com.
+56.209.50.201.in-addr.arpa.
+trillian.brothersoft.com.
+www.wip4.adobe.com.
+cftfire.com.
+www.nescafe.es.
+a2.sphotos.ak.fbcdn.net.
+7-courier.push.apple.com.
+103.61.106.186.in-addr.arpa.
+cdn1.videothumbs.xtube.com.
+time.chttl.com.tw.
+18.201.175.190.in-addr.arpa.
+194.57.74.190.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+miks-pix.blogspot.com.
+photos-e.ak.fbcdn.net.
+mailgate.server-mail.com.
+www.google-analytics.com.
+www.cartoonnetwork.cl.
+46.5.19.177.in-addr.arpa.
+itsbebeipa01p.eu.jnj.com.
+t4.liverail.com.
+mail.google.com.
+a7.sphotos.ak.fbcdn.net.
+_490_97_9.
+csi.gstatic.com.
+a8.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+www.7elm1.com.
+www.jsoftj.com.
+mailcloud6.ourmailservers.net.
+zh-cn.facebook.com.
+mm.servidornoticias.com.
+a.root-servers.net.
+a.root-servers.net.
+8h5aws2pj.77zi.
+www.youtube.com.
+www.sqm.microsoft.com.
+igoogle-skins.googleusercontent.com.
+c.thumbs.redditmedia.com.
+fmail.infotek.ru.
+mail.martin-riley.com.
+platis.updates.pandasoftware.com.
+tbr.ask.com.
+ad.yieldmanager.com.
+developers.facebook.com.
+img1.blogblog.com.
+fpa5b1qrq.a61z3y9j.
+en.wikipedia.org.
+l9ni:4pz5.b20y8k4h.
+miescuelita.org.
+cuneo.alpcom.it.
+entretenimiento.latam.msn.com.
+v45zivrkd.99ql.
+embarzmail.com.
+143.61.4.64.in-addr.arpa.
+nucor-seattle.com.s7a1.psmtp.com.
+149.190.30.211.in-addr.arpa.
+xzqpypjovkvkph.com.
+33.52.244.189.in-addr.arpa.
+217.215.235.201.in-addr.arpa.
+mail4.gosafco.com.
+add.my.yahoo.com.
+apix.iminent.com.
+photos-c.ak.fbcdn.net.
+201.68.155.114.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.youtube.com.mx.
+micromentis.com.
+ssl.gstatic.com.
+pnhoffman.com.s5b2.psmtp.com.
+leadersinstitute.com.s7b2.psmtp.com.
+www.virginsdesires.com.
+www.iminent.com.
+metrics.apple.com.
+developers.facebook.com.
+feedburner.google.com.
+146.238.39.187.in-addr.arpa.
+www.youtube.com.
+www.hotmilfhunter.com.
+235.14.115.212.in-addr.arpa.
+www.google.com.mx.
+p44-buy.itunes.apple.com.
+rasgarelvelo.blogspot.com.
+clients2.google.com.
+a4.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+russianfemdom.net.
+87.133.34.186.in-addr.arpa.
+a1057.b.akamai.net.
+i.holder.com.ua.
+olivia.com.s5a2.psmtp.com.
+aapexbank.com.
+204.225.138.190.in-addr.arpa.
+cheeseclub.ru.
+a2.espncdn.com.
+twf.com.au.
+www.google.com.
+233.235.163.67.in-addr.arpa.
+ia600205.us.archive.org.
+v21.lscache5.c.bigcache.googleapis.com.
+a3.sphotos.ak.fbcdn.net.
+b-0.19-a3004008.c071081.1518.19d4.3ea1.410.0.hb9dnwhqwczv6eeqserq9nrsgi.avqs.mcafee.com.
+songsofpraise.com.
+pixel.facebook.com.
+_892_54_1.
+43.16.173.70.in-addr.arpa.
+profile.ak.fbcdn.net.
+119.58.146.186.in-addr.arpa.
+c.msn.com.
+tlc.ousd.k12.ca.us.
+baboolercheme.org.
+a8.sphotos.ak.fbcdn.net.
+fr-fr.facebook.com.
+wvxmil7ki.x48a2q8e.
+dns.msftncsi.com.
+services.google.com.
+www.comidacolombiana.com.
+www.detounchin.com.
+cdn.meaningtool.com.
+www.humidipak.com.
+47.161.84.187.in-addr.arpa.
+nkb8cn1t4.w62m0z6u.
+earthlink.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+lovetransfusion.tumblr.com.
+www.ediets.com.
+e906.g.akamaiedge.net.
+_574_16_4.
+a4.sphotos.ak.fbcdn.net.
+mx.answers.yahoo.com.
+portalnw.ru.
+www.bywifi.com.
+132.162.20.190.in-addr.arpa.
+www.hk-kicks.com.
+www.bing.com.
+losangeles.imprelistas.com.
+a1.sphotos.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+espire.net.
+connect.facebook.net.
+sp.cwfservice.net.
+fbcdn-photos-a.akamaihd.net.
+mail.jvkmovers.com.
+a.root-servers.net.
+www.girlsgogames.es.
+40.29.53.83.in-addr.arpa.
+cms.quantserve.com.
+mail.110sf.ru.
+sabine.com.
+kronix.ru.
+mail.xn--80adhndn9l.com.
+a7.sphotos.ak.fbcdn.net.
+mscrl.microsoft.com.
+summerthymestudio.blogspot.com.
+developers.facebook.com.
+contextmenu.toolbar.conduit-services.com.
+widget3.linkwithin.com.
+prensahistorica.mcu.es.
+a.root-servers.net.
+bmw-avtohaus.ru.
+243.185.65.85.in-addr.arpa.
+191.225.253.201.in-addr.arpa.
+developers.facebook.com.
+bobmakarley.ru.
+mpv.web.aol.com.
+ksn2-12.kaspersky-labs.com.
+www.tedligety.com.
+www.chandrakclarke.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+baymsg1020323.gateway.messenger.live.com.
+api.twitter.com.
+202.113.143.114.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.winajuda.com.
+affiliate.ru.
+957993.r.msn.com.
+smtp.domainsbyproxy.com.
+comersantander.com.
+novelasconfamosos.globered.com.
+xompuserve.com.
+tobolsk.info.
+css.wlxrs.com.
+photos-a.ak.fbcdn.net.
+211.149.195.210.in-addr.arpa.
+api.twitter.com.
+a.root-servers.net.
+development1.entremed.com.
+c.f.4.f.7.6.b.2.d.f.b.3.c.5.0.1.d.f.9.7.5.f.e.5.0.0.0.0.1.0.0.2.ip6.arpa.
+www.facebook.com.
+14.251.48.190.in-addr.arpa.
+a1404.w41.akamai.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx3.mariinsky.ru.
+i1.ytimg.com.
+mccaffetyelectric.com.
+somosnicas.net.
+2.89.177.83.in-addr.arpa.
+a03.t26.net.
+a.root-servers.net.
+static.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.a9euros.com.
+apnmedia.ask.com.
+mysoul.com.au.
+www.spiegel.tv.
+www.adultdreamlinks.com.
+www.mandco.com.
+a.root-servers.net.
+www.lobosoft.es.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+inbound.cancrate.com.netsolmail.net.
+ymlp310.net.
+idsa.org.s7b2.psmtp.com.
+a.root-servers.net.
+roadplanet.ru.
+clients1.google.com.mx.
+jazzguitar.com.
+mejormevoy.com.
+apps.facebook.com.
+rblns81.mailshell.net.
+photos-h.ak.fbcdn.net.
+45.74.95.201.in-addr.arpa.
+marbel.sp.ru.
+ridproject.ru.
+www.facebook.com.
+edge.quantserve.com.
+vefire.ru.
+mail.margoliscapital.com.
+a.root-servers.net.
+188.39.49.186.in-addr.arpa.
+fxfeeds.mozilla.com.
+www.devilly.org.
+photos-a.ak.fbcdn.net.
+204.37.127.200.in-addr.arpa.
+11.66.201.71.in-addr.arpa.
+cdn.applifier.com.
+a.root-servers.net.
+lolnewera.forumclan.net.
+checkip.dyndns.org.
+40.12.254.98.in-addr.arpa.
+external.ak.fbcdn.net.
+www.facebook.com.
+iepwbpb4a.87tf.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+totalcmd.pl.
+crwscdn8.appspot.com.
+41.75.154.189.in-addr.arpa.
+bart25s-paintjobfabrik.blogspot.com.
+profile.ak.fbcdn.net.
+third-rate.com.
+pro-activesolutions.net.
+hi-in.facebook.com.
+gulfcoastfibres.com.
+alliegiance.tv.
+rs505dt.rapidshare.com.
+grudniowo.soup.io.
+cch-lis.com.
+mi-medianaranja.blogspot.com.
+content.yieldmanager.edgesuite.net.
+kislorod-nn.ru.
+a-0.19-21099001.9090083.1518.19d3.3ea1.410.0.h4g5975dfhvrdrzlmhdmk2rzwv.avqs.mcafee.com.
+26.147.218.2.in-addr.arpa.
+5.58.106.189.in-addr.arpa.
+freshdailyblog.blogspot.com.
+seal.thawte.com.
+developers.facebook.com.
+www.lasabrosita.fm.
+cdn1.predictad.com.
+www.cmcmedicalgroup.es.
+creative.ak.fbcdn.net.
+www.proverbia.net.
+ad.doubleclick.net.
+25.media.tumblr.com.
+lightenupradio.com.
+blog.farmville.com.
+_435_96_3.
+cis.netmng.com.
+147.92.122.200.in-addr.arpa.
+173.32.146.187.in-addr.arpa.
+layouts.ru.
+pqdgvyjqjk.com.
+www.miletra.net.
+87.103.188.186.in-addr.arpa.
+c-0.19-2309c481.30483.1518.19d4.2f28.10.0.5ej8v54t12timlrc9ibsua66di.avqs.mcafee.com.
+about.tagged.com.
+a.root-servers.net.
+ewatches.com.
+facebook.conduitapps.com.
+162.5.195.187.in-addr.arpa.
+a749.g.akamai.net.
+gfx4.hotmail.com.
+plus.google.com.
+static.ak.fbcdn.net.
+www.youtube.com.
+photos-c.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+cload.com.
+m1.joymii.com.
+i1.ytimg.com.
+ib.adnxs.com.
+menuaingles.blogspot.com.
+external.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+209.151.1.190.in-addr.arpa.
+rtm.ebaystatic.com.
+mx.msn.recepedia.com.
+aloe-a.net.ru.
+104.40.203.190.in-addr.arpa.
+www.cpc.cl.
+humor.orange.es.
+m.adnxs.com.
+229.156.148.92.in-addr.arpa.
+19.111.39.190.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.faceb.
+a.root-servers.net.
+www.keygens.biz.
+clients1.google.com.
+wp.me.
+28.191.231.190.in-addr.arpa.
+irc.kelebekmafia.com.
+vlarock.ru.
+hi-in.facebook.com.
+a1404.w41.akamai.net.
+c0013989.ssl.cf1.rackcdn.com.
+www.google.com.
+static.ak.fbcdn.net.
+puffballsunited.newgrounds.com.
+_185_69_9.
+tobolsk.info.
+www.reachoutmichigan.org.
+developers.facebook.com.
+ff.media.v4.skyrock.net.
+sp.cwfservice.net.
+www.zenitalk.com.
+hjltxrqnvupgm.com.
+svod.espn.go.com.
+websearch.ask.com.
+117.218.8.78.in-addr.arpa.
+a.root-servers.net.
+hgddgbmbtvns.yi.org.
+ohsheglows.lightbox.com.
+connect.facebook.net.
+155.37.150.79.in-addr.arpa.
+the-sims-2.en.malavida.com.
+cmd-law.com.s9b1.psmtp.com.
+petroffbank.ru.
+225.55.46.189.in-addr.arpa.
+m.addthisedge.com.
+www.google.com.
+99.64.180.88.in-addr.arpa.
+ad.doubleclick.net.
+a3.sphotos.ak.fbcdn.net.
+0-jh-w.channel.facebook.com.
+static.yooco.de.
+graph.facebook.com.
+qtbuilders.com.
+www.letsdeal.no.
+bluewin.ch.
+pheedo-rdr.msnbc.msn.com.
+derek.netpivotal.com.
+186.82.190.71.in-addr.arpa.
+www.dlhonline.co.uk.
+lkckclcklii1i.com.home.
+outlookcbts.enterprisenet.org.
+90.72.26.190.in-addr.arpa.
+support.google.com.
+crl.microsoft.com.
+www.vibop.com.
+www.google.com.
+au.download.windowsupdate.com.
+135.245.158.200.in-addr.arpa.
+www.pgm-class.org.
+doc-10-80-docsviewer.googleusercontent.com.
+72.198.171.201.in-addr.arpa.
+a.root-servers.net.
+g.live.com.
+apps.facebook.com.
+www.bunnies4money.com.
+a.root-servers.net.
+216.67.100.190.in-addr.arpa.
+developers.facebook.com.
+qglcufhn7.b47z0d3o.
+profile.ak.fbcdn.net.
+baseball.cbssports.com.
+es.answers.yahoo.com.
+a5.sphotos.ak.fbcdn.net.
+mx0.day.org.
+dolsenco.com.inbound15.mxlogic.net.
+thumbs3.ebaystatic.com.
+www.googleadservices.com.
+www.google-analytics.com.
+brewich.com.
+imagesperiodicook.s3.amazonaws.com.
+247.91.27.190.in-addr.arpa.
+csi.gstatic.com.
+i324.photobucket.com.
+209.130.46.189.in-addr.arpa.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+18.128.3.211.in-addr.arpa.
+87.125.34.189.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.laredoute.de.
+bucks.edu.s9a2.psmtp.com.
+secure.shared.live.com.
+ksn2-12.kaspersky-labs.com.
+djesibonajeb.com.
+checkip.dyndns.com.
+russian-business.ru.
+smtp.hoffmaster.com.
+holichaxor.com.
+www.googleadservices.com.
+mail.thau.co.uk.
+www.paranormal-fr.net.
+ksn2-12.kaspersky-labs.com.
+ocsp.digicert.com.
+realdatamanagement.com.
+zynga1-a.akamaihd.net.
+skywaynews.net.
+redkid.net.
+commentarymagazine.us2.list-manage.com.
+139.253.213.83.in-addr.arpa.
+hotsms.ru.
+arriesgo.wordpress.com.
+ksn2-12.kaspersky-labs.com.
+a.root-servers.net.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+134.84.216.217.in-addr.arpa.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+connect.facebook.net.
+girl.kizifriv.com.
+unitarius.hu.
+d2059932.instant.xoom.it.
+westonlogistics.com.
+api.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+mail.burson-weathers.com.
+www.ingilizcecin.net.
+www.eclipstore.com.
+190.120.221.95.in-addr.arpa.
+217.72.178.190.in-addr.arpa.
+www.sqm.microsoft.com.
+85.135.171.77.in-addr.arpa.
+plus.google.com.
+client-software.real.com.
+www.googletagservices.com.
+youtu.be.
+168.19.168.192.in-addr.arpa.
+apis.google.com.
+blog.analytics.tapulous.com.
+store.yossawat.com.
+nwland.ru.
+anaphraseus.sourceforge.net.
+profile.ak.fbcdn.net.
+antal-int.com.
+r._dns-sd._udp.0.129.37.10.in-addr.arpa.
+external.ak.fbcdn.net.
+www.locusmicrowave.com.
+20minutos.feedsportal.com.
+34.219.44.200.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.france24.com.
+160.66.153.186.in-addr.arpa.
+platform.ak.fbcdn.net.
+dnl-01.geo.kaspersky.com.
+serv01.colo.owned.hu.
+d2090733.xoom.it.
+empresas.mundo-r.com.
+107.170.113.79.in-addr.arpa.
+jackdanielsmotors.com.
+encrypted-tbn0.google.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+206.116.155.81.in-addr.arpa.
+budgetresale.com.
+static.ak.fbcdn.net.
+andrew-mcculloch.co.uk.
+140.235.195.62.in-addr.arpa.
+ja.y8.com.
+cainet.com.br.
+thenetherworks.com.
+crl.globalsign.net.
+game3a.com.
+eth0.
+google.com.
+www.4cdg.com.
+diarioaxaca.com.
+25.93.62.61.in-addr.arpa.
+12.20.0.10.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+connect.facebook.net.
+www.biotherm.co.uk.
+32.39.169.68.in-addr.arpa.
+www.aljazeera.net.
+a.root-servers.net.
+metaline.de.
+static.ak.fbcdn.net.
+pkids.files.wordpress.com.
+167.39.168.192.in-addr.arpa.
+connect.facebook.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cdn1.widdit.com.
+cf.addthis.com.
+www.sugudeli.jp.
+p49-buy.itunes.apple.com.
+www.tccandler.com.
+www.loveisdashit.com.
+toolbar.thepiratebay.se.
+a.root-servers.net.
+scribe.twitter.com.
+mailout.burlington-nj.net.
+www.ivgstores.com.
+www.turbogears.org.
+photos-g.ak.fbcdn.net.
+sp.cwfservice.net.
+microlinear.com.
+a.root-servers.net.
+a.root-servers.net.
+cdn.turn.com.
+150.223.142.187.in-addr.arpa.
+pixel.quantserve.com.
+154.81.173.190.in-addr.arpa.
+www.google.com.
+webcache.googleusercontent.com.
+smtp.crossconnectcentral.com.
+camilocartagena.com.
+microtekmed.com.
+gic-it.de.
+59.39.251.180.in-addr.arpa.
+static.ak.fbcdn.net.
+www.miescolarium.com.
+ngfarah.com.au.
+weather.service.msn.com.
+edge.quantserve.com.
+nccpr.p2p.baofeng.net.
+d24w6bsrhbeh9d.cloudfront.net.
+holessence.wordpress.com.
+servicios.prodigy.msn.com.
+a524.g.akamai.net.
+photos-g.ak.fbcdn.net.
+relay.quorum.ru.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+evsecure-ocsp.verisign.com.
+mail.cyberquest.com.
+mobile.myspace.com.
+www.facebook.com.
+208.244.134.187.in-addr.arpa.
+creative.ak.fbcdn.net.
+i3.ytimg.com.
+googleads.g.doubleclick.net.
+api.facebook.com.
+yourfavoriterealtors.com.
+es.nntp2http.com.
+a.root-servers.net.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+colonialkc.org.2.0001.arsmtp.com.
+223.135.192.180.in-addr.arpa.
+www.google-analytics.com.
+dnl-01.geo.kaspersky.com.
+www.jugosylicuados.com.
+frankcooney.com.
+mrmelkwintergames.hyper.no.
+themes.belchfire.net.
+a.root-servers.net.
+www.google-analytics.com.
+lucy.corp.netopia.com.
+sinaman.com.
+googleads.g.doubleclick.net.
+dns.msftncsi.com.
+www.archive.org.
+www.todaycal.com.
+a.root-servers.net.
+gcserevision101.wordpress.com.
+fexobkn.es.tl.
+oldmdgirl.blogspot.com.
+59.205.11.189.in-addr.arpa.
+16.209.70.166.in-addr.arpa.
+www.facebook.com.
+goo.gl.
+armmf.adobe.com.
+espanol.orlando-florida.net.
+www.todotorrents.com.
+b.scorecardresearch.com.
+a.root-servers.net.
+53.194.22.186.in-addr.arpa.
+ilogic.ru.
+pjrwadulmbvc.info.
+news.google.com.mx.
+mail.renneberg.com.
+download.iolo.net.
+radio.blackplanet.com.
+smtp.blink.ca.
+178.116.173.190.in-addr.arpa.
+itbriefing.net.
+www.facebook.com.
+mail.internationaldg.com.
+www.update.microsoft.com.
+www.nataliaoreiro.com.
+vanbortel.com.inbound10.mxlogicmx.net.
+www.ecs.gov.bd.
+mail.aai-office.com.
+i3.imageban.ru.
+mail.hooddistribution.com.
+class.ee.iastate.edu.
+esteparticular.wordpress.com.
+mailgate.learningderby.net.
+dns.msftncsi.com.
+a2.sphotos.ak.fbcdn.net.
+www.romeoburner.com.
+www.facebook.com.
+bjornfree.com.
+creative.ak.fbcdn.net.
+apple.com.
+update.avg.com.
+a8.sphotos.ak.fbcdn.net.
+i1.ytimg.com.
+time.nist.gov.
+131.61.83.160.in-addr.arpa.
+developers.facebook.com.
+entertainment.wikia.com.
+faceboock.com.
+a1.da1.akamai.net.
+shtihmass.ru.
+wsteele.com.s8a2.psmtp.com.
+168.82.85.78.in-addr.arpa.
+w.sharethis.com.
+i4.ytimg.com.
+cmap.am.ace.advertising.com.
+www.rankingshq.com.
+www.facebook.com.
+cbuk.112.2o7.net.
+101.7.168.192.in-addr.arpa.
+117.250.215.108.in-addr.arpa.
+hitstatus.com.
+www.asociacionportimujer.org.
+router.bittorrent.com.
+dns.msftncsi.com.
+www.tuenti.com.
+byfiles.storage.msn.com.
+twitter.com.
+www.galleries.teenemery.com.
+zbar.zynga.com.
+moodyvalleyins.com.2.arsmtp.com.
+the-best-tour.com.
+www.carpediem-services.com.
+americanmicrosemi.com.
+141.171.49.211.in-addr.arpa.
+a.root-servers.net.
+xl.topstat.com.
+dplus.net.
+ad.adnetwork.net.
+www.izle.ilahisevenler.com.
+a.root-servers.net.
+www.tdt-latinoamerica.tv.
+www.google.com.
+www.isg-apple.com.akadns.net.
+liveonletterman.radio.com.
+170.206.178.186.in-addr.arpa.
+secure.vaginalcumshots.com.
+ifroggy.com.
+afrhomeloans.com.s8a2.psmtp.com.
+pagead2.googlesyndication.com.
+lacasadeshiva.blogspot.com.
+pixel.facebook.com.
+www.development.fighthubtv.com.
+a.root-servers.net.
+166.14.224.189.in-addr.arpa.
+sn105w.snt105.mail.live.com.
+118.164.6.200.in-addr.arpa.
+_246_96_4.
+www.gaga101.nl.ae.
+dns.msftncsi.com.
+a6.sphotos.ak.fbcdn.net.
+94.79.3.27.in-addr.arpa.
+.
+128.220.45.173.in-addr.arpa.
+www.allipodtouchwallpapers.com.
+es-es.facebook.com.
+crl.globalsign.net.
+bs.serving-sys.com.
+www.google-analytics.com.
+www.themasterteacher.tv.
+optimized-by.rubiconproject.com.
+ad-apac.doubleclick.net.
+122.93.116.121.in-addr.arpa.
+comceptos.com.
+iguana-tango.com.
+tags.bluekai.com.
+voipb.sip.yahoo.com.
+_146_63_6.
+182.217.18.187.in-addr.arpa.
+www.gatewayworkshops.com.
+arribaelachancha.cl.
+static-0.farmville.com.
+m.addthisedge.com.
+www.youtube-mp3-download.com.
+rsup8.rising.com.cn.home.
+evt.adrcntr.com.
+www.reforma.com.
+127.42.82.200.in-addr.arpa.
+msn.com.
+0.gravatar.com.
+creative.ak.fbcdn.net.
+a.c-0.19-21094000.10033.1518.19b2.410a.400.9d.kw1163b1wmniwtu1r3flrs4f8q.avqs.mcafee.com.
+tattoodesignspictures.com.
+publicbt.ath.cx.
+imagenen1.247realmedia.com.
+de-de.facebook.com.
+graph.facebook.com.
+centrelab.com.
+mx.usa.net.
+animeytv.com.
+xdcnq7lq9.11qn.
+d15gt9gwxw5wu0.cloudfront.net.
+ads.yimg.com.
+a.root-servers.net.
+myweb2.search.yahoo.com.
+253.40.141.189.in-addr.arpa.
+mail.google.com.
+nfbkids.ca.
+api.twitter.com.
+a-0.19-21093008.5000083.1518.19d4.3ea1.410.0.2hhg9t58pwjl629vqnrvmpg4lb.avqs.mcafee.com.
+131.41.194.187.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+65.147.61.83.in-addr.arpa.
+a.root-servers.net.
+ns1-170.akam.net.
+saltel.net.
+17.254.208.74.zen.spamhaus.org.
+tas.orangeads.fr.
+ww.facebok.com.
+122.83.27.189.in-addr.arpa.
+googleads.g.doubleclick.net.
+pssaudio.com.
+85.218.226.168.in-addr.arpa.
+timesgrop.com.
+nip.net.ua.
+jaypark.net.
+ferens.net.
+crmassociatesinc.com.
+www.slashdot.com.
+sites.google.com.
+host30.ru.
+mail.capitolmarketing.com.
+wac.0c28.edgecastcdn.net.
+a.root-servers.net.
+m.facebook.com.
+jiuan.jiagoo.com.
+facebook-gadget.programas-gratis.net.
+youtu.be.
+feng.brujeriayhechizos.com.
+plusone.google.com.
+209.70.92.201.in-addr.arpa.
+profile.pics.ak.sonicocnt.com.
+_430_13_0.
+a2.sphotos.ak.fbcdn.net.
+oregon.students.k12.wi.us.
+ksn2.kaspersky-labs.com.
+140.138.134.190.in-addr.arpa.
+_240_07_9.
+v3it.com.
+www.alidaa-alwatania.ma.
+www.clicanoo.re.
+resolver2.wguard.ctmail.com.
+static.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+neocounter.neoworx-blog-tools.net.
+_ldap._tcp.7648c4d1-51f9-4a61-bbe5-816892afb98a.domains._msdcs.im-2.net.
+www.beinghunted.com.
+43.155.158.189.in-addr.arpa.
+183.138.168.192.in-addr.arpa.
+irc.kelebekmafia.com.
+novelasdetv2.blogspot.com.
+ate.lacoctelera.net.
+170.204.177.190.in-addr.arpa.
+177.20.206.190.in-addr.arpa.
+www.grungi.com.
+mdawmdezmdaxmjaxmg.org.
+docinthemachine.com.
+www.blabbers.com.
+firewall.bccu.org.
+ds.serving-sys.com.
+hudson.org.
+tracker.bidder7.mookie1.com.
+69.29.75.187.in-addr.arpa.
+128.129.171.218.in-addr.arpa.
+time.windows.com.
+intranet.unep.org.
+images.hi5.com.
+adserving.cpxinteractive.com.
+95mb2mkmk.06yk.
+ftfp.net.
+media.ccomrcdn.com.
+smx10.ccc-c.ru.
+bspots.com.
+ng.
+www.google-analytics.com.
+google.com.
+18.171.173.187.in-addr.arpa.
+poseidon.dl.playstation.net.
+vw.
+twitter.com.
+download.windowsupdate.com.
+clickserv2.sitescout.com.
+m.bangbook.com.
+c.statcounter.com.
+fitwatch.blogspot.com.
+palpably.com.
+113.63.26.70.in-addr.arpa.
+p08-bookmarks.icloud.com.
+hygloceaf.39jl.
+nat240.convex.ru.
+38.109.50.186.in-addr.arpa.
+bing.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ksn2.kaspersky-labs.com.
+dl.dropbox.com.
+blstb.msn.com.
+photos-e.ak.fbcdn.net.
+ksn2-12.kaspersky-labs.com.
+cic.co.th.
+gtamodreynosa.blogspot.com.
+www.oregonlive.com.
+molinasalinas.com.
+qst.com.pri-mx.smtproutes.com.
+37.75.106.186.in-addr.arpa.
+www.fpsalceda.com.
+mail.jino.ru.
+profile.ak.fbcdn.net.
+dc.logmein-gateway.com.
+mx.gameshop-international.com.
+a5.sphotos.ak.fbcdn.net.
+signin.ebay.com.
+90.99.229.190.in-addr.arpa.
+166.242.158.189.in-addr.arpa.
+js.myspacecdn.com.
+ocsp.thawte.com.
+www.ilfusion.com.
+email-dm.caroljones.com.
+mx.lynxdev.com.
+a.root-servers.net.
+textad.sexsearch.com.
+twitter.com.
+jers3.info.
+ns5.assembly.spb.ru.
+photos-a.ak.fbcdn.net.
+www.elacuario.es.
+122.28.200.98.in-addr.arpa.
+dev2.ru.
+creative.ak.fbcdn.net.
+carmelvets.com.
+www.ransen.com.
+updatekeepalive.mcafee.com.
+video.google.com.mx.
+de-de.facebook.com.
+125.106.220.189.in-addr.arpa.
+182.41.14.189.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+canada.com.
+a5.sphotos.ak.fbcdn.net.
+68.238.245.190.in-addr.arpa.
+apps.facebook.com.
+www.movistar.com.co.
+bbcore.cloudapp.net.
+.
+colunas.criativa.globo.com.
+apps.facebook.com.
+limg1.imgsmail.ru.
+jnuvxfm19.61vk.
+53.2.134.187.in-addr.arpa.
+ann.over-blog.com.
+us.bc.yahoo.com.
+likpavlovsk.ru.
+gxcmnoaqhvfkyjd.theforgive.net.
+r49jgld21.34uc.
+www.blossgroup.com.
+107.250.48.190.in-addr.arpa.
+a.root-servers.net.
+img.nikeprice.com.
+sopsmtpin.shuion.com.cn.
+mail.moderntimes.gr.
+photos-f.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+ru.iozcluster.com.
+ssl.gstatic.com.
+a7.sphotos.ak.fbcdn.net.
+www.picresize.com.
+22.1.168.192.in-addr.arpa.
+16036.diloconfrases.com.
+mail.isolofoam.com.
+a.root-servers.net.
+www.acorentacar.com.
+liveupdate.symantecliveupdate.com.
+paracozinhar.blogspot.com.
+222.147.34.201.in-addr.arpa.
+ovist.ru.
+lcbbqx.com.
+mail.amarchitx.com.
+mail.gandiagroup.com.
+photos-f.ak.fbcdn.net.
+www.trafficholder.com.
+c7.zedo.com.
+a6.sphotos.ak.fbcdn.net.
+newfbcover.com.
+130.254.107.200.in-addr.arpa.
+_ldap._tcp.
+www.10joke.com.
+hitman-blood-money.softonic.com.
+30.100.87.200.in-addr.arpa.
+www.mikemerritt.me.
+mobilemedianow.com.
+99.133.34.177.in-addr.arpa.
+163.133.159.189.in-addr.arpa.
+byfiles.storage.msn.com.
+mail.plateau.ru.
+85.163.52.174.in-addr.arpa.
+tap2-cdn.rubiconproject.com.
+corazones.100foros.com.
+accounts.google.com.
+_540_03_3.
+www.crunchbase.com.
+213.141.226.190.in-addr.arpa.
+194.25.185.91.in-addr.arpa.
+mail2.duferdofin.it.
+check6.facebook.com.
+ad.doubleclick.net.
+juegosbeta.net.
+ntp.glb.nist.gov.
+evsecure-crl.verisign.com.
+www.facebook.com.
+levittandsons.com.
+video.cnbc.com.
+.
+229.165.171.201.in-addr.arpa.
+s.clicktale.net.
+www.facebook.com.
+erichluna.files.wordpress.com.
+42.187.68.195.in-addr.arpa.
+api.twitter.com.
+107.1.168.192.in-addr.arpa.
+www-cctld.l.google.com.
+h.live.com.
+r._dns-sd._udp.0.97.168.192.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+fc.pickerington.k12.oh.us.
+66.177.229.201.in-addr.arpa.
+s-external.ak.fbcdn.net.
+mx.msn.recepedia.com.
+photos-e.ak.fbcdn.net.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+ads.lfstmedia.com.
+140.156.166.190.in-addr.arpa.
+a.root-servers.net.
+sites.google.com.
+www.marchpr.com.
+www.caminandoensantidad.com.
+a4.sphotos.ak.fbcdn.net.
+www.landbou.com.
+ladies.ivwbox.de.
+www.facebook.com.
+www.microsoft.com.
+astroyogisays.wordpress.com.
+www.unifor.it.
+profile.ak.fbcdn.net.
+relay.voice.edge.messenger.live.com.
+www.youtube.com.
+a.root-servers.net.
+:y9zbn78:.a60b4f0b.
+www.holgablog.com.
+10.100.210.64.in-addr.arpa.
+google.com.
+www.addthis.com.
+www.pakmailveracruz.com.
+xslt.alexa.com.
+ins00002.nycomed.local.
+emailbizz.com.
+solemovement.com.
+onetel.net.
+tracker.ex.ua.
+43.200.26.188.in-addr.arpa.
+desipride.co.uk.
+www.schoolworld.com.
+ad-g.doubleclick.net.
+4.69.158.200.in-addr.arpa.
+darkmail.ru.
+a.root-servers.net.
+www.artificialgallery.co.uk.
+safebrowsing.clients.google.com.
+mx.scitz.com.
+200.236.126.199.in-addr.arpa.
+49.250.22.190.in-addr.arpa.
+static.ak.fbcdn.net.
+euro.mediotiempo.com.
+profile.ak.fbcdn.net.
+a1856.w5.akamai.net.
+i.ytimg.com.
+2.218.227.213.in-addr.arpa.
+www.amateurwebcamsexlive.com.
+cdn-w.fapdu.com.
+espanol.galerias.autocosmos.yahoo.net.
+a5.sphotos.ak.fbcdn.net.
+ieonlinews.microsoft.com.
+init-p01md.apple.com.
+pravitelstvokbr.ru.
+179.36.186.201.in-addr.arpa.
+adserver.adtech.de.
+lineage2.plaync.jp.
+www.polarbearmusic.com.
+evhs.net.s10b2.psmtp.com.
+static.ak.fbcdn.net.
+178.156.245.190.in-addr.arpa.
+g.msn.com.
+www.wildaboutmovies.com.
+79.10.61.186.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+208.237.252.72.in-addr.arpa.
+mtalk.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+alerts.conduit-services.com.
+aswlingerie.com.
+www.facebook.com.
+osce10-5-en.url.trendmicro.com.
+javadl-esd.sun.com.
+17.159.122.186.in-addr.arpa.
+carib.lnet.fr.
+col.stj.s-msn.com.
+search.twitter.com.
+www.abcmanualidades.com.
+meti.com.
+e-deliver.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+philosophy.hertford.ox.ac.uk.
+ssl.gstatic.com.
+bestmodelgirls.com.
+insidehighered.com.
+ad.yieldmanager.com.
+amdbgn5n4.x51v7y4s.
+static.ak.fbcdn.net.
+www.ozgurdunyam.com.
+1.gravatar.com.
+www.facebook.com.
+ec2-184-73-21-146.zumodrive.com.
+82.30.237.189.in-addr.arpa.
+quitcount.sourceforge.net.
+thankyounurses.com.s10a2.psmtp.com.
+dnfdl.qq.com.
+twitter.com.
+omundoasiatico.wordpress.com.
+a.root-servers.net.
+nic99:opq.y86y4h6t.
+a6.sphotos.ak.fbcdn.net.
+twcble.com.
+r._dns-sd._udp.lan.
+photos-g.ak.fbcdn.net.
+www.footballtip.co.uk.
+johnsoncountytx.org.s5a2.psmtp.com.
+38.232.86.74.in-addr.arpa.
+mail.autonizh.nnov.ru.
+rssbarcode.com.
+www.fabulous.com.
+im61.vk.com.
+time.nist.gov.
+wvc.net.
+img4.drawn-incest.net.
+model850.deviantart.com.
+178.126.247.69.in-addr.arpa.
+obeloer.de.
+169.147.174.190.in-addr.arpa.
+mx.youtube.com.
+www.slona.net.
+browsersync.google.com.
+google.com.
+www.facebook.com.
+127.129.79.190.in-addr.arpa.
+webcache.googleusercontent.com.
+api.webrep.avast.com.
+mail.pressdisplay.com.
+skyfallen.com.
+60.159.35.187.in-addr.arpa.
+alvago.ru.
+93.199.116.194.in-addr.arpa.
+b754:eygv.76jj.
+ville-argenteuil.fr.
+www.uhcretiree.com.
+15cb25h1.aime7.eu.
+brand.celio.com.
+billing.sharo4ka.ru.
+77.196.40.177.in-addr.arpa.
+asp-8.reflexion.net.
+en.wikipedia.org.
+www.tuchiste.com.
+0-244.channel.facebook.com.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+www.google-analytics.com.
+www.legislation.hmso.gov.uk.
+estky.com.
+api.bizographics.com.
+_514_96_1.
+de-de.facebook.com.
+static.ak.facebook.com.
+a.root-servers.net.
+255.80.54.208.in-addr.arpa.
+wiredarchives.disqus.com.
+assets.hostedtube.com.
+www.google-analytics.com.
+tubisuteria.com.ve.
+external.ak.fbcdn.net.
+grayburn.blogspot.com.
+ax.su.itunes.apple.com.
+row.bc.yahoo.com.
+100.21.228.189.in-addr.arpa.
+www.l.google.com.
+pixel.facebook.com.
+g.ceipmsn.com.
+mozilla.yongbok.net.
+a2.sphotos.ak.fbcdn.net.
+platform.twitter.com.
+data.flurry.com.
+apple.com.
+mra1.mail.ru.
+137.79.218.186.in-addr.arpa.
+distilleryimage0.s3.amazonaws.com.
+ocsp.verisign.com.
+inbound.mstgllc.com.netsolmail.net.
+edge-media1.snooth.com.
+129.211.91.195.in-addr.arpa.
+cantaalsenor.com.
+bing.com.
+53.151.24.82.in-addr.arpa.
+static-0.farmville.zgncdn.com.
+logs.sync.prodenv4.mysoluto.com.
+time.nist.gov.
+www.idea.gob.mx.
+l2.zedo.com.
+redragonairsoft.50.forumer.com.
+_860_63_2.
+198.49.23.186.in-addr.arpa.
+a.root-servers.net.
+s-static.ak.facebook.com.
+www.mundoauxilio.com.ar.
+209.129.176.190.in-addr.arpa.
+47-courier.push.apple.com.
+s.ytimg.com.
+agng78sagdfdkjdtwa716.com.
+b3.mookie1.com.
+_369_86_0.
+69.175.178.190.in-addr.arpa.
+www.sx.xinhuanet.com.
+a.rad.msn.com.
+www.downloadhelper.net.
+85.231.89.186.in-addr.arpa.
+dcpq6oz4b.l15w5x9z.
+neetguias.com.
+static-cdn2.ustream.tv.
+www.google-analytics.com.
+a.root-servers.net.
+barbershopconnect.com.
+vsantivirus.com.
+t.co.
+bwp.download.com.
+157.255.247.190.in-addr.arpa.
+150.23.122.186.in-addr.arpa.
+cdn.loading321.com.
+download.windowsupdate.com.
+foros.3dgames.com.ar.
+aperture.maccreate.com.
+p3v.ru.
+googleads.g.doubleclick.net.
+ksn7-12.kaspersky-labs.com.
+head.rd.na-gmbh.net.
+a.root-servers.net.
+conduit.anybodyoutthere.com.
+109.214.5.217.in-addr.arpa.
+4wg9s:ggi.61rl.
+a1725.l.akamai.net.
+i3.ytimg.com.
+altfarm.mediaplex.com.
+59.36.48.186.in-addr.arpa.
+mail.sw15.com.
+amazonm-346.vo.llnwd.net.
+salespages.s3.amazonaws.com.
+4ebec7j26.j35y9q2p.
+brocheszepequena.blogspot.com.
+60.89.88.186.in-addr.arpa.
+s1-powerpoint.vo.msecnd.net.
+d15gt9gwxw5wu0.cloudfront.net.
+www.ducati.it.
+www.jeremyskinner.co.uk.
+pics-4.gaybearsvideo.com.
+gwave.com.
+inbound.matchettandward.com.netsolmail.net.
+encrypted-tbn3.google.com.
+180.123.101.190.in-addr.arpa.
+developers.facebook.com.
+ejabat.google.com.
+775t3k5wd.z31l8t1x.
+127.17.155.189.in-addr.arpa.
+120.136.159.187.in-addr.arpa.
+us.bc.yahoo.com.
+www.gstatic.com.
+32.26.94.186.in-addr.arpa.
+58.114.92.186.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+vp.sip.messenger.msn.com.
+f5uj5ae3n.y25k0v8m.
+y.fs8-88a.video.ckcdn.com.
+content.yieldmanager.edgesuite.net.
+i26.fastpic.ru.
+browse.deviantart.com.
+125.156.234.41.in-addr.arpa.
+www.megadosya.net.
+salon-pantera.ru.
+57.193.181.189.in-addr.arpa.
+img1.blogblog.com.
+www.corralboots.com.
+215.55.17.95.in-addr.arpa.
+leanintree.com.inbound30.mxlogicmx.net.
+s7.addthis.com.
+www.gop.com.
+social.bidsystem.com.
+www.spainmoviles.com.
+a.root-servers.net.
+www.condesadf.com.
+chart.shopping.daum.net.
+ec.atdmt.com.
+downloadcatolico.blogspot.com.
+34.139.87.203.in-addr.arpa.
+dodo.com.au.
+63.197.50.190.in-addr.arpa.
+ardownload.adobe.com.
+clients2.google.com.
+mail2.baruta.net.
+jeffingermany.com.
+ecoclima.cl.
+analytics.live.com.
+ssl.gstatic.com.
+62.252.153.200.in-addr.arpa.
+icanhascheezburger.com.
+godsremedy.com.
+www.google.com.
+sc.cuevana.tv.
+vitamin.utk.ru.
+www.xatakaciencia.com.
+liveupdate.symantecliveupdate.com.
+profile.ak.fbcdn.net.
+a-0.19-2309d081.c030083.1518.19cd.3ea1.410.0.d5g4l32d6jgjp7wsn6vrk57hvq.avqs.mcafee.com.
+toolbarqueries.google.com.
+retracker.kld.ru.
+support.google.com.
+www.showsiteinfo.appspot.com.
+www.chillingeffects.org.
+p05-caldav.icloud.com.
+a.root-servers.net.
+dovstrechy.ru.
+stfansub.chatango.com.
+i3.ytimg.com.
+img100.xvideos.com.
+bat.wbusiness.fr.
+a.root-servers.net.
+www.thetrafficstat.net.lan.
+ksn2-12.kaspersky-labs.com.
+168.89.50.99.in-addr.arpa.
+um.simpli.fi.
+www.clansta.com.
+zicrizabdi.com.
+mystichealingart.blogspot.com.
+google.com.
+dnl-01.geo.kaspersky.com.
+google.com.
+assist.zoho.com.
+photos-d.ak.fbcdn.net.
+sp.cwfservice.net.
+_390_33_8.
+pr-static.tnaflix.com.
+e4344.g.akamaiedge.net.
+58.231.224.190.in-addr.arpa.
+www.google.com.
+ms3.verticalscreen.com.
+www.ebcwebstore.com.
+iloveatom.wikispaces.com.
+www.decadeofaction.org.
+www.google.com.
+en-us.fxfeeds.mozilla.com.
+www.youtube.com.
+www.hairypussiessex.com.
+bit.ly.
+shop.ebay.com.
+www.google.com.
+www.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+hotmail.com.
+accounts.google.com.
+lccmail.com.
+api.facebook.com.
+www.ticketmaster.com.
+140.72.208.186.in-addr.arpa.
+cdn-1.nflximg.com.
+a.root-servers.net.
+cm.g.doubleclick.net.
+es.ask.com.
+ustream.vo.llnwd.net.
+www.googleadservices.com.
+www.portantos.es.
+phobos.apple.com.
+v7.cache3.c.youtube.com.
+bbcore.cloudapp.net.
+download.akvis.com.
+gibbins18.fsnet.co.uk.
+0-ig-w.channel.facebook.com.
+tracker9.bol.bg.
+jpost.ru.
+www.mobilemammoth.com.
+rcp.na.blackberry.com.
+www.costume-designer.co.uk.
+das2.ru.
+tiempoderugby.com.
+30.166.214.201.in-addr.arpa.
+dixis.spb.ru.
+pagead2.googlesyndication.com.
+64.162.4.65.in-addr.arpa.
+253.105.121.187.in-addr.arpa.
+rv.ginyas.com.
+api.twitter.com.
+safebrowsing-cache.google.com.
+gojane.us-dc1-edit.store.yahoo.net.
+www.ver-pelis.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+dsn7.d.skype.net.
+www.ontariotrackers.com.
+27.37.48.49.in-addr.arpa.
+gdata.youtube.com.
+rokita.zigzag.pl.
+www.update.microsoft.com.
+www.terra.com.pe.
+searchclient.live.net.
+www.acee.cl.
+profile.ak.fbcdn.net.
+btinternet.com.
+get.adobe.com.
+225.171.13.88.in-addr.arpa.
+tools.google.com.
+86.117.22.190.in-addr.arpa.
+.
+cdn-8.pics.hardsextubepremium.com.
+reuben.org.
+dns.msftncsi.com.
+wahm-masters.sitesell.com.
+12.170.215.84.in-addr.arpa.
+connect.facebook.net.
+www.risesecurity.org.
+173.202.232.190.in-addr.arpa.
+platform.ak.fbcdn.net.
+iphone-ld.apple.com.
+beonline.com.ph.
+www.facebook.com.
+47.82.176.186.in-addr.arpa.
+leifpodhajsky.com.
+twitter.com.
+www.xuldev.org.
+tradefx.advertserve.com.
+voip.gtdmanquehue.com.
+inbound.jimjenningsarchitecture.com.netsolmail.net.
+apps.facebook.com.
+teredo.ipv6.microsoft.com.
+photos-e.ak.fbcdn.net.
+c.atdmt.com.
+mail.google.com.
+a2.twimg.com.
+194.134.95.201.in-addr.arpa.
+.
+byfiles.storage.msn.com.
+a4.sphotos.ak.fbcdn.net.
+ads.gamesbannernet.com.
+login.live.com.
+plus.google.com.
+www.sun-sentinel.com.
+ad-g.doubleclick.net.
+www.google.com.mx.
+creative.ak.fbcdn.net.
+www.adobe.com.
+riptight.de.
+download.windowsupdate.com.
+4.67.252.201.in-addr.arpa.
+urs.microsoft.com.
+www.coverphotos.ne.
+planetforlife.com.
+cs.wikinews.org.
+pegas.pgta.ru.
+www.azgallerie.com.
+pixel.facebook.com.
+227.94.141.201.in-addr.arpa.
+a.root-servers.net.
+integsystemscorp.com.
+7xxdudax017.org.
+yonkerracing.com.
+deptof.com.
+cache.pack.google.com.
+guardianpm.com.inbound45.mxlogicmx.net.
+www.20minutos.es.
+m688.photobucket.com.
+www.cincodias.com.
+addons.mozilla.org.
+static.ak.fbcdn.net.
+computerwoche.de.
+www3.l.google.com.
+rfi-global.com.
+mail.bmsystem.ru.
+121.158.1.201.in-addr.arpa.
+mail.whitepinecopper.com.
+158.154.30.50.in-addr.arpa.
+mail.isladom.com.do.
+3.170.107.186.in-addr.arpa.
+www.gestiopolis.com.
+5h458z:9q.34nn.
+mail.rwt.com.
+qvvz72iwb.r32f3e0u.
+b._dns-sd._udp.0.16.168.192.in-addr.arpa.
+feeds.feedburner.com.
+voidumonde.com.
+p05-keyvalueservice.icloud.com.
+72.36.215.95.in-addr.arpa.
+trendmicro-g.georedirector.akadns.net.
+col.stc.s-msn.com.
+as.usnuc.com.
+a1.sphotos.ak.fbcdn.net.
+95.244.71.219.in-addr.arpa.
+toolsworld.zzl.org.
+73.56.170.189.in-addr.arpa.
+56.55.131.187.in-addr.arpa.
+86.66.123.189.in-addr.arpa.
+olmue.com.
+154.128.51.190.in-addr.arpa.
+www.google.com.
+95.86.45.12.in-addr.arpa.
+www.17-s.info.
+banner.casinolasvegas.com.
+mail2.gocial.com.
+xalapa.infored.com.mx.
+kjia5mie3.05yq.
+www.fontanka.ru.
+i-dressup.com.
+www.google.com.
+242.50.167.187.in-addr.arpa.
+coupons.houstonpress.com.
+_355_42_7.
+www.weather.com.
+192.123.87.67.in-addr.arpa.
+227.240.143.175.in-addr.arpa.
+www.bingobase.com.
+139.23.85.190.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+40.215.123.201.in-addr.arpa.
+151.143.215.189.in-addr.arpa.
+19.148.74.187.in-addr.arpa.
+roofing.ms.
+music.egexa.com.
+zaring.com.
+zmsg.mobi.
+a1.sphotos.ak.fbcdn.net.
+ro-botica.com.
+onlywarez.info.
+i2.itc.cn.
+www.googleadservices.com.
+i3.ytimg.com.
+www.google.com.
+mail65.ixwebhosting.com.
+64.200.141.63.in-addr.arpa.
+db2.stc.s-msn.com.
+photos-e.ak.fbcdn.net.
+www.horrortheque.com.
+client94.dropbox.com.
+www.youtube.com.
+platform.ak.fbcdn.net.
+cltfile300.corp.kbr.com.beknet.us.
+graph.facebook.com.
+trackaphone.com.
+photos-h.ak.fbcdn.net.
+a1408.w43.akamai.net.
+cdn1.public.tube8.com.
+ionchran.msk.ru.
+s-static.ak.facebook.com.
+www.plrcodemine.com.
+31.80.19.190.in-addr.arpa.
+www.gstatic.com.
+www.hotmail.com.
+static.ak.fbcdn.net.
+033hotmail.com.
+www.ufovideos.ws.
+1109.xphonia.com.
+a.root-servers.net.
+ciaoshopes.122.2o7.net.
+www.jeasyui.com.
+johnsonlawia.com.
+pixel.facebook.com.
+www.speedbibleverse.com.
+ib.adnxs.com.
+83.162.41.177.in-addr.arpa.
+t3.gstatic.com.
+www.file4sharing.com.
+rcp.na.blackberry.com.
+profile.ak.fbcdn.net.
+www.freedomdebtrelief.com.
+www.thelogoloft.com.
+www.google-analytics.com.
+softkey.ru.
+137.43.110.201.in-addr.arpa.
+120.246.157.90.in-addr.arpa.
+239.32.178.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+bkg.bund.de.
+the-weather-channel.en.softonic.com.
+12.119.113.186.in-addr.arpa.
+code.google.com.
+www.bristolgroup.com.ar.
+fbcdn-sphotos-a.akamaihd.net.
+www.buttmachineboys.com.
+mail.mo-pca.org.
+go.microsoft.com.
+mail.sskom.su.
+ajax.googleapis.com.
+fbcdn-photos-a.akamaihd.net.
+_471_33_5.
+a.root-servers.net.
+m04.r64.nalog.ru.
+a7.sphotos.ak.fbcdn.net.
+media.fasthosts.co.uk.
+154.75.91.186.in-addr.arpa.
+www.themotoguide.com.
+razorfamilyfarms.com.
+a.root-servers.net.
+roswellgov.com.
+www.iwork.com.
+blst.msn.com.
+mail.bebisim.net.
+accounts.google.com.
+stage-shredded-status.com.
+pagead2.googlesyndication.com.
+3.17.66.177.in-addr.arpa.
+www.darty.com.
+qpkppwwxk.15qw.
+roadsideamerica.com.
+grandcoffee.ru.
+allkpop.co.
+rr.a.5d6d.com.
+groups.google.es.
+js.wlxrs.com.
+www.facebook.com.
+twitter.com.
+roller-dollz-scene-4.ss.ztod.com.
+accounts.google.com.
+www.kitchenremodelideas.com.
+www.apples4theteacher.com.
+a749.g.akamai.net.
+146.172.250.201.in-addr.arpa.
+desmotivaciones.es.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+sites.google.com.
+cheerleading.about.com.
+mail.thermospas.com.
+dnl-01.geo.kaspersky.com.
+www.emol.com.
+meta.wikimedia.org.
+205.119.240.46.in-addr.arpa.
+mscrl.microsoft.com.
+10.240.222.190.in-addr.arpa.
+a.root-servers.net.
+bank.imgdumpr.com.
+137.55.137.190.in-addr.arpa.
+mail.trak-music.com.
+photos-a.ak.fbcdn.net.
+www.gamespot.com.
+www.fielddayfestivals.com.
+mail.top-med.ru.
+teamhfa-com.mail.eo.outlook.com.
+proxy.org.
+s.ytimg.com.
+a.root-servers.net.
+ssl.gstatic.com.
+s0.2mdn.net.
+builderswholesale.com.
+ilead.itrack.it.
+173.61.70.77.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+safebrowsing-cache.google.com.
+dnl-01.geo.kaspersky.com.
+www.reikiindia.org.
+gci-prod-lb-743530114.us-east-1.elb.amazonaws.com.
+download.live.com.
+content.yieldmanager.edgesuite.net.
+www.iapqroo.org.mx.
+www.directoriowebdemexico.com.mx.
+darkecho.ru.
+crl.geotrust.com.
+57.104.153.187.in-addr.arpa.
+newsrss.bbc.co.uk.
+tkmnet.ru.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+234.4.241.81.in-addr.arpa.
+147.51.40.124.in-addr.arpa.
+wpad.phx-dc.dhl.com.
+www.videostias.net.
+www.bygraziela.com.
+ls2web.redmond.corp.microsoft.com.
+klipxtreme.com.
+www.erkdesigns.com.
+www.facebook.com.
+developers.facebook.com.
+gs-loc.apple.com.
+ad.media-servers.net.
+cc.ysu.edu.
+uiu:pfpp1.k90u2e0f.
+protonworld.com.
+cgi.ebay.com.
+ja.cnt.v.sina.com.cn.
+mx04.traviangames.com.
+mail-bk0-f53.google.com.
+photos-g.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+a.root-servers.net.
+hi-in.facebook.com.
+toyotacredit.ru.
+partner.googleadservices.com.
+masuren-ferienhaus.com.
+wmkreditonline.ru.
+www.googletagservices.com.
+f1rz3vpuf.y61e7v8o.
+245.244.65.222.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+browsermusic.titleservices.com.
+www.airserverapp.com.
+151.94.139.189.in-addr.arpa.
+a.root-servers.net.
+2.223.110.109.in-addr.arpa.
+autoupdate.chromewebtb.conduit-services.com.
+www.fetishsnake.com.
+www.jmsky.com.
+www.webcomparte.cl.
+im-perfection.com.
+photofla.me.
+217.148.168.192.in-addr.arpa.
+download781.avast.com.
+umail.ukrtel.net.
+localhost.
+alphatoris.com.
+i5.tagstat.com.
+content.imorphosis.com.
+plus.google.com.
+bglh2dojw.36cd.
+a.root-servers.net.
+www.jellyegg.com.
+fb.me.
+listen.grooveshark.com.
+hotfixline.eu.
+app.kpi.com.
+_338_05_1.
+a3.twimg.com.
+169.208.225.212.in-addr.arpa.
+58.56.179.78.in-addr.arpa.
+gaffneyinc.com.s7a2.psmtp.com.
+229.185.29.201.in-addr.arpa.
+ninemsn.video.msn.com.
+sf2.wmclinic.com.
+clickmedia.sitescout.com.
+cuantodanio.blogspot.com.
+.
+a8.sphotos.ak.fbcdn.net.
+www.adobe.com.
+138.104.223.201.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+109.183.255.113.in-addr.arpa.
+236.62.61.186.in-addr.arpa.
+www.googletagservices.com.
+thewindowsclub.disqus.com.
+126.26.120.200.in-addr.arpa.
+ads12.groovinads.com.
+vp.sip.messenger.msn.com.
+a200.da1.akamai.net.
+a5.sphotos.ak.fbcdn.net.
+s.youtube.com.
+profile.ak.fbcdn.net.
+developers.facebook.com.
+smtp.boardofchildcare.org.
+238.243.204.190.in-addr.arpa.
+us.mg5.mail.yahoo.com.
+www.victoriaschool.co.uk.
+fallback.mail.fr.uu.net.
+forexcms.hs.llnwd.net.
+api.zynga.com.
+www.portalnet.cl.
+pt-br.facebook.com.
+_133_30_3.
+tools.google.com.
+189.224.74.190.in-addr.arpa.
+img1.catalog.video.msn.com.
+diapeesandwipees.com.
+www.eatstopeat.com.
+b.photobucket.com.
+webfront.ru.
+www.extremestraponsex.com.
+a4.sphotos.ak.fbcdn.net.
+www.facebook.com.
+fafa6.com.
+173.245.224.67.in-addr.arpa.
+platform.twitter.com.
+www.statcounter.com.
+www.exileskimboards.com.
+server6.camelot-hosting.com.
+profile.ak.fbcdn.net.
+www.youtube.com.
+www.newmountain.com.
+geoiplookup.wikimedia.org.
+a0.twimg.com.
+169.142.102.85.in-addr.arpa.
+spcum.qc.ca.
+photos-a.ak.fbcdn.net.
+innovativee-com02e.mail.eo.outlook.com.
+www.designingforhumans.com.
+plusone.google.com.
+tracker.openbittorrent.com.
+travelocity.conduitapps.com.
+uno.wt-rotator104.ru.
+www.tomsalta.com.
+henna.com.
+79.84.66.76.in-addr.arpa.
+www.kzao.com.
+restaurant.teamlava.com.
+109.205.176.187.in-addr.arpa.
+www.facebook.com.
+niynossgm.info.lan.
+224.109.158.189.in-addr.arpa.
+48.121.196.205.in-addr.arpa.
+tracker.bitreactor.to.
+191.227.2.187.in-addr.arpa.
+www.facebook.com.
+195.10.87.186.in-addr.arpa.
+ad.turn.com.
+lactofilia.blogspot.com.
+www.wirefresh.com.
+globet.com.
+www.infolanka.com.
+www.amaranthia.com.
+m.denverpost.com.
+dns.msftncsi.com.
+a-0.19-a3097081.d010583.1518.19d2.3ea1.410.0.jn69rb291g6mjqcwbz2gqzla1b.avqs.mcafee.com.
+twitter.com.
+npgcable.com.
+altx-soft.ru.
+1xom1yyiz.64ns.
+www.positivelysplendid.com.
+draka.com.
+sharelink.com.cy.
+platform.ak.fbcdn.net.
+www.brunelalumni.co.uk.
+195.194.207.190.in-addr.arpa.
+www.xvideos.com.
+crocjokes.com.
+imap.gmail.com.
+a5.da1.akamai.net.
+google.com.
+de-de.facebook.com.
+www.rebuildbabel.com.
+89.238.242.24.in-addr.arpa.
+201.0.187.189.in-addr.arpa.
+morefilm.ru.
+29.186.137.190.in-addr.arpa.
+l.yimg.com.
+mail.lllindberg.com.
+stag-live.gourmet.com.
+103.119.137.187.in-addr.arpa.
+120.237.55.201.in-addr.arpa.
+iland-net-bk.messaging.lotuslive.com.
+www.idedge.com.
+miski-igla.blogspot.com.
+trentonpolice.net.
+creative.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ssl.gstatic.com.
+49.18.55.157.in-addr.arpa.
+www.iapchiapas.org.mx.
+m1.nsimg.net.
+a.root-servers.net.
+a.root-servers.net.
+gun.su.
+gw006.lphbs.com.
+61.217.32.31.in-addr.arpa.
+135.164.184.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+feyenoord.headliner.nl.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cv.duba.net.
+www.attdroids.com.
+loseasi.blogspot.com.
+124.173.106.186.in-addr.arpa.
+creative.ak.fbcdn.net.
+edge.quantserve.com.
+scm-l3.technorati.com.
+125.141.248.189.in-addr.arpa.
+190.154.214.189.in-addr.arpa.
+img-2007-09.photosight.ru.
+calendar.live.com.
+zzominternet.net.
+www.epicgameads.com.
+www.googleadservices.com.
+66.20.237.189.in-addr.arpa.
+www.gstatic.com.
+a1.sphotos.ak.fbcdn.net.
+webcache.googleusercontent.com.
+25.150.3.186.in-addr.arpa.
+www.prostitv.com.
+jsurnwy16.96yo.
+164.15.53.186.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+robbbest1.wordpress.com.
+searchjs.s3.amazonaws.com.
+123.34.50.190.in-addr.arpa.
+top5.mail.ru.
+stmlending.com.
+news.l.google.com.
+121.68.174.190.in-addr.arpa.
+137.209.129.186.in-addr.arpa.
+www.cadeaux-poker.com.
+external.ak.fbcdn.net.
+rover.ebay.com.
+s.ytimg.com.
+iyashinet.net.
+smsclub.ru.
+s-external.ak.fbcdn.net.
+www.facebook.com.
+sp.cwfservice.net.
+0-244.channel.facebook.com.
+photos-b.ak.fbcdn.net.
+limewire-speedup-pro.programas-gratis.net.
+westnet.gr.
+s.youtube.com.
+toolbarqueries.clients.google.com.
+blseamon.com.inbound10.mxlogicmx.net.
+connect.facebook.net.
+teredo.ipv6.microsoft.com.
+98.132.93.186.in-addr.arpa.
+a.root-servers.net.
+www.photostringer.com.
+www.3dtuning.ru.
+a.root-servers.net.
+download957.avast.com.
+cadgroup.com.au.
+translate.google.com.mx.
+dxocy7wsx.57lc.
+240.77.21.190.in-addr.arpa.
+a.root-servers.net.
+tisindia.com.
+usd232.org.
+es-la.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+65.255.48.65.in-addr.arpa.
+www.facebook.com.
+facebook-en-espanol.com.
+connect.facebook.net.
+avatars.whatboyswant.com.
+s.youtube.com.
+api.facebook.com.
+mscrl.microsoft.com.
+hbf.cloud.avg.com.
+thewholeheartedmind.wordpress.com.
+rose.ocn.ne.jp.
+cdn.coolsmileypack.com.
+minnesota-mn-cars.tk.
+www.dream-teens.net.
+profile.ak.fbcdn.net.
+z021.fma.fb.me.
+meraki.com.
+a.root-servers.net.
+www.buscatube.org.
+117.180.83.74.in-addr.arpa.
+farm6.static.flickr.com.
+bresso.net.
+settings.toolbar.search.conduit.com.
+235.229.178.190.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+2.247.37.77.in-addr.arpa.
+www.vgatohdmi.net.
+251.133.89.201.in-addr.arpa.
+yahoo.es.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+thumbs3.maturebjtube.com.
+candysoirees.blogspot.com.
+eur6.akam.net.
+166.213.96.200.in-addr.arpa.
+improveverywhere.com.
+mail.google.com.
+bvohk.com.domain.name.
+platform.twitter.com.
+34.23.241.189.in-addr.arpa.
+www.facebook.com.
+external.ak.fbcdn.net.
+207.159.152.187.in-addr.arpa.
+ads.espectador.com.
+tambotur.ru.
+pa.starmedia.com.
+a6.sphotos.ak.fbcdn.net.
+sanjeeve.com.
+a3.twimg.com.
+external.ak.fbcdn.net.
+external.ak.fbcdn.net.
+148.56.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+ns.tc-exe.ru.
+putzlowitsch.de.
+41.243.255.201.in-addr.arpa.
+www.election-presidentielle.com.
+38.96.128.67.in-addr.arpa.
+api.twitter.com.
+diariowebstardoll.blogspot.com.
+nctc.com.s6b1.psmtp.com.
+www.facebook.com.
+tdcsgwxd1.63cx.
+98.116.144.189.in-addr.arpa.
+robert.de.
+js2.wlxrs.com.
+phillipsandtemro.com.
+44.27.247.69.in-addr.arpa.
+extrapetiteblogroll.blogspot.com.
+connect.facebook.net.
+static.ver-pelis.net.
+photos-b.ak.fbcdn.net.
+o.facebook.com.
+cfg.smartshopper.com.
+ecnu38522.37cd.
+a.root-servers.net.
+28.1.168.192.in-addr.arpa.
+server9.fulltono.com.
+229.162.49.200.in-addr.arpa.
+www.lamatanza.gov.ar.
+f.chtah.com.
+_725_93_3.
+ajax.googleapis.com.
+_564_90_7.
+52.160.234.189.in-addr.arpa.
+dns.msftncsi.com.
+global.ard.yahoo.com.
+kennametal.com.
+wzeu.ask.com.
+msn.es.
+_920_33_4.
+ec.atdmt.com.
+profile.ak.fbcdn.net.
+249.205.178.186.in-addr.arpa.
+clock.fmt.he.net.
+photos-d.ak.fbcdn.net.
+ap.nic.in.
+support.microsoft.com.
+ksn2-12.kaspersky-labs.com.
+0806accac1.org.
+deformacionprofesional.blogspot.com.
+168.238.69.190.in-addr.arpa.
+vidasanayfelicidad.blogcindario.com.
+www.suffolkmaths.co.uk.
+www.daetsid.upv.es.
+discovereddreams.com.
+time.windows.com.
+sandroses.com.
+toolbar.aol.com.
+www.numaticengineering.com.
+translate.google.com.mx.
+teredo.ipv6.microsoft.com.
+google.com.
+tasteofbritain.com.
+apps.facebook.com.
+rmxlabs.ru.
+htc2.accu-weather.com.
+200.142.56.186.in-addr.arpa.
+www.teveonline.net.
+ib.adnxs.com.
+11.21.89.69.in-addr.arpa.
+ddtrslab.blogspot.com.
+a.root-servers.net.
+i4.ytimg.com.
+managedforexbrokers.com.
+celebrityphotosnews.files.wordpress.com.
+foros.3dgames.com.ar.
+anuncios-comunidad.vivastreet.com.mx.
+mx2.free.fr.
+www.google-analytics.com.
+pwindow.ru.
+sn1msg3020234.sn1.gateway.edge.messenger.live.com.
+252.88.92.186.in-addr.arpa.
+img.rankplan.net.
+alkhaleej.com.sa.
+dnl-19.geo.kaspersky.com.
+haymarket.btsdev.net.
+mscrl.microsoft.com.
+fb.trove.com.
+e693i1pqz.84xi.
+www.facebook.com.
+pixel.facebook.com.
+on.fb.me.
+time.chttl.com.tw.
+js.revsci.net.
+ocsp.digicert.com.
+cfgommausa.com.
+static.ak.fbcdn.net.
+mydomainname.com.
+www.cnnturk.com.
+www.yourtrafficstarterblog.com.
+236.111.93.213.in-addr.arpa.
+www.friend2friend.com.
+_213_27_0.
+sites.google.com.
+551qev521.d54n6b0t.
+sonawebzone.blogspot.com.
+www.easy-dating.org.
+marilynmanson.shop.bravadousa.com.
+183.97.10.186.in-addr.arpa.
+www.google.com.
+115.90.252.189.in-addr.arpa.
+www.facebook.com.
+61.37.221.190.in-addr.arpa.
+www.youtube.com.
+imexsa.com.
+cox.net.
+www.xvideos.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+img1.wsimg.com.
+feminidadconsciente.es.tl.
+crl.microsoft.com.
+a.root-servers.net.
+api.twitter.com.
+www.decoundstyle.de.
+playagain.es.
+www.stateofartacademy.com.
+www.valentine.com.
+static.2mdn.net.
+mqppxz198.10tq.
+static.ak.fbcdn.net.
+125.47.170.189.in-addr.arpa.
+www.internetcultural.org.
+136.30.152.85.in-addr.arpa.
+www.dbspublicidad.com.mx.
+www7.pic-upload.de.
+irc.purchaseservice.com.
+profile.ak.fbcdn.net.
+xenoborg.blogspot.com.
+zynga.tm.
+safebrowsing-cache.google.com.
+27.86.248.189.in-addr.arpa.
+www.connect.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+y12fcu.org.
+a.root-servers.net.
+a.analytics.yahoo.com.
+descargarlibrosde.com.
+twitter.com.
+9.1.211.186.in-addr.arpa.
+www.taringa.net.
+safebrowsing.clients.google.com.
+9gag.com.
+view.atdmt.com.
+a.root-servers.net.
+159.135.212.201.in-addr.arpa.
+ssl.gstatic.com.
+50.166.171.69.in-addr.arpa.
+service.collarity.com.
+www.cineticket.com.mx.
+congafoods.com.au.
+www.softonic.jp.
+phoenixtrucklines.com.
+www.facebook.com.
+a.root-servers.net.
+developers.facebook.com.
+www10.0zz0.com.
+129.114.239.201.in-addr.arpa.
+t2.gstatic.com.
+www.racingbetter.co.uk.
+safebrowsing.clients.google.com.
+traductoringlesespanol.mobi.
+shipping.lauritz.com.
+a2.da1.akamai.net.
+mail.donet.com.
+photos-c.ak.fbcdn.net.
+www.ibit.org.
+1.220.181.189.in-addr.arpa.
+mail.acornmedia.com.
+strelnasanatoriy.ru.
+www.marsden.com.
+ipm.avira.com.
+api.twitter.com.
+twitter.com.
+smtp.renault.fr.
+www.facebook.com.
+146.talkgadget.google.com.
+a1007.w43.akamai.net.
+107.116.203.87.in-addr.arpa.
+www.tibcommunity.com.
+competitrack.com.s8b2.psmtp.com.
+www.amivisible.org.
+wolframcdn.com.
+prointec.es.
+252.29.151.187.in-addr.arpa.
+www.astradur.is.
+maplesugarshack.net.
+i1.ytimg.com.
+93.194.87.190.in-addr.arpa.
+198.77.216.223.in-addr.arpa.
+seupdate.360safe.com.
+www.facebook.com.
+www.bloglines.com.
+www.black.100topsites.net.
+142.50.30.189.in-addr.arpa.
+trosch.com.inbound10.mxlogic.net.
+safebrowsing-cache.google.com.
+a.root-servers.net.
+cityvillefb1.static.zgncdn.com.
+www.tripadvisor.com.mx.
+api.twitter.com.
+az-rmt.osprint.ru.
+login.yahoo.com.
+www.redtubexvideos.com.
+108.84.105.186.in-addr.arpa.
+oooevroinvest.ru.
+mamortgage.com.
+caobasecurities.com.
+www.culpepper.com.
+cdn.cxense.com.
+data.mobclix.com.
+photos-a.ak.fbcdn.net.
+cdn.doclix.com.
+pix04.revsci.net.
+alhama.com.
+www.el-tallercito.com.
+tracker.mytorrenttracker.com.
+www.artistdirect.com.
+www.pepper.pk.
+117.20.49.190.in-addr.arpa.
+a.root-servers.net.
+.
+istockanalyst.com.
+www.trend-uk.com.
+188.44.58.186.in-addr.arpa.
+fblog-chismes.blogspot.com.
+ak1.abmr.net.
+compadreorock.blogspot.com.
+ddl-zone.org.
+external.ak.fbcdn.net.
+baby.shop.ebay.com.
+zynga2-a.akamaihd.net.
+a4.sphotos.ak.fbcdn.net.
+s1.apollolv.adocean.pl.
+123.32.64.76.in-addr.arpa.
+www.ustream.tv.
+mmv.admob.com.
+www32.patrz.pl.
+s2jl7vqg5.j23e5d7q.
+csi.gstatic.com.
+limelight.cedexis.com.
+versioncheck.addons.mozilla.org.
+152.232.171.69.plus.bondedsender.org.
+estore.pubeasyschool.com.
+a.root-servers.net.
+149.6.113.76.in-addr.arpa.
+b.scorecardresearch.com.
+profile.ak.fbcdn.net.
+partner.googleadservices.com.
+teredo.ipv6.microsoft.com.
+asciinickbuilder.softonic.com.
+mail.superlink.ru.
+ax.su.itunes.apple.com.
+www3.oovoo.com.
+49.147.220.66.in-addr.arpa.
+www.youtube.com.
+www.google.com.
+a1108.da1.akamai.net.
+mscrl.microsoft.com.
+35.114.1.186.in-addr.arpa.
+kirbos.net.
+mail.uniwebinc.com.
+check4.facebook.com.
+willhelm-cinefilo.blogspot.com.
+translate.google.com.mx.
+pagead2.googlesyndication.com.
+track.searchignite.com.
+photos-a.ak.fbcdn.net.
+router.infolinks.com.
+86.169.252.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+api.twitter.com.
+weather.wapp.wii.com.
+www.autopart.com.
+cgi1.ebay.com.
+ganardineroeninternet101.com.
+nsall.huawei.com.
+js.wlxrs.com.
+217.134.68.118.in-addr.arpa.
+widgets.twimg.com.
+nordeus.hs.llnwd.net.
+www.kemi.org.
+junny.de.
+fr.y8.com.
+www.msnarea.com.
+au.pool.ntp.org.
+mathildaastrand.tumblr.com.
+a1911.phobos.apple.com.
+www.themorristribe.com.
+aluni.net.
+vthumb.ak.fbcdn.net.
+apps.facebook.com.
+www.update.microsoft.com.
+smtp3.aceaspa.it.
+fbcdn-profile-a.akamaihd.net.
+_775_26_9.
+www.emusic.com.
+static-resource.np.community.playstation.net.
+mail.catapultprofiling.com.
+216.99.219.81.in-addr.arpa.
+blog.lydiapintscher.de.
+rrcaribbean.com.
+228.30.135.187.in-addr.arpa.
+billing.sharo4ka.ru.
+dns.msftncsi.com.
+www.bloomberg.com.
+sp.cwfservice.net.
+216.234.171.1.in-addr.arpa.
+mail2.hmgmt.com.
+u.goal.com.
+pubads.g.doubleclick.net.
+barbantesaofrancisco.blogspot.com.
+www.momsexland.com.
+bar.searchqu.com.
+2.5.204.201.in-addr.arpa.
+makeshift-designs.co.cc.
+apps.facebook.com.
+alerts.conduit-services.com.
+despiertatuqueduermes.blogspot.com.
+106.157.138.190.in-addr.arpa.
+api.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+connect.facebook.net.
+shar.es.
+selectmortgageresources.com.
+ksn6-12.kaspersky-labs.com.
+sc19.rules.mailshell.net.
+a8.sphotos.ak.fbcdn.net.
+100.54.50.190.in-addr.arpa.
+pencor.com.
+199.0.168.192.in-addr.arpa.
+vcs2.msg.yahoo.com.
+52.183.210.201.in-addr.arpa.
+66.59.204.187.in-addr.arpa.
+faldin.ru.
+a-0.19-2109f071.c010083.1518.19d4.3ea1.410.0.76j2nh7aft59gpznre2b33aszj.avqs.mcafee.com.
+www.sub5zero.com.
+sc2.rules.mailshell.net.
+teredo.ipv6.microsoft.com.
+roncallihs.org.
+danniiminogueofficial.blogspot.com.
+mail.conninc.com.
+mail.rialcom.ru.
+ansarenterprises.com.
+developers.facebook.com.
+ticketalternative.com.
+liveupdate.symantecliveupdate.com.
+row.bc.yahoo.com.
+luckyshoes.com.2.arsmtp.com.
+cdn.qpn.360.cn.
+instagr.am.
+fbcdn-profile-a.akamaihd.net.
+www.google-analytics.com.
+google.svstyle.com.ua.
+17.156.229.190.in-addr.arpa.
+67.636569706d736e.636f6d.80hcf2ec172.webcfs00.com.
+147.1.201.72.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+graphic-inline.co.uk.
+65.133.243.201.in-addr.arpa.
+234.61.217.189.in-addr.arpa.
+171.179.92.186.in-addr.arpa.
+oakmitsui.com.
+54.12.133.186.in-addr.arpa.
+196.185.29.186.in-addr.arpa.
+www.dentonisd.org.
+imgditan.mycollect.net.
+a.root-servers.net.
+234.148.151.79.in-addr.arpa.
+www.gstatic.com.
+watmidco.net.
+cc-net.net.
+219.164.79.190.in-addr.arpa.
+yu.elearning.yu.edu.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.do-m.ru.
+optimized-by.rubiconproject.com.
+b.scorecardresearch.com.
+195.251.44.200.in-addr.arpa.
+www.facebook.com.
+sa2.ttu.ee.
+mx2.jbaengr.com.
+xxcal.com.s8b1.psmtp.com.
+www.upamayorista.com.ar.
+a6.sphotos.ak.fbcdn.net.
+cdn-9.pics.hardsextubepremium.com.
+a8.sphotos.ak.fbcdn.net.
+mx1.brighthorizons.com.
+profile.ak.fbcdn.net.
+www.googleadservices.com.
+a6.sphotos.ak.fbcdn.net.
+app.my.4399.com.
+backofficesite.epyte.com.
+240.166.121.189.in-addr.arpa.
+mail.cirrusassociates.com.
+26103.ua.all.biz.
+a998.mm1.akamai.net.
+mail-attachment.googleusercontent.com.
+148.30.135.190.in-addr.arpa.
+filter1.natski-1.mailguard.com.au.
+autos.mercadolibre.com.ar.
+170.5.48.186.in-addr.arpa.
+sdparts.com.s6b2.psmtp.com.
+cs274.vk.com.
+myimagingexam.com.
+www.clickhereforpantyhose.com.
+surcon.ru.
+photos.voyage-prive.es.
+smtp.alacranedizioni.it.
+a5.sphotos.ak.fbcdn.net.
+tenzing.fmpub.net.
+storage.surfingbird.ru.
+annettevandenbosch.nl.
+chat.online.citi.com.
+m.adnxs.com.
+www.google.com.
+concesionarias.net.
+a1294.w20.akamai.net.
+a394.phobos.apple.com.
+190.64.54.208.in-addr.arpa.
+developers.facebook.com.
+mail.pdqpayroll.net.
+a8.sphotos.ak.fbcdn.net.
+www.linkedin.com.
+www.chrono24.pt.
+179.44.253.212.in-addr.arpa.
+_221_11_9.
+pagead2.googlesyndication.com.
+photos-e.ak.fbcdn.net.
+www.facebook.com.
+rheagl.com.
+63.150.114.190.in-addr.arpa.
+20.234.187.124.in-addr.arpa.
+csi.gstatic.com.
+aol.com.
+www.jgmb829.com.
+www.ardillanet.com.
+vanessahudgens.silverback.sparkart.net.
+8fhmajt9e.b56j0n5d.
+www.blackdragonsperu.com.
+156.137.55.182.in-addr.arpa.
+223.14.119.68.in-addr.arpa.
+promotions.newegg.com.
+www.elnuevoexponente.blogspot.com.
+www.elementtuning.com.
+ad.yieldmanager.com.
+209.96.114.201.in-addr.arpa.
+s.youtube.com.
+go.srvnow.com.
+cdn.api.twitter.com.
+apps.facebook.com.
+223.103.10.186.in-addr.arpa.
+filatina.wordpress.com.
+pubads.g.doubleclick.net.
+eircommusichub.ie.
+pagead2.googlesyndication.com.
+www.ullapopken.com.
+listado.deremate.com.ec.
+rya.rockyou.com.
+www.6rb.com.
+a.root-servers.net.
+www.losroblerinos.cl.
+www.facebook.com.
+ads.trafficjunky.net.
+45.28.54.187.in-addr.arpa.
+ax.init.itunes.apple.com.
+anaconda-manifesto.blogspot.com.
+230.157.172.78.in-addr.arpa.
+ijasamxs2.k79t4q2s.
+www.ibc-asia.com.
+.
+www.lakelandtimes.com.
+244.224.0.68.in-addr.arpa.
+broenserud.com.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+chickamauga.com.
+www.it-bs.com.ar.
+www.wikeez.com.
+a1294.w20.akamai.net.
+231.116.156.189.in-addr.arpa.
+external.ak.fbcdn.net.
+b.scorecardresearch.com.
+data.flurry.com.
+s19.radikal.ru.
+a996.mm1.akamai.net.
+ajax.googleapis.com.
+www.escortpoint.com.
+sindia.polyvore.com.
+contentserv.brandaffinity.net.
+cs9933.vk.com.
+www.tabacoyron.dimelorecords.com.
+www.facebook.com.
+google.com.
+www.vocerodelcafe.com.
+stitchstud.podbean.com.
+mail.chemreport.com.
+dnl-01.geo.kaspersky.com.
+209.19.240.201.in-addr.arpa.
+star.facebook.com.
+rotabanner.nsk.ru.
+teredo.ipv6.microsoft.com.
+165.107.26.190.in-addr.arpa.
+is.gd.
+www.adobe.com.
+ksn1-11-part2.kaspersky-labs.com.
+paintballtoro.es.
+pagead2.googlesyndication.com.
+www.sammynetbook.com.
+photos-a.ak.fbcdn.net.
+cdn1.ads.brazzers.com.
+photos-a.ak.fbcdn.net.
+www.2darray.net.
+cdn.betrad.com.
+a.root-servers.net.
+a.root-servers.net.
+mail.fastmarketmail.com.
+46-courier.push.apple.com.
+ssl.gstatic.com.
+176.91.84.186.in-addr.arpa.
+blogicars.com.
+b76.photo.store.qq.com.
+dgapartners.com.2.0001.arsmtp.com.
+t1.gstatic.com.
+searchjs.s3.amazonaws.com.
+mail.google.com.
+download983.avast.com.
+126.246.98.171.in-addr.arpa.
+www.programmingsimplified.com.
+pixel.facebook.com.
+cfh.wapp.wii.com.
+diario.latercera.com.
+img268.imageshack.us.
+mail.thewisegroup.co.uk.
+safebrowsing-cache.google.com.
+analogartsensemble.net.
+www.portube.com.
+194.111.113.186.in-addr.arpa.
+www.smartadserver.com.
+i4.ytimg.com.
+external.ak.fbcdn.net.
+a.root-servers.net.
+njaes.rutgers.edu.
+push.apple.com.
+a4.sphotos.ak.fbcdn.net.
+222.23.31.190.in-addr.arpa.
+mx.nehemiahinstitute.com.
+9.231.52.24.in-addr.arpa.
+blogskinny.com.
+c-0.19-a3095081.10023.1518.19d4.3ea1.210.0.389ipn6vifghc4ezzc8t24r8fv.avqs.mcafee.com.
+www.granpared.com.
+www.bing.com.
+developers.facebook.com.
+a.root-servers.net.
+166.199.193.201.in-addr.arpa.
+i795.photobucket.com.
+co.marin.co.us.
+www.seldomparty.com.
+www.stardoll.com.
+130.252.200.190.in-addr.arpa.
+a.root-servers.net.
+img.rincondelvago.com.
+www.easycounter.com.
+ho1.eunic.net.ua.
+www.googletagservices.com.
+teredo.ipv6.microsoft.com.
+nardei.com.
+mx.davidkjefferies.com.
+107.130.188.189.in-addr.arpa.
+thebestbankrates.com.
+a7.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+www.gstatic.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s-static.ak.fbcdn.net.
+3ba1f48a4b3e87fbdcea52325266e210.info.
+www.myhatespace.com.
+people.hankyung.com.
+g.msn.com.
+mx.youtube.com.
+www.parentsmedguide.org.
+www.cotodigital.com.ar.
+configuration.apple.com.
+bks.co.za.
+www.facebook.com.
+f.facemoods.com.
+firefoxupdate.dealply.com.
+www.meteosort.com.
+pt-br.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+us.data.toolbar.yahoo.com.
+apps.facebook.com.
+medexpress32.ru.
+ad.yieldmanager.com.
+todaunaexperienciasermama.blogspot.com.
+usersystem783aa.ru.
+3.bp.blogspot.com.
+newsrss.bbc.co.uk.
+priorityinfo.com.
+dns.msftncsi.com.
+a-0.19-a309e081.c0c0083.1518.19d3.3ea1.410.0.51iw1za3evdf6rvgbu2994uqkb.avqs.mcafee.com.
+static.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+www.theinquirer.es.
+jnba.com.s6b2.psmtp.com.
+profile.ak.fbcdn.net.
+a2.mzstatic.com.
+114.185.120.174.in-addr.arpa.
+cdn1.clkads.com.
+www.barcelonainternships.com.
+apis.google.com.
+dns.msftncsi.com.
+eshop.tutorialonline.biz.
+a.root-servers.net.
+119.183.228.72.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+maqil.ru.
+developers.facebook.com.
+_ldap._tcp.servidor.local.
+dailynews.anniesattic.com.
+195.185.159.187.in-addr.arpa.
+a.root-servers.net.
+www.seriesyonkis.com.
+a.root-servers.net.
+cinismoilustrado.bigcartel.com.
+img18.pixiv.net.
+teredo.ipv6.microsoft.com.
+profile.ak.fbcdn.net.
+d2055744.instant.xoom.it.
+148.142.36.83.in-addr.arpa.
+mail.megapolis-pnz.ru.
+hitback.ru.
+2kfrnv7j6.x20w3j1c.
+accounts.google.com.
+109.126.151.189.in-addr.arpa.
+www.play-music.com.
+xfem7gnot.72rz.
+nursing.edu.au.
+www.lacostena.com.mx.
+sufism.org.
+community.ebay.com.
+www.facebook.com.
+mx2.hotmail.com.
+149.212.144.189.in-addr.arpa.
+venta.odm.com.mx.
+time.chttl.com.tw.
+survivingtheworld.net.
+mac.ign.com.
+go.microsoft.com.
+beneast.co.uk.
+brier.afsc.k12.ar.us.
+www.palabraspordinero.com.
+www.4pnc.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+a.root-servers.net.
+ajax.googleapis.com.
+photos-d.ak.fbcdn.net.
+bay.messenger.services.live.com.
+adserving.cpxinteractive.com.
+21.201.59.201.in-addr.arpa.
+mail.wegowild.com.
+mx.divillarosa.com.
+2.238.190.186.in-addr.arpa.
+caras.com.mx.
+itunes.apple.com.
+228.226.144.222.in-addr.arpa.
+time.windows.com.
+mds-oman.com.
+mail.banktcnb.com.
+186.225.110.71.in-addr.arpa.
+xxxroom.net.
+profile.ak.fbcdn.net.
+gbglawoffice.com.
+vmwebfe.voice.yahoo.com.
+www.icascanada.ca.
+spalatvia.ru.
+179.150.138.188.in-addr.arpa.
+www.gstatic.com.
+cs4762.vkontakte.ru.
+g.live.com.
+cpersonnel.com.
+trophy.ww.np.community.playstation.net.
+67.242.35.189.in-addr.arpa.
+www.mozilla.com.
+167.197.130.201.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+62.103.11.190.in-addr.arpa.
+10.50.125.213.in-addr.arpa.
+mailbag.adnet-sys.com.
+watch-dragonball.com.
+usuarios.maptel.es.
+a.root-servers.net.
+mail.truckwriters.com.
+a.root-servers.net.
+misvideos-curiosos.com.
+s-external.ak.fbcdn.net.
+translate.googleapis.com.
+16.1.168.192.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+www.suurland.com.
+a7.sphotos.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+114.105.168.86.in-addr.arpa.
+syndication.exoclick.com.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+dns.msftncsi.com.
+7-courier.push.apple.com.
+mountainviewfruit.com.
+109.11.182.186.in-addr.arpa.
+cdn1.image.spankwire.phncdn.com.
+168.202.163.67.in-addr.arpa.
+www.clairol.ie.
+www.starclean.de.
+141.237.191.190.in-addr.arpa.
+www.mtvla.com.
+onepiece-revolution.foroactivo.mx.
+www.brookingsregister.com.
+157.67.188.189.in-addr.arpa.
+login.live.com.
+i4.ytimg.com.
+34.166.29.76.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+telia.com\".
+www.gstatic.com.
+i1.ytimg.com.
+play.cultures-online.gamigo.es.
+mygadgets99.com.
+csi.gstatic.com.
+a.root-servers.net.
+developers.facebook.com.
+accounts.google.com.
+autozentrum-ebber.de.
+www.kimfoundation.com.
+tura.evenkya.ru.
+158.104.69.189.in-addr.arpa.
+mail.mhs-pa.org.
+apps.facebook.com.
+128.215.43.201.in-addr.arpa.
+a.root-servers.net.
+170.10.25.177.in-addr.arpa.
+auth.bleast1.perfectworld.com.
+ad.harrenmedianetwork.com.
+98.22.220.189.in-addr.arpa.
+126.181.229.190.in-addr.arpa.
+121.163.60.186.in-addr.arpa.
+panicsubtitulado.blogspot.com.
+a6.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+172.166.7.199.in-addr.arpa.
+www.newmediaexplorer.org.
+52.69.90.78.in-addr.arpa.
+iris.eonet.ne.jp.
+www.kon.org.
+db._dns-sd._udp.lan.
+telefunda.blogspot.com.
+img.mediaplex.com.
+235.11.164.85.in-addr.arpa.
+craig.se.
+secure.base.wlxrs.com.akadns.net.
+nl.webcams.travel.
+vb.grorbnat.com.
+sohoo.com.
+crl.microsoft.com.
+www.mtvla.com.
+10.74.161.187.in-addr.arpa.
+www.facebook.com.
+www.oopsydaisybaby.com.
+emc.org.
+www.mediafire.com.
+nutricionistaonline.org.
+224.78.174.190.in-addr.arpa.
+antfarminteractive.com.
+bpatruth.com.
+225.216.183.189.in-addr.arpa.
+www.circovip.com.
+a1408.w43.akamai.net.
+maps.googleapis.com.
+photos-b.ak.fbcdn.net.
+unsw.edu.au.
+www.gpwiki.org.
+bw1.midasplayer.com.
+a.root-servers.net.
+static.ak.connect.facebook.com.
+mx.netelisys.com.
+sites.google.com.
+l.yimg.com.
+www.internetfrog.com.
+apps.facebook.com.
+dnl-01.geo.kaspersky.com.
+www.disegnicolorare.com.
+photos-f.ak.fbcdn.net.
+time.windows.com.
+img4.ask.fm.
+pixel.facebook.com.
+www.fbskins.com.
+ar-ar.facebook.com.
+mail.rivercitysalesinc.com.
+kidszone1.com.
+1804289383.localhost.
+clients1.google.com.
+nsx.sec.np.dl.playstation.net.
+www.eximeno.com.
+www.casayjardin.net.ve.
+www.scrapbookmax.com.
+a.root-servers.net.
+www.abrconsulting.com.
+vergelcastro.atspace.com.
+urs.microsoft.com.
+www.google.com.
+www.carlosmaldonado.org.
+139.196.203.190.in-addr.arpa.
+206.230.44.124.in-addr.arpa.
+72.239.79.190.in-addr.arpa.
+jqueryjs.googlecode.com.
+qea:q2ubq.37pr.
+accountservices.msn.com.
+dr._dns-sd._udp.home.
+.
+bigpond.com.
+choconaturebio.choconature.com.
+autoaccessories4less.com.
+desmond.yfrog.com.
+mail2.psipack.com.
+br.fling.com.
+www.bleachhforos.com.
+a.root-servers.net.
+www.facebook.com.
+30.57.173.190.in-addr.arpa.
+api.facebook.com.
+latinas.buenchat.com.ar.
+www.switchedonart.com.
+www.losdejalisco.blogspot.com.
+73.246.144.86.in-addr.arpa.
+a.root-servers.net.
+mail.capobeach.com.
+a3.sphotos.ak.fbcdn.net.
+artandculturecenter.org.
+googleads.g.doubleclick.net.
+www.manebooks.com.
+redbluff.com.
+a.root-servers.net.
+translate.googleapis.com.
+239.7.89.201.in-addr.arpa.
+49.234.67.190.in-addr.arpa.
+rad.msn.com.
+www.asurline.com.ar.
+146.53.223.189.in-addr.arpa.
+im.rediff.com.
+dns.msftncsi.com.
+api-read.facebook.com.
+pagead2.googlesyndication.com.
+6to4.ipv6.microsoft.com.
+chomp.com.
+www.update.microsoft.com.
+g.live.com.
+photos-d.ak.fbcdn.net.
+dc336.4shared.com.
+ad-g.doubleclick.net.
+a.root-servers.net.
+rv.ginyas.com.
+i183.photobucket.com.
+themancavedaily.com.
+57.201.161.189.in-addr.arpa.
+hi-in.facebook.com.
+jobnetworks.com.
+www.xatech.com.
+ocsp.comodoca.com.
+safebrowsing-cache.google.com.
+131.209.95.76.in-addr.arpa.
+205.15.219.85.in-addr.arpa.
+s.sputnik.mail.ru.
+twitter.com.
+sct.com.
+photos-c.ak.fbcdn.net.
+games.9o9i.com.
+gissler-pass.de.
+photos-f.ak.fbcdn.net.
+filter1.gofast.mailplatform.co.uk.
+prisonpolicy.org.
+smart.montiera.com.
+37-courier.push.apple.com.
+210.131.149.186.in-addr.arpa.
+151.79.103.91.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+wnep.com.
+devices.live.com.
+mail.owenpugh.com.
+ads.revsci.net.
+a.collective-media.net.
+remc11.k12.mi.ua.
+medrocktraining.co.uk.
+179.81.222.190.in-addr.arpa.
+cwwis.com.
+bitly.com.
+rad.msn.com.
+groups.google.com.
+.
+reports.gate2shop.com.
+222.1.143.189.in-addr.arpa.
+external.ak.fbcdn.net.
+1tiemposmodernos.blogspot.com.
+a.root-servers.net.
+184.228.234.188.in-addr.arpa.
+nogoingback-thereisonlyforward.blogspot.com.
+gdata.youtube.com.
+55.51.141.201.in-addr.arpa.
+yahoo.ca.
+a8.sphotos.ak.fbcdn.net.
+login.live.com.
+www.pepperjamnetwork.com.
+catalogphoto.goo-net.com.
+b.scorecardresearch.com.
+dc345.4shared.com.
+a4.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+symresources.com.
+www.bing.com.
+www.youtube.com.
+s-static.ak.fbcdn.net.
+asociacionminga.org.
+tap2-cdn.rubiconproject.com.
+c-0.19-a3098481.483.1518.19d4.3ea1.210.0.lk3skchnhslkqeilqu72vadqzj.avqs.mcafee.com.
+studio-grad.ru.
+toysdownunder.com.
+42.48.56.200.in-addr.arpa.
+newhogwarts.mi-foro.es.
+26.240.72.189.in-addr.arpa.
+evsecure-crl.verisign.com.
+webcache.googleusercontent.com.
+www.google-analytics.com.
+www.tiendavirtualupb.com.
+47.20.145.189.in-addr.arpa.
+197.102.214.189.in-addr.arpa.
+70.244.177.189.in-addr.arpa.
+hq.umland.com.my.
+arteexpress.com.
+tc3.easythumbhost.com.
+hotmail.com.
+63.118.2.181.in-addr.arpa.
+www.reedpumps.com.
+www.bowers-wilkins.co.uk.
+shakerroad.pvt.k12.nh.us.
+92.11.185.187.in-addr.arpa.
+gastronomiayunapizca.blogspot.com.
+update.messenger.yahoo.com.
+158.85.11.186.in-addr.arpa.
+www.thumbs.lesbocollection.com.
+www.greenbrier.com.
+www.thekittenranch.com.
+tribune.ie.
+keramida.com.inbound10.mxlogic.net.
+apps.facebook.com.
+sdo.gsfc.nasa.gov.
+230.211.141.201.in-addr.arpa.
+csi.gstatic.com.
+fr-fr.facebook.com.
+www.armagetronad.net.
+platform.twitter.com.
+taxi-novaya-era.ru.
+fbcdn-sphotos-a.akamaihd.net.
+dr._dns-sd._udp.c.
+de-de.facebook.com.
+groups.google.com.mx.
+a.root-servers.net.
+www.9cloudsebookmarketingandpromotions.com.
+photos-e.ak.fbcdn.net.
+aca.quik.com.
+geo.tp-cdn.com.
+feedburner.google.com.
+www.stroitelstwo.ru.
+s2.youtube.com.
+core.caster.espn.go.com.
+mx.bluephoenixmedia.com.
+talkgadget.google.com.
+photos-c.ak.fbcdn.net.
+comcast.net.
+62.47.22.129.in-addr.arpa.
+www.genovabene.it.
+www.todoanimes.com.
+isatap.covad.net.
+122.169.44.81.in-addr.arpa.
+i1.ytimg.com.
+translate.googleapis.com.
+dns.msftncsi.com.
+ns1.v6.wow.lk.
+b-0.19-21090008.2020580.1518.19d3.3ea1.410.0.w63gpf5wia6jnshhq6na3bjhnj.avqs.mcafee.com.
+www.peaceteam.net.
+creative.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+cyklingcarrier.com.
+feedburner.google.com.
+es-la.facebook.com.
+a.root-servers.net.
+smtp.historiador.eu.
+mail.womenclub.ru.
+a.root-servers.net.
+segment-pixel.invitemedia.com.
+redir.metaservices.microsoft.com.
+intohome.ru.
+www.alterway.fr.
+profile.ak.fbcdn.net.
+spectrumfiltration.com.
+video.google.com.
+mx.youtube.com.
+www.tviberica.net.
+mypearsonmobile.com.
+siriquestions.com.
+pt-br.facebook.com.
+www.alpsmountaineering.com.
+google.com.
+uploadkeep.com.
+api.twitter.com.
+profile.ak.fbcdn.net.
+developers.facebook.com.
+69.46.34.189.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.loccitane.ru.
+b-0.19-31005079.11081.1518.19d4.36d4.210.0.ngqff7bnf2tq9nf6itwpzrlje6.avqs.mcafee.com.
+77.250.58.83.in-addr.arpa.
+feeds.bbci.co.uk.
+95.33.249.77.in-addr.arpa.
+188.142.100.118.in-addr.arpa.
+art-inc.com.
+docs.google.com.
+www.google.com.mx.
+stickeen.com.
+a1294.w20.akamai.net.
+50.34.51.190.in-addr.arpa.
+logs.aiya.com.cn.
+cookex.amp.yahoo.com.
+dns.msftncsi.com.
+plus.google.com.
+searchclient.live.net.
+86.228.192.68.in-addr.arpa.
+www.john-cena-posters.com.
+willhill.vo.llnwd.net.
+a7.sphotos.ak.fbcdn.net.
+124.103.203.190.in-addr.arpa.
+s.gravatar.com.
+julesandjames.blogspot.com.
+certificates.starfieldtech.com.
+static.ak.fbcdn.net.
+docs.google.com.
+energistix.com.
+227.57.184.109.in-addr.arpa.
+1.223.74.212.in-addr.arpa.
+18.167.27.201.in-addr.arpa.
+mail.moryazilim.com.
+books.google.com.mx.
+sp.search-results.com.
+c-0.19-23095081.10023.1518.19d4.2f4a.210.0.1heevkgp7p8h9nzaareieu62mb.avqs.mcafee.com.
+videodown.baofeng.com.
+76.221.242.189.in-addr.arpa.
+annonse.sol.no.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sdfsda.com.
+153.194.121.82.zz.countries.nerd.dk.
+a5.sphotos.ak.fbcdn.net.
+www.google.com.
+satair.com.
+feedproxy.google.com.
+google.com.
+www.tierradeviajes.com.
+linehaullogistics.com.
+9z4l:8mtf.y32v0b3f.
+comment.2008.sina.com.cn.
+liard.ru.
+barby08bsas.wordpress.com.
+sac.gti.mcafee.com.
+www.ver-pelis.net.
+67.87.131.189.in-addr.arpa.
+231.140.207.98.in-addr.arpa.
+espasa.es.
+uc.
+photos-b.ak.fbcdn.net.
+es-la.facebook.com.
+i.ytimg.com.
+a6.sphotos.ak.fbcdn.net.
+mail.mukhin.ru.
+profile.ak.fbcdn.net.
+vesta.ocn.ne.jp.
+home.live.com.
+ping.chartbeat.net.
+thumbs4.ebaystatic.com.
+www3.filthydatez.com.
+www.flickr.com.home.
+a2.sphotos.ak.fbcdn.net.
+qzone.qq.com.
+77.250.34.156.in-addr.arpa.
+mail.rus.net.
+entretenimiento.prodigy.msn.com.
+www.green.com.
+fimen.ru.
+178.229.114.189.in-addr.arpa.
+powaypopwarner.com.
+fwjolp:89.84ll.
+fatsofa.com.
+mx1.sed.ru.
+199.218.56.79.in-addr.arpa.
+nzbirds.com.
+arabinform.com.
+ads.tlvmedia.com.
+wd-edge.sharethis.com.
+91.31.81.186.in-addr.arpa.
+tv.gsp.ro.
+twitter.com.
+plantayflor.blogspot.com.
+207.92.140.189.in-addr.arpa.
+www.hotmail.com.
+gfx3.hotmail.com.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+hotmail.com.
+bedrosiantile.com.
+dnl-01.geo.kaspersky.com.
+247.230.213.83.in-addr.arpa.
+trackedbyet.info.
+mirdetstva.ru.
+static.ak.fbcdn.net.
+www-qporama-805569008.eu-west-1.elb.amazonaws.com.
+34.11.20.92.in-addr.arpa.
+100.35.30.190.in-addr.arpa.
+rx6z9n69v.o96j5y8p.
+a2.sphotos.ak.fbcdn.net.
+162.240.49.190.in-addr.arpa.
+www.spanish-food.org.
+a.root-servers.net.
+api.twitter.com.
+verify.speedbit.com.
+ax.search.itunes.apple.com.
+86.225.48.174.in-addr.arpa.
+media3.picsearch.com.
+www.cupoint.com.
+cloudsync.dm.origin.com.
+svetservice.ru.
+a995.mm1.akamai.net.
+www.efd.admin.ch.
+153.97.65.173.in-addr.arpa.
+118.122.236.123.in-addr.arpa.
+americantelnet.com.
+forum.anlaids.org.
+api.twitter.com.
+www.juegos.com.es.
+dnl-01.geo.kaspersky.com.
+www.twitter.com.
+0-149.channel.facebook.com.
+75.36.48.85.in-addr.arpa.
+www.mbaup.com.au.
+s3.amazonaws.com.
+static.ak.fbcdn.net.
+199.149.47.187.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a3.da1.akamai.net.
+lp.longtailvideo.com.
+b-0.19-220af089.10081.1518.19d4.3ea1.410.0.fckzbrmw6r9bt5bw42zjr48d7j.avqs.mcafee.com.
+www.torinofc.it.
+clinique-la-casamance.fr.
+76.29.134.189.in-addr.arpa.
+maps.google.com.
+apps.facebook.com.
+www.duslerforum.org.
+www.youtube.com.
+dns.msftncsi.com.
+www.facebook.com.
+clients2.google.com.
+mail.next.ru.
+leaedbf9j.u82w1k9c.
+a5.sphotos.ak.fbcdn.net.
+mail2.shelby-sheriff.org.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+css.wlxrs.com.
+91.10.68.189.in-addr.arpa.
+134.12.53.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+img100.xvideos.com.
+www.youtube.com.
+www.astroaficion.com.
+clients1.google.com.
+bhsi.com.
+www.google.com.
+ad.yieldmanager.com.
+developers.facebook.com.
+i2.ytimg.com.
+connect.facebook.net.
+th.wikipedia.org.
+232.186.183.189.in-addr.arpa.
+adserving.cpxinteractive.com.
+246.126.51.201.in-addr.arpa.
+www.admissions.ualberta.ca.
+u4world.com.
+gaiafile.com.
+a.root-servers.net.
+141.151.253.201.in-addr.arpa.
+e566.b.akamaiedge.net.
+curiouskangaroos.blogspot.com.
+www.linkedin.com.
+downloads.networkmagic.com.
+static-css.veevr.com.
+www.tuifly.com.
+a1.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.delees.com.
+hswenterprises.com.
+pop3.hot.glbdns.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+www.turbochargers.com.
+35.153.232.85.in-addr.arpa.
+65.0.113.68.in-addr.arpa.
+widgets.amung.us.
+i3.ytimg.com.
+www.chandrakclarke.com.
+euro.mediotiempo.com.
+55.13.168.192.in-addr.arpa.
+prontarepa.com.
+dmcritchie.mvps.org.
+static.ak.fbcdn.net.
+143.153.121.200.in-addr.arpa.
+www.nadieesperfecto.com.
+www.wetenschapsforum.nl.
+consorcio.ru.
+www.mercadolibre.com.mx.
+239.210.16.177.in-addr.arpa.
+www.amazon.de.
+www.paradisecoin.com.
+77.41.83.177.in-addr.arpa.
+kabuco.de.
+rs.sinajs.cn.
+shamrockmanagementllc.com.
+mz7xi8w2i.i21f8v5r.
+196.94.238.41.in-addr.arpa.
+apis.google.com.
+time.chttl.com.tw.
+google.com.
+oss.ticketmaster1st.akadns.net.
+biblhertz.it.
+foil.ru.
+a4.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+veldkamp.net.
+api-public.addthis.com.
+assetverification.com.
+bbns.org.
+lh3.googleusercontent.com.
+creative.myspace.com.
+lumbermens.com.s7a1.psmtp.com.
+teas-star.com.
+www.fuerzasdeelite.com.
+img32.imageshack.us.
+profile.ak.fbcdn.net.
+203.50.19.186.in-addr.arpa.
+hardrock.starcite.com.
+s-external.ak.fbcdn.net.
+dnl-03.geo.kaspersky.com.
+dia-net.ru.
+www.onlyamateursteens.com.
+sro.whatsapp.net.
+dns.msftncsi.com.
+www.usadanceshoes.com.
+loopingrecursion.com.
+156.65.203.190.in-addr.arpa.
+civic-club.ru.
+www.update.microsoft.com.
+basilisk.cebix.net.
+ad-g.doubleclick.net.
+www.bcr.gob.sv.
+hdvysxvvb.64fx.
+static.ak.fbcdn.net.
+time.chttl.com.tw.
+www.youtube.com.
+mobilepet-ii-monkey.softonic.com.
+166.141.185.78.in-addr.arpa.
+documentalesdehistoria.blogspot.com.
+233.176.46.186.in-addr.arpa.
+182.113.171.201.in-addr.arpa.
+241.158.49.190.in-addr.arpa.
+img2.uploadhouse.com.
+a4.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+www.facebook.com.
+artistalife.com.
+profile.ak.fbcdn.net.
+developers.facebook.com.
+a.root-servers.net.
+linux.softpedia.com.
+es-la.facebook.com.
+freecyberbabes.clickyou.com.
+att.net.
+40-courier.push.apple.com.
+cumbiadenegros.net.
+180.136.26.216.in-addr.arpa.
+gfx3.hotmail.com.
+bemega.com.
+a5.sphotos.ak.fbcdn.net.
+www.thebigassblog.com.
+a4.sphotos.ak.fbcdn.net.
+nuevomundochile.cl.
+a7.sphotos.ak.fbcdn.net.
+rulezfag.narod.ru.
+dnl-01.geo.kaspersky.com.
+maps.google.com.
+vestidos-de-15-anos1.blogspot.com.
+electrowiki.wikidot.com.
+www.youtube.com.
+fr.mcafee.com.
+dawnuk.net.
+geometricglobal.com.
+metrociti.com.
+www.youtube.com.
+fbcdn-sphotos-a.akamaihd.net.
+secure.wlxrs.com.
+hardwaresphere.com.
+photos-e.ak.fbcdn.net.
+www.gaymapbuenosaires.com.
+gfx2.hotmail.com.
+apps.facebook.com.
+www.tikilive.com.
+aosnotify.mac.com.
+images.instagram.com.
+dart.l.doubleclick.net.
+94.55.194.190.in-addr.arpa.
+s-static.ak.fbcdn.net.
+250.92.63.200.in-addr.arpa.
+apps.facebook.com.
+cr.starmedia.com.
+assets.tp-cdn.com.
+images02.olx.com.
+sklka.ru.
+t1.gstatic.com.
+eccbuffalo.com.
+dns.msftncsi.com.
+a1.sphotos.ak.fbcdn.net.
+knowjr.com.
+myoasis.colum.edu.
+142.14.188.190.in-addr.arpa.
+0-292.channel.facebook.com.
+s.ytimg.com.
+ocsp.verisign.com.
+a1739.phobos.apple.com.
+graph.facebook.com.
+1.34.33.190.in-addr.arpa.
+www.google-analytics.com.
+www.weather.com.
+20.140.19.186.in-addr.arpa.
+a.root-servers.net.
+hotchyx.com.
+sites.google.com.
+e-2dj6wjliwidjibp.stats.esomniture.com.
+www.despegar.com.ar.
+www.pogo.com.
+wiki.cihar.com.
+www.cleopatraescorts.es.
+translate.googleapis.com.
+www.molehillempire.ro.
+a.root-servers.net.
+www.datadesignsb.com.
+hombredetuvida.blogspot.com.
+a-0.19-a3091081.d1b0082.1518.19d2.3ea1.410.0.qpaiisl2c21jk14tcibq1mcv6t.avqs.mcafee.com.
+a.root-servers.net.
+smpweb.com.inbound10.mxlogicmx.net.
+killerglass.com.
+ib.adnxs.com.
+photos-b.ak.fbcdn.net.
+gdata.youtube.com.
+gs-loc.apple.com.
+174.31.201.67.in-addr.arpa.
+53.217.237.98.in-addr.arpa.
+websitetrafficspy.com.
+wilmarinc.com.inbound15.mxlogicmx.net.
+m.youtube.com.
+www.teengirlgirl.com.
+www.advanceddermatologypc.com.
+lk023.info.
+host2.sandlotgames.com.
+152.221.111.193.in-addr.arpa.
+www.delish.com.
+a.root-servers.net.
+ci.kk.dk.
+mail.hardwaretech.ru.
+www.genolevures.org.
+asia.perf.glbdns.microsoft.com.
+facebook.farmville.com.
+proekt-cvetnik.ru.
+ws.tapjoyads.com.
+www.masalacism.com.
+id.google.com.mx.
+5.103.31.186.in-addr.arpa.
+211.228.49.190.in-addr.arpa.
+st.kendincos.com.
+79.185.158.189.in-addr.arpa.
+68.20.19.186.in-addr.arpa.
+cltetg.com.s8b1.psmtp.com.
+blog.trade.gov.
+24.169.138.75.in-addr.arpa.
+rincondeunescritor.ticoblogger.com.
+118.162.41.114.in-addr.arpa.
+windowsphone.xbox.com.
+d24elmu442q75h.cloudfront.net.
+mail.redremo.com.
+i3.ytimg.com.
+_737_73_5.
+msginfo.rising.com.cn.
+207.4.157.201.in-addr.arpa.
+teikovo.tpi.ru.
+250.222.58.187.in-addr.arpa.
+medlux.ru.
+dns.msftncsi.com.
+maltanet.net.
+activitycheckv6.co.cc.
+vhsnewengland.com.s7b2.psmtp.com.
+b.scorecardresearch.com.
+fei.pro-market.net.
+hotmail.com.
+254.230.156.189.in-addr.arpa.
+cardwhacheng20.blogspot.com.
+external.ak.fbcdn.net.
+evsecure-ocsp.verisign.com.
+d.yimg.com.
+lox.lekool.com.
+ns3.emerson.com.
+documentamania.blogspot.com.
+243.183.146.217.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+220.95.220.201.in-addr.arpa.
+external.ak.fbcdn.net.
+118.83.161.118.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.google.com.
+140.196.165.46.in-addr.arpa.
+accounts.google.com.
+au.download.windowsupdate.com.
+226.128.139.187.in-addr.arpa.
+ad.yieldmanager.com.
+f6ilrdgkc.66mj.
+95.75.153.186.in-addr.arpa.
+babi.com.
+wherela.com.
+developers.facebook.com.
+mail.johan.com.my.
+ads.smowtion.com.
+pixel.facebook.com.
+no-replay.alertreceived.com.
+143.225.114.201.in-addr.arpa.
+63.34.77.190.in-addr.arpa.
+a.root-servers.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.onestophumour.com.
+crl.globalsign.net.
+tk2.greedland.net.
+www.cochesjuegos.net.
+www.internet-khazana.com.
+www.nbastore.com.
+db._dns-sd._udp.c.
+r.mzstatic.com.
+140.198.169.78.in-addr.arpa.
+17.233.22.1.in-addr.arpa.
+cdn-1.nflximg.com.
+gilco.com.
+platform.linkedin.com.
+136.215.96.121.in-addr.arpa.
+205.190.232.200.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.green.com.
+teamasia.com.
+www.parchis.com.
+gad.about.com.
+a.root-servers.net.
+taawgh.com.
+profile.ak.fbcdn.net.
+opaygames.com.
+2.185.152.75.in-addr.arpa.
+68.105.238.220.in-addr.arpa.
+89.162.212.89.in-addr.arpa.
+a.root-servers.net.
+mail.anextour.com.
+laaldea.com.mx.
+gcdevelopment.ru.
+www.youtube.com.
+s-external.ak.fbcdn.net.
+t2.gstatic.com.
+112.157.222.189.in-addr.arpa.
+www.goldcoastpower.com.
+samsungvuiasr.vlingo.com.
+www.cochesrc.net.
+barracuda.kempervalve.com.
+classicalmusic.about.com.
+abcheck.com.s7b1.psmtp.com.
+tap-cdn.rubiconproject.com.
+179.31.168.192.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+trinitybrand.com.
+60.158.249.66.in-addr.arpa.
+www.mymelbournehomes.com.
+vdkltcxrqdnl.im.
+www.kiggr.com.
+235.5.243.201.in-addr.arpa.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+eros-expo.ru.
+a.root-servers.net.
+231.50.254.99.in-addr.arpa.
+tpb.tracker.thepiratebay.org.
+17.94.127.84.in-addr.arpa.
+a.root-servers.net.
+clients2.google.com.
+zh-cn.facebook.com.
+6.186.248.203.in-addr.arpa.
+161.133.166.109.in-addr.arpa.
+mail0.spinsoft.it.
+a151.d.akamai.net.
+a199.gi3.akamai.net.
+minecraftforo.foroactivo.net.
+a7.sphotos.ak.fbcdn.net.
+ic.tynt.com.
+photos-b.ak.fbcdn.net.
+182.231.194.187.in-addr.arpa.
+static.ak.fbcdn.net.
+docs.google.com.
+sa-live.com.
+ojodepez-fanzine.blogspot.com.
+teredo.ipv6.microsoft.com.
+mail.cityofeuclid.com.
+27.cim.meebo.com.
+local-bay.contacts.msn.com.
+www.goldenglowpaints.com.
+post-gazette.com.s5a1.psmtp.com.
+connect.facebook.net.
+owenton.rms.slb.com.
+gev.copi.ru.
+brandemali.ru.
+a.root-servers.net.
+253.35.23.4.in-addr.arpa.
+smtpgw-1.akhela.com.
+secure.moshimonsters.com.
+email-telekom.de.
+search.twitter.com.
+www.google.com.
+biejallth.sharkdunle.tm.
+www.realtime.net.
+creative.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+1.static.sportspickle.cvcdn.com.
+fbcdn-sphotos-a.akamaihd.net.
+164.129.176.180.in-addr.arpa.
+59.249.178.190.in-addr.arpa.
+groups.live.com.
+photos-a.ak.fbcdn.net.
+extended-validation-ssl.verisign.com.
+www.dietriffic.com.
+loading1.widdit.com.
+www.whatithinkabout.com.
+elsigloweb.com.
+www.facebook.com.
+www.coinfactswiki.com.
+s2.youtube.com.
+imgboot.disqus.com.
+ad.xtendmedia.com.
+photos-g.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+www.brujadesalem.com.ar.
+dl.dropbox.com.
+ha18iv:8l.58db.
+iesa.com.br.
+07hd.com.
+roza.su.
+collectdolls.about.com.
+a2.sphotos.ak.fbcdn.net.
+www.connect.facebook.com.
+s0.2mdn.net.
+www.openbuildings.com.
+pixel.facebook.com.
+29.6.174.190.in-addr.arpa.
+www.usamail1.com.
+29.242.211.62.in-addr.arpa.
+photo.pic.sohu.com.
+de-de.facebook.com.
+mashable.com.
+www.chrisridley.co.uk.
+54.234.86.200.in-addr.arpa.
+akorus.com.
+www.maydaylivingbrands.com.
+assets2.henribendel.com.
+mail.wirx.com.
+74.38.172.189.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+130.247.158.189.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+act.presente.org.
+3v95bc9wz.97cm.
+a4.sphotos.ak.fbcdn.net.
+www.facebook.com.
+photos-g.ak.fbcdn.net.
+papercraft.jhonsryo.com.
+a6.sphotos.ak.fbcdn.net.
+static.tlavideo.com.
+suppliers.chinacommodity.net.
+facebook.dirtydancingresort.com.
+ar.wikipedia.org.
+fnpbzxuwe.c73d1q2e.
+www.gees.org.
+santiago.clasificadosgratis.cl.
+www.segurosvip.com.
+checkip.dyndns.com.
+cqpz17y9a.f33w3w9i.
+www.pos-software.org.
+35.28.91.187.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+0.11-a70e7079.83.1518.18a4.3ea1.210.0.ed1ii45j1ghkf9v3q6pmlamarq.avqs.mcafee.com.
+checkip.dyndns.com.
+profissaodentista.com.br.
+beta.stun.voice.yahoo.com.
+a.root-servers.net.
+mscrl.microsoft.com.
+newportsteel.com.
+log.client.akadns.net.
+apps.bittorrent.com.
+profile.ak.fbcdn.net.
+212.131.79.189.in-addr.arpa.
+safebrowsing.clients.google.com.
+www.spycars.net.
+www.anarchyonline.com.
+100.30.206.24.in-addr.arpa.
+168.130.174.189.in-addr.arpa.
+srv2.wa.marketingsolutions.yahoo.com.
+pagead2.googlesyndication.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.suchsmallportions.com.
+www.buenamusica.com.
+wctatel.net.
+sniper1.skec.co.kr.
+rs617l3.rapidshare.com.
+m.facebook.com.
+api.conduit.com.
+photos-h.ak.fbcdn.net.
+unahotels.it.
+assets.informador.com.mx.
+_085_65_6.
+s.youtube.com.
+a5.sphotos.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+hd21.xiaonei.com.
+www.facebook.com.
+pt-br.facebook.com.
+www.facebook.com.
+netscape.net.
+grandfantasia.aeriagames.com.
+addisonboot.com.
+114.191.63.187.in-addr.arpa.
+i2.ytimg.com.
+224.250.83.62.in-addr.arpa.
+a.root-servers.net.
+www.facebook.com.
+apps.facebook.com.
+bigtimerushlatino.com.
+orcart.facebook.com.
+rp.gwallet.com.
+63.3.129.186.in-addr.arpa.
+128.0.168.192.in-addr.arpa.
+www.facebook.com.
+222.114.0.186.in-addr.arpa.
+120.0.168.192.in-addr.arpa.
+www.evenpro.com.ar.
+koolmobile.net.
+gwfpower.com.
+246.244.18.190.in-addr.arpa.
+mail.scotcom.com.au.
+ygame.gy9y.com.
+ksn.cc.
+129.70.210.189.in-addr.arpa.
+www.enladisco.tv.
+img1.gamespotcdn.com.
+ns02.nexthost.nl.
+photos-d.ak.fbcdn.net.
+twitter.com.
+a.root-servers.net.
+londonlux.com.inbound15.mxlogic.net.
+66.1.201.201.in-addr.arpa.
+www.facebook.com.
+col.stc.s-msn.com.
+photos-d.ak.fbcdn.net.
+static.ak.fbcdn.net.
+242.252.33.189.in-addr.arpa.
+k7.ru.
+cyril.almeras.free.fr.
+mfiane.com.s8a1.psmtp.com.
+dns.msftncsi.com.
+ssl.gstatic.com.
+224.207.203.190.in-addr.arpa.
+p01-keyvalueservice.icloud.com.
+csi.gstatic.com.
+a.root-servers.net.
+api.twitter.com.
+profile.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+google.com.
+ars.icq.com.
+a286.w31.akamai.net.
+ad.yieldmanager.com.
+lifespan.com.au.
+bibank-msk.ru.
+coolwalls.awardspace.com.
+ithinkso.listal.com.
+torrentclub.su.
+vmx.lcturbonet.com.redcondor.net.
+53.141.193.186.in-addr.arpa.
+230.206.230.60.in-addr.arpa.
+a.root-servers.net.
+www.google-analytics.com.
+uktechnologyresources.com.
+pagead2.googlesyndication.com.
+dns.msftncsi.com.
+115.115.27.46.in-addr.arpa.
+www.smuckers.com.mx.
+arunsag.wordpress.com.
+haru-ka.net.
+us.data.toolbar.yahoo.com.
+88.35.133.86.zz.countries.nerd.dk.
+sofortuberweisung.de.
+wpad.
+transmedics.com.
+www.bravospots.com.
+ec.atdmt.com.
+99.69.59.85.in-addr.arpa.
+pxty.ru.
+www.tumix.ru.
+165.1.168.192.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+t2.gstatic.com.
+plus.google.com.
+photos-b.ak.fbcdn.net.
+www.totalplay.com.mx.
+m.hotmail.com.
+successpax.ru.
+dr._dns-sd._udp.domain.name.
+a3.sphotos.ak.fbcdn.net.
+connectads.com.
+xzqcw3vmu.37td.
+col.stb00.s-msn.com.
+thesymbianblog.com.
+mail.nettsoft.no.
+133.120.107.190.in-addr.arpa.
+carlossanmiguel23.blogspot.com.
+hickel.at.
+connect.facebook.net.
+113.160.102.218.in-addr.arpa.
+www.extremetube.com.
+141.49.77.190.in-addr.arpa.
+julius.lookbook.nu.
+www.thinktechno.com.
+api-read.facebook.com.
+euro.mediotiempo.com.
+cdn-6.pics.keezpremium.com.swiftcdn1.com.
+190.237.114.186.in-addr.arpa.
+en.wikipedia.org.
+download772.avast.com.
+scribe.twitter.com.
+photos-a.ak.fbcdn.net.
+56.88.12.99.in-addr.arpa.
+www.facebook.com.
+www.ticketmaster.com.mx.
+22.224.171.69.in-addr.arpa.
+facemoods.com.
+teredo.ipv6.microsoft.com.
+www.google.com.
+3cluaocri.y57x9a9m.
+a6.sphotos.ak.fbcdn.net.
+b.static.ak.fbcdn.net.
+www.google.com.
+profile.ak.fbcdn.net.
+uniklinikum-dresden.de.
+www.rough-sex-in-russia.com.
+developers.facebook.com.
+www.elgranhost.com.
+www.youtube.com.
+mail.logicbytes.com.
+a.root-servers.net.
+68.128.245.77.in-addr.arpa.
+dns.msftncsi.com.
+s.youtube.com.
+39.195.35.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+tilera.com.inbound15.mxlogic.net.
+profile.ak.fbcdn.net.
+www.airportparkingreservations.com.
+a1725.l.akamai.net.
+a.root-servers.net.
+ads1.msads.net.
+api.webrep.avast.com.
+13.8.38.187.in-addr.arpa.
+www.medela.com.
+mcgoye.com.s6b2.psmtp.com.
+www.livefilipinacams.com.
+www.bikeit.co.uk.
+c-0.19-a30ff081.70481.1518.19d3.3ea1.210.0.4vlzs791h9blm6ibv261d8ja7j.avqs.mcafee.com.
+profile.ak.fbcdn.net.
+timberfinec.com.
+s4.histats.com.
+b.scorecardresearch.com.
+sn1msg3020319.gateway.messenger.live.com.
+_122_32_9.
+psp3.pagesuite.com.
+es.foursquare.com.
+iphone-wu.apple.com.
+i2.ytimg.com.
+telecoms-mag.com.
+78.57.15.50.in-addr.arpa.
+gfx2.hotmail.com.
+advertise.sakura.ne.jp.
+hawaaworld.net.
+developers.facebook.com.
+rs989dt.rapidshare.com.
+6.255.54.187.in-addr.arpa.
+s0.2mdn.net.
+www.invisionpower.com.
+va4en.sftcdn.net.
+www.facebook.com.
+www.chiclana.es.
+www.thedailystar.net.
+www.3tailer.com.
+srvupi.inforonda.com.
+www.facebook.com.
+img.perezhilton.com.
+www.youtube.com.
+productshopnyc.com.
+relay.mplik.ru.
+www.bywifi.com.
+deblinux.files.wordpress.com.
+images.colehaan.com.
+a5.sphotos.ak.fbcdn.net.
+www.listainmuebles.com.
+et6.xhamster.com.
+www.kbresource.com.
+_214_83_1.
+66.226.132.190.in-addr.arpa.
+a.ads2.msads.net.
+mx.mujer.yahoo.com.
+www.goodfoodshow.com.au.
+leercadadiaalgo.blogspot.com.
+ib.adnxs.com.
+188.223.248.201.in-addr.arpa.
+194.121.135.189.in-addr.arpa.
+img13.imagemaniac.com.
+a1.sphotos.ak.fbcdn.net.
+234.170.76.94.in-addr.arpa.
+193.188.114.93.in-addr.arpa.
+media.tumblr.com.
+www.adobe.com.
+zqn2ghhtj.39os.
+pinclub.hardrock.com.
+fetdn6qis.36cg.
+aoadns1.nestle.com.
+ee.iitd.ernet.in.
+41.2.237.189.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+cdn1.widdit.com.
+plusone.google.com.
+238.179.86.122.in-addr.arpa.
+0.10.27.125.in-addr.arpa.
+ww2.supergt.net.
+js2.wlxrs.com.
+c.prodigy.msn.com.
+toolbarqueries.google.com.
+orcart.facebook.com.
+a.root-servers.net.
+www.theladylikes.com.
+s0.2mdn.net.
+www.google-analytics.com.
+pagead2.googleadservices.com.
+pixel.facebook.com.
+61.140.93.186.in-addr.arpa.
+www.metrolyrics.com.
+webacom.com.
+193.103.126.187.in-addr.arpa.
+127.97.193.187.in-addr.arpa.
+dl-ssl.google.com.
+photos-a.ak.fbcdn.net.
+ssl.gstatic.com.
+db._dns-sd._udp.lan.
+www.google-analytics.com.
+158.150.158.189.in-addr.arpa.
+www.youtube-nocookie.com.
+236.129.57.186.in-addr.arpa.
+openxfront.iminent.com.
+e3353.c.akamaiedge.net.
+im20.gulfup.com.
+d3k9hgzf8ej9hc.cloudfront.net.
+www.elblogdemontaner.com.
+mx.ipera.net.au.
+basketball.com.
+s.mobclix.com.
+puntacondor.com.
+a107.ui5g0.akafms.net.
+google.com.
+www.youtube.com.
+juegosonline.com.
+jobs.myfoxorlando.com.
+dnl-01.geo.kaspersky.com.
+owa.framinghamma.gov.
+s.ytimg.com.
+:qe:qk37k.84ng.
+mamanluisa.blogspot.com.
+www.breatheheavy.com.
+stats.buysellads.com.
+www.vongo.com.
+a.root-servers.net.
+www.mozilla.com.
+et9.xhamster.com.
+culinarytravel.about.com.
+www.sexaben.dk.
+71.192.239.85.in-addr.arpa.
+www.sagemcom.com.
+www.youtuberepeater.com.
+cm.g.doubleclick.net.
+89.38.101.92.in-addr.arpa.
+www.laughteryoga.org.
+a.root-servers.net.
+www.fandino.net.
+pixel.quantserve.com.
+a1174.g.akamai.net.
+www.google-analytics.com.
+armadatd.ru.
+smtp2.crescentstatebank.com.
+i1.ytimg.com.
+nav3.poker.zynga.com.
+photos-f.ak.fbcdn.net.
+clubdefansdeloganhenderson.globered.com.
+talk.m5zn.com.
+photos-e.ak.fbcdn.net.
+groups.google.com.
+origin.url.trendmicroip.chinacache.net.
+apps.facebook.com.
+pagead2.googlesyndication.com.
+gambit.blogs.nytimes.com.
+srv2.tv-stream.to.
+b.scorecardresearch.com.
+teambstudio.com.
+30.70.247.88.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+toitoninte.museum.
+img.discovery.com.
+free-desktop-backgrounds.info.
+photos-e.ak.fbcdn.net.
+www.williamgibsonbooks.com.
+a5.sphotos.ak.fbcdn.net.
+secure-us.imrworldwide.com.
+bersconstructores.com.
+mail.blackhillsvacations.com.
+www.espacioparalelo.com.
+a.root-servers.net.
+tools.google.com.
+61.45.134.188.in-addr.arpa.
+www.x2music.com.
+188.147.172.189.in-addr.arpa.
+adserving.cpxadroit.com.
+profile.ak.fbcdn.net.
+relay.voice.edge.messenger.live.com.
+1.117.23.190.in-addr.arpa.
+pontevedra.campusanuncios.com.
+70.227.127.201.in-addr.arpa.
+18.51.145.189.in-addr.arpa.
+www.meinvmtv.com.
+mail.google.com.
+mscrl.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+www.remov.es.
+www.lastfm.es.
+130.8.135.105.in-addr.arpa.
+208.209.222.90.in-addr.arpa.
+blackw.msk.ru.
+bijouterieyaccesoriosmr.blogspot.com.
+89.55.132.187.in-addr.arpa.
+www.physics.org.
+199.149.35.211.in-addr.arpa.
+forum.sh3bwah.maktoob.com.
+translate.googleapis.com.
+www.taobao.com.
+netozero.net.
+goolocal.com.mx.
+kstu.ru.
+cloudflare.com.
+m.facebook.com.
+i1.ytimg.com.
+dellaceramica.ru.
+external.ak.fbcdn.net.
+tsgconsumer.com.s8b1.psmtp.com.
+cl30-179-182-213.cl.metrocom.ru.
+a.root-servers.net.
+www.imdb.com.
+a1.sphotos.ak.fbcdn.net.
+99.213.22.190.in-addr.arpa.
+56.154.66.190.in-addr.arpa.
+.
+go.microsoft.com.
+l3tga7:8x.87xg.
+client79.dropbox.com.
+scholar.google.com.
+placaazul.org.
+www.corner-college.com.
+1.bp.blogspot.com.
+www.spankwire.com.
+223.248.111.87.in-addr.arpa.
+24.156.147.79.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+www.milesbinz-shipping.com.
+25.191.32.190.in-addr.arpa.
+clients1.google.com.
+a-0.19-35097001.d010583.1518.19d4.36d4.210.0.bs1jd7se11i96w8mdfnsn57wiq.avqs.mcafee.com.
+mail.supermetal.com.
+56.95.124.78.in-addr.arpa.
+mail.ilscargogroup.com.
+cccservices.com.
+214.96.117.200.in-addr.arpa.
+mail.unelko.com.
+telus.inq.com.
+ptd.net.
+192.205.246.88.in-addr.arpa.
+www.facebook.com.
+www.prompyme.gob.pe.
+a1.sphotos.ak.fbcdn.net.
+service.collarity.com.
+ads.lfstmedia.com.
+www.albemarle-london.com.
+mail.mwaarchitects.com.
+apis.google.com.
+s2.youtube.com.
+a4.sphotos.ak.fbcdn.net.
+widgets.fbshare.me.
+84.197.160.187.in-addr.arpa.
+t.co.
+elquepiensagana.wordpress.com.
+httpcs.msg.yahoo.com.
+photos-a.ak.fbcdn.net.
+145.170.124.59.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.mltailor.com.
+btech.ac.th.
+ns2.dns26.net.
+red-stripe.info.
+drunkula.blogspot.com.
+wzeu.uk.ask.com.
+google.com.
+ns3.cemex.com.
+wirelescefard.com.
+www.jscount.com.
+96.133.211.201.in-addr.arpa.
+www.aclunc.org.
+khm1.google.co.id.
+www.csir.res.in.
+fznz44zgn.64jg.
+www.webcamsexo.info.
+diretorio.tol.pro.br.
+195.112.169.62.in-addr.arpa.
+192.31.159.189.in-addr.arpa.
+ourfamilyrealm.com.
+b._dns-sd._udp.0.130.16.172.in-addr.arpa.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+trophy01.np.community.playstation.net.
+181.201.18.187.in-addr.arpa.
+www.xnet.co.il.
+sigloxxb.blogspot.com.
+14.235.225.201.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.howtomatter.com.
+thesecretgardenllc.com.
+a.root-servers.net.
+a.root-servers.net.
+groups.google.com.mx.
+www.lavidaesbeta.com.
+ns2-auth.teo.lt.
+2plpbgnox.72yo.
+cs510419.vkontakte.ru.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+profile.ak.fbcdn.net.
+plusone.google.com.
+gsconco.com.
+www.humorvariado.com.
+11.246.25.89.in-addr.arpa.
+bbb.sp.f-secure.com.
+leahdawson.com.
+www.ldelgado.es.
+0-jg-w.channel.facebook.com.
+hnequwxsjtumpsrk.com.
+primarycarellc.net.
+sunrise-sakhalin.ru.
+123.128.95.108.in-addr.arpa.
+a.root-servers.net.
+www.adobe.com.
+b.scorecardresearch.com.
+chowvegan.com.
+photos-b.ak.fbcdn.net.
+col.stj.s-msn.com.
+img.mail.ru.
+cgi.chatvibes.com.
+safebrowsing.clients.google.com.
+needformadness.wikia.com.
+a8.sphotos.ak.fbcdn.net.
+cdn.missuniverse.com.
+mail.mrbank.ru.
+translate.twttr.com.
+www.skycig.co.uk.
+digg.com.
+p.hostingprod.com.
+www.juegosvertigo.com.
+kphpb.com.
+creative.ak.fbcdn.net.
+billsgarage.com.
+a771.da1.akamai.net.
+30.168.33.71.in-addr.arpa.
+29.230.182.189.in-addr.arpa.
+i6.expansys.com.
+a1.sphotos.ak.fbcdn.net.
+js2.wlxrs.com.
+photos-f.ak.fbcdn.net.
+www.causewaymall.com.
+photoshopto4ka.net.ru.
+388.com.
+tsk.tulask.ru.
+www.shimritshoshan.com.
+www.danzabuenosaires.com.ar.
+view.atdmt.com.
+a.root-servers.net.
+117.229.177.190.in-addr.arpa.
+132.208.136.186.in-addr.arpa.
+www.sexofree.com.br.
+mingjitang.com.
+e2799.e7.akamaiedge.net.
+88.83.151.120.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+feedback.yandex.ru.
+pixel.facebook.com.
+www.vibramfivefingers.com.
+i.kissmetrics.com.
+pop3.hot.glbdns.microsoft.com.
+mailserver.mehfilmatch.com.
+www.naabt.org.
+map.wwiionline.com.
+retardmedia.com.
+131.146.171.201.in-addr.arpa.
+d2105804.xoom.it.
+www.nortonstore.kr.
+trialgraphic.com.inbound15.mxlogic.net.
+f5-mail.digitalvm.com.
+a.root-servers.net.
+dns.msftncsi.com.
+a.root-servers.net.
+msk.suek.ru.
+www.xkisses.com.
+profile.ak.fbcdn.net.
+ynpndcevents.org.
+insatiable.gotop100.com.
+www.venta-por-catalogo.com.ar.
+www.gstatic.com.
+s2.youtube.com.
+malluhotvideos.in.
+lindawallpapers.appspot.com.
+81.18.168.192.in-addr.arpa.
+135.246.34.99.in-addr.arpa.
+es-es.facebook.com.
+mitecnologico.com.
+l-bank.de.
+www.redtube.com.
+www.arabiccalligrapher.com.
+lomira.k12.wi.us.
+www.ashleytisdale.com.
+37.241.160.201.in-addr.arpa.
+i144.photobucket.com.
+www.lacocinadepili.com.
+mail.live.com.
+mejores-videos-internet.blogspot.com.
+25.153.168.192.in-addr.arpa.
+www.lunatic-films.com.
+notsomekid.com.
+affiliates.x10hosting.com.
+letib.com.
+servicemap.conduit-services.com.
+uppod.ru.
+54.53.198.190.in-addr.arpa.
+43.243.212.98.in-addr.arpa.
+49.106.9.88.in-addr.arpa.
+platform.twitter.com.
+www.feedburner.com.
+lgg.it.
+www.ft.com.
+www.myspace.com.
+www.painspanking.com.
+a.root-servers.net.
+aeiengr.com.pri-mx.smtproutes.com.
+exchange.storkcraft.com.
+a.root-servers.net.
+kundert.com.s10a1.psmtp.com.
+ytimg.com.bl.open-whois.org.
+177.42.251.85.in-addr.arpa.
+tdspedjgh.25lu.
+a.root-servers.net.
+mail.maristes.net.
+conquest.91.com.
+www.vh1la.com.
+218.84.174.189.in-addr.arpa.
+www.ultramar.cl.
+pixel.facebook.com.
+mail.sohu.com.
+sn21.mailshell.net.
+global.ard.yahoo.com.
+www.topfashionb2b.com.
+creative.ak.fbcdn.net.
+ksn2-12.kaspersky-labs.com.
+127.156.143.187.in-addr.arpa.
+auscredits.com.au.
+32.47.149.187.in-addr.arpa.
+static.ak.facebook.com.
+mail.banvenez.com.
+api.twitter.com.
+a26.ms.akamai.net.
+a-0.19-a309b081.d090082.1518.19d4.3ea1.410.0.9c5ieabp7eivvapescd2b8tdkb.avqs.mcafee.com.
+new.pagegangster.com.
+s-static.ak.facebook.com.
+tbr.ask.com.
+creative.ak.fbcdn.net.
+75.118.49.60.in-addr.arpa.
+my.unisa.ac.za.
+ad-g.doubleclick.net.
+eir.turningtechnologies.com.
+my6fjeksh.y57m8z6v.
+buscoempleo.anuncioneon.com.
+mail.chanterellenyc.com.
+adobe-acrobat.software.informer.com.
+external.ak.fbcdn.net.
+domain.mail.yandex.net.
+tunnel.cfw.trustedsource.org.
+worldclassicautos.com.
+accounts.google.com.
+www.mangaid.com.
+www-fc-opensocial.googleusercontent.com.
+www.allgigs.co.uk.
+apis.google.com.
+www.baidu.com.
+a.root-servers.net.
+infinitedangers.com.
+anindiansummer-design.blogspot.com.
+0-271.channel.facebook.com.
+sc2.rules.mailshell.net.
+www.youtube.coml.
+90.23.168.192.in-addr.arpa.
+exchange.chalmersgroup.com.
+photos-a.ak.fbcdn.net.
+peliculassi.com.
+bym-fb-lbns.dc.kixeye.com.
+bt.rghost.net.
+.
+piaoan.en.alibaba.com.
+fxfeeds.mozilla.com.
+cdn.tynt.com.
+netanday.it.
+router.infolinks.com.
+www.google.com.
+134.144.137.201.in-addr.arpa.
+static.ak.fbcdn.net.
+accounts.google.com.
+external.ak.fbcdn.net.
+ccrcanada.com.s9a1.psmtp.com.
+.
+www.bakumens.com.
+a.root-servers.net.
+soft.export.yandex.ru.
+www.facebook.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ailtel.net.
+gadgets-for-men.net.
+safebrowsing-cache.google.com.
+biteme.net.
+ratings-wrs.symantec.com.
+180.136.177.78.in-addr.arpa.
+searchclient.live.net.
+ksn1-12-part2.kaspersky-labs.com.
+www.google.com.
+www101.jimdo.com.
+s1-04.twitpicproxy.com.
+it-it.facebook.com.
+api.zynga.com.
+s247.hotfile.com.
+ksn2-12.kaspersky-labs.com.
+www.cnnchile.com.
+i4.ytimg.com.
+www.dequienes.com.
+215.121.195.123.in-addr.arpa.
+mail.ci.ceres.ca.us.
+www.trafficswarm.com.
+tuc8nquw2.z88a1w0a.
+paradoxfive.blogspot.com.
+178.77.202.81.in-addr.arpa.
+c7.zedo.com.
+sites.google.com.
+pu3dcnwg1.y94b7g6g.
+vz.com.ru.
+pool.ntp.org.
+campodelturia.fadlan.com.
+rocknet.net.au.
+it.italyculture.it.
+mx.astrology.yahoo.com.
+ksn2-12.kaspersky-labs.com.
+a5.sphotos.ak.fbcdn.net.
+s.ytimg.com.
+mail.icix.com.
+www.facebook.com.
+www.salesianosvaldivia.cl.
+a.root-servers.net.
+168.85.91.190.in-addr.arpa.
+ssp-p.com.
+www.adobe.com.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+tap2-cdn.rubiconproject.com.
+photos-h.ak.fbcdn.net.
+google.com.
+reald.com.
+a.root-servers.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+124.149.255.201.in-addr.arpa.
+www.elcorillord.co.
+110.80.29.186.in-addr.arpa.
+s2.youtube.com.
+lumpeny.com.
+a8.sphotos.ak.fbcdn.net.
+weather.service.msn.com.
+s-external.ak.fbcdn.net.
+a.root-servers.net.
+tudi.com.inbound15.mxlogicmx.net.
+e5168.g.akamaiedge.net.
+www.dragspecialties.com.
+clkads.com.
+europolitics.info.
+a.root-servers.net.
+157.101.236.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+145.150.206.196.in-addr.arpa.
+beeskow.de.
+bouleafacettes.biz.
+pf.u.51img1.com.
+www.miltontwins.in.
+rs-e.com.
+78.78.209.190.in-addr.arpa.
+co104w.col104.mail.live.com.
+youtubedownload.altervista.org.
+office.microsoft.com.
+www.archiportfolio.com.
+nowmco.com.
+populus.es.msn.com.
+teredo.ipv6.microsoft.com.
+a5.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+gw0.suite224.net.
+164.145.47.60.in-addr.arpa.
+177.238.247.190.in-addr.arpa.
+s2.youtube.com.
+coylehospitality.com.
+game1.netmarble.net.
+a2.sphotos.ak.fbcdn.net.
+sunbeam.ru.
+content.yieldmanager.edgesuite.net.
+travelmateonline.com.
+yn9h6y2y1.q13f2e3a.
+107.1.168.192.in-addr.arpa.
+memtracker.appspot.com.
+www.make1c.com.
+botanov.net.
+dns.msftncsi.com.
+s7.addthis.com.
+a.root-servers.net.
+db._dns-sd._udp.lan.
+pda.mv.bidsystem.com.
+tweetmeme.com.
+s.ytimg.com.
+a5.sphotos.ak.fbcdn.net.
+27.206.185.67.in-addr.arpa.
+qspbaztwaaf.com.
+www.gstatic.com.
+static.ak.fbcdn.net.
+dns.msftncsi.com.
+www.minitokyo.net.
+pt-br.facebook.com.
+bluemoon.softonic.com.
+www.diariodeboadilla.es.
+_006_44_2.
+twitter.com.
+pixel.indieclick.com.
+128.166.167.189.in-addr.arpa.
+137.39.130.186.in-addr.arpa.
+01.myjewishpage.com.
+213.111.112.190.in-addr.arpa.
+g811d3181c5bb4cfd.api.playtomic.com.
+www.comprar-ofertas.com.
+pro5.livebooks.com.
+i1.ytimg.com.
+a.root-servers.net.
+twitter.com.
+101.139.227.190.in-addr.arpa.
+i.imgur.com.
+widgets.serverboy.net.
+check4.facebook.com.
+41.117.173.118.in-addr.arpa.
+apicultura.wikia.com.
+202.138.10.94.in-addr.arpa.
+_648_85_2.
+181.229.137.85.in-addr.arpa.
+rentcash.ca.
+181.21.244.190.in-addr.arpa.
+mail.jesseengineering.com.
+188.128.239.76.in-addr.arpa.
+revistalamision.es.tl.
+mail.abstinence.net.
+api.prod.capptain.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+kathyawai.com.
+greenearthjourney.blogspot.com.
+dominicano.ru.
+googleads.g.doubleclick.net.
+www.e-messenger.net.
+p9nnqaq9n.35zt.
+_070_81_1.
+static-resource.np.community.playstation.net.
+www.google-analytics.com.
+vcs2.msg.yahoo.com.
+rad.msn.com.
+6.158.28.186.in-addr.arpa.
+29-courier.push.apple.com.
+cfectiva.cfe.gob.mx.
+lb._dns-sd._udp.lan.
+sp.cwfservice.net.
+200.229.42.181.in-addr.arpa.
+mail.rcmclean.com.
+254.232.145.186.in-addr.arpa.
+.
+www.iskullgames.com.
+accounts.google.com.
+pinttars.miscaricaturas.com.
+bb.dev.bbvms.com.
+v21.nonxt8.c.youtube.com.
+thebostonchannel.com.
+mx.msn.recepedia.com.
+www.modoo.es.
+integration.fellowshipone.com.
+a5.sphotos.ak.fbcdn.net.
+wilshirebank.com.
+thumb5.webshots.net.
+test-rt.liftdna.com.
+starving4myperfection.blogspot.com.
+www.facebook.com.
+inerdisc.com.
+18.91.218.186.in-addr.arpa.
+es.meetic.yahoo.net.
+media.trafficjunky.net.
+st8.live800.com.
+a5.sphotos.ak.fbcdn.net.
+cdn.larepublica.pe.
+27.72.91.186.in-addr.arpa.
+c.es.msn.com.
+www.probass.net.
+35.105.179.190.in-addr.arpa.
+ssl.gstatic.com.
+messagent.concentra.be.
+dm-download02.mozilla.org.home.
+mardi09.wordpress.com.
+shela.ru.
+p04-imap.mail.me.com.
+131.105.149.187.in-addr.arpa.
+www.coolermaster.com.
+view.atdmt.com.
+us1153dom12.nam.slb.com.
+bestspb.ru.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+petitforestier.fr.
+iwashige.com.inbound15.mxlogicmx.net.
+www.todotorrents.com.
+c13.zedo.com.
+82.74.10.186.in-addr.arpa.
+2.210.62.68.in-addr.arpa.
+ssl.gstatic.com.
+gfx6.hotmail.com.
+af.acuraprint.com.
+games.yahoo.com.
+loading5.widdit.com.
+www.dailytubevideos.com.
+apps.facebook.com.
+80.132.113.190.in-addr.arpa.
+www.utilisima.com.
+static.ak.fbcdn.net.
+correo.aprosi.net.
+a3.sphotos.ak.fbcdn.net.
+mail.google.com.
+gartsports.com.
+79.69.227.213.in-addr.arpa.
+www.be-still.com.au.
+anticd.ru.
+guia.planetajoy.com.
+sixpackshortcuts.com.
+a7.sphotos.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+e906.g.akamaiedge.net.
+anobanooo.blogspot.com.
+streamlky.alsolnet.com.
+szddfe389.i00r1x3p.
+skedm01.cn.diodes.com.
+www.facebook.com.
+usadatanet.net.
+developers.facebook.com.
+www.australia.edu.
+mx4.hotmail.com.
+www.20minutos.es.
+147.146.9.72.bl.spamcop.net.
+time.chttl.com.tw.
+www.unvm.edu.ar.
+www.territorioenemigo.net.
+74.180.123.99.in-addr.arpa.
+cdn1.widdit.com.
+dreamspr.com.
+s.youtube.com.
+39.156.235.189.in-addr.arpa.
+gam.adnxs.com.
+photos-f.ak.fbcdn.net.
+agddf8fk5.47uy.
+allcovered.com.s6a2.psmtp.com.
+feeds.feedburner.com.
+pixel.facebook.com.
+58.211.129.186.in-addr.arpa.
+www.tylermedicalclinic.com.
+www.leve.su.
+events.theledger.com.
+scribe.twitter.com.
+static.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+beta.stun.voice.yahoo.com.
+22.45.77.89.in-addr.arpa.
+uscm.med.sc.edu.
+yahoo.com.
+www.theworkofthepeople.com.
+a.root-servers.net.
+lightros.ru.
+126.18.202.189.in-addr.arpa.
+www.freshlookcontacts.com.
+134.67.169.62.in-addr.arpa.
+01-1.store.lh.embed.ro.
+o1.inviziads.com.
+foofus.com.
+smithplc.com.
+107.36.154.189.in-addr.arpa.
+157.252.133.187.in-addr.arpa.
+a.root-servers.net.
+alwehda.net.
+94.38.57.186.in-addr.arpa.
+flashembed.xvideos.com.
+i.qype.com.
+hi-in.facebook.com.
+165.107.37.92.in-addr.arpa.
+thechengman.spreadshirt.com.
+www.annemurray.net.au.
+www.facebook.com.
+www.pluralworld.com.
+static.crakcash.com.
+oascentral.babble.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+comtelspa.com.
+www.facebook.com.
+spotify-windows-mobile.softonic.com.
+www.funnyjunksite.com.
+www.gruposmusicalesparroquiales.org.
+plus.google.com.
+171.216.139.189.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+dns.msftncsi.com.
+www.vpsland.com.
+static.ak.fbcdn.net.
+respond2u.com.
+row.bc.yahoo.com.
+117.159.162.190.in-addr.arpa.
+crl.microsoft.com.
+www.facebook.com.
+m.ebags.com.
+a3.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+mailj.sml.com.
+draftfcb.co.il.
+plus.google.com.
+www-google-analytics.l.google.com.
+www.footbo.com.
+fxfeeds.mozilla.com.
+80.52.81.108.in-addr.arpa.
+s-external.ak.fbcdn.net.
+www.facebook.com.
+www.facebook.com.
+frontlinedirectinc.com.
+plusone.google.com.
+hash.orbitdownloader.com.
+qb20bgpatch.quickbooks.com.
+www.cancer.org.
+yaironline.wordpress.com.
+motorcycledesktopwallpaper.blogspot.com.
+www.facebook.com.
+copystationinc.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.csd.toshiba.com.
+182.98.250.189.in-addr.arpa.
+mx00.1and1.es.
+mscrl.microsoft.com.
+p.ebaystatic.com.
+9.42.203.24.in-addr.arpa.
+maltanet.net.
+www.xbox360chat.com.
+219.167.103.189.in-addr.arpa.
+7.126.248.189.in-addr.arpa.
+fstongfang.en.alibaba.com.
+www.adgenie.co.uk.
+clkads.com.
+100.129.136.186.in-addr.arpa.
+32.11.181.189.in-addr.arpa.
+tas.orangeads.fr.
+190.29.168.192.in-addr.arpa.
+www.wrenkitchens.com.
+thclibrary.net.
+www.supercheats.com.
+kona.kontera.com.
+secure.shared.live.com.
+tedchin.com.
+abtco.ru.
+ascg.com.
+dnl-01.geo.kaspersky.com.
+mail.universalcargo.net.
+enter.mofosworldwide.com.
+s-static.ak.fbcdn.net.
+d1.openx.org.
+who.bumpmyip.net.
+najera-javimanzanares.blogspot.com.
+profile.microsoft.com.
+wzus1.search-results.com.
+s1-powerpoint.vo.msecnd.net.
+167.64.230.190.in-addr.arpa.
+rostini.ru.
+mininghouse.com.
+careers.microsoft.com.
+forsaleadsonline.com.
+ad.harrenmedianetwork.com.
+www.facebook.com.
+www.natrue.org.
+developers.facebook.com.
+ksn1-11-part2.kaspersky-labs.com.
+static.ak.fbcdn.net.
+mail.wynhg.com.
+apps.facebook.com.
+www.fabulouscuties.com.
+teplohodmaestro.ru.
+btguard.com.
+www.addthis.com.
+a5.sphotos.ak.fbcdn.net.
+mail.nahalat.ru.
+login.dotomi.com.
+google.com.
+dr._dns-sd._udp.0.55.211.10.in-addr.arpa.
+broadcast.infomaniak.ch.
+profile.ak.fbcdn.net.
+cdn1.certified-apps.com.
+acewallpapers.com.
+bitly.com.
+dns.msftncsi.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+poigraemtut.ru.
+tap2-cdn.rubiconproject.com.
+6-1.qlty.finarea.ch.
+www.cuevana.com.
+gearsofwar.wikia.com.
+appworld.blackberry.com.
+dc339.4shared.com.
+www.facebook.com.
+a.root-servers.net.
+a.root-servers.net.
+mailno.actasone.com.
+fbcdn-profile-a.akamaihd.net.
+cs933.vk.com.
+ic.tynt.com.
+www.bcvo.co.za.
+abslogic.ru.
+mail.trexta.com.
+acti.ru.
+110.142.179.189.in-addr.arpa.
+a2.twimg.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+ihg-chicago.jobs.
+kkqx2lxi1.o17f4m5b.
+tomhumphrey.commaureen.
+kuq4ogt5:.33sv.
+www.google-analytics.com.
+borel.com.
+www.um.edu.mx.
+201.107.73.178.in-addr.arpa.
+179.56.25.190.in-addr.arpa.
+c-0.19-430cc069.20001.1518.19d4.2f4a.210.0.9ditbwm77wrkfpjqfdfg51fndv.avqs.mcafee.com.
+crl.microsoft.com.
+a.root-servers.net.
+www.choate.edu.
+terra.com.br.
+okbz:zqhe.d61a5o8h.
+www.google.com.
+cdn2-pivotaltracker.pantherssl.com.
+a6.sphotos.ak.fbcdn.net.
+vgpmuaqgp.76nc.
+mail.sppkk.ru.
+palletone.com.
+photos-g.ak.fbcdn.net.
+74.43.15.187.in-addr.arpa.
+img713.imageshack.us.
+25.199.65.190.in-addr.arpa.
+lb._dns-sd._udp.lan.
+121.75.208.190.in-addr.arpa.
+pixel.facebook.com.
+relay.ast-ins.ru.
+1d.media.v4.skyrock.net.
+s.youtube.com.
+www.greentradebay.com.
+www.cctv.com.
+a6.sphotos.ak.fbcdn.net.
+search.conduit.com.
+dotaplayer.net.
+mt1.google.com.
+img.intelihealth.com.
+www.trafficholder.com.
+mail.aplusnet.hu.
+bentelhalal.maktoob.com.
+220.24.85.200.in-addr.arpa.
+a1856.da1.akamai.net.
+translate.google.com.
+aragon.es.
+lonelyweb.net.
+www.xvideoslive.com.
+external.ak.fbcdn.net.
+splob.com.
+voicevale-fr.com.
+218.7.55.190.in-addr.arpa.
+83.56.92.186.in-addr.arpa.
+129.131.96.190.in-addr.arpa.
+mail.resole.com.
+0.11-a70a2219.80110b3.1518.197d.3ea1.210.0.95wbuu72j1uq5nkuipia8wtjki.avqs.mcafee.com.
+banners.datenation.com.
+www.facebook.com.
+wap.hao123.com.
+49.78.38.187.in-addr.arpa.
+dns.msftncsi.com.
+64.185.10.187.in-addr.arpa.
+184.82.92.65.in-addr.arpa.
+a.root-servers.net.
+accounts.google.com.
+tm0.blackberry.net.
+221.86.6.95.in-addr.arpa.
+news.google.com.
+117.68.200.14.in-addr.arpa.
+vskmsd1kg.p63b8b0a.
+www.crunchbase.com.
+afc-holcroft-com.relay1a.spamh.com.
+a.root-servers.net.
+trsoft.ru.
+44.1.168.192.in-addr.arpa.
+view2.picapp.com.
+photos-g.ak.fbcdn.net.
+cs109.vk.com.
+mail.kmztech.ru.
+a3.sphotos.ak.fbcdn.net.
+pubads.g.doubleclick.net.
+bookapp.book.qq.com.
+www.facebook.com.
+liveupdate.gocyberlink.com.
+www.berkshirefinearts.com.
+report.bitdefender.com.
+anthrotech.com.
+_338_94_0.
+www.youtube.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+0-staging.channel.facebook.com.
+cdn.mediafire.com.
+raptr.com.
+er9rjiy18.k85b6o2z.
+www.raulrico.com.
+apps.facebook.com.
+ashland.navy.mil.
+172.36.74.66.in-addr.arpa.
+www.intel.com.
+www.plasticprinters.com.
+accountservices.msn.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+178.186.50.83.in-addr.arpa.
+174.23.205.190.in-addr.arpa.
+dr._dns-sd._udp.0.55.211.10.in-addr.arpa.
+piratesofarchery.net.
+1stmediasolutions.com.
+teredo.ipv6.microsoft.com.
+bs.serving-sys.com.
+profile.ak.fbcdn.net.
+26.175.50.190.in-addr.arpa.
+i4.ytimg.com.
+photos-c.ak.fbcdn.net.
+www.adobe.com.
+es-la.facebook.com.
+aish.edu.
+www.playgames.to.
+alerts.conduit-services.com.
+content.yieldmanager.edgesuite.net.
+safebrowsing.clients.google.com.
+110.252.198.190.in-addr.arpa.
+230.67.183.189.in-addr.arpa.
+fls.doubleclick.net.
+manualforyou.ru.
+www.trlaser.com.
+apps.facebook.com.
+asoc-fulbright.es.
+profile.ak.fbcdn.net.
+api.recaptcha.net.
+teredo.ipv6.microsoft.com.
+rushpostcardprinting.com.
+205.18.134.189.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+food-junky.blogspot.com.
+en.wikipedia.org.
+a.root-servers.net.
+developers.facebook.com.
+mail.shades-technics.com.
+ping.chartbeat.net.
+api16.thetrafficstat.net.
+peoplepccc.com.
+facemoods.com.
+de.tynt.com.
+apis.google.com.
+www.facebook.com.
+i2.ytimg.com.
+ip2.shi.com.
+a2.sphotos.ak.fbcdn.net.
+www.google-analytics.com.
+uptus.oilnet.ru.
+ec2-us-east-1a.cedexis.com.
+tools.l.google.com.
+list-new.ru.
+ns19.worldnic.com.
+38.125.133.190.in-addr.arpa.
+b-0.19-a300a008.c831580.1518.19d4.3ea1.410.0.jq1blb8q3pgzggvftm9bcmkf1t.avqs.mcafee.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+b.scorecardresearch.com.
+www.aeivalencia.com.
+bs.serving-sys.com.
+cdn.metanetworkslider.com.
+34.115.170.209.in-addr.arpa.
+www.usbwifi.orcon.net.nz.
+bpy.wikipedia.org.
+www.coveylink.com.
+www.jlsd.org.
+107.100.164.189.in-addr.arpa.
+43.200.49.201.in-addr.arpa.
+dns.msftncsi.com.
+mail.yimg.com.
+external.ak.fbcdn.net.
+www.articleinfoblog.com.
+ellipsiz.com.s7a1.psmtp.com.
+99.99.175.189.in-addr.arpa.
+a.root-servers.net.
+cs4930.vk.com.
+a.rad.msn.com.
+231.201.242.60.in-addr.arpa.
+fsarecruitment.com.au.
+www.datacredito.com.co.
+47.89.156.189.in-addr.arpa.
+ocsp.verisign.com.
+46.180.201.200.in-addr.arpa.
+161.153.79.200.in-addr.arpa.
+services.xboxlive.com.
+a2.sphotos.ak.fbcdn.net.
+biebernovelastu.metroblog.com.
+adsfront.iminent.com.
+pagead2.googlesyndication.com.
+mscrl.microsoft.com.
+a5.sphotos.ak.fbcdn.net.
+156.237.25.201.in-addr.arpa.
+home.ru.
+edgesuperstar.blogspot.com.
+mail.climatedesign.com.
+oprint.ru.
+0-264.channel.facebook.com.
+americaninsulators.com.bak-mx.na0106.smtpbak.com.
+photos-c.ak.fbcdn.net.
+studentmailcenter.com.
+au:dcz3my.m19i0g0q.
+165.169.19.84.in-addr.arpa.
+a.root-servers.net.
+104.209.178.186.in-addr.arpa.
+www.pssl.com.
+estatestore.org.
+teredo.ipv6.microsoft.com.
+matcher-apx.bidder7.mookie1.com.
+audiest.es.
+88.12.159.189.in-addr.arpa.
+t2.gstatic.com.
+alerts.conduit-services.com.
+www.woow.ro.
+59.223.7.187.in-addr.arpa.
+42.29.11.186.in-addr.arpa.
+a1725.l.akamai.net.
+todoloquegira.blogspot.com.
+yilmen.com.
+www.phocos.com.
+_377_12_6.
+apps4u2.conduitapps.com.
+www.adonistwinks.com.
+9li38:nbn.72wb.
+desiclub.in.
+www.curriculum-web.com.
+sturgillturner.com.1.arsmtp.com.
+210.145.131.187.in-addr.arpa.
+tomm.ru.
+sites.google.com.
+www.bootyliciousink.com.
+b-0.19-a309b008.1481.1518.19cd.3ea1.410.0.j1rph37chqkbzjqrvfif1wb1zi.avqs.mcafee.com.
+platio.ru.
+googleads.g.doubleclick.net.
+www.facebook.com.
+www.mejoresfrases.net.
+fbcdn-photos-a.akamaihd.net.
+www.cnn.com.
+filmgordon.wordpress.com.
+photos-h.ak.fbcdn.net.
+tyco-fire.com.
+164.239.160.201.in-addr.arpa.
+mail2.cabledahmer.com.
+nice.dealply.com.
+listserv.utk.edu.
+forum.downloadhelper.net.
+googleads.g.doubleclick.net.
+a82.photo.store.qq.com.
+www.shadowflames.us.
+174.156.151.190.in-addr.arpa.
+24.224.51.190.in-addr.arpa.
+162.157.233.125.in-addr.arpa.
+a.root-servers.net.
+dnl-05.geo.kaspersky.com.
+www.autopistas.com.mx.
+platform.ak.fbcdn.net.
+shamrockrealtors.com.
+abawaba.com.
+220.175.244.88.in-addr.arpa.
+pricebazaar.in.
+miproconsulting-com.relay1c.spamh.com.
+neilduckett.com.
+a.root-servers.net.
+141.190.18.182.in-addr.arpa.
+120.150.22.186.in-addr.arpa.
+a.root-servers.net.
+www.tumblr.com.
+photos-d.ak.fbcdn.net.
+mx3.lasredes.net.
+dns.msftncsi.com.
+240.135.233.221.in-addr.arpa.
+www.hackforums.net.
+new.york.eventguide.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.carrefour.com.ar.
+_ldap._tcp.
+_766_69_2.
+linkhelp.clients.google.com.
+a.root-servers.net.
+www.clubfayerunaway.com.
+ejabat.google.com.
+a.root-servers.net.
+a.root-servers.net.
+147.231.97.76.in-addr.arpa.
+anoush.com.s9a1.psmtp.com.
+189.87.37.190.in-addr.arpa.
+i.ytimg.com.
+fonts.googleapis.com.
+milagrofunding.com.
+185.153.52.186.in-addr.arpa.
+use.typekit.com.
+www.facebook.com.
+a87a36d8.linkbucks.com.
+photos-f.ak.fbcdn.net.
+a.root-servers.net.
+messages.recon.com.
+gio162.wordpress.com.
+www.adxpansion.com.
+236.182.118.200.in-addr.arpa.
+ntp1.dlink.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+a.root-servers.net.
+www.google.com.
+sz8.tencent.com.
+38.208.174.201.in-addr.arpa.
+74.3.72.50.in-addr.arpa.
+79.220.151.12.in-addr.arpa.
+rsmiami.com.
+photos-c.ak.fbcdn.net.
+platform.twitter.com.
+mail.stollamerica.com.
+s.ytimg.com.
+a.root-servers.net.
+www.aqabazone.com.
+accountservices.msn.com.
+photos-d.ak.fbcdn.net.
+8.108.186.190.in-addr.arpa.
+johndawsoninsurance.com.pri-mx.smtproutes.com.
+search.softonic.com.
+ads.pubmatic.com.
+plus.google.com.
+poll.hotlayouts2u.com.
+profile.ak.fbcdn.net.
+partners.socialvi.be.
+au.download.windowsupdate.com.
+o49cq3xz6.49ny.
+mail.netorn.ru.
+static.ak.fbcdn.net.
+mariokart64.com.
+idealegc.com.br.
+static.ak.fbcdn.net.
+static.ak.facebook.com.
+a.root-servers.net.
+36.49.73.187.in-addr.arpa.
+www.peiweiblog.com.
+www.gstatic.com.
+msgate.wdl.loral.com.
+pagead2.googlesyndication.com.
+www.facebook.com.
+nkrumah.net.
+primatrading.com.
+101.5.189.201.in-addr.arpa.
+carawalsh.com.
+api.twitter.com.
+twitter.com.
+tools.google.com.
+config.conduitapps.com.
+icm.ginyas.com.
+d2100485.xoom.it.
+microplan.de.
+60.134.195.187.in-addr.arpa.
+www.carphototutorials.com.
+smalltakeover.blogspot.com.
+bounderds.com.
+www.youtube.com.
+clients1.google.com.
+197.22.192.108.in-addr.arpa.
+pics5.madthumbscdn.com.
+sharethis.com.
+videodownloads.o2.co.uk.
+download802.mediafire.com.
+byfiles.storage.msn.com.
+shealink.com.s7a1.psmtp.com.
+photos-b.ak.fbcdn.net.
+ad.yieldmanager.com.
+chat.facebook.com.
+www.adobe.com.
+131.224.215.186.in-addr.arpa.
+blog.heartsonfire.com.
+heparin.com.
+a3.sphotos.ak.fbcdn.net.
+xonoxlabs.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+167.130.126.75.in-addr.arpa.
+89.237.42.200.in-addr.arpa.
+ksn1-12-part2.kaspersky-labs.com.
+234.141.223.80.in-addr.arpa.
+152.203.191.188.in-addr.arpa.
+cdn.api.twitter.com.
+108.231.248.201.in-addr.arpa.
+static.ak.fbcdn.net.
+241.248.192.190.in-addr.arpa.
+www.deborahkingcenter.com.
+www.cineticket.com.mx.
+hotmail.com.
+knight.com.jo.
+ptcnet.net.s6b2.psmtp.com.
+hk.arthurandersen.com.
+pudfaceup.paran.com.
+ebrochazos.blogspot.com.
+201.31.220.192.in-addr.arpa.
+www.kustomcoachwerks.com.
+www.rhymezone.com.
+www.bicaramakdara.com.
+lockwoodpublications.com.s5b2.psmtp.com.
+www.teniaquedecirlo.com.
+lyris.asmestaff.org.
+cutmp3.net.
+www.facebook.com.
+skydrive.live.com.
+s-external.ak.fbcdn.net.
+venezuela.yaclasificados.com.
+columbustax.net.
+www.facebook.com.
+asg.gershmanbrown.com.
+a.root-servers.net.
+a.root-servers.net.
+avarady.files.wordpress.com.
+fxfeeds.mozilla.com.
+news.commscope.com.
+a.root-servers.net.
+jailbreak-me.info.
+static.ak.fbcdn.net.
+www.speedtest.gr.
+ropavieja72.blogspot.com.
+www.shopbando.com.
+fbcdn-photos-a.akamaihd.net.
+shared.live.com.
+a.root-servers.net.
+search.treasuretrooper.com.
+saincsa.com.
+beacon-1.newrelic.com.
+scholar.google.com.
+profile.ak.fbcdn.net.
+www.facebook.com.
+226.13.139.74.in-addr.arpa.
+250.205.168.90.in-addr.arpa.
+231.32.116.46.in-addr.arpa.
+nobee.jefferson.lib.la.us.
+a.root-servers.net.
+194.5.166.190.in-addr.arpa.
+i-cdn.servedbyopenx.com.
+_913_35_4.
+pixel.facebook.com.
+111.188.8.200.in-addr.arpa.
+mi.adinterax.com.
+m.facebook.com.
+1.map.pop6.com.
+s7.addthis.com.
+www.poraqui.net.
+sro.whatsapp.net.
+cettente.com.
+mail.belnet.ru.
+www.google.com.
+bn.rstel.net.
+doug1izaerwt3.cloudfront.net.
+ocsp.usertrust.com.
+www.listablaze.com.
+troy.edu.
+yahoo.com.
+apps.facebook.com.
+healthtools.aarp.org.
+o-o.preferred.dfw06s10.v15.lscache1.c.youtube.com.
+a6.sphotos.ak.fbcdn.net.
+72.75.45.108.in-addr.arpa.
+alinvest.cz.
+a1067.phobos.apple.com.edgesuite.net.
+deepweb.spb.ru.
+www.juicyads.com.
+cdn.widgetserver.com.
+mail.ek-chor-cn.com.
+a995.mm1.akamai.net.
+www.lmp-adapter.com.
+preissturz24.com.
+i3.ytimg.com.
+www.connectmaster.org.
+profile.ak.fbcdn.net.
+www.facebook.com.
+www.google.se.
+www.92to.com.
+www.youtube.com.
+www.addthis.com.
+profile.ak.fbcdn.net.
+uvsk6ojda.q55x9y1r.
+creative.ak.fbcdn.net.
+mx3.westlothian.gov.uk.
+127.93.101.208.in-addr.arpa.
+a.root-servers.net.
+external.ak.fbcdn.net.
+228.245.25.86.in-addr.arpa.
+real-url.org.
+252.105.204.82.in-addr.arpa.
+news.newsmax.com.
+adamwestinc.com.
+e5016.b.akamaiedge.net.
+vvnkdlu.vlingo.com.
+celestica-catc.com.
+www.malwarepatrol.net.
+photos-f.ak.fbcdn.net.
+lacasadelritmo.net.
+11.245.173.70.in-addr.arpa.
+adserving.cpxinteractive.com.
+813562poj.01ov.
+m.addthisedge.com.
+printdirection.com.1.arsmtp.com.
+members.ebay.com.
+laoficina.blogsmyspace.es.
+www.mexicolaw.com.mx.
+.
+a.root-servers.net.
+www.tune-town.com.
+a2.sphotos.ak.fbcdn.net.
+insurancepill.com.
+s0.2mdn.net.
+a.root-servers.net.
+www.iacea.com.ar.
+wssecmgr2.atlanta.hp.com.
+www.colonirritable.com.ar.
+s0.2mdn.net.
+www.statcounter.com.
+kazna.spb.ru.
+fbcdn-profile-a.akamaihd.net.
+ru.wikipedia.org.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+i3.ytimg.com.
+a8.sphotos.ak.fbcdn.net.
+s2.youtube.com.
+eu.wikipedia.org.
+a771.da1.akamai.net.
+www.facebook.com.
+www.google-analytics.com.
+144.178.94.201.in-addr.arpa.
+mx.yearginmetals.com.
+lucaspublicarena.blogspot.com.
+i275.photobucket.com.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+upload.wikimedia.org.
+npi2.phys.msu.ru.
+11.177.92.91.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+time-nw.nist.gov.
+client.akamai.com.
+80.201.191.186.in-addr.arpa.
+apir.webrep.avast.com.
+traffic.outbrain.com.
+wx1epls9s.v54n9z0d.
+omcdit.net.
+photos-a.ak.fbcdn.net.
+165.17.237.190.in-addr.arpa.
+espn.sl.advertising.com.
+7rivp9bhw.h88d8x7f.
+www.brothersoft.com.
+47.28.24.189.in-addr.arpa.
+loading2.widdit.com.
+www.noballs.co.uk.
+mail.myspa2go.com.
+www.ortizortizabogados.com.mx.
+diym2yidm.87hq.
+d.adroll.com.
+de.answers.yahoo.com.
+s-static.ak.facebook.com.
+dtboot.orbitdownloader.com.
+photos-g.ak.fbcdn.net.
+d2094192.xoom.it.
+cgenetwork.com.
+mx1.dici.ru.
+comstor.com.
+profile.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+www.metalitalia.com.
+usersuz.newsvine.com.
+btinternbet.com.
+i2.ytimg.com.
+fr.wikipedia.org.
+111.139.130.27.in-addr.arpa.
+supernet.santander.com.uy.
+cdn1.image.keezmovies.phncdn.com.
+www.adobe.com.
+mx1.beget.ru.
+s.ytimg.com.
+mailgate.sebastianmclean.com.
+mail3.fibrogen.com.
+info.xvideos.com.
+www.sclerals.com.
+isohunt.com.
+prodigy.msn.com.
+host-delay.logmein-gateway.com.
+207.135.80.190.in-addr.arpa.
+0.docs.google.com.
+tiss.com.ru.
+www.apple.com.
+static.ak.fbcdn.net.
+musgara.ru.
+21.43.210.81.in-addr.arpa.
+streamerapi.finance.yahoo.com.
+col.stb00.s-msn.com.
+mailrelay.wernsing.de.
+49.75.42.114.in-addr.arpa.
+report.mpcstar.com.
+www.facebook.com.
+www.thesoapopera.com.
+a.root-servers.net.
+www.aardvarktopsitesphp.com.
+gamefilez.mofunzone.com.
+teredo.ipv6.microsoft.com.
+api.facebook.com.
+d2105399.xoom.it.
+apis.google.com.
+89.107.216.217.in-addr.arpa.
+configuration.apple.com.
+16.189.229.66.in-addr.arpa.
+www.facebook.com.
+ark-one.com.
+faisdodo.com.
+tecumsehindia.com.
+243.31.172.187.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+103.1.168.192.in-addr.arpa.
+184.185.110.189.in-addr.arpa.
+fizomed.ru.
+uac.advertising.com.
+download325.avast.com.
+crux.max-i-tec.net.
+explicit.fr.
+hamburgeramerica.blogspot.com.
+groups.google.com.mx.
+230.17.50.190.in-addr.arpa.
+0-257.channel.facebook.com.
+www.google-analytics.com.
+cshi.ru.
+fbcdn-profile-a.akamaihd.net.
+db2.stb01.s-msn.com.
+227.16.33.189.in-addr.arpa.
+mymail.sap.com.
+download330.avast.com.
+www.odnoklassniki.ru.
+uniquescrapdesigns.com.
+bin-short.whatsapp.net.
+earthlink.net.
+v11.nonxt5.c.youtube.com.
+www.mrmovietimes.com.
+s.amazon-adsystem.com.
+b.scorecardresearch.com.
+www.abamia.net.
+www.facebook.com.
+a.root-servers.net.
+4.bp.blogspot.com.
+gilpizano.com.
+gilchristconst.com.
+d15gt9gwxw5wu0.cloudfront.net.
+calendar.live.com.
+b._dns-sd._udp.lan.
+simsandcompany.com.
+sp.cwfservice.net.
+i4.ytimg.com.
+time.nist.gov.
+www.gstatic.com.
+teredo.ipv6.microsoft.com.
+rnxouxyq2.j76c7e5x.
+img1.123friendster.com.
+android.clients.google.com.
+a5.sphotos.ak.fbcdn.net.
+rorb:1mep.m48s7w6o.
+jzca371im.69jk.
+www.agronomia.uchile.cl.
+www.aqualabtechnologies.com.
+www.google.com.
+www.mibloglg.com.ar.
+mail.bankatlanticbancorp.com.
+openx.panet.co.il.
+photos-e.ak.fbcdn.net.
+243.174.173.189.in-addr.arpa.
+s-static.ak.fbcdn.net.
+urllol.
+es.optimost.com.
+a3.sphotos.ak.fbcdn.net.
+www.zonaganjah.net.
+a1.sphotos.ak.fbcdn.net.
+videosraros.info.
+media.doink.com.
+www.ftplive.com.
+ssl.google-analytics.com.
+images02.mundoanuncio.com.hn.
+h.live.com.
+156.213.30.79.in-addr.arpa.
+api.iheart.com.
+katiluv87.livejournal.com.
+cdn2.ads.datinggold.com.
+191.54.94.186.in-addr.arpa.
+german.alibaba.com.
+www.ornithology.com.
+ads.popconnex.com.
+dns.msftncsi.com.
+hurstlabeling.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+ads1.msn.com.
+bucaramanga.pegateya.com.
+249.133.191.186.in-addr.arpa.
+www.facebook.com.
+api.zynga.com.
+on.fb.me.
+www.adobe.com.
+hifiheadphones.co.uk.
+blog.beliefnet.com.
+www.google.com.
+_728_64_7.
+www.cardscanning.com.
+pubads.g.doubleclick.net.
+news.bbc.co.uk.
+a.root-servers.net.
+affiliates.tshirt-factory.com.
+26.media.tumblr.com.
+_386_97_6.
+www.acn.com.ve.
+conn.skype.com.
+fitness.meetup.com.
+skills.business.qld.gov.au.
+becnet.com.
+static.ak.fbcdn.net.
+sp.cwfservice.net.
+0-staging.channel.facebook.com.
+game.landsharkgames.com.
+www.elrinconderesu.com.
+market.android.com.
+artevanhautte.blogspot.com.
+feeds.animekon.com.
+www.periodico-eldia.com.
+static1.spilcdn.com.
+www.registrar.ucf.edu.
+www.propagandamatrix.com.
+www.google.com.
+www.scarletpress.com.
+connect.facebook.net.
+129.83.125.99.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx2.russneft.ru.
+substanceabusefree.org.
+8.courier-sandbox-push-apple.com.akadns.net.
+www.grupoamor.com.
+0-ji-w.channel.facebook.com.
+apix.iminent.com.
+115.186.0.65.in-addr.arpa.
+time.chttl.com.tw.
+tradesecret.com.s9b1.psmtp.com.
+islam.makcdn.com.
+251.109.211.108.in-addr.arpa.
+mail.stvgkb4.ru.
+es-la.facebook.com.
+usns.uwingame.com.
+streamate.doublepimp.com.
+adspaces.ero-advertising.com.
+ads.cpxinteractive.com.
+132.181.205.190.in-addr.arpa.
+tietex.com.
+www.redaroa.org.
+en.gamescope.ru.
+creative.ak.fbcdn.net.
+222.164.159.189.in-addr.arpa.
+www.facebook.com.
+113.243.23.91.in-addr.arpa.
+v6.nonxt7.googlevideo.com.
+bonhumor.blog.com.
+17.89.231.189.in-addr.arpa.
+234.89.130.189.in-addr.arpa.
+mail.fmiint.com.
+berta4.simsim.ge.
+www.facebook.com.
+teredo.ipv6.microsoft.com.
+apis.google.com.
+shudbefishin.listal.com.
+moveon.org.
+shorouknews.com.
+webnesbay.com.
+dns.msftncsi.com.
+youtu.be.
+sakioneil.blogspot.com.
+abc.ojdinteractiva.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b.scorecardresearch.com.
+105.66.110.189.in-addr.arpa.
+platform.twitter.com.
+glyphservices.com.
+adframes.iminent.com.
+114.112.153.114.in-addr.arpa.
+114.40.114.186.in-addr.arpa.
+150.74.164.190.in-addr.arpa.
+voxomat.com.
+oodweynenews.com.
+xksvzbytb.58pj.
+trailers.apple.com.
+a.root-servers.net.
+www.facebook.com.
+www.youtube.com.
+mmi.explabs.net.
+mail.legalemail.com.
+www.planetacurioso.com.
+124.74.134.187.in-addr.arpa.
+a.root-servers.net.
+fbcdn-photos-a.akamaihd.net.
+beta.stun.voice.yahoo.com.
+126.92.82.203.in-addr.arpa.
+isse.utk.edu.
+www.wallstein-verlag.de.
+www.google.com.
+profile.ak.fbcdn.net.
+sp.ask.com.
+img2.solocunts.com.
+conservacionyequidad.podomatic.com.
+content.yieldmanager.edgesuite.net.
+ksn2-12.kaspersky-labs.com.
+googleads.g.doubleclick.net.
+profile.ak.fbcdn.net.
+ip33.mebel-moskva.ru.
+www.baitandswitchtv.com.
+newsrss.bbc.co.uk.
+google.com.
+miamireia.com.
+b.scorecardresearch.com.
+a6.sphotos.ak.fbcdn.net.
+www.farmaervas.com.br.
+isvbqx.info.
+www.google-analytics.com.
+clients1.google.com.
+a749.g.akamai.net.
+fcv.org.
+apple-mobile.query.yahooapis.com.
+203.34.237.189.in-addr.arpa.
+159.76.222.189.in-addr.arpa.
+update.slimdevices.com.
+api.twitter.com.
+creative.ak.fbcdn.net.
+www.nikkijackson.com.
+exalead.ru.
+ds.serving-sys.com.
+developers.facebook.com.
+rest-img.msg.yahoo.com.
+3cpok.ru.home.
+media.trafficjunky.net.
+225.78.88.200.in-addr.arpa.
+79.132.160.187.in-addr.arpa.
+www.asiagames.com.
+pixel.facebook.com.
+232.85.41.189.in-addr.arpa.
+www.google.com.
+0-155.channel.facebook.com.
+ahsl.ca.
+www.google.com.mx.
+twitter.com.
+hiphopcanario.com.
+toolbarqueries.clients.google.com.
+118.60.125.69.in-addr.arpa.
+nucrdk.com.
+media.gameworldnetwork.com.
+orcart.facebook.com.
+a.root-servers.net.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+juventud.gob.pe.
+degiacomo.com.
+156.228.206.200.in-addr.arpa.
+36.172.112.200.in-addr.arpa.
+profile.ak.fbcdn.net.
+t1.gstatic.com.
+syndication.exoclick.com.
+tc.v14.cache1.c.youtube.com.
+rlp.ru.
+flightstats-inc.com.
+a1.sphotos.ak.fbcdn.net.
+sc17.rules.mailshell.net.
+ars.oscar.aol.com.
+www.educatednation.com.
+www.games.soft82.com.
+chartboost.com.
+bnpparibas.clicmobileanalytics.com.
+s-static.ak.facebook.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+249.208.180.79.in-addr.arpa.
+tubisuteria.com.ve.
+118.224.10.186.in-addr.arpa.
+24.234.49.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+133.52.115.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+25.225.71.98.in-addr.arpa.
+a.root-servers.net.
+dev.hardsextube.com.
+google.co.uk.
+www.facebook.com.
+content.yieldmanager.edgesuite.net.
+www.google.com.
+developers.facebook.com.
+www.facebook.com.
+img3.catalog.video.msn.com.
+123.98.209.189.in-addr.arpa.
+www.petrosil.com.
+cs4495.vk.com.
+152.97.149.202.in-addr.arpa.
+www.brautkleideronlineladen.de.
+books.google.com.mx.
+tpemail.com.s8b2.psmtp.com.
+1.122.235.199.in-addr.arpa.
+feeds.bitterwallet.com.
+apis.google.com.
+services.digg.com.
+www.google-analytics.com.
+www.e-encuestas.com.
+sofit-spb.ru.
+mattflynn.co.uk.
+theavamovement.com.
+17.160.8.200.in-addr.arpa.
+alsglobal.com.
+a955.phobos.apple.com.
+verdizon.net.
+_365_99_1.
+ow.ly.
+crl.globalsign.net.
+www.sjdxa.org.
+151.157.211.89.in-addr.arpa.
+mx.horoscopo.yahoo.net.
+dns.msftncsi.com.
+www.slowfood.it.
+www.webdesign-entreprise.com.
+201.199.91.187.in-addr.arpa.
+c-0.19-a309f481.483.1518.19d4.3ea1.410.0.3wl4k743w1rtfisw2chzs8baci.avqs.mcafee.com.
+cyber.playboy.com.
+static.ak.fbcdn.net.
+backend.uniblue.com.
+mp3dlb.cdn.kuwo.cn.
+234.96.179.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+capital604.com.
+a7.sphotos.ak.fbcdn.net.
+pool.ntp.org.
+photos-e.ak.fbcdn.net.
+stormsustainability.com.
+a3.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+38.137.139.190.in-addr.arpa.
+aln-mailrelay.att.net.
+www.hgh.com.
+www.computrabajo.com.mx.
+.
+hesperiatrussinc.com.
+productnews.link.net.
+profile.ak.fbcdn.net.
+www.michaeltilsonthomas.com.
+download831.avast.com.
+www.twittular.com.
+www.theclimateproject.org.
+csi.gstatic.com.
+ahzxwacg4.07vj.
+155.186.93.186.in-addr.arpa.
+didrickmedical.com.s7a1.psmtp.com.
+230.1.240.201.in-addr.arpa.
+162.189.13.209.in-addr.arpa.
+s.ytimg.com.
+bridge.inc.ru.
+19-courier.push.apple.com.
+reminc.com.
+twitter.com.
+orcart.facebook.com.
+login.yahoo.com.
+84.8.166.89.in-addr.arpa.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+getprof.nl.np.community.playstation.net.
+amazingdeals1.info.
+dubaided.com.
+227.88.161.189.in-addr.arpa.
+119.47.98.174.in-addr.arpa.
+136.11.48.174.in-addr.arpa.
+apps.facebook.com.
+notasparalectorescuriosos.blogspot.com.
+belleusa.com.
+tochlit.ru.
+21.53.134.187.in-addr.arpa.
+qipim.com.
+www.oooforum.org.
+www.twitter.com.
+49.8.182.93.in-addr.arpa.
+forum.siemens-club.ru.
+spider.tm.
+premierfoto.ru.
+znoihyb.cc.home.
+www.consejotecnicoconsultivo.org.mx.
+a5.sphotos.ak.fbcdn.net.
+82yahoo.com.
+a995.mm1.akamai.net.
+auddi.ru.
+mariah.com.
+ihd.com.
+fbcdn-profile-a.akamaihd.net.
+i.ebayimg.com.
+www.google-analytics.com.
+55.49.32.177.in-addr.arpa.
+dogguy.us.
+ads7261.hotwords.com.ar.
+www.airspartner.com.
+dns.msftncsi.com.
+fonts3.scribdassets.com.
+www.planetmad.es.
+photos-b.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+silveiro.com.
+a4.sphotos.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+121.93.89.210.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+ifab.spb.ru.
+www.apple.com.
+th02.deviantart.net.
+safebrowsing-cache.google.com.
+gsp10-ssl.apple.com.
+hyec.en.alibaba.com.
+pixel.facebook.com.
+api-public.addthis.com.
+www.biggunspestcontrol.com.
+ib.adnxs.com.
+a3.sphotos.ak.fbcdn.net.
+download.mozilla.org.
+www.google.com.
+mail.thomascook.fr.
+pcsynergy.com.
+178.204.5.174.in-addr.arpa.
+rolypolygangbang.maniacpass.com.
+lb._dns-sd._udp.0.0.0.5.in-addr.arpa.
+www.milenio.com.
+179.186.178.183.in-addr.arpa.
+163.60.244.189.in-addr.arpa.
+us.telex.com.
+a.root-servers.net.
+a.root-servers.net.
+142.225.255.201.in-addr.arpa.
+ask.com.
+221.182.137.186.in-addr.arpa.
+c7.zedo.com.
+xqtspkhmxruszajp.org.
+adictosgeek.com.
+api-read.facebook.com.
+0-74.channel.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+gas-web2.no-ip.info.
+a1890.g.akamai.net.
+96.46.137.190.in-addr.arpa.
+248.8.149.83.in-addr.arpa.
+i.dell.com.
+gateway.loseit.com.
+guiamexico.com.mx.
+62.122.143.101.in-addr.arpa.
+mailgate.cybercity.dk.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+external.ak.fbcdn.net.
+d2103269.xoom.it.
+67.24.231.91.in-addr.arpa.
+py.starmedia.com.
+dr._dns-sd._udp.lan.
+www.vinnylingham.com.
+mx.youtube.com.
+aka-cdn-ns.adtech.de.
+creatividadcondulsuras.blogspot.com.
+www.gtasanandreas.net.
+maps.google.co.uk.
+www.elpatronfm.com.mx.
+restauracionreseda.com.
+a1.sphotos.ak.fbcdn.net.
+bergancardio.com.
+dingtao333.3322.org.
+budapest.frasershospitality.com.
+31.190.63.69.in-addr.arpa.
+google.com.
+202.236.159.110.in-addr.arpa.
+www.seresvivos.net.
+a954.v.phobos.apple.com.
+alloymail.com.
+limbobreakfast.blogspot.com.
+www.google-analytics.com.
+www.pideyoo.com.
+449-async.olark.com.
+73.87.155.190.in-addr.arpa.
+em1x-375.lhr.messaging.nokia.com.
+ar-ar.facebook.com.
+dns.msftncsi.com.
+c-0.19-a30f1081.80481.1518.19d1.3ea1.200.0.hgthlrt321s5gnj4pjsjfr7q4q.avqs.mcafee.com.
+accounts.google.com.
+158.220.188.189.in-addr.arpa.
+pixel.facebook.com.
+43.210.214.67.in-addr.arpa.
+i3.ytimg.com.
+www.youtube.com.
+www.housetweaking.com.
+maps.google.es.
+v10.nonxt2.c.googlesyndication.com.
+static6.flixster.com.
+plod.ru.
+z-ecx.images-amazon.com.
+azad-net.net.
+sac.gti.mcafee.com.
+www.cnn.com.
+ao.l.com.
+a3.sphotos.ak.fbcdn.net.
+ar.answers.yahoo.com.
+t0.gstatic.com.
+googleads.g.doubleclick.net.
+fr-fr.facebook.com.
+photos-d.ak.fbcdn.net.
+www.youtube.com.
+24.195.65.74.in-addr.arpa.
+a.root-servers.net.
+57.248.113.186.in-addr.arpa.
+maps.google.com.
+s.ytimg.com.
+search.yahoo.com.
+www.alanhoskins.com.
+25.10.160.187.in-addr.arpa.
+developers.facebook.com.
+www.rmservices.nsw.gov.au.
+localhost.
+a5.sphotos.ak.fbcdn.net.
+www.pufcompany.com.
+exf1.dsa.reldom.tamu.edu.
+hiloterapiaclubdeagujaehilo.blogspot.com.
+inc.appliedsec.com.
+b.scorecardresearch.com.
+63.91.169.189.in-addr.arpa.
+en.netlog.com.
+newversion.epyte.com.
+foxvall.com.
+www.sevillasevillasevilla.com.
+www.instants.cl.
+37.153.104.68.in-addr.arpa.
+103.81.181.85.in-addr.arpa.
+122.218.93.186.in-addr.arpa.
+www.facebook.com.
+moonscoop.com.
+liquidlove.cc.
+16.99.9.177.in-addr.arpa.
+download.iolo.net.
+www.googleadservices.com.
+a652.phobos.apple.com.
+www.vai.com.
+a2.sphotos.ak.fbcdn.net.
+_482_20_2.
+pagead2.googlesyndication.com.
+dns.msftncsi.com.
+viavh1la.112.2o7.net.
+mjwinnovations.com.
+www.twitter.com.
+rawarrior.com.
+secure.shared.live.com.
+voyo.cz.
+titanium30-en.url.trendmicro.com.
+137.0.72.187.in-addr.arpa.
+75.161.52.187.in-addr.arpa.
+helo.org.
+109.76.250.166.in-addr.arpa.
+lyv9u78hs.k16u9c8f.
+master.sdabocconi.it.
+twitter.com.
+39.201.58.200.in-addr.arpa.
+secure-us.imrworldwide.com.
+um16.eset.com.
+static.ak.fbcdn.net.
+ntp.glb.nist.gov.
+www.youtube.com.
+100.1.168.192.in-addr.arpa.
+www.autoscout24.es.
+www.facebook.com.
+www.ngskintools.com.
+check6.facebook.com.
+qjtogpkupjighkr.net.
+img.fiesta101.com.s3.amazonaws.com.
+photos-b.ak.fbcdn.net.
+:y85m4vcd.g53f3l5t.
+pagead2.googlesyndication.com.
+xatracing.com.
+profile.ak.fbcdn.net.
+142.173.205.190.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+coxnc.com.
+www.googletagservices.com.
+147.142.152.189.in-addr.arpa.
+221.108.204.190.in-addr.arpa.
+207.215.19.187.in-addr.arpa.
+4b2eapnji.q49s5i5z.
+secure-us.imrworldwide.com.
+www.peachtree.com.
+10.225.230.190.in-addr.arpa.
+prensaagraria.blogspot.com.
+api-read.facebook.com.
+peliculasdelholocaustojudio.blogspot.com.
+3rxba3akr.31xu.
+davis-cpa.net.
+www.video-lyrics.com.
+33.210.160.201.in-addr.arpa.
+dns.msftncsi.com.
+peterhalliwell.com.
+www.elcornudo.es.
+96.148.59.199.in-addr.arpa.
+www.google.com.
+241.239.12.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.sophiedeeonline.com.
+mail-attachment.googleusercontent.com.
+api-read.facebook.com.
+luisldg.wordpress.com.
+mail.kphbuilds.com.
+389.webim0221.webim.myspace.com.
+us-w1.rockmelt.com.
+www.kachivaches.es.
+ow4ml3wlr.g99l5x2u.
+novoco.com.
+152.174.172.189.in-addr.arpa.
+www.movies-24h.com.
+eilat.sci.brooklyn.cuny.edu.
+apple.com.
+www.windowtothemovies.com.
+army.togetherweserved.com.
+ad.e-viral.com.
+rcp.na.blackberry.com.
+rss.cbc.ca.
+vp.sip.messenger.msn.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.facebook.com.
+iceweb.net.
+content.yieldmanager.edgesuite.net.
+mailgateway1.hochschule.li.
+www.ottoskins.com.
+a.root-servers.net.
+apis.google.com.
+149.115.231.190.in-addr.arpa.
+www.googleadservices.com.
+init-p01md.apple.com.
+19-courier.push.apple.com.
+www.gratisistockholm.nu.
+mx.jewsonrealty.com.
+a.ads2.msads.net.
+a.root-servers.net.
+ccshows.com.
+csi.gstatic.com.
+89.1.40.201.in-addr.arpa.
+abacus.tumblr.com.
+sprint-canada.com.home.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+i730.photobucket.com.
+b.scorecardresearch.com.
+www.facebook.com.
+yiwucollection.en.alibaba.com.
+sro-alianzalatina.blogspot.com.
+174.81.215.201.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+bs.serving-sys.com.
+www.barcodesinc.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+207.167.130.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+secure.csfm.com.
+187.1.21.95.in-addr.arpa.
+207.120.26.92.in-addr.arpa.
+www.niswan.net.
+www.teamrocs.com.
+52.47.100.208.in-addr.arpa.
+www.google.es.
+js2.wlxrs.com.
+eabd3b6ed1.static.crowdscience.com.
+news.google.com.mx.
+htc2.accu-weather.com.
+www.glamourbabes.org.
+www.statcounter.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+155.185.49.190.in-addr.arpa.
+www.jpedsurg.org.
+www.google-analytics.com.
+ksn2-12.kaspersky-labs.com.
+0-238.channel.facebook.com.
+s7.addthis.com.
+www.bay-of-fundie.com.
+s2.youtube.com.
+www.faridaguitars.co.uk.
+profile.ak.fbcdn.net.
+www.abbyswings.nude-beach-sex.com.
+cursoderobotica.blogspot.com.
+www.amarillashialeah.com.
+apex.od.ua.
+www.guiamania.com.
+portablesdoctor-reprod.blogspot.com.
+xboxlive.ign.com.
+makeupbynyna.blogspot.com.
+www.sivananda.es.
+sun.uchc.edu.
+tdtv.microsoft.fr.
+hootsuite.com.
+a.root-servers.net.
+www.bjmama.net.
+amazonm-611.vo.llnwd.net.
+www.bunkergraphics.com.
+186.212.188.200.in-addr.arpa.
+www.net-pratique.fr.
+nethunting.files.wordpress.com.
+mail.prodigy.net.mx.
+insider.msg.yahoo.com.
+www.noubarris.net.
+c.baidu.com.
+esmas2006.occ.com.mx.
+www.google.es.
+r._dns-sd._udp.lan.
+163.105.154.184.in-addr.arpa.
+www.googleadservices.com.
+241.18.23.187.in-addr.arpa.
+api.facebook.com.
+cranbarry.com.
+svacom.com.
+external.ak.fbcdn.net.
+keckobservatory.org.
+blog.allusb.com.
+bolsasistemas.com.woopra-ns.com.
+piteau.com.1.arsmtp.com.
+s-static.ak.facebook.com.
+hosturl.no-ip.biz.
+time.nist.gov.
+www.google.com.
+download.microsoft.com.
+mail.ikka.com.
+articulo.mercadolibre.com.mx.
+clients2.google.com.
+uk.answers.yahoo.com.
+apps.facebook.com.
+photos-e.ak.fbcdn.net.
+231.43.144.78.in-addr.arpa.
+86.198.159.189.in-addr.arpa.
+87.73.58.189.in-addr.arpa.
+www.theshadowlounge.co.uk.
+widgets.twimg.com.
+creative.ak.fbcdn.net.
+www.michaela.it.
+quantumgraphics.ru.
+pumpcoinc.com.
+www.tv-so.com.
+fbcdn-sphotos-a.akamaihd.net.
+c4.zedo.com.
+www.philips.com.mx.
+video.google.com.
+news.google.com.mx.
+appsmetadata.toolbar.conduit-services.com.
+140.196.165.46.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+kabuj.polyvore.com.
+cdn.vps.net.c.footprint.net.
+camrent.se.
+www.memeadictos.org.
+dmmail01.demac.com.
+_634_23_7.
+pixel.facebook.com.
+www.thesun.co.uk.
+www.google.com.
+227.244.78.186.in-addr.arpa.
+external.ak.fbcdn.net.
+repository.jboss.org.
+b.scorecardresearch.com.
+lizzie-secret.bravoerotica.com.
+a.root-servers.net.
+dns.msftncsi.com.
+tamp04.activenetcontroller.net.
+canarias.indymedia.org.
+bs.serving-sys.com.
+ds.serving-sys.com.
+programtv.interia.pl.
+photos-e.ak.fbcdn.net.
+bd0dc.v.fwmrm.net.
+finchleycatholic.org.uk.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+crl.microsoft.com.
+www.3djuegos.com.
+_902_96_1.
+freeapps.me.
+98.235.111.58.in-addr.arpa.
+84.39.23.186.in-addr.arpa.
+apis.google.com.
+116.104.26.190.in-addr.arpa.
+www.facebook.com.
+photos-h.ak.fbcdn.net.
+version.jomsocial.com.
+228.59.89.186.in-addr.arpa.
+i4.ytimg.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+opportune.ru.
+3.247.100.97.in-addr.arpa.
+abcommortgage.com.
+shelfari-kcp.amazon.com.
+dns.msftncsi.com.
+go.microsoft.com.
+www.activolcans.info.
+api.twitter.com.
+s.jimdo.com.
+photos-g.ak.fbcdn.net.
+134.47.42.201.in-addr.arpa.
+www.buscoenlaces.es.
+dt.tongji.linezing.com.
+53.103.106.186.in-addr.arpa.
+s-static.ak.facebook.com.
+206.38.22.107.in-addr.arpa.
+4.77.206.190.in-addr.arpa.
+m.facebook.com.
+www.planetofbirds.com.
+www.ecosdosur.org.
+photos-h.ak.fbcdn.net.
+inbound.kprecruiting.com.netsolmail.net.
+r._dns-sd._udp.lan.
+mx.pronosticofoxsportsla.com.
+www.greencorrespondents.com.
+ar-ar.facebook.com.
+profile.ak.fbcdn.net.
+apps.facebook.com.
+www.los40.com.gt.
+sg-asia.vertical.search.ystg1.b.yahoo.com.
+232.77.234.189.in-addr.arpa.
+wpad.
+static.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+mail2.chat-land.org.
+elrinconbiologico.blogspot.com.
+jtools.smartmoney.com.
+www.gaylife.time4twinks.com.
+es.kioskea.net.
+bs.serving-sys.com.
+allanhomes.com.inbound10.mxlogic.net.
+external.ak.fbcdn.net.
+www.schools.com.
+misterolympia.com.ar.
+platform.twitter.com.
+heartbeat.belkin.com.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+tour.windyvidz.com.
+a6.sphotos.ak.fbcdn.net.
+de-de.facebook.com.
+u6sadblvs.86fo.
+89.171.57.186.in-addr.arpa.
+dangar.artelista.com.
+sp3.fotolog.com.
+developers.facebook.com.
+bidsystem.adknowledge.com.
+static.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+www.facebook.com.
+92.43.86.190.in-addr.arpa.
+www.tracerplus.com.
+ad.doubleclick.net.
+a.root-servers.net.
+26.249.208.86.in-addr.arpa.
+apps.facebook.com.
+gopro.com.
+52.86.164.189.in-addr.arpa.
+img6.pictiger.com.
+www.randomdetox.com.
+34.184.110.189.in-addr.arpa.
+145.63.226.213.in-addr.arpa.
+apps.facebook.com.
+tlanders.com.
+waycooldesigns.com.
+247.168.76.76.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+63.100.157.186.in-addr.arpa.
+hog.assets.zgncdn.com.
+www.joomla.royy.net.
+www.facebook.com.
+_725_84_1.
+checkout.google.c.
+a.root-servers.net.
+ssl.gstatic.com.
+tswgarage.blogspot.com.
+mail.prometeo.com.
+a5.sphotos.ak.fbcdn.net.
+newsrss.bbc.co.uk.
+time.chttl.com.tw.
+28.249.1.181.in-addr.arpa.
+a.root-servers.net.
+mx3.wellsfargo.com.
+radiouno.net.
+content3c1b.omroep.nl.
+js.casalemedia.com.
+www.3dglasses.com.
+watson.microsoft.com.
+144.253.35.200.in-addr.arpa.
+atlr.ec.
+a6.sphotos.ak.fbcdn.net.
+p4.focus.de.
+central.keppel.k12.ca.us.
+foto.paraisowebcam.com.
+groupevianden.com.
+tredir.go.com.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+www.facebook.com.
+s2.youtube.com.
+200.190.9.186.in-addr.arpa.
+feeds.bbci.co.uk.
+linkin-park-theme.archivospc.com.
+www.citasdeamor.es.
+65.186.179.190.in-addr.arpa.
+jpwkake3m.z31z8n6d.
+www.google.com.mx.
+crm.digitalchocolate.com.
+210.201.10.186.in-addr.arpa.
+sites.google.com.
+apps.facebook.com.
+mail2.acpr.ru.
+fbcdn-profile-a.akamaihd.net.
+i.i.imgur.com.
+afcmails.com.
+www.facebook.com.
+www.newfoundglorystuff.com.
+www.bing.com.
+www.sektor.gen.tr.
+form.hktdc.com.
+129.86.53.186.in-addr.arpa.
+col.stb01.s-msn.com.
+time.chttl.com.tw.
+madrid.salir.com.
+i4.ytimg.com.
+www.adbrite.com.
+168.161.105.186.in-addr.arpa.
+obradoretumbante.globo.com.
+youtube-downloader-hq-pro.softonic.com.
+photos.cams.com.
+clock.fmt.he.net.
+ydpj.com.
+hyperdatis.de.
+mail.muellerenvironmental.com.
+m.see-my-ip.com.
+checkip.dyndns.org.
+sbcglobal.net.
+photos-e.ak.fbcdn.net.
+market.android.com.
+chat.onlinefootballmanager.co.uk.
+indoexports.net.
+view.atdmt.com.
+a1822.phobos.apple.com.
+ntp1.dlink.com.
+gsp1.apple.com.
+id.google.com.
+ygum7qsd:.y41n2s4s.
+cheapestenergy.eu.
+shreya.co.in.
+safebrowsing.clients.google.com.
+www.incremento.net.
+keepalive.se2.softether.com.
+204.49.135.181.in-addr.arpa.
+15.149.220.66.in-addr.arpa.
+www.dbsheppard.com.
+secure.wlxrs.com.
+www.loveinfobook.com.
+www.youtube.com.
+highslide.com.
+p.yoho.cn.
+api.twitter.com.
+nj663tv3t.z21t0j0p.
+twitter.co.
+ksn2-12.kaspersky-labs.com.
+a.root-servers.net.
+plusone.google.com.
+ydigminkt.97mt.
+www.pcconnectionexpress.com.
+entertainment.webshots.com.
+155.77.146.189.in-addr.arpa.
+229.155.64.177.in-addr.arpa.
+static.ak.fbcdn.net.
+hhzbhhpfn.95rq.
+a.root-servers.net.
+221.63.204.186.in-addr.arpa.
+metrics.apple.com.
+assets.tumblr.com.
+cdn02.cartown.com.edgesuite.net.
+static.ak.fbcdn.net.
+time.windows.com.
+www.gameslist.com.
+www.sega.nl.
+fonts.googleapis.com.
+gamer.portail.free.fr.
+www.millenniumassessment.org.
+alienbabeltech.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+a.root-servers.net.
+jovenescoleccionistas.tallermultinacional.org.
+194.211.25.189.in-addr.arpa.
+ssl.gstatic.com.
+a.root-servers.net.
+usmpagency.com.s7b1.psmtp.com.
+www.gdocu.es.
+29.172.203.190.in-addr.arpa.
+156.10.228.77.in-addr.arpa.
+cdn.zeusclicks.com.
+glerum.com.
+s-static.ak.fbcdn.net.
+i1.ytimg.com.
+photos-c.ak.fbcdn.net.
+239.28.193.207.in-addr.arpa.
+www.atlantafixture.com.
+csi.gstatic.com.
+www.nothingcomparestohavana.com.
+a6.sphotos.ak.fbcdn.net.
+www.apeironmagazine.com.
+116.15.33.90.in-addr.arpa.
+safebrowsing-cache.google.com.
+a8.sphotos.ak.fbcdn.net.
+insider.msg.yahoo.com.
+a.root-servers.net.
+www.pbscolorado.com.
+79.121.113.186.in-addr.arpa.
+i2.ytimg.com.
+a5.sphotos.ak.fbcdn.net.
+www.hotmail.com.
+www.microsoft.com.
+splayer.uptodown.com.
+91.230.95.65.in-addr.arpa.
+search.babylon.com.
+hipay.com.
+:knpbrhnp.o32z8k4r.
+www.mesmo.tv.
+mail.imageworks4signs.com.
+.
+230.169.152.85.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.aa.com.
+profile.ak.fbcdn.net.
+175.98.63.212.in-addr.arpa.
+exchange2003.snapon.com.
+ajax.cloudflare.com.
+gosstroy.gov.ru.
+static.ak.fbcdn.net.
+flowhot.info.
+109.94.86.200.in-addr.arpa.
+smtp2.vianetworks.de.
+www.facebook.com.
+131.81.142.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+nomolesten.com.
+statse.webtrendslive.com.
+photos-c.ak.fbcdn.net.
+mail.fortifiber.com.
+da8thaern.95ra.
+login.toolbar.conduit-services.com.
+38.25.141.201.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+32-courier.push.apple.com.
+mipeq.com.
+105.47.52.186.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+47.189.142.190.in-addr.arpa.
+209.72.22.186.in-addr.arpa.
+www.ultimatehandyman.org.
+free2night.net.
+upload.wikimedia.org.
+f42.stagero.eu.
+premiumcars.autotrader.ca.
+linksfb.com.
+www.youtube.com.
+cuentame.inegi.org.mx.
+sp.cwfservice.net.
+a3.sphotos.ak.fbcdn.net.
+infanciasolidaria.blogspot.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+apis.google.com.
+content.dl-rms.com.
+kearnyfederalsavings.net.inbound10.mxlogic.net.
+a3.sphotos.ak.fbcdn.net.
+mowprod.kaboomsocial.com.
+pixel.facebook.com.
+ajax.googleapis.com.
+xcdn.xgraph.net.
+u40.eset.com.lan.
+97.44.90.24.in-addr.arpa.
+lb-chw-webserver-cache-1218636608.us-east-1.elb.amazonaws.com.
+161.42.0.186.in-addr.arpa.
+81.184.132.94.in-addr.arpa.
+googleads.g.doubleclick.net.
+a212.phobos.apple.com.
+by2msg3010706.gateway.messenger.live.com.
+myo74ld8m.u67k2r5q.
+www.google.com.
+static.ak.fbcdn.net.
+www.google.com.
+dtboot.orbitdownloader.com.
+www.google-analytics.com.
+lalocuradelpecado.blogspot.com.
+v8.cache7.c.youtube.com.
+aromanova.ru.
+s-static.ak.facebook.com.
+at.amgdgt.com.
+rs531l32.rapidshare.com.
+payments.ebay.com.
+www.facebook.com.
+www.askvids.com.
+9gag.com.
+165.190.12.61.in-addr.arpa.
+webmail35.yandex.ru.
+fr-fr.facebook.com.
+140.80.141.201.in-addr.arpa.
+yamalarchaeology.ru.
+google.com.
+checkip.dyndns.org.
+165.50.0.10.in-addr.arpa.
+plus.google.com.
+content.mobile.viaden.com.
+hog.assets1.zgncdn.com.
+www.geobaby.com.
+29.134.134.187.in-addr.arpa.
+29.160.1.201.in-addr.arpa.
+go.trafficshop.com.
+110.74.158.200.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+179.wap517.biz.
+fbcdn-photos-a.akamaihd.net.
+downloads3.kaspersky-labs.com.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+ad.yieldmanager.com.
+vgcqabgpc.51lt.
+sp.cwfservice.net.
+b3.imgsrc.ro.
+a.root-servers.net.
+it-it.facebook.com.
+cdn.api.twitter.com.
+0-68.channel.facebook.com.
+149.94.209.201.in-addr.arpa.
+207.241.151.79.in-addr.arpa.
+dns.msftncsi.com.
+www.facebook.com.
+ttu.edu.
+tmx.technoratimedia.com.
+photos-g.ak.fbcdn.net.
+pnpco.com.
+content.yieldmanager.edgesuite.net.
+csi.gstatic.com.
+249.62.148.190.in-addr.arpa.
+wacomail1.wacotrib.com.
+p.twimg.com.
+76.87.228.189.in-addr.arpa.
+www.17dht.com.
+tv.mk.ru.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.programmingfacts.com.
+hepm.hitachi-asia.com.
+239.194.110.85.in-addr.arpa.
+ping4.client.sandai.net.
+deadtravelgroup.blogspot.com.
+a2.sphotos.ak.fbcdn.net.
+i.ytimg.com.
+platform.stumbleupon.com.
+www.google.com.
+bit.ly.
+77.158.8.200.in-addr.arpa.
+www.tripsandtreasures.blogspot.com.
+sc2.rules.mailshell.net.
+www.nikkohurtado.com.
+vtr.net.
+218.35.153.201.in-addr.arpa.
+bertamares.blogspot.com.
+ar.wikipedia.org.
+www.hogarandum.com.
+www.cell-lines-service.de.
+my.plaza.rakuten.co.jp.
+a.root-servers.net.
+mlocate.spotlife.net.
+archiblock.com.
+www.rockmobilez.net.
+49.224.93.186.in-addr.arpa.
+bin-short.whatsapp.net.
+l972nb7:u.x91z2x2l.
+102.127.250.201.in-addr.arpa.
+premierair.com.
+www.adobe.com.
+dnl-01.geo.kaspersky.com.
+www.virit.net.
+it-it.facebook.com.
+tmz.com.
+mx00.1and1.co.uk.
+www.trm.md.
+lb._dns-sd._udp.lan.
+rlwaconsult.com.
+a5.sphotos.ak.fbcdn.net.
+mail.google.com.
+techhelp0417.webs.com.
+61.88.233.189.in-addr.arpa.
+gimnasialatina.com.
+www.spike.com.
+.
+twitter.com.
+www.sunwayhotels.com.
+profile.ak.fbcdn.net.
+aka-cdn-ns.adtech.de.
+dns.msftncsi.com.
+nomulous.com.
+labontology.wikispaces.com.
+71.212.58.186.in-addr.arpa.
+www.emotional.sk.
+static.exoclick.com.
+comidaspostresalimentosrecetascomidas.blogspot.com.
+mscrl.microsoft.com.
+a6.sphotos.ak.fbcdn.net.
+www.gpstc.org.
+casbygroup.com.
+www.estacionsanpedro.com.ar.
+salva-reyes.blogspot.com.
+download986.avast.com.
+78.147.46.189.in-addr.arpa.
+10.7.20.76.in-addr.arpa.
+ads2.contentabc.com.
+wow.hro.cl.
+en-us.fxfeeds.mozilla.com.
+mx1.koreazinc.co.kr.
+b.scorecardresearch.com.
+grenson.com.
+dns.msftncsi.com.
+plugin.maldi.tv.
+27.28.193.187.in-addr.arpa.
+ensigngeo.com.
+195.78.26.177.in-addr.arpa.
+charliebucket.com.au.
+rest-img.msg.yahoo.com.
+30.97.61.202.in-addr.arpa.
+mail2.newlife.co.za.
+www.xvideosredtube.com.
+marxists.org.
+ajax.googleapis.com.
+partner.googleadservices.com.
+193.103.174.189.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+tunebb.ru.
+sn3v015.colegium.com.
+mi.wikipedia.org.
+plusone.google.com.
+eguard2.bizoservices.com.
+s4.histats.com.
+a.root-servers.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+www.google.com.
+static.ak.fbcdn.net.
+www.universia.cl.
+www.linkedin.com.
+buttconstruction.com.
+smarturl.it.
+www.gpp-osijek.com.
+210.108.157.79.in-addr.arpa.
+neovortal.com.
+ic.tynt.com.
+www.facebook.com.
+i2.ytimg.com.
+email.wtsonline.com.
+150.197.85.186.in-addr.arpa.
+jy2opikcn.94sf.
+sn2files.storage.msn.com.
+40.116.102.201.in-addr.arpa.
+www.couponmole.com.
+www.ops.org.ni.
+yadtal.net.
+www.textsrv.com.
+whistlerfilmfestival.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+12.64.web1.im.weibo.com.
+brucelynton.com.
+194.17.251.189.in-addr.arpa.
+251.211.39.195.in-addr.arpa.
+pensionfuenflinden.de.
+people.directory.live.com.
+cyberguerre.blogspot.com.
+external.ak.fbcdn.net.
+mail.sxwtc.com.
+checkip.dyndns.org.
+232.33.254.190.in-addr.arpa.
+chat.extalia.net.
+mx.graycelltech.com.
+www.nitrodesign.com.
+th00.deviantart.net.
+.
+43.198.114.69.in-addr.arpa.
+159.243.125.96.in-addr.arpa.
+celebhairstyle.files.wordpress.com.
+blackstaramps.forumotion.com.
+www.mediawiki.org.
+graph.facebook.com.
+www.google.com.
+stereotown.com.
+s3.amazonaws.com.
+www.kga.neva.ru.
+www.connect.facebook.com.
+3.ns1631262.info.
+books.google.com.mx.
+111.218.226.190.in-addr.arpa.
+rss.emol.com.
+carrosyradios.galeon.com.
+33.153.174.190.in-addr.arpa.
+www.losnacionales.com.
+www.thevervoid.com.
+www.federacion-espa-airsoft.es.
+www.strategicsourceror.com.
+www.eepa.be.
+www.spiderboost.com.
+radiohead.mx.
+35.162.233.186.in-addr.arpa.
+google.com.
+2008webset5.net.
+softwareandscripts.com.
+www.goohle.com.
+local-bay.contacts.msn.com.
+i216.photobucket.com.
+checkip.dyndns.com.
+a1725.l.akamai.net.
+vp.sip.messenger.msn.com.
+zrp.spb.ru.
+blih.com.
+66.184.114.186.in-addr.arpa.
+41.186.178.190.in-addr.arpa.
+a.root-servers.net.
+cdn.pastemagazine.com.
+kontentservice.ru.
+imageharvest.net.
+mail.y-olastroy.ru.
+164.125.173.201.in-addr.arpa.
+signup.21sexturycash.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+evsecure-ocsp.verisign.com.
+a1001.w40.akamai.net.
+udc.msn.com.
+www.madrimasd.org.
+lewismarine.com.
+home.live.com.
+www.facebook.com.
+a.root-servers.net.
+armina.ru.
+newsitedesigns-com.mail.eo.outlook.com.
+blst.msn.com.
+smtp1.kt.co.kr.
+chatenabled.mail.google.com.
+ivanowo.ru.
+105.108.34.99.in-addr.arpa.
+cdn1.ticketsinventory.com.
+barracuda.townsendcapital.com.
+search.twitter.com.
+vp.sip.messenger.msn.com.
+developers.facebook.com.
+www.portalhomeopatico.com.ar.
+wcsh-com.mail.eo.outlook.com.
+productosdeperu.com.
+sso.samsung.com.
+innovationnewsdaily.com.
+profile.ak.fbcdn.net.
+cdn-0.nflximg.com.
+74.81.190.189.in-addr.arpa.
+relay.voice.messenger.msn.com.
+164.26.10.24.in-addr.arpa.
+content.dl-rms.com.
+apps.facebook.com.
+199.124.183.180.in-addr.arpa.
+bc.rentershotline.ca.
+29.170.78.186.in-addr.arpa.
+32.4.87.121.in-addr.arpa.
+mail4.landtag-bw.de.
+www.gstatic.com.
+www.happynights.org.
+photos-h.ak.fbcdn.net.
+unafotopordiabylorenus.blogspot.com.
+csi.gstatic.com.
+b-0.19-21006008.d071081.1518.19d4.3ea0.410.0.pesqeebfp881qkmpk4aw8nfsc5.avqs.mcafee.com.
+secure.logmein.com.
+teredo.ipv6.microsoft.com.
+a4.sphotos.ak.fbcdn.net.
+ecn.t0.tiles.virtualearth.net.
+sp.cwfservice.net.
+www.bluecoat.com.
+geo.messenger.services.live.com.
+royal-wolf.com.
+www.habitual.eng.br.
+www.yaleherald.com.
+www.abraham-hickslawofattraction.com.
+9.181.242.201.in-addr.arpa.
+a.root-servers.net.
+spamfilter.bodekandrhodes.com.
+cccpschmidt.de.
+videoalbumy.azet.sk.
+111.144.249.78.in-addr.arpa.
+227.11.179.163.in-addr.arpa.
+fp.vendaria.com.
+rad.msn.com.
+a.root-servers.net.
+studio-nsk.ru.
+130.224.34.177.in-addr.arpa.
+apix.iminent.com.
+photos-c.ak.fbcdn.net.
+www.electroindustria.com.
+profile.ak.fbcdn.net.
+4.bp.blogspot.com.
+www.innovacion.gob.cl.
+profile.ak.fbcdn.net.
+dsn5.d.skype.net.
+ksn7.kaspersky-labs.com.
+de.jigzone.com.
+wushu-school.ru.
+plus.google.com.
+associatedsubs-com.relay1b.spamh.com.
+sorosfiles.com.
+ws-cloud203-blur.svcmot.com.
+iswimemler.com.s9a2.psmtp.com.
+119.144.155.90.in-addr.arpa.
+static.ak.fbcdn.net.
+tnhpqj79c.97vi.
+a.root-servers.net.
+skymonk.net.
+www.wizard101.it.
+signatron.com.
+www.delish.com.
+ads.adbrite.com.
+gadgets.live.com.
+www.cousyaward.com.
+242.110.90.200.in-addr.arpa.
+29.101.120.200.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+cinematografia.cl.
+18.10.24.201.in-addr.arpa.
+botopolis.com.
+www.youtube.com.
+js.wlxrs.com.
+pixel.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+mhminc.com.inbound10.mxlogic.netet.
+resumenesdelibros.mlarac.cl.
+47.224.171.69.in-addr.arpa.
+ammlaw.com.inbound10.mxlogicmx.net.
+a.root-servers.net.
+209.103.220.189.in-addr.arpa.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+admin.brightcove.com.
+www.quemadres.com.
+secure.shared.live.com.
+photos-f.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+crl.microsoft.com.
+photos-f.ak.fbcdn.net.
+free.voyeur-eye.com.
+128.144.51.190.in-addr.arpa.
+47.122.88.2.in-addr.arpa.
+nokia-s40-11-cust.opera-mini.net.
+photos-b.ak.fbcdn.net.
+www.google.com.
+19.33.251.85.in-addr.arpa.
+bestbuycondo.com.
+mail.dersa.com.
+71.206.73.69.in-addr.arpa.
+dns.msftncsi.com.
+mail.google.com.
+ax.init.itunes.apple.com.
+safebrowsing-cache.google.com.
+49.147.223.201.in-addr.arpa.
+englewoodhospital.com.
+www.nationwide.com.
+kuzbass-veda.ru.
+autoupdate.igw.sdo.com.
+www.google.com.
+api.twitter.com.
+www.avantmusicnews.com.
+i240.photobucket.com.
+plus.google.com.
+platform.stumbleupon.com.
+mail.
+www.lakueva.com.
+falfn.com.
+btinfo.flashget.com.
+www.addthis.com.
+49.224.52.186.in-addr.arpa.
+hcibooks.com.
+213.187.138.190.in-addr.arpa.
+te-tronik.info.
+lcsitemain.symantec.com.
+mx2.ertelecom.ru.
+static.ak.fbcdn.net.
+my.occ.com.mx.
+a.root-servers.net.
+a.root-servers.net.
+i4.tagstat.com.
+fonts.googleapis.com.
+a.root-servers.net.
+unifi.
+www.mellowvirgins.com.
+s5.mangareader.net.
+www.sexolewebcams.com.
+53.34.112.213.in-addr.arpa.
+k1pfo727f.n43f5i5x.
+162.20.209.190.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+dsn3.d.skype.net.
+teredo.ipv6.microsoft.com.
+ib.adnxs.com.
+s-external.ak.fbcdn.net.
+a.root-servers.net.
+s.ytimg.com.
+dumasses.com.
+api.conduit.com.
+vrvybx4zt.60lq.
+0.pool.ntp.org.
+usbionline.com.s6b2.psmtp.com.
+api.geo.kontagent.net.
+155.116.30.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+mail.tathwell.com.
+hogalia.com.
+237.199.243.201.in-addr.arpa.
+graph.facebook.com.
+ocsp.verisign.com.
+www.jabbim.com.
+14.190.63.69.in-addr.arpa.
+248.203.138.200.in-addr.arpa.
+clients2.google.com.
+84.233.96.190.in-addr.arpa.
+lldinc.com.
+a639.da1.akamai.net.
+osmtpws01.airtechniques.com.
+search.4shared.com.
+www.politica21.org.
+49.172.220.190.in-addr.arpa.
+hosting-gratis.com.es.
+fs60.myvi.ru.
+www.examiner.com.
+michaelmillerfabrics.com.
+41.30.59.186.in-addr.arpa.
+static.ak.fbcdn.net.
+pixel.facebook.com.
+196.90.86.188.in-addr.arpa.
+uspowerinc.com.s7a2.psmtp.com.
+237.125.126.84.in-addr.arpa.
+89o:53in3.88bc.
+www.see-through-shirt.com.
+eyeos-miniserver.softonic.com.
+231.221.8.99.in-addr.arpa.
+divx.112.2o7.net.
+www.energyfirst.com.
+sites.google.com.
+distibutel.net.
+klinika-ran.ru.
+photos-f.ak.fbcdn.net.
+253.235.172.190.in-addr.arpa.
+www.facebook.com.
+clients1.google.com.
+therealtrends.com.
+api-read.facebook.com.
+ray.
+56.92.53.64.in-addr.arpa.
+ad.xtendmedia.com.
+photos-e.ak.fbcdn.net.
+www.mozilla.org.
+67.147.156.216.in-addr.arpa.
+mailbox3.tcfbank.com.
+160.217.110.186.in-addr.arpa.
+download.mapleeurope.com.
+azze.ru.
+nbcpolitics.msnbc.msn.com.
+www.hipotecas-bancos.com.
+d303resfoavrtt.cloudfront.net.
+www.despegar.com.ar.
+www.cancun-map.com.
+metalrelease.blogspot.com.
+wsfcsk12.nc.us.
+www.google-analytics.com.
+dingtao333.3322.org.
+56.71.134.189.in-addr.arpa.
+www.copiadoras-xerox.com.mx.
+creative.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+aidps.atdmt.com.
+sp.cwfservice.net.
+icm.ginyas.com.
+redsky.com.s8a2.psmtp.com.
+fu8j1dmn8.m11i0y0h.
+a1.sphotos.ak.fbcdn.net.
+accounts.google.com.
+zirconmusic.com.
+gs-loc.isg-apple.com.akadns.net.
+leventhal.com.
+81.118.93.109.in-addr.arpa.
+www.macromedia.com.
+freewaywebhost.com.multi.uribl.com.
+mail.ecanarys.com.
+a.root-servers.net.
+70.207.13.187.in-addr.arpa.
+jers3.info.
+a.root-servers.net.
+trupart.com.
+www.foot-locker.co.uk.
+lakeofweb.com.
+oneexwidow.blogspot.com.
+dreblen.com.
+c.static-cdn.playfish.com.
+tv.vilanoise.com.
+www.marinespecies.org.
+connect.facebook.net.
+www.banneradsthatpay.com.
+photos-f.ak.fbcdn.net.
+pandcwebmasters.com.
+s.ytimg.com.
+133.125.111.189.in-addr.arpa.
+ads2.msads.net.
+3.212.13.219.in-addr.arpa.
+151.192.57.62.in-addr.arpa.
+tracker.ccc.de.
+xm.corsendonk.com.
+www.google-analytics.com.
+plus.google.com.
+alphabetizer.flap.tv.
+78.150.49.178.in-addr.arpa.
+zeppelin.sasknet.sk.ca.
+82.69.226.168.in-addr.arpa.
+adfarm.mediaplex.com.
+www.netbrand.cl.
+i565.photobucket.com.
+br.wikipedia.org.
+mail.live.com.
+www.udenti.es.
+235.213.179.64.in-addr.arpa.
+yandalaw.com.
+highklass.ru.
+fancytuning.fancytuning.netdna-cdn.com.
+accessories.vancl.com.
+a7.sphotos.ak.fbcdn.net.
+folkhop.com.
+www.ieco.clarin.com.
+lorenzo.newfaceshere.info.
+tusvinilosdecorativosmx.blogspot.com.
+66.193.49.187.in-addr.arpa.
+netsacpe.net.
+ad.yieldmanager.com.
+www.rivtube.com.
+www.milliscent.com.
+ad.yieldmanager.com.
+developers.facebook.com.
+a.root-servers.net.
+alcam.com.
+b.scorecardresearch.com.
+0-238.channel.facebook.com.
+a.root-servers.net.
+116.185.167.190.in-addr.arpa.
+www.modern-war-generals.com.
+appworld.blackberry.com.
+queridobloc.blogspot.com.
+dce.unm.edu.
+newsrss.bbc.co.uk.
+a5.sphotos.ak.fbcdn.net.
+netflix336.pop1.la.nflximg.com.edgesuite.net.
+news.yahoo.com.
+28.131.229.190.in-addr.arpa.
+services.seagate.com.
+indiana-paw.com.
+products.wdc.com.
+a7.sphotos.ak.fbcdn.net.
+pubads.g.doubleclick.net.
+support.google.com.
+www.google.com.
+fr.webrep.avast.com.
+s.youtube.com.
+www.20minutos.es.
+utils.babylon.com.
+a.root-servers.net.
+mchxas:zj.u26q6o6x.
+224.37.83.24.in-addr.arpa.
+213.100.208.189.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+www.blogblog.com.
+249.165.194.210.in-addr.arpa.
+img.diynetwork.com.
+a8.sphotos.ak.fbcdn.net.
+app168341283206303.socialappspot.com.
+copt.ru.
+153.112.51.190.in-addr.arpa.
+a.root-servers.net.
+d2108831.xoom.it.
+.
+cityvillefb3.static.zgncdn.com.
+a1920.g.akamai.net.
+165.173.19.95.in-addr.arpa.
+static.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+84.92.172.189.in-addr.arpa.
+.
+91.20.80.201.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+www.facebook.com.
+www.hatsinthebelfry.com.
+mail.bit-torrent.ru.
+www.google.com.
+www.apple.com.
+dm-commerce.hr.
+www.flagline.com.
+profile.ak.fbcdn.net.
+mail1.bethanna.org.
+lgecorp.com.mail6.psmtp.com.
+a.root-servers.net.
+scribe.twitter.com.
+22.32.227.186.in-addr.arpa.
+webscouter.net.
+sites.google.com.
+a.root-servers.net.
+147.211.242.189.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+dns.msftncsi.com.
+142.24.179.88.in-addr.arpa.
+churchextension.org.inbound10.mxlogic.net.
+167.53.155.85.in-addr.arpa.
+gnomoncopy.com.
+ad.yieldmanager.com.
+c.live.com.
+233.135.35.189.in-addr.arpa.
+www.itsgonnahurt.com.
+www.youtube.com.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+s-static.ak.facebook.com.
+img.baofeng.net.
+check.sanasecurity.com.
+static.ak.fbcdn.net.
+_391_37_3.
+potrebitel.ru.
+www.cienciaysociedad.info.
+o.xbox.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+www.hydro-orchids.com.
+233.189.58.186.in-addr.arpa.
+226.25.253.190.in-addr.arpa.
+vietseas.com.
+elpozodejacob.tripod.com.
+account.live.com.
+102.xg4ken.com.
+144.105.239.89.in-addr.arpa.
+time.stdtime.gov.tw.
+accounts.google.com.
+ad.adnetwork.net.
+a4.sphotos.ak.fbcdn.net.
+165.235.169.58.in-addr.arpa.
+vpod.tv.
+a1.sphotos.ak.fbcdn.net.
+206.184.228.99.in-addr.arpa.
+133.74.188.189.in-addr.arpa.
+245.155.160.89.in-addr.arpa.
+armpoucohunde.mp.
+thumbs1.ebaystatic.com.
+www.imdb.com.
+78.233.108.76.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.ingdirect.com.au.
+178.16.168.189.in-addr.arpa.
+157.231.198.112.in-addr.arpa.
+partner.googleadservices.com.
+185.44.4.186.in-addr.arpa.
+avatar.xboxlive.com.
+www.facebook.com.
+arielarrieta.com.
+profile.ak.fbcdn.net.
+vast.bp3844834.btrll.com.
+gtanime-kai.foroactivo.com.
+www.youtube.com.
+miparroquia.fullblog.com.ar.
+.
+a.root-servers.net.
+rewardchannelcenter.com.
+external.ak.fbcdn.net.
+ar-ar.facebook.com.
+news.google.com.mx.
+bcbsla.com.
+50.11.158.82.in-addr.arpa.
+64.244.132.190.in-addr.arpa.
+www.youtube.com.
+feed190.photobucket.com.
+mybeautyloveaffair.blogspot.com.
+210.49.35.201.in-addr.arpa.
+s88lkzeqz.j64a3w4q.
+psp.ign.com.
+a6.sphotos.ak.fbcdn.net.
+118.94.92.201.in-addr.arpa.
+redirector.c.youtube.com.
+148.123.29.201.in-addr.arpa.
+www.visual28.com.
+photos-d.ak.fbcdn.net.
+49.140.209.190.in-addr.arpa.
+www.thebigprojectme.com.
+de-de.facebook.com.
+a1725.l.akamai.net.
+stats.ecb.europa.eu.
+photos-e.ak.fbcdn.net.
+www.alquranic.com.
+www.facebook.com.
+www.fotoefectos.com.
+profile.ak.fbcdn.net.
+topics.bo7.net.
+creative.ak.fbcdn.net.
+rcp.na.blackberry.com.
+www.ecoportal.net.
+www.betonsm.tk.
+www.google.com.
+photos-a.ak.fbcdn.net.
+www.bravoerotica.com.
+ssl.gstatic.com.
+api.facebook.com.
+a0.twimg.com.
+19.211.202.190.in-addr.arpa.
+www.goal-setting-for-success.com.
+www.mininova.org.
+us.rd.yahoo.com.
+cdn1.ads.contentabc.com.
+yahoo.com.
+ntp.glb.nist.gov.
+i2.ytimg.com.
+www.blogbigcock.blogspot.com.
+sa.bbc.com.
+profile.ak.fbcdn.net.
+edrmortgage.com.
+games.metaservices.microsoft.com.
+a6.sphotos.ak.fbcdn.net.
+8497.kz.all.biz.
+p04-caldav.icloud.com.
+somos.arkihome.netdna-cdn.com.
+thumbs4.ebaystatic.com.
+14.115.92.65.in-addr.arpa.
+h20397.www2.hp.com.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+postmaster.laguitare.com.
+232.50.132.190.in-addr.arpa.
+a.root-servers.net.
+www.youxakep.ru.
+twitter.com.
+m.tn.com.ar.
+37.140.51.190.in-addr.arpa.
+www.fi.bitefight.org.
+www.battlefieldsports.com.
+166.26.171.221.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+fedexkinos.com.
+thumbs1.ebaystatic.com.
+s59.chatango.com.
+teamsmi.com.
+a.root-servers.net.
+www.theanalogdept.com.
+icanhascheezburger.com.
+247.15.0.192.in-addr.arpa.
+seaoleena.bandcamp.com.
+muchosmisterios.blogspot.com.
+www.justsimple.com.au.
+www.monochrome-heaven.com.
+torrentspy.com.
+static.ak.facebook.com.
+www.google.com.
+bay.messenger.services.live.com.
+75.70.102.200.in-addr.arpa.
+163.238.198.77.in-addr.arpa.
+a.root-servers.net.
+www.espacioebook.com.
+100.1.168.192.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+oka-auto.ru.
+carlosalvatelli.ru.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+bs.serving-sys.com.
+dr._dns-sd._udp.0.33.168.192.in-addr.arpa.
+cdn.api.twitter.com.
+getprof.gb.np.community.playstation.net.
+a.root-servers.net.
+subaru-tlt.ru.
+67.76.159.99.in-addr.arpa.
+pix.search.iminent.com.
+edconma.macintotheredi.museum.
+www.google.com.
+ryapps-a.akamaihd.net.
+www.empleo.gob.mx.
+external.ak.fbcdn.net.
+cornosul.blogspot.com.
+gmail.com.
+twitter-widgets.s3.amazonaws.com.
+www.deviajeabrasil.com.
+bin-short.whatsapp.net.
+websms.orange.es.
+www.google-analytics.com.
+101.62.217.196.in-addr.arpa.
+www.playfirst.com.
+whos.amung.us.
+laptopsgadgets.com.
+www.betamarket.info.
+safebrowsing-cache.google.com.
+171.173.168.192.in-addr.arpa.
+a.root-servers.net.
+a1.v.phobos.apple.com.
+www.monster.at.
+s0.2mdn.net.
+ax.init.itunes.apple.com.
+jajajajawww.facebook.com.
+172.53.44.24.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+narutofriends.foro-argentina.net.
+photos-a.ak.fbcdn.net.
+sac.gti.mcafee.com.
+47.191.78.84.in-addr.arpa.
+nb8tl9z:1.38lr.
+teledeporteonline12.chatango.com.
+www.keek.com.
+static.avast.com.
+72.26.247.83.in-addr.arpa.
+175.211.118.93.in-addr.arpa.
+r.66.ru.
+ns.gov.gu.
+cleavelandbrowns.com.
+pref.email.wetv.com.
+ad.adserve.com.
+www.care-bears.com.
+197.80.149.187.in-addr.arpa.
+231.175.55.190.in-addr.arpa.
+mk-mx-4.b2b.tiscali.co.uk.
+www.google.com.
+tracker.tjgame.enorth.com.cn.
+coffeeandwine.com.
+www.freelivejasmincams.com.
+ebadalrhman.yoo7.com.
+www.feet-sniffing.com.
+horaceroweb.disqus.com.
+elit36.ru.
+i2.ytimg.com.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+teredo.ipv6.microsoft.com.
+aaa-calif.com.
+proofpoint1.dordcs.org.
+a8.sphotos.ak.fbcdn.net.
+hpcs.bvsalud.org.
+b-0.19-2300a008.11481.1518.19d3.3ea1.410.0.hukp6abflsusuhjnckn31hgnlj.avqs.mcafee.com.
+dencinconsulting.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+a1404.w41.akamai.net.
+www.facebook.com.
+dns.msftncsi.com.
+profile.ak.fbcdn.net.
+drivingclub.com.
+besthairstyles.tk.
+www.davidpaulmorris.com.
+54.133.145.120.in-addr.arpa.
+profile.ak.fbcdn.net.
+csi.gstatic.com.
+googleads.g.doubleclick.net.
+b.scorecardresearch.com.
+t3.gstatic.com.
+220.172.190.186.in-addr.arpa.
+widgets.amung.us.
+cma-italia.com.
+versatel.de.
+145.175.167.118.in-addr.arpa.
+www.poolred.com.
+undiesaddiction.tumblr.com.
+a.root-servers.net.
+e4733.b.akamaiedge.net.
+smtp.conamex.com.
+a.root-servers.net.
+45.110.183.114.in-addr.arpa.
+16.64.238.80.in-addr.arpa.
+a.root-servers.net.
+creative.ak.fbcdn.net.
+40.234.225.77.in-addr.arpa.
+p01-bookmarks.icloud.com.
+42.47.164.187.in-addr.arpa.
+a787.phobos.apple.com.
+apps.facebook.com.
+58.131.91.186.in-addr.arpa.
+109.119.75.65.in-addr.arpa.
+mail.vmje.com.
+7.251.158.187.in-addr.arpa.
+t.co.
+profile.ak.fbcdn.net.
+modeminksigns.com.
+rew.no-ip.info.
+pbid.iforex.com.
+f806.mail.yahoo.com.
+scribe.twitter.com.
+157.81.240.189.in-addr.arpa.
+tetraprint.ru.
+ocsp.godaddy.com.
+phone.com.
+s-static.ak.facebook.com.
+14.52.101.187.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+store3.up-00.com.
+www.wholesaleclothing4u.com.
+www.nlm.nih.gov.
+ad-g.doubleclick.net.
+122.28.167.190.in-addr.arpa.
+a.root-servers.net.
+br.answers.yahoo.com.
+t1.gstatic.com.
+ja-jp.facebook.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+images.apple.com.
+montreal.olx.ca.
+textilescachicadan.blogspot.com.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+146.36.205.190.in-addr.arpa.
+no.nonsense.ee.
+www.web-ideas.com.au.
+220.255.81.186.in-addr.arpa.
+www-valusoft-com.wip.digitalrivercontent.net.
+190.189.112.186.in-addr.arpa.
+228.102.19.189.in-addr.arpa.
+a.root-servers.net.
+118.128.241.201.in-addr.arpa.
+i3.ytimg.com.
+news.ottoversand.at.
+secure.wlxrs.com.
+dns.msftncsi.com.
+olgatanon.com.
+38.116.143.189.in-addr.arpa.
+l.yimg.com.
+4124234.frasesinolvidables1.com.ar.
+lugaresquever.tumblr.com.
+api-read.facebook.com.
+twimg0-a.akamaihd.net.
+km-brown.com.
+row.bc.yahoo.com.
+jjue268rp.52nb.
+mail.swot-analysis.ru.
+us.jobomas.com.
+a.root-servers.net.
+a.root-servers.net.
+promonegocios.net.
+a5.sphotos.ak.fbcdn.net.
+tms30.icrc.trendmicro.com.
+static.ak.fbcdn.net.
+zgn.static.zynga.com.
+luvthatdrtywata.livejournal.com.
+photos-f.ak.fbcdn.net.
+237.173.170.201.in-addr.arpa.
+a323.yahoofs.com.
+_631_53_3.
+fast-autos.net.
+0-jg-w.channel.facebook.com.
+aidps.atdmt.com.
+doha.oilfield.slb.com.
+putnam.com.s7b2.psmtp.com.
+billing.sharo4ka.ru.
+www.facebook.com.
+illiweb.com.
+bbs.chinasiemens.com.
+www.facebook.com.
+finance.yahoo.com.
+157.247.85.24.in-addr.arpa.
+ikm.com.ua.
+yahoo.com.
+www.google.co.id.
+hugheslandscaping.com.
+d2091827.xoom.it.
+184.206.180.68.in-addr.arpa.
+iwl.com.
+www.mozilla.com.
+www.sems.gob.mx.
+profile.ak.fbcdn.net.
+103.44.135.66.in-addr.arpa.
+en.1000mikes.com.
+apple-mobile.query.yahooapis.com.
+ib.adnxs.com.
+icons.iconator.com.
+zynga2-a.akamaihd.net.
+aol.com.
+a.root-servers.net.
+a1090.v.phobos.apple.com.
+www.msftncsi.com.
+220.198.121.200.in-addr.arpa.
+latam.preciomania.com.
+req.appads.com.
+api.twitter.com.
+rosich-logistic.ru.
+a.root-servers.net.
+93.202.173.190.in-addr.arpa.
+us.mg6.mail.yahoo.com.
+crl.microsoft.com.
+andrescanavesi.com.uy.
+canyouplaypes.com.
+images01.spacash.com.
+safebrowsing.clients.google.com.
+116.208.24.81.in-addr.arpa.
+isss.gob.sv.
+imap.gmail.com.
+clients1.google.com.
+nestag.com.
+wheatdesign.com.
+sunct2.jinr.ru.
+profiles.google.com.
+a6.sphotos.ak.fbcdn.net.
+_319_42_3.
+www.clarin.com.
+www.google-analytics.com.
+www.youngandbusty.net.
+static.ak.fbcdn.net.
+244.37.112.186.in-addr.arpa.
+corbettharper.com.
+ar-ar.facebook.com.
+0-317.channel.facebook.com.
+a.root-servers.net.
+pixel.facebook.com.
+a.root-servers.net.
+platform.ak.fbcdn.net.
+clients-cctld.l.google.com.
+accountservices.passport.net.
+input2.comment.qq.com.
+mx.2niteline.com.
+api-public.addthis.com.
+www.achtzehn99.de.
+ict.tgw.com.
+_ldap._tcp.
+_207_75_1.
+bubba.ntrade.it.
+stealth.y9.vc.
+www.nyhotties.com.
+groups.google.com.ua.
+97.34.252.189.in-addr.arpa.
+inbound.ranatech.com.netsolmail.net.
+24.193.0.181.in-addr.arpa.
+107.137.69.190.in-addr.arpa.
+gfx3.hotmail.com.
+m.motortrend.com.
+webcache.googleusercontent.com.
+www.usgs.gov.
+miscancionesinfantiles.disqus.com.
+images.empora.com.
+es-la.facebook.com.
+engine.demo.medialand.ru.
+external.ak.fbcdn.net.
+www.google.com.
+www.benalmadena.es.
+49.78.173.201.in-addr.arpa.
+38.176.120.200.in-addr.arpa.
+www.avis.co.uk.
+clients1.google.com.
+static.ak.facebook.com.
+www.king-bearings.com.
+mail2.eplushealthcare.com.
+dem0003.in.
+www.facebook.com.
+smart-journal.ru.
+www.facebook.com.
+mysp.ac.
+xr562c2a9.k17m6d2t.
+a5.sphotos.ak.fbcdn.net.
+243.139.1.46.in-addr.arpa.
+19.43.112.99.in-addr.arpa.
+accounts.google.com.
+130.172.185.58.in-addr.arpa.
+yahoo.com.
+google.com.
+0-ji-w.channel.facebook.com.
+static2.bitacoras.com.
+img.huanleguang.com.
+a.root-servers.net.
+photos-e.ak.fbcdn.net.
+developers.facebook.com.
+106.98.93.186.in-addr.arpa.
+222.211.152.201.in-addr.arpa.
+sites.google.com.
+a.root-servers.net.
+sp.cwfservice.net.
+validator.w3.org.
+52.197.28.181.in-addr.arpa.
+www.descargarmanuales.com.ar.
+de-de.facebook.com.
+7.106.180.69.in-addr.arpa.
+titanium30-en.url.trendmicro.com.
+www.facebook.com.
+transmotion.pt.
+www.cmu.org.mx.
+251.107.104.187.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+152.47.254.201.in-addr.arpa.
+www.internetzona.pl.
+239.203.132.189.in-addr.arpa.
+nappyboyonline.com.
+tc.v20.cache3.c.youtube.com.
+mail.surferie.net.
+118.174.109.186.in-addr.arpa.
+www.jewelryshop.bz.
+a.root-servers.net.
+cust4181-3.in.mailcontrol.com.
+whiskeyandgunpowder.com.
+teredo.ipv6.microsoft.com.
+relay3.geoksc.apatity.ru.
+arandomurl.com.
+29.193.171.124.in-addr.arpa.
+cm.ar.taringa.overture.com.
+13.152.168.192.in-addr.arpa.
+hit.trafficholder.com.
+googleads.g.doubleclick.net.
+download2.nexon.net.
+www.googleadservices.com.
+nxcache.nexon.net.
+yahoo.com.
+a3.sphotos.ak.fbcdn.net.
+dc.logmein-gateway.com.
+a.root-servers.net.
+flazm.disqus.com.
+122.178.153.189.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+145.1.189.190.in-addr.arpa.
+acicapital.com.s8b2.psmtp.com.
+a1416.g.akamai.net.
+a.root-servers.net.
+static.socialvi.be.
+prod2.rest-core.msg.yahoo.com.
+a7.sphotos.ak.fbcdn.net.
+dlactn.org.
+welcometointernet.org.
+content.yieldmanager.edgesuite.net.
+ewingl.com.
+client-software.real.com.
+123.4.87.66.in-addr.arpa.
+www.googleadservices.com.
+s-static.ak.fbcdn.net.
+eusdwsmail010.logistics.corp.
+apps.facebook.com.
+104.62.162.109.in-addr.arpa.
+188.186.10.186.in-addr.arpa.
+aol.com.
+_656_10_5.
+120.14.160.187.in-addr.arpa.
+164.117.52.186.in-addr.arpa.
+meizen40.net.
+www.wip4.adobe.com.
+hddiziizle.net.
+www.congresoahila2011.com.
+s.ytimg.com.
+media.admob.com.
+srx.main.ebayrtm.com.
+safebrowsing-cache.google.com.
+xheli.com.
+www.google-analytics.com.
+81.172.131.189.in-addr.arpa.
+consults.ru.
+a.root-servers.net.
+www.drbrandtskincare.com.
+112.77.203.87.in-addr.arpa.
+226.164.160.187.in-addr.arpa.
+wdbj7.com.
+fbcdn-profile-a.akamaihd.net.
+www.sina.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+att.net.
+www.androiddownloadnow.com.
+16.88.73.77.in-addr.arpa.
+_857_76_7.
+www.theworldrecipebook.com.
+www.docs.sony.com.
+images-71.har.com.
+intelliswitch.net.
+www.mdsone.com.
+tinyurl.com.
+n4403ad.doubleclick.net.
+photos-f.ak.fbcdn.net.
+dns.msftncsi.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.anxer.net.
+ucom.net.
+250.255.114.200.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+143.201.141.201.in-addr.arpa.
+aol.com.
+www.google-analytics.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+hdl.loc.gov.
+h.live.com.
+162.163.243.201.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+152.0.32.189.in-addr.arpa.
+:fqf33dir.62ez.
+www.rankspirit.com.
+21m86g2s8.65cj.
+algebra-net.programas-gratis.net.
+a.root-servers.net.
+gfx4.hotmail.com.
+csi.gstatic.com.
+a.adcloud.net.
+0-244.channel.facebook.com.
+www.ridiculopathy.com.
+www.google.cpm.
+www.administradores-empresas.com.
+resolver5.pand.ctmail.com.
+youtube-ui.l.google.com.
+60.242.243.189.in-addr.arpa.
+time.chttl.com.tw.
+flatironcorp.com.inbound10.mxlogicmx.net.
+ar-ar.facebook.com.
+245.138.188.76.in-addr.arpa.
+184.77.136.190.in-addr.arpa.
+thumbs1.ebaystatic.com.
+dte.sellpoint.net.
+creative.ak.fbcdn.net.
+31.102.104.189.in-addr.arpa.
+tobolsk.info.
+ntp1.cs.wisc.edu.
+147.209.177.79.in-addr.arpa.
+mail.gb.avtograd.ru.
+awjarcitects.com.
+hi-in.facebook.com.
+twimg0-a.akamaihd.net.
+photos-h.ak.fbcdn.net.
+google.com.
+.
+i4.ytimg.com.
+bottleofjack.tumblr.com.
+i1.ytimg.com.
+137.29.31.190.in-addr.arpa.
+sn1msg2020222.gateway.messenger.live.com.
+eskimovie.com.
+www.facebook.com.
+profile.ak.fbcdn.net.
+www.culturalivre.net.
+amazonm-722.vo.llnwd.net.
+content.yieldmanager.edgesuite.net.
+127.198.30.186.in-addr.arpa.
+98.59.50.201.in-addr.arpa.
+197.240.21.190.in-addr.arpa.
+www.xbox360.com.
+www.cochilco.cl.
+platform.ak.fbcdn.net.
+secure.wlxrs.com.
+service6.pricegong.com.
+a1108.da1.akamai.net.
+s.ytimg.com.
+www.cpmr.org.
+service.ess.apple.com.
+www.digitalscores.us.
+175.219.138.189.in-addr.arpa.
+16.96.98.189.in-addr.arpa.
+126.189.237.190.in-addr.arpa.
+joystiq.search.aol.com.
+131.37.183.189.in-addr.arpa.
+imagenes.es.sftcdn.net.
+beacon.lijit.com.
+www.conapo.gob.mx.
+img.rincondelvago.com.
+www.consultas.curp.gob.mx.
+163.39.199.190.in-addr.arpa.
+www.google-analytics.com.
+pagead2.googlesyndication.com.
+baymsg1030121.gateway.messenger.live.com.
+ruscrete.co.uk.
+urethanesupply.com.s8b2.psmtp.com.
+128.26.45.187.in-addr.arpa.
+i182.photobucket.com.
+dogs2.ngmoco.com.
+218.210.67.94.in-addr.arpa.
+www.google-analytics.com.
+dnl-ru5.kaspersky-labs.com.
+90.73.213.74.in-addr.arpa.
+mail.masstop.com.
+www.facebook.com.
+plusone.google.com.
+creative.ak.fbcdn.net.
+sites.google.com.
+116.96.90.195.in-addr.arpa.
+fm.ru.
+leaelliott.com.s6b2.psmtp.com.
+accounts.google.com.
+www.fotosdesexo.org.es.
+teredo.ipv6.microsoft.com.
+ggames.com.br.
+70.103.34.189.in-addr.arpa.
+www2.sherwin-williams.com.
+a749.g.akamai.net.
+afasic.org.uk.
+170.134.246.85.in-addr.arpa.
+s0002113.ecdomain.net.
+accounts.google.com.
+photos-c.ak.fbcdn.net.
+www.cubatravelusa.com.
+london.langhamhotels.co.uk.
+tracker.ydy.com.
+fonts.googleapis.com.
+56.172.114.177.in-addr.arpa.
+www.ma-recreation.com.
+lengthenyourstride.com.
+voipa.sip.yahoo.com.
+mercury.stdominic.net.
+a.root-servers.net.
+www.blackberry.com.
+wakeboard.es.
+112.239.171.189.in-addr.arpa.
+fitnessysalud.blogspot.com.
+www.webgradnja.hr.
+www.lifehealthcare.co.za.
+profile.ak.fbcdn.net.
+pix:t1kbx.75nr.
+218.176.2.88.in-addr.arpa.
+thepregnantnudes.com.
+ad.xtendmedia.com.
+emailnotifier.services.conduit.com.
+ksn2-12.kaspersky-labs.com.
+carbsense.com.
+251.134.10.221.in-addr.arpa.
+news.google.es.
+assets.rubiconproject.com.
+247.117.201.74.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.google.com.
+i163.photobucket.com.
+209.104.223.87.in-addr.arpa.
+a.root-servers.net.
+i.w.inmobi.com.
+widgets.twimg.com.
+toolbar.live.com.
+fbcdn-photos-a.akamaihd.net.
+9gag.com.
+static.ak.fbcdn.net.
+146.57.126.187.in-addr.arpa.
+media.sas.upenn.edu.
+mx2.jetisi.com.
+www.marketingdebusca.com.br.
+216.54.38.187.in-addr.arpa.
+mplguam.com.
+www.redfugios.org.
+a1001.w40.akamai.net.
+a.root-servers.net.
+video.l3.fbcdn.net.
+50.2.255.220.in-addr.arpa.
+golfthelinks.com.
+107.164.86.69.in-addr.arpa.
+wegroup.ru.
+uk.mcafee.com.
+a.root-servers.net.
+a.root-servers.net.
+cs9306.vk.com.
+rcp.na.blackberry.com.
+.
+_ldap._tcp.pdc._msdcs.neoris.cxnetworks.net.
+51.189.251.76.in-addr.arpa.
+6.86.139.216.in-addr.arpa.
+ad.z5x.net.
+25.181.248.89.in-addr.arpa.
+110.253.10.200.in-addr.arpa.
+f.snagfilms.com.
+view.atdmt.com.
+h4f5mx4zk.s03u3n2a.
+105.70.41.187.in-addr.arpa.
+www.theshangri-las.com.
+es-la.facebook.com.
+www.embrujo.net.
+smtp.dumonds.com.
+profile.ak.fbcdn.net.
+112.150.11.76.in-addr.arpa.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+us.bc.yahoo.com.
+cs1926.vk.com.
+smtp.webcravings.com.
+static.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+wickedthemusical.com.sg.
+a7.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.microsoft.com.
+ntp1.dlink.com.
+bial.pl.
+yahoo.com.
+34.1.157.201.in-addr.arpa.
+www.kronosgo.com.
+251.72.85.86.in-addr.arpa.
+www.google.com.
+appsforbb.com.
+chaminade.edu.
+109.189.132.41.in-addr.arpa.
+www.google.com.
+39.32.48.190.in-addr.arpa.
+www.bricolageymanualidades.com.
+34-courier.push.apple.com.
+.
+a2.sphotos.ak.fbcdn.net.
+0-299.channel.facebook.com.
+a.root-servers.net.
+go.microsoft.com.
+www.usa.gov.
+content.yieldmanager.edgesuite.net.
+17.8.137.2.in-addr.arpa.
+52.169.16.87.in-addr.arpa.
+gfx2.hotmail.com.
+c5a.ah.yahoo.com.
+p02-ubiquityws.icloud.com.
+mail.live.com.
+sn102w.snt102.mail.live.com.
+matcher-cwb.bidder7.mookie1.com.
+218.152.130.189.in-addr.arpa.
+geo.messenger.services.live.com.
+a1505.l.akamai.net.
+gt.eredan.com.
+fr-fr.facebook.com.
+www.energiainterior.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+sm-beta.ovi.messaging.nokia.com.
+external.ak.fbcdn.net.
+api-read.facebook.com.
+hub-odc.samsungapps.com.
+mail.jetmotors.perm.ru.
+voipb.sip.yahoo.com.
+22.133.10.186.in-addr.arpa.
+js.blinkadr.com.
+www.denobisipsis.es.
+schnaapklicks.com.
+www-google-analytics.l.google.com.
+169.87.231.190.in-addr.arpa.
+pubads.g.doubleclick.net.
+www.facebook.com.
+n-link.com.
+170.56.246.201.in-addr.arpa.
+209.170.137.187.in-addr.arpa.
+fxfeeds.mozilla.com.
+158.3.76.70.in-addr.arpa.
+download.live.com.
+pts.lockerz.com.
+75.183.98.62.in-addr.arpa.
+41.126.81.216.in-addr.arpa.
+q6pesnyqz.50lc.
+mediastreet.ca.s7a2.psmtp.com.
+nds.wiktionary.org.
+svrsecure-g2-aia.verisign.com.
+a.root-servers.net.
+tracker.thepiratebay.org.
+dns.msftncsi.com.
+www.crautonoma.gov.co.
+128.7.6.186.in-addr.arpa.
+kalininrad.ru.
+hccsmg.com.
+v529.vkadre.ru.
+report.cedexis.com.
+platform.twitter.com.
+actionrealtyks.com.
+suggestqueries.google.com.
+blog.outsystems.com.
+gameofthrones.wikia.com.
+dutchschulze.com.
+api.twitter.com.
+datinggold.com.s10b1.psmtp.com.
+www.mspca.org.
+random.frivolity.info.
+www.hotmail.com.
+8l1vqiyzr.s33b9p9z.
+tracker.openbittorrent.com.
+www.facebook.com.
+www.radioradar.net.
+la.dynonobel.com.
+solarus.biz.
+nada5.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+mhatoday.org.
+compaq.mbservice.pp.ru.
+a-0.19-330f3081.9110081.1518.19d3.2f1c.10.0.5wauzj8kclu1up9r1vmvdufkaj.avqs.mcafee.com.
+elstatic.weborama.fr.
+33.176.49.216.in-addr.arpa.
+biosantepharma.com.2.0001.arsmtp.com.
+fr-fr.facebook.com.
+105.1.168.192.in-addr.arpa.
+mowt.gov.tt.
+www.jetcero.com.
+ambience.com.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+download.www.arte.tv.
+cs4484.vk.com.
+bmj-logistics.ru.
+itf-ost.ru.
+wallpapers.desicomments.com.
+www.cmtpetconferences.com.
+www.radio.com.pl.
+itunes.apple.com.
+a.root-servers.net.
+206.109.136.78.in-addr.arpa.
+247.178.255.201.in-addr.arpa.
+becmfg.com.
+124.147.136.190.in-addr.arpa.
+a.root-servers.net.
+www.gstatic.com.
+tumblon.com.
+1.bp.blogspot.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+rmd.atdmt.com.
+photos-e.ak.fbcdn.net.
+ad.yieldads.com.
+www.galeriaseroticas.xpg.com.br.
+ad.yieldmanager.com.
+usiko.ru.
+bs.serving-sys.com.
+mail3.sisk.ie.
+www.macauhotel.org.
+dns.msftncsi.com.
+s-static.ak.fbcdn.net.
+smtp.ci.lenexa.ks.us.
+239.58.31.190.in-addr.arpa.
+65.217.37.62.in-addr.arpa.
+www.liujo.it.
+s1-excel.vo.msecnd.net.
+villaluro.olx.com.ar.
+www.transexualesfollando.org.
+agmkoq.com.
+medlinia.ru.
+www.facebook.com.
+www.belajarkonseling.com.
+csi.gstatic.com.
+mypisamba4.com.
+a.root-servers.net.
+connect.facebook.net.
+231.39.176.186.in-addr.arpa.
+167.153.155.189.in-addr.arpa.
+a.root-servers.net.
+205.252.113.186.in-addr.arpa.
+docs.google.com.
+androcode.es.
+a1.sphotos.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+velikanrostov.ru.
+pixel.rubiconproject.com.
+thomcoins.com.
+leaderit.ru.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+i2.ytimg.com.
+ad.yieldmanager.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+i3.ytimg.com.
+chivaselmejorequipodemexico.blogspot.com.
+translate.googleapis.com.
+equico.net.
+time.stdtime.gov.tw.
+residentialsearch.savills.co.uk.
+42.31.207.112.in-addr.arpa.
+54.49.59.189.in-addr.arpa.
+www.famemonsters.com.
+fromdoppler.com.rbl2.mcafee.com.
+services.leapfrog.com.
+64.38.14.186.in-addr.arpa.
+www.ademails.com.
+s-static.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+lovefilm.dl.playstation.net.
+77.93.106.200.in-addr.arpa.
+external.ak.fbcdn.net.
+melapuedencerrar.com.
+landing.ancestry.co.uk.
+72.105.22.186.in-addr.arpa.
+53.80.7.69.in-addr.arpa.
+a.root-servers.net.
+71.183.64.181.in-addr.arpa.
+mail.google.com.
+rp.rusal.ru.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+s.clicktale.net.
+hotmaiwww.facebook.com.
+35.126.150.114.in-addr.arpa.
+divulgalia.blogspot.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+www.inbox.com.
+a.root-servers.net.
+150.53.31.173.in-addr.arpa.
+browsersync.google.com.
+translate.google.com.
+toolbarqueries.google.com.mx.
+es.kioskea.net.
+197.72.51.201.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+30.229.171.69.in-addr.arpa.
+www.puertasabiertas.org.
+dlm.com.
+dr._dns-sd._udp.0.179.16.172.in-addr.arpa.
+i1.ytimg.com.
+aol.rr.com.
+www.clasimexico.com.
+www.fundacionsantillana.org.co.
+www.kittierocks.com.
+rihdntv1p.67rg.
+opensuse-community.org.
+yui.yahooapis.com.
+cbp-us.nccp.netflix.com.
+203.123.154.95.in-addr.arpa.
+a.root-servers.net.
+mx.psport.ru.
+scholar.google.com.ar.
+server.kan.nnov.ru.
+xml.pricegong.com.
+utils.babylon.com.
+www.learning4good.net.
+42.36.20.190.in-addr.arpa.
+www.tarjetasbubba.com.
+a3.sphotos.ak.fbcdn.net.
+www.facebook.com.
+kyx2m6jkm.45dg.
+a.root-servers.net.
+x-journal.net.
+abierto-hasta-el-amanecer-2-texas-blood-money.peliculon.tv.
+www.google.com.
+150.90.190.41.in-addr.arpa.
+fonts.foxsports.com.
+182.162.93.186.in-addr.arpa.
+ad.yieldmanager.com.
+a.root-servers.net.
+dns.msftncsi.com.
+dewater.com.inbound15.mxlogicmx.net.
+www.djonty.com.ar.
+shydude.deviantart.com.
+www.cellreception.com.
+.
+d2089652.xoom.it.
+sensorprod.com.
+dlvr.it.
+a6.sphotos.ak.fbcdn.net.
+accounts.google.com.
+145.162.4.46.in-addr.arpa.
+soic.us.
+200.101.40.84.in-addr.arpa.
+burton-homes.com.
+gateway.messenger.hotmail.com.
+gtaonline.com.ar.
+photos-d.ak.fbcdn.net.
+102.193.23.186.in-addr.arpa.
+img.youtube.com.
+126.162.226.186.in-addr.arpa.
+_072_67_4.
+static.ak.fbcdn.net.
+www.facebook.com.
+api.facebook.com.
+poorva.com.
+galleries.hdhardcore.com.
+aaa.com.au.
+adval.com.
+smartphone-gprs-traffic-monitor.softonic.com.
+mobile.login.yahoo.com.
+234.83.198.112.in-addr.arpa.
+s-static.ak.fbcdn.net.
+aservise.ru.
+a8.sphotos.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+mail.jump-out.dk.
+asprotech.blogspot.com.
+chilesintransgenicos.cl.
+a.root-servers.net.
+www.wikimail.org.
+mail.google.com.
+www.facebook.com.
+48.116.239.216.in-addr.arpa.
+36.142.211.201.in-addr.arpa.
+cdn-static.liverail.com.
+adsx.greystripe.com.
+136.6.94.186.in-addr.arpa.
+usersystem783aa.ru.
+a5.sphotos.ak.fbcdn.net.
+6.183.247.88.in-addr.arpa.
+mtalk.google.com.
+external.ak.fbcdn.net.
+i1.ytimg.com.
+dns.msftncsi.com.
+accounts.google.com.
+googleads.g.doubleclick.net.
+219.49.184.190.in-addr.arpa.
+apis.google.com.
+www.thehabibshow.com.
+monduce.com.
+pagead2.googlesyndication.com.
+www.somewrinkles.blogspot.com.
+developers.facebook.com.
+sites.google.com.
+sadinsa.com.
+newsrss.bbc.co.uk.
+100.69.35.83.in-addr.arpa.
+194.48.101.118.in-addr.arpa.
+autohubasia.com.
+billing.sharo4ka.ru.
+www.verwandt.de.
+147.145.51.201.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+b._dns-sd._udp.lan.
+vereltrailersdelapelicula.blogspot.com.
+illinoisfamily.org.
+s-static.ak.fbcdn.net.
+www.the-best-web-hosting-service.com.
+login.live.com.
+www.bbm.com.
+it-it.facebook.com.
+www.sptfm.ro.
+mx2.inertiainteractive.net.
+s.ytimg.com.
+redirector.c.youtube.com.
+ads.bluelithium.com.
+a8.sphotos.ak.fbcdn.net.
+commercebankmn.com.s8b2.psmtp.com.
+alcgs34ma.20oh.
+www.foto.technetium.be.
+db11.spamcatcher.net.
+www.yanmar.com.
+6.79.170.189.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+mx.youtube.com.
+yui.yahooapis.com.
+a.root-servers.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+client.akamai.com.
+si0.twimg.com.
+badoo.com.
+too-drunk-to-dream.tumblr.com.
+andovercollege.com.
+www.europa-lkw.de.
+169.133.205.186.in-addr.arpa.
+www.capecentralhigh.com.
+hg3.ceryxefw.com.
+mail.thunda.com.
+safebrowsing-cache.google.com.
+bit.ly.
+flounderart.com.
+evsecure-crl.verisign.com.
+mx.naruto-ll.com.
+a4.sphotos.ak.fbcdn.net.
+svaepro.weebly.com.
+photos-d.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+thefusebox.com.s200b2.psmtp.com.
+s0.2mdn.net.
+31.246.48.186.in-addr.arpa.
+www.richandbrainless.com.
+cs504605.vk.com.
+a8.sphotos.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+28.252.16.177.in-addr.arpa.
+www.facebook.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+167.239.141.201.in-addr.arpa.
+orig-10002.productmadness.cotcdn.net.
+a6.sphotos.ak.fbcdn.net.
+beta.stun.voice.yahoo.com.
+aol.com.
+api.looklater.com.
+safemoods.com.
+connect.facebook.net.
+entretenimiento.prodigy.msn.com.
+www.legalmovz.info.
+mustin.com.inbound15.mxlogicmx.net.
+www.mtit.com.
+www.facebook.com.
+pagead2.googlesyndication.com.
+www.youtube.com.
+download.windowsupdate.com.
+2.51.214.189.in-addr.arpa.
+v8.secure.nfstr.ea.com.
+www.youtube.com.
+157.0.103.71.in-addr.arpa.
+mailin-01.netatlantic.com.
+a6.sphotos.ak.fbcdn.net.
+110.69.231.190.in-addr.arpa.
+texarkanagastroenterology.com.
+static.app.widdit.com.
+_592_84_1.
+alsmithtrucking.com.
+zoom.co.uk.home.
+d2092102.xoom.it.
+www.discoveryindochina.com.
+api-read.facebook.com.
+secure.easycgi.com.
+51.235.178.190.in-addr.arpa.
+www.dic.org.ar.
+members.ebonymax.com.
+oliver-tour.ru.
+nero-move-it.programas-gratis.net.
+missrowlandgifs.tumblr.com.
+www.facebook.com.
+api.twitter.com.
+s.youtube.com.
+www.facebook.com.
+a-0.19-2309d081.99a0083.1518.19cf.3ea1.410.0.6eka98rdd5n7fllv2bglmpqiti.avqs.mcafee.com.
+1.bp.blogspot.com.
+www-hotmail-com.com.
+proyectodeartecasiopea.blogspot.com.
+binladen.ru.
+112.135.14.181.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+config.messenger.msn.com.
+a1.sphotos.ak.fbcdn.net.
+essen.vol.at.
+151.146.220.121.in-addr.arpa.
+sadownload.mcafee.com.
+207.60.70.208.in-addr.arpa.
+jamn945.com.
+blogs.elpais.com.
+static.ak.fbcdn.net.
+52.36.94.174.in-addr.arpa.
+www.bing.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+img4.catalog.video.msn.com.
+188.149.40.201.in-addr.arpa.
+www.googleadservices.com.
+groups.google.com.mx.
+www.mybabyexperts.tv.
+www.flirteos.com.
+www.lemec.net.
+44.81.208.190.in-addr.arpa.
+mail.vuria.com.
+www.rmcoin.com.
+code.jquery.com.
+advert-king.tk.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+www.google.com.
+profile.ak.fbcdn.net.
+www.paulownia.ws.
+s.ytimg.com.
+u512.badoo.com.
+www.20minutos.es.
+www.youtube.com.
+vsml.com.
+154.245.7.190.in-addr.arpa.
+mail.pmdl.com.au.
+signup.doitbiatch.com.
+51.121.113.94.in-addr.arpa.
+a.root-servers.net.
+xovoyrolqppifp.net.
+fbcdn-photos-a.akamaihd.net.
+www.noticias.com.ve.
+127.26.51.190.in-addr.arpa.
+luc19msnxl38izbrcxpqizl48kyjuc29iqb38.ru.
+cmu.edu.
+ad.adserverplus.com.
+www.younggunsmusic.com.
+www.foodmag.co.nz.
+23.68.149.189.in-addr.arpa.
+api.facebook.com.
+www.cruelebony.com.
+_903_44_1.
+developers.facebook.com.
+kittysnooks.blogspot.com.
+d2ud4lg6esq2e1.cloudfront.net.
+252.101.105.189.in-addr.arpa.
+131.47.132.190.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+ct.buzzfeed.com.
+mail.acu.net.
+api.facebook.com.
+s-static.ak.fbcdn.net.
+www.clubbisexual.com.
+www.sirintipgreenhome.com.
+173.53.168.189.in-addr.arpa.
+84.187.110.123.in-addr.arpa.
+i2.ytimg.com.
+vevideo.com.es.
+c.perf.glbdns.microsoft.com.
+support.live.com.
+dag.de.
+www.google.com.
+www.amateurdarling.com.
+online.potencialhumanotv.tv.
+www.igui.ru.
+www.conocer.gob.mx.
+sabores.com.
+i1.ytimg.com.
+o31fsfrlrmsf62j46bxotc19aqn50gqbwdya57.info.
+41.212.85.209.bl.spamcop.net.
+csi.gstatic.com.
+ksn2-12.kaspersky-labs.com.
+www.124marketingsystem.com.
+twitter.com.
+www.prnewschannel.com.
+242.255.207.190.in-addr.arpa.
+avatar.pic.itiexue.net.
+scala.ru.
+submit-stroke.ahajournals.org.
+www.google.com.
+a.root-servers.net.
+www.facebook.com.
+20.191.126.186.in-addr.arpa.
+a.c-0.19-210fe000.10590.1518.19d4.3ea1.210.0.rikjfg7q7l6iidkwd5rfk4vkbi.avqs.mcafee.com.
+dejhtq:j3.z52a9x8j.
+blackbookmag.com.
+static.ak.fbcdn.net.
+mail.netlife.ru.
+clientes.disegnia.com.
+blogs.monografias.com.
+fr.answers.yahoo.com.
+www.google.com.
+data.whicdn.com.
+_704_15_6.
+photos-e.ak.fbcdn.net.
+re.revolvermaps.com.
+poker.wincomparator.com.
+get.adobe.com.
+huellasdelbarrio.blogspot.com.
+214.248.67.208.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+yik7yflmh.59ya.
+commander.clara.net.
+photos4.hi5.com.
+ow.ly.
+a4.skype.tom.com.
+5uaxx4or3.20es.
+google.com.
+fbcdn-photos-a.akamaihd.net.
+a6.sphotos.ak.fbcdn.net.
+www.saveyourflight.de.
+a5.sphotos.ak.fbcdn.net.
+26.112.226.190.in-addr.arpa.
+external.ak.fbcdn.net.
+a.root-servers.net.
+pixel.facebook.com.
+89.172.171.69.in-addr.arpa.
+32.183.145.201.in-addr.arpa.
+a.root-servers.net.
+lb._dns-sd._udp.lan.
+mx.vardareast.com.
+youtu.be.
+google.com.
+www.lanvin.com.
+developers.facebook.com.
+wwwimages.adobe.com.
+secure-us.imrworldwide.com.
+d2098016.xoom.it.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+137.48.168.192.in-addr.arpa.
+alucinemodelkits.blogspot.com.
+windows-media-player-9-codecs-pack.programas-gratis.net.
+www.yoreparo.com.
+colin.uk.com.
+safebrowsing.clients.google.com.
+www.surya.com.
+www.oaed.gr.
+teredo.ipv6.microsoft.com.
+6.157.174.189.in-addr.arpa.
+242.15.57.85.in-addr.arpa.
+247.132.125.77.in-addr.arpa.
+google.com.
+cvgps.com.
+cloud1.opensystemsmedia.com.
+rude.hello-net.info.
+a.root-servers.net.
+remail.ru.
+msc.wlxrs.com.
+a7.sphotos.ak.fbcdn.net.
+472.ns1631261.com.
+billing.sharo4ka.ru.
+70.41.43.186.in-addr.arpa.
+upload.xhamster.com.
+statistics02.topface.ru.
+static.ak.connect.facebook.com.
+231.187.137.86.in-addr.arpa.
+155.227.88.186.in-addr.arpa.
+153.110.0.213.in-addr.arpa.
+mafbaymafbay.com.
+fwm3paslw.b42w7b5p.
+a.root-servers.net.
+stoli.com.
+www.worldsmostunique.com.
+www.mason-mahfili.org.tr.
+preflopraise.ru.
+123.155.26.85.in-addr.arpa.
+www.lamparasdeled.com.mx.
+accounts.google.com.
+petfooddirect.com.s10b1.psmtp.com.
+apps.facebook.com.
+secure.tagged.com.
+t.co.
+crl.microsoft.com.
+skpkurortgel.ru.
+ssl.gstatic.com.
+38.184.20.187.in-addr.arpa.
+a.root-servers.net.
+www.google-analytics.com.
+mx.dbaviation.com.
+www.nyfa.edu.
+latinotaku.ucoz.es.
+a.root-servers.net.
+yahoo.com.
+a.root-servers.net.
+cando-online.com.
+ad.doubleclick.net.
+cus.com.
+atss.lu.
+192.111.129.189.in-addr.arpa.
+169.48.96.38.in-addr.arpa.
+exchange.mbcco.com.
+www.goal.org.
+api.facebook.com.
+mail.zoom-dsl.com.
+h.live.com.
+168.244.143.69.in-addr.arpa.
+143.247.236.200.in-addr.arpa.
+1-ps.googleusercontent.com.
+www.octopusproject.eu.
+jmcwd.com.
+amhaire.com.
+josedelcorral.es.
+photos3.zillow.com.
+trainweb.info.
+3478052.megustasabelo.net.
+s-static.ak.fbcdn.net.
+www.cupcakesandcutlery.blogspot.com.
+222.186.4.181.in-addr.arpa.
+i2.ytimg.com.
+34.1.179.190.in-addr.arpa.
+goodyear.com.
+213.229.190.189.in-addr.arpa.
+logo.designcrowd.com.
+mscrl.microsoft.com.
+suggest.infospace.com.
+a.root-servers.net.
+ad.reachjunction.com.
+connect.facebook.net.
+hubspot.com.
+pixel.facebook.com.
+61.224.141.174.combined.njabl.org.
+sg.eyi.com.
+photos-e.ak.fbcdn.net.
+s0.2mdn.net.
+mailfilter.crebe.com.
+mea6hto2g.89yg.
+.
+251.121.232.84.in-addr.arpa.
+www.bywifi.com.
+29.media.tumblr.com.
+groups.google.com.mx.
+www.centerfiresystems.com.
+www.titanbet.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+smail.hrn9.com.
+hi-in.facebook.com.
+martinsalter.net.
+localhost.
+x.tlbron.facemoods.com.
+ale.pakibili.com.
+ar-ar.facebook.com.
+_ldap._tcp.75e1692b-6de3-40f0-8543-b5ffccd67d07.domains._msdcs.gerdau.net.
+pagead2.googlesyndication.com.
+www.google.com.
+a4.sphotos.ak.fbcdn.net.
+ad.z5x.net.
+pixel.facebook.com.
+seg.sharethis.com.
+afrigator.com.
+feeds.bbci.co.uk.
+www.deproviquique.cl.
+s90.vuclip.com.
+www.bbc.co.uk.
+checkip.dyndns.com.
+3detorrevelo.blogspot.com.
+g.live.com.
+133.162.0.94.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.superbeautyfactory.es.
+fox411.blogs.foxnews.com.
+mail.google.com.
+hhotmail.co.
+video.google.com.
+pagead2.googlesyndication.com.
+autowarehouse.com.
+a.root-servers.net.
+44.184.152.187.in-addr.arpa.
+234.153.195.125.in-addr.arpa.
+one.lv.
+googleads.g.doubleclick.net.
+56.80.114.187.in-addr.arpa.
+5.7.174.190.in-addr.arpa.
+tomorrowinvinland.blogspot.com.
+talk21.com.
+mail.worksights.com.
+181.100.208.190.in-addr.arpa.
+www.siaf-china.com.
+mx.eltima.com.
+55.154.72.190.in-addr.arpa.
+wpad.
+tms30.icrc.trendmicro.com.
+dns.msftncsi.com.
+www.mediafire.com.
+skydrive.live.com.
+i.ytimg.com.
+www.googleadservices.com.
+www.barrichello.com.br.
+fc00.deviantart.net.
+zapatosdemodayfiesta.blogspot.com.
+brutaldildos.sexdelivery.com.
+42.27.232.76.in-addr.arpa.
+sagaev.ru.
+www.allfreeclipart.com.
+survey-cdn.effectivemeasure.net.
+86.19.25.190.in-addr.arpa.
+proyectotarotcolectivo.blogspot.com.
+118.174.129.189.in-addr.arpa.
+o-o.preferred.nuq04s10.v18.lscache2.c.youtube.com.
+l.yimg.com.
+static.ak.fbcdn.net.
+236.172.203.81.in-addr.arpa.
+www.designerzcentral.com.
+cc-s.de.
+10.110.159.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+menghao76.en.made-in-china.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+secure.logmein.com.
+5-brujas.peliculon.tv.
+www.albiladdaily.com.
+mail.krhleb.ru.
+node1.bbcimg.co.uk.
+db._dns-sd._udp.0.2.0.10.in-addr.arpa.
+gm.com.
+mooreelectric.com.
+mail.frontierstravel.com.
+www.lagaceta.com.ar.
+searchclient.live.net.
+101.49.124.201.in-addr.arpa.
+chevychaseforecast.com.
+www.googleadservices.com.
+140.47.137.216.in-addr.arpa.
+cbp-us.nccp.netflix.com.
+a.root-servers.net.
+166.128.21.83.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.consultabaekeland.com.
+43.228.171.69.in-addr.arpa.
+recipes.bhg.com.
+heret.net.
+134.86.159.189.in-addr.arpa.
+mail2.torchlake.com.
+117.83.210.201.in-addr.arpa.
+2.pool.ntp.org.
+external.ak.fbcdn.net.
+zynga2-a.akamaihd.net.
+brownandhudson.com.
+a.root-servers.net.
+btjunkie.org.
+www.habemuspapam.it.
+119.181.23.187.in-addr.arpa.
+29.241.175.187.in-addr.arpa.
+www.msftncsi.com.
+a6.sphotos.ak.fbcdn.net.
+ksn1-11-part1.kaspersky-labs.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.macromedia.com.
+api-read.facebook.com.
+dns.msftncsi.com.
+www.lingsoft.fi.
+11-courier.push.apple.com.
+ohio.k12.ky.us.
+www.enjoydressup.com.
+37.128.27.189.in-addr.arpa.
+svrintl-g3-crl.verisign.com.
+ggschmitt.com.
+photos-g.ak.fbcdn.net.
+128.207.172.190.in-addr.arpa.
+www9.effectivemeasure.net.
+www.tutorialesyrecursos.es.
+www.facebook.com.
+googleads.g.doubleclick.net.
+151.251.211.201.in-addr.arpa.
+www.flickr.com.
+jannikeviveka.files.wordpress.com.
+www.jabfm.org.
+d2056968.instant.xoom.it.
+superiorplastic.com.
+clients5.google.com.
+ad.foxnetworks.com.
+platform.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+68ohh6com6c1h-c.c.yom.mail.yahoo.com.
+d2058291.instant.xoom.it.
+fbcdn-photos-a.akamaihd.net.
+pixel.facebook.com.
+186.152.47.147.in-addr.arpa.
+20.246.120.89.in-addr.arpa.
+159.178.177.190.in-addr.arpa.
+68.28.202.81.in-addr.arpa.
+mail1.synagro.com.
+www.download.windowsupdate.com.
+img3.91huo.cn.
+a.root-servers.net.
+api.allmyapps.com.
+www.london-tubemap.com.
+www.rscycle.com.
+98.42.172.90.in-addr.arpa.
+about.tagged.com.
+epiccm.blogspot.com.
+ns2.relkama.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+view.atdmt.com.
+can2012.rfi.fr.
+bpmcpas.com.pri-mx.na0106.smtproutes.com.
+photocontestinformation.com.
+252.233.129.189.in-addr.arpa.
+dagda37.blogia.com.
+jamesmanagement.com.
+a6.sphotos.ak.fbcdn.net.
+amirahall.com.
+oas.monster.com.
+carrolltonpd.net.
+tracker.irc.su.
+webcache.googleusercontent.com.
+pt-br.facebook.com.
+cfile77.uf.daum.net.
+simplecdn.maxcdn.com.
+a3.sphotos.ak.fbcdn.net.
+mail.copernicused.com.
+vide0s.org.
+ds.serving-sys.com.
+mail.pcrc.spb.ru.
+sp.cwfservice.net.
+img.apnanalytics.com.
+52.109.190.189.in-addr.arpa.
+ns2.yaknet.ca.
+photos-b.ak.fbcdn.net.
+103.136.95.200.in-addr.arpa.
+crl.microsoft.com.
+mundoconquis.files.wordpress.com.
+img1-fotki.yandex.net.
+dr._dns-sd._udp.lan.
+getlive.com.
+0-jw-w.channel.facebook.com.
+treenosoftware.com.
+img71.exs.cx.
+hlylsbty.net.
+36-courier.push.apple.com.
+jrol.com.
+tv.about.com.
+badge.facebook.com.
+www.mexicanisimo.com.mx.
+134.207.240.148.in-addr.arpa.
+ajax.googleapis.com.
+a.root-servers.net.
+g.ceipmsn.com.
+156.71.102.201.in-addr.arpa.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+coldraria.blogspot.com.
+www.odfl.com.
+lyrics.music-strike.net.
+www.xg7979.com.
+_431_19_2.
+a.root-servers.net.
+a83.phobos.apple.com.
+edge.quantserve.com.
+netflix757.pop3.la.nflximg.com.edgesuite.net.
+4cskenyatuitakayo.org.
+s-static.ak.fbcdn.net.
+135.89.87.190.in-addr.arpa.
+_511_72_7.
+www.boca-lobo.blogspot.com.
+sc21.rules.mailshell.net.
+www.pilgrimcars.com.
+189.56.180.64.in-addr.arpa.
+open.qzone.qq.com.
+a-0.19-21094071.9030083.1518.19d3.3ea1.410.0.e5c2hr5rirvc83viczadisp8rb.avqs.mcafee.com.
+nvjqjsnx9.f70y3n1q.
+www.myslavegirls.com.
+forums.socialpointgames.com.
+0.3099009.com.
+time.chttl.com.tw.
+www.zadetek.net.
+dns.msftncsi.com.
+tecnologia.es.msn.com.
+a.root-servers.net.
+prosperityloan.com.
+code.jquery.com.
+creative.ak.fbcdn.net.
+naissance.bebe.notrefamille.com.
+rcp.na.blackberry.com.
+hootsuite.com.
+beton-pesok.ru.
+145.101.179.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+128.177.49.190.in-addr.arpa.
+vypxvs.com.
+a.root-servers.net.
+9.240.230.83.in-addr.arpa.
+4.143.86.200.in-addr.arpa.
+pollsdynamic.esmas.com.
+201.143.77.82.in-addr.arpa.
+www.teachingnews.co.uk.
+cdn2.image.keezmovies.phncdn.com.
+203.70.142.190.in-addr.arpa.
+maddogweb.com.s7a2.psmtp.com.
+www.rgawi.com.
+2.bp.blogspot.com.
+gra-elmundomagicodelasagujas.blogspot.com.
+kfedisbroke.com.lan.
+centaurmx1.dxsolutions.biz.
+photos-b.ak.fbcdn.net.
+www.allergynet.com.au.
+dnl-19.geo.kaspersky.com.
+98.82.27.201.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+springerlink.metapress.com.
+img.mediaplex.com.
+www.google-analytics.com.
+sro.whatsapp.net.
+216.153.19.186.in-addr.arpa.
+plusone.google.com.
+a.root-servers.net.
+www.ylab.es.
+e906.g.akamaiedge.net.
+video.foxsmallbusinesscenter.com.
+static.ak.fbcdn.net.
+82.222.2.204.in-addr.arpa.
+www.toquetoques.com.
+beta.stun.voice.yahoo.com.
+0-250.channel.facebook.com.
+trendingsearches.net.
+support.maktoob.com.
+130.127.117.91.in-addr.arpa.
+apps.facebook.com.
+i1.ytimg.com.
+dkndbrm1z.x80c1x2o.
+23.130.130.201.in-addr.arpa.
+espanol.answers.yahoo.com.
+www.addthis.com.
+a.root-servers.net.
+video.google.com.
+cs10658.vk.com.
+discavery.ru.
+www.gabrielacastillo.com.
+static.imonografias.com.
+mmetal.ru.
+photos-d.ak.fbcdn.net.
+184.209.47.201.in-addr.arpa.
+www.freeridegames.com.
+www.foodbuzz.com.
+mail.industrialgines.com.
+cdn1.clkads.com.
+www.rincondelvago.com.
+55.89.173.190.in-addr.arpa.
+www.adobe.com.
+85.85.231.190.in-addr.arpa.
+.
+a.root-servers.net.
+csi.gstatic.com.
+photos-d.ak.fbcdn.net.
+www.turismoinkaiko.net.
+150.174.86.201.in-addr.arpa.
+zakazmebel.ru.
+147.112.249.81.in-addr.arpa.
+mail.burtcrane.com.
+dns.msftncsi.com.
+baymsg1020409.gateway.messenger.live.com.
+www.images.com.
+87.124.113.188.in-addr.arpa.
+_991_90_9.
+88ig51n5t.d34k2e1b.
+mrmbw.com.
+a.root-servers.net.
+d2092230.xoom.it.
+a8.sphotos.ak.fbcdn.net.
+ecx.images-amazon.com.
+fusion.google.com.
+humannova.files.wordpress.com.
+pt-br.facebook.com.
+www.wordpress.com.
+dc305.4shared.com.
+wirelessmedia.ign.com.
+a.root-servers.net.
+begonebrotherhood.forumotion.com.
+dmqg0yef478ix.cloudfront.net.
+a.c-0.19-210fe000.10590.1518.19d4.3ea1.410.0.rikjfg7q7l6iidkwd5rfk4vkbi.avqs.mcafee.com.
+csi.gstatic.com.
+teredo.ipv6.microsoft.com.
+api.twitter.com.
+bs.serving-sys.com.
+www.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+range-systems.com.s8b1.psmtp.com.
+garageband.maccreate.com.
+blog.matoo.net.
+accounts.google.com.
+seaquest.com.
+go.universal-music.de.
+www.rangerover.com.
+ds.serving-sys.com.
+mx7.hushmail.com.
+trauerhahn.de.
+a8.sphotos.ak.fbcdn.net.
+www.viva4madrid.com.
+92.86.193.187.in-addr.arpa.
+scanpell.no.
+mail.westcall.net.
+static.ak.fbcdn.net.
+safesprinklers.com.
+img3.xcarimg.com.
+qq.net.
+photos-c.ak.fbcdn.net.
+twentynineinches.com.
+a4.sphotos.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+135.72.158.201.in-addr.arpa.
+clients2.google.com.
+46.106.146.194.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+rebmaillink.rebtel.com.
+_417_65_8.
+38.97.132.189.in-addr.arpa.
+blog.comsatmedia.com.
+a.root-servers.net.
+c.plma.se.
+101.232.108.84.in-addr.arpa.
+ad.z5x.net.
+a1251.phobos.apple.com.edgesuite.net.
+pixel.facebook.com.
+www.lahueca.ec.
+katherussa.blogspot.com.
+blog.9marks.org.
+s-static.ak.facebook.com.
+44.156.127.201.in-addr.arpa.
+60.76.122.200.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+110.33.36.186.in-addr.arpa.
+scholar.google.com.
+www.redfaction.com.
+recoveryisbeautiful.tumblr.com.
+dnl-02.geo.kaspersky.com.
+delacarreracavanzo.com.
+metrics.raptr.com.
+photos-h.ak.fbcdn.net.
+yahoo.com.
+aprendeareirconelcolegiotartessos.blogspot.com.
+ge.com.
+www.facebook.com.
+3.145.68.201.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+twitter.co.
+6-courier.push.apple.com.
+www.youtube.com.
+translate.google.com.
+safebrowsing.clients.google.com.
+208.45.233.201.in-addr.arpa.
+107.146.220.66.in-addr.arpa.
+adblock-plus.uptodown.com.
+p08-bookmarks.icloud.com.
+28.41.148.190.in-addr.arpa.
+35.189.33.151.in-addr.arpa.
+ybinst3.ec.yimg.com.
+189.195.222.189.in-addr.arpa.
+checkip.dyndns.org.
+www.blogpsicopositiva.com.
+www.elperiodicodemexico.com.
+173.150.252.190.in-addr.arpa.
+49.1.168.192.in-addr.arpa.
+mailgateway02.acs-corp.com.
+139.77.121.186.in-addr.arpa.
+open.hr.
+cyber.net.
+sri.ua.es.
+profile.ak.fbcdn.net.
+74.144.242.78.in-addr.arpa.
+pheedo-rdr.msnbc.msn.com.
+140.138.20.190.in-addr.arpa.
+135.49.145.181.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+181.132.22.187.in-addr.arpa.
+sites.google.com.
+nosotroslosgorditos.blogspot.com.
+238.56.174.189.in-addr.arpa.
+27.251.210.201.in-addr.arpa.
+www.locaporlamodachile.com.
+www.thinkwithgoogle.co.uk.
+mx0.gmx.net.
+smtp1.rehau.com.
+46.22.212.201.in-addr.arpa.
+pixel.facebook.com.
+sac.gti.mcafee.com.
+www.nosolodepanviveelhombre.com.
+fbcdn-profile-a.akamaihd.net.
+mail.moava.net.
+41.231.233.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ravens.ru.
+photos-h.ak.fbcdn.net.
+external.ak.fbcdn.net.
+ie.todoexplorer.com.
+a8.sphotos.ak.fbcdn.net.
+www.funcionjudicial-pichincha.gov.ec.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+adoregames.com.
+homezeus.tanagraltd.com.
+39.61.35.177.in-addr.arpa.
+www.stcwatches.com.
+226.63.30.190.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+v20.nonxt1.c.youtube.com.
+rhodeisland.broadwayworld.com.
+adfarm.mediaplex.com.
+www.facebook.com.
+mail1.islc.net.
+phaseiv.com.
+mail.bya.ru.
+fbcdn-sphotos-a.akamaihd.net.
+www.emagister.com.mx.
+engine24-1452-2.icritical.com.
+57.121.168.192.in-addr.arpa.
+wm44wmoy2.w21t8k1j.
+www.youtube.com.
+167.130.243.189.in-addr.arpa.
+cluster3.eu.messagelabs.com.
+um18.eset.com.
+a1.sphotos.ak.fbcdn.net.
+210.28.33.27.in-addr.arpa.
+49.60.204.91.in-addr.arpa.
+active.xo.com.
+searchclient.live.net.
+ow.ly.
+ssl.gstatic.com.
+b.scorecardresearch.com.
+connect.facebook.net.
+rest-img.msg.yahoo.com.
+www.mysoccerpatch.com.
+a.root-servers.net.
+153.139.125.186.in-addr.arpa.
+tcp.net.uk.
+a.root-servers.net.
+115.3.8.124.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+connect.facebook.net.
+a4.sphotos.ak.fbcdn.net.
+mail.popsforchampagne.com.
+api.twitter.com.
+www.selectividad.tv.
+toolbarqueries.google.es.
+photos-e.ak.fbcdn.net.
+api.conduit.com.
+www.facebook.com.
+sivis.com.br.
+www.facebook.com.
+otmail.de.
+www.statusq.org.
+olympics.wikia.com.
+www.stayclassy.org.
+ctsi-global.com.
+ads.adxpansion.com.
+col.stj.s-msn.com.
+service.gc.apple.com.akadns.net.
+61.89.18.95.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.sonoframbow.com.
+pt-br.facebook.com.
+www.myspace.com.
+msc.wlxrs.com.
+www.drumscore.com.
+a.root-servers.net.
+www.facebook.com.
+57.187.137.190.in-addr.arpa.
+dns.msftncsi.com.
+multimedia.gustavo-castro.com.
+mail2.m7aerospace.com.
+c5uhsqqmo.40sv.
+au.download.windowsupdate.com.
+29-courier.push.apple.com.
+769.coll.ning.com.
+50.234.94.190.in-addr.arpa.
+200.222.67.201.in-addr.arpa.
+10-courier.push.apple.com.
+video.forcedfemdomtgp.com.
+s-static.ak.fbcdn.net.
+a.root-servers.net.
+www.definicion.com.mx.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+206.40.10.201.in-addr.arpa.
+oyhubl.com.
+gfx4.hotmail.com.
+static.ak.facebook.com.
+www.flexgallery.com.
+71.12.22.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+87.122.201.190.in-addr.arpa.
+apis.google.com.
+www.annecoyleinteriors.com.
+photos-f.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+www.thaidvd.biz.
+yahoo.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+www.elciudadano.cl.
+wwwimages.adobe.com.
+www.diabetesjournals.org.
+neoenergiaedp.com.
+cn.pool.ntp.org.
+_311_12_5.
+members.dyndns.org.
+teredo.ipv6.microsoft.com.
+byfiles.storage.msn.com.
+14eg6s-de-he3d6ss.juegosipo.com.
+mail.columbusfirstbank.com.
+151.57.115.187.in-addr.arpa.
+hjuhsd.k12.ca.us.
+235.30.198.187.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+checkout.google.com.
+239.179.158.189.in-addr.arpa.
+readeronline.wip4.adobe.com.
+img268.
+jcsu.edu.s10a2.psmtp.com.
+krithiskitchen.blogspot.com.
+muchascajasdecarla.blogspot.com.
+hofra.sr.
+crl.microsoft.com.
+atlanticcityelectric.com.
+114.129.44.99.in-addr.arpa.
+ad-apac.doubleclick.net.
+ville-nice.fr.
+www.pastelerialety.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.eu-ssa.org.
+231.210.58.186.in-addr.arpa.
+26.20.223.98.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+205.126.37.80.in-addr.arpa.
+zolotoy-venetz.spb.ru.
+132.68.231.213.in-addr.arpa.
+37.171.79.190.in-addr.arpa.
+s2.youtube.com.
+148.133.101.199.in-addr.arpa.
+cn1.redswoosh.akadns.net.
+a.root-servers.net.
+62.165.231.189.in-addr.arpa.
+153.56.47.190.in-addr.arpa.
+api-read.facebook.com.
+impulsi.ru.
+a.root-servers.net.
+14.133.211.201.in-addr.arpa.
+s3.subirimagenes.com.
+144.34.151.187.in-addr.arpa.
+cdn.extensions.buzznet.com.
+www.jiggystudio.com.
+profile.ak.fbcdn.net.
+mail.yimg.com.
+an.tacoda.net.
+software.filestube.com.
+238.158.164.189.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+www.google.com.
+a8.sphotos.ak.fbcdn.net.
+www.pixelfanatic.com.
+us.data.toolbar.yahoo.com.
+artone.ru.
+www.serial-on.clan.su.
+mail.glatt.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+224.198.127.59.in-addr.arpa.
+www.blog.proxyroller.com.
+s3.hddownloader.com.
+www.thelusted.com.
+www.lugaresquenoquierocompartirconnadie.com.
+cdn1.clkads.com.
+197.238.236.190.in-addr.arpa.
+cs505204.vk.com.
+cfs-p4.l3.fbcdn.net.
+www.findserialnumber.me.
+smtp2.prointec.es.
+www.foreverunique.co.uk.
+www.lace-up.de.
+www.youtube.com.
+www.deremate-inc.com.
+pixel.rubiconproject.com.
+d15gt9gwxw5wu0.cloudfront.net.
+xglobal.froo.com.
+yui.yahooapis.com.
+www.facebook.com.
+api-public.addthis.com.
+digg.com.
+www.facebook.com.
+crl.verisign.net.
+rad.msn.com.nsatc.net.
+s.youtube.com.
+redfaceplus.com.
+www.macromedia.com.
+event.adxpose.com.
+126.96.170.90.in-addr.arpa.
+77.167.170.184.in-addr.arpa.
+fivetowntoyota.com.
+mail.youngstartup.com.
+mail.spectrasonics.com.
+googleads.g.doubleclick.net.
+112.84.214.201.in-addr.arpa.
+s0.2mdn.net.
+www.idcow.com.
+view.atdmt.com.
+plus.google.com.
+external.ak.fbcdn.net.
+www.playspidermangames.org.
+budget.moneycontrol.com.
+secure.wlxrs.com.
+4xusys5mt.87bq.
+annaandtheringlondon.blogspot.com.
+rainbow-it.mythings.com.
+t.co.
+smtp.live.com.
+www.facebook.com.
+25.0/27.3.69.83.in-addr.arpa.
+sportsgrid.com.
+www.ganfx.com.
+plus.google.com.
+13.144.206.200.in-addr.arpa.
+relay.voice.edge.messenger.live.com.
+clients2.google.com.
+dc.logmein-gateway.com.
+blog.wunderlist.com.
+58.144.153.201.in-addr.arpa.
+129.167.116.78.in-addr.arpa.
+www.sharethis.com.
+www.yahoo.com.
+a8.sphotos.ak.fbcdn.net.
+mail.walkercontracting.com.
+wrg1008.webradiogratis.com.
+www.keezmovies.com.
+utrade.ru.
+www.importvelez.com.ar.
+75.204.34.189.in-addr.arpa.
+a.root-servers.net.
+liability-insurance-types.com.
+www.tarocchiamore.info.
+thumbnails9.imagebam.com.
+www.mold-help.org.
+86.4.122.187.in-addr.arpa.
+165.81.49.70.in-addr.arpa.
+humor.petardas.com.
+43.74.230.71.in-addr.arpa.
+punkmagazine.com.
+153.95.55.189.in-addr.arpa.
+utils.babylon.com.
+wclacc.org.
+gdata.youtube.com.
+static.uk.groupon-content.net.
+gsp1.apple.com.
+api.twitter.com.
+www.diamantalia.com.
+pu4fox653.c75o8x5p.
+www.beautifulmag.com.
+billing.sharo4ka.ru.
+ivyleagueadmission.com.
+cesarasilva.com.
+qualitymetalwv.com.
+villanoticias.blogspot.com.
+bowdoin.academia.edu.
+susanne-weber.eu.
+provgrp.us.
+www.gruposiete.com.mx.
+pensketruckleasing.com.
+c-0.19-230f0081.c050081.1518.19c5.3ea1.210.0.l3ep1t8fv2s2q4njwbkes7s4nb.avqs.mcafee.com.
+ssfsf.com.
+download.windowsupdate.com.
+www.creditme.com.
+dns.msftncsi.com.
+59a92430e6.com.
+links.mkt3094.com.
+wildernesslore.com.
+safebrowsing-cache.google.com.
+radugaprint.ru.
+jasperautomotive.com.
+dominguez-cia.com.
+deckercollege.com.
+hosting.lockhosts.com.
+profile.ak.fbcdn.net.
+api.webrep.avast.com.
+217.173.36.186.in-addr.arpa.
+www.amazon.com.
+194.96.141.83.in-addr.arpa.
+176.43.65.69.in-addr.arpa.
+evsecure-ocsp.verisign.com.
+ksn2-12.kaspersky-labs.com.
+check4.facebook.com.
+platform.ak.fbcdn.net.
+csi.gstatic.com.
+www.lux.
+google.com.
+a.root-servers.net.
+126.121.107.190.in-addr.arpa.
+mail.olympuspower.com.
+i2.ytimg.com.
+go.srvnow.com.
+badurls119.gsecurity.de.
+support.ovi.com.
+continent-mebel.ru.
+a.root-servers.net.
+a.root-servers.net.
+www.myhomeremedies.com.
+74.233.158.213.in-addr.arpa.
+sp.cwfservice.net.
+jobsale.ru.
+www.sherweb.com.
+keywest.com.
+n3yve26iy.p87i5v0q.
+alfa.ns.active24.cz.
+www.partymonster.cl.
+inbound.parry.biz.netsolmail.net.
+118.101.56.190.in-addr.arpa.
+www.facebook.com.
+www.autobacklinkservice.com.
+sjstatic.sj.91.com.
+100.143.63.46.in-addr.arpa.
+gmailc.om.
+teredo.ipv6.microsoft.com.
+28.223.144.189.in-addr.arpa.
+mail.sacvoyage.com.
+external.ak.fbcdn.net.
+20.234.246.88.in-addr.arpa.
+plus.google.com.
+www.poderypaz.com.
+www.erlupacchiotto.com.
+223.119.137.201.in-addr.arpa.
+www.nakedgirlfriend.net.
+www.sabiasque.info.
+87.146.220.66.in-addr.arpa.
+www.google-analytics.com.
+mhl2w4zpt.l77z8p6y.
+safebrowsing.clients.google.com.
+mx.youtube.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.google.com.
+hotmail.com.
+profile.ak.fbcdn.net.
+s-static.ak.facebook.com.
+www.l.google.com.
+checkip.dyndns.org.
+squall21000.unblog.fr.
+semprautilities.com.
+www.download-free-templates.com.
+www.facebook.com.
+rekad.be.
+9.254.103.189.in-addr.arpa.
+bloggergadgets.googlecode.com.
+autos.demotores.com.ar.
+api.facebook.com.
+www.facebook.com.
+i3.ytimg.com.
+www.facebook.com.
+78.241.14.186.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+groups.google.com.mx.
+a.rtiindia.org.
+19.174.192.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+jangsara.blogspot.com.
+tracsablog.typepad.com.
+cicb-chemicon-com.antispam2.softcell.in.
+internetservice.shopsgroup.com.
+prwg.wikispaces.com.
+boletotal.mx.
+platform.twitter.com.
+line4u.ru.
+110.196.222.186.in-addr.arpa.
+www.amarillasnevada.com.
+aoltv.com.
+nationwiderestorationllc.com.
+jesmar.com.
+developers.facebook.com.
+dns.msftncsi.com.
+a1.sphotos.ak.fbcdn.net.
+mynnb.com.s8a1.psmtp.com.
+a5.sphotos.ak.fbcdn.net.
+us.topshop.com.
+a8.sphotos.ak.fbcdn.net.
+www.fanaticinema.com.
+www.newstar-cherry.net.
+img.realvoyeurpost.com.
+mb.marathonbet.com.
+www.facebook.com.
+36ohk6dgmcd1n-c.c.yom.mail.yahoo.net.
+pyx.net.
+gizma.ru.
+saude.ig.com.br.
+news.google.com.mx.
+www.google-analytics.com.
+1.0.0.223.lbl7.mailshell.net.
+26.196.138.189.in-addr.arpa.
+223.216.118.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+nama3.thamrin.net.id.
+www.senatorsextra.com.
+amor.prodigy.match.com.
+lainquisicionprogramadetv.blogspot.com.
+mediacenter2.clicrbs.com.br.
+www.miniclip.com.
+v4.lscache5.googlevideo.com.
+7.10.22.186.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+juki.su.
+62.9.133.186.in-addr.arpa.
+dak.donetsk.ua.
+api.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+l3.image.dirty101.com.
+docs.google.com.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+abcdiario2010.blogspot.com.
+9.112.44.60.in-addr.arpa.
+246.191.136.14.in-addr.arpa.
+dns.msftncsi.com.
+spe.com.
+s3.amazonaws.com.
+mx2.inflin.ru.
+www.ardillamedia.com.
+www.joinecsc.com.
+141.163.239.201.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.thethinkingstick.com.
+34.229.171.69.in-addr.arpa.
+105.10.43.200.in-addr.arpa.
+google.com.
+www.monografias.com.
+94.15.168.192.in-addr.arpa.
+pixel.facebook.com.
+55.17.59.186.in-addr.arpa.
+gearjunkie.com.
+www.datadev.com.
+static.canalstat.com.
+tracker.bittorrent.am.
+www.cloudantivirus.com.
+photos-f.ak.fbcdn.net.
+iztapalapa.infoisinfo.com.mx.
+platform.ak.fbcdn.net.
+ertolete.wordpress.com.
+www.bidstrup.ru.
+130.53.206.187.in-addr.arpa.
+i3.ytimg.com.
+del.icio.us.
+holiday-for-children.ru.
+s7.addthis.com.
+es-es.facebook.com.
+nations.tm-exchange.com.
+moritzchevrolet.com.
+203.156.200.98.in-addr.arpa.
+profile.ak.fbcdn.net.
+g.live.com.
+2dwti6j8g.n70r9f3f.
+lb._dns-sd._udp.0.9.168.192.in-addr.arpa.
+log.client.akadns.net.
+de-de.facebook.com.
+clients4.google.com.
+samcoline.com.
+www.google.com.
+sea-wallpapers.blogspot.com.
+mx.youtube.com.
+ad.doubleclick.net.
+www.msn.com.
+ewriters.org.
+mailserver.ctf-uk.com.
+hotmail.com.
+connect2.askadmissions.net.
+www-fc-opensocial.googleusercontent.com.
+paginadeerro.ig.com.br.
+image-c.c.yom.mail.yahoo.net.
+m.facebook.com.
+sintechms.com.
+googlemaps.
+calif.com.
+www.gayxxxblog.com.
+a.root-servers.net.
+enthought.com.s9a1.psmtp.com.
+loganlibrary.org.
+194.34.174.90.in-addr.arpa.
+a.root-servers.net.
+www.google.com.mx.
+insightbb.com.
+abp2go.com.
+external.ak.fbcdn.net.
+235.242.13.187.in-addr.arpa.
+sp.cwfservice.net.
+67652.envacaciones.info.
+smtp.equipcokuwait.com.
+50.7.93.186.in-addr.arpa.
+www.imprentavalencia.com.
+ns7.ptspb.ru.
+www.egagenerics.com.
+api.facebook.com.
+support.google.com.
+img.uptodown.net.
+www.ulani.de.
+20.228.171.69.in-addr.arpa.
+msnia.login.live.com.
+webcache.googleusercontent.com.
+s.youtube.com.
+beko-zuid.nl.
+listas.trisquel.info.
+sp.cwfservice.net.
+pagead2.googlesyndication.com.
+www.situsotomotif.com.
+185.214.242.98.in-addr.arpa.
+tap2-cdn.rubiconproject.com.
+www.google.com.
+kayucolectivo.obolog.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+o.analytics.yahoo.com.
+4.213.188.190.in-addr.arpa.
+crc4pr.com.
+e906.g.akamaiedge.net.
+www.guanakos.net.
+www.ratteb.com.
+140.7.231.189.in-addr.arpa.
+a.root-servers.net.
+ad.adnetwork.net.
+253.8.124.186.in-addr.arpa.
+www.earthincommon.com.
+135.242.225.189.in-addr.arpa.
+a.root-servers.net.
+blugro2relay.groove.microsoft.com.
+market.android.com.
+.
+www.google.com.
+orcart.facebook.com.
+inbound.staffordsmith.com.netsolmail.net.
+skipod.ru.
+73.104.19.190.in-addr.arpa.
+hotpremiumcookies.blogspot.com.
+tubularsuspensionsystems.com.
+a4.sphotos.ak.fbcdn.net.
+234.204.55.216.in-addr.arpa.
+www.apple.com.
+4.183.115.79.in-addr.arpa.
+i3.ytimg.com.
+www.bic-code.org.
+pagead2.googlesyndication.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+retromed.doc-martin.ru.
+_360_40_2.
+a5.sphotos.ak.fbcdn.net.
+iffexc.fibraforte.com.
+www.kidsafensw.org.
+userimages01-akm.imvu.com.
+www.teensdefloration.net.
+a2.sphotos.ak.fbcdn.net.
+zapatec.com.
+105.77.69.189.in-addr.arpa.
+emob247.photobucket.com.
+mail.cpmail.ru.
+s-static.ak.fbcdn.net.
+251.221.124.201.in-addr.arpa.
+tenet.ru.
+bank06.mi.ads.mp.mydas.mobi.
+barranquillaes.chatango.com.
+tap-cdn.rubiconproject.com.
+teredo.ipv6.microsoft.com.
+a7.sphotos.ak.fbcdn.net.
+www.michaeljordanoutlet.com.
+105.52.205.190.in-addr.arpa.
+11.231.61.78.in-addr.arpa.
+jers3.info.
+www.google.com.
+www.googleadservices.com.
+jorgevila.blogspot.com.
+losmasgrandesdelahistoria.blogspot.com.
+profile.ak.fbcdn.net.
+wwc.instacam.com.
+nt3.ggpht.com.
+189.229.39.187.in-addr.arpa.
+a.root-servers.net.
+armmf.adobe.com.
+zgn.static.zynga.com.
+youtube-espanol.blogspot.com.
+contiadvertising.name.
+url.edu.gt.
+jobs.raytheon.com.
+i1.ytimg.com.
+a2.da1.akamai.net.
+0-jf-w.channel.facebook.com.
+ksn2-12.kaspersky-labs.com.
+login.yahoo.com.
+fcat.fldoe.org.
+hangtime.blogs.nba.com.
+3.242.168.189.in-addr.arpa.
+www.skyrama.de.
+61.127.134.122.in-addr.arpa.
+maxcontrols.com.
+developers.facebook.com.
+155.48.70.173.in-addr.arpa.
+ksn7-12.kaspersky-labs.com.
+www.google.com.
+sites.google.com.
+vmirror3.garant.ru.
+ptpw.com.tw.
+dsn13.d.skype.net.
+www.jesusdemanuel.es.
+cronicasdeinternet.com.
+a5.sphotos.ak.fbcdn.net.
+luismthen.posterous.com.
+86.12.227.190.in-addr.arpa.
+akm.atlas-rt.ru.
+alpha.newsx.com.
+s.youtube.com.
+229.94.113.88.in-addr.arpa.
+thegoodlife.ru.
+pocketpc-fujitsu.ru.
+www.addthis.com.
+cdn.conceptdezain.com.
+isatap.gateway.2wire.net.
+a.root-servers.net.
+jg.com.
+www.adoptivefamilies.com.
+3limona.ru.
+www.google.com.
+a.root-servers.net.
+sp.cwfservice.net.
+cybernet.net.
+foundationsource.com.2.0001.arsmtp.com.
+ja-jp.facebook.com.
+carina-a-met-art.bravoerotica.com.
+.
+95.107.160.69.in-addr.arpa.
+www.google.com.
+138.125.241.201.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cur.cursors-4u.net.
+entretenimiento.prodigy.msn.com.
+b-0.19-a3005008.11081.1518.19d0.3ea1.410.0.ddcllgmu7e9kp2t99kj9blbvp6.avqs.mcafee.com.
+shared.live.com.
+www.otakugaming.com.
+rtpnet.org.
+mail.mccmetro.com.
+accounts.google.com.
+thumbs4.ebaystatic.com.
+ssl.gstatic.com.
+radiolafavorita.com.
+trc-hq.com.
+checkip.dyndns.org.
+224.194.89.201.in-addr.arpa.
+a979.v.phobos.apple.com.
+img25.imageshack.us.
+s2.youtube.com.
+147.218.225.212.in-addr.arpa.
+fr.shegame.com.
+www.facebook.com.
+43.220.27.108.in-addr.arpa.
+a.root-servers.net.
+4.166.138.190.in-addr.arpa.
+www.sweetim.com.
+isotron.com.s200a2.psmtp.com.
+rcp.na.blackberry.com.
+_822_10_2.
+47.23.95.190.in-addr.arpa.
+hdmanagement.com.
+a.root-servers.net.
+brico-pack-vista-inspirat.malavida.com.
+rsca.be.
+31.170.218.80.in-addr.arpa.
+messenger.hotmail.com.
+0-271.channel.facebook.com.
+web.me.com.edgekey.net.
+www.facebook.com.
+smtp.bitterrootgroup.com.
+97.53.209.190.in-addr.arpa.
+skynet-services-other.metriweb.be.
+126.127.47.190.in-addr.arpa.
+sigs.symantec.com.
+a.root-servers.net.
+pixel.facebook.com.
+mx03.t-online.de.
+www.ngsimages.com.
+disneylatino.com.
+159.25.38.187.in-addr.arpa.
+maktoob.yahoo.com.
+alerts.conduit-services.com.
+138.225.193.190.in-addr.arpa.
+blueyonder.co.uk.
+smtp.ww.co.nz.
+2.30.207.190.in-addr.arpa.
+202.28.165.189.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.allisonangel.info.
+86.143.153.188.in-addr.arpa.
+mail.choifm.com.
+www.netnanny.com.
+tarot-egipcio.com.
+124.226.74.190.in-addr.arpa.
+a1108.da1.akamai.net.
+186.178.229.189.in-addr.arpa.
+dogs2.f5.vip.milp.ngmoco.com.
+s-static.ak.fbcdn.net.
+d.mzc.in.
+profile.ak.fbcdn.net.
+142.217.245.190.in-addr.arpa.
+www.philippi.cl.
+www.fincen.gov.
+www.imageport.info.
+www.cosmetic-plastic-surgery.info.
+a.root-servers.net.
+mixph.com.
+214.151.178.190.in-addr.arpa.
+i4.ytimg.com.
+181.212.186.189.in-addr.arpa.
+28.64.125.186.in-addr.arpa.
+static.ak.fbcdn.net.
+mail.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.premioelbarcodevapor-blaa.com.
+a.root-servers.net.
+g.ceipmsn.com.
+www.xatech.com.
+sfigroup.co.uk.
+10.21.255.201.in-addr.arpa.
+preparacion2012.argentinaforo.net.
+a34.g.akamai.net.
+www.nrcu.gov.ua.
+apps.facebook.com.
+i1213.photobucket.com.
+iraqpics.net.
+blogs.laverdad.es.
+ad-g.doubleclick.net.
+css.wlxrs.com.
+a3.sphotos.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+peoplepc.compeoplepc.com.
+pixel.quantserve.com.
+francemebel.ru.
+70.202.67.187.in-addr.arpa.
+coronapalto.ru.
+photos-g.ak.fbcdn.net.
+mid-valleysupply.com.
+www.usolympicteam.com.
+meneame.net.
+177.241.26.46.in-addr.arpa.
+www.harryshumjr.com.
+48.216.85.209.iadb.isipp.com.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.facebook.com.
+canseco.com.s8b1.psmtp.com.
+www.mediafire.com.
+hpana.com.
+www.rutacol.com.
+luismaenlasnubes.blogspot.com.
+photos-a.ak.fbcdn.net.
+factory.okna5.ru.
+ksn7-12.kaspersky-labs.com.
+bp1.blogger.com.
+www.middleeasthealthmag.com.
+photos-h.ak.fbcdn.net.
+www.gn4me.com.
+correoweb.com.
+cdn.ad4game.com.
+e-yes.gr.
+1.0.0.10.in-addr.arpa.
+sakura-card-captor-anime.blogspot.com.
+142.175.25.187.in-addr.arpa.
+descuidofamosas.info.
+gotfuturama.com.
+172.92.255.190.in-addr.arpa.
+cdn.mediafire.com.
+www.videosmz.com.
+www.detiknews.com.
+grnlakeorion.com.
+tfw-current.s3.amazonaws.com.
+goodtimes.com.
+211.11.4.175.in-addr.arpa.
+www.facebook.com.
+morgansstanley.com.
+titanium30-en.url.trendmicro.com.
+www.picadillocircus.com.
+secure.wlxrs.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+187.2.115.92.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+svr3.marketrends.net.
+static.ak.fbcdn.net.
+a.root-servers.net.
+gg.google.com.
+ksn1-12-part2.kaspersky-labs.com.
+mail.buddysbarbq.com.
+iit.net.ru.
+59.216.92.186.in-addr.arpa.
+www.libraryloungelizard.com.
+barcelonacultura.bcn.cat.
+img1.imensagens.com.
+www.moringa.com.
+129.102.255.201.in-addr.arpa.
+buycostumes.pscsrv.net.
+208.64.32.190.in-addr.arpa.
+rodnik.biz.
+creative.ak.fbcdn.net.
+heart4me.com.
+static.ak.fbcdn.net.
+sites.google.com.
+mx.mujer.yahoo.com.
+plus.google.com.
+vnmade.com.
+www.google-analytics.com.
+rds.yahoo.com.
+40.53.24.189.in-addr.arpa.
+static.ak.facebook.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+96.145.171.187.in-addr.arpa.
+-de-masa-y-tortillas.wired.com.mx.
+158.46.153.201.in-addr.arpa.
+co122w.col122.mail.live.com.
+www.facebook.com.
+privetsochi.ru.
+159.146.180.189.in-addr.arpa.
+pixel.facebook.com.
+free.timeanddate.com.
+ru.thefreedictionary.com.
+sitebitrix.ru.
+www.simel.it.
+el-oso-oshitas.blogspot.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+118.49.40.190.in-addr.arpa.
+virginmega.com.s7b1.psmtp.com.
+21.115.138.189.in-addr.arpa.
+ic.tynt.com.
+t3.gstatic.com.
+a.root-servers.net.
+www.xatech.com.
+24.136.176.190.in-addr.arpa.
+rcp.na.blackberry.com.
+www.my-shop.com.au.
+bmaa.gv.at.
+met.adwhirl.com.
+vlex.com.co.
+urban.com.ru.
+a.root-servers.net.
+muuuvies.files.wordpress.com.
+homercentral.org.
+bartoncreek.com.
+89.210.205.190.in-addr.arpa.
+40.51.175.187.in-addr.arpa.
+mollenkopf.de.
+50.108.236.189.in-addr.arpa.
+a.root-servers.net.
+fbcdn-profile-a.akamaihd.net.
+googleapis.l.google.com.
+ajax.googleapis.com.
+a.root-servers.net.
+17.120.228.24.in-addr.arpa.
+51.89.53.92.in-addr.arpa.
+mx.hazlettinc.com.
+_311_33_5.
+a.root-servers.net.
+www.101incredibleplaces.com.
+53.149.48.65.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.damselstruction.com.
+ksn7-12.kaspersky-labs.com.
+photos-e.ak.fbcdn.net.
+an.tacoda.net.
+horizonsisg.com.s8b2.psmtp.com.
+m.adnxs.com.
+ejabat.google.com.
+armonia-avm.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+tcsinow.com.
+img125.hotlinkimage.com.
+www.readytogo.net.
+d2094182.xoom.it.
+ma61-c.analytics.edgesuite.net.
+www.gstatic.com.
+www.namazzamani.net.
+buckshotboredom.com.
+a.root-servers.net.
+ay84moqm1.c19d4d4q.
+176.206.132.190.in-addr.arpa.
+linkhelp.clients.google.com.
+angle-droit.fr.
+99.145.6.186.in-addr.arpa.
+wpad.
+fotoria.ru.
+205.41.9.109.in-addr.arpa.
+skins.gmodules.com.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+malaysia.answers.yahoo.com.
+geo.yahoo.com.
+maps.google.es.
+rcp.na.blackberry.com.
+www.maillife.co.uk.
+enterarteregional.blogspot.com.
+90.64.170.189.in-addr.arpa.
+www.apogee-web-consulting.com.
+api.facebook.com.
+tossersite.com.
+201.248.233.201.in-addr.arpa.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+tracken.dolphin-browser.com.
+105.102.158.178.in-addr.arpa.
+es-es.com.wmlwww.login.facebook.com.
+tiny.cc.
+227.131.115.200.in-addr.arpa.
+www.facebook.com.
+52.238.90.200.in-addr.arpa.
+a.root-servers.net.
+teredo.ipv6.microsoft.com.
+www.faceb.
+www.webgamegame.com.
+hosteltur.com.
+mjls.org.
+static.ak.connect.facebook.com.
+safebrowsing.clients.google.com.
+www.okcupid.com.
+fbcdn-profile-a.akamaihd.net.
+newsrss.bbc.co.uk.
+api.nanigans.com.
+www.20minutos.es.
+searchclient.live.net.
+www.weekday.se.
+img.youtube.com.
+mail.mfworks.com.
+www.antivirus.com.
+graph.facebook.com.
+static-0.farmville.zgncdn.com.
+external.ak.fbcdn.net.
+215.162.134.190.in-addr.arpa.
+28.42.161.222.in-addr.arpa.
+search.twitter.com.
+toolbarqueries.google.com.
+a5.sphotos.ak.fbcdn.net.
+146.209.120.24.in-addr.arpa.
+b7g9v4d4s.i51f3w4b.
+zibzfwpdz.87it.
+66.185.9.186.in-addr.arpa.
+iceauto.ru.
+_535_21_7.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+42.208.159.189.in-addr.arpa.
+aljazeera.net.
+scores.mochimedia.com.
+blu.stc.s-msn.com.
+b48mxdwk47ktl28j36k17d50buhxk57p62k67lrou.com.
+www.smarturl.it.
+249.102.244.190.in-addr.arpa.
+13.228.171.69.in-addr.arpa.
+60.6.55.85.in-addr.arpa.
+thewimshurstsmachine.com.
+valf.ru.
+18.39.25.88.in-addr.arpa.
+zrres.zt.energy.gov.ua.
+protocolocomentarios.blogspot.com.
+16.59.80.199.in-addr.arpa.
+hub.video.msn.com.
+h.live.com.
+lewer.com.s7b2.psmtp.com.
+ar-ar.facebook.com.
+ar.answers.yahoo.com.
+164.179.43.201.in-addr.arpa.
+neurosis2.concordia.ca.
+a.root-servers.net.
+external.ak.fbcdn.net.
+comunidades.esmas.com.
+ajax.googleapis.com.
+ad-g.doubleclick.net.
+37.145.248.189.in-addr.arpa.
+msk.aeroflot.ru.
+8.193.143.24.in-addr.arpa.
+exchange.highwoods.com.
+static.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+time-a.nist.gov.
+17-courier.push.apple.com.
+blu.stj.s-msn.com.
+ns4.combell.net.
+191.196.233.118.in-addr.arpa.
+es.888.com.
+mail.rexcargo.com.
+180.20.168.192.in-addr.arpa.
+afisha.ru.
+teredo.ipv6.microsoft.com.
+_376_15_3.
+pixel.facebook.com.
+r._dns-sd._udp.home.
+static.ak.fbcdn.net.
+you-have-what-it-takes.com.
+jaringnews.com.
+ar.games.yahoo.com.
+148.64.156.93.in-addr.arpa.
+sgsdg.com.
+solta.com.
+static.ak.fbcdn.net.
+resources.alibaba.com.
+ssl.gstatic.com.
+www.sahafa.com.
+inbound.ffta.com.netsolmail.net.
+p0b.ru.
+www.xvideos.com.
+ajax.googleapis.com.
+optimized-by.rubiconproject.com.
+forums.hennapage.com.
+audio-libro.info.
+www.laverdad.es.
+finescale.com.s8b1.psmtp.com.
+mail.inflightcareers.com.
+242.46.69.190.in-addr.arpa.
+138.18.168.192.in-addr.arpa.
+vap1sea1.lijit.com.
+mail.
+pixel.mathtag.com.
+mail.copyandcamera.com.
+_579_98_6.
+photos-b.ak.fbcdn.net.
+unasesentona.blogspot.com.
+boards.dingoonity.org.
+games.piczo.com.
+talk.google.com.
+funcampco.ca.
+sp.cwfservice.net.
+f.facemoods.com.
+uniccos.com.
+newsletter.o2world.de.
+22.169.15.189.in-addr.arpa.
+amer.rel.msn.com.
+accounts.google.com.
+timmtytjhjdfj.blogspot.com.
+160.125.150.24.in-addr.arpa.
+bloodshedzine-spain.blogspot.com.
+dns.msftncsi.com.
+alma.net.
+photos-g.ak.fbcdn.net.
+www.ypmadserver.com.
+profile.ak.fbcdn.net.
+81.95.171.189.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+mail.twcinci.com.
+128.143.60.186.in-addr.arpa.
+safebrowsing-cache.google.com.
+sp.iphone-unlocker-pro.com.
+159.223.137.190.in-addr.arpa.
+www.update.microsoft.com.
+dapez.com.ar.
+www.cobraboxing.com.
+teredo.ipv6.microsoft.com.
+col.stj.s-msn.com.
+www.modern-canvas-art.com.
+static.cbox.ws.
+a8.sphotos.ak.fbcdn.net.
+mail.qzip.net.
+ds2.uniblue.com.
+mail.dd-rd.ca.
+12.10.162.46.in-addr.arpa.
+s.youtube.com.
+t2.gstatic.com.
+www.ssclg.com.
+sp.cwfservice.net.
+es.wikipedia.org.
+_759_60_5.
+elite-finance.com.
+transamtruck.com.
+i4.ytimg.com.
+xanky.com.
+pixel.quantserve.com.
+43.244.236.189.in-addr.arpa.
+filter1.presco-6.mailguard.com.au.
+corporate.ford.com.
+honor.americanheart.org.
+146.238.71.77.in-addr.arpa.
+motor.superdeporte.es.
+art-hist.ru.
+photos-g.ak.fbcdn.net.
+tracker.torrentbay.to.
+www.crowngroup.com.au.
+loading.retry.widdit.com.
+1.132.204.187.in-addr.arpa.
+70.163.144.189.in-addr.arpa.
+www.maincor.de.
+www.blogger.com.
+cineinblog.atarde.com.br.
+safebrowsing-cache.google.com.
+mp4-i7-1b.perfectgirls.net.
+a8.sphotos.ak.fbcdn.net.
+www.imobisoft.co.uk.
+ebay-volgograd.ru.
+82.98.140.175.in-addr.arpa.
+kotaku.com.
+cdn.api.twitter.com.
+clients2.google.com.
+easy-youtube-video-downloader.en.softonic.com.
+alpineutahrealty.com.
+a.root-servers.net.
+newt7.adultadworld.com.
+bjv9xcng.emltrk.com.
+www.cpxadspace.com.
+_247_65_6.
+web.educastur.princast.es.
+183.121.242.201.in-addr.arpa.
+51.80.4.186.in-addr.arpa.
+gfx2.hotmail.com.
+support.google.com.
+243.164.8.95.in-addr.arpa.
+www.premiershipwallpapers.com.
+a4.sphotos.ak.fbcdn.net.
+proxy-relay1.red.net.
+auth.shequ.10086.cn.
+enj9u3ka6.e74h6t4v.
+4rgk5srwp.d39k9p3b.
+video1.hobbico.com.
+www.djtonypeopleshousemusic.com.
+www.aradani.com.
+a.root-servers.net.
+ns1.itdienstleistung.at.
+photos-e.ak.fbcdn.net.
+www.hondunet.com.
+abco01.abcoproducts.com.
+vi.ebaydesc.com.
+43.214.85.209.bl.spamcop.net.
+mb.sympatico.ca.
+92.122.168.192.in-addr.arpa.
+zh-cn.facebook.com.
+18.181.84.59.in-addr.arpa.
+www.youtube.com.
+alta-print.com.
+geo.messenger.services.live.com.
+102.120.74.190.in-addr.arpa.
+gruponuevotramo.blogspot.com.
+secure.shared.live.com.
+12.38.225.189.in-addr.arpa.
+postal.essd.northgrum.com.
+fr-fr.facebook.com.
+grayen1.com.
+msc.wlxrs.com.
+a.root-servers.net.
+i3.ytimg.com.
+www.telenovelasgratis.com.
+unitrac.com.
+secure1.zynga.com.
+superfoodinfos.com.
+profile.ak.fbcdn.net.
+d2055595.instant.xoom.it.
+moviesonlinehere.com.
+a.root-servers.net.
+ads.bluelithium.com.
+_898_68_2.
+axismedia.co.uk.
+static.ak.fbcdn.net.
+upload.7ozn.com.
+ajax.googleapis.com.
+inty.net.
+ntp1.dlink.com.
+wvnvaxbd.com.
+a.root-servers.net.
+accounts.google.com.
+hu.wikipedia.org.
+gyptech.on.ca.
+firewall.idealcomponents.net.
+l.sharethis.com.
+23qnyctn8.13eh.
+www.imdb.com.
+102.143.254.180.in-addr.arpa.
+p7677.cdngc.net.
+travel.yahoo.com.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+fbcdn-profile-a.akamaihd.net.
+www.googletagservices.com.
+60.181.58.187.in-addr.arpa.
+a.root-servers.net.
+223.169.160.189.in-addr.arpa.
+183.36.229.189.in-addr.arpa.
+0-id-w.channel.facebook.com.
+sites.google.com.
+worelliesbrdm.su.
+fpdownload2.macromedia.com.
+developers.facebook.com.
+christophermills.uk.com.
+_259_22_5.
+a7.sphotos.ak.fbcdn.net.
+135.71.144.181.in-addr.arpa.
+www.flashgameport.com.
+d3lvr7yuk4uaui.cloudfront.net.
+vehiculos-usados.vivastreet.com.mx.
+coemsa.com.
+teredo.ipv6.microsoft.com.
+www.mariadeagreda.org.
+a8.sphotos.ak.fbcdn.net.
+135.62.177.189.in-addr.arpa.
+a.root-servers.net.
+time.stdtime.gov.tw.
+teaworld.ru.
+www.facebook.com.
+www.designerblogs.com.
+www.autumndewilde.com.
+ads.revsci.net.
+securemail.pmsyscorp.com.
+tt.wikipedia.org.
+gateway1i.kewill.com.
+www.adamtaylorphotography.com.
+www.discovery.com.
+opml.radiotime.com.
+api.geo.kontagent.net.
+dns.msftncsi.com.
+teredo.ipv6.microsoft.com.
+vuelos.viajes.hispavista.com.
+94.117.247.190.in-addr.arpa.
+plus.google.com.
+a.root-servers.net.
+media.roportal.ro.
+jigsy.com.
+api.youversion.com.
+rad.msn.com.
+www.tetactics.com.
+www.manualesdetodo.net.
+dingenvanlia.nl.
+www.soundofdrowning.com.
+developers.facebook.com.
+www.smoder.com.
+239.184.11.190.in-addr.arpa.
+cs11067.vk.com.
+m.facebook.com.
+a997.mm1.akamai.net.
+tutu.es.
+multimedia.eluniversal.com.mx.
+feim.com.s7a1.psmtp.com.
+23.1.168.192.in-addr.arpa.
+punkska.ru.
+safebrowsing-cache.google.com.
+s1-powerpoint.vo.msecnd.net.
+fbcdn-profile-a.akamaihd.net.
+225.32.57.187.in-addr.arpa.
+199.244.83.200.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+www.gnuart.net.
+242.183.168.192.in-addr.arpa.
+api.facebook.com.
+www.incredimages.com.
+ad-g.doubleclick.net.
+www.unonoticias.com.
+www.tuempresaenlared.net.
+henna-boy.co.uk.
+hi-audit.ru.
+236.84.147.79.in-addr.arpa.
+friskygeek.com.
+orionika.ru.
+designcentrix.com.
+s-external.ak.fbcdn.net.
+1671.live.streamtheworld.com.
+int.search-results.com.
+www.df.gob.mx.
+www.healthcare.uci.edu.
+external.ak.fbcdn.net.
+www.kiddycade.com.
+mail.gek.ru.
+teredo.ipv6.microsoft.com.
+dtboot.orbitdownloader.com.
+geoip.vmn.net.
+10412569.mx1.autocarindia.com.
+tmmc.ca.
+100.151.182.93.in-addr.arpa.
+t2.gstatic.com.
+a.root-servers.net.
+www.adobe.com.
+a8.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+118.242.143.187.in-addr.arpa.
+_449_64_2.
+12.206.83.67.in-addr.arpa.
+www.google.com.
+tts.se.
+www.facebook.com.
+s08.flagcounter.com.
+www.winespectator.com.
+27.181.157.186.in-addr.arpa.
+twitter.com.
+port.state.de.us.s7b1.psmtp.com.
+web.buddytv.netdna-cdn.com.
+www.tiffanyco.biz.
+edge.quantserve.com.
+ar-ar.facebook.com.
+ads2.msads.net.
+68.132.170.189.in-addr.arpa.
+devisa.ru.
+twitter.com.
+www.google.com.
+a.root-servers.net.
+a.root-servers.net.
+faiting.ru.
+sniderinc.com.s5a2.psmtp.com.
+i2.ytimg.com.
+rblns68.mailshell.net.
+dns.msftncsi.com.
+35.53.92.186.in-addr.arpa.
+prod2.rest-notify.msg.yahoo.com.
+static.ak.fbcdn.net.
+i3.ytimg.com.
+embarqmill.com.
+safebrowsing.clients.google.com.
+whos.amung.us.
+192.27.132.190.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+v13.nonxt3.c.youtube.com.
+153.239.158.200.in-addr.arpa.
+153.125.65.189.in-addr.arpa.
+img822.imageshack.us.
+ads.creafi-online-media.com.
+www.facebook.com.
+www.belkin.com.
+mx.west.cox.net.
+goodfilesloader.ru.
+83.149.188.189.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+7.150.173.201.in-addr.arpa.
+aol.com.
+mail.dovetailenterprises.co.uk.
+54.167.46.189.in-addr.arpa.
+api.zynga.com.
+ns1.cheat.net.ru.
+chccig.com.
+i3.ytimg.com.
+100.204.226.88.in-addr.arpa.
+android.clients.google.com.
+profile.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+75.79.141.201.in-addr.arpa.
+209.253.199.187.in-addr.arpa.
+g-pixel.invitemedia.com.
+safebrowsing.clients.google.com.
+mail.conio.net.
+www.opendeco.es.
+144.31.210.201.in-addr.arpa.
+mail.leshak.perm.ru.
+a.root-servers.net.
+infanciayotrascosas.blogspot.com.
+gs02.supremacy1914.com.
+109.103.114.177.in-addr.arpa.
+denis.stalker.h3q.com.
+cydia.saurik.com.
+dns.msftncsi.com.
+49.222.171.189.in-addr.arpa.
+cplog.flashget.com.
+duck.ru.
+rwillustrator.blogspot.com.
+news.google.com.mx.
+www.nudismlife.com.
+www.miami-airport.com.
+rad.msn.com.
+creative.ak.fbcdn.net.
+a1408.w43.akamai.net.
+www.blackthickgirls.com.
+googleads.g.doubleclick.net.
+129.163.145.189.in-addr.arpa.
+a1003.w41.akamai.net.
+mailout.cop-inc.com.
+profile.ak.fbcdn.net.
+ebiparaguay.blogspot.com.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mzmqh54k17exiwgxp22fuhuhyozntjrm69ky.com.
+82.138.25.187.in-addr.arpa.
+touch.facebook.com.
+pigrush.reigndesign.com.
+ieonlinews.microsoft.com.
+www.youtube.com.
+www.shbabelyom.com.
+www.facebook.com.
+uvg1zsa12.70pl.
+8hlns7iy2.o89k3z6q.
+127.16.244.189.in-addr.arpa.
+219.155.161.189.in-addr.arpa.
+dns.msftncsi.com.
+c-0.19-a309f481.483.1518.19d3.3ea1.410.0.6tri6qwwfgscawewswfsjz2qk6.avqs.mcafee.com.
+www.negotips.com.
+celiac-disease.emedtv.com.
+151.175.82.190.in-addr.arpa.
+checkip.dyndns.org.
+www.bywifi.com.
+a5.sphotos.ak.fbcdn.net.
+christineestima.wordpress.com.
+stats.wordpress.com.
+i4.ytimg.com.
+www.twitter.com.
+ws.tapjoyads.com.
+65.156.109.118.in-addr.arpa.
+fastonlineusers.com.
+tds.traforet.ru.
+dsn5.d.skype.net.
+fourwinds.ru.
+www.zonaoriente.com.
+i1.ytimg.com.
+140.209.225.189.in-addr.arpa.
+www.facebook.com.
+73.48.136.98.in-addr.arpa.
+asrs.net.
+monet.ru.
+netmcr.com.
+zelda.wikia.com.
+pagead2.googlesyndication.com.
+a7.sphotos.ak.fbcdn.net.
+as.digiturk.com.tr.
+meussshomenss.blogspot.com.
+figlobal.112.2o7.net.
+www.facebook.com.
+mail.pirate-party.ru.
+dl-desktop-apps.sonyericsson.com.
+time.stdtime.gov.tw.
+mx.megaproduct.com.
+apps.facebook.com.
+fbcdn-sphotos-a.akamaihd.net.
+190.239.5.200.in-addr.arpa.
+um12.eset.com.
+danhba.bao-anh.com.
+grovesconstruction.com.
+ricoh.com.
+10f.ru.
+a3.sphotos.ak.fbcdn.net.
+esohavuelto.blogspot.com.
+181.145.67.76.in-addr.arpa.
+time.apple.com.
+16.169.156.201.in-addr.arpa.
+228.218.101.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+voteview.com.
+98.49.168.189.in-addr.arpa.
+110.91.53.186.in-addr.arpa.
+a.root-servers.net.
+145.86.181.190.in-addr.arpa.
+apps.facebook.com.
+oilandgasvacancy.com.
+download342.avast.com.
+hillsace.com.
+outsors.com.
+cocovishop.com.
+news.yahoo.com.
+hi-in.facebook.com.
+cdn1.widdit.com.
+53.249.223.201.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+.
+creative.ak.fbcdn.net.
+billing.sharo4ka.ru.
+www.blackberry.com.
+www2.edi7.lu.
+tc.v22.cache1.c.youtube.com.
+business.shop.ebay.com.
+nivelexperto.com.
+119.203.177.190.in-addr.arpa.
+www.google.com.mx.
+www.girlfriends.bestnudethumbs.com.
+proquestcombo.safaribooksonline.com.
+vsimki.ru.
+www.anime-channel.org.
+g.ceipmsn.com.
+edge.sharethis.com.
+apps.facebook.com.
+www.bodyrock.tv.
+botones.blogalaxia.com.
+libya11.com.
+mk.cam4.com.
+streetwisemaps.com.
+static.ak.fbcdn.net.
+www.facebook.com.
+electronicaportable.blogspot.com.
+addons.mozilla.org.
+developer.sprint.com.
+googleads.g.doubleclick.net.
+lkcdn.com.
+genius.itunes.apple.com.
+a.root-servers.net.
+scenicwolfresort.com.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+corp.39.net.
+smtp2.aaanorthpenn.com.
+fxfeeds.mozilla.com.
+connect.facebook.net.
+ad.adnetwork.net.
+egyutt.hu.
+uruguay.clasificadoya.com.
+ad.yieldmanager.com.
+v6.cache1.googlevideo.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+amega.com.
+a.root-servers.net.
+mtalk.google.com.
+_108_06_0.
+x04.o.ismtp.integra.net.
+markevin.fan-sites.org.
+linamar.ca.
+accessatt.net.
+pixel.facebook.com.
+khmervn.com.
+a.root-servers.net.
+www.celsa.fr.
+immortalseed.com.
+photos-a.ak.fbcdn.net.
+franke.com.
+38.voncp.com.
+gorod.dn.ua.
+cuentosdeprincesas.blogia.com.
+amandadecadenet.com.
+www.arcanos.org.
+reddit.com.
+ajax.googleapis.com.
+www.bogotaoccidente.com.
+noik.ru.
+pixel.facebook.com.
+50.170.153.201.in-addr.arpa.
+apis.google.com.
+tgmedia.ru.
+www.stc-law.com.
+arts.hku.hk.
+fbcdn-photos-a.akamaihd.net.
+lemondrealty.com.
+on.fb.me.
+google.com.
+166.120.3.121.in-addr.arpa.
+smaart.com.au.
+113.232.26.85.in-addr.arpa.
+translate.google.com.mx.
+external.ak.fbcdn.net.
+es.scribd.com.
+altfarm.mediaplex.com.
+www.facebook.com.
+secure.oldgoesyoung.com.
+mail.timberlineenergy.com.
+images2.cinemaki.com.
+4o:gzrhbj.88ic.
+awesmoe.files.wordpress.com.
+b-0.19-a3090009.8011081.1518.19d3.3ea1.410.0.6j7lctstkz7wl87kq7wnadkpp6.avqs.mcafee.com.
+dns.msftncsi.com.
+alphashirt.com.
+cdn.adventofdeception.com.
+149.69.221.72.in-addr.arpa.
+0-327.channel.facebook.com.
+232.234.172.190.in-addr.arpa.
+google.com.
+214.205.106.187.in-addr.arpa.
+client-software.real.com.
+55.120.207.186.in-addr.arpa.
+165.28.120.84.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.danaestratou.gr.
+hiltontrinidad.com.
+www.decorshome.net.
+mail.google.com.
+a.root-servers.net.
+www.facebook.com.
+www.irnike.com.
+itunes.com.
+www.feartofaithclothing.com.
+ad.yieldmanager.com.
+mail.dynamac-usa.com.
+www.whathealth.com.
+i2.ytimg.com.
+www.salahtoons.net.
+u31.eset.com.
+time.chttl.com.tw.
+smtp.prestigehotels.com.
+262.com.
+110.43.3.173.in-addr.arpa.
+128.253.212.67.in-addr.arpa.
+www.ceain.acoge.org.
+24.228.171.69.in-addr.arpa.
+tappeconstruction.com.
+pc-drivers.fr.
+googlemail.l.google.com.
+ds.addthis.com.
+www.mundonick.com.
+pixel.facebook.com.
+horsethatleaps.com.
+met.adwhirl.com.
+113.32.25.201.in-addr.arpa.
+a.root-servers.net.
+www.fanreviews.com.
+a.root-servers.net.
+114.152.159.189.in-addr.arpa.
+a0.twimg.com.
+www.tidanhotels.com.
+www.mirrordev.com.
+static.ak.fbcdn.net.
+ih2.gamecopyworld.com.
+keridita11-11.blogdiario.com.
+blogs.miarroba.es.
+dns.msftncsi.com.
+uchypbz57.57mo.
+www.internetdownloadmanager.com.
+152.193.33.177.in-addr.arpa.
+beauty.interremi.com.
+243.89.158.189.in-addr.arpa.
+nccp-wii.cloud.netflix.net.
+googleads.g.doubleclick.net.
+huhu.com.
+_525_54_6.
+rv.ginyas.com.
+105.206.77.200.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.turkcraft.com.
+a4.mzstatic.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+cymynebgzyr.info.
+211.115.64.123.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+hog.assets1.zgncdn.com.
+www.adobe.com.
+www.chinavista.com.
+zeus.saarproperties.com.
+s0.2mdn.net.
+en-us.fxfeeds.mozilla.com.
+cityvillefb1.static.zgncdn.com.
+34.42.61.186.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+feeds.feedburner.com.
+gate.atk-media.ru.
+groups.google.com.mx.
+214.39.15.187.in-addr.arpa.
+orcart.facebook.com.
+translate.google.com.mx.
+129.13.151.79.in-addr.arpa.
+www.imdb.com.
+thumbs2.ebaystatic.com.
+motherboards.mbarron.net.
+www.facebook.com.
+i3.ytimg.com.
+7i3cveei3.58di.
+15-courier.push.apple.com.
+www.burialinsurance.com.
+a1.sphotos.ak.fbcdn.net.
+tms30.icrc.trendmicro.com.
+www.cocina.org.
+fbcdn-photos-a.akamaihd.net.
+nus.cdn.c.shop.nintendowifi.net.
+www.strangemag.com.
+secure-sg.imrworldwide.com.
+maps.google.com.
+adx.allstar.cz.
+translation.toolbar.conduit-services.com.
+www.mozilla.com.
+106.48.51.188.in-addr.arpa.
+mail.desupernet.com.
+0-staging.channel.facebook.com.
+checkip.dyndns.org.
+a.root-servers.net.
+pad2.whstatic.com.
+130.2.45.70.in-addr.arpa.
+28.212.139.190.in-addr.arpa.
+89.114.131.81.in-addr.arpa.
+sefram.testoon.com.
+a.root-servers.net.
+developers.facebook.com.
+105.185.73.190.in-addr.arpa.
+plus.google.com.
+189.188.217.87.in-addr.arpa.
+docs.google.com.
+tags.expo9.exponential.com.
+cdn.api.twitter.com.
+_080_37_3.
+a771.da1.akamai.net.
+static.ak.fbcdn.net.
+mail1.cruzdelsur.com.
+newtex.ru.
+elhadaqueteje.blogspot.com.
+corian.es.
+22.144.67.76.in-addr.arpa.
+safebrowsing.clients.google.com.
+a.root-servers.net.
+b.googlemail.l.google.com.
+www.designworldonline.com.
+235.215.196.74.in-addr.arpa.
+52.239.51.190.in-addr.arpa.
+email.americanexpress.com.
+googleapis.l.google.com.
+210.197.120.59.in-addr.arpa.
+225.29.17.190.in-addr.arpa.
+www.google.com.mx.
+ar-ar.facebook.com.
+www.gorillas.org.
+safebrowsing-cache.google.com.
+www.nuigalway.ie.
+224.60.124.95.in-addr.arpa.
+crisfusterber.blogspot.com.
+231.151.183.189.in-addr.arpa.
+a.root-servers.net.
+hotmail.com.
+b-womeninamericanhistory17.blogspot.com.
+mediaws.ign.com.
+a.root-servers.net.
+www.moevenpick-hotels.com.
+smtp.sportsmanswarehouse.com.
+cn1.redswoosh.akadns.net.
+mail.kuban.su.
+_479_43_2.
+a7.sphotos.ak.fbcdn.net.
+partner.googleadservices.com.
+121.184.99.190.in-addr.arpa.
+ksn1-12-part1.kaspersky-labs.com.
+www.chinaoffshore.net.
+v12.nonxt7.c.youtube.com.
+dns.msftncsi.com.
+email.sigmadesign.net.
+a1.twimg.com.
+ntfpm.cn.
+.
+a.root-servers.net.
+js.revsci.net.
+labteh.ru.
+www.4h4.com.
+olhandoaooeste.blogspot.com.
+yb45.yearbookreunions.com.
+a6.sphotos.ak.fbcdn.net.
+3cp9lcoq32dpn-c.c.yom.mail.yahoo.com.
+158.164.82.201.in-addr.arpa.
+198.212.89.186.in-addr.arpa.
+www.warnermusic.com.mx.
+check.sanasecurity.com.
+support.google.com.
+eznam.cz.
+www.chinnahom.com.
+www.lebonangle.com.
+static.ak.fbcdn.net.
+251.69.136.186.in-addr.arpa.
+edge.quantserve.com.
+ksn2-12.kaspersky-labs.com.
+81.30.26.151.in-addr.arpa.
+purposemagazine.com.
+static-cdn2.ustream.tv.
+olcuk.com.
+twitter.com.
+crazycollecting.wordpress.com.
+r.mzstatic.com.
+162.167.235.190.in-addr.arpa.
+www.nissinfoods.co.jp.
+cbbonline.com.s8b2.psmtp.com.
+243.220.156.189.in-addr.arpa.
+dns.msftncsi.com.
+a.root-servers.net.
+caslonsoft.com.
+platform.twitter.com.
+136.74.120.95.in-addr.arpa.
+js2.wlxrs.com.
+tinypic.com.
+sp.cwfservice.net.
+nygrants.com.inbound15.mxlogic.net.
+.
+kcapex.com.s8b1.psmtp.com.
+inbound.toiletwater.net.netsolmail.net.
+mail1.lowes.com.
+profile.ak.fbcdn.net.
+106.11.18.190.in-addr.arpa.
+static.ak.fbcdn.net.
+www.facebook.com.
+mob.adwhirl.com.
+200.253.42.181.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.connect.facebook.com.
+www.apple.com.
+sigmatestudio.com.
+a8.sphotos.ak.fbcdn.net.
+cteainc.com.
+profile.ak.fbcdn.net.
+bjc.bash.ru.
+yahoo.com.
+nextenergycorp.com.
+avtobog.com.
+content.yieldmanager.edgesuite.net.
+beerbloggers.ning.com.
+sbcglobal.net.
+www.julio.com.
+www.facebook.com.
+school.edu.ru.
+avtia.com.
+23.52.167.75.in-addr.arpa.
+tecnologia.starmedia.com.
+91.12.247.190.in-addr.arpa.
+sibur.nnov.ru.
+jaxsuns02.jaxsuns.com.
+e566.b.akamaiedge.net.
+photos-g.ak.fbcdn.net.
+delishworld.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.buysearcher.com.
+a1415.phobos.apple.com.
+thumbs.4chan.org.
+code.jquery.com.
+9.174.224.77.in-addr.arpa.
+a.root-servers.net.
+facebook.conduitapps.com.
+webcache.googleusercontent.com.
+camaraymicrofonos.blogspot.com.
+csi.gstatic.com.
+224.129.190.70.in-addr.arpa.
+connect.facebook.net.
+teredo.ipv6.microsoft.com.
+pcbut.com.tw.
+plusone.google.com.
+62.110.218.83.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+gol.com.
+234147.r.msn.com.
+tunnel.cfw.trustedsource.org.
+player.vimeo.com.
+mmx.fangtech.net.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+mx.ingenuitypro.com.
+api.facebook.com.
+t3.gstatic.com.
+77.111.248.88.in-addr.arpa.
+204.211.50.190.in-addr.arpa.
+magumbo-anime.blogspot.com.
+www.toxicfreenc.org.
+zrgzmjx8f.c42w9e1w.
+remote.legendsinconcert.com.
+www.google.com.
+wlyjhjjcttw.cc.company.com.
+toolbarqueries.google.com.
+cdn.api.twitter.com.
+news.bbc.co.uk.
+d2104037.xoom.it.
+photos-b.ak.fbcdn.net.
+187.24.171.201.in-addr.arpa.
+ilam.irna.ir.
+d.proadsdirect.com.
+mail.kungfudesign.com.
+a4.da1.akamai.net.
+smtp.rainbowsplash.com.
+a.root-servers.net.
+gleaf.net.
+koranmp3.ru.
+www.movieactors.com.
+www.oilman.com.au.
+ib.adnxs.com.
+vu.sel.sony.com.
+ffupdate.engine.conduit-services.com.
+she.yahoo.com.
+www.facebook.com.
+iczdwp5o8.b19y7y4c.
+usa.nedstatpro.net.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+65.225.220.190.in-addr.arpa.
+32.144.135.105.in-addr.arpa.
+t.co.
+rs178l32.rapidshare.com.
+s.ytimg.com.
+bikningallygr.nu.
+autos.latino.msn.com.
+hr-consult.ru.
+2iazzg3ne.z50f7l3i.
+www.gedonet.com.
+voyeur4you.com.hypestat.com.
+legalcity.es.
+photos-e.ak.fbcdn.net.
+aln.su.
+171.180.27.116.in-addr.arpa.
+sitnstitch.com.
+www.didtheyreadit.com.
+exclusive-restaurants.com.
+plus.google.com.
+a2.sphotos.ak.fbcdn.net.
+215.160.86.186.in-addr.arpa.
+magentmng.alipay.com.
+www.xvideos.com.
+johnnydeppargentina.350.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+27.228.115.186.in-addr.arpa.
+186.95.159.82.in-addr.arpa.
+s.youtube.com.
+_470_90_6.
+yahoo.de.
+_554_01_5.
+a.root-servers.net.
+94.36.86.85.in-addr.arpa.
+a.root-servers.net.
+saul.nueve.com.mx.
+perfectboundstudio.blogspot.com.
+stroyholding.ru.
+ocsp.verisign.com.
+gdata.youtube.com.
+2.205.218.76.in-addr.arpa.
+4.162.132.187.in-addr.arpa.
+10.46.172.186.in-addr.arpa.
+mayfairmills.com.
+photos-c.ak.fbcdn.net.
+evt.collarity.com.
+120.234.171.189.in-addr.arpa.
+forofashion.com.
+0-68.channel.facebook.com.
+touch.facebook.com.
+215.157.15.189.in-addr.arpa.
+absolutetitleagency.com.
+a.root-servers.net.
+.
+dns.msftncsi.com.
+mail.delfinoinsulation.com.
+40.142.171.78.in-addr.arpa.
+delivery.simplytechnology.net.
+a2.sphotos.ak.fbcdn.net.
+www.latimes.com.
+0-if-w.channel.facebook.com.
+prutopical.com.
+4.50.194.190.in-addr.arpa.
+www.foxsportsla.com.
+tumblrplug.com.
+comicmexicano.blogspot.com.
+external.ak.fbcdn.net.
+235.151.29.64.in-addr.arpa.
+dns.msftncsi.com.
+0-167.channel.facebook.com.
+mishay.blogspot.com.
+rmcsda.org.s10a2.psmtp.com.
+348.ch.meebo.com.
+dr._dns-sd._udp.lan.
+smtp.rsnlt.com.
+nljyhq5lv.18cr.
+214.36.149.17.in-addr.arpa.
+www.protege323.com.
+www.qstraint.com.
+i12.photobucket.com.
+api.aizheke.com.
+demosite.ondemand.flumotion.com.
+d2056450.instant.xoom.it.
+www.socialgrowthtechnologies.com.
+a.root-servers.net.
+www.buenscoring.com.
+www.apex.com.om.
+js.revsci.net.
+external.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+www.youtube.com.
+150.216.13.201.in-addr.arpa.
+c7.zedo.com.
+glyde.com.
+accounts.google.com.
+shfpc.com.
+www.enjoysudoku.com.
+eldorado.ru.
+www.lacaja.com.ar.
+_384_70_5.
+a.root-servers.net.
+widgets.5z5.com.
+mail.moellergroup.com.
+www.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+switchboard.real.com.
+info.automotix.net.
+photos-c.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+242.71.166.190.in-addr.arpa.
+3cp9lcoq32dpn-c.c.yom.mail.yahoo.com.
+www.hyperpromote.com.
+google.com.
+its-outrageous.com.
+89.82.175.200.in-addr.arpa.
+i-7917323e.us-west-1a.service.amazonsilk.com.
+sanantoniodeltachira.olx.com.ve.
+timeline.leagueoflegends.com.
+www.precisioncounter.com.
+www.sanvalentinsebaila.es.
+nacion.docpit.com.
+sgp.gascom.ru.lan.
+support.google.com.
+www.htx.ro.
+hubbell-premise.com.s7b2.psmtp.com.
+dallas-land.com.
+www.photoscape.org.
+www.knucklebonz.com.
+content.yieldmanager.edgesuite.net.
+developers.facebook.com.
+38.22.18.190.in-addr.arpa.
+m.youtube.com.
+www.blogsandocs.com.
+orellana.mundoanuncio.ec.
+xbc9r8jli.56cz.
+history.cultural-china.com.
+s.imwx.com.
+www.ampalucienbriet.blogspot.com.
+www.topappsquare.com.
+josemartinezbolio.blogspot.com.
+a4.sphotos.ak.fbcdn.net.
+www.google.com.
+113.178.174.190.in-addr.arpa.
+gfx1.hotmail.com.
+175.165.176.190.in-addr.arpa.
+www.culturaclick.com.
+foros.toxico-pc.com.
+acquirelawer.org.
+133.253.56.190.in-addr.arpa.
+s4.mcstatic.com.
+27.150.8.200.in-addr.arpa.
+13-courier.push.apple.com.
+loading1.widdit.com.
+actaware.it.
+stilettostyle.com.
+wiki.pentaho.com.
+_ldap._tcp.
+de-de.facebook.com.
+clients2.google.com.
+stats.panet.co.il.
+25.4.168.192.in-addr.arpa.
+wrowsezns.52au.
+a896.phobos.apple.com.edgesuite.net.
+www.cheaphandbagsuk.co.uk.
+a8.sphotos.ak.fbcdn.net.
+rblns81.mailshell.net.
+157.60.137.92.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+hes.ucfsd.org.
+jandex.ru.
+keshmuney.com.
+jacqueslowe.com.
+169.245.88.200.in-addr.arpa.
+static.ak.connect.facebook.com.
+lipstitsteethhips.blogspot.com.
+pentax-k100d.info.
+194.46.253.218.in-addr.arpa.
+mx.msn.recepedia.com.
+www.laceylady.com.
+www.youtube.com.
+www.cinepolis.com.
+5.43.14.88.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+149.205.131.24.in-addr.arpa.
+sputnikmaps.mail.ru.
+sc17.rules.mailshell.net.
+6.745565e-02.com.
+220.78.211.108.in-addr.arpa.
+decipher.me.uk.
+j003.palmws.com.
+www.proc.britac.ac.uk.
+don.com.s9a2.psmtp.com.
+mx.coldwellbankerthomas.com.
+www.tyler.com.mx.
+integral.com.au.
+hairloss.ygoy.com.
+33.144.22.186.in-addr.arpa.
+rtl.feedsportal.com.
+a3.sphotos.ak.fbcdn.net.
+m.facebook.com.
+developers.facebook.com.
+col.stb00.s-msn.com.
+greedykidz.net.
+a8.sphotos.ak.fbcdn.net.
+www.shoptoys.ru.
+cdn.api.twitter.com.
+fc09.deviantart.net.
+towncountryrealty.net.
+ns2.tktor.ru.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+bajaryoutube.com.
+a.root-servers.net.
+www.domedeep.com.
+23-courier.push.apple.com.
+images02.olx-st.com.
+a1005.w42.akamai.net.
+a.root-servers.net.
+sslmit.unibo.it.
+k.ilius.net.
+196.50.122.84.in-addr.arpa.
+conduit.anybodyoutthere.com.
+partner.googleadservices.com.
+www.okcupid.com.
+ibogroups.com.
+www.google.com.
+blgspb.ru.
+cleanrun.com.
+giancarloescalante.blogspot.com.
+a8.sphotos.ak.fbcdn.net.
+player.vimeo.com.
+www.meinprospekt.de.
+a4.sphotos.ak.fbcdn.net.
+csc3-2010-crl.verisign.com.
+upload.facebook.com.
+70.28.138.24.in-addr.arpa.
+150.151.51.188.in-addr.arpa.
+www.subdivx.com.
+a4.sphotos.ak.fbcdn.net.
+img.hellocotton.com.
+um18.eset.com.
+www.google.com.
+searchjs.s3.amazonaws.com.
+webres4.pand.ctmail.com.
+245.117.169.189.in-addr.arpa.
+www.265jkw.net.
+ibxaxl-cash.net.
+fira.ru.
+adcofnorton.com.inbound15.mxlogic.net.
+secure.adnxs.com.
+a.root-servers.net.
+promostation.ru.
+203.185.15.118.in-addr.arpa.
+img3.theboyspics.com.
+www.tu-farmacia.com.
+g.msn.com.
+salud.nih.gov.
+go.microsoft.com.
+28.67.75.65.in-addr.arpa.
+track.sextorrent.to.
+uikusuvpj.info.
+bs.serving-sys.com.
+a2.sphotos.ak.fbcdn.net.
+mscrl.microsoft.com.
+www.toybangers.net.
+dns.msftncsi.com.
+api-read.facebook.com.
+a.root-servers.net.
+www.facebook.com.
+48.108.132.94.in-addr.arpa.
+buc.k12.va.us.
+76.223.238.99.in-addr.arpa.
+189.5.188.207.in-addr.arpa.
+external.ak.fbcdn.net.
+www-fc-opensocial.googleusercontent.com.
+:lugv26hs.e86h1r2q.
+www.viagemdossentidos.com.
+ads.vs.com.
+drewfriedman.blogspot.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+grupogaleria.com.
+statistic-collector.gad.de.
+api.twitter.com.
+www.gentlemensclubpodcast.com.
+t-online.de.
+a.root-servers.net.
+a.root-servers.net.
+external.ak.fbcdn.net.
+fdafda.com.
+time.windows.com.
+ballroomradio.com.
+i1.ytimg.com.
+external.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+pfo.su.
+plus.google.com.
+90.121.55.65.in-addr.arpa.
+75.64.225.190.in-addr.arpa.
+time.windows.com.
+www.medicalsupplydepot.com.
+a.root-servers.net.
+234.168.78.190.in-addr.arpa.
+www.prmoment.com.
+www.musicload.ch.
+www.google.com.
+equinejournal.com.
+static.ak.fbcdn.net.
+pixel.facebook.com.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+www.google.com.
+capricorp.com.
+_978_09_7.
+time.chttl.com.tw.
+pubads.g.doubleclick.net.
+cache-simg1.pressdisplay.com.
+55.192.207.190.in-addr.arpa.
+204.113.76.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+www.youtube.com.
+www.lpf.com.
+thehollywoodnews.com.
+210.9.69.190.in-addr.arpa.
+www.allcasinoslots.com.
+dat.ru.
+www.themeblvd.com.
+141.178.59.74.in-addr.arpa.
+6c461c1f.filesonthe.net.
+244.154.56.187.in-addr.arpa.
+static.app.widdit.com.
+www.vindiesel.com.
+12.0.168.192.in-addr.arpa.
+grasche.com.mx3.net10.rcimx.net.
+acm.master-code.ru.
+rss.marca.com.
+static.ak.fbcdn.net.
+admeld.adnxs.com.
+a7.sphotos.ak.fbcdn.net.
+local-bay.contacts.msn.com.
+scholar.google.com.
+9.157.134.186.in-addr.arpa.
+133.129.203.69.in-addr.arpa.
+a.root-servers.net.
+o-o.preferred.ams03g05.v22.lscache5.c.youtube.com.
+www.google.com.
+borntotry.polyvore.com.
+buenosairesrunway.blogspot.com.
+mail.live.com.
+hoiantrailsresort.com.vn.
+ampliatumente.com.
+searchjs.s3.amazonaws.com.
+mibollywoodmania.blogspot.com.
+profile.ak.fbcdn.net.
+metrics.caracoltv.com.
+i1.ytimg.com.
+mail.google.com.
+tracker.openbittorrent.com.
+www.globo.com.
+funniest-commercials.net.
+6.3.d.8.7.2.b.4.a.3.9.2.8.0.8.1.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+analytic.spamfighter.com.
+srob.com.
+www.circuittube.com.
+secure.skypeassets.com.
+yahoo.co.in.
+a.root-servers.net.
+sac.gti.mcafee.com.
+a6.sphotos.ak.fbcdn.net.
+static-images.veevr.com.
+.
+146.213.177.190.in-addr.arpa.
+www.iwantbanners.com.
+developers.facebook.com.
+e4805.b.akamaiedge.net.
+_863_35_6.
+support.live.com.
+part710.ru.
+time.windows.com.
+sp.cwfservice.net.
+hotmail.com.
+a639.da1.akamai.net.
+developers.facebook.com.
+static.ak.fbcdn.net.
+ds.addthis.com.
+a.root-servers.net.
+forums.motivemag.com.
+photos-b.ak.fbcdn.net.
+checkip.dyndns.org.
+photos-g.ak.fbcdn.net.
+bin.images.tuenti.net.
+tfw-current.s3.amazonaws.com.
+so-many-roads-boots.blogspot.com.
+billing.sharo4ka.ru.
+36ohk6dgmcd1n-c.c.yom.mail.yahoo.net.
+updatekeepalive.mcafee.com.
+a5.sphotos.ak.fbcdn.net.
+www.wsf.la.
+imageb.epocrates.com.
+a6.sphotos.ak.fbcdn.net.
+go.epson.com.
+rorwqgflplllupx.info.
+profile.ak.fbcdn.net.
+133.81.48.208.in-addr.arpa.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+download332.avast.com.
+www.differencebetween.co.in.
+elmicrobiologo.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+a5.da1.akamai.net.
+mobile.kobobooks.com.
+_635_45_9.
+josephsgolfshop.com.
+twitter.com.
+www.mulasoft.com.
+s-static.ak.facebook.com.
+bgoa.coxmail.com.
+silkshop.ru.
+checkip.dyndns.com.
+deccats.com.
+69.200.162.189.in-addr.arpa.
+www.elcorreo.com.
+mail4.red-tube.com.
+wpmlegal.com.
+a.root-servers.net.
+couponbuddy.s3.amazonaws.com.
+www.facebook.com.
+49.165.174.190.in-addr.arpa.
+175.217.26.125.in-addr.arpa.
+ligsay.com.mail9.psmtp.com.
+my.yahoo.com.
+a17sa.com.
+www.themarryblogger.com.
+wlp.carlead.com.
+photos-h.ak.fbcdn.net.
+local.msn.com.
+photos.e46fanatics.com.
+86.170.53.60.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+yl9y5g7k4.i27r3n4w.
+itbe.com.
+www.iyifilmizle.org.
+www.google.com.
+photos-h.ak.fbcdn.net.
+www.smuckers.com.mx.
+157.239.98.190.in-addr.arpa.
+adsfront.iminent.com.
+a5.sphotos.ak.fbcdn.net.
+dl_dir3.qq.com.
+search-mx.mlstatic.com.
+www.tmk.com.
+inbound.atiwave.com.netsolmail.net.
+www.adsphinx.com.
+artswork.org.uk.
+google.com.
+comienzoatejer.blogspot.com.
+brensoncorp.com.
+qualink.com.
+www.google.com.mx.
+234.247.92.186.in-addr.arpa.
+www.facebook.com.
+ip-link.ru.
+sites.google.com.
+www.mena.co.nz.
+cox.net.
+www.cunda.at.
+a5.sphotos.ak.fbcdn.net.
+allfreeiphones.net.
+_601_17_8.
+a.root-servers.net.
+88.34.225.190.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+ad.yieldmanager.com.
+www.wowstars.com.
+billing.sharo4ka.ru.
+casaycampo.es.
+104.142.106.186.in-addr.arpa.
+102.226.251.122.in-addr.arpa.
+www.youtube.com.
+time.chttl.com.tw.
+mail.classicjourneys.com.
+www.cafepress.com.
+image2.pubmatic.com.
+pandasux.com.
+www.google-analytics.com.
+www.deine-mutter.de.
+a.root-servers.net.
+a.root-servers.net.
+ad.yieldmanager.com.
+www.google.com.
+colombiavallenato.wordpress.com.
+keuk.elektra.ru.
+static.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+cdn-7.pics.t8premium.com.
+sweetlorraine.com.
+186.229.129.98.in-addr.arpa.
+202.58.70.200.in-addr.arpa.
+_220_45_0.
+a.root-servers.net.
+spitfire.com.au.
+20.224.171.69.in-addr.arpa.
+l.longtailvideo.com.
+www.adobe.com.
+mx.sonet.ru.
+www.successhappinessformula.com.
+25.210.174.189.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+bellsout.h.net.
+i2.ytimg.com.
+161.241.120.186.in-addr.arpa.
+pp2.inet.fi.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+a1737.g.akamai.net.
+professional.avira-update.com.
+137.192.68.89.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.derechoalverde.com.
+katzforums.com.
+hoatmil.com.
+google.com.
+.
+.
+www.cortexpower.de.
+mail.webengr.com.
+67.57.100.84.in-addr.arpa.
+fortresstrophyroom.blogspot.com.
+groups.google.com.mx.
+wer.microsoft.com.
+www.mysearsrebate.com.
+111.84.100.177.in-addr.arpa.
+mail2fantasy.com.
+www.rechargefree.weebly.com.
+www.facebook.com.
+archive.popurls.com.
+posta72a.mailbeta.libero.it.
+www.christopherpoole.tv.
+megaman.wikia.com.
+www.antoniotsai.com.
+p04-keyvalueservice.icloud.com.
+track.reinvigorate.net.
+179.17.77.190.in-addr.arpa.
+aadel.iranhrdc.org.
+pt-br.facebook.com.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+48.94.172.95.in-addr.arpa.
+19.85.101.187.in-addr.arpa.
+yfrog.com.
+msn.com.
+m-smanufacturing.com.
+i2.ytimg.com.
+www.saaid.net.
+irc.purchaseservice.com.
+corporate.miniclip.com.
+allwrongallright.files.wordpress.com.
+ocelott.tumblr.com.
+external.ak.fbcdn.net.
+dsn15.d.skype.net.
+911law.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+dfsfin.com.
+dnl-00.geo.kaspersky.com.
+pixel.facebook.com.
+a.root-servers.net.
+img19.exs.cx.
+sadhugroup.com.
+youtu.be.
+a.root-servers.net.
+external.ak.fbcdn.net.
+zhanet.com.
+crl.microsoft.com.
+profile.ak.fbcdn.net.
+kvoxgvihcv.com.
+mail3.soam.com.
+c4pi.de.
+oads.com.s5b1.psmtp.com.
+www.ortamtr.net.
+www.oakridgeproductions.ca.
+197.238.100.94.in-addr.arpa.
+live-for-speed.softonic.com.
+jsonline.com.s8a2.psmtp.com.
+smtp.wcbicecream.com.
+api.twitter.com.
+226.251.117.79.in-addr.arpa.
+sanpablo.com.pe.
+mikryptorincon.com.
+106.133.82.200.in-addr.arpa.
+gasa.hit.gemius.pl.
+topper.rmcc.cc.ar.us.
+apple.com.
+chromejs.s3.amazonaws.com.
+core.mochibot.com.
+divx-films.ru.
+prazdnik77.ru.
+www.alexcdn.info.
+a1.bing4.com.
+pagead2.googlesyndication.com.
+mx2.hotmail.com.
+profile.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+66.9.22.186.in-addr.arpa.
+saudireadymix.com.sa.
+www.facebook.com.
+pbid.iforex.com.
+sreenevasan.com.
+www.tataclub.com.ar.
+us.img.e-planning.net.
+196.19.164.189.in-addr.arpa.
+thecleanlife.hubpages.com.
+mailx2.alsolnet.com.
+stream3.mxcdn.com.
+22.149.220.66.in-addr.arpa.
+_232_67_1.
+253.147.198.187.in-addr.arpa.
+i1.makcdn.com.
+89.103.133.41.in-addr.arpa.
+www.google-analytics.com.
+mail.finklealaw.com.
+249.247.110.186.in-addr.arpa.
+ahmsi3.com.s7a2.psmtp.com.
+mtyfcpvyu.cc.private.
+welcometohosana.com.
+32.241.149.186.in-addr.arpa.
+tamsconj.com.
+47.14.17.95.in-addr.arpa.
+www.designisfels.net.
+mail.all4inc.com.
+a2.sphotos.ak.fbcdn.net.
+78.19.185.124.in-addr.arpa.
+dns.msftncsi.com.
+www.mall506.com.
+a3.sphotos.ak.fbcdn.net.
+b48fscxe11e11cuoyfrd30dsa67bqf62ptcwcv.net.
+99.244.205.190.in-addr.arpa.
+postd.cn.
+www.google.com.mx.
+traderjoestravel.com.
+131.164.215.89.in-addr.arpa.
+tools.google.com.
+239.97.120.95.in-addr.arpa.
+www.domcentral.org.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+www.imahero.com.
+twitter.com.
+address.yahoo.com.
+img181.imagevenue.com.
+ad.doubleclick.net.
+tags.crwdcntrl.net.
+cssdeck.com.
+www.fromzerotoseo.com.
+ugliesttattoos.wordpress.com.
+n19.8-d.com.
+226.40.191.190.in-addr.arpa.
+104.165.40.114.in-addr.arpa.
+alltel.net.
+s0.2mdn.net.
+ad.metanetwork.com.
+expandondemand.net.
+77.163.138.201.in-addr.arpa.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+www.podiatry-arena.com.
+dsdtraffic.com.
+translation1.paralink.com.
+i4.ytimg.com.
+xhkbkxm:5.65gz.
+health-beauty-tips.org.
+194.209.30.200.in-addr.arpa.
+116.85.50.190.in-addr.arpa.
+45.64.195.83.in-addr.arpa.
+player.vimeo.com.
+t2.gstatic.com.
+dns.msftncsi.com.
+242.15.120.174.in-addr.arpa.
+malah.biz.
+a.root-servers.net.
+images.paraorkut.com.
+142.164.232.99.in-addr.arpa.
+ocsp.verisign.com.
+lh5.googleusercontent.com.
+stats.wordpress.com.
+vialibrepl.com.
+i3.ytimg.com.
+grupobbva.net.
+www.latest-tattoo-designs.com.
+loading3.widdit.com.
+130.109.50.190.in-addr.arpa.
+www.google.com.
+a3.sphotos.ak.fbcdn.net.
+k:hq:wtqh.r10q2s9n.
+irc.purchaseservice.com.
+s-static.ak.fbcdn.net.
+mail.glhsco.com.
+t.co.
+photos-f.ak.fbcdn.net.
+adserver.adtech.de.
+80.115.151.184.in-addr.arpa.
+zapy9d5oe.45di.
+cache-default04g.cdn.yandex.net.
+220.126.178.186.in-addr.arpa.
+www.wing-zero.net.
+hbf.cloud.avg.com.
+cs506402.vk.com.
+153.252.78.186.in-addr.arpa.
+215.140.39.99.in-addr.arpa.
+www.onlinesayac.com.
+justcookit.blogspot.com.
+www.clavier-arab.org.
+a7.sphotos.ak.fbcdn.net.
+telepizzaes.solution.weborama.fr.
+images.google.com.
+iadsdk.apple.com.
+tolu.na.
+i073.radikal.ru.
+developers.facebook.com.
+www.odditieszone.com.
+a.root-servers.net.
+ad.yieldmanager.com.
+masdeluna.com.
+167.35.76.91.in-addr.arpa.
+www.123news.org.
+zillo.de.
+ksn7-12.kaspersky-labs.com.
+a.root-servers.net.
+chepireastlibr.cn.
+151.189.128.189.in-addr.arpa.
+leased-lines-204-235.tricom.net.
+support.google.com.
+www.migoa.com.
+crl.microsoft.com.
+pixel.facebook.com.
+48.13.93.186.in-addr.arpa.
+carroll.k12.ia.us.
+www.customsolutions.es.
+profile.ak.fbcdn.net.
+mail.slesnick.com.
+iphone-wu.apple.com.
+photos-b.ak.fbcdn.net.
+dns.msftncsi.com.
+tradal.net.
+player.vimeo.com.
+goo.gl.
+platform.ak.fbcdn.net.
+faq.immobilienscout24.de.
+translate.google.com.
+safebrowsing.clients.google.com.
+clock.fmt.he.net.
+www.manginasal.com.
+rihanna.wikia.com.
+144.63.178.187.in-addr.arpa.
+historymaker.com.
+60.55.48.27.in-addr.arpa.
+e1374.c.akamaiedge.net.
+a.root-servers.net.
+www.fmnh.helsinki.fi.
+disney.go.com.
+coldcomfort.com.s7a2.psmtp.com.
+a.root-servers.net.
+img2.blogblog.com.
+a.root-servers.net.
+ksn-kddi.kaspersky-labs.com.
+www.cherryconnect.com.
+s.youtube.com.
+vkusnoteevo.ru.
+www.facebook.com.
+dlvr.it.
+www.dancetrippin.tv.
+a.root-servers.net.
+yourfuture.ab.ca.
+docs.google.com.
+video.od.visiblemeasures.com.
+pt.cam4.com.
+www.google.com.
+www.hdtmedia.com.
+mail.tjohns.net.
+www.seejapan.co.uk.
+lb._dns-sd._udp.lan.
+a1.sphotos.ak.fbcdn.net.
+fo7b7kids.83bo.
+mailhost.groupe-sesar.com.
+api.twitter.com.
+photos-h.ak.fbcdn.net.
+floridafemme.net.
+disney.go.com.
+btfans.3322.org.
+a2.sphotos.ak.fbcdn.net.
+www.uniquecarsandparts.com.au.
+redberry.com.
+bioware.com.s7b1.psmtp.com.
+96.157.97.83.in-addr.arpa.
+awards.aol-soft.com.
+47.134.242.96.in-addr.arpa.
+www.facebook.com.
+fxfeeds.mozilla.com.
+f4.r.56.com.
+www.google.com.
+aps.ru.
+www.afiyetle.com.
+msc.wlxrs.com.
+urs.microsoft.com.
+234.99.17.88.in-addr.arpa.
+www.semarmenia.gov.co.
+cdn1.image.keezmovies.phncdn.com.
+sc6.rules.mailshell.net.
+ocsp.digicert.com.
+94.musclemeal.pay.clickbank.net.
+www.raf.mod.uk.
+empleo.trovit.com.mx.
+consoltech.com.
+coohuxnlpdtqmynypssqfhals.jp.
+katherineisawesome.files.wordpress.com.
+www.footylounge.org.
+external.ak.fbcdn.net.
+www.youtube.com.
+skylinealabama.com.
+www.velaro.com.
+173.153.223.87.in-addr.arpa.
+tvtomsk.ru.
+137.204.93.186.in-addr.arpa.
+twitter.com.
+mail.agilityphysicaltherapy.com.
+194.142.72.91.in-addr.arpa.
+236.113.113.186.in-addr.arpa.
+cf.addthis.com.
+e905.b.akamaiedge.net.
+google.com.
+photos-f.ak.fbcdn.net.
+ic.tynt.com.
+www.facebook.com.
+i3.ytimg.com.
+www.perfectlyengraved.co.uk.
+checkip.dyndns.org.
+photos-b.ak.fbcdn.net.
+www.sexenon.com.
+mail.winnercom.ru.
+banner.paypopup.com.
+a.root-servers.net.
+w291.photobucket.com.
+iirc.niu.edu.
+www.floorballmagazin.de.
+creative.ak.fbcdn.net.
+t2.gstatic.com.
+igor.facemoods.com.
+banners.iminent.com.
+www.avionics-event.com.
+platform.twitter.com.
+www.google.com.
+de-de.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+epsilon-group.com.
+www.youtube.com.
+www.xvideos.com.
+mac4rteso.wordpress.com.
+www.fanlore.org.
+_458_87_9.
+www.cheapcues.com.
+dpdn.sandai.net.
+es.wikipedia.org.
+translate.google.com.mx.
+img2.mlstatic.com.
+a6.phobos.apple.com.
+ad-power.ru.
+sc2.rules.mailshell.net.
+www.theagencyonline.co.uk.
+116.103.19.190.in-addr.arpa.
+panda-antivirus.softonic.com.
+www.hoycocino.com.ar.
+amer.rel.msn.com.
+i.ebayimg.com.
+www.reventandoculos.com.
+www.google.com.
+dagoatrapist.com.
+www.facebook.com.
+www.hillandknowlton.com.
+pacwriter.softonic.com.
+static3.wonderwall.com.
+www.eleccionesandalucia.es.
+210.164.255.201.in-addr.arpa.
+www.autocosmos.com.mx.
+www.halohairextensions.com.
+dcmovies.wikia.com.
+image2.pubmatic.com.
+photos-e.ak.fbcdn.net.
+subine.net.
+shinko-spl.com.sg.
+240.42.190.190.in-addr.arpa.
+www.eset.com.ph.
+google.com.
+amer.rel.msn.com.
+_857_75_1.
+a.root-servers.net.
+angel-a.ru.
+profile.ak.fbcdn.net.
+mail.befa.net.
+fcs91-1.streamate.com.
+www.educatico.ed.cr.
+mashable.com.
+box.ijneb.com.
+ads.smowtion.com.
+www.skk-banjaluckapivara.com.
+a1404.w41.akamai.net.
+tophost.it.
+www.ourproperty.co.uk.
+100.50.31.190.in-addr.arpa.
+downloader.versalsoft.com.
+www.aapkikismat.com.
+hpmedcenter.com.s8b1.psmtp.com.
+clasesdejoyeria.blogspot.com.
+72.87.232.190.in-addr.arpa.
+d15gt9gwxw5wu0.cloudfront.net.
+not-mail.uniwin.ru.
+messenger.hotmail.com.
+static.apotheken-umschau.de.
+db._dns-sd._udp.lan.
+kbvm:p74y.55lb.
+negro0045.com.
+dnl-01.geo.kaspersky.com.
+books.google.es.
+static.ak.fbcdn.net.
+time.windows.com.
+parentingsquad.com.
+safebrowsing-cache.google.com.
+safebrowsing-cache.google.com.
+www.facebook.com.
+d2102706.xoom.it.
+clinton.k12.ky.us.
+86.143.203.69.in-addr.arpa.
+i3.ytimg.com.
+ps3.brewology.com.
+88.253.142.187.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+twitter.com.
+www.xvideos.com.
+platform.ak.fbcdn.net.
+evsecure-ocsp.verisign.com.
+32.112.236.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+63.242.184.99.in-addr.arpa.
+transloadamerica.com.s5a2.psmtp.com.
+folio.com.
+aclupa.org.
+nuestrasmiscelaneas.blogspot.com.
+clients4.google.com.
+asktoolbar.weather.com.
+photos-e.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+img815.imageshack.us.
+www.rsvp.com.au.
+unless.com.
+img42.imageshack.us.
+touch.facebook.com.
+photos-c.ak.fbcdn.net.
+a.root-servers.net.
+a727.phobos.apple.com.
+230.247.96.109.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+accounts.google.com.
+unifi.
+trans-p2p.pandora.tv.
+6.177.55.201.in-addr.arpa.
+www.youtube.com.
+arielassociates.com.
+www.sourcevibrations.com.
+a6.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+a1.sphotos.ak.fbcdn.net.
+dnl-18.geo.kaspersky.com.
+a3.sphotos.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+google.com.
+www.googletagservices.com.
+a6.sphotos.ak.fbcdn.net.
+3end.ru.
+144.248.138.189.in-addr.arpa.
+i1.ytimg.com.
+js.admeld.com.
+22.239.187.189.in-addr.arpa.
+www.quicklycode.com.
+evolutionarypsychiatry.blogspot.com.
+portugalunderground.blogspot.com.
+b.scorecardresearch.com.
+developers.facebook.com.
+secure-anntaylor2.richfx.com.
+accounts.google.com.
+235.26.27.188.in-addr.arpa.
+a.root-servers.net.
+switchboard.real.com.
+apps.facebook.com.
+a.root-servers.net.
+121.38.32.46.in-addr.arpa.
+www.google.com.
+129.176.129.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+s-static.ak.facebook.com.
+sofi.ua.
+html.rincondelvago.com.
+i3.ytimg.com.
+storage.conduit.com.
+177.138.141.189.in-addr.arpa.
+a.root-servers.net.
+sc19.rules.mailshell.net.
+omega.ua.
+developers.facebook.com.
+a.root-servers.net.
+normateca.educal.com.mx.
+caldav.calendar.yahoo.com.
+www.americanwhitewater.org.
+i1.nyt.com.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+:lvzz93qr.46pf.
+110.254.162.76.in-addr.arpa.
+sjc.ads.nexage.com.
+248.154.104.190.in-addr.arpa.
+195.10.8.95.in-addr.arpa.
+img1.blogblog.com.
+214.16.168.192.in-addr.arpa.
+www.studymalaysia.com.
+www.google.com.
+jesuitswisprov.org.
+.
+ju.edu.
+ghs.l.google.com.
+98.34.97.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+mail2.foley2.com.
+cropper.com.
+fxfeeds.mozilla.com.
+verizoni.net.
+www.facebook.com.
+175.64.94.186.in-addr.arpa.
+s.youtube.com.
+et-consulting.ru.
+nl-pic1.ciao.com.
+84.174.85.209.in-addr.arpa.
+th209.photobucket.com.
+166.61.225.76.in-addr.arpa.
+hojuuncontentingness.com.
+securepubads.g.doubleclick.net.
+ads.yimg.com.
+js2.wlxrs.com.
+a.root-servers.net.
+217.221.114.93.in-addr.arpa.
+www.thugmart.com.
+imperiyaavto.ru.
+cux9u3dpp.42qh.
+www.facebook.com.
+q6y9cx9vg.g95j5g3k.
+api-read.facebook.com.
+amer.rel.msn.com.
+zynga1-a.akamaihd.net.
+upload.facebook.com.
+baklanov.msk.ru.
+webcache.googleusercontent.com.
+754866.r.msn.com.
+bigmail-file18.mail.daum.net.
+threw.ru.
+music.darrenlock.com.
+translate.google.com.mx.
+ladolcevitaevents.net.
+www.tattoodownloadz.com.
+fdpinvest.ru.
+www.dontlookbackconcerts.com.
+blufiles.storage.msn.com.
+www.coffeeshrub.com.
+www.caninest.com.
+scholar.google.com.
+rzhrdb.com.
+static.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+rcp.na.blackberry.com.
+evintl-ocsp.verisign.com.
+sc2.rules.mailshell.net.
+loading3.widdit.com.
+zonaalfasex.blogspot.com.
+orthoctrsofl.com.
+okwm38xxk.q21f1e6u.
+download343.avast.com.
+www.derrierelacolline.net.
+www.mi6-hq.com.
+www.labcreations.biz.
+www.televisa.com.
+www.ibcrosario.com.ar.
+official-fangoria.disqus.com.
+a.root-servers.net.
+www.hi5.com.
+a.root-servers.net.
+www.martinfowler.com.
+www.putalocura.com.
+a.root-servers.net.
+ttln.com.
+resolver.3.geo.ctmail.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+panservice.it.
+api.twitter.com.
+mail.f2.net.
+pr.starmedia.com.
+91.216.101.187.in-addr.arpa.
+a.root-servers.net.
+www.inac.gov.ve.
+media.adxpansion.com.
+sn21.mailshell.net.
+mail.hawaiireserves.com.
+1-live-gs-emhe.6waves.com.
+andor.net.
+mailyam.com.
+api-read.facebook.com.
+114.130.80.84.in-addr.arpa.
+.
+kepa.ru.
+www.thinkyhead.com.
+159.39.61.81.in-addr.arpa.
+jcom.home.ne.jp.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+files.myopera.com.
+33.72.188.189.in-addr.arpa.
+ws-cloud236-blur.svcmot.com.
+ad.yieldmanager.com.
+myonlyuniverse.blogspot.com.
+www.skyshape.com.
+english-by-phone-admin.com.
+www.joinmyvillage.com.
+img513.imageshack.us.
+accounts.google.com.
+sr.wikipedia.org.
+www.facebook.com.
+ss28:mxx8.n82f3g6e.
+a.root-servers.net.
+71.31.93.189.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+ads.adbrite.com.
+www.cheapukgirls.com.
+ametekaerodefense.com.
+alfordot.com.
+udc.msn.com.
+www.21stcenturydental.com.
+as.py.impact-ad.jp.
+gdyn.hlntv.com.
+www.karlsruhe.de.
+alltrl.net.
+www.youtube.com.
+210.221.132.187.in-addr.arpa.
+www.inlandnewstoday.com.
+static.ak.fbcdn.net.
+investor.power-one.com.
+lrbdvj813.26ax.
+200.109.175.110.in-addr.arpa.
+cyberinsecure.com.
+blacklist.teamspeak.com.
+a4.sphotos.ak.fbcdn.net.
+annita.bligoo.com.
+87.148.59.199.in-addr.arpa.
+taniaraymondefan.com.
+ads.creafi-online-media.com.
+35.89.182.190.in-addr.arpa.
+www.clubdelvento.com.ar.
+235.42.151.68.in-addr.arpa.
+hi-in.facebook.com.
+pixel.facebook.com.
+smtp.hometelco.com.s5b1.psmtp.com.
+static.ak.fbcdn.net.
+mx.dilltech.com.
+a.root-servers.net.
+www.kaba.co.nz.
+19.228.171.69.in-addr.arpa.
+cnfg.montiera.com.
+photos-g.ak.fbcdn.net.
+hot-goods.ru.
+external.ak.fbcdn.net.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+unimac.com.
+164.70.215.190.in-addr.arpa.
+sp.cwfservice.net.
+www.gstatic.com.
+126.62.139.75.in-addr.arpa.
+asplundhbpg.com.
+sites.google.com.
+lvtlslxupeptemc.com.
+www.truthtube.tv.
+enough.com.
+docs.google.com.
+photos-g.ak.fbcdn.net.
+d2103737.xoom.it.
+myownlabels.com.
+sp.cwfservice.net.
+10.53.37.83.in-addr.arpa.
+www.tattoologist.com.
+sp.cwfservice.net.
+197.184.149.69.in-addr.arpa.
+www.transparencia.unam.mx.
+static.ak.fbcdn.net.
+a.root-servers.net.
+developers.facebook.com.
+secure-assets.rubiconproject.com.
+www.facebook.com.
+s-static.ak.facebook.com.
+mx.youtube.com.
+78.4.175.94.in-addr.arpa.
+img133.picfoco.com.
+ad.yieldads.com.
+www.bannerflux.com.
+triton.mnet.com.
+201.81.179.90.in-addr.arpa.
+js.wlxrs.com.
+www.adobe.com.
+www.moneysupermarket.com.
+pgcff.pricegong.com.
+s-external.ak.fbcdn.net.
+tc.v7.cache4.c.youtube.com.
+safebrowsing-cache.google.com.
+twitter.com.
+css.wlxrs.com.
+a.root-servers.net.
+jers1.info.
+_636_24_0.
+go.microsoft.com.
+126.190.119.98.in-addr.arpa.
+arabic.hktdc.com.
+incredibots2.com.
+accounts.google.com.
+graph.facebook.com.
+213.146.179.187.in-addr.arpa.
+90.0.75.187.in-addr.arpa.
+12.143.237.189.in-addr.arpa.
+www.nonudeladies.info.
+api.twitter.com.
+www.rudnei.cunha.nom.br.
+www.youtube.com.
+juegos-ultimate-arcade.blogspot.com.
+130.100.160.182.in-addr.arpa.
+mx.fgup.net.
+inbound.reetex.com.netsolmail.net.
+113.3.103.189.in-addr.arpa.
+tampa.holaciudad.com.
+westelcom-mx.messaging.lotuslive.com.
+download.windowsupdate.com.
+wishlist-products.s3.amazonaws.com.
+fbcdn-profile-a.akamaihd.net.
+yadjose.espacioblog.com.
+watershipltd.com.
+a7.sphotos.ak.fbcdn.net.
+www.googleadservices.com.
+120.187.117.68.in-addr.arpa.
+www.facebook.com.
+profile.ak.fbcdn.net.
+www.feedage.net.
+a-0.19-a30f3081.80e0180.1518.19d4.3ea1.410.0.wh8h6hw9qeh8hzi3ulfja7itat.avqs.mcafee.com.
+pop.netaddress.com.
+gchu-ao.foroactivo.net.
+creative.ak.fbcdn.net.
+chim.vrn.ru.
+notify10.dropbox.com.
+widget.alot.com.
+shamrocksportsgroup.com.s8a2.psmtp.com.
+www.downextra.net.
+a4.sphotos.ak.fbcdn.net.
+www.dollandthecity.com.
+71.123.164.79.in-addr.arpa.
+15.123.145.213.in-addr.arpa.
+www.containerhandbuch.de.
+a.root-servers.net.
+24.192.178.190.in-addr.arpa.
+c13.zedo.com.
+profile.ak.fbcdn.net.
+invest.grainger.com.
+116.205.171.201.in-addr.arpa.
+gknholding.com.
+sp.cwfservice.net.
+rocketmail.com.
+1pic1mtb1.p60r1h7e.
+www.gmail.com.
+179.236.144.189.in-addr.arpa.
+www.madmaxmodels.com.
+bhdccudap02.blackhillscorp.com.
+www.siestakeyvacationsrental.com.
+rvlife.net.
+touch.facebook.com.
+api.facebook.com.
+external.ak.fbcdn.net.
+flame.ru.
+jonjulio.tumblr.com.
+a.root-servers.net.
+a.root-servers.net.
+masqueperras.blogspot.com.
+csi.gstatic.com.
+centum.cz.
+carrison.co.uk.
+conduit.anybodyoutthere.com.
+fb-client-0.castle.zynga.com.
+157.147.152.201.in-addr.arpa.
+a.root-servers.net.
+194.68.37.186.in-addr.arpa.
+jet.sao.ru.
+www.gpr.hu.
+ht50.easou.com.
+platform.twitter.com.
+113.169.162.187.in-addr.arpa.
+fonts.googleapis.com.
+pear.php.net.
+14.202.178.186.in-addr.arpa.
+zh-cn.facebook.com.
+www.rtc.com.
+ls2web.redmond.corp.microsoft.com.
+www.plastimo.com.
+schantz.com.
+l.yimg.com.
+api.facebook.com.
+248.225.58.189.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cmsimg.wausaudailyherald.com.
+ts-transport.ru.
+crochetemoda.blogspot.com.
+4.bp.blogspot.com.
+hantoma.hani.co.kr.
+sovetrector.ru.
+api.conduit.com.
+webcache.googleusercontent.com.
+photos-a.ak.fbcdn.net.
+companion-group.com.
+38.113.14.71.in-addr.arpa.
+computerpoint.net.s8a2.psmtp.com.
+www.toyopumps.com.
+mail.sincol.com.
+130.9.137.82.in-addr.arpa.
+2ah:afnbd.b11r2u1t.
+teredo.ipv6.microsoft.com.
+img260.imagevenue.com.
+s.youtube.com.
+200.37.51.180.in-addr.arpa.
+253.53.36.190.in-addr.arpa.
+145.174.207.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+134.176.104.186.in-addr.arpa.
+0-278.channel.facebook.com.
+www.excatholicsforchrist.com.
+calambresabdominales.blogspot.com.
+publishers.org.
+mail-3.readingbody.com.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+dtlink.com.br.
+mtalk.google.com.
+aol.com.
+s-static.ak.fbcdn.net.
+api.twitter.com.
+wwwimages.adobe.com.
+sp.ask.com.
+104.158.212.186.in-addr.arpa.
+swift.xobni.com.cdngc.net.
+reconquista.pt.
+about.ask.com.
+s4.histats.com.
+27.211.172.118.in-addr.arpa.
+bing.com.
+profile.ak.fbcdn.net.
+www.facebook.com.
+southern-container.com.
+mail.chokseychem.com.
+d1j68ux4ukg4g1.cloudfront.net.
+220.92.80.2.in-addr.arpa.
+sp.cwfservice.net.
+51.12.39.114.in-addr.arpa.
+careagemanagement.com.inbound10.mxlogicmx.net.
+ntp1.dlink.com.
+mxtreme1.bob.fi.
+from-the-mountains.com.
+rim.trapis.net.
+aocuoikhanhlinh.vn.
+www.provocativebabes.com.
+cdn.turn.com.
+download.windowsupdate.com.
+mail.youngnoel.com.
+lo5ssmq3z.35eo.
+photos-g.ak.fbcdn.net.
+www.procostas.org.
+privcomm.com.
+resudox.net.1.0001.arsmtp.com.
+external.ak.fbcdn.net.
+es-es.facebook.com.
+data.flurry.com.
+smtpjp.lvmh-group.com.
+www.yyhworld.com.
+mail1.hella.com.
+www.awmads.com.
+www.kissthatsound.com.
+m.webtrends.com.
+texasdebrazil.fbmta.com.
+google.com.
+sp.cwfservice.net.
+midlandsco-op.com.
+9.rarbg.com.
+www.reuters.com.
+www.google.com.
+ms-max.ru.
+cs11168.vkontakte.ru.
+www.brent.gov.uk.
+m.asu.edu.
+www.lantern-festival.com.
+23.187.36.190.in-addr.arpa.
+www.urljet.com.
+v8.cache2.c.youtube.com.
+www.stumbleupon.com.
+morelandassoc.com.
+www.truckertotrucker.com.
+247.65.222.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+199.162.226.189.in-addr.arpa.
+static.linkbucks.com.
+sabre.tomlin.yahoo.com.
+67.106.255.77.in-addr.arpa.
+pagead2.googlesyndication.com.
+30.205.89.173.in-addr.arpa.
+www.arte-y-plata.com.
+culinaryschools.ru.
+covemotoring.com.
+mail.yoowalk.com.
+proposal.com.
+s-static.ak.fbcdn.net.
+nzgiexyo8.79io.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+nokia.com.
+profile.ak.fbcdn.net.
+www.tumblr.com.
+www.astrocentral.co.uk.
+156.235.29.86.zz.countries.nerd.dk.
+teredo.ipv6.microsoft.com.
+www.sqm.microsoft.com.
+www.seagate.com.
+drjohn2020.com.
+urs.microsoft.com.
+teredo.ipv6.microsoft.com.
+crashlog.whatsapp.net.
+moca.org.
+a997.mm1.akamai.net.
+77.152.132.187.in-addr.arpa.
+a.root-servers.net.
+malah.biz.
+www.animeplanet1000.blogspot.com.
+rotfl.com.
+23.214.192.66.in-addr.arpa.
+www.ebonyfacial.net.
+90.102.53.186.in-addr.arpa.
+95.253.36.184.in-addr.arpa.
+dns.carnainfo.com.br.
+voipb.sip.yahoo.com.
+www.verfutbolonline.net.
+37.24.100.85.in-addr.arpa.
+tags.bluekai.com.
+1.201.173.190.in-addr.arpa.
+secure-us.imrworldwide.com.
+www.assa.edu.au.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+dns.msftncsi.com.
+www.plics.net.
+www.ademails.com.
+pic.srv104.wapedia.mobi.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+iamronel.com.
+ns1.freewebship.net.
+espanol.wunderground.com.
+api.conduit.com.
+a.root-servers.net.
+hpp.orange.fr.
+acpo.org.
+rosieflores.com.
+a.root-servers.net.
+40.29.100.190.in-addr.arpa.
+cdn.ad4game.com.
+2.150.218.186.in-addr.arpa.
+mac1.no.
+bs.serving-sys.com.
+lys.org.
+39.225.48.190.in-addr.arpa.
+cdn1.certified-apps.com.
+a4.sphotos.ak.fbcdn.net.
+skydrive.live.com.
+10.192.188.186.in-addr.arpa.
+mpcstatic.com.
+www.corporate-impressum.com.
+host71.123flashchat.com.
+a.root-servers.net.
+google.com.
+ksn3-11.part2.kaspersky-labs.com.
+mail.roosevelt.k12.tx.us.
+papercraftparadise.blogspot.com.
+www.noroeste.com.mx.
+moviecities.com.
+167.224.181.72.in-addr.arpa.
+www.googleadservices.com.
+gmail.com.
+88.252.178.186.in-addr.arpa.
+hi-in.facebook.com.
+95.72.14.186.in-addr.arpa.
+poodlesarepeople.com.
+42.92.19.201.in-addr.arpa.
+www.google.com.
+free.fr.dnsbl7.mailshell.net.
+224.43.191.190.in-addr.arpa.
+edge.quantserve.com.
+www.chinuka.com.
+www.youtube.com.
+cust14266-1.in.mailcontrol.com.
+apps.facebook.com.
+www.google.com.
+profile.ak.fbcdn.net.
+google.com.
+www.villa-bisono.com.
+itunes.apple.com.
+e4967.g.akamaiedge.net.
+a6.sphotos.ak.fbcdn.net.
+ten-arquitectos.com.s8a1.psmtp.com.
+mailrelay.harrisburgnewsco.com.
+espanol.answers.yahoo.com.
+linksys-con10.url.trendmicro.com.
+ieonlinews.microsoft.com.
+224.49.66.186.in-addr.arpa.
+www.youtube.com.
+_715_42_7.
+zh-cn.facebook.com.
+messenger.hotmail.com.
+s12.last.fm.
+web.haceb.com.
+a2.sphotos.ak.fbcdn.net.
+api2.4shared.com.
+www.bundarika.com.
+txla.org.
+ut2.xhamster.com.
+32.226.79.190.in-addr.arpa.
+142.31.245.189.in-addr.arpa.
+imagenes.es.sftcdn.net.
+www.youtube.com.
+sp.cwfservice.net.
+static.girlgames4u.com.
+photos-f.ak.fbcdn.net.
+www.izleyivergari.info.
+prhospital.com.
+plus.google.com.
+www.eldiariomontanes.es.
+api.facebook.com.
+pagead2.googlesyndication.com.
+discovision.com.s9a1.psmtp.com.
+chmail.ru.
+uu1.orbitdownloader.com.
+a2.sphotos.ak.fbcdn.net.
+vpn.su.
+sites.google.com.
+www.fxfisherman.com.
+_608_72_5.
+grandviewlodge.com.
+s.youtube.com.
+a.root-servers.net.
+cm.ac3.msn.com.
+translate.google.com.mx.
+www.woodgundy.com.
+www.g999g.com.
+school.moodlemoot.com.au.
+l52bfy8l1.94me.
+www.riaupos.co.
+theparkdowntown.com.
+ad.ad-srv.net.
+dynamoelectronics.blogspot.com.
+serecon.ca.
+diamondcertified.org.
+www.corel.com.
+museumca.org.
+msntest.serving-sys.com.
+cplus.about.com.
+a4.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+www.google-analytics.com.
+www.myfamily.com.
+andsewitgoes.blogspot.com.
+baboolercheme.org.
+photos-c.ak.fbcdn.net.
+a.root-servers.net.
+widgets.amung.us.
+a4.sphotos.ak.fbcdn.net.
+www.google.com.
+www.uac.pt.
+114.117.156.187.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+3.bp.blogspot.com.
+ads2.contentabc.com.
+239.84.139.189.in-addr.arpa.
+pixel.facebook.com.
+swf.fizzgame.com.
+mail.shm.ru.
+www.fairouz.com.
+130.16.250.189.in-addr.arpa.
+firsterotica.com.
+ib.adnxs.com.
+247.207.73.69.in-addr.arpa.
+60.66.64.186.in-addr.arpa.
+www.facebook.com.
+116.144.138.201.in-addr.arpa.
+s5.mogujie.cn.
+c7.zedo.com.
+246.134.0.186.in-addr.arpa.
+newsaxon.org.
+a7.sphotos.ak.fbcdn.net.
+nesk2fgrx.73ru.
+ele.aut.ac.ir.
+www-cctld.l.google.com.
+www.stretcher.com.
+_887_71_6.
+cdn4.digitaltrends.com.
+pl.wikipedia.org.
+crl.microsoft.com.
+ssl.gstatic.com.
+col.stb00.s-msn.com.
+213.125.153.189.in-addr.arpa.
+c.prodigy.msn.com.
+www.oldwayspt.org.
+195.174.39.60.in-addr.arpa.
+www.registry.in.
+onestopfunny.com.
+css.wlxrs.com.
+noticias.latam.msn.com.
+www.voayeurs.com.
+displayworks.com.s7b1.psmtp.com.
+caracteres.wordpress.com.
+121.185.215.108.in-addr.arpa.
+api.connect.facebook.com.
+sulzer.com.s201a1.psmtp.com.
+cherkessk.ru.
+www.siaccss.com.
+www.tvacres.com.
+adserver.adtechus.com.
+teredo.ipv6.microsoft.com.
+ondetroitmi.com.
+231.42.234.189.in-addr.arpa.
+www.facebook.com.
+www.playdojam.com.
+olshtyn.ru.
+74.124.163.46.in-addr.arpa.
+aka-cdn-ns.adtechus.com.
+27.media.tumblr.com.
+s-static.ak.facebook.com.
+cfisco.com.
+en.wikipedia.org.
+pagead2.googlesyndication.com.
+banners.iminent.com.
+googleads.g.doubleclick.net.
+bit.ly.
+www.tutiempo.net.
+i2.ytimg.com.
+www.gstatic.com.
+seinur.info.
+www.sexoflover.com.
+developers.facebook.com.
+bsvst.ru.
+google.com.
+clients1.google.com.
+dr._dns-sd._udp.lan.
+privacy2.msn.com.
+pagead2.googlesyndication.com.
+teredo.ipv6.microsoft.com.
+ping.chartbeat.net.
+fbcdn-profile-a.akamaihd.net.
+apmc.net.s10b1.psmtp.com.
+121.253.84.200.in-addr.arpa.
+si-tx.com.s7b2.psmtp.com.
+a.root-servers.net.
+apix.iminent.com.
+a8.sphotos.ak.fbcdn.net.
+downbytheriverbank.blogspot.com.
+kb-law.com.s8a2.psmtp.com.
+safebrowsing-cache.google.com.
+creative.ak.fbcdn.net.
+relestar.com.
+hotmail.com.
+199.1.130.79.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+aidps.atdmt.com.
+connect.facebook.net.
+www.jesusferrer.es.
+b.scorecardresearch.com.
+35.237.51.190.in-addr.arpa.
+p03-streams.icloud.com.
+baileycompany.com.
+developers.facebook.com.
+_122_26_3.
+mail.starband.com.
+kiev.unian.net.
+lkayrnosi.n79w7f1n.
+platform.twitter.com.
+gbjha.zeneca.com.
+www.google.com.
+infogen.com.
+www.quicksupply.net.
+hotwater.build.com.au.
+203.175.206.200.in-addr.arpa.
+a.root-servers.net.
+twimg0-a.akamaihd.net.
+api.twitter.com.
+234.254.200.190.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+www.google.com.
+193.96.129.217.in-addr.arpa.
+translate.google.com.mx.
+jacuzzi.vidz.com.
+cn1.redswoosh.akadns.net.
+a6.sphotos.ak.fbcdn.net.
+www2.dca.ca.gov.
+www.star-advertising.com.
+html.atm.youku.com.
+www.ihrdc.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+68.11.168.192.in-addr.arpa.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ads.bluelithium.com.
+pixel.facebook.com.
+tc21.easythumbhost.com.
+www.eluniversal.com.mx.
+25.15.206.41.in-addr.arpa.
+lunarstuff.com.
+haapavesi.fi.
+photos-a.ak.fbcdn.net.
+_002_80_1.
+119.49.11.189.in-addr.arpa.
+xk18zs87c.14rh.
+zahduc34k.64kr.
+58.111.79.201.in-addr.arpa.
+content.xbox.com.edgesuite.net.
+api-read.facebook.com.
+216.86.251.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+125.240.56.66.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+p.jango.com.
+secure.wlxrs.com.
+www.retratech.ca.
+mahindra.co.za.
+mail.spindlereng.com.
+89.252.166.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.andrewlab.com.
+www.ciol.com.
+gaztekinzale.wordpress.com.
+time.chttl.com.tw.
+40.1.101.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+166.60.229.189.in-addr.arpa.
+1.11.71.187.in-addr.arpa.
+a13.t26.net.
+iphone.facebook.com.
+stox.ru.
+api.twitter.com.
+gw.home.vix.com.
+playerservices.streamtheworld.com.
+a.root-servers.net.
+mail2.investural.ru.
+crossfit-gyms.com.
+koenigscale.com.mail7.psmtp.com.
+clients1.google.com.
+www.abstractmath.org.
+fbcdn-photos-a.akamaihd.net.
+lasco.costeel.com.
+www.tequesquitengo.org.mx.
+mail.gas12.ru.
+fbcdn-sphotos-a.akamaihd.net.
+s815.photobucket.com.
+www.gamefaqs.com.
+a.root-servers.net.
+z-ecx.images-amazon.com.
+bit.ly.
+www.cat-barcelona.com.
+voipa.sip.yahoo.com.
+www.top10series.com.
+exhiberexpo.ru.
+lbcore1.metacafe.com.
+buchete-mireasa.ro.
+124.99.171.78.in-addr.arpa.
+creative.ak.fbcdn.net.
+151.25.253.189.in-addr.arpa.
+a3.twimg.com.
+googleads.g.doubleclick.net.
+gcsd.global.sonicwall.com.
+180.80.81.201.in-addr.arpa.
+190.49.178.78.in-addr.arpa.
+www.spacesoundrecords.com.
+fiteyes.com.
+202.196.70.86.in-addr.arpa.
+alternativaslibres.mcye.misiones.gov.ar.
+228.154.108.114.in-addr.arpa.
+161.148.194.190.in-addr.arpa.
+atspam.atproperties.com.
+www.aveev.org.
+djesibonajeb.com.
+rediffmail.com.
+cobaltemail.com.
+202.211.118.190.in-addr.arpa.
+www.nshamabagdad.com.
+206.71.0.71.in-addr.arpa.
+metrics.nokia.com.
+creative.ak.fbcdn.net.
+rcp.na.blackberry.com.
+94.140.227.190.in-addr.arpa.
+time-nw.nist.gov.
+fbcdn-sphotos-a.akamaihd.net.
+mail.pesd.k12.wi.us.
+static.ak.fbcdn.net.
+www.ironcreek.net.
+external.ak.fbcdn.net.
+rocketfuel.com.
+profile.ak.fbcdn.net.
+126.196.155.93.in-addr.arpa.
+www.google.com.
+126.162.217.196.in-addr.arpa.
+t7.tagstat.com.
+www1.plumpestgrannies.com.
+www.luxurybeachresorts.com.mx.
+photos-f.ak.fbcdn.net.
+cdchww3gm.56bf.
+cdn.zeusclicks.com.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+evaysuserpientes.blogspot.com.
+a.root-servers.net.
+ebarasolar.com.
+abooking.net.
+asdlabs.com.
+facebookhackingcourse.com.
+baseavalancha.mforos.com.
+podcast.gcnlive.com.
+taxpro.hrblock.com.
+88.92.196.216.in-addr.arpa.
+holatu.com.
+universal-document-converter-win.softonic.com.
+service-public.fr.
+profile.ak.fbcdn.net.
+google.com.
+9q9vf:hom.n29j4k0y.
+138.58.235.201.in-addr.arpa.
+16.59.44.129.in-addr.arpa.
+109.59.0.27.in-addr.arpa.
+abc.volga.ru.
+74.194.66.201.in-addr.arpa.
+103.118.11.190.in-addr.arpa.
+b5e:e98u8.w52x0e3l.
+www.bakers.co.uk.
+.
+www.maserati.com.
+mediacdn.disqus.com.
+a7.sphotos.ak.fbcdn.net.
+i2.ytimg.com.
+mx2.kennemergroup.com.
+anmagroup.com.
+tracker.publicbt.com.
+nl0105dom26.fea.slb.com.
+a5.sphotos.ak.fbcdn.net.
+api.twitter.com.
+www.espacio15.com.
+universat.com.
+213.56.47.189.in-addr.arpa.
+api-read.facebook.com.
+m.facebook.com.
+mnademexico.com.
+ksn2.kaspersky-labs.com.
+belrus.kuban.ru.
+103.180.182.189.in-addr.arpa.
+mail.midwestrespiratory.com.
+apps.facebook.com.
+a1725.l.akamai.net.
+bs.serving-sys.com.
+108.248.41.175.in-addr.arpa.
+safebrowsing.clients.google.com.
+quepiensaeltercerhombre.blogspot.com.
+17.168.50.190.in-addr.arpa.
+speed.cd.
+rad.msn.com.
+.
+110.249.226.76.in-addr.arpa.
+planet.wordpress.org.
+www.heterodoxos.org.
+a.root-servers.net.
+ax.su.itunes.apple.com.
+123.203.140.79.in-addr.arpa.
+a4.da1.akamai.net.
+www.bywifi.com.
+rcm.org.uk.
+trailw.dealply.com.
+unica.com.br.
+apple.com.
+58.244.165.190.in-addr.arpa.
+elobservadorsarcastico.blogspot.com.
+a4.da1.akamai.net.
+a.root-servers.net.
+salud-solobuenasnoticias.blogspot.com.
+_560_76_2.
+www.voodootonic.com.
+descargas.juegos.com.
+104.224.194.58.in-addr.arpa.
+shahid.mbc.net.
+www.ihstar.com.
+plus.google.com.
+205.135.141.118.in-addr.arpa.
+newsrss.bbc.co.uk.
+img187.imageshack.us.
+photos-h.ak.fbcdn.net.
+29-courier.push.apple.com.
+157.206.230.190.in-addr.arpa.
+212.44.83.78.in-addr.arpa.
+rostplastik.ru.
+static.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+developers.facebook.com.
+image-school.ru.
+shoemanic.com.
+conduit.anybodyoutthere.com.
+t3.gstatic.com.
+escueladefotografia.blogspot.com.
+lexha.org.
+support.google.com.
+246.73.88.74.in-addr.arpa.
+ad.yieldmanager.com.
+146.117.144.201.in-addr.arpa.
+metafisica.galeon.com.
+b.scorecardresearch.com.
+waterpas.com.
+.
+platform.ak.fbcdn.net.
+plusone.google.com.
+ptpc.com.
+.
+www.youtube.com.
+developers.facebook.com.
+simple.wikipedia.org.
+labhut.com.
+a6.sphotos.ak.fbcdn.net.
+ar-ar.facebook.com.
+www.bible.cc.
+static.ak.fbcdn.net.
+nycap.rr.com.
+zynga2-a.akamaihd.net.
+a.root-servers.net.
+ad-g.doubleclick.net.
+88.108.56.200.in-addr.arpa.
+dnjnet.com.
+www.anka.com.
+osobnyak.ru.
+translate.google.com.mx.
+statcounter.com.
+graph.facebook.com.
+cuautitlanizcalli.olx.com.mx.
+join.thecrossdressers.com.
+ignaciogalvez.com.
+flaq4b4te.69il.
+www.adobe.com.
+sthelaz.blogspot.com.
+aunicom.ru.
+static.ak.fbcdn.net.
+www.facebook.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.knijnenburgbeheer.nl.
+a4.sphotos.ak.fbcdn.net.
+i299.photobucket.com.
+crashmania.net.
+22.39.96.184.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.bligoo.com.
+www.showtime.jp.
+www.asefapi.es.
+tile.openstreetmap.org.
+ssl.google-analytics.com.
+www.mfa.gov.eg.
+photos-a.ak.fbcdn.net.
+psikolokospucp.blogspot.es.
+ksn1-11-part1.kaspersky-labs.com.
+117.91.68.189.in-addr.arpa.
+ad.yieldmanager.com.
+beautypageantnews.com.
+dns.msftncsi.com.
+diverticulitis.org.uk.
+bestvalueinn-lethbridge.com.
+checkip.dyndns.com.
+relay2.ncc.co.za.
+ukeas.com.tw.
+www.msftncsi.com.
+platform.ak.fbcdn.net.
+porchsyndicate.com.
+it-it.facebook.com.
+www.blancasexxx.com.
+ares.uptodown.com.
+banners.iminent.com.
+apps.facebook.com.
+cartermcrae.com.
+profile.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+simssoc.game.playfish.com.
+valleymeat.com.
+landscapearchitectureresource.com.
+db.darthhater.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+mail2.gratefulpalate.com.
+151.237.236.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.facebook.com.
+www.germanbitch.de.
+photos-g.ak.fbcdn.net.
+www.portableworld.ru.
+www.youtube.com.
+photos-b.ak.fbcdn.net.
+api.facebook.com.
+a.root-servers.net.
+195.26.90.186.in-addr.arpa.
+mozilla-firefox.soft32.com.
+www.songwritersfestival.com.
+www.facebook.com.
+cdn.spotxchange.com.
+d.f.2.c.e.3.5.b.1.c.d.1.c.2.8.3.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+fashion.allwomenstalk.com.
+www.despertardetamaulipas.com.
+psgw.t-mobilesgws.com.
+a.root-servers.net.
+clubblockpost.ru.
+a.root-servers.net.
+public.liss.slidesharecdn.com.
+s.youtube.com.
+google.com.
+www.facebook.com.
+mail34.mimecast.co.za.
+archives1.twoplustwo.com.
+242.28.235.190.in-addr.arpa.
+75.192.141.190.in-addr.arpa.
+ad.yieldmanager.com.
+s.ytimg.com.
+www.vividforfree.com.
+a0.twimg.com.
+paragraphinc.com.
+homeaway.com.122.2o7.net.
+a7.sphotos.ak.fbcdn.net.
+ns1.easydns.com.
+rcp.eu.blackberry.com.
+d3j5vwomefv46c.cloudfront.net.
+sfilter.celizion.com.
+a.analytics.yahoo.com.
+www.girlsofheaven.com.
+sc2.rules.mailshell.net.
+v5.cache2.c.bigcache.googleapis.com.
+teredo.ipv6.microsoft.com.
+swisstab.be.
+hcxd88nly.11nx.
+142.31.130.41.in-addr.arpa.
+pagead2.googlesyndication.com.
+groups.google.com.mx.
+platform.twitter.com.
+novatube.com.
+www.google-analytics.com.
+www.macitynet.it.
+187.242.25.201.in-addr.arpa.
+ssl.gstatic.com.
+107.230.141.189.in-addr.arpa.
+www.kaspersky.com.
+profile.ak.fbcdn.net.
+lcucr.com.
+www.yahoo.com.
+touch.facebook.com.
+plusone.google.com.
+181.209.79.190.in-addr.arpa.
+nv68eht68.v88e7t3a.
+www.juegosbmxgratis.com.
+159.207.245.190.in-addr.arpa.
+dollar.uaportal.com.
+farm6.staticflickr.com.
+img2.mlstatic.com.
+fbcdn-profile-a.akamaihd.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+99.81.54.65.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+.
+smtpin.tdc.dk.
+42.127.199.76.in-addr.arpa.
+a.root-servers.net.
+204.1.168.192.in-addr.arpa.
+130.40.212.178.in-addr.arpa.
+s.ytimg.com.
+m.xp1.ru4.com.
+mail.tortnadom.ru.
+35.187.53.187.in-addr.arpa.
+v12.nonxt5.c.youtube.com.
+a.root-servers.net.
+csi.gstatic.com.
+ssl.google-analytics.com.
+www.jorditorre.com.
+_803_79_8.
+www9.effectivemeasure.net.
+sugiur.com.
+pixel.fetchback.com.
+mail.elliron.com.
+www.uach.cl.
+224.111.129.125.in-addr.arpa.
+www.tierradesoldados.com.
+mail.google.com.
+photos-b.ak.fbcdn.net.
+y:2bwibln.32cc.
+el-real-blog.blogspot.com.
+egal.com.
+1.85.19.186.in-addr.arpa.
+232.178.219.194.in-addr.arpa.
+www.herosmash.com.
+t.co.
+kred.com.
+ksn2-12.kaspersky-labs.com.
+a.root-servers.net.
+library.karelia.ru.
+a5.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+_229_73_2.
+www.dnanow.com.
+dc153.4shared.com.
+mobilelinuxinfo.com.
+138.253.168.192.in-addr.arpa.
+a.root-servers.net.
+9.138.122.187.in-addr.arpa.
+view.atdmt.com.
+relay.uep-cd.ru.
+google.com.
+www.bridgeguys.com.
+a.root-servers.net.
+21.180.35.177.in-addr.arpa.
+inbound.anchorsubaru.com.netsolmail.net.
+mail.sites-sw.com.
+baltimore.orioles.mlb.com.
+apps.facebook.com.
+time.chttl.com.tw.
+external.ak.fbcdn.net.
+92.253.250.201.in-addr.arpa.
+thumbs4.ebaystatic.com.
+105.165.151.85.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+dr._dns-sd._udp.lan.
+u.dd341c002d6d86bd.com.
+dns.msftncsi.com.
+trilliumcos.com.
+ssl.gstatic.com.
+www.youtube.com.
+ads2.msads.net.
+photos-g.ak.fbcdn.net.
+gekgo.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+static.ak.fbcdn.net.
+bisd.com.
+baggio.com.ar.
+webcache.googleusercontent.com.
+177.99.0.190.in-addr.arpa.
+dns.msftncsi.com.
+iiseutu.fi.
+noticias.es.msn.com.
+lighthousebaptist.com.1.arsmtp.com.
+teredo.ipv6.microsoft.com.
+d7.zedo.com.
+www.karritos.mx.
+www.surgjournal.com.
+pixel.facebook.com.
+i2.ytimg.com.
+creative.ak.fbcdn.net.
+cow_fb_cdn0-a.akamaihd.net.
+200.143.131.187.in-addr.arpa.
+d2092717.xoom.it.
+data.flurry.com.
+192.143.19.95.in-addr.arpa.
+cdn5-0.quizapps.com.
+243.46.112.186.in-addr.arpa.
+36.182.218.193.in-addr.arpa.
+138.140.225.77.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+157.29.180.69.in-addr.arpa.
+onlinux-fr.setupdns.net.
+www.amazon.com.
+izone.com.
+creative.ak.fbcdn.net.
+mail.roughbros.com.
+s1-powerpoint.vo.msecnd.net.
+kakputin.ru.
+58.68.171.201.in-addr.arpa.
+cdn.search.sweetim.com.
+ssl.gstatic.com.
+mail.stroisouz.ru.
+nhdayton.com.2.arsmtp.com.
+es.house.wikia.com.
+www.newbackdoor.com.
+wallstreetmtg.com.
+www.mancoraperu.com.
+systor.com.
+windsor.olx.ca.
+russianet.ru.
+43.76.37.46.in-addr.arpa.
+mvz.berkeley.edu.
+accounts.google.com.
+iasishealth.com.
+www.britishcolumbia.name.
+www.ringtonematcher.com.
+243.60.27.72.in-addr.arpa.
+pagead2.googlesyndication.com.
+mall.shinsegae.com.
+alhena3.blogspot.com.
+www.healthplanspain.com.
+146.16.76.184.in-addr.arpa.
+bloomstudio.ru.
+hackneycitizen.co.uk.
+a.triggit.com.
+14392e5a.linkbucks.com.
+invproj.ru.
+www.youtube.com.
+bestamateurland.com.
+248.91.173.190.in-addr.arpa.
+i2.ytimg.com.
+nationalholidays24.com.
+245.207.21.190.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.gamefaqs.com.
+tracker.ccc.de.
+es-la.facebook.com.
+profile.ak.fbcdn.net.
+www.aircleaners.com.
+ing-serv.ru.
+external.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+www.lesbianas.us.
+234.153.203.201.in-addr.arpa.
+pingoat.com.
+69.33.161.187.in-addr.arpa.
+www.kirkdunne.com.
+mail.midcomp.com.
+157.18.144.186.in-addr.arpa.
+ardeacap.com.
+www.alwaraq.net.
+us-w1.rockmelt.com.
+addvalue.com.
+a.root-servers.net.
+i3.imlive.com.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+mountaincement.com.mail9.psmtp.com.
+www.yajuegos.com.
+eabka.info.company.com.
+pics.gallery.weddingbee.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mbmo-online.ru.
+fam.gigabox.info.
+123.231.248.182.in-addr.arpa.
+www.chacovende.com.
+www.crazymikesapps.com.
+a4.sphotos.ak.fbcdn.net.
+imageseu.fewo-direkt.de.
+icons.cubics.com.
+www.google-analytics.com.
+138.45.59.186.in-addr.arpa.
+www.tuenti.com.
+a.root-servers.net.
+s.youtube.com.
+sp.cwfservice.net.
+mediostransporte.blogspot.com.
+madhouse110.fsnet.co.uk.
+ajax.googleapis.com.
+mail.vikingsoutheast.com.
+a8.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+mail2.provcorp.com.
+proactusa.com.inbound15.mxlogic.net.
+mx.siberia-zeo.ru.
+assets.zestadz.com.
+t5.tagstat.com.
+i4.ytimg.com.
+a1125.phobos.apple.com.
+vistamfg.com.inbound10.mxlogic.net.
+pixel.facebook.com.
+44.115.125.186.in-addr.arpa.
+g.live.com.
+i-cdn.servedbyopenx.com.
+172.38.251.189.in-addr.arpa.
+www.alanbaxteronline.com.
+_199_49_2.
+mx5.perusion.com.
+mysticsaint.blogspot.com.
+youtu.be.
+14.190.98.62.in-addr.arpa.
+jensen.mail.dk.
+d2089619.xoom.it.
+.
+dns.msftncsi.com.
+tienda.levante-emv.es.
+1.bp.blogspot.com.
+www.google-analytics.com.
+www.apps4rent.com.
+mail.secnrs.ru.
+wastewater.ru.
+www.youtube.com.
+gameplay.mochimedia.com.home.
+www.killersofeden.com.
+dns.msftncsi.com.
+platform.ak.fbcdn.net.
+s-external.ak.fbcdn.net.
+usage.hosting.toolbar.conduit-services.com.
+watson.microsoft.com.
+avillage.web.virginia.edu.
+www.blogspottemplate.com.
+122.18.122.189.in-addr.arpa.
+191.230.21.187.in-addr.arpa.
+mail.doverphila.com.
+a3.sphotos.ak.fbcdn.net.
+smtp.alfredstate.edu.
+0.11-2300a008.e1032.1518.19d4.3ea1.410.0.kjzwb3lh5n28ezha8i1alrbphq.avqs.mcafee.com.
+i3.ytimg.com.
+c5x4h.dyndns.org.
+proxy.ncc.nnov.ru.
+52.17.156.189.in-addr.arpa.
+a-m-b-i-v-a-l-e-n-c-e.tumblr.com.
+check4.facebook.com.
+static.a.gs-cdn.net.
+gsi.pl.
+weather.services.conduit.com.
+www.soapoperadigest.com.
+m.facebook.com.
+m.addthisedge.com.
+s-static.ak.facebook.com.
+se8od84j5.m34g8u4u.
+s.skimresources.com.
+www.reit.com.
+www.facebook.com.
+28.239.215.201.in-addr.arpa.
+www.usasexguide.info.
+174.37.211.201.in-addr.arpa.
+62.239.66.199.in-addr.arpa.
+h.live.com.
+ad.yieldmanager.com.
+97.188.138.201.in-addr.arpa.
+www.facebook.com.
+phissc6mj.j68r1u3w.
+smtpx2.fpcusa.com.
+a3.sphotos.ak.fbcdn.net.
+modavestidos.es.
+49.204.139.187.in-addr.arpa.
+72.11.231.189.in-addr.arpa.
+r._dns-sd._udp.0.55.211.10.in-addr.arpa.
+115.54.1.190.in-addr.arpa.
+234.62.51.170.in-addr.arpa.
+101.206.42.181.in-addr.arpa.
+54.59.105.190.in-addr.arpa.
+pixel.invitemedia.com.
+mvusd.net.
+i1.ytimg.com.
+a.root-servers.net.
+video.google.com.mx.
+63.170.23.79.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+hotmail.com.
+centennialwireless.com.
+bbcore.cloudapp.net.
+www.thekyotoconnection.com.
+www.revodvr.com.
+www.wrangler.com.
+distilleryimage2.s3.amazonaws.com.
+www.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+ntp.glb.nist.gov.
+portales.puj.edu.co.
+fkepygflaoh.ws.
+balas-celebs.com.
+223.183.78.186.in-addr.arpa.
+a.root-servers.net.
+galagans.com.
+www.elgrancatador.com.
+download.mozilla.org.
+rad.msn.com.
+ayuban.com.
+a.root-servers.net.
+kasut.net.
+172.121.157.69.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+52.106.2.42.in-addr.arpa.
+a.mx.icetalk.com.
+rucrj4p4u.85rp.
+external.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+somosmovies.disqus.com.
+api.geo.kontagent.net.
+sp.cwfservice.net.
+www.kt2syggf436dtag106.com.
+cont-dc6-2.pandora.com.
+www.facebook.com.
+api.twitter.com.
+www.google-analytics.com.
+www.timwe.com.
+jobs.cgsociety.org.
+safebrowsing.clients.google.com.
+a8.sphotos.ak.fbcdn.net.
+www.poikosoft.com.
+sbcglobel.net.
+www.pagerank.si.
+profile.ak.fbcdn.net.
+3ba1f48a4b3e87fbdcea52325266e210.info.
+www.courts.state.hi.us.
+124.176.21.115.in-addr.arpa.
+static.xvideos.com.
+www.eyedocs.co.uk.
+trc-tempe.com.
+googleads.g.doubleclick.net.
+86.238.117.208.in-addr.arpa.
+35.110.111.109.in-addr.arpa.
+a.root-servers.net.
+229.109.138.69.in-addr.arpa.
+wap.jamster.com.
+www.facebook.com.
+ipeinc.com.
+51.14.236.201.in-addr.arpa.
+195.214.186.189.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+saturnkmv.ru.
+40.12.198.187.in-addr.arpa.
+instagram.com.
+www.viki.net.
+168.90.55.65.sbl-xbl.spamhaus.org.
+www.wiworks.com.
+click.infospace.com.
+us.bc.yahoo.com.
+a6.sphotos.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+es-la.facebook.com.
+203.241.60.125.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+303.gt2.vkadre.ru.
+www.ekospor.com.
+naia-design.com.
+estaticos02.marcaplayer.com.
+liveupdate.symantecliveupdate.com.
+www.whitesmoke.com.
+cs11445.vk.com.
+www.netflix.com.
+photos-h.ak.fbcdn.net.
+9dkl1xkjk.u44o7m3c.
+www.kare11.com.
+www.massmediamail.com.
+backlink.elchoclo.net.
+www.google.com.
+www.grinshare.com.
+wnyahl.com.
+twitter.com.
+210.3.24.188.in-addr.arpa.
+ns2.ameritech.net.
+static1.putlocker.com.
+api.facebook.com.
+a.root-servers.net.
+sp.cwfservice.net.
+www.womens-health-advice.com.
+host26.taxcom.ru.
+smyt.ru.
+10.1.168.192.in-addr.arpa.
+118.205.74.200.in-addr.arpa.
+152.143.239.190.in-addr.arpa.
+recreationland.net.
+webcache.googleusercontent.com.
+144.12.133.78.in-addr.arpa.
+ns7.dnsmadeeasy.com.
+farmacap.it.
+ajax.googleapis.com.
+www.mysatin.com.
+silkroad4gold.com.
+svp.co.uk.
+platform.ak.fbcdn.net.
+narutorev3wii.natneg1.gs.nintendowifi.net.
+pixel.facebook.com.
+149.118.152.201.in-addr.arpa.
+turt.aclap.com.
+www.adserve.com.
+www.volaris.mx.
+ads.us.e-planning.net.
+34.104.201.187.in-addr.arpa.
+southeastern.stokes.k12.nc.us.
+a.root-servers.net.
+5.23.143.201.in-addr.arpa.
+74.112.36.177.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.youtube-nocookie.com.
+profile.ak.fbcdn.net.
+www.amw.com.
+websearch.ask.com.
+static.app.widdit.com.
+appraiserdepot.com.
+www.lageografiadelmundo.com.
+www.desmotivado.es.
+mail.iq-networks.ru.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+64.149.229.99.in-addr.arpa.
+mail-in.daimler.com.
+mail.spangenbergphillips.com.
+pqvpsisuyrgywmaeywjjsuudr.so.
+127.184.227.78.in-addr.arpa.
+123.192.117.70.in-addr.arpa.
+jatek.origo.hu.
+inbound.jnshh.com.netsolmail.net.
+groszassociates.com.
+software-files-a.cnet.com.
+ikcstatic.krazystatic.com.
+www.downtownbahostel.com.
+www.radiomelodia.com.pe.
+_ldap._tcp.
+217.44.105.190.in-addr.arpa.
+camerussia.ru.
+fbcdn-profile-a.akamaihd.net.
+configuration.apple.com.
+13.227.103.93.in-addr.arpa.
+www.monografias.com.
+photos-h.ak.fbcdn.net.
+65.247.1.181.in-addr.arpa.
+s-static.ak.facebook.com.
+190.41.4.186.in-addr.arpa.
+mxserv1.swisstimeclub.ru.
+a995.mm1.akamai.net.
+47.88.204.190.in-addr.arpa.
+horoscopos.prodigy.msn.com.
+s2.youtube.com.
+xwweaasj.cn.
+chat3.doook.com.
+cp36268.edgefcs.net.
+mx02.bis.na.blackberry.com.
+104.41.121.84.in-addr.arpa.
+58.163.171.69.in-addr.arpa.
+newsrss.bbc.co.uk.
+www.myaudiq5.com.
+mcvax4.d48.lilly.com.
+twitter.com.
+steklo.renet.ru.
+a5.sphotos.ak.fbcdn.net.
+www.prediccionesytarot.com.
+photos-e.ak.fbcdn.net.
+pasullivan.com.mt.
+9.94.200.195.zen.spamhaus.org.
+thomas.gov.
+au.download.windowsupdate.com.
+gazinvest.ru.
+31.107.37.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+42.91.177.76.in-addr.arpa.
+www.google.com.
+bing.com.
+titanium30-en.url.trendmicro.com.
+www.facebook.com.
+33.7.31.189.in-addr.arpa.
+by2msg3020507.gateway.messenger.live.com.
+www.javatutoriales.com.
+uv2adglzi.77vf.
+a.root-servers.net.
+17.60.149.187.in-addr.arpa.
+creative.ak.fbcdn.net.
+webssl.com.
+184.35.166.190.in-addr.arpa.
+189.157.168.192.in-addr.arpa.
+www.xdir.com.
+219.45.161.189.in-addr.arpa.
+126.172.115.186.in-addr.arpa.
+a.root-servers.net.
+clubtochka.ru.
+a.root-servers.net.
+studiobritney.ning.com.
+voipb.sip.yahoo.com.
+crl.godaddy.com.
+quebecoworld.com.
+mail.yahoo.com.
+www.wildfatties.com.
+internationalmarinellc.com.s5a1.psmtp.com.
+connect.facebook.net.
+www.fncstatic.com.
+developers.facebook.com.
+www.facebook.com.
+foursquare.com.
+qjr1raiva.12bk.
+photos-g.ak.fbcdn.net.
+kokugai.com.
+au.download.windowsupdate.com.
+js.wlxrs.com.
+bs.serving-sys.com.
+www.conduit.com.
+saibos-services.com.
+blog.es.twitter.com.
+api.facebook.com.
+55.102.186.189.in-addr.arpa.
+www.gfjapan.com.
+a.root-servers.net.
+mxav2.amecom.it.
+107.234.234.189.in-addr.arpa.
+sp.cwfservice.net.
+myfeasts.blogspot.com.
+a1877.phobos.apple.com.
+_500_41_8.
+88.14.124.190.in-addr.arpa.
+mail2.citywide.com.au.
+news.google.com.mx.
+10.147.252.119.in-addr.arpa.
+voipa.sip.yahoo.com.
+developers.facebook.com.
+150.238.120.186.in-addr.arpa.
+www.digitalfotoclub.com.
+ec.atdmt.com.
+9-1.qlty.finarea.ch.
+.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ads27908.hotwords.com.br.
+mail3.cs.state.ny.us.
+www.facebook.com.
+34.58.138.201.in-addr.arpa.
+159.118.47.189.in-addr.arpa.
+motd.fumadorasguarras.com.
+segment-pixel.invitemedia.com.
+rabanco.com.
+a6.sphotos.ak.fbcdn.net.
+tobolsk.info.
+m.addthisedge.com.
+static.ak.fbcdn.net.
+www.elblogdechuchus.com.
+51.131.159.190.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+liteapps.mcafee.com.
+www.alexanderrichterphoto.com.
+s-assets.tp-cdn.com.
+ocsp.comodoca.com.
+www.monsterdivx.com.
+www.allsaints.com.
+sp.cwfservice.net.
+photos-d.ak.fbcdn.net.
+themes.googleusercontent.com.
+224.86.171.59.in-addr.arpa.
+www.elmundonewspaper.com.
+teredo.ipv6.microsoft.com.
+17.14.168.192.in-addr.arpa.
+s-external.ak.fbcdn.net.
+accounts.google.com.
+www.facebook.com.
+www.directferries.sk.
+downloads.networkmagic.com.
+a.root-servers.net.
+accounts.google.com.
+nimturbo.ru.
+mail.in.ptpgh.com.
+a1.sphotos.ak.fbcdn.net.
+ru.norton.com.
+149.178.138.201.in-addr.arpa.
+htp.net.
+www.rockambul.com.
+152.169.120.87.in-addr.arpa.
+decoracionesyeventos.blogspot.com.
+ns2sw1.amhost.info.
+ls2web.redmond.corp.microsoft.com.
+3.2.144.189.in-addr.arpa.
+mail.broganuk.com.
+86.110.110.189.in-addr.arpa.
+market.android.com.
+alternatedjvu.sourceforge.net.
+www.nubesnegras.com.
+twsu.campus.mci.net.
+static.ak.fbcdn.net.
+www.dramastyle.com.
+www.facebook.com.
+149.211.212.108.in-addr.arpa.
+akamai.turn.com.
+voipa.sip.yahoo.com.
+imagenescelestiales.blogspot.com.
+rs409l36.rapidshare.com.
+www.wiroos.com.
+iebinc.com.
+cambosoup.blogspot.com.
+i.ytimg.com.
+www.facebook.com.
+dl27.hotgoo.com.
+www.shelterpub.com.
+ar-ar.facebook.com.
+www.assoc-amazon.com.
+es-la.facebook.com.
+apps.facebook.com.
+ven.nvidia.com.
+id1.java551.come2play.com.
+weather.service.msn.com.
+206.61.38.190.in-addr.arpa.
+www.argskill.com.
+api.facebook.com.
+img24.imageshack.us.
+a745.g.akamai.net.
+www.hibon.com.
+signin.ebay.com.
+forum.lingvo.ru.
+never-let-me-go.foroactivo.com.
+ipn.academia.edu.
+conntest.nintendowifi.net.
+static.ak.fbcdn.net.
+_095_96_2.
+a.root-servers.net.
+es.kioskea.net.
+a0.twimg.com.
+mail.tridon.com.
+bayal.blogspot.com.
+translate.google.co.ve.
+www.polesports.org.
+www.facebook.com.
+static.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+primecountry.com.
+georges-flowers.com.
+pop.aol.com.
+pacifichealthcorp.com.s8b1.psmtp.com.
+essentialhomme.com.
+www.tradearabia.com.
+byfiles.storage.msn.com.
+www.tecamachalco.mobi.
+www.ubiqua.net.
+external.ak.fbcdn.net.
+webassets.sparkybee.com.
+11.239.162.200.in-addr.arpa.
+www.livecams.com.
+www.iabperu.com.
+www.ritmosonlaino.com.
+mailhost.ahigroup.com.
+www.faceook.com.
+www.reduc.edu.cu.
+au.download.windowsupdate.com.
+cdn.kakuroconquest.com.
+mexicanainforma.com.
+www.math.grin.edu.
+external.ak.fbcdn.net.
+validator.w3.org.
+resumejob.ru.
+www.cheapmonclerjacketsale.co.uk.
+boblemke.blogspot.com.
+www.massiveassaultnetwork.com.
+mail.claasindia.com.
+cs12843.vk.com.
+www.jiriruzek.net.
+a.root-servers.net.
+nedschroef.be.
+lascincoestaciones.blogspot.com.
+www.blogherads.com.
+app.offer99.com.
+www.openclik.com.
+www.msftncsi.com.
+u14.eset.com.lan.
+a1.sphotos.ak.fbcdn.net.
+www.facebook.com.
+chemcentral.com.s8a1.psmtp.com.
+www.oxfamnovibpaktuit.nl.
+stlarshabos.dotheortontab.tk.
+a2.sphotos.ak.fbcdn.net.
+atlantic-pub.com.bak-mx.na0104.smtpbak.com.
+www.todoanimes.com.
+check4.facebook.com.
+87.26.45.24.in-addr.arpa.
+rapidcityrec.com.
+153.228.151.79.in-addr.arpa.
+pixel.facebook.com.
+253.105.92.78.in-addr.arpa.
+_344_85_7.
+lyrics.tunewiki.com.
+299.channel.facebook.com.
+idisk.mac.com.
+www.google-analytics.com.
+www.casinoval.com.
+www.ons.mr.
+bluehatuk.com.inbound10.mxlogicmx.net.
+www.ttfn.net.
+teredo.ipv6.microsoft.com.
+middlefokpartners.com.
+leproduct.com.inbound10.mxlogic.net.
+childrensmemorial.org.
+www.ford.nl.
+129.32.212.189.in-addr.arpa.
+94.69.47.189.in-addr.arpa.
+www.xvideoslive.com.
+www.google-analytics.com.
+tps31.doubleverify.com.
+byfiles.storage.msn.com.
+revista-zoom.com.ar.
+blairwilliams.com.
+photos-f.ak.fbcdn.net.
+rcp.na.blackberry.com.
+postfix1.vitro.epldt.net.
+time.chttl.com.tw.
+www.pnosker.com.
+13.184.38.190.in-addr.arpa.
+m.addthisedge.com.
+www.charlestonbusiness.com.
+dns.msftncsi.com.
+www.servercraft.co.
+benz4ever.com.
+images2.culiarmedia.com.
+external.ak.fbcdn.net.
+154.53.115.190.in-addr.arpa.
+188.134.88.186.in-addr.arpa.
+37-courier.push.apple.com.
+104.226.10.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+_275_66_5.
+b._dns-sd._udp.lan.
+cox-iternet.com.
+s-static.ak.facebook.com.
+platform.twitter.com.
+spm02.pinehost.net.
+www.facebook.com.
+26.116.81.68.in-addr.arpa.
+addons.mozilla.org.
+www.informatica.ith.mx.
+whos.amung.us.
+www.google-analytics.com.
+i2.ytimg.com.
+ads1.msads.net.
+109.179.82.200.in-addr.arpa.
+www.royalskandia.com.
+dbcc.edu.
+contextmenu.toolbar.conduit-services.com.
+pixel.quantserve.com.
+upload.wikimedia.org.
+external.ak.fbcdn.net.
+mercuryexcelum.com.1.0001.arsmtp.com.
+dcbrands.com.s6b2.psmtp.com.
+arabic.arabia.msn.com.
+a.root-servers.net.
+150.151.228.190.in-addr.arpa.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+178.140.246.201.in-addr.arpa.
+5.78.216.178.in-addr.arpa.
+218.53.199.190.in-addr.arpa.
+www.alu-stock.es.
+0-jx-w.channel.facebook.com.
+sp.cwfservice.net.
+pixel.facebook.com.
+90.24.160.187.in-addr.arpa.
+fr-fr.facebook.com.
+photos-d.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.googleadservices.com.
+ip1.dynupdate.no-ip.com.
+g.live.com.
+amathusvip.ru.
+tbr.ask.com.
+photos-a.ak.fbcdn.net.
+www.european-podcast-award.eu.
+www.purnas.com.
+cowboy.com.
+100.155.60.186.in-addr.arpa.
+event-post.ru.
+www.facebook.com.
+time.windows.com.
+profile.ak.fbcdn.net.
+7.134.121.124.in-addr.arpa.
+cricket-league-of-champions.en.softonic.com.
+curriculo.catho.com.br.
+apple-mobile.query.yahooapis.com.
+photos-a.ak.fbcdn.net.
+118.208.122.189.in-addr.arpa.
+external.ak.fbcdn.net.
+35.198.132.190.in-addr.arpa.
+tc22.easythumbhost.com.
+ws-cloud-msgplus.linkury.com.
+fei9988.3322.org.
+photos-g.ak.fbcdn.net.
+rcm-fr.amazon.fr.
+winstar.com.
+l-e.com.s6a2.psmtp.com.
+et5.xhamster.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s0.2mdn.net.
+r.mzstatic.com.
+msgs.smarterfox.com.
+176.235.29.186.in-addr.arpa.
+mcsoh.org.
+www.tyrone-power.com.
+tc.v16.cache8.c.youtube.com.
+179.75.235.189.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+mets.crb.apmoller.net.
+d.yimg.com.
+74.54.174.189.in-addr.arpa.
+sphotos.ak.fbcdn.net.
+et7.xhamster.com.
+tdkarat.ru.
+productosweb.org.
+36.194.3.188.in-addr.arpa.
+api.twitter.com.
+a.root-servers.net.
+sedonasouladventures.com.
+127.106.135.110.in-addr.arpa.
+146.232.19.83.in-addr.arpa.
+8wbhurv6l.w55v3k9p.
+207.212.179.189.in-addr.arpa.
+www.google-analytics.com.
+www.quantumtouch.com.
+videobam.com.
+24.248.69.186.in-addr.arpa.
+service.homepages.demon.net.
+sp.cwfservice.net.
+sarah-london.blogspot.com.
+websearch.ask.com.
+mightydeals.s3.amazonaws.com.
+a.root-servers.net.
+img.fewdress.com.
+a.root-servers.net.
+gamcaretradeservices.com.
+developers.facebook.com.
+www.matiogi.com.
+t.co.
+www.facebook.com.
+www.nme.com.
+courrier.fadq.qc.ca.
+checkip.dyndns.com.
+244.120.35.62.in-addr.arpa.
+142.49.232.24.in-addr.arpa.
+mail.mrdelaw.com.
+8.101.123.186.in-addr.arpa.
+162.224.58.186.in-addr.arpa.
+a.root-servers.net.
+xiscoekzo.files.wordpress.com.
+106.206.214.189.in-addr.arpa.
+www.youtube.com.
+pixel.facebook.com.
+lh6.googleusercontent.com.
+www.newincredimail.com.
+mail.bankofoldmonroe.com.
+134.66.210.186.in-addr.arpa.
+yahoo.com.
+members.graphicsfactory.com.
+vincitori.wordpress.com.
+ad.yieldmanager.com.
+loading.ninja.game321.com.
+cdn.smosh.com.
+www.cymax.com.
+webgetclick.com.home.
+a.root-servers.net.
+s2.youtube.com.
+em1x-198.lhr.messaging.nokia.com.
+hasancanbozkurt.net.
+auditsonmer.blogspot.com.
+wispresort.com.inbound15.mxlogicmx.net.
+googleads.g.doubleclick.net.
+aptitudequestionsandanswers.in.
+api.twitter.com.
+www.openpa.net.
+trivantisdev.com.
+www.whitefrog.org.
+rs233l34.rapidshare.com.
+1804289383.localhost.
+sagesoftware.com.
+utess.ru.
+view.atdmt.com.
+223.89.19.95.in-addr.arpa.
+s2.youtube.com.
+247.219.155.189.in-addr.arpa.
+www.facebook.com.
+mail.onlinenetworking.com.
+dns.msftncsi.com.
+com-pac.com.
+aflex.ru.
+www.b2bonlinesolutions.com.
+rmd.atdmt.com.
+www.northropandjohnson.com.
+www.changesxchange.com.
+133.5.223.14.in-addr.arpa.
+_882_86_3.
+time.chttl.com.tw.
+profile.ak.fbcdn.net.
+thumbs.totale-defonce.com.
+profile.ak.fbcdn.net.
+johnsonmoncrief.com.
+_ldap._tcp.
+news.yahoo.com.
+tropicfishhawaii.com.
+www.wallsoffame.com.
+m.facebook.com.
+gobrainstrom.net.
+mail.empireindustries.com.
+securemetrics.apple.com.
+www.google.com.
+canal.univalle.edu.co.
+lasenoritalasenorita.blogspot.com.
+mail.puratone.com.
+chart.vgmc.com.
+133.212.32.72.in-addr.arpa.
+a.root-servers.net.
+banashare.com.
+info.babylon.com.
+dl-debug32.dropbox.com.
+167.143.58.186.in-addr.arpa.
+wxxr3vy4e.r02r9f2r.
+201.67.25.186.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+s3-eu-west-1.amazonaws.com.
+services.runescape.com.
+pagead2.googlesyndication.com.
+www.wallpaperfans.com.
+googleads.g.doubleclick.net.
+google.com.
+juventudenmarcha.wordpress.com.
+accounts.google.com.
+hotmail.com.
+www.redtube.com.
+img193.imageshack.us.
+z8ojttuzg.06nx.
+static.ak.fbcdn.net.
+aleksey.tver.ru.
+.
+9.77.43.190.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+189.103.119.83.in-addr.arpa.
+www.naqatube.com.
+cgi1.ebay.com.
+hwqm9j9r7.w38c8o7h.
+mail.micmedia.ru.
+www.noisemachine.com.
+35.156.22.50.in-addr.arpa.
+apps.facebook.com.
+17.26.140.200.in-addr.arpa.
+a.root-servers.net.
+google.com.
+138.255.28.80.in-addr.arpa.
+73.238.200.195.in-addr.arpa.
+www.markosweb.com.
+www.megasecurity.org.
+oscsm3y2r.99qe.
+fvg.cgil.it.
+gunsnrosesbootlegs.blogspot.com.
+niunomas.foroactivo.com.
+www.pe.pirelli.com.
+www.actualizar-messenger.com.
+122.49.103.76.in-addr.arpa.
+media.admob.com.
+113.23.168.192.in-addr.arpa.
+gepigeny.hu.
+170.89.102.71.in-addr.arpa.
+a.root-servers.net.
+web59516.mail.ac4.yahoo.com.
+i3.ytimg.com.
+a.root-servers.net.
+a6.sphotos.ak.fbcdn.net.
+3c2is992:.e41v2m1d.
+admin.mundotoro.com.
+aidps.atdmt.com.
+d2060193.instant.xoom.it.
+cdn.fastclick.net.
+photos-c.ak.fbcdn.net.
+www.funnyhub.com.
+www.gstatic.com.
+229.184.22.107.in-addr.arpa.
+tele2adsl.dk.home.
+a6.sphotos.ak.fbcdn.net.
+cdn.widgets.spongecell.com.
+photos-e.ak.fbcdn.net.
+79.99.96.58.in-addr.arpa.
+35.184.79.190.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+abanfin.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+powervoice.at.
+telaquecortar.wordpress.com.
+photos-g.ak.fbcdn.net.
+.
+36.102.13.187.in-addr.arpa.
+safebrowsing-cache.google.com.
+rendezvous.blogs.nytimes.com.
+4.36.203.190.in-addr.arpa.
+frnx9q8kd.22ll.
+87.14.62.186.in-addr.arpa.
+luzverdadeterna.blogspot.com.
+news.ino.com.
+profile.ak.fbcdn.net.
+a12.t26.net.
+u.openx.net.
+elseruno-gallery.blogspot.com.
+192.40.198.190.in-addr.arpa.
+a.root-servers.net.
+twitter.com.
+66.170.255.201.in-addr.arpa.
+goo.gl.
+rcp.eu.blackberry.com.
+photos-d.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+.
+235.31.249.201.in-addr.arpa.
+time.stdtime.gov.tw.
+167.47.231.77.in-addr.arpa.
+secure-us.imrworldwide.com.
+104.133.142.189.in-addr.arpa.
+158.77.154.189.in-addr.arpa.
+122.254.60.78.in-addr.arpa.
+223.226.110.186.in-addr.arpa.
+www.facebook.com.
+profile.ak.fbcdn.net.
+173.176.92.212.in-addr.arpa.
+db1.stat.gov.lt.
+sbcglobal.net.
+www.facebook.com.
+www.ca.uky.edu.
+a1820.phobos.apple.com.
+sv.monkeybroker.net.
+code.jquery.com.
+107.166.10.186.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a0.twimg.com.
+_ldap._tcp.
+co123w.col123.mail.live.com.
+time.chttl.com.tw.
+www.20minutos.es.
+www.traductordepaginasweb.com.
+koala.webeasy.com.
+ifxchange.appspot.com.
+www.despegar.com.
+43.177.47.190.in-addr.arpa.
+sp.cwfservice.net.
+ar-ar.facebook.com.
+140.187.130.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.aaronvaldez.com.
+teredo.ipv6.microsoft.com.
+photos-b.ak.fbcdn.net.
+smtp.mtsolutions.net.
+154.26.27.187.in-addr.arpa.
+plusone.google.com.
+bmw-vw.tk.
+a-ak.static-rootmusic.com.
+pixel.facebook.com.
+profile.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+entertainment-memorabilia.shop.ebay.com.
+assets3.castle.zgncdn.com.
+1.19.29.186.in-addr.arpa.
+www.heymister.net.
+l.sharethis.com.
+75.90.23.69.in-addr.arpa.
+www.linkedin.com.
+web39207.mail.mud.yahoo.com.
+i1gpwuhrk.p88i6r3u.
+www.l.google.com.
+router.tlvmedia.com.
+orcart.facebook.com.
+mobth915.photobucket.com.
+15.58.209.201.in-addr.arpa.
+yahoo.de.
+www.theecommercepro.com.
+fbcdn-profile-a.akamaihd.net.
+www.margaritabonita.com.
+pixel.facebook.com.
+.
+www.minigamesfreak.com.
+a3.sphotos.ak.fbcdn.net.
+store.grooveshark.com.
+a.root-servers.net.
+www.meowmistidawn.com.
+support.google.com.
+www.biap.org.
+support.google.com.
+a.root-servers.net.
+darling.artmodelingstudios.com.
+www.unknownnews.net.
+www.facebook.com.
+www.greekairsoft.gr.
+www.monografias.com.
+www.le-maitre-du-chaos.skyrock.com.
+safebrowsing.clients.google.com.
+superiorwallsystems.com.
+95.36.209.189.in-addr.arpa.
+praetoriangroup.com.s6a1.psmtp.com.
+www.google.com.
+199.208.122.84.in-addr.arpa.
+fxfeeds.mozilla.com.
+sthi.com.inbound10.mxlogic.net.
+4t8yva9ap.v06m0j7r.
+www.youtube.com.
+www.penews.com.
+_500_61_5.
+www.youtube.com.
+jeffmo.us.
+chromejs.s3.amazonaws.com.
+i4.ytimg.com.
+010b36352e35342e36312e39340c40686f746d61696c2e636f6d00.lbl8.mailshell.net.
+media.elnuevoheraldo.com.
+i2.ytimg.com.
+www.facebook.com.
+l.yimg.com.
+www.mascotas.org.
+www.gardenphotos.com.
+71.232.240.189.in-addr.arpa.
+ku7t46lw9.e36k5v2b.
+safebrowsing-cache.google.com.
+a747.v.phobos.apple.com.
+emob178.photobucket.com.
+a.c-0.19-a30fb000.30011.1518.19d4.3ea1.210.0.k5gu7j63sb9mz9wvg8g2f9uart.avqs.mcafee.com.
+s1-onenote.vo.msecnd.net.
+developers.facebook.com.
+39.65.3.186.in-addr.arpa.
+_257_43_8.
+www.bytepr.com.
+rus-eda.ru.
+external.ak.fbcdn.net.
+www.itait.org.mx.
+dj7nmfd6odmeo.cloudfront.net.
+33.66.91.186.in-addr.arpa.
+s.youtube.com.
+traauctions.com.
+summit.retailcustomerexperience.com.
+60.149.157.189.in-addr.arpa.
+245.13.73.190.in-addr.arpa.
+b.scorecardresearch.com.
+businessdailyreview.com.
+ad.yieldmanager.com.
+97.134.225.186.in-addr.arpa.
+22.197.6.187.in-addr.arpa.
+www.shell-storm.org.
+s-static.ak.fbcdn.net.
+lulila21.blogspot.com.
+profile.ak.fbcdn.net.
+255.235.254.190.in-addr.arpa.
+clients2.google.com.
+mich.edu.
+www.googleadservices.com.
+37.244.236.98.in-addr.arpa.
+www.foxsportsla.com.
+sites.google.com.
+dron.beth.com.
+www.google.com.
+231.19.233.190.in-addr.arpa.
+.
+sites.google.com.
+cribreak.com.
+iphone-wu.apple.com.
+profile.ak.fbcdn.net.
+secure.drilledmouths.com.
+a.root-servers.net.
+idonno.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+46.233.227.189.in-addr.arpa.
+www.facebook.com.
+amherst.k12.wi.us.
+1.37.112.190.in-addr.arpa.
+orcart.facebook.com.
+lb._dns-sd._udp.lan.
+mx.youtube.com.
+www.google.com.
+a8.sphotos.ak.fbcdn.net.
+connecta-2000.softonic.com.
+whatismyip.org.
+cdn.api.twitter.com.
+gwpjosae2.b88m7j2n.
+headbangorgtfo.files.wordpress.com.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+.
+161.226.194.180.in-addr.arpa.
+updatekeepalive.mcafee.com.
+mail-pz0-f47.google.com.
+mx.answers.yahoo.com.
+sp.cwfservice.net.
+clients1.google.com.
+www.switchnode.com.
+gaiaware.net.
+www.servidoresrack.com.
+t1.gstatic.com.
+jorgebarontelevision.com.co.
+a.root-servers.net.
+my.ebay.com.
+thailandpopper.com.
+conn.skype.com.
+community.d.xx.openx.com.akadns.net.
+loading2.widdit.com.
+97.158.188.190.in-addr.arpa.
+countduhmoney.com.
+android.clients.google.com.
+thedesignsuperhero.com.
+107.130.64.186.in-addr.arpa.
+pixel.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+exp02.eset.com.
+livefiles18.vo.msecnd.net.
+238.123.24.201.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+comtrend.com.ua.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+baymsg1010734.by2.gateway.edge.messenger.live.com.
+www.gfxrls.com.
+denshou.wordpress.com.
+a1725.l.akamai.net.
+photos-f.ak.fbcdn.net.
+kdoudyxnkxuusofs.info.
+vthumb.ak.fbcdn.net.
+tap2-cdn.rubiconproject.com.
+ajax.googleapis.com.
+dsn3.d.skype.net.
+clients1.google.com.
+juegos.latino.msn.com.
+s-external.ak.fbcdn.net.
+www.vicensvives.com.co.
+www.facebook.com.
+photos-h.ak.fbcdn.net.
+images0-ig-opensocial.googleusercontent.com.
+architetto-casa.blogautore.repubblica.it.
+i1.ytimg.com.
+news.google.com.mx.
+www.buenscoring.com.
+apps.facebook.com.
+ssl.gstatic.com.
+pixel.facebook.com.
+ad.yieldmanager.com.
+ali-299.zapto.org.
+179.35.199.190.in-addr.arpa.
+external.ak.fbcdn.net.
+toolbar.google.com.
+179.174.163.189.in-addr.arpa.
+www.cocukoyunlari4.com.
+144.68.29.186.in-addr.arpa.
+2.9.c.f.8.0.6.8.2.5.2.2.f.0.c.3.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+alleventsgroup.com.
+99.25.106.95.in-addr.arpa.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+57.98.183.83.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+ssl.google-analytics.com.
+_ldap._tcp.
+rs342tl5.rapidshare.com.
+api.twitter.com.
+ocsp.thawte.com.
+www.instalacionesdeportivas.es.
+profile.ak.fbcdn.net.
+weatherhistory.almanac.com.
+funbike.com.
+pnrws.skype.com.
+itunes.apple.com.
+profile.ak.fbcdn.net.
+www.calendarclub.co.uk.
+pix04.revsci.net.
+134.220.230.190.in-addr.arpa.
+pintandoluces.blogspot.com.
+clients2.google.com.
+7.189.166.78.in-addr.arpa.
+safebrowsing-cache.google.com.
+blog.fo.ifeng.com.
+developers.facebook.com.
+sn133w.snt133.mail.live.com.
+jebo.ru.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+zbsbms7lm.62zh.
+time.chttl.com.tw.
+urbansketchers-moscow.blogspot.com.
+jus.com.br.
+www.google-analytics.com.
+it-it.facebook.com.
+mail2.motion-ind.com.
+mail2.gidinvest.ru.
+www.adobe.com.
+android.clients.google.com.
+mail.ruentex.com.tw.
+www.action-games.co.
+www.juegosmz.com.
+175.107.13.80.in-addr.arpa.
+wunruxzcdu.net.home.
+a.root-servers.net.
+foxpool.com.
+www.khosoof.com.
+87.165.22.190.in-addr.arpa.
+114.213.168.82.in-addr.arpa.
+www.multilateralfund.org.
+227.225.240.84.in-addr.arpa.
+crl.microsoft.com.
+apps.facebook.com.
+www.compresores.redee.com.
+mineracholino.com.ar.
+static.ak.fbcdn.net.
+0-jh-w.channel.facebook.com.
+t0.gstatic.com.
+horizonfinancial.org.
+a4.sphotos.ak.fbcdn.net.
+www.sinembargo.mx.
+dns.msftncsi.com.
+beacon-1.newrelic.com.
+pool.ntp.org.
+refresh.monohrome.com.
+profile.ak.fbcdn.net.
+www.usavisasonline.com.
+35.2.7.189.in-addr.arpa.
+77.220.75.94.zz.countries.nerd.dk.
+cdn.advertserve.com.
+www.love-m.com.
+www.google-analytics.com.
+safebrowsing-cache.google.com.
+photos-h.ak.fbcdn.net.
+faculty.citadel.edu.
+jers1.info.
+www.google.com.
+scores.neonplay.com.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+www.youtube.com.
+d8bz4crf4.k48u1e7g.
+www.proxytopsitelist.com.
+photos-d.ak.fbcdn.net.
+developers.facebook.com.
+mail.ulcomnet.ru.
+r02.member.ukl.yahoo.com.
+ajax.googleapis.com.
+cloud-search.linkury.com.
+www.ibersearch.com.
+73.244.165.190.in-addr.arpa.
+d2057087.instant.xoom.it.
+a.root-servers.net.
+0-jl-w.channel.facebook.com.
+73.101.250.190.in-addr.arpa.
+50.149.220.66.in-addr.arpa.
+21.80.59.186.in-addr.arpa.
+dns.msftncsi.com.
+images02.olx.com.sv.
+www.consult.com.
+mp3topdeals.com.
+dns.msftncsi.com.
+www.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+hscontshitifti.mp.
+pineapp.health.gov.il.
+www.ebay.es.
+i6.ifile.it.
+mdc-games.clanteam.com.
+www.pitbullclothing.com.
+www.maquina-tragaperras.org.
+lb._dns-sd._udp.lan.
+teredo.ipv6.microsoft.com.
+adsfront.iminent.com.
+a.root-servers.net.
+gu.e-hentai.org.
+google.com.
+mscrl.microsoft.com.
+www.5xxx.ru.
+safebrowsing.clients.google.com.
+cs83.vk.com.
+185.73.37.190.in-addr.arpa.
+112.142.188.189.in-addr.arpa.
+www.stephenkingshop.com.
+webishdesign.com.
+ocsp.verisign.com.
+content.netsuite.com.
+www.iamm.org.my.
+ntp1.tummy.com.
+safebrowsing-cache.google.com.
+nserver.calipso.com.co.
+static.ak.fbcdn.net.
+st.xiami.com.
+40.0.157.201.in-addr.arpa.
+sup.live.com.
+ep00.epimg.net.
+clients1.google.com.mx.
+almas.com.mx.
+office.microsoft.com.
+s1-powerpoint.vo.msecnd.net.
+www.facebook.com.
+clients2.google.com.
+creative.ak.fbcdn.net.
+s.youtube.com.
+gw0.aholding.com.ua.
+190.182.39.116.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+www.buenosairesfreetour.com.
+www.facebook.com.
+249.19.52.186.in-addr.arpa.
+149.150.164.187.in-addr.arpa.
+www.verynicejoke.com.
+51.152.80.190.in-addr.arpa.
+lesta-kr.ru.
+intranet.icipc.org.
+www.google.com.
+ax.su.itunes.apple.com.
+a.root-servers.net.
+173.41.122.85.in-addr.arpa.
+crystalseye.redbubble.com.
+www.facebook.com.
+www.facebook.it.
+fls.doubleclick.net.
+www.astrojar.org.uk.
+photos-e.ak.fbcdn.net.
+wpi-mexico.com.
+teredo.ipv6.microsoft.com.
+24.229.171.69.in-addr.arpa.
+102.149.238.190.in-addr.arpa.
+smetrics.aetn.com.
+static.ak.fbcdn.net.
+www.thedmonline.com.
+widgets.amung.us.
+_474_78_6.
+a.root-servers.net.
+tcr.tynt.com.
+en.wikipedia.org.
+r9aa:cx7q.e19a4d5k.
+old.longjuyt2tugas.com.
+www.tuffluvusa.com.
+147.23.168.192.in-addr.arpa.
+118.197.242.189.in-addr.arpa.
+194.146.129.94.in-addr.arpa.
+ssl.gstatic.com.
+rathole.ru.
+a.root-servers.net.
+themes.googleusercontent.com.
+rterybrstutnrsbberve.com.
+apple-mobile.query.yahooapis.com.
+www.adobe.com.
+mail.flyrichmond.com.
+android.clients.google.com.
+r._dns-sd._udp.lan.
+estilos.prodigy.msn.com.
+telecinc.com.
+pixel.facebook.com.
+platform.twitter.com.
+www.centroagb.cl.
+ksn3-11.part1.kaspersky-labs.com.
+fluoramec.com.
+www.cityofmovies.com.
+a1.sphotos.ak.fbcdn.net.
+video.google.com.
+futurclima.it.
+livereports.gpupdate.net.
+ssl.gstatic.com.
+www.lechaim.ru.
+s0.2mdn.net.
+ads.cleveland.com.
+www.youtube.com.
+i4.ytimg.com.
+a3.sphotos.ak.fbcdn.net.
+ips-glass.ru.
+photos-a.ak.fbcdn.net.
+251.162.244.190.in-addr.arpa.
+spectrumbloggers.com.
+aploan.com.s7b2.psmtp.com.
+ssl.gstatic.com.
+delta-sport.ru.
+lasclementinas.com.
+1.map.pop6.com.
+ib.adnxs.com.
+profile.ak.fbcdn.net.
+uc7e8x6ty.52xc.
+176.234.82.177.in-addr.arpa.
+c-0.19-a3090081.23.1518.19d3.3ea1.410.0.b8etnr6scdgjt2agmdu7i489av.avqs.mcafee.com.
+www.google.com.
+\(none\).
+227.3.151.187.in-addr.arpa.
+104.114.137.186.in-addr.arpa.
+www.sex8.cc.
+apac002.fra.samsungsocialhub.com.
+60.129.31.186.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+impactopositivo.bligoo.com.
+bobbrownauto.com.
+localhost.
+135.193.174.189.in-addr.arpa.
+bit.ly.
+149.28.168.192.in-addr.arpa.
+p42-buy.itunes.apple.com.
+mail.comgate.cz.
+www.theryancenter.com.
+down10.zol.com.cn.
+www.gstatic.com.
+groups.google.com.mx.
+www.msftncsi.com.
+osogay.disqus.com.
+www.hotmail.com.
+www.coolest-baby-shower-idea.com.
+dnl-01.geo.kaspersky.com.
+irc.purchaseservice.com.
+es.justin.tv.
+rntcalls.com.
+ssl.gstatic.com.
+sp.cwfservice.net.
+ecsnyder.com.
+57.112.107.187.in-addr.arpa.
+thean.com.
+224.117.145.201.in-addr.arpa.
+7p7xc58by.95nt.
+a4.mzstatic.com.
+www.descubrewindowslive.com.
+50.174.171.201.in-addr.arpa.
+mx1.botkyrka.see.
+a1.sphotos.ak.fbcdn.net.
+_354_51_7.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cvw7.navy.mil.
+altfarm.mediaplex.com.
+133.24.146.99.in-addr.arpa.
+cdd.emakumeak.org.
+www.conduit.com.
+profile.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+login.live.com.
+a1.sphotos.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+s0.2mdn.net.
+i.imgur.com.
+ss.websearch.ask.com.
+www.manualmovil.com.
+www.facebook.com.
+ayreycia.com.
+southernphone.com.au.
+sites.google.com.
+www.hotmail.com.
+on.fb.me.
+developers.facebook.com.
+e82eikdbp.71um.
+cloudscaling.com.
+ru.radioera.com.ua.
+160.110.164.110.in-addr.arpa.
+100.149.43.211.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+www.belkin.com.
+b.scorecardresearch.com.
+widgets.amung.us.
+xxlcc.com.
+cydia.hackulo.us.
+112.41.171.187.in-addr.arpa.
+www.igadi.org.
+www.reddoorindy.com.
+www.greatplacetowork.com.co.
+any-world.ngd.ysm.yahoodns.net.
+168.171.255.201.in-addr.arpa.
+ns4.p13.dynect.net.
+km.
+a5.sphotos.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+_020_85_2.
+135.101.191.186.in-addr.arpa.
+v4.netlogstatic.com.
+accoladehomecare.com.
+www.quanser.com.
+i1.ytimg.com.
+243.56.60.190.in-addr.arpa.
+johnmerritt.wikidot.com.
+a6.sphotos.ak.fbcdn.net.
+angg.ru.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+6xj.info.
+a.tribalfusion.com.
+www.makeupobsessed.com.
+carew.com.
+static-js.veevr.com.
+balancingact-africa.com.
+zokugo-dict.com.
+www.youtube.com.
+www.enelfacebook.com.
+a4.sphotos.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+_ldap._tcp.
+163.6.134.190.in-addr.arpa.
+usctap3132.apac.schp.com.
+www.saintnick.org.
+talkx.l.google.com.
+mail.asig.us.
+i46.tinypic.com.
+www.fourwheelcampers.com.
+connect.facebook.net.
+www.youtube.com.
+berkelouw.com.au.
+118.168.56.186.in-addr.arpa.
+ax.init.itunes.apple.com.
+erdemimports.com.
+ping.chartbeat.net.
+a6.sphotos.ak.fbcdn.net.
+22.107.248.201.in-addr.arpa.
+forum.b92.net.
+answers.nordstrom.com.
+creative.ak.fbcdn.net.
+i.ytimg.com.
+images.apple.com.
+survey.edmunds.com.
+t1.tagstat.com.
+redirector.c.youtube.com.
+cnfg.montiera.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+www.muscat-festival.com.
+2.bp.blogspot.com.
+rasthg.ru.
+nucleotide.ru.
+fbcdn-sphotos-a.akamaihd.net.
+www.xxx-69-xxx.com.
+smssandmold.com.
+www.youtube.com.
+pixel.facebook.com.
+smena.tusur.ru.
+150.225.146.186.in-addr.arpa.
+_430_11_9.
+www.google.com.
+www.ppvnetworks.com.
+gfx4.hotmail.com.
+63.159.10.186.in-addr.arpa.
+93.172.123.201.in-addr.arpa.
+photodoctorgraphics.com.
+www.onepcbsolution.com.
+cleantown.ru.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+32.191.146.187.in-addr.arpa.
+nppl.c.app.nintendowifi.net.
+ksn2-12.kaspersky-labs.com.
+nl.sykes.com.
+93.35.152.189.in-addr.arpa.
+panajidb.foroactivo.net.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+selectownerscorp.com.au.
+248.73.169.178.in-addr.arpa.
+www.verbinteractive.com.
+pop.e-medex.com.
+www.medical-conditions.org.
+emailmgr.aetv.com.
+ib.adnxs.com.
+blog.zap2it.
+www.metroflog.com.
+97.71.55.65.in-addr.arpa.
+sp.cwfservice.net.
+www.hotmail.com.
+52.177.233.190.in-addr.arpa.
+225.178.70.71.in-addr.arpa.
+mailstore1.secureserver.net.
+32.98.250.67.in-addr.arpa.
+www.www8-hp.com.
+d15gt9gwxw5wu0.cloudfront.net.
+a.root-servers.net.
+www.sociedaduruguaya.org.
+ns2.attdns.com.
+145.208.168.192.in-addr.arpa.
+tc3.easythumbhost.com.
+settings.toolbar.search.conduit.com.
+www.nuevomovil.com.
+www.ellsberg.net.
+.
+158.200.167.77.in-addr.arpa.
+froggy.com.au.
+dns.msftncsi.com.
+au.download.windowsupdate.com.
+hzimc01.hzmot.com.
+xtra1.gpsonextra.net.
+static.ak.fbcdn.net.
+time.chttl.com.tw.
+188.142.255.201.in-addr.arpa.
+167.16.180.189.in-addr.arpa.
+111.75.234.189.in-addr.arpa.
+als.wikipedia.org.
+www.safenet.com.
+www.snopes.com.
+pub.betclic.com.
+91.128.153.187.in-addr.arpa.
+zolotoerunohotel.ru.
+www.voyages-sncf.com.
+mail.skynet.lv.
+a4.sphotos.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+www.google.com.
+nr.rr.com.
+22.208.55.110.in-addr.arpa.
+173.211.111.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+176.1.149.190.in-addr.arpa.
+samosval-market.ru.
+a1.sphotos.ak.fbcdn.net.
+229.90.112.79.in-addr.arpa.
+ws.tapjoyads.com.
+google.com.
+www.bayharborislands.org.
+www.google.com.
+googleads.g.doubleclick.net.
+116.118.4.190.in-addr.arpa.
+brand-way.ru.
+mail.interdepotservices.com.
+228.3.79.187.in-addr.arpa.
+s.ytimg.com.
+ad.xtendmedia.com.
+www.seleccionuruguayadefutbol.com.
+bestmanager.rags.ru.
+igor.facemoods.com.
+profile.ak.fbcdn.net.
+streetdate.radio.com.
+weather.wapp.wii.com.
+82.248.250.189.in-addr.arpa.
+www.connect.facebook.com.
+www.rootsweb.ancestry.com.
+64.118.103.201.in-addr.arpa.
+www.modernhomedesigns.info.
+jers2.info.
+www.buy4now.ie.
+www.bankrollsports.com.
+cf.blogetery.com.
+data.goodgamestudios.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+vp.sip.messenger.msn.com.
+www.libreriaselatril.com.ar.
+photos-a.ak.fbcdn.net.
+www.blogtopsites.com.
+www.arbada.org.
+keais.com.s9a1.psmtp.com.
+121.138.40.187.in-addr.arpa.
+a-0.19-210fb801.c0c0081.1518.19d4.3ea1.210.0.9nvrwias8sz3akezrl3whq4et5.avqs.mcafee.com.
+iglasses.en.softonic.com.
+www.dwfitnessclubs.com.
+ntp.glb.nist.gov.
+in.emachines.com.
+intelligented.com.
+allencanning.com.
+110.27.205.187.in-addr.arpa.
+cdn.adnxs.com.
+oq-smtp02.rutgers.edu.
+accentpaper.ru.
+twitter.com.
+equip.ru.
+www.mumosengen.com.
+primerosauxilioscomunidad.blogspot.com.
+_ldap._tcp.dc._msdcs.nextiraone.com.mx.
+c.betrad.com.
+www.facebook.com.
+www.yjeverlasting.com.
+146.68.225.190.in-addr.arpa.
+brandfundamentals.com.
+www.clivebarker.info.
+plusone.google.com.
+218.134.211.201.in-addr.arpa.
+180.7.56.187.in-addr.arpa.
+pjstar.eviesays.com.
+a.root-servers.net.
+ms.ferr.ru.
+photos-e.ak.fbcdn.net.
+api.twitter.com.
+nueterra.com.s9b1.psmtp.com.
+gpuac.org.
+www.google.com.
+idpix.media6degrees.com.
+pho3nix-bf.deviantart.com.
+us.mc656.mail.yahoo.com.
+pop3.hot.glbdns.microsoft.com.
+fwl-tv.foroes.org.
+a6.sphotos.ak.fbcdn.net.
+radiusadvisors.com.inbound15.mxlogicmx.net.
+ads.yimg.com.
+dehoy.blogspot.com.
+a.root-servers.net.
+artisanent.com.
+www.torrentflux.com.
+mangahentai.org.com.
+ddi.com.
+aeroexchange.aerocontrolex.com.
+e-stud.vgtu.lt.
+wpad.
+a.root-servers.net.
+120.47.139.190.in-addr.arpa.
+www.zueiai.net.
+21.142.242.109.in-addr.arpa.
+m.facebook.com.
+static.ak.fbcdn.net.
+www.tysknews.com.
+elfriorock.com.
+prensalibre.d.xx.openx.com.akadns.net.
+db._dns-sd._udp.lan.
+updateext.services.openoffice.org.
+www.leedeelive.com.
+ssl.google-analytics.com.
+acpimc2b.pancanal.com.
+7ch826l9y.u54f5u6d.
+ikuzoanime.com.
+connect.facebook.net.
+clwebb.com.
+www.google.com.
+queensu.ca.
+profootballhof.com.
+stairs4u.com.
+loading4.widdit.com.
+92.71.55.65.in-addr.arpa.
+discountchristmasshop.com.
+atmofresh.ru.
+lasermax.com.
+www.youtube.com.
+212.220.168.192.in-addr.arpa.
+japattack.com.
+faceboooklikes.com.
+120.134.158.175.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+www.mtv.bumeran.com.ar.
+shiptoshore.com.
+s-static.ak.facebook.com.
+cpleft.com.
+www.google.ae.
+www.nuevoplaneta.com.
+37.165.152.189.in-addr.arpa.
+mail2.cocoplans.com.
+a5.sphotos.ak.fbcdn.net.
+twitter.com.
+tc.v19.cache6.c.youtube.com.
+accounts.google.com.
+swm-eu.com.s200a1.psmtp.com.
+217.74.69.189.in-addr.arpa.
+m.facebook.com.
+240.81.151.186.in-addr.arpa.
+vira.biz.
+a2.twimg.com.
+djsolo.ru.
+photos-h.ak.fbcdn.net.
+115.19.194.187.in-addr.arpa.
+a.root-servers.net.
+132.54.171.209.in-addr.arpa.
+213.234.100.78.in-addr.arpa.
+ak.imgfarm.com.
+www.scentoflife.com.au.
+time.nist.gov.
+quality-plumbing.net.
+www.subpelis.info.
+clock.isc.org.
+comcast.net.
+mail.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+190.161.166.190.in-addr.arpa.
+a.root-servers.net.
+a1402.w40.akamai.net.
+207.240.183.66.in-addr.arpa.
+b.scorecardresearch.com.
+28.66.179.187.in-addr.arpa.
+us.data.toolbar.yahoo.com.
+www.mondo-libero.eu.
+freedomloansolutions.com.
+a.root-servers.net.
+books.google.com.
+r._dns-sd._udp.lan.
+www.facebook.com.
+sites.google.com.
+245.102.55.157.in-addr.arpa.
+xp.yimg.com.
+_979_76_7.
+226.242.43.190.in-addr.arpa.
+htmortgage.net.
+www.fotothing.com.
+www.youtube.com.
+114.174.208.202.in-addr.arpa.
+www.jogosdomario.tk.
+www.asos.com.
+0-jg-w.channel.facebook.com.
+kobold.stu.neva.ru.
+switch.atdmt.com.
+myfunnyfamily.com.
+102.207.82.200.in-addr.arpa.
+41.9.219.108.in-addr.arpa.
+_786_44_2.
+a4.sphotos.ak.fbcdn.net.
+mscrl.microsoft.com.
+platform.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+jp.loobiz.com.
+asktoolbar.weather.com.
+kyungbock.net.
+static.ak.fbcdn.net.
+www.moneymanagement.com.au.
+www.xrxgsn.com.
+www.hdtvtunerinfo.com.
+www.adobe.com.
+csi.gstatic.com.
+sos-dan.ru.
+alerts.conduit-services.com.
+109.246.112.187.in-addr.arpa.
+www.alarabiya.net.
+www.espncricinfo.com.
+32.wap517.biz.
+www.stardoll.com.
+eg4y:eolc.60un.
+190.141.253.201.in-addr.arpa.
+phvids.voxcdn.com.
+criminologiamentescriminales.blogspot.com.
+dns.msftncsi.com.
+89.244.177.187.in-addr.arpa.
+117.53.41.77.in-addr.arpa.
+ns3.domain24.de.
+_869_58_5.
+www.textsrv.com.
+service.gc.apple.com.
+erreway.net.ru.
+www.facebook.com.
+herramientas.bbmundo.com.
+mail.modia.com.
+cix.co.kr.
+acs-it.ru.
+18.204.61.81.in-addr.arpa.
+fr-fr.facebook.com.
+24.media.tumblr.com.
+api.twitter.com.
+get.adobe.com.
+50.43.137.175.in-addr.arpa.
+167.250.111.190.in-addr.arpa.
+conair.com.
+backup-spool.iccx.net.
+te.en.alibaba.com.
+profile.ak.fbcdn.net.
+247.171.16.88.in-addr.arpa.
+www.contractorcalculator.co.uk.
+blog51.fc2.com.
+mail.narvajoesuu.ru.
+www9.effectivemeasure.net.
+exch.winwardsilks.com.
+53.13.198.187.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+233.36.173.201.in-addr.arpa.
+49.187.171.187.in-addr.arpa.
+market.android.com.
+estj.msn.com.
+248.74.173.190.in-addr.arpa.
+rss.com.com.
+lh3.googleusercontent.com.
+ributionapplyt.fm.
+livefiles18.vo.msecnd.net.
+r955totyv.92po.
+26.32.60.187.in-addr.arpa.
+d-e-n-e-g.net.ru.
+www.correiomagico.com.
+ssl.gstatic.com.
+127.0.0.1.
+wechslerbecker.com.
+photos-c.ak.fbcdn.net.
+ad.reachjunction.com.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mta6.am0.yahoodns.net.
+ads.bluelithium.com.
+173.250.197.217.in-addr.arpa.
+img843.imageshack.us.
+delivery.trafficbroker.com.
+safebrowsing-cache.google.com.
+googleads.g.doubleclick.net.
+eatonhydraulics.com.
+dnl-01.geo.kaspersky.com.
+c.betrad.com.
+metcomm.net.
+www.breakdanceforum.de.
+www.abbywintersrocks.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.ecoanimal.com.
+click.icetraffic.com.
+liveupdate01.asus.com.
+a6.sphotos.ak.fbcdn.net.
+bloggerphotos.l.google.com.
+91.120.215.189.in-addr.arpa.
+www.tomsguide.fr.
+v9.nonxt4.c.pack.google.com.
+rcp.na.blackberry.com.
+lab3.lbt.nsk.ru.
+se.bing.com.
+www.toyotire.es.
+savetubevideo.com.
+billets-train-avion.vivastreet.fr.
+antarinith.blogspot.com.
+www.gstatic.com.
+a6.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+ci.sherwood.or.us.s9b1.psmtp.com.
+google.com.
+l1.yimg.com.
+a.root-servers.net.
+home.mcafee.com.
+creative.ak.fbcdn.net.
+clients1.google.com.mx.
+166.44.251.190.in-addr.arpa.
+growingchild.com.
+www.moreemilk.com.
+17.38.25.88.in-addr.arpa.
+www.tepapa.govt.nz.
+waseca.copyleft.no.
+dsn1.d.skype.net.
+yahoo.download.vmn.net.
+api10.thetrafficstat.net.lan.
+243.240.141.201.in-addr.arpa.
+www.youtube.com.
+gim.net.
+pixel.facebook.com.
+199.82.172.187.in-addr.arpa.
+pixel.facebook.com.
+seify.ru.
+133.87.9.83.in-addr.arpa.
+71.56.244.189.in-addr.arpa.
+233.248.200.112.in-addr.arpa.
+www.saopauloguide.travel.
+picsart.com.
+sofla.com.
+televisa.esmas.com.
+trinaturk.com.
+www.dailyhotties.com.
+concordenterprises.com.
+www.ll.com.
+profile.ak.fbcdn.net.
+pix04.revsci.net.
+www.bywifi.com.
+7fdykzmvc.24wz.
+static-96-234-151-89.bltmmd.fios.verizon.net.
+s-external.ak.fbcdn.net.
+time.stdtime.gov.tw.
+photos-b.ak.fbcdn.net.
+api.autocompleteplus.com.
+a6.sphotos.ak.fbcdn.net.
+www.mininova.org.
+www.toy-wave.com.
+ctcpk8:tz.p06b2k5h.
+81.27.29.186.in-addr.arpa.
+96.98.102.201.in-addr.arpa.
+content.yieldmanager.edgesuite.net.
+137.173.167.74.in-addr.arpa.
+css.healthkicker.com.
+musikexpress.de.
+www.optimedia.es.
+creative.ak.fbcdn.net.
+f.facemoods.com.
+ymlp266.net.
+www.yamahamotos.cl.
+apis.google.com.
+ohsofab.com.
+computersplace.net.
+adslmail.es.
+www.yildiz.edu.tr.
+247.215.184.81.in-addr.arpa.
+googleads.g.doubleclick.net.
+sito-stal.ru.
+gac.edu.
+twitter.com.
+dress-proffi.ru.
+www.hot-files.net.
+a2.sphotos.ak.fbcdn.net.
+i3.ytimg.com.
+mail.lumusnet.com.
+symbolism.wikia.com.
+ad.yieldmanager.com.
+www.insurance.com.
+www3.snapfish.co.uk.
+www.honeymag.com.
+cdn.api.twitter.com.
+133.198.127.200.in-addr.arpa.
+cnilink.com.
+92.166.232.190.in-addr.arpa.
+encyclopediaurantia.org.
+a.root-servers.net.
+www.lengua.profes.net.
+greek-recipe.blogspot.com.
+js.fengwu.net.
+193.97.173.189.in-addr.arpa.
+mscrl.microsoft.com.
+static.ak.fbcdn.net.
+201-43-30-122.dsl.telesp.net.br.
+photos-c.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+65.43.35.99.in-addr.arpa.
+135.152.157.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+cdn.loading321.com.
+viajarencruceros.com.
+plusone.google.com.
+a-0.19-2109e041.5020082.1518.19d4.3ea1.400.0.is7mmqtl93n5sfff22b8e4dvvq.avqs.mcafee.com.
+161.37.35.189.in-addr.arpa.
+a.root-servers.net.
+42.133.52.190.in-addr.arpa.
+platform.twitter.com.
+124.185.27.189.in-addr.arpa.
+omsd.k12.ca.us.
+photos-f.ak.fbcdn.net.
+www.turnto23.com.
+apps.facebook.com.
+lp.live.monsters.wooga.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+172.176.5.117.in-addr.arpa.
+widgets.montiera.com.
+ja.wikipedia.org.
+basoscomunicantes.blogspot.com.
+setting3.yeahost.com.
+tsm04.eset.com.
+ulaex.cu.
+add.bugun.com.tr.
+ultimarealestate.com.
+_946_47_8.
+www.adobe.com.
+chhg.biz.
+googleads.g.doubleclick.net.
+www.facebook.com.
+portal.avaya-news.com.
+msg-01-0802.vetonaula.fi.
+a.root-servers.net.
+_295_92_7.
+l.d.
+server.iad.liveperson.net.
+crl.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+graphicsys.com.
+22.200.20.186.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+u35.eset.com.
+www.theshemaleorgy.com.
+ford.co.
+a.root-servers.net.
+freelotto.com.
+145.180.181.190.in-addr.arpa.
+blu124.mail.live.com.
+gfx1.hotmail.com.
+lh3.ggpht.com.
+64.6.203.24.in-addr.arpa.
+platform.ak.fbcdn.net.
+revistatejido.blogspot.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+denis.stalker.h3q.com.
+igloodesign.net.
+solihullsfc.ac.uk.
+teredo.ipv6.microsoft.com.
+104.5.55.186.in-addr.arpa.
+100.101.168.192.in-addr.arpa.
+www.baincapital.com.
+sp.edu.sg.
+sencolatinamerica.com.s6b1.psmtp.com.
+friendsinwar.com.
+a995.mm1.akamai.net.
+mail.cyberdom.ru.
+41.30.56.85.in-addr.arpa.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+android.clients.google.com.
+a7.sphotos.ak.fbcdn.net.
+www.askamum.co.uk.
+img2.blogblog.com.
+bel-net.ru.
+0-74.channel.facebook.com.
+bttracker.debian.org.
+ws.amazon.com.
+60.91.153.189.in-addr.arpa.
+cdn.api.twitter.com.
+ow.ly.
+www.google-analytics.com.
+133.193.213.83.in-addr.arpa.
+97.222.156.190.in-addr.arpa.
+api.twitter.com.
+orcart.facebook.com.
+simssoc.game.playfish.com.
+external.ak.fbcdn.net.
+crl.microsoft.com.
+www.lombards.com.au.
+a.root-servers.net.
+nino.ru.
+luzete.com.
+www.formspring.me.
+t3.gstatic.com.
+chgz.ru.
+53.48.54.65.in-addr.arpa.
+www.escolar.com.mx.
+www.lookandfeelbetter.com.
+wer.microsoft.com.
+kristynenapiolina.blogspot.com.
+s.youtube.com.
+about-diving.ch.
+s.ytimg.com.
+mail.sunyjcc.edu.
+photos-b.ak.fbcdn.net.
+mail.sleekcom.com.
+a3.sphotos.ak.fbcdn.net.
+apple.com.
+www.ultrarun.es.
+tr0.ds.ignames.net.
+158.17.228.189.in-addr.arpa.
+167.225.49.96.in-addr.arpa.
+br.fling.com.
+fbcdn-sphotos-a.akamaihd.net.
+thebigtv.com.
+a-0.19-a7091081.e0b0083.1518.19d3.3ea1.410.0.vmlhtvjuflgiddme6imndigcd6.avqs.mcafee.com.
+139.107.49.190.in-addr.arpa.
+_052_36_2.
+.
+buzznet-76.vo.llnwd.net.
+rad.msn.com.
+photos-g.ak.fbcdn.net.
+www.christiansanchini.com.
+f8ej9:w9k.f41q7l9u.
+us1.badoo.com.
+a4.sphotos.ak.fbcdn.net.
+tempurga.blogspot.com.
+207.51.132.190.in-addr.arpa.
+www.statcounter.com.
+a.root-servers.net.
+12mdosa.tk.
+static.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+themes.googleusercontent.com.
+beccue.com.
+a1.sphotos.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+113.80.137.66.in-addr.arpa.
+us.andronavi.com.
+everybody.ru.
+213.52.232.190.in-addr.arpa.
+a.root-servers.net.
+se.itunes.apple.com.
+www.sindicalistas.net.
+distrowatch.org.
+hotmail.com.
+www.hotmail.com.
+www.adgame.co.kr.
+94.139.18.187.in-addr.arpa.
+www.smi.ru.
+a7.sphotos.ak.fbcdn.net.
+www.visitstockholm.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+peru.com.
+surfrider.org.inbound15.mxlogic.net.
+spynet2.microsoft.com.
+www.locurajuegos.com.
+sp.ask.com.
+a.root-servers.net.
+nf.net.
+147.150.254.188.in-addr.arpa.
+pool.ntp.org.home.
+i1.ytimg.com.
+37.163.27.201.in-addr.arpa.
+ssl.gstatic.com.
+cpl.net.
+filologocfa.blogspot.com.
+s.ytimg.com.
+.
+www.ucarshare.com.
+9.198.31.190.in-addr.arpa.
+googleads.g.doubleclick.net.
+photoshop.nl.malavida.com.
+google.com.
+a2.sphotos.ak.fbcdn.net.
+www.google-analytics.com.
+a.root-servers.net.
+smtp.rimamfg.com.
+m.facebook.com.
+www.laboratoriodeconcienciadigital.com.
+apps.facebook.com.
+myculture.tumblr.com.
+www.wdc.com.
+183.118.18.187.in-addr.arpa.
+mail.wfmcdonald.com.
+m.addthisedge.com.
+luminouslogic.com.
+228.48.94.186.in-addr.arpa.
+wssecmgr2.atlanta.hp.com.
+pixel.facebook.com.
+25.27.167.190.in-addr.arpa.
+ksn2.kaspersky-labs.com.
+cs303208.vk.com.
+beta.data.toolbar.yahoo.com.
+32.169.6.200.in-addr.arpa.
+114.181.112.99.in-addr.arpa.
+frenital.byu.edu.
+dns.msftncsi.com.
+x18q2wii6.54nc.
+shiruva.files.wordpress.com.
+www.facebook.com.
+e3353.c.akamaiedge.net.
+server.cpmstar.com.
+a4.sphotos.ak.fbcdn.net.
+www.oribesalon.com.
+www.waraqat.net.
+ritual-nfl.aztecadeportes.com.
+ntzxot6hp.z36u6h4l.
+yahoonimbuz.com.
+widgets.twimg.com.
+mail.rsdcmi.com.
+profile.ak.fbcdn.net.
+www.opcionempleo.com.mx.
+api.twitter.com.
+sp.cwfservice.net.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+digitalpaper.com.
+3ae1mc4rm4e9l.c.yom.mail.yahoo.com.
+static.4shared.com.
+mail.asltg2.com.
+hsi-kbw-134-3-251-55.hsi14.kabel-badenwuerttemberg.de.
+mediacdn.disqus.com.
+tctechcrunch2011.files.wordpress.com.
+ksn1-12-part1.kaspersky-labs.com.
+a.root-servers.net.
+ar.wikipedia.org.
+checkip.dyndns.org.
+mail.ausapts.com.
+resolver1.bullguard.ctmail.com.
+194.5.139.189.in-addr.arpa.
+www.el-nacional.com.
+mediennetzwerk.de.
+mail.google.com.
+platform.twitter.com.
+lavidadehugo.blogspot.com.
+s.ytimg.com.
+zapatosmoda.org.
+thedenimguy.com.
+s.ytimg.com.
+38.204.7.189.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+232.249.114.186.in-addr.arpa.
+clients4.google.com.
+www.gentedlsur.blogspot.com.
+plus.google.com.
+230.246.67.201.in-addr.arpa.
+238.68.166.190.in-addr.arpa.
+tiscali.fr.
+android.clients.google.com.
+camptowanda.com.
+angieliddiard.scentsy.us.
+www.facebook.com.
+_320_63_9.
+cdn.api.twitter.com.
+m.cxt.ms.
+m.addthisedge.com.
+seg.sharethis.com.
+33.74.50.186.in-addr.arpa.
+www.hoe1.com.
+player2.narrowstep.tv.
+www.mercadolibre.com.mx.
+a6.sphotos.ak.fbcdn.net.
+www.d943b904.com.
+api.twitter.com.
+bayworldmfg.com.
+ax.init.itunes.apple.com.
+developers.facebook.com.
+p4mlnulls.53ki.
+mail3.demirdokum.ru.
+www.grisb.org.
+www.l.google.com.
+vikont-spb.ru.
+thesystemis.com.
+lj.libraryjournal.com.
+154.152.252.180.in-addr.arpa.
+www.ziggysgames.com.
+twitter.com.
+www.deadlydarling.tumblr.com.
+shedmediaus.com.inbound15.mxlogic.net.
+teredo.ipv6.microsoft.com.
+www.mercadopago.com.br.
+www.chatbazaar.com.
+www.solovenezolanas.com.
+photos-e.ak.fbcdn.net.
+www.cityoforlando.net.
+224.237.101.109.in-addr.arpa.
+megustavivirlavida.blogspot.com.
+ar.games.yahoo.com.
+www.google.com.
+www.youtube.com.
+mail2.ostling.com.
+s.youtube.com.
+photos-e.ak.fbcdn.net.
+165.221.33.176.in-addr.arpa.
+sp.ask.com.
+50.61.117.91.in-addr.arpa.
+ajax.googleapis.com.
+1.gravatar.com.
+es.wikipedia.org.
+mailhostrdc.aptiumoncology.com.
+www.yellbox.com.
+www.elpais.com.
+www.youth-guard.org.
+bmxxx.notengodominio.com.
+kaboomtune.com.
+www.facebook.com.
+d11777b.ess.barracudanetworks.com.
+153.226.106.189.in-addr.arpa.
+de-de.facebook.com.
+m.facebook.com.
+regionlimanoticias.com.
+www.google-analytics.com.
+hbw:79a9x.g50b5u8m.
+ksn2-12.kaspersky-labs.com.
+centrodiseno.com.
+iitx.com.
+ofertasonlineweb.com.
+resolver2.gdata.ctmail.com.
+d:atmd872.o16p4h5x.
+a4.sphotos.ak.fbcdn.net.
+6.41.252.201.in-addr.arpa.
+latam.msn.com.
+hardcorejkd.com.
+hermes.marketmetrix.com.
+187.35.20.190.in-addr.arpa.
+www.facebook.com.
+rt1401.infolinks.com.
+ww2.arthritis.org.
+176.150.106.124.in-addr.arpa.
+delcogeneralcontractors.com.
+101.86.37.186.in-addr.arpa.
+itunes.apple.com.
+www.deanjrobinson.com.
+static.4shared.com.
+s.imwx.com.
+ssl.gstatic.com.
+a1757.g.akamai.net.
+150.206.110.189.in-addr.arpa.
+a1408.w43.akamai.net.
+mariaelisacrochet.blogspot.com.
+voipc.sip.yahoo.com.
+79.151.14.98.in-addr.arpa.
+iwon.com.
+64.6.194.190.in-addr.arpa.
+optimized-by.rubiconproject.com.
+tc.v3.cache3.c.pack.google.com.
+ads2.msads.net.
+a5.sphotos.ak.fbcdn.net.
+anku-aruma.blogspot.com.
+photos-a.ak.fbcdn.net.
+www.dcsea.uqroo.mx.
+a7.sphotos.ak.fbcdn.net.
+billing.sharo4ka.ru.
+a6.sphotos.ak.fbcdn.net.
+www.mejoramos.com.
+www.facebook.com.
+s-static.ak.facebook.com.
+translate.google.com.
+a7.sphotos.ak.fbcdn.net.
+zk44vlvx8.65pa.
+197.226.131.187.in-addr.arpa.
+chichismusings.blogspot.com.
+safebrowsing.clients.google.com.
+11.186.31.99.in-addr.arpa.
+_163_60_7.
+ping3.teamviewer.com.
+www.philosophytogo.org.
+v10.nonxt4.c.pack.google.com.
+de-de.facebook.com.
+156.176.5.189.in-addr.arpa.
+a.root-servers.net.
+ssl.gstatic.com.
+gay-lesbianas.vivavisos.com.ar.
+external.ak.fbcdn.net.
+d2108043.xoom.it.
+es-la.facebook.com.
+s.ytimg.com.
+colorysabor.blogspot.com.
+mediatecpub.com.
+gala-shop.ru.
+www.power-21.com.
+a.root-servers.net.
+66.243.188.189.in-addr.arpa.
+www.facebook.com.
+92.217.19.186.in-addr.arpa.
+starinsur.com.
+a8.sphotos.ak.fbcdn.net.
+o.imgbox.com.
+17.131.128.186.in-addr.arpa.
+maxfreund.files.wordpress.com.
+74.164.30.78.in-addr.arpa.
+www.uncontactedtribes.org.
+photos-f.ak.fbcdn.net.
+www.interlinkeo.com.
+sebastiancorp.net.
+0.0.0.0.
+sexualidad.es.msn.com.
+www.athmg.com.
+us.i1.yimg.com.
+ksn2-12.kaspersky-labs.com.
+www.misfrases.org.
+www.facebook.com.
+www.trainsonthebrain.com.
+relay2.terranet.ru.
+ksn2-12.kaspersky-labs.com.
+direxpo.com.
+photos-c.ak.fbcdn.net.
+www.danceradio.es.
+csi.gstatic.com.
+116.203.214.186.in-addr.arpa.
+shanaflare.minitokyo.net.
+_270_92_7.
+24.159.244.67.in-addr.arpa.
+a997.mm1.akamai.net.
+vostokms.ru.
+cignethealth.com.
+kimochiii.foroes.net.
+forums.mi6-hq.com.
+guestbooks.pathfinder.gr.
+www.google.com.
+www.fullchristmas.com.
+nullmx.mcshi.com.
+checkip.dyndns.org.
+craftolution.ru.
+188.194.141.201.in-addr.arpa.
+inc.com.s8a1.psmtp.com.
+www.google.com.
+190.76.115.186.in-addr.arpa.
+mail1.qmiaw.com.
+107.161.6.189.in-addr.arpa.
+a11.t26.net.
+rchsd.org.
+grindrguy.com.s3.amazonaws.com.
+bodyforlife-tracker.com.
+www.v-like-vintage.net.
+breakthu.com.
+redfaceplus.com.
+www.google.com.
+gofree.indigo.ie.
+a8.sphotos.ak.fbcdn.net.
+s10.histats.com.
+googleads.g.doubleclick.net.
+casasbahia.com.
+primediacmmg.com.
+_863_43_0.
+137.204.229.189.in-addr.arpa.
+tradetang.com.
+www.mixx.com.
+tmail.com.
+www.facebook.com.
+photos-b.ak.fbcdn.net.
+www.eluniversaltv.com.mx.
+contextmenu.toolbar.conduit-services.com.
+zonacine.uservoice.com.
+itx5.smartadserver.com.
+slhtobit01.shangri-la.com.
+s10.histats.com.
+www.twenga.nl.
+www.hsbc.com.mx.
+youtubebajar.chatango.com.
+meetingmillionares.com.
+lb._dns-sd._udp.0.137.168.192.in-addr.arpa.
+www.funnypenispictures.com.
+sadiegen.blogspot.com.
+vcs2.msg.yahoo.com.
+smtp.fianzasmonterrey.com.mx.
+chelvis.3x.ro.
+a.root-servers.net.
+16.110.139.205.in-addr.arpa.
+cloud-q.duba.net.
+dns.msftncsi.com.
+fhc.alphagammadelta.org.
+google.com.
+outlaw-hs.com.
+dco.nmbbm.jp.
+safebrowsing-cache.google.com.
+26.138.10.187.in-addr.arpa.
+geo.it.
+s.srvntrk.com.
+sites.google.com.
+mail.spiratex.com.
+sliddoors.ru.
+synacortoshiba.112.2o7.net.
+a1892.phobos.apple.com.
+photos-a.ak.fbcdn.net.
+www.guppies.com.
+www.uhs.edu.pk.
+77.21.235.98.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+torrent-download.to.
+33.190.63.69.in-addr.arpa.
+ntp.glb.nist.gov.
+www.brandsouthafrica.com.
+none.
+199.0.137.186.in-addr.arpa.
+i3.ytimg.com.
+mail.sboa.com.
+www.google.com.
+gj37765.blogspot.com.
+www.macstation.com.ar.
+css.lainformacionalsegundo.com.
+gfx4.hotmail.com.
+www.streaming-films.info.
+photos-h.ak.fbcdn.net.
+mail.kns.net.
+imap.gmail.com.
+alerts.conduit-services.com.
+skarevolution69.files.wordpress.com.
+google.com.
+b.scorecardresearch.com.
+www.tipsdrills.com.
+cdn-static.liverail.com.
+142.189.171.110.in-addr.arpa.
+freenet-reg-ripn.ru.
+download.cyberlink.com.
+static.ak.fbcdn.net.
+46.181.63.69.in-addr.arpa.
+a.root-servers.net.
+ayma.com.
+a.root-servers.net.
+v1.panthercdn.com.
+209.176.120.200.in-addr.arpa.
+travelprosinc.com.
+www.felixagm.es.
+sumisoporamor.blogspot.com.
+rfigroup.com.
+5.249.6.201.in-addr.arpa.
+img123.exs.cx.
+www.darktorrents.com.
+inbound.toyotawc.com.netsolmail.net.
+d2091958.xoom.it.
+a.root-servers.net.
+www.servicioscreativos.com.
+cdn.api.twitter.com.
+pix04.revsci.net.
+fbcdn-photos-a.akamaihd.net.
+a8.sphotos.ak.fbcdn.net.
+kastenchase.com.
+_705_61_8.
+www.digitalartscalifornia.com.
+c9uqhrli8.30aa.
+dns.msftncsi.com.
+a-0.19-210fb071.c880580.1518.19d3.3ea1.210.0.iia1lvgs7trinugwplwbbha5aq.avqs.mcafee.com.
+www.facebook.com.
+account.cancer.org.
+key-copy.ru.
+qvapotejat.com.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+eoweqokc.org.
+www.facebook.com.
+0.static.ak.fbcdn.net.
+psicologiaymigracion.blogspot.com.
+www.blsclinic.com.
+mail.putnamco.org.
+15.180.145.201.in-addr.arpa.
+inbound.bwe-nc.com.netsolmail.net.
+metrocast.net.
+80.155.97.94.in-addr.arpa.
+m.facebook.com.
+_599_34_2.
+www.peeblesplay.com.
+www.bonusthemes.com.
+pr.prchecker.info.
+sms.siemens.com.
+hp.nknox.k12.in.us.
+teredo.ipv6.microsoft.com.
+www.nic.cd.
+252.218.212.116.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+dbzepisodeorg.chatango.com.
+api.twitter.com.
+m.hotmail.com.
+dnl-01.geo.kaspersky.com.
+r.nexac.com.
+www.google-analytics.com.
+caglesinc.com.
+nickthompson.com.
+tools.google.com.
+a2.sphotos.ak.fbcdn.net.
+dualstack.ipv6-exp.l.google.com.
+oliveoil.wholesaleonlineweb.com.
+17.159.253.190.in-addr.arpa.
+www.wmitechnologies.com.
+sites.google.com.
+margulies.com.inbound15.mxlogic.net.
+a5.sphotos.ak.fbcdn.net.
+albionauto.ru.
+webres2.bullguard.ctmail.com.
+bowietownmedical.com.
+www.problemsolving.net.
+themoneyconverter.com.
+148.147.176.190.in-addr.arpa.
+pvp.com.
+9.173.204.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+cust22764-1.in.mailcontrol.com.
+www.udelas.ac.pa.
+113.15.39.187.in-addr.arpa.
+hzrcoq8ih.10no.
+external.ak.fbcdn.net.
+shadow.mature.nl.
+profile.ak.fbcdn.net.
+blog.formspring.me.
+17.177.105.186.in-addr.arpa.
+a.root-servers.net.
+no-one.com.
+rs543l35.rapidshare.com.
+210.203.206.186.in-addr.arpa.
+time-nw.nist.gov.
+46.229.34.189.in-addr.arpa.
+a-0.19-2709a081.99c0083.1518.19c2.3ea1.210.0.aktazdp51b34gma5pp33cfbhh5.avqs.mcafee.com.
+veksel.komitex.ru.
+www.christandpopculture.com.
+mt1.google.com.
+tap2-cdn.rubiconproject.com.
+a.root-servers.net.
+teredo.ipv6.microsoft.com.
+www.facebook.com.
+sp.cwfservice.net.
+www.adtool.de.
+arielluque.blogspot.com.
+133.226.27.190.in-addr.arpa.
+api.twitter.com.
+a.root-servers.net.
+168.158.218.186.in-addr.arpa.
+avin02.melange.net.
+gecits.com.
+casscomm.com.s9b2.psmtp.com.
+www.feedcat.net.
+dns.msftncsi.com.
+tegam.com.
+mx.dlls.pa.frontiernet.net.
+127.92.9.81.in-addr.arpa.
+static.ak.fbcdn.net.
+loc1.eu1.badoo.com.
+m.addthisedge.com.
+orfodpc985862.sh.marrcorp.marriott.com.
+view.atdmt.com.
+a.root-servers.net.
+fdsn0.skype.net.
+www.spermed.net.
+aka-cdn-ns.adtech.de.
+trac.qutecom.org.
+www.amanngirrbach.com.
+ads.iforex.com.
+photos-f.ak.fbcdn.net.
+i3.ytimg.com.
+periodico.morelos.gob.mx.
+s4.histats.com.
+saillavka.ru.
+ced.sascdn.com.
+71.96.85.77.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+123-outlook-express-backup.programas-gratis.net.
+155.108.168.192.in-addr.arpa.
+accounts.google.com.
+app.reg.techweb.com.
+a.root-servers.net.
+138.230.69.94.in-addr.arpa.
+245.245.135.188.in-addr.arpa.
+4:9nrmxww.i31g1n2l.
+bedewsd01.npsp.com.
+eun.org.
+a2.sphotos.ak.fbcdn.net.
+26.79.179.189.in-addr.arpa.
+c1.tacdn.com.
+tags.crwdcntrl.net.
+ocsp.verisign.com.
+lacocinademiabue.blogspot.com.
+jp.123rf.com.
+randewy.ru.
+www.google.com.
+eligrey.com.
+dezcom.ru.
+a.root-servers.net.
+revolutionmedia.ign.com.
+sc6.rules.mailshell.net.
+www.pauldewar.ca.
+external.ak.fbcdn.net.
+fp3.wg1.b.yahoo.com.
+meroo.polyvore.com.
+zitomedia.com.
+support.google.com.
+a6.sphotos.ak.fbcdn.net.
+amer.rel.msn.com.
+a.root-servers.net.
+impact-in.jobstreet.com.
+www.facebook.com.
+142.27.82.201.in-addr.arpa.
+a.root-servers.net.
+118.85.191.186.in-addr.arpa.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+246.239.86.67.in-addr.arpa.
+pogovorka.ru.
+ustarb001ads.ww005.siemens.net.med.siemens.de.
+www.google.com.
+platform.ak.fbcdn.net.
+53.160.166.190.in-addr.arpa.
+a.root-servers.net.
+external.ak.fbcdn.net.
+120.26.250.188.in-addr.arpa.
+191.84.108.71.in-addr.arpa.
+i1.ytimg.com.
+profile.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+api.airpush.com.
+104.25.225.190.in-addr.arpa.
+a.root-servers.net.
+www.tomrobinsonphotography.com.
+es.answers.yahoo.com.
+photos-h.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+searchclient.live.net.
+a3.sphotos.ak.fbcdn.net.
+mail.thplastics.com.
+www.youtube.com.
+www.myconnectfm.com.
+236.241.174.190.in-addr.arpa.
+datafirst.fr.
+s-static.ak.facebook.com.
+sites.google.com.
+fm-realty.com.
+p1t.ru.
+cs953.vk.com.
+www.mariaauxiliadora.org.mx.
+apple-pie.in.
+on24.com.dnsbl7.mailshell.net.
+safebrowsing-cache.google.com.
+a.root-servers.net.
+25.media.tumblr.com.
+mail1.jandp.com.sa.
+connect.facebook.net.
+te10.kontera.com.
+s10.histats.com.
+www.facebook.com.
+www.google.com.
+a.root-servers.net.
+bt-service.ru.
+images2.memegenerator.net.
+23.10.43.186.in-addr.arpa.
+www.facebook.com.
+www.organizatusviajes.com.
+tvcsp.com.
+146.16.0.192.in-addr.arpa.
+84.156.113.190.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+amdc-smp01.intranet.mckinsey.com.
+39.51.252.201.in-addr.arpa.
+seg.p.sharethis.com.akadns.net.
+photos-e.ak.fbcdn.net.
+klaus-schimanski.de.
+creative.ak.fbcdn.net.
+36.139.94.190.in-addr.arpa.
+vogdesigns.com.
+a.root-servers.net.
+mattters.com.
+thefinecut.blogspot.com.
+echo.edge.messenger.live.com.
+48-courier.push.apple.com.
+google.com.
+0-38.channel.facebook.com.
+mx2.mcn.org.gslb.pphosted.com.
+static.ak.fbcdn.net.
+a.root-servers.net.
+ocsp.thawte.com.
+a7.sphotos.ak.fbcdn.net.
+webcache.googleusercontent.com.
+a.root-servers.net.
+magicphotoshop.com.
+shelbygt500review.com.
+www.comparere.com.
+css.wlxrs.com.
+.
+a2.sphotos.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+img862.imageshack.us.
+24.134.44.62.in-addr.arpa.
+askville.amazon.com.
+msgr.updates.yahoo.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+140.47.66.189.in-addr.arpa.
+seoul.fm.
+130.178.94.208.in-addr.arpa.
+ads.genericlink.com.
+64.129.8.87.in-addr.arpa.
+img5.joyreactor.ru.
+macmiller.com.
+photos-d.ak.fbcdn.net.
+dem0003.in.
+35.160.160.186.in-addr.arpa.
+files.discountechnology.com.
+fxfeeds.mozilla.com.
+www.submitblognow.info.
+fbcdn-sphotos-a.akamaihd.net.
+mannyzoom.com.
+accounts.google.com.
+epost.fo.
+sp.cwfservice.net.
+ksn2-12.kaspersky-labs.com.
+91.123.138.201.in-addr.arpa.
+s1-word-view.vo.msecnd.net.
+www.heredis.com.
+vblk3mtfy.52vq.
+217.214.10.187.in-addr.arpa.
+arizona.diamondbacks.mlb.com.
+blog.bjrn.se.
+thefamousgroup.com.1.0001.arsmtp.com.
+www.drtuber.com.
+genesis.1337x.org.
+static.ak.fbcdn.net.
+axnvmip7g.b81y9j5m.
+mx.astrology.yahoo.com.
+photos-d.ak.fbcdn.net.
+136.254.38.180.in-addr.arpa.
+bay.gateway.messenger.live.com.
+_259_22_6.
+js.wlxrs.com.
+imagess.ru.
+www.facebook.com.
+a.root-servers.net.
+www.netmanager.com.br.
+juventudxhardcore.blogspot.com.
+106.52.8.200.in-addr.arpa.
+111.170.18.95.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+mail.telecomholdings.com.
+smtp.kclife.com.
+ksn2-12.kaspersky-labs.com.
+webcache.googleusercontent.com.
+6zuqsydog.m92s2p6l.
+pagead2.googlesyndication.com.
+www.hon.com.
+ssl.google-analytics.com.
+inbound.capitolmed.com.netsolmail.net.
+cs505502.vkontakte.ru.
+144.86.194.187.in-addr.arpa.
+astroline.ru.
+www.marco.org.mx.
+tracker.xpear.de.
+mediacdn.disqus.com.
+azorero.blogspot.com.
+www.shockmd.com.
+mx1.pspvodka.ru.
+platform.twitter.com.
+s0.2mdn.net.
+twitter.com.
+a.root-servers.net.
+www.massnurses.org.
+com.imangi.s3-website-us-east-1.amazonaws.com.
+173.230.195.187.in-addr.arpa.
+a.root-servers.net.
+www.trackmusic.com.ar.
+www.md-dui-defense.com.
+1.119.223.189.in-addr.arpa.
+elmundomagicode-reina.blogspot.com.
+frases.eslamoda.com.
+mail.bluetie.com.
+ad.adnetwork.net.
+tr.adinterax.com.
+static-1.farmville.zgncdn.com.
+apps.facebook.com.
+www.top50dancepop.es.
+google.com.
+ktrailer.blogspot.com.
+www.idiomascuc.com.
+ksn2-12.kaspersky-labs.com.
+mail.adpk.net.
+okc.mx0.rhinocommunications.net.
+secure.aolanswers.com.
+www.babeforums.org.
+s-static.ak.facebook.com.
+www.facebook.com.
+ns1.eu.bitnames.com.
+resolute-midatlantic.com.inbound15.mxlogic.net.
+18.48.101.189.in-addr.arpa.
+103.11.168.192.in-addr.arpa.
+sitelife.clarionledger.com.
+123.245.132.187.in-addr.arpa.
+fred-graichen.de.
+store.notionsmarketing.com.
+netrscape.net.
+www.google.com.
+3.0.168.192.in-addr.arpa.
+48.44.122.186.in-addr.arpa.
+1.0.168.192.in-addr.arpa.
+140.137.124.77.in-addr.arpa.
+www.itadvocate.com.au.
+xtra1.gpsonextra.net.
+29.91.160.24.in-addr.arpa.
+mail.google.com.
+a.root-servers.net.
+google.com.
+moboogie.com.
+sitecheck2.opera.com.
+ffrtrgfdf.com.
+ad.xtendmedia.com.
+photos-c.ak.fbcdn.net.
+www.google-analytics.com.
+21.13.67.213.in-addr.arpa.
+owensborograin.com.s8a1.psmtp.com.
+i2.ytimg.com.
+111.29.229.190.in-addr.arpa.
+a.root-servers.net.
+_836_57_2.
+1-0-1-0.category.programsbase.com.
+sunstone.com.
+228.141.254.77.in-addr.arpa.
+uplus.ru.
+static.ak.facebook.com.
+time.chttl.com.tw.
+guicci.ru.
+i.ytimg.com.
+photos-a.ak.fbcdn.net.
+cartoonnetwork.com.mx.
+d2ks4vnin.n76v8o6f.
+100.220.192.187.in-addr.arpa.
+althing.org.
+cmd.ru.
+lt3opi:pp.q33t2n6p.
+ecbldhaka.com.
+www.cht.in.
+www2.viamichelin.com.
+developers.facebook.com.
+gorbushina.ru.
+ocsp.verisign.com.
+sp.cwfservice.net.
+mob51.photobucket.com.
+google.com.
+www.facebook.com.
+ns1.relex.com.
+pagead2.googlesyndication.com.
+mx3.umflint.edu.
+chatcluster.scruffapp.com.
+www.youtube.com.
+keflog.com.
+swaroop.deviantart.com.
+46.159.106.177.in-addr.arpa.
+110.127.179.190.in-addr.arpa.
+a995.mm1.akamai.net.
+www.metronoticias.com.mx.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.twitter.com.
+252.155.102.41.in-addr.arpa.
+s-static.ak.facebook.com.
+ladygaga.wikia.com.
+i2.ytimg.com.
+www.calculopesoideal.com.
+graph.facebook.com.
+kidsrus.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+rovio.appads.com.
+www.mrauto.cl.
+43.220.247.189.in-addr.arpa.
+199.18.115.189.in-addr.arpa.
+www.robertososa.com.mx.
+radi2.com.
+bangalicommunity.com.
+25.93.102.200.in-addr.arpa.
+rogers.com.
+apps.facebook.com.
+224.250.93.186.in-addr.arpa.
+186.106.145.187.in-addr.arpa.
+ak-media.soundcloud.com.
+www.peinadosycortes.com.
+92.20.100.157.in-addr.arpa.
+www.origamiseiten.de.
+www.barefootfoundation.com.
+www.imhc.mil.kr.
+bestsmileys.com.
+5.198.52.186.in-addr.arpa.
+id.google.com.mx.
+profile.ak.fbcdn.net.
+fpmccann.co.uk.
+mail.close.ru.
+d2060276.instant.xoom.it.
+s1-word-edit.vo.msecnd.net.
+pixel.facebook.com.
+61.187.127.200.in-addr.arpa.
+rad.msn.com.
+floridabuilderappliances.com.
+titanium30-en.url.trendmicro.com.
+diosrestauramatrimonios.blogspot.com.
+img100.xvideos.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+130.181.29.88.in-addr.arpa.
+proxy-sn.contacts.msn.com.
+drw-milliman.com.
+www.motopartscenter.com.
+www.google.com.
+ols.systemofadown.com.
+a.root-servers.net.
+external.ak.fbcdn.net.
+59.34.178.190.in-addr.arpa.
+146.73.1.201.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+69.133.13.186.in-addr.arpa.
+creative.ak.fbcdn.net.
+11.118.112.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+bestbuytest.convertlanguage.com.
+gl.wikipedia.org.
+plus.google.com.
+time.stdtime.gov.tw.
+it.justin.tv.
+www.eroticperfection.com.
+go.microsoft.com.
+229.140.2.181.in-addr.arpa.
+jers1.info.
+static.ak.facebook.com.
+comm-2000.com.inbound10.mxlogic.net.
+cs5058.vkontakte.ru.
+www.apple-mac.cz.
+225.254.251.190.in-addr.arpa.
+static.app.widdit.com.
+dnl-01.geo.kaspersky.com.
+pixel.facebook.com.
+mx.siemens-club.org.
+rmgmedia.com.
+static.ak.fbcdn.net.
+ccgetsemani.wordpress.com.
+irc.purchaseservice.com.
+cdn.theknot.com.
+server1.transammonia.net.
+mail.vidnoe-grad.ru.
+search.twitter.com.
+view.atdmt.com.
+b-sidemg.com.
+mx2.maildefender.net.
+www.acblack.com.
+www.dhl.co.in.
+a5.sphotos.ak.fbcdn.net.
+th06.deviantart.net.
+api.twitter.com.
+129.144.252.190.in-addr.arpa.
+sharpeiclub.ru.
+19-courier.push.apple.com.
+www.facebook.com.
+www.bloob.fr.
+11.136.16.62.in-addr.arpa.
+caketin.honeyrosebakery.com.
+www.crunchbase.com.
+mobth1076.photobucket.com.
+a.root-servers.net.
+travel.state.gov.
+ut7.xhamster.com.
+i-sec.slutload-media.com.
+www.techlabs4u.com.
+133.186.25.125.in-addr.arpa.
+madeira-lets.com.
+a3.sphotos.ak.fbcdn.net.
+msc.wlxrs.com.
+profile.ak.fbcdn.net.
+img.seriesgo.com.
+www.youtube.com.
+tbcom.ru.
+mail.soft.com.
+65.225.80.186.in-addr.arpa.
+104.105.230.190.in-addr.arpa.
+miplandeboda.blogspot.com.
+www.googleadservices.com.
+accuratedoor.com.
+a5.sphotos.ak.fbcdn.net.
+1n1.mooo.com.
+www.facebook.com.
+www.facebook.com.
+_502_08_7.
+www.agoda.cz.
+rhap5tbq8.48bv.
+abitur.mipt.ru.
+this.content.served.by.adshuffle.com.
+215.65.155.201.in-addr.arpa.
+a.root-servers.net.
+static.olx.com.
+www.google-analytics.com.
+www.gstatic.com.
+www.asstoyedshemales.com.
+api.facebook.com.
+60.217.210.201.in-addr.arpa.
+search.babylon.com.
+88.50.11.188.in-addr.arpa.
+ym.adnxs.com.
+www.las-palmas-24.com.
+vvnktku.vlingo.com.
+fw.kose.edu.ee.
+59.175.6.186.in-addr.arpa.
+googleads.g.doubleclick.net.
+ui.skype.com.
+a.root-servers.net.
+www.singlescrowd.com.
+www.towerdefenceworld.com.
+www.nyctourism.com.
+ssl.gstatic.com.
+www.dirtbox.net.
+2j2c12fes.68yb.
+home-design-software-review.toptenreviews.com.
+fbcdn-profile-a.akamaihd.net.
+photos-h.ak.fbcdn.net.
+tracker.thepiratebay.org.
+www.four05.nl.
+statse.webtrendslive.com.
+cs301510.vk.com.
+ensombrerada.blogspot.com.
+rmd.atdmt.com.
+1-210.channel.facebook.com.
+mail.dauphintechnologie.net.
+gj77l2roa.37ap.
+berettaargentina.com.ar.
+www.staypoland.com.
+www.advertising.expedia.com.
+photos-g.ak.fbcdn.net.
+www.destentoradverteren.nl.
+104.113.51.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.eco-nutricionhumana.blogspot.com.
+40.219.134.187.in-addr.arpa.
+unitedco.net.
+a2.sphotos.ak.fbcdn.net.
+m.facebook.com.
+arquivo.arkbr.com.br.
+www.academictutorials.com.
+manage.ixwebhosting.com.
+vikingpump.com.
+www.greenstarholistix.com.
+secure-uk.imrworldwide.com.
+photos-d.ak.fbcdn.net.
+www.f2000delasamericas.com.
+www.atufavor.com.mx.
+polisci.ucla.edu.
+51.116.111.124.in-addr.arpa.
+e566.b.akamaiedge.net.
+weblogger-dynamic-lb.playdom.com.
+40.165.242.201.in-addr.arpa.
+118.17.80.92.in-addr.arpa.
+moltaqa1.com.
+p.d.ovi.com.
+www.appitalism.com.
+108.2.73.189.in-addr.arpa.
+drcnh.org.
+evsecure-ocsp.verisign.com.
+mtalk.google.com.
+cdn.api.twitter.com.
+katerawlings.com.
+maps.google.com.
+evsecure-crl.verisign.com.
+megusta.followland.com.
+www.relishgourmet.com.
+www.101babyshowerideas.com.
+photos-f.ak.fbcdn.net.
+93.61.1.189.in-addr.arpa.
+api.twitter.com.
+a743.g.akamai.net.
+www.linuxhomenetworking.com.
+a4.sphotos.ak.fbcdn.net.
+torrents.edwardk.info.
+gmail.com.
+a995.mm1.akamai.net.
+appworld.blackberry.com.
+kirstinz.en.made-in-china.com.
+couponbuddy.s3.amazonaws.com.
+impisr.edunsk.ru.
+groups.l.google.com.
+144.162.67.187.in-addr.arpa.
+www.woodcentral.com.
+touch.facebook.com.
+translate.google.com.mx.
+elvela.org.
+uniquemadness.com.
+gencoat.com.
+cafe.mt.iphone.sgnapps.com.
+211.218.161.201.in-addr.arpa.
+profiles.takingitglobal.org.
+velocent.net.
+papa-anggry.blogspot.com.
+i.w55c.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.facebook.com.
+15.172.88.200.in-addr.arpa.
+www.facebook.com.
+153.125.109.89.in-addr.arpa.
+profile.ak.fbcdn.net.
+rest-img.msg.yahoo.com.
+photos-a.ak.fbcdn.net.
+logv18.xiti.com.
+elliman.com.s9b1.psmtp.com.
+ad-g.doubleclick.net.
+googleads.g.doubleclick.net.
+ad-apac.doubleclick.net.
+sites.google.com.
+creative.ak.fbcdn.net.
+mail.mppgen.com.
+www.subealring.org.ve.
+rv.coupish.com.
+a1.sphotos.ak.fbcdn.net.
+twitter.com.
+c800869.r69.cf2.rackcdn.com.
+exploradorl2.blogspot.com.
+d13t5qcdsiucvs.cloudfront.net.
+tag.admeld.com.
+230.227.213.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.syabas.com.my.
+pixel.facebook.com.
+bittersweetbella.tumblr.com.
+bw-it.ru.
+a.root-servers.net.
+a898.x.akamai.net.
+www.facebook.com.
+kremlinencrypt.com.
+162.33.37.201.in-addr.arpa.
+www.facebook.com.
+tracking.percentmobile.com.
+login.toolbar.conduit-services.com.
+termasworld.com.
+secure-us.imrworldwide.com.
+29.media.tumblr.com.
+photos-b.ak.fbcdn.net.
+tqbzesadg.71pn.
+57.133.50.46.in-addr.arpa.
+youtube.com.
+sn3.mailshell.net.
+b1.media.v4.skyrock.net.
+lingvo-german.ru.
+a8.sphotos.ak.fbcdn.net.
+b-0.19-23066089.80110b1.1518.19d3.3ea1.410.0.4tev3i12ugd4h8rdbt4jpaujnb.avqs.mcafee.com.
+www.y8girlsgames.com.
+mi.adinterax.com.
+agen-bola-online.nuke.im.
+cb.alimama.cn.
+www.uniteberlin.de.
+s-static.ak.facebook.com.
+www.rotary.org.
+pac.bell.com.
+inguat.gob.gt.inbound10.mxlogicmx.net.
+www.gospelherald.com.
+mail.secondhand-opt.ru.
+www.ccl.org.
+www.facebook.com.
+arabic.cnn.com.
+i4.ytimg.com.
+lindas-stampinloft.blogspot.com.
+neri1.com.
+qs.aastocks.com.
+253.104.105.186.in-addr.arpa.
+macdaddynews.disqus.com.
+mntr.babcdn.com.
+photos-g.ak.fbcdn.net.
+gs.mil.ee.
+www.clicporlalibertad.com.
+s.ytimg.com.
+www.bbva.es.
+56.157.73.121.in-addr.arpa.
+www.univercell-biosolutions.com.
+www.imago.com.pt.
+teredo.ipv6.microsoft.com.
+witter.com.
+webres2.pand.ctmail.com.
+www.ciromarchetti.com.
+29.33.134.189.in-addr.arpa.
+external.ak.fbcdn.net.
+sianganland.ru.
+alerts.conduit-services.com.
+o3frc56jg.a61w2o4y.
+108.9.37.190.in-addr.arpa.
+e55nqkqi5.32ju.
+go.srvnow.com.
+dns.msftncsi.com.
+34.246.52.186.in-addr.arpa.
+napervilleparks.org.
+thumbnails.mystyle.com.
+83113mailerpost.com.
+tools.google.com.
+www.srl.caltech.edu.
+215.12.168.192.in-addr.arpa.
+noseq.com.
+catfish.ru.
+www.greatnannies.com.
+_781_28_8.
+proua.com.
+t2.gstatic.com.
+3d-object-converter.softonic.com.
+80.41.141.201.in-addr.arpa.
+api.twitter.com.
+mail.fleetauctiongroup.com.
+www.uol.com.mx.
+www.facebook.com.
+a.root-servers.net.
+comernowling.com.inbound10.mxlogic.net.
+gorod.dp.ua.
+www.statcounter.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.zvdk.nl.
+widget.roomme.net.
+83.119.1.58.in-addr.arpa.
+_675_36_2.
+a995.mm1.akamai.net.
+api.facebook.com.
+clicks.adengage.com.
+0.209.172.118.in-addr.arpa.
+plusone.google.com.
+106.85.156.90.in-addr.arpa.
+www.tecolotefilms.com.
+46.133.225.190.in-addr.arpa.
+eva-miscosicas.blogspot.com.
+0-jk-w.channel.facebook.com.
+ace-north.org.uk.
+zk3.dec.com.
+163.184.76.178.in-addr.arpa.
+www.google-analytics.com.
+8mu1b5czx.s61q1q5j.
+ads.avvio.com.
+234.26.136.190.in-addr.arpa.
+de-de.facebook.com.
+d2095767.xoom.it.
+teredo.ipv6.microsoft.com.
+secure.cartown.com.
+mx.youtube.com.
+assets4.castle.zgncdn.com.
+www.eboncall.org.
+179.70.46.92.in-addr.arpa.
+kairon.malavida.com.
+forums.objectsbydesign.com.
+theruckergroup.com.
+www.promowebperu.com.
+a.root-servers.net.
+gfx7.hotmail.com.
+estrenos-de-cine.labutaca.net.
+gestion.fundacioncarolina.es.
+tracker.ccc.de.
+costcentral.com.
+daft.ie.
+gma52w7lp.37ml.
+fbcdn-sphotos-a.akamaihd.net.
+222.173.1.181.in-addr.arpa.
+www.facebook.com.
+www.autotrader.co.nz.
+60.204.81.200.in-addr.arpa.
+a.root-servers.net.
+scribblesandsnaps.wordpress.com.
+htrnews.com.s7b2.psmtp.com.
+a1404.w41.akamai.net.
+adspaces.ero-advertising.com.
+safebrowsing-cache.google.com.
+pedsocial.files.wordpress.com.
+widgets.twimg.com.
+mail1.rimslow.com.
+gaycounty.com.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+client.akamai.com.
+gccoxmail.net.
+yahoo.com.
+s.wordpress.com.
+evolutionofstyleblog.blogspot.com.
+mail1.mbginsurance.com.
+elcantil.com.
+dns.msftncsi.com.
+scribe.twitter.com.
+cdn2.trimm.com.c.footprint.net.
+37.58.198.190.in-addr.arpa.
+api.twitter.com.
+wildlifehc.org.
+androauth.0916161bcltd.netdna-cdn.com.
+hits.e.cl.
+a.root-servers.net.
+t3.gstatic.com.
+28.190.49.200.in-addr.arpa.
+131.150.159.187.in-addr.arpa.
+sp.cwfservice.net.
+www.opcion.net.
+edosushibar.com.
+safebrowsing-cache.google.com.
+218.87.9.186.in-addr.arpa.
+imail.columbuscontainer.com.
+profile.ak.fbcdn.net.
+clients1.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tsm05.eset.com.
+time.chttl.com.tw.
+photos-f.ak.fbcdn.net.
+google.com.
+6.224.219.186.in-addr.arpa.
+hot-shots-2.peliculon.tv.
+tracking.affiliaxe.com.
+itunes.apple.com.
+developers.facebook.com.
+gmaul.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+i1.ytimg.com.
+www.facebook.com.
+www.ragnadrima.com.
+us.data.toolbar.yahoo.com.
+newideas.ru.
+88.34.178.74.in-addr.arpa.
+18.79.247.189.in-addr.arpa.
+adsl.kis.ru.
+cdn.api.twitter.com.
+blog.e-kereta.com.
+tc.v14.cache7.c.youtube.com.
+150.28.75.151.in-addr.arpa.
+go.microsoft.com.
+as.casalemedia.com.
+mundodelyaoi.blogspot.com.
+fathomgear.com.
+adult.chinese.cn.
+sr.wikipedia.org.
+cdn2.vippy.co.
+dsn12.d.skype.net.
+users4.jabry.com.
+osvanceloth.elbruto.es.
+a8.sphotos.ak.fbcdn.net.
+131.92.157.186.in-addr.arpa.
+16.147.220.66.in-addr.arpa.
+59.135.20.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.thecutestblogontheblock.com.
+151.129.239.201.in-addr.arpa.
+www.gstatic.com.
+_704_31_9.
+itella.ru.
+103.235.249.190.in-addr.arpa.
+www.hotpussy.tv.
+mail.derishev.ru.
+artsugar-merche.blogspot.com.
+api.twitter.com.
+a7.sphotos.ak.fbcdn.net.
+www.jisc-collections.ac.uk.
+s.youtube.com.
+static.ak.connect.facebook.com.
+photos-b.ak.fbcdn.net.
+82.199.51.95.in-addr.arpa.
+www.whatismyip.org.
+www.gruposancorseguros.com.
+88.61.253.201.in-addr.arpa.
+www.facebook.com.
+ib.adnxs.com.
+www.brenda.uni-koeln.de.
+freenet.de.
+postoffice.condenast.ru.
+www.shemalemodelindex.com.
+r.mzstatic.com.
+125.136.124.190.in-addr.arpa.
+c3.free18.net.
+iminent.ourtoolbar.com.
+www.luxurycoachoutlet.com.
+www.yaganeloquevale.com.
+248.227.231.189.in-addr.arpa.
+urs.microsoft.com.
+123.26.186.201.in-addr.arpa.
+orchidrenaissance.com.
+profile.ak.fbcdn.net.
+valenky.ru.
+sro.whatsapp.net.
+ec2-50-19-138-103.zumodrive.com.
+s.youtube.com.
+132.21.174.189.in-addr.arpa.
+zh-cn.facebook.com.
+static4.educaedu.com.pe.
+profile.ak.fbcdn.net.
+www.motoresx.com.
+www.ton.cz.
+del.icio.us.
+sportsnation.espn.go.com.
+openx.wooga.com.
+ntp1.dlink.com.
+a.root-servers.net.
+accounts.google.com.
+pixel.facebook.com.
+i4.ytimg.com.
+49.191.121.64.in-addr.arpa.
+yui.yahooapis.com.
+dnl-15.geo.kaspersky.com.
+a.root-servers.net.
+145.236.108.186.in-addr.arpa.
+ocsp.thawte.com.
+a.root-servers.net.
+l.yimg.com.
+a6.sphotos.ak.fbcdn.net.
+199.248.234.189.in-addr.arpa.
+jobboom.com.
+photos-a.ak.fbcdn.net.
+89.76.178.190.in-addr.arpa.
+www.michellemoistpussy.com.
+photos-d.ak.fbcdn.net.
+www.luxuryworld.altervista.org.
+www.facebook.com.
+122.123.205.190.in-addr.arpa.
+uucycxpucmoc.ru.
+gateway.messenger.hotmail.com.
+cancerpulmonar.org.
+85.95.6.89.in-addr.arpa.
+www.e-galileo.eu.
+232.149.59.199.in-addr.arpa.
+www.full-stop.net.
+www.clipato.com.
+stauffergold.com.
+a.webring.com.
+dayak.com.
+ads.zizzero.com.
+amx.grandslamdesign.net.redcondor.net.
+cnt.tyxo.bg.
+i.furiousmod.com.
+support.google.com.
+www.youtube.com.
+crl.comodoca.com.
+bifkqfr:u.25ek.
+sport4ever.maktoob.com.
+mail.skyworth.com.
+cookex.amp.yahoo.com.
+www.compunoa.com.
+_ldap._tcp.
+ssl.gstatic.com.
+flipchat.com.
+www.youtube.com.
+75522lineb.cn.
+214.244.24.200.in-addr.arpa.
+toolbarqueries.google.com.
+162.63.141.201.in-addr.arpa.
+images.torrentsland.com.
+graph.facebook.com.
+a.root-servers.net.
+www.defensenewstv.com.
+millerarchitects.co.uk.
+a.root-servers.net.
+195.21.25.201.in-addr.arpa.
+www.google.com.
+ves.smolen.ru.
+messenger.hotmail.com.
+sarahjanestudios.com.
+71.241.75.190.in-addr.arpa.
+www.watchknowlearn.org.
+www.msftncsi.com.
+profile.ak.fbcdn.net.
+230.108.219.64.in-addr.arpa.
+vlex.com.pe.
+a.root-servers.net.
+www.alan4.net.
+media.trafficjunky.net.
+143.97.61.95.in-addr.arpa.
+courtesy.nominalia.com.
+9kif6czfc.k51l0p0b.
+img.paisdelocos.com.
+mail.google.com.
+ems-uk.org.
+bpcgi.nikkeibp.co.jp.
+98.145.11.187.in-addr.arpa.
+dns.msftncsi.com.
+326.webim0220.webim.myspace.com.
+a8.sphotos.ak.fbcdn.net.
+www.ipadforos.com.
+238.40.67.201.in-addr.arpa.
+which.net.
+safebrowsing-cache.google.com.
+pdf.textfiles.com.
+www.google.com.
+arkcrew.com.
+sfparenting.com.
+www.gravatar.com.
+www.alipso.com.
+www.bkstr.com.
+244.68.242.83.in-addr.arpa.
+18.1.142.187.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+192.25.238.189.in-addr.arpa.
+blog.aziawaoutour.com.
+sstat.360buy.com.
+photos-f.ak.fbcdn.net.
+polk-sullivan.com.
+7.234.15.199.in-addr.arpa.
+mail.imessagingsystems.com.
+esva1.itech.ms.
+arabiasaudita.pordescubrir.com.
+235.236.248.201.in-addr.arpa.
+este.
+cdnrockyou-a.akamaihd.net.
+zy.china.com.cn.
+teredo.ipv6.microsoft.com.
+propacificfresh.com.
+233.131.179.190.in-addr.arpa.
+www.andiamo.com.
+121.55.54.65.in-addr.arpa.
+b.scorecardresearch.com.
+pokerfreemail.com.
+60.59.222.189.in-addr.arpa.
+137.0.19.88.in-addr.arpa.
+85.132.248.111.in-addr.arpa.
+gfx1.hotmail.com.
+pagead2.googlesyndication.com.
+a6.sphotos.ak.fbcdn.net.
+www.google-analytics.com.
+newrivercabinet.com.
+86.67.139.187.in-addr.arpa.
+vast.bp3847758.btrll.com.
+36.80.242.189.in-addr.arpa.
+alt1.chessclub.com.
+18.165.49.190.in-addr.arpa.
+lecturasarztucuman.wordpress.com.
+web-gin.ru.
+capitalfederal.adoos.com.ar.
+19.110.78.187.in-addr.arpa.
+api.twitter.com.
+_586_16_0.
+safebrowsing-cache.google.com.
+tl04.chip.eu.
+www.opicode.org.
+www.pensandoenpsicologia.com.
+clients1.google.com.
+dailycappuccino.nl.
+alfar.com.tr.
+54.190.152.186.in-addr.arpa.
+api.facebook.com.
+legalterms.cbsinteractive.com.
+34.6.43.186.in-addr.arpa.
+o-o.preferred.atl14s01.v21.lscache3.c.youtube.com.
+www.monstershack.net.
+aronasarwar.co.uk.
+external.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+offers.cmtrax.com.
+ksn2-12.kaspersky-labs.com.
+plusone.google.com.
+40.243.58.187.in-addr.arpa.
+www.google.com.
+t1.gstatic.com.
+www.pandora.com.
+fullscale.com.
+181.159.209.201.in-addr.arpa.
+p1t.ru.
+fbcdn-photos-a.akamaihd.net.
+fbcdn-profile-a.akamaihd.net.
+www.hookedonjuice.com.
+photos-b.ak.fbcdn.net.
+1.244.132.190.in-addr.arpa.
+smtp.fsmail.net.
+seniorsolutions.com.
+img.moonbuggy.org.
+apk.dir4world.com.
+www.sweetimstore.com.
+224.0.55.190.in-addr.arpa.
+html.rincondelvago.com.
+www.alw-ed.com.
+dns.msftncsi.com.
+jetcatalog.ru.
+tallconnections.com.
+sproutonline.channelfinder.net.
+komonews.s3.amazonaws.com.
+photos-d.ak.fbcdn.net.
+s-static.ak.facebook.com.
+242.219.93.186.in-addr.arpa.
+www.sophimania.pe.
+lisd.k12.mi.us.
+five.tv.
+photos-h.ak.fbcdn.net.
+de-de.facebook.com.
+93.coll.ning.com.
+tracker.novalayer.org.
+ip-81-23-55-150.ask4internet.com.
+developers.facebook.com.
+tap2-cdn.rubiconproject.com.
+a3.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+www.google.com.mx.
+m.addthisedge.com.
+images02.olx-st.com.
+169.132.92.201.in-addr.arpa.
+img.hotwords.com.br.
+151.144.182.186.in-addr.arpa.
+coffee.haohaowan.com.
+pattwhite.com.
+sritchie645.orangehome.co.uk.
+kingofsat.net.
+scripts.verticalacuity.com.
+c.prodigy.msn.com.
+www.google-analytics.com.
+blushnightclub.com.
+static.ak.fbcdn.net.
+exodus.1337x.org.
+avanquest.upclick.com.
+fbcdn-sphotos-a.akamaihd.net.
+boise.gannett.com.
+vinylopedia.tk.
+wrvideo.com.br.
+a.root-servers.net.
+en-us.fxfeeds.mozilla.com.
+photos-b.ak.fbcdn.net.
+a2:ey7:ug.c34q3i7i.
+84.71.21.187.in-addr.arpa.
+a.root-servers.net.
+stl-mbsin-01.boeing.com.
+www.apple.com.
+twoliverpoolfans.files.wordpress.com.
+ns3.slb.com.
+hoskinson.net.
+www.facebook.com.
+malah.biz.
+55.230.213.201.in-addr.arpa.
+83.69.248.116.in-addr.arpa.
+platform.twitter.com.
+video-aqui-mismo.blogspot.com.
+broenserud.com.
+www.archos.com.
+80.80.78.190.in-addr.arpa.
+googleads.g.doubleclick.net.
+photos-g.ak.fbcdn.net.
+24.120.92.186.in-addr.arpa.
+rs543l32.rapidshare.com.
+mail-2.traditio.org.
+sportdaten.welt.de.
+notibang.blogspot.com.
+5mk6g:cd7.91xw.
+www.santander.com.mx.
+www.ebzzo.eu.
+137.186.171.187.in-addr.arpa.
+2.0.168.192.in-addr.arpa.
+img028.rockyou.com.
+profile.ak.fbcdn.net.
+a34.g.akamai.net.
+au.download.windowsupdate.com.
+www.advertisingcrossing.com.
+onlinecliptv.com.
+0-333.channel.facebook.com.
+172.90.121.84.in-addr.arpa.
+www.dailyhotnews.org.
+news.google.com.mx.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.addthis.com.
+profile.ak.fbcdn.net.
+www.mj1000.com.
+56.247.134.187.in-addr.arpa.
+www.jldfineart.com.
+bafta.org.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mashable.com.
+151.146.185.190.in-addr.arpa.
+tsm00.eset.com.
+photos-h.ak.fbcdn.net.
+www.thestrokesfan.com.
+brig-td.spb.ru.
+96.195.55.177.in-addr.arpa.
+i4.ytimg.com.
+periodicozocalo.com.mx.
+www.verycheapuggsboots.co.uk.
+m59eop2ip.61wg.
+mail.oppermanns-online.de.
+pftmobile.com.
+smtp.kndati.lv.
+wd.ggili.com.
+novotec.ru.
+www.tusourcecard.com.
+135.15.143.201.in-addr.arpa.
+57.198.119.79.in-addr.arpa.
+tamarind.co.ke.
+4.42.64.151.in-addr.arpa.
+translate.google.com.
+photos-a.ak.fbcdn.net.
+vegassportsexperts.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+raycomm.com.
+www.google.com.
+a8.sphotos.ak.fbcdn.net.
+connorarnold.karoo.co.uk.
+a.root-servers.net.
+relay.digsys.bg.
+a4.sphotos.ak.fbcdn.net.
+br.premierleague.fantasysports.yahoo.com.
+a.root-servers.net.
+cache-download.real.com.
+ocnj.us.
+s2.youtube.com.
+www.bankhalter.de.
+www.googleadservices.com.
+sheri.net.
+photos-e.ak.fbcdn.net.
+akllaw.com.s5a2.psmtp.com.
+a.root-servers.net.
+wnbvaircmngnugnewxvffvfp.ac.
+content.yieldmanager.edgesuite.net.
+www.facebook.com.
+oakleynetworks.com.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+time.chttl.com.tw.
+apps.facebook.com.
+coins.shop.ebay.com.
+superiortandems.com.
+a.root-servers.net.
+safebrowsing.clients.google.com.
+widgets.twimg.com.
+110.127.141.201.in-addr.arpa.
+static.tianya.cn.
+cruznet2.cruznet.net.
+g.ceipmsn.com.
+a.root-servers.net.
+artisanfilms.com.
+img6.gg.mmo4arab.com.
+orcart.facebook.com.
+mrs-cbe.mrs.yimg.com.
+fxfeeds.mozilla.com.
+webcache.googleusercontent.com.
+www.euphoriashop.co.uk.
+view.atdmt.com.
+api.facebook.com.
+pjyyon.com.
+raslist.dhl.com.
+platform.twitter.com.
+42.52.60.190.in-addr.arpa.
+jobbuzz.timesjobs.com.
+www.v-trail.com.
+csi.gstatic.com.
+homestore.cisco.com.
+www.playrelax.com.
+www.marketplace-live.com.
+photos-e.ak.fbcdn.net.
+www.youtube.com.
+login.secure.co1.msn.com.
+jvlw21t6t.u74x0n8f.
+a.root-servers.net.
+a.root-servers.net.
+www.rednet21.com.
+translate.google.com.mx.
+olympictool.com.
+miriam-montero-duque.suite101.net.
+uslshop.com.
+www.phpdocx.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+farcaster.org.
+static.ak.fbcdn.net.
+116.60.245.173.in-addr.arpa.
+morrow30.freeserve.co.uk.
+connect.facebook.net.
+a3.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+www.cemexmexico.com.
+www.benettontalk.com.
+pts.net.
+17.131.35.189.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+portlandonline.com.
+a.root-servers.net.
+email.theshoppingchannel.com.
+a.root-servers.net.
+violetmall.ru.
+5-courier.push.apple.com.
+114.242.179.190.in-addr.arpa.
+ebm.cheetahmail.com.
+img100.xvideos.com.
+188.141.171.201.in-addr.arpa.
+js.admeld.com.
+a.root-servers.net.
+bts.inet.fi.
+in2itivegroup.com.
+static.ak.facebook.com.
+teredo.ipv6.microsoft.com.
+102.89.69.66.in-addr.arpa.
+www.atomretro.com.
+a.root-servers.net.
+225.91.9.177.in-addr.arpa.
+231.113.79.186.in-addr.arpa.
+16.147.220.66.in-addr.arpa.
+pixel.facebook.com.
+external.ak.fbcdn.net.
+external.ak.fbcdn.net.
+dns.msftncsi.com.
+www.filesonic.com.
+a1.sphotos.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+valied.wrzuta.pl.
+a2.sphotos.ak.fbcdn.net.
+151.62.173.118.in-addr.arpa.
+aspmx2.googlemail.com.
+guru.avg.com.
+ksn1-11-part1.kaspersky-labs.com.
+www.orjinalafrikamangosu.gen.tr.
+www.ipaddressworld.com.
+psgw.t-mobilesgws.com.
+hi-in.facebook.com.
+dem0003.in.
+gcr-capital.com.
+34.38.227.77.in-addr.arpa.
+external.ak.fbcdn.net.
+www.facebook.com.
+www.azringtones.com.
+148.91.145.78.in-addr.arpa.
+www.youtube.com.
+wpad.hrbl.net.
+tw.itunes.com.
+energyflashbysimonreynolds.blogspot.com.
+shared.live.com.
+pixel.quantserve.com.
+www.tdu.com.mx.
+c-0.19-2309c481.30483.1518.19d3.3ea1.210.0.35rgm4fbje6tc9tn3f1evbbss5.avqs.mcafee.com.
+downloads4.kaspersky-labs.com.
+uk.forvo.com.
+www.baby-connect.com.
+plus.google.com.
+c.statcounter.com.
+www.facebook.com.
+skydrive.live.com.
+www.telasparacortinas.com.
+mail.artemka.ru.
+music4yourvids.co.uk.
+211.115.154.79.in-addr.arpa.
+clients4.google.com.
+dingtao333.3322.org.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.l.yimg.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+greedygoose.blogspot.com.
+semana.com.
+codenew.impresionesweb.com.
+ecl.tbc.tetrisfb.com.
+acuariopolitico.blogspot.com.
+partners.aljazeera.net.
+wxod1p3eb.z75t8u8x.
+inbound.mveinc.com.netsolmail.net.
+theimagist.com.
+www.yanbal.com.
+www.pheasantsforever.org.
+photos-e.ak.fbcdn.net.
+www.movistar.com.ve.
+mail.rrsid.com.
+google.com.
+fbcdn-profile-a.akamaihd.net.
+cameroncommunities.com.
+profile.ak.fbcdn.net.
+105.107.54.27.in-addr.arpa.
+www.facebook.com.
+www.top-buyer.com.
+data.cmcore.com.
+a.root-servers.net.
+twitter.com.
+photos-f.ak.fbcdn.net.
+207.148.237.84.in-addr.arpa.
+es-es.facebook.com.
+sp.ask.com.
+a-0.19-a70c8079.d150083.1518.19d4.3ea0.210.0.76k1c41vmrdtkq5sgh9jewtvsj.avqs.mcafee.com.
+cdn.stumble-upon.com.
+vp.sip.messenger.msn.com.
+fibres.net.s7b1.psmtp.com.
+134.14.49.190.in-addr.arpa.
+dns.msftncsi.com.
+125.196.63.119.in-addr.arpa.
+www.kidsrooms.co.uk.
+orcart.facebook.com.
+www.google.com.mx.
+wire-pro.com.
+www.trangobroadband.com.
+naysue.wordpress.com.
+wrenconsult.com.
+reddevelopment.ru.
+www.bywifi.com.
+sync.mathtag.com.
+88.42.207.108.in-addr.arpa.
+25.media.tumblr.com.
+latis03.cbthebank.com.
+lightsonthelake.blogspot.com.
+static.ak.fbcdn.net.
+login.toolbar.conduit-services.com.
+i1.akcdn.net.
+www.gomovers.com.
+a2.sphotos.ak.fbcdn.net.
+146.136.139.190.in-addr.arpa.
+arrogant.ru.
+240.7.55.186.in-addr.arpa.
+www.youtube.com.
+122.6.23.190.in-addr.arpa.
+ads.tlvmedia.com.
+shared.live.com.
+s2.wp.com.
+www.msn.com.
+1.us.vps.garantname.com.
+vcs1.msg.yahoo.com.
+www.sweetpotatosoftware.com.
+service.matomy.com.
+249.59.94.189.in-addr.arpa.
+us.mg.mail.yahoo.com.
+49.185.49.190.in-addr.arpa.
+pixel.facebook.com.
+117.130.150.190.in-addr.arpa.
+internetshakespeare.uvic.ca.
+gigmaps.net.
+www.diarioderegatas.es.
+search-it-today.com.
+12.124.107.190.in-addr.arpa.
+s4is.histats.com.
+datacenterdynamics.com.
+104.238.19.190.in-addr.arpa.
+dundefndpc.natneg3.gamespy.com.
+rc.rlcdn.com.
+nec-tokin.com.
+97.163.51.190.in-addr.arpa.
+www.youtube.com.
+www.marbleslab.ca.
+zh.wikipedia.org.
+marblecrafters.com.inbound30.mailprotector.net.
+69.102.155.189.in-addr.arpa.
+beta.stun.voice.yahoo.com.
+marquintas.wordpress.com.
+www.naimlabel.com.
+69.247.17.190.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+218.212.146.189.in-addr.arpa.
+20-courier.push.apple.com.
+firepowereurope.com.
+dakelem.luminet.net.
+tracker.bidder7.mookie1.com.
+ping3.dyngate.com.
+www.mozilla.com.
+csi.gstatic.com.
+giport.ru.
+neptuno.cestel.es.
+59.235.7.89.in-addr.arpa.
+ksn3-11.part2.kaspersky-labs.com.
+adanacsales.com.inbound15.mxlogic.net.
+titanium30-en.url.trendmicro.com.
+clients4.google.com.
+64.254.18.189.in-addr.arpa.
+fkm-anons.ru.
+partnercomm.net.s7a1.psmtp.com.
+_505_04_2.
+a.root-servers.net.
+www.tango-dj.at.
+gmail-smtp-in.l.google.com.
+gallys.bustykerrymarie.com.
+caman.ru.
+imtop.ru.
+www.facebook.com.
+laxmnvmaltiris1.fs.marrcorp.marriott.com.
+zanestle.com.
+api-public.addthis.com.
+del.icio.us.
+a.root-servers.net.
+venusonmars.com.
+99.64.91.190.in-addr.arpa.
+102.163.253.189.in-addr.arpa.
+201.107.32.80.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+172.59.238.189.in-addr.arpa.
+dns.msftncsi.com.
+214.114.107.186.in-addr.arpa.
+113.44.48.190.in-addr.arpa.
+www.ukcigarforums.com.
+seg.sharethis.com.
+mta5.am0.yahoodns.net.
+mitutoyo.com.
+www.ophtalmologie.fr.
+31.228.46.124.in-addr.arpa.
+60.210.209.190.in-addr.arpa.
+www.google-analytics.com.
+100.70.8.200.in-addr.arpa.
+mailhost.lecxp.com.
+ocsp.thawte.com.
+hoteldiscount.ru.
+www.l.google.com.
+js.microsoft.com.
+static.ak.fbcdn.net.
+apis.google.com.
+96.43.12.186.in-addr.arpa.
+loading6.widdit.com.
+static.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+www.dairyqueen.com.ph.
+waynesville.k12.mo.us.
+videos.picapon.com.
+35.206.186.189.in-addr.arpa.
+0.gravatar.com.
+a.root-servers.net.
+googlemail.l.google.com.
+video.nudelingeriepics.com.
+www.facebook.com.
+www.google-analytics.com.
+a4.sphotos.ak.fbcdn.net.
+63.96.168.189.in-addr.arpa.
+www.wowjuju.com.
+a6.sphotos.ak.fbcdn.net.
+sheisnotyourmother.blogspot.com.
+a3.sphotos.ak.fbcdn.net.
+ocsp.comodoca.com.
+a6.sphotos.ak.fbcdn.net.
+bettergolf.net.
+img102.herosh.com.
+translate.googleapis.com.
+142.147.82.190.in-addr.arpa.
+msdn.microsoft.com.
+250.63.137.216.in-addr.arpa.
+global.ard.yahoo.com.
+www.youtube.com.
+bbs.health.ifeng.com.
+a4.sphotos.ak.fbcdn.net.
+zzz.clickbank.net.
+s-external.ak.fbcdn.net.
+www.jennifervaughn.com.
+www.okinawan-shorinryu.com.
+207.243.168.192.in-addr.arpa.
+a1725.l.akamai.net.
+24.media.tumblr.com.
+153.18.42.62.in-addr.arpa.
+rosalind-hicks.memory-of.com.
+www.google.com.
+profile.ak.fbcdn.net.
+gleasonhosting.com.
+mail.dibadi.net.
+google.com.
+es.wikipedia.org.
+tikitaka.foroactivo.com.
+egbmbdey.mooo.com.
+ksn2-12.kaspersky-labs.com.
+archives.obs-us.com.
+plus.google.com.
+215.235.211.189.in-addr.arpa.
+a.root-servers.net.
+macgm-log.com.
+grylott.fsbusiness.co.uk.
+www.breakfastpointlifestyle.com.au.
+www.scotlandsoftware.com.
+donboscovictorias.org.
+a.root-servers.net.
+pme.tscapeplay.com.
+pixel.facebook.com.
+s2.youtube.com.
+www.corvettepartsforsale.com.
+42.9.21.108.in-addr.arpa.
+cs1212.vk.com.
+www.egipto2012.com.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+21.224.171.69.in-addr.arpa.
+www.facegroup.com.
+www.museolaligua.cl.
+www.byrdseed.com.
+www.aulaclic.es.
+tmi.gr.jp.
+a2.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+pubads.g.doubleclick.net.
+diy-mail.alerta.su.
+a1505.l.akamai.net.
+www.mrmusicman17.com.
+www.facebook.com.
+mx01.eagle-design.com.
+l1.yimg.com.
+pinnaclecollects.com.s9b1.psmtp.com.
+js.patheos.com.s3.amazonaws.com.
+83.253.47.201.in-addr.arpa.
+getprof.us.np.community.playstation.net.
+img3.catalog.video.msn.com.
+ncoss.org.au.
+chromejs.s3.amazonaws.com.
+symr2a.backup.com.
+127.123.215.66.in-addr.arpa.
+shop.tsumorichisato.com.
+xybion.com.inbound10.mxlogic.net.
+apps.facebook.com.
+mail.richardsoncap.com.
+pixel.quantserve.com.
+168.117.71.193.in-addr.arpa.
+www.druzestudies.org.
+mx02.ipac.caltech.edu.
+a6.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+fireblast.net.
+a.root-servers.net.
+yodemoda.blogspot.com.
+183.159.18.186.in-addr.arpa.
+us.bc.yahoo.com.
+electriclane.de.
+waterworkscircuit.com.
+bookbirddog.blogspot.com.
+232.189.136.162.in-addr.arpa.
+api.facebook.com.
+google.com.
+155.126.18.176.in-addr.arpa.
+ax.init.itunes.apple.com.
+cdn.api.twitter.com.
+ip2location.conduit-services.com.
+ap.lijit.com.cdngc.net.
+rewardz.vodafone.co.uk.
+mx3.prima.de.
+a.root-servers.net.
+media.sliderocket.com.
+apps.facebook.com.
+teredo.ipv6.microsoft.com.
+static-resource.np.community.playstation.net.
+sipinternal.gmail.com.
+itb-group.ru.
+a.root-servers.net.
+241.165.77.188.in-addr.arpa.
+xslt.alexa.com.
+a.root-servers.net.
+herry.com.
+134.42.41.126.in-addr.arpa.
+alerts.conduit-services.com.
+photos-c.ak.fbcdn.net.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+orionimpex.ru.
+185.25.122.186.in-addr.arpa.
+www.google-analytics.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+31kp9ake1.78qc.
+114.106.138.187.in-addr.arpa.
+macfarlanepartners.com.s8a2.psmtp.com.
+141.212.24.201.in-addr.arpa.
+www.jessmills.co.uk.
+screenshots.bravotube.net.
+www.spakti.eu.
+a.root-servers.net.
+jhtpc.com.
+9.140.149.186.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+von_der.galeon.com.
+stliqwltryhkwh.com.
+api-read.facebook.com.
+static.addtoany.com.
+137.188.191.186.in-addr.arpa.
+www.stylelist.com.
+www.google-analytics.com.
+www.sitionica.com.ar.
+tag.admeld.com.
+ceusa.virtualiza.com.br.
+131.250.88.186.in-addr.arpa.
+0bps664l3vqk05dj8qih0t5renri9iic.ig.ig.gmodules.com.
+228.175.253.201.in-addr.arpa.
+197.5.11.190.in-addr.arpa.
+a.root-servers.net.
+www.google-analytics.com.
+photos-g.ak.fbcdn.net.
+do.kershaw.k12.sc.us.
+rkhunter.sourceforge.net.
+www.balidesa.com.
+94.138.204.62.in-addr.arpa.
+mohegansunpocono.com.
+222.130.195.187.in-addr.arpa.
+llwineworld.com.
+i2.ytimg.com.
+sp.cwfservice.net.
+112.235.56.186.in-addr.arpa.
+mx.ablefreight.com.
+b.scorecardresearch.com.
+graph.facebook.com.
+js2.wlxrs.com.
+by2msg3010606.gateway.messenger.live.com.
+urs.microsoft.com.
+help.amaland.com.
+pointemagazine.com.
+gdata.youtube.com.
+austinfoodcarts.com.
+bloomu.edu.
+34.64.252.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+multiplos.hotwords.com.br.
+translate.google.com.mx.
+beatrizsalas10.blogspot.com.
+65.54.55.190.in-addr.arpa.
+www.plattoes.com.
+rss.elmundo.es.
+by2msg4020409.gateway.messenger.live.com.
+bd-natok.com.
+aptar.com.
+es-la.facebook.com.
+www.rome.info.
+userimages02-akm.imvu.com.
+www30l2.glam.com.
+www.gamersmint.com.
+108.59.129.189.in-addr.arpa.
+ypk.cs4u.co.il.
+smf.prefpoa.com.br.
+developers.facebook.com.
+pleated-jeans.com.
+a5.sphotos.ak.fbcdn.net.
+cachend.meetlocals.com.rncdn1.com.
+apps.facebook.com.
+www.bateriafinas.biz.
+28.181.85.75.in-addr.arpa.
+t.co.
+www.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+140.40.78.184.in-addr.arpa.
+crossinginc.com.inbound15.mxlogicmx.net.
+www.google.com.
+appfrica.net.
+www.wwemelina.com.
+ads.lfstmedia.com.
+medusa.it.
+qu.ebay.com.
+www.shabbyfrenchcottage.com.
+lycosasia.com.
+distilleryimage2.instagram.com.
+mcdr-law.com.inbound10.mxlogicmx.net.
+a-0.19-230fc081.c0f0081.1518.19d4.2f4a.210.0.98wd185z1pd8v166u63l2c1lqt.avqs.mcafee.com.
+incidentalsgiftshop.com.
+itom.com.
+83.205.168.192.in-addr.arpa.
+www.opodo.at.
+us.my.alibaba.com.
+clients1.google.com.
+172.135.94.75.in-addr.arpa.
+apps.facebook.com.
+kitanaisasayaki.foroactivo.com.
+email.gemlimo.com.
+60.176.53.178.in-addr.arpa.
+secure-us.imrworldwide.com.
+toolbarqueries.google.com.
+ssw.live.com.
+d.agkn.com.
+www.britevents.com.
+ad.yieldmanager.com.
+:rjljfdre.52mj.
+apps.facebook.com.
+external.ak.fbcdn.net.
+epd5fa8vi.u25y3c6x.
+adspaces.ero-advertising.com.
+147.1.165.188.in-addr.arpa.
+0af2d87b0af12c898897744f51c37b7f.org.
+tc10.easythumbhost.com.
+d7.zedo.com.
+distilleryimage9.s3.amazonaws.com.
+159.144.42.190.in-addr.arpa.
+www.cocanews.com.
+read.gov.
+access1.net.
+caglarteknik.com.
+img.hotwords.com.br.
+218.28.55.80.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+mantecamail.sjcoe.net.
+152.89.120.190.in-addr.arpa.
+a.root-servers.net.
+153.71.43.208.in-addr.arpa.
+blog.sproutcore.com.
+112.175.172.190.in-addr.arpa.
+pastordice.blogcindario.com.
+msfs.nspmotion.com.
+157.245.222.189.in-addr.arpa.
+9.144.239.189.in-addr.arpa.
+124.193.19.190.in-addr.arpa.
+19.77.228.67.in-addr.arpa.
+external.ak.fbcdn.net.
+www.facebook.com.
+dnl-07.geo.kaspersky.com.
+www.facebook.com.
+mp.moshimo.com.
+security.freebsd.org.
+arqiva.com.
+mail.tencorr.com.
+news.google.com.
+api.mixpanel.com.
+halo.neoseeker.com.
+enquete.linternaute.com.
+6%20hermosos%20marcos%20para%20fotos%20en%20png.
+successfulcompanies.com.
+i49.tinypic.com.
+86.58.246.24.in-addr.arpa.
+nnmigmmlh.n27f5r5e.
+evintl-aia.verisign.com.
+www.donewaiting.com.
+www.google-analytics.com.
+s-static.ak.facebook.com.
+adspaces.ero-advertising.com.
+photos-c.ak.fbcdn.net.
+10-courier.push.apple.com.
+260.webim0247.webim.myspace.com.
+228.114.240.88.in-addr.arpa.
+static.ak.connect.facebook.com.
+static.ak.fbcdn.net.
+hiresystems.com.
+rwenpower.com.
+experiments.instrum3nt.com.
+webcache.googleusercontent.com.
+a.root-servers.net.
+147.138.30.189.in-addr.arpa.
+t.co.
+2itb.com.
+pixel.facebook.com.
+creativosonline.org.
+_951_89_9.
+hey-tu.jimdo.com.
+msdn.microsoft.com.
+joomlavi.vn.
+ljhuqasjdz.info.
+smtp.gmail.com.
+inbound.sunsetstudio.com.netsolmail.net.
+ad.yieldmanager.com.
+alerts.conduit-services.com.
+vulcanlogix.com.
+dhs.state.il.us.
+flqfamxsm.00yb.
+6.198.173.90.in-addr.arpa.
+68.95.236.189.in-addr.arpa.
+www.google.com.
+chart.googleapis.com.
+www.payidar.net.
+172.230.190.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+25.129.251.212.in-addr.arpa.
+www.bo.avon.com.
+60.63.91.186.in-addr.arpa.
+basketball.stack.com.
+teredo.ipv6.microsoft.com.
+www.tarotdeesperanza.es.
+c13.zedo.com.
+i1.ytimg.com.
+wild-fb-apache-active-vip.playdom.com.
+www.laguiabonaerense.com.ar.
+twitter.com.
+zq8cbrr92.43ex.
+mail.sjgames.com.
+wpad.
+203.112.228.67.in-addr.arpa.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+seniorflexonics.com.
+teredo.ipv6.microsoft.com.
+photos-e.ak.fbcdn.net.
+node1.bbcimg.co.uk.
+www.cnnmoney.com.
+galardigroup.com.
+vtekusa.com.s9b2.psmtp.com.
+t5.oopsmovs.com.
+119.196.199.187.in-addr.arpa.
+www.asiansquash.com.
+aol.com.
+d2099343.xoom.it.
+profile.ak.fbcdn.net.
+77.7.51.190.in-addr.arpa.
+180medical.com.
+m.ebuddy.com.
+ro.wikipedia.org.
+48.216.55.50.in-addr.arpa.
+110.210.89.186.in-addr.arpa.
+20.95.53.186.in-addr.arpa.
+googlemail.l.google.com.
+facemoods.com.
+sosyalmedya.co.
+skdstudio.com.
+bakery.teamlava.com.
+cdn.orbengine.com.
+www.bkrtx.com.
+a.root-servers.net.
+jonlscott.com.
+api.zynga.com.
+www.picoscar.com.
+barracuda.sadlier.com.
+fbcdn-photos-a.akamaihd.net.
+edge.sharethis.com.
+95.100.70.99.in-addr.arpa.
+64.19.123.84.in-addr.arpa.
+static.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+www.facebook.com.
+9juexh:gn.n16k3n9y.
+166.85.158.189.in-addr.arpa.
+gfx2.hotmail.com.
+mail2.shabakah.net.sa.
+syndication.mmismm.com.home.
+tealab.com.
+am.joneslanglaselle.com.
+apps.facebook.com.
+watsonfurniture.com.s7a1.psmtp.com.
+178.41.171.201.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+ksn1-11-part1.kaspersky-labs.com.
+ka2.no-ip.biz.
+a.root-servers.net.
+50.149.220.66.in-addr.arpa.
+showbiz.count.brat-online.ro.
+api.twitter.com.
+market.android.com.
+m.youtube.com.
+221.222.205.190.in-addr.arpa.
+www.imdb.com.
+lightera.com.
+forums.taleworlds.com.
+escuela.ipae.pe.
+d2ainc.com.
+i.ytimg.com.
+plexmovie.plexapp.com.
+connect.facebook.net.
+a.root-servers.net.
+isatap.felipe.
+www.20minutos.es.
+client-software.real.com.
+oshea.com.
+92.105.30.88.in-addr.arpa.
+218.0.173.190.in-addr.arpa.
+prov.us.mydlink.com.
+static.ak.fbcdn.net.
+93.177.74.70.in-addr.arpa.
+ok-training.ru.
+_231_97_3.
+152.102.34.190.in-addr.arpa.
+pagead2.googlesyndication.com.
+jxliu.com.
+ads2.iforex.com.
+anmpress.com.
+www.hulaisland.com.
+iji.com.
+theimaginarybody.co.uk.
+e566.b.akamaiedge.net.
+local537.com.
+rincon.com.s5a1.psmtp.com.
+117.224.7.200.in-addr.arpa.
+creative.ak.fbcdn.net.
+support.google.com.
+a3.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+50.66.187.190.in-addr.arpa.
+www.nero.com.
+www.hcso.tampa.fl.us.
+cdn.tacoda.at.atwola.com.
+t1.gstatic.com.
+k12.dserv.com.
+www.enterprise.com.
+www.maxi-juegos.com.
+translate.google.com.mx.
+au.download.windowsupdate.com.
+.
+butlerme.com.
+photos-h.ak.fbcdn.net.
+maa.com.my.
+theor.jinr.ru.
+msmgate.mrg.uswest.com.
+zorfox.com.
+www.minilening.nl.
+apairofnuts.com.
+ssl.gstatic.com.
+ereshermosa.galeon.com.
+a5.sphotos.ak.fbcdn.net.
+galasso.com.s8a1.psmtp.com.
+sk.hicow.com.
+408.ch.meebo.com.
+static.ak.fbcdn.net.
+bestofeverythingafter50.com.
+www.aprendelenguadesignos.
+231.44.132.187.in-addr.arpa.
+sportsmanflyer.blogspot.com.
+www.kissinggames.org.
+bp.specificclick.net.
+a.root-servers.net.
+maxi1419.newsvine.com.
+sn.nishitech.ac.jp.
+js.wlxrs.com.
+pixel.facebook.com.
+a.root-servers.net.
+219.230.243.189.in-addr.arpa.
+www.kayak.com.
+97.104.133.189.in-addr.arpa.
+115.96.220.41.in-addr.arpa.
+mail.jrbooth.net.
+s.youtube.com.
+activesync.softonic.com.br.
+153.2.76.201.in-addr.arpa.
+www.corodebabel.com.ar.
+e3353.c.akamaiedge.net.
+www.photowatches.eu.
+3d.pchome.net.
+175.61.91.186.in-addr.arpa.
+counterb.statcounter.com.
+my56k.net.
+2.127.14.187.in-addr.arpa.
+laposte.net.
+m:ybilogt.h36m0a7l.
+217.119.51.190.in-addr.arpa.
+sq.wikipedia.org.
+sn3.mailshell.net.
+24.125.233.220.in-addr.arpa.
+www.opdirect.net.
+www.facebook.com.
+cust6410-2.in.mailcontrol.com.
+www.lasbahamas.es.
+partner.googleadservices.com.
+sac.gti.mcafee.com.
+developers.facebook.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx.openmail.paran.com.
+92.185.44.83.in-addr.arpa.
+ar.iiarjournals.org.
+liscuba.sld.cu.
+mobile.juicyads.com.
+wboc.com.
+accounts.google.com.
+p-posad.ru.
+rp.gwallet.com.
+b.ads1.msads.net.
+ie9.discoverbing.com.
+www.enviprotect.de.
+s6.motherlessmedia.com.
+a2.sphotos.ak.fbcdn.net.
+chirrup.com.
+photos-a.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.icqoso.com.
+31.162.3.107.in-addr.arpa.
+ng.lighthousez11.com.
+7.45.27.187.in-addr.arpa.
+www.gamelink.com.
+overstockcom.112.2o7.net.
+38.27.139.189.in-addr.arpa.
+www.bywifi.com.
+intovsts.net.
+www.fastaccess.drivers.bellsouth.net.
+191.55.37.213.in-addr.arpa.
+www.yahoo.com.
+google.com.
+d3lvr7yuk4uaui.cloudfront.net.
+photos-g.ak.fbcdn.net.
+toiletpaperexpress.wordpress.com.
+i3.ytimg.com.
+fbcdn-photos-a.akamaihd.net.
+i2.ytimg.com.
+www.mexicantextiles.com.
+86.186.162.189.in-addr.arpa.
+q.ebaystatic.com.
+ox-i.earnmydegree.com.
+a.root-servers.net.
+rj.m.taobao.com.
+83.225.102.201.in-addr.arpa.
+98.164.246.220.in-addr.arpa.
+time.nist.gov.
+82.63.114.98.in-addr.arpa.
+mx.accuratecontrols.com.
+notifications.conduit-services.com.
+clients2.google.com.
+upload.traidnt.net.
+code.jquery.com.
+www.minispel.be.
+fbcdn-photos-a.akamaihd.net.
+plusone.google.com.
+11.241.83.62.in-addr.arpa.
+www.chinasportsbeat.com.
+photos-f.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+50.143.46.68.in-addr.arpa.
+adkny.org.
+bhk.spb.ru.
+groups.google.com.mx.
+lindaburwell.com.
+247.82.154.187.in-addr.arpa.
+rad.msn.com.
+t.co.
+a.root-servers.net.
+100.63.31.83.in-addr.arpa.
+keetchins.com.
+nordix-metrology.ru.
+_348_69_5.
+myrealfanatictv.blogspot.com.
+carp3.rjf.com.
+s-static.ak.facebook.com.
+95.146.220.66.in-addr.arpa.
+www.xvidupdate.com.
+by2msg3030108.by2.gateway.edge.messenger.live.com.
+235.177.109.186.in-addr.arpa.
+www.bywifi.com.
+www.angelteenagers.com.
+t.337.com.
+ssl.google-analytics.com.
+atyab.com.
+www.rmkstore.com.
+external.ak.fbcdn.net.
+eck7.ru.
+nychhc.org.
+ccnow.wip.digitalrivercontent.net.
+tools.google.com.
+img25.imageshack.us.
+profile.ak.fbcdn.net.
+www.google.com.
+nakara.china.alibaba.com.
+a1.sphotos.ak.fbcdn.net.
+wiki.bssd.org.
+pixel.facebook.com.
+static.ak.connect.facebook.com.
+83.65.29.85.in-addr.arpa.
+148.102.238.190.in-addr.arpa.
+nt3.ggpht.com.
+138.65.16.95.in-addr.arpa.
+jetzt.sueddeutsche.de.
+www.energy-base.org.
+www.mywebsearch.comm.
+mail.sumtel.ru.
+52.183.137.85.in-addr.arpa.
+124.15.0.10.in-addr.arpa.
+39.251.6.201.in-addr.arpa.
+a.root-servers.net.
+a2.wupload.com.
+83.173.110.190.in-addr.arpa.
+236.192.71.190.in-addr.arpa.
+amai.org.
+download-notebook-drivers.com.
+a.root-servers.net.
+www.google.com.
+moshmosh.22web.net.
+www.noticias15m.eu.
+americas.cpqcorp.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+backend8.aha.ru.
+verizon.net.
+fc79.deviantart.com.
+weather.services.conduit.com.
+204.118.156.187.in-addr.arpa.
+25.32.254.201.in-addr.arpa.
+google.com.
+a1496.da1.akamai.net.
+content.yieldmanager.edgesuite.net.
+a.root-servers.net.
+www.marcominnemann.com.
+tnz.taleo.net.
+www.art-exchange.com.
+64.243.45.151.in-addr.arpa.
+ssl-i.cdn.openx.com.
+z122cn2ej.z77s3e1e.
+250.84.5.87.in-addr.arpa.
+254.104.149.187.in-addr.arpa.
+59.66.222.24.in-addr.arpa.
+127.0.0.1.
+creative.ak.fbcdn.net.
+144.184.137.69.in-addr.arpa.
+211.158.95.2.in-addr.arpa.
+w7845x9xa.07uc.
+photos-f.ak.fbcdn.net.
+a1725.l.akamai.net.
+external.ak.fbcdn.net.
+51.233.227.189.in-addr.arpa.
+www.origenae.com.
+external.ak.fbcdn.net.
+wwws.ru.warnerbros.com.
+www.xvideos.com.
+pixel.facebook.com.
+www.facebook.com.
+adx.adnxs.com.
+a.root-servers.net.
+www.google.com.
+www.microsoft.com.
+41.167.8.200.in-addr.arpa.
+www.villagegeek.com.
+gmail-smtp-in.l.google.com.
+pagead2.googlesyndication.com.
+iadsdk.apple.com.
+creacionesycrochet.blogspot.com.
+elitaudit.ru.
+www.aasp.org.br.
+fitnessfirst.com.
+39-courier.push.apple.com.
+cande-knd.deviantart.com.
+nsx.np.dl.playstation.net.
+30.media.tumblr.com.
+pixel.facebook.com.
+directory.services.live.com.
+googleads.g.doubleclick.net.
+mk.wikipedia.org.
+safebrowsing.clients.google.com.
+ak.copi.ru.
+franational.com.
+js.admeld.com.
+ins-solutions.com.
+www.ukmediacentre.pwc.com.
+a.root-servers.net.
+empretsinf.blogs.upv.es.
+a.root-servers.net.
+www.pcl.com.
+icex.imperial.ac.uk.
+swim.lookbook.nu.
+news.google.com.mx.
+91chat.wisshen.info.
+dannyayers.com.
+platform.ak.fbcdn.net.
+www.google.com.
+photos-c.ak.fbcdn.net.
+mail.google.com.
+a.root-servers.net.
+trumedtech.com.s9a1.psmtp.com.
+pyninc.org.
+dvrlink.net.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+p7:aaqlv3.s32o1p9v.
+30.164.69.190.in-addr.arpa.
+babelfish.altavista.digital.com.
+mail.ead-sda.ru.
+content.yieldmanager.edgesuite.net.
+159.61.48.188.in-addr.arpa.
+50.174.50.201.in-addr.arpa.
+sn130w.snt130.mail.live.com.
+asu.vks.mosenergo.elektra.ru.
+jers3.info.
+external.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+pixel.facebook.com.
+131.33.174.190.in-addr.arpa.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+red.adshandy.com.
+157.65.132.189.in-addr.arpa.
+curado.ru.
+sheapfel-music.blogspot.com.
+vzppdvhisqea.com.
+cards.mail.ru.
+marbellatraumhaus.de.
+barjaweb.free.fr.
+rewards.ebay.com.
+a1.sphotos.ak.fbcdn.net.
+img.123freebrushes.com.
+d8.ce.bb.a1.top.mail.ru.
+desmond.yfrog.com.
+www.radianresearch.com.
+francais.toptwilightblogs.com.
+ad.yieldmanager.com.
+twitter.com.
+www.extube.com.
+naranjas-limones.blogspot.com.
+domein.nl.
+www.canimmigratecanada.com.
+ace.wikipedia.org.
+commons.wikimedia.org.
+baymsg1030112.gateway.messenger.live.com.
+tis17-5-en.url.trendmicro.com.
+a1406.w42.akamai.net.
+pansexualpride.tumblr.com.
+www.maishoroscopo.com.br.
+montagar.com.
+www.xplonet.net.
+neoretro.tumblr.com.
+www.facebook.com.
+xxx.stopklatka.pl.
+safebrowsing.clients.google.com.
+www.digwin.com.
+dollhousediary.com.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+api-read.facebook.com.
+sp.ask.com.
+cdn-7.nflximg.com.
+octoberon.blogspot.com.
+photos-d.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+trendtechnology.com.
+83.72.102.71.in-addr.arpa.
+m.addthisedge.com.
+feeds.feedburner.com.
+entretenimiento.starmedia.com.
+rs896l33.rapidshare.com.
+www.fm88-108.nl.
+gateway.arabia-ins.com.lb.
+photos-a.ak.fbcdn.net.
+233.208.124.186.in-addr.arpa.
+20minutos.feedsportal.com.
+34.139.137.187.in-addr.arpa.
+docs.google.com.
+www.facebook.com.
+174.137.220.41.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+apple.com.
+en.globetorch.com.
+53.221.132.192.in-addr.arpa.
+www.blogger.com.
+www.sgisland.gs.
+57.186.48.65.in-addr.arpa.
+e566.b.akamaiedge.net.
+piim.com.
+61.236.56.187.in-addr.arpa.
+datafeed.weatherbug.com.
+24-courier.push.apple.com.
+d2105352.xoom.it.
+140.108.27.189.in-addr.arpa.
+download.windowsupdate.com.
+profile.ak.fbcdn.net.
+hi-in.facebook.com.
+www.wikicristiano.org.
+147.22.161.101.in-addr.arpa.
+mail.s1000658.ptasp.com.
+a.root-servers.net.
+draxis.com.
+rcp.na.blackberry.com.
+pixelsmuertos.com.
+creaturesofcomfort.us.
+240.233.85.85.in-addr.arpa.
+bogdanos.skai.gr.
+anycoolspb.ru.
+mx4.peterhost.ru.
+www.lacaxcada.com.
+194.253.150.79.in-addr.arpa.
+q2broadcasting.com.
+www.world-finance-conference.com.
+enternet.hu.
+www.artesaniaelsol.es.
+static.ak.fbcdn.net.
+twitter.com.
+init-p01md.apple.com.
+a2.sphotos.ak.fbcdn.net.
+www.diariopyme.com.
+static-js.veevr.com.
+73.73.78.190.in-addr.arpa.
+api.facebook.com.
+de-de.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+www.smlisten.dk.
+82.103.157.98.in-addr.arpa.
+geo.messenger.services.live.com.
+lib.verycd.com.
+115.83.145.190.in-addr.arpa.
+mail.live.com.
+resolver1.bullguard.ctmail.com.
+123.86.172.190.in-addr.arpa.
+tw.apple.com.
+beta.twitlonger.com.
+a1.sphotos.ak.fbcdn.net.
+f26batchimg.auctions.yahoo.co.jp.
+weather.partners.msn.com.
+www.google.com.
+129.146.176.124.in-addr.arpa.
+google.com.
+dsn2.d.skype.net.
+www.islam101.com.
+external.ak.fbcdn.net.
+api.nanigans.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+onskookboek.be.
+tools.google.com.
+profile.ak.fbcdn.net.
+clients4.google.com.
+controltemp.com.
+plus.google.com.
+a.root-servers.net.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+csi.gstatic.com.
+126.74.9.46.in-addr.arpa.
+profile.ak.fbcdn.net.
+i1.ytimg.com.
+www.google.com.
+2.248.199.190.in-addr.arpa.
+about.duke.edu.
+mueller-runte.de.
+www.italkcash.com.
+chicvintagebrides.com.
+28.181.92.108.in-addr.arpa.
+www.hotel-theresia.com.
+photos-d.ak.fbcdn.net.
+inbound.bulkpetro.com.netsolmail.net.
+dns.msftncsi.com.
+amdinternet.com.
+27.78.8.201.in-addr.arpa.
+220.95.37.46.in-addr.arpa.
+a996.mm1.akamai.net.
+wwwclu.um.es.
+www.toshibapc.com.
+kibbey.net.
+189.250.65.187.in-addr.arpa.
+www.conjugacionesverbos.com.
+a.root-servers.net.
+retera.ru.
+a2.sphotos.ak.fbcdn.net.
+plusone.google.com.
+www.pro-billiard.ru.
+assets.treasure.zgncdn.com.
+api.facebook.com.
+nxa-ls.s3.amazonaws.com.
+a1725.l.akamai.net.
+svrintl-crl.verisign.com.
+zi.net.
+crl3.digicert.com.
+777777.6d696e696e6f7661.6f7267.80h505e4c05.webcfs00.com.
+insight.aon.com.
+shared.live.com.
+windowslivehelp.com.
+facebook-chat.softonic.de.
+msnbcmedia.msn.com.
+google.com.
+a5.sphotos.ak.fbcdn.net.
+litvany.com.
+farm6.staticflickr.com.
+www.ambito.com.
+66.59.229.189.in-addr.arpa.
+accounts.youtube.com.
+mail.yahoo.com.
+www.despegar.com.mx.
+moseisleyradio.com.
+www.jq663.com.
+edge.quantserve.com.
+ru.wikipedia.org.
+a997.mm1.akamai.net.
+www.denacrain.com.
+www-google-analytics.l.google.com.
+s-external.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+mta5.am0.yahoodns.net.
+219.207.141.201.in-addr.arpa.
+clients1.google.com.
+www.newszoom.com.
+110.8.240.111.in-addr.arpa.
+140.34.230.67.in-addr.arpa.
+cffei.org.s5a1.psmtp.com.
+49.161.168.192.in-addr.arpa.
+contextmenu.toolbar.conduit-services.com.
+t1-completion.amazon.com.
+pt-br.facebook.com.
+www.google.com.
+id.l.google.com.
+connect.facebook.net.
+ed62.zeekler.com.
+56.82.42.201.in-addr.arpa.
+www.sm-rgs.com.
+groups.google.com.mx.
+a.root-servers.net.
+www.bloomenergy.com.
+58.235.55.74.in-addr.arpa.
+71.179.232.190.in-addr.arpa.
+www.freestream.pl.
+d7.zedo.com.
+thirdnetworks.com.
+api.facebook.com.
+249.110.148.190.in-addr.arpa.
+mail.nicox.it.
+mail.pierce-industries.com.
+serw.clicksor.com.
+128.222.173.190.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+157.174.246.201.in-addr.arpa.
+43.107.25.114.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+download.cloudantivirus.com.
+aj8q45hdn.10qe.
+splcen.blogspot.com.
+a.root-servers.net.
+gemma-international.co.uk.
+favstar.fm.
+sillylikes.com.
+cs244.vk.com.
+creative.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+hu.wikipedia.org.
+anomalink.com.
+lh4.googleusercontent.com.
+images.apple.com.
+13.62.173.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+115.222.142.190.in-addr.arpa.
+34.204.14.186.in-addr.arpa.
+netthere.com.
+a3.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+www.gratispeliculas.org.
+teredo.ipv6.microsoft.com.
+tap2-cdn.rubiconproject.com.
+ad.adnetwork.net.
+www.facebook.com.
+s-static.ak.facebook.com.
+ads.bluelithium.com.
+a7.sphotos.ak.fbcdn.net.
+s0000686.ecdomain.net.forestproducts.sca.com.
+indepsocres.spb.ru.
+apps.facebook.com.
+ex2.broadser.
+billpentz.com.
+upxewi.com.
+www.ark.ac.uk.
+img20.imageshack.us.
+a.root-servers.net.
+www.youtube.com.
+ochaonline.un.org.
+morgan.kyschools.us.
+17.204.141.201.in-addr.arpa.
+www.apexjr.com.
+kkaqhzl:a.u21y9s7g.
+mozhelah.com.
+a.root-servers.net.
+mx.youtube.com.
+rcp.na.blackberry.com.
+explore.live.com.
+acor.org.
+a3.twimg.com.
+graph.facebook.com.
+guru.avg.com.
+www.facebook.com.
+www.gemma.es.
+a.root-servers.net.
+d3lvr7yuk4uaui.cloudfront.net.
+eyepatchfilms.com.
+profile.ak.fbcdn.net.
+lacasadecloti.blogspot.com.
+profile.ak.fbcdn.net.
+img7.imageshack.us.
+a1.sphotos.ak.fbcdn.net.
+api.twitter.com.
+170.251.91.186.in-addr.arpa.
+214.53.130.72.in-addr.arpa.
+secure.gravatar.com.
+gameplay.mochimedia.com.
+timmermanco.com.
+www.anythingtostopthepain.com.
+188.141.39.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+analisismatematico.wordpress.com.
+www.esi-audiotechnik.com.
+a.root-servers.net.
+rxdrugstore-pro.com.
+157.17.149.190.in-addr.arpa.
+www.cemexcolombia.com.
+blog.advancedphotoshop.co.uk.
+ksn1-11-part1.kaspersky-labs.com.
+sn122w.snt122.mail.live.com.
+schaubroeck.be.
+194.206.162.189.in-addr.arpa.
+files.rsf-es.org.
+cs4100.vkontakte.ru.
+cwahi.net.multi.uribl.com.
+eu4.grannytaste.com.
+samsungmobile.accu-weather.com.
+tematica.mercadolibre.com.ve.
+tecnociencia.co.
+www.tenseconds.com.au.
+anuncie.taringa.net.
+www.planetahuerto.es.
+www.isearch.im.
+www.bg.gladiatus.com.
+www.google-analytics.com.
+a7.sphotos.ak.fbcdn.net.
+mail.jlk.com.
+mlsksfkajsfsa.com.
+rentar-casa.vivastreet.com.mx.
+thethirdestate.net.
+cwomissions.org.
+182.241.59.200.in-addr.arpa.
+94.146.203.190.in-addr.arpa.
+cdn.api.twitter.com.
+tecnologia.starmedia.com.
+webcognisant.com.
+102.184.38.190.in-addr.arpa.
+www.youtube.com.
+146.9.165.189.in-addr.arpa.
+wg8.so-net.ne.jp.
+a-0.19-22092081.20200b3.1518.19d3.3ea1.410.0.sddcpssrmu8th8pkmqaj6ca6p6.avqs.mcafee.com.
+www.powerpresspodcast.com.
+a.root-servers.net.
+www.thedandyproject.com.
+developers.facebook.com.
+136.93.52.59.in-addr.arpa.
+107.181.153.189.in-addr.arpa.
+babesbycity.com.
+fbcdn-profile-a.akamaihd.net.
+mail.iiwengr.com.
+www.planetfortress.com.
+webographers.com.
+yahoo.com.
+althenia.net.
+ltgqcs.com.
+www.multiautomotores.com.ar.
+www.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+static.supadupa.me.
+pt-br.facebook.com.
+www.axeso5.com.
+google.com.
+42.43.237.190.in-addr.arpa.
+88.100.232.24.in-addr.arpa.
+www.bywifi.com.
+a2.sphotos.ak.fbcdn.net.
+235.217.208.201.in-addr.arpa.
+error404.000webhost.com.
+_291_07_6.
+faces.doccheck.com.
+85.111.51.190.in-addr.arpa.
+fr.webrep.avast.com.
+www.woldoringa.com.
+dusty.sensi.org.
+img11.imageshack.us.
+an.wikipedia.org.
+www.plasteck.cl.
+www.facebook.com.
+api.twitter.com.
+a1.espncdn.com.
+cs.adxpansion.com.
+a639.da1.akamai.net.
+101.17.153.201.in-addr.arpa.
+81.211.179.178.in-addr.arpa.
+s.ytimg.com.
+gihfvp1mq.60bb.
+101.103.97.71.in-addr.arpa.
+dr._dns-sd._udp.belkin.
+169.202.78.177.in-addr.arpa.
+www.formacionoptometrica.com.
+www.roodos.com.ve.
+pronetworksolutions.net.
+www.pasarmiedo.net.
+kroupnov.ru.
+s.ytimg.com.
+a1.sphotos.ak.fbcdn.net.
+2009-861.blog.163.com.
+www-google-analytics.l.google.com.
+157.15.46.207.in-addr.arpa.
+38.159.220.77.in-addr.arpa.
+131.196.113.177.in-addr.arpa.
+gclsupport.nhl.com.
+fpsaw35c3.o58z1z8n.
+a5.sphotos.ak.fbcdn.net.
+us.bc.yahoo.com.
+apple.imap.mail.yahoo.com.
+configuration.apple.com.
+biztravels-museums.net.
+cdn-2emediafire-2ecom-2fblank-2ehtml.ph.bdrbl.com.
+www.themendo.com.
+232.29.27.72.in-addr.arpa.
+137.169.158.94.in-addr.arpa.
+sites.google.com.
+a.root-servers.net.
+news.google.com.mx.
+i1.ytimg.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+csi.gstatic.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.stlawrencecollege.ca.
+homevalleybank.com.
+4.233.213.201.in-addr.arpa.
+182.194.230.189.in-addr.arpa.
+mail2.globalddh.net.
+images6.porkolt.com.
+sn1msg2010622.gateway.messenger.live.com.
+video.google.com.mx.
+marmweb.com.
+a6.sphotos.ak.fbcdn.net.
+www.z-sys.org.
+cs9394.vk.com.
+money.service.msn.com.
+a.root-servers.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+lh3.googleusercontent.com.
+us.ebmpapst.com.
+www.q8land.net.
+error.facebook.com.
+mail.outdoorimage.com.au.
+tags.expo9.exponential.com.
+www.noticias.com.
+29-courier.push.apple.com.
+img810.imageshack.us.
+rospres.com.
+labotp.org.
+233.168.227.189.in-addr.arpa.
+s3.productwiki.com.
+www.efe2003.com.
+221.158.255.190.in-addr.arpa.
+ads.adxpose.com.
+31-courier.push.apple.com.
+apple.com.
+233.252.244.99.in-addr.arpa.
+mail.
+mail.carmensvacuum.com.
+nnnn.com.
+akqa.com.s5b2.psmtp.com.
+paraellas.net.
+img2.etsystatic.com.
+242.139.181.78.in-addr.arpa.
+server5.cnsonline.com.
+profile.ak.fbcdn.net.
+telephonecode.ru.
+cacheck.ey.net.
+astrotrans.blogspot.com.
+a.root-servers.net.
+www.cdtracks.org.
+secure-us.imrworldwide.com.
+ch.foto.com.
+thefutblog.info.
+mail.seiko-i.com.
+a.root-servers.net.
+34-courier.push.apple.com.
+artdography.com.
+www.myriamfaresfans.com.
+ad.bmo.tbn.ru.
+eaacorp.com.
+m.hotmail.com.
+91.95.134.115.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+email.urbanoutfitters.com.
+www.facebook.com.
+profile.ak.fbcdn.net.
+38.100.8.200.in-addr.arpa.
+e1789.c.akamaiedge.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+usd416.org.
+ad-emea.doubleclick.net.
+sunchem.ru.
+www.narcissism101.com.
+169.45.43.186.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+214.122.244.61.in-addr.arpa.
+140.225.224.24.in-addr.arpa.
+googleads.g.doubleclick.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sp.cwfservice.net.
+www.youtube.com.
+goponygo.com.
+d2098345.xoom.it.
+www.project-lime.com.
+a1725.l.akamai.net.
+partyheld.de.
+248.230.202.190.in-addr.arpa.
+grandrating.ru.
+fr.fxfeeds.mozilla.com.
+ssl.gstatic.com.
+www.hairoin.de.
+124.197.144.187.in-addr.arpa.
+127.165.146.187.in-addr.arpa.
+www.amaitlan.mx.
+adserving.cpxinteractive.com.
+gr4kcwiaw.g66s8x7v.
+cap1.conduit-apps.com.
+mx1.satelcom.qc.ca.
+www.trafficfactory.biz.
+r6xmlzsah.19av.
+21.82.245.189.in-addr.arpa.
+mail.kingroup.ru.
+able.co.uk.
+bchy4g:o4.68qi.
+68.8.120.189.in-addr.arpa.
+www.ole.com.ar.
+coches-actu.com.
+faypublicidad.com.
+133.150.58.85.in-addr.arpa.
+yahoo.com.
+xcdn.xgraph.net.
+urs.microsoft.com.
+andersonsecurity.com.
+www.mcc.is.
+time.chttl.com.tw.
+www.djlah.net.
+divison8.mcanime.net.
+173.72.66.190.in-addr.arpa.
+_529_50_0.
+www.strictdownload.com.
+bugmpa.com.
+superoil.ru.
+45.44.90.186.in-addr.arpa.
+v9.lscache4.googlevideo.com.
+widget.uservoice.com.
+a1.sphotos.ak.fbcdn.net.
+webcameffects.softonic.com.
+accounts.google.com.
+photos-c.ak.fbcdn.net.
+a.root-servers.net.
+24.18.246.190.in-addr.arpa.
+repo666.ultrasn0w.com.
+138.178.125.84.in-addr.arpa.
+artbatik.ru.
+fifelife.ru.
+89.79.55.65.in-addr.arpa.
+www.losgobernadores.com.
+profile.ak.fbcdn.net.
+apis.google.com.
+225.89.132.190.in-addr.arpa.
+a.root-servers.net.
+www.kaixindian.com.
+entre-pensamientos.blogspot.com.
+www.ebayers.es.
+www.panetdeal.co.il.
+saimecha.wordpress.com.
+farorbit.com.
+www.primarydisplays.co.uk.
+solo.aqui.creatusfrases.net.
+maudnewton.com.
+www.prettyteenpics.com.
+carmen-ysusrecetas.blogspot.com.
+memrb.spb.su.
+feedroom.speedera.net.
+msupdate.emodio.com.
+.
+54.12.156.186.in-addr.arpa.
+27.229.235.89.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+117.29.224.189.in-addr.arpa.
+www.facebook.com.
+waterhunters.ru.
+mystart.uservoice.com.
+254.166.109.200.in-addr.arpa.
+128.187.68.177.in-addr.arpa.
+www.rolisimas.com.
+www.naharro.com.
+bit.ly.
+1jhw3vc93.t79x7g0y.
+developers.facebook.com.
+photos-g.ak.fbcdn.net.
+_925_22_3.
+citukerala.org.
+133.139.62.186.in-addr.arpa.
+58.109.43.114.in-addr.arpa.
+nooopuedeser.blogspot.com.
+google.com.
+corporatefitnessworks.com.
+1.bp.blogspot.com.
+59.1.26.96.in-addr.arpa.
+4.209.150.189.in-addr.arpa.
+www.sodoku.com.
+130.235.55.74.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.eluniversaltv.com.mx.
+byrdr.omega.contacts.msn.com.
+www.importjap.com.
+ads2.msads.net.
+www.herbalifemauralaussanjuan.es.tl.
+47.224.25.177.in-addr.arpa.
+233.129.28.187.in-addr.arpa.
+mortenjust.com.
+109.113.88.186.in-addr.arpa.
+twitter.com.
+robinson-derus.co.nz.
+poverh.kiev.ua.
+i2.ytimg.com.
+www.zonajobs.com.ar.
+hotmail.com.
+www.amazon.es.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+graph.facebook.com.
+jkt.spb.ru.
+a.root-servers.net.
+i3.ytimg.com.
+.
+mail1.chemspec.com.
+kuhnyatv.ru.
+allure.com.
+34.49.218.202.in-addr.arpa.
+www1.k9webprotection.com.
+healthcontent.bhsi.com.
+www.twitter.com.
+www.googleadservices.com.
+instagib.net.
+www.bansa.org.
+97.205.27.77.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+56.225.102.190.in-addr.arpa.
+115.146.110.201.in-addr.arpa.
+google.com.
+rawwordrecords.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+_336_08_7.
+zxtm-vnxhosapaha.nexica.net.
+www.buzzfocus.com.
+52.121.87.213.in-addr.arpa.
+apple.com.
+ugzxbcuhe.35qq.
+hotword.dictionary.com.
+mobile.airasia.com.
+sgqsyeaoes.com.
+151.149.247.190.in-addr.arpa.
+www.google-analytics.com.
+229.169.209.201.in-addr.arpa.
+www.facebook.com.
+www.mediachannel.com.
+www.amazon.com.
+i4.ytimg.com.
+profile.ak.fbcdn.net.
+img.nextproducts.net.
+time.chttl.com.tw.
+a4.mzstatic.com.
+244.207.240.148.in-addr.arpa.
+static.ak.fbcdn.net.
+www.desktopgoldfish.com.
+b._dns-sd._udp.0.10.168.192.in-addr.arpa.
+53.143.168.192.in-addr.arpa.
+developers.facebook.com.
+airs.jpl.nasa.gov.
+www.youtube.com.
+www.anarchistcookbookz.com.
+mail.cyrbustours.com.
+32-courier.push.apple.com.
+www.tpwang.net.
+color-by-numbers.net.
+umail.net.
+mail.promtractor.ru.
+update3.jdownloader.org.
+www.mcanime.net.
+thomarie-fanclub.deviantart.com.
+29.72.149.99.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+mail.plasa.com.
+api.conduit.com.
+www.facebook.com.
+time.nist.gov.
+api.conduit.com.
+p0b.ru.
+.
+www.update.microsoft.com.
+checkip.dyndns.org.
+39.49.10.75.in-addr.arpa.
+idipus.tumblr.com.
+www.encuentro-practico.com.
+www.yahoo.com.
+nonghai.net.multi.uribl.com.
+www.w3.org.
+231.11.223.148.in-addr.arpa.
+blog.metropolislibros.com.
+by2msg3010518.by2.gateway.edge.messenger.live.com.
+me.effectivemeasure.net.
+www.datefree.com.
+tw.pool.ntp.org.
+bs.serving-sys.com.
+mail.gestionrv.com.
+d3lvr7yuk4uaui.cloudfront.net.
+graph.facebook.com.
+client-software.real.com.
+csc3-2010-crl.verisign.com.
+fr-fr.facebook.com.
+modern-glass.com.
+oldis.ru.
+east-west.fr.
+www.google.com.
+240.60.55.174.in-addr.arpa.
+196.139.177.190.in-addr.arpa.
+animesite2.blogspot.com.
+air-control.softonic.com.
+103.198.79.188.in-addr.arpa.
+.
+www.justin.tv.
+smokingmirrors.blogspot.com.
+img100.xvideos.com.
+www.google.com.
+repositori.upf.edu.
+www.cenetec.salud.gob.mx.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+final-fantasy-x-tidus.programasgratis.es.
+www.google.com.
+muzy.com.
+254.1.168.192.in-addr.arpa.
+vbe.cci.
+60.68.141.201.in-addr.arpa.
+isatap.home.
+l.yimg.com.
+artesiatech.com.
+bleah.com.
+roitrack.urtbk.com.
+_897_64_8.
+a.root-servers.net.
+www4.l.google.com.
+exp01.eset.com.
+105.245.231.77.in-addr.arpa.
+yztkxo2fh.63tm.
+mail.clvec.ie.
+39-courier.push.apple.com.
+www.google-analytics.com.
+earthds.info.
+profile.ak.fbcdn.net.
+mail.mtremblay.com.
+evermor.net.
+a6.sphotos.ak.fbcdn.net.
+224.92.131.187.in-addr.arpa.
+lrhvridjyg.info.
+dl.macpaw.com.
+glueckkanja-de.mail.eo.outlook.com.
+fb-client-0.castle.zynga.com.
+mscrl.microsoft.com.
+www.weheartit.com.
+omikom.ru.
+kriminalforsorgen.dk.
+mx3.hotmail.com.
+mail.guarantyresearch.com.
+host356.hostmonster.com.
+carservis.pl.
+santarom.ru.
+68ohh6com6c1h-c.c.yom.mail.yahoo.com.
+b.static.ak.fbcdn.net.
+www.todoferreteria.com.
+207.234.226.189.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+mog.com.
+a1.twimg.com.
+a.root-servers.net.
+simurl.com.
+mail.fbcpalmetto.com.
+d7.zedo.com.
+creative.ak.fbcdn.net.
+huuah.com.
+fkjdeljfeew32233.com.
+www.facebook.com.
+www.adobe.com.
+ssl.gstatic.com.
+sartaonline.com.1.0001.arsmtp.com.
+62.158.220.66.in-addr.arpa.
+gpl-violations.org.
+takvim.com.tr.
+foto36.com.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+www.20minutos.es.
+wheelsworldwide.co.uk.
+www.youtube.com.
+www.addthis.com.
+api.twitter.com.
+elchavodelocho.bravehost.com.
+barochanynicky.su.
+138.33.247.190.in-addr.arpa.
+bit.ly.
+phoenixtechnology.com.
+l.sharethis.com.
+thecloudplayer.com.
+bizinformation.org.
+173.5.172.201.in-addr.arpa.
+pixel.facebook.com.
+haveasenseofhumor.cheezburger.com.
+www.blogpulp.com.
+remote.rtcimpex.ru.
+i25nvbyk27l68k47m39jqg23p42kvb28mwjycunr.net.
+a.root-servers.net.
+191.169.208.77.in-addr.arpa.
+fannin.k12.ga.us.
+b.scorecardresearch.com.
+_464_80_6.
+biouzhen.dyndns-server.com.
+qeeq.net.
+service.gc.apple.com.
+152.52.154.98.in-addr.arpa.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+www.chitambo.com.
+it-it.facebook.com.
+tsvetyoptom.ru.
+163.40.23.71.in-addr.arpa.
+content.everydayhealth.com.
+www.google-analytics.com.
+185.127.149.187.in-addr.arpa.
+ssl.gstatic.com.
+a-0.19-2209d081.c030083.1518.19d2.3ea1.410.0.d5g4l32d6jgjp7wsn6vrk57hvq.avqs.mcafee.com.
+rs571l33.rapidshare.com.
+photos-e.ak.fbcdn.net.
+mscrl.microsoft.com.
+susana-solea.blogspot.com.
+smtp.yopmail.com.
+www.translate.ge.
+tdy.prodigy.msn.com.
+rmd3f8mbk.v20u1c3h.
+videos-gratis.petardas.com.
+www.consultadetarotgratuita.com.
+merriam-webster.sl.advertising.com.
+clasificados.fiestaideas.com.
+daa-spokane.com.
+probe.iomegacloud.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+zcache.zgncdn.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+www.clubcassiecruz.com.
+34.5.254.41.in-addr.arpa.
+tools.google.com.
+88.28.14.187.in-addr.arpa.
+235.145.248.81.in-addr.arpa.
+cdn.naxpgaming.com.
+12.92.45.190.in-addr.arpa.
+pacificu.edu.
+t4.tagstat.com.
+110.19.34.94.in-addr.arpa.
+graphics478.nytimes.com.edgesuite.net.
+www.graydenpoper.com.
+guru.avg.com.
+ad.aim4media.com.
+twitter.com.
+192.194.208.108.in-addr.arpa.
+93.142.174.189.in-addr.arpa.
+climat24.ru.
+www.nabdh-alm3ani.net.
+beta.stun.voice.yahoo.com.
+www.ajnonline.com.
+photos-a.ak.fbcdn.net.
+darkshadows.wikia.com.
+60.130.15.189.in-addr.arpa.
+urs.microsoft.com.
+161.218.60.187.in-addr.arpa.
+pixel.facebook.com.
+suomi24.com.
+tools.google.com.
+static.ak.fbcdn.net.
+134.173.116.200.in-addr.arpa.
+sync.mathtag.com.
+data.flurry.com.
+39.183.220.62.in-addr.arpa.
+www.kt2syggf436dtag646.com.
+www.toonsup.de.
+rcw.wc24.wii.com.
+www.tko24.com.
+www.adobe.com.
+test-rt.liftdna.com.
+api.conduit.com.
+fabulousims.blogspot.com.
+www.entertainmentworld.us.tt.
+photos-e.ak.fbcdn.net.
+platform.ak.fbcdn.net.
+group.hawahome.com.
+aimnet.net.
+a.root-servers.net.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+www.l.google.com.
+search.bittorrent.com.
+webexpromt.ru.
+v2.cache1.c.youtube.com.
+www.google-analytics.com.
+132.122.114.200.in-addr.arpa.
+www.facebook.com.
+d15gt9gwxw5wu0.cloudfront.net.
+manyue.com.
+photographers.co.uk.
+bs.serving-sys.com.
+www.jatox.com.
+www.googleadservices.com.
+photos-e.ak.fbcdn.net.
+35.129.134.186.in-addr.arpa.
+mail.rstrents.com.
+veureka.net.
+coyoacan.linkbyme.com.mx.
+g.ceipmsn.com.
+sbcglobal.net.
+img.csfd.cz.
+www.linkedin.com.
+m1.webstats.motigo.com.
+www.elmundoenpositivo.com.
+a.root-servers.net.
+114.124.225.190.in-addr.arpa.
+58.72.52.99.in-addr.arpa.
+cdn-0.nflximg.com.
+86.108.221.90.in-addr.arpa.
+tap2-cdn.rubiconproject.com.
+proxy-77.ix.dailymotion.com.
+j2.yokacdn.com.
+external.ak.fbcdn.net.
+decoradecora.blogspot.com.
+profile.ak.fbcdn.net.
+138.13.94.188.in-addr.arpa.
+no10.unternehmen.com.
+mail2.elar.ru.
+clientstat.rockyourphone.com.
+253.225.85.85.in-addr.arpa.
+l.yimg.com.
+s0.2mdn.net.
+photos-g.ak.fbcdn.net.
+kinisoku.sakura.ne.jp.
+adv-lance.com.
+www.google.com.
+api-read.facebook.com.
+n8.8-d.com.
+sunde.com.inbound15.mxlogic.net.
+intercambio-compra-venta.blogspot.com.
+117.121.183.189.in-addr.arpa.
+www.perriguay.com.
+ajax.googleapis.com.
+www.google.com.
+widgets.twimg.com.
+sb-mail.sbci.com.
+211.214.200.190.in-addr.arpa.
+pt-br.facebook.com.
+36.9.222.77.in-addr.arpa.
+okoninc.com.
+a1.sphotos.ak.fbcdn.net.
+www.facebook.com.
+crl.verisign.com.
+cdn.enterupload.com.
+val-test.com.
+weather.wapp.wii.com.
+www.lib.utulsa.edu.
+sites.google.com.
+ksn2.kaspersky-labs.com.
+digg.com.
+x.tagstat.com.
+campbellalliance.com.s8b2.psmtp.com.
+www.pantallazoazul.net.
+pro.vrn.ru.
+outtengolden.com.
+dns.msftncsi.com.
+saltydroid.info.
+www.muitogostoso.com.br.
+dimeca.unica.it.
+i.canddi.com.
+36.115.172.187.in-addr.arpa.
+a.root-servers.net.
+mortgageadvisorskc.com.
+a6.sphotos.ak.fbcdn.net.
+goo.gl.
+fbcdn-photos-a.akamaihd.net.
+shared.live.com.
+cxz23.meaningtool.com.
+www.facebook.com.
+img-s3-01.mytextgraphics.com.
+mail.pleasval.k12.ia.us.
+www.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+www.facebook.com.
+aol.com.
+hash.orbitdownloader.com.
+www.google.com.
+www.tvps.com.
+professional.avira-update.com.
+tg.game2.cn.
+125.126.219.190.in-addr.arpa.
+conn.skype.com.
+aircarrierzf.com.
+profile.ak.fbcdn.net.
+www.hostalcondesa.com.
+67.230.16.190.in-addr.arpa.
+invest-centr.ru.sci.smolensk.ru.
+creative.ak.fbcdn.net.
+b._dns-sd._udp.lan.
+www.google.com.
+217.12.6.189.in-addr.arpa.
+www.wellpad.com.
+www.facebook.com.
+140.140.95.99.in-addr.arpa.
+fruit.blurtit.com.
+googleads.g.doubleclick.net.
+korigan.net.
+83.114.66.186.in-addr.arpa.
+www.softonic.cn.
+38.147.220.66.in-addr.arpa.
+steveholtvstheuniverse.tumblr.com.
+dr._dns-sd._udp.0.0.0.5.in-addr.arpa.
+157.15.192.190.in-addr.arpa.
+developers.facebook.com.
+100.1.168.192.in-addr.arpa.
+3ys5nh::h.42kc.
+freerollpw.info.
+mail.quakermaid.com.
+1st.net.com.
+api.facebook.com.
+a.root-servers.net.
+94.158.125.74.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+_198_43_8.
+ecatv.home.ne.jp.
+a3.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+www.morelosdiario.com.
+www.pekegifs.com.
+ads.tlvmedia.com.
+www.hemei.co.
+pixel.facebook.com.
+photos-f.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+cs11517.vk.com.
+themecraft.net.
+159.28.152.201.in-addr.arpa.
+www.juegosdiarios.com.
+mx.answers.yahoo.com.
+dougseven.com.
+1804289383.localhost.
+liveupdate.symantecliveupdate.com.
+71.253.230.190.in-addr.arpa.
+mx2.tgp.iphmx.com.
+btopenworld.com.
+americanmotorabilia.com.
+photos-h.ak.fbcdn.net.
+2464555234.dnsbl7.mailshell.net.
+a3.sphotos.ak.fbcdn.net.
+google.com.
+gerbergear.com.
+mystartantiphishing.com.
+btfans.3322.org.
+a.root-servers.net.
+networkedblogs.com.
+www.verbicidemagazine.com.
+freegames.zone.com.
+www.gmodules.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+178.242.18.186.in-addr.arpa.
+mail.americanzephyr.com.
+160.89.132.203.in-addr.arpa.
+supermotard.dk.
+shusd.k12.ca.us.
+news-briefs.ew.com.
+mail.mfsia.com.
+argin.net.
+211.222.2.204.in-addr.arpa.
+a.root-servers.net.
+222.80.27.177.in-addr.arpa.
+copy.yandex.net.
+mail.fcmoscow.ru.
+csi.gstatic.com.
+ads.e-planning.net.
+time.chttl.com.tw.
+www.facebook.com.
+ratings-wrs.symantec.com.
+ac3filter.net.
+1wk83cbvh.95fd.
+a995.mm1.akamai.net.
+www.swosu.edu.
+95.6.191.186.in-addr.arpa.
+159.39.143.201.in-addr.arpa.
+mx.pochemu.ru.
+i7x6a8w8x.83nx.
+comoaumentarlospechos1.blogspot.com.
+platform.twitter.com.
+platform.ak.fbcdn.net.
+totalbis.com.
+www.uwebi.org.
+178.96.91.125.in-addr.arpa.
+plus.google.com.
+tymewyse.com.
+photos-d.ak.fbcdn.net.
+cf.addthis.com.
+mscrl.microsoft.com.
+a.root-servers.net.
+gers.com.
+wpad.
+lh3.googleusercontent.com.
+sp.cwfservice.net.
+www.fireshell.wordpress.com.
+www.searchqu.com.
+www.marions-kochbuch.com.
+www.aumentodemamas.es.
+9.122.98.189.in-addr.arpa.
+www.losttv-forum.com.
+ocsp.verisign.com.
+gethotfree.eu.
+www.straponvideotop.com.
+sn136w.snt136.mail.live.com.
+kmlworks.appspot.com.
+a6.sphotos.ak.fbcdn.net.
+_133_24_3.
+www.google.com.
+txlogistik.de.
+lpamail.com.
+garply.com.
+techprolonged.disqus.com.
+toltec-nagual.com.
+alchemysoft.com.
+loading5.widdit.com.
+240.244.77.190.in-addr.arpa.
+platform.ak.fbcdn.net.
+search.mywebsearch.com.
+20.33.69.189.in-addr.arpa.
+27.200.93.186.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+ksn2-12.kaspersky-labs.com.
+www.tire-information-world.com.
+infomama.ru.
+profile.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+www.stopbadware.org.
+myhughesnet.com.
+usapears.ru.
+pitch.ru.
+www.estomaterapia.es.
+235.117.234.189.in-addr.arpa.
+connect.facebook.net.
+222.8.121.178.in-addr.arpa.
+img855.imageshack.us.
+shania-twain-wallpapers.blogspot.com.
+holaya.blogspot.com.
+www.wfp.org.
+www.hudakonhollywood.com.
+94.218.168.189.in-addr.arpa.
+starry.net.s7a1.psmtp.com.
+www.bywifi.com.
+47.138.55.182.in-addr.arpa.
+autolife116.ru.
+stats.televisadeportes.esmas.com.
+a7.sphotos.ak.fbcdn.net.
+64.54.56.200.in-addr.arpa.
+www.europa-ciezarowki.pl.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+53.16.16.200.in-addr.arpa.
+accor-mail.com.dob.sibl.support-intelligence.net.
+197.54.114.186.in-addr.arpa.
+postales-y-tarjetas.com.
+static-cdn.modernwar-game.com.
+es.wowhead.com.
+141.150.80.190.in-addr.arpa.
+googleads.g.doubleclick.net.
+utility1.software.informer.com.
+www.herongyang.com.
+172.240.81.93.in-addr.arpa.
+www.facebook.com.
+weblinkone.com.
+142.8.18.186.in-addr.arpa.
+mundogamers.com.
+sigs.symantec.com.
+178.99.55.74.in-addr.arpa.
+135.72.55.65.in-addr.arpa.
+pixel.facebook.com.
+kassnet.net.
+a1003.w41.akamai.net.
+photos-a.ak.fbcdn.net.
+google.com.
+a.root-servers.net.
+cruins.com.
+emark.rtl.de.
+segment-pixel.invitemedia.com.
+twbcompany.com.s7a1.psmtp.com.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+www.googletagservices.com.
+c1142172.cdn.cloudfiles.rackspacecloud.com.
+farm8.staticflickr.com.
+147.210.124.2.in-addr.arpa.
+profile.ak.fbcdn.net.
+spiralcom.co.uk.
+www.edoglovers.com.
+a1961.w7.akamai.net.
+www.autoline.tv.
+69620.ua.all.biz.
+csi.gstatic.com.
+156.247.100.81.in-addr.arpa.
+254.108.104.59.in-addr.arpa.
+automatedlogic.com.s7a2.psmtp.com.
+213.233.55.190.in-addr.arpa.
+96.213.89.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.flipdrive.com.
+www.bradleysalmanac.com.
+it.answers.com.
+www.ver-series-online.com.
+app.appatyze.com.
+dns.msftncsi.com.
+hotmail.com.
+a.root-servers.net.
+asset5.puatraining.com.
+pa.wordpress.com.
+a7.sphotos.ak.fbcdn.net.
+www.tecnosapiens.cl.
+87.105.9.186.in-addr.arpa.
+98.47.143.190.in-addr.arpa.
+a34.g.akamai.net.
+sp.cwfservice.net.
+api.twitter.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s-static.ak.fbcdn.net.
+pixel.facebook.com.
+www.mikextube.com.
+sassysarongs.com.
+photos-b.ak.fbcdn.net.
+aol.com.
+connect.facebook.net.
+a.root-servers.net.
+74.101.168.192.in-addr.arpa.
+lyrebirdradio.com.
+developers.facebook.com.
+twist45.wanadoo.co.uk.
+www.google.com.mx.
+www.decorationtricks.com.
+231.113.171.187.in-addr.arpa.
+9.13.254.17.in-addr.arpa.
+celebhairstyle.files.wordpress.com.
+31.30.168.187.in-addr.arpa.
+185.171.123.187.in-addr.arpa.
+smithnv.com.
+a.root-servers.net.
+www.avanza.se.
+s-static.ak.fbcdn.net.
+132.238.74.187.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+www.thebadrash.com.
+photos-a.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+u11.eset.com.
+gocpc.com.inbound10.mxlogic.net.
+api.twitter.com.
+228.216.139.190.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+static.chartbeat.com.
+38.147.220.66.in-addr.arpa.
+21.191.132.187.in-addr.arpa.
+cns.ru.
+gogastudios.com.
+cuartetos.org.
+nutramax.com.
+tc11.easythumbhost.com.
+tms30.icrc.trendmicro.com.
+accounts.google.com.
+223.87.160.201.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+mp3.es.
+suezsteel.com.
+dns.msftncsi.com.
+transloadamerica.net.s5a1.psmtp.com.
+go.microsoft.com.
+plus.google.com.
+gemmark.it.
+becausemusicismylife.blogspot.com.
+www.youtube-nocookie.com.
+curgos.galeon.com.
+bing.com.
+chiapas.olx.com.mx.
+creative.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+track.pubmatic.com.
+photos-b.ak.fbcdn.net.
+api.twitter.com.
+twitter.com.
+s.youtube.com.
+laricreazionenonaspetta.comunita.unita.it.
+gfx3.hotmail.com.
+a2.sphotos.ak.fbcdn.net.
+wazzy88.deviantart.com.
+api.geo.kontagent.net.
+browsefb.com.
+csi.gstatic.com.
+oppcos.com.s10a2.psmtp.com.
+www.youtube-nocookie.com.
+musicbestseller.com.
+219.47.165.189.in-addr.arpa.
+www.ircfast.com.
+lastchaos.softonic.fr.
+photos-d.ak.fbcdn.net.
+dns.msftncsi.com.
+apps.facebook.com.
+46.177.85.24.in-addr.arpa.
+www.eltiempo.com.
+www.cfr.ro.
+dl-ssl.google.com.
+131.95.163.71.zz.countries.nerd.dk.
+titanium30-en.url.trendmicro.com.
+www.solunet-infomex.com.
+static.ak.fbcdn.net.
+2.254.32.200.in-addr.arpa.
+133.241.52.186.in-addr.arpa.
+a.root-servers.net.
+s-static.ak.facebook.com.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+249.226.225.186.in-addr.arpa.
+ib.adnxs.com.
+s1-05.twitpicproxy.com.
+pagead2.googlesyndication.com.
+kocd4jfm1.x69t6f5f.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.cantur.com.
+profile.ak.fbcdn.net.
+122.54.54.85.in-addr.arpa.
+a.root-servers.net.
+apps.facebook.com.
+csi.gstatic.com.
+g.di0.org.
+www.google.com.
+gdrnylaw.com.
+ip1.dynupdate.no-ip.com.
+69.22.238.190.in-addr.arpa.
+www.google.com.
+diva-inc.com.
+s.ytimg.com.
+photos-b.ak.fbcdn.net.
+.
+twitter.com.
+mail.lss-corp.com.
+191.169.166.99.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+x1.mobileboner.com.
+a3.sphotos.ak.fbcdn.net.
+media.fastclick.net.
+1-a-pay.com.
+gropc.com.
+pc.vggen.com.
+navegandoporgrecia.blogspot.com.
+cdn-1.nflximg.com.
+gate2.finpar.ru.
+www.icc-cpi.int.
+safebrowsing.clients.google.com.
+p32d20cvjyi45c19nvd40avdtb18hva67iqbsar.org.
+www.amazon.es.
+oascentral.marklevinshow.com.
+35.40.221.190.in-addr.arpa.
+74.194.102.80.in-addr.arpa.
+www.tcscouriers.com.
+admin.brightcove.com.
+a3.sphotos.ak.fbcdn.net.
+a.xlink.xboxlive.com.
+veracitymanagementgroup.com.
+www.husky-owners.com.
+234.71.50.201.in-addr.arpa.
+review.tidebuy.com.
+www.rptcontentserver.com.
+mail.radio.ru.
+images.bomb-mp3.com.
+i.ytimg.com.
+657-async.olark.com.
+pohmtk.com.
+youtu.be.
+a.root-servers.net.
+232.65.52.186.in-addr.arpa.
+e4805.b.akamaiedge.net.
+telcel3g.wordpress.com.
+www.ela-salaty.com.
+a1294.w20.akamai.net.
+15.149.220.66.in-addr.arpa.
+254.250.192.187.in-addr.arpa.
+static.ak.fbcdn.net.
+www.bloggertipsandtricks.com.
+www.littlebigplanetarium.com.
+a153.phobos.apple.com.
+a.root-servers.net.
+242.252.105.95.in-addr.arpa.
+ieonlinews.microsoft.com.
+urs.microsoft.com.
+www.wtp101.com.
+www.googleapis.com.
+mail.cbici.net.
+sc2.rules.mailshell.net.
+a1725.l.akamai.net.
+180.156.68.87.in-addr.arpa.
+sp.cwfservice.net.
+a.root-servers.net.
+45.137.188.201.in-addr.arpa.
+_727_05_5.
+stlsports.org.
+ca.answers.yahoo.com.
+misandanzasporlavida.blogspot.com.
+api.conduit.com.
+ns.polikvart.ru.
+shop.xango.com.hk.
+udvgpbctq.q56x4w8i.
+img.youtube.com.
+117.255.242.201.in-addr.arpa.
+hassan-khan-solicitors.com.
+www.asev.org.
+116.95.168.192.in-addr.arpa.
+google.com.
+rca.com.
+1.88.158.187.in-addr.arpa.
+www.facebook.com.
+jdgtffhwysurnu.tw.
+tcr.tynt.com.
+b._dns-sd._udp.lan.
+images.speedbit.com.
+www.installingwoodfloors.com.
+pics.hi5.com.
+modedevoted.blogspot.com.
+59.30.75.190.in-addr.arpa.
+pixel.rubiconproject.net.akadns.net.
+p06-bookmarks.icloud.com.
+a4.sphotos.ak.fbcdn.net.
+t1.gstatic.com.
+248.60.198.190.in-addr.arpa.
+search.yahoo.com.
+r._dns-sd._udp.0.0.1.10.in-addr.arpa.
+a.root-servers.net.
+www.ssasychic.com.
+www.datarecovery.net.
+pagead2.googlesyndication.com.
+mail.raphaministries.com.
+freeqq2.qq.com.
+b._dns-sd._udp.lan.
+work-in-net.ru.
+adspaces.ero-advertising.com.
+dns.msftncsi.com.
+_550_41_5.
+54.192.177.78.in-addr.arpa.
+tpm.com.au.
+a.root-servers.net.
+www.derecho.com.
+apps.facebook.com.
+www.myviphealth.com.
+d3lvr7yuk4uaui.cloudfront.net.
+olysteel.com.
+h.live.com.
+macralace.com.
+stats.wartsila.net.
+zh-cn.facebook.com.
+elviasboutique.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+l.yimg.com.
+35.91.142.68.in-addr.arpa.
+garufa.com.
+instagr.am.
+www.rincondeljuego.net.
+pbid.iforex.com.
+ocsp.digicert.com.
+www.2joyourself.tv.
+aodinc.com.
+cnhmexico.com.mx.
+mail.absolutesoundinc.com.
+router.infolinks.com.
+irc.purchaseservice.com.
+100.248.92.186.in-addr.arpa.
+www.xtube.com.
+mail.metastar.com.
+a995.mm1.akamai.net.
+info.babylon.com.lan.
+98.190.11.190.in-addr.arpa.
+aol.com.
+swdpme4oh.a76v7b1o.
+mail.kjcomm.com.
+cecs.pdx.edu.
+0-68.channel.facebook.com.
+game.taobao.com.
+v9.nonxt5.c.pack.google.com.
+qhj3egwiz.06oe.
+www.shemaletubeclips.com.
+b-0.19-2304d408.80010c1.1518.19d4.3ea1.410.0.1dhr69rzugs8hlqbdeuv9fnjrv.avqs.mcafee.com.
+mercedesbenz.com.
+photos-d.ak.fbcdn.net.
+ha-ash.com.
+www.google.com.
+www.agoda.pl.
+www.justanswer.com.
+alerts.conduit-services.com.
+connect.facebook.net.
+dns.msftncsi.com.
+www.ice.it.
+thesourcecompanies.com.
+teredo.ipv6.microsoft.com.
+www.joey-silvera-shemales.com.
+ads.hotgirlsgames.net.
+bestimpressionsinc.net.
+www.nokiakiller.com.
+profile.ak.fbcdn.net.
+clients1.google.com.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+173.20.3.88.in-addr.arpa.
+www.experiencestmaarten.com.
+ejabat.google.com.
+www.google-analytics.com.
+www.facebook.com.
+volcanoseven.com.
+www.yahoo.com.
+www.juegosdebarbiebebe.com.
+www.megastock.com.
+245.43.213.189.in-addr.arpa.
+113.186.183.178.in-addr.arpa.
+www.alejandrodemiguel.com.
+www.askgamblers.com.
+112.221.152.189.in-addr.arpa.
+cache.netacad-cdn.net.
+wee.fadri.org.
+14.63.209.190.in-addr.arpa.
+a995.mm1.akamai.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+161.233.126.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+a-0.19-23088089.8060033.1518.19d4.3ea1.210.0.vt371gbcdzpj6jlp46w5q5wglb.avqs.mcafee.com.
+mail.aikenprinting.com.
+www.talanews.com.
+profile.ak.fbcdn.net.
+moodpoll.nfdaily.cn.
+crl.microsoft.com.
+www.microsoft.com.
+static.gulli.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+empoweredbirth.typepad.com.
+sjc-smtp1.sjc.dropbox.com.
+row.bc.yahoo.com.
+sites.google.com.
+v3.nonxt1.c.android.clients.google.com.
+plus.google.com.
+www.tripadvisor.com.my.
+www.facebook.com.
+www.facebook.com.
+www.hardhornyme.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+asspmvv.puntdoc.es.
+a5.sphotos.ak.fbcdn.net.
+56.230.178.190.in-addr.arpa.
+19.76.241.201.in-addr.arpa.
+www.breaktaker.com.
+ocsp.digicert.com.
+a8.sphotos.ak.fbcdn.net.
+www.lodgingbarcelona.com.
+brantly.com.
+pixel.facebook.com.
+www.ciasf2010.es.
+piraeusbank.gr.
+time.microsoft.akadns.net.
+dns.msftncsi.com.
+www.airrunnersystems.com.
+145.96.245.189.in-addr.arpa.
+adserv.comze.com.
+xmy.froo.com.
+subdere.gov.cl.
+www.adobe.com.
+www.fundacionamanecer.cl.
+dtboot.orbitdownloader.com.
+profile.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+ottu-da.ru.
+i3.ytimg.com.
+photos-g.ak.fbcdn.net.
+140.120.167.80.in-addr.arpa.
+a.root-servers.net.
+www.elpobladodeprince.com.
+a1907.g.akamai.net.
+a.root-servers.net.
+davidweikel.com.
+captcha.qq.com.
+13.203.192.71.in-addr.arpa.
+www.ebgames.com.au.
+photos-g.ak.fbcdn.net.
+bomberman.chulojuegos.com.
+11.111.166.201.in-addr.arpa.
+apis.google.com.
+6pix3ikxv.23mj.
+nsx.sec.np.dl.playstation.net.
+platform.ak.fbcdn.net.
+open-tracker.appspot.com.
+www.afuj.fr.
+198.250.9.190.in-addr.arpa.
+a.root-servers.net.
+creative.ak.fbcdn.net.
+cs12962.vkontakte.ru.
+quick-876346.com.
+a323.yahoofs.com.
+www.facebook.com.
+mx2.fidalgo.net.
+16.192.68.177.in-addr.arpa.
+gamestats.gamespy.com.
+s-static.ak.facebook.com.
+www.lovevalencia.com.
+www.rioave-fc.pt.
+oi681.photobucket.com.
+www.justinbiebermexico.com.
+sync.search.spotxchange.com.
+hardsalsa.com.
+www.cool-bites.com.
+memelodia.blogspot.com.
+158.199.161.189.in-addr.arpa.
+mailgate1.bdal.de.
+secure.nsta.org.
+zh-cn.facebook.com.
+mobilemaps.clients.google.com.
+s2.youtube.com.
+h0m-master.ru.
+api25.thetrafficstat.net.
+ax.init.itunes.apple.com.
+a-0.19-230f1041.9050081.1518.19d0.3ea1.410.0.vfprgn6rjkecblnk3rzsiqms7i.avqs.mcafee.com.
+xmadenx.files.wordpress.com.
+a.root-servers.net.
+hockey.cbssports.com.
+static.ak.fbcdn.net.
+p24.packet8.net.
+lissamonet.com.
+a1725.l.akamai.net.
+g.live.com.
+www.abc.es.
+www.foxnews.com.
+dns149.a.register.com.
+themes.googleusercontent.com.
+gmlive.narod.ru.
+73y5662up.86ot.
+fullrangedriver.com.
+assets00.grou.ps.
+cmcelectronics.com.
+27.222.192.187.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+a2.ec-images.myspacecdn.com.
+11.80.104.186.in-addr.arpa.
+www.youtube.com.
+snake.cc.ncu.edu.tw.
+www.cuevana.tv.
+cbflouhouse.com.
+api.twitter.com.
+comtelsystem.com.
+wirelessnotebook.com.
+60.11.6.24.in-addr.arpa.
+storage.conduit.com.
+blog.rainbowhill.com.au.
+plus.google.com.
+sherland.ru.
+bandstores.co.uk.
+st2.xxxkinky.com.
+www.benedictinescat.com.
+mail.centurytel.net.
+a7.sphotos.ak.fbcdn.net.
+iistbrai1.t98a4n7p.
+photos-f.ak.fbcdn.net.
+juegos7.juegosdiarios.com.
+teredo.ipv6.microsoft.com.
+www.mtv.co.uk.
+www.bodyfitcheck.com.au.
+www.mascus.co.za.
+ads.adxpansion.com.
+lasvarinet.com.ar.
+apps.facebook.com.
+206.190.235.189.in-addr.arpa.
+78.129.52.186.in-addr.arpa.
+hex.namehub.com.
+22-courier.push.apple.com.
+metrics.blackberry.com.
+tracking.usage.app.conduit-services.com.
+zynga1-a.akamaihd.net.
+email.xmradio.com.
+179.203.96.190.in-addr.arpa.
+www.nanking-massacre.com.
+rewfkg0ret876.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+walmart.ugc.bazaarvoice.com.
+www.thejohnreport.net.
+de-freshmilk.cdn.videoplaza.tv.
+photos-g.ak.fbcdn.net.
+33.143.209.77.in-addr.arpa.
+google.com.
+blogs.desitara.com.
+11.185.153.189.in-addr.arpa.
+s-static.ak.facebook.com.
+pagead2.googlesyndication.com.
+www.adam4adamlive.com.
+asiandvdclub.org.
+i.lumosity.com.
+132.207.225.190.in-addr.arpa.
+blog.apps.su.
+mipagina.esmas.com.
+49.219.27.46.in-addr.arpa.
+wmost.com.
+dx3723.tinyurl.com.
+static.ak.facebook.com.
+static.ak.fbcdn.net.
+www.winksfun.com.
+dark-wraith.com.
+login.live.com.
+9.94.161.187.in-addr.arpa.
+static.ak.fbcdn.net.
+login.yahoo.com.
+csi.gstatic.com.
+toolbarqueries.google.com.mx.
+ad.turn.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+116.185.2.123.in-addr.arpa.
+svrsecure-g2-crl.verisign.com.
+www.sigoconana.blogspot.com.
+879.coll.ning.com.
+mobile.twitter.com.
+www.cuantarazon.com.
+l16.member.kr3.yahoo.com.
+mail.packup.ru.
+xml.truveo.com.
+apis.google.com.
+mail.ccalawcorp.com.
+mail.qm-company.com.
+129.13.58.189.in-addr.arpa.
+csi.gstatic.com.
+v7.cache3.c.youtube.com.
+www.salud.df.gob.mx.
+cdn1.iofferphoto.com.
+jmu.edu.
+dns.msftncsi.com.
+images1-focus-opensocial.googleusercontent.com.
+toolbarqueries.google.com.mx.
+a5.sphotos.ak.fbcdn.net.
+kaltura.com.
+lb._dns-sd._udp.lan.
+www.google.com.
+edsal.com.
+www.centroexcursionista.org.
+static.ak.facebook.com.
+apps.teamlava.com.
+www.lebnights.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+bj.bbs.house.sina.com.cn.
+alt1.aspmx.l.google.com.
+5.134.45.190.in-addr.arpa.
+www.facebook.com.
+101.43.73.94.in-addr.arpa.
+45.181.63.69.in-addr.arpa.
+carnby.altervista.org.
+25.83.0.88.in-addr.arpa.
+134.192.56.186.in-addr.arpa.
+banners.wunderground.com.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+simonds.ru.
+sn1msg2010523.gateway.messenger.live.com.
+picgalleries.hotshemalesluts.com.
+id.google.com.
+apis.google.com.
+gan.wikipedia.org.
+recabrones.com.
+249.99.34.186.in-addr.arpa.
+52.151.221.189.in-addr.arpa.
+www.mediafire.com.
+195.12.188.186.in-addr.arpa.
+pda-bes.amazon.com.
+sro.whatsapp.net.
+30.7.22.187.in-addr.arpa.
+downloadgraphy.blogspot.com.
+ksn2-12.kaspersky-labs.com.
+163.165.194.180.in-addr.arpa.
+id.google.com.mx.
+millersofclaflin.com.
+an-penza.ru.
+6.254.189.190.in-addr.arpa.
+_826_89_5.
+inbound.nightline-inc.com.netsolmail.net.
+jovenescritora.metroblog.com.
+235.63.70.187.in-addr.arpa.
+20.26.108.27.in-addr.arpa.
+154.93.27.201.in-addr.arpa.
+support.google.com.
+246.36.78.201.in-addr.arpa.
+27925x2ti.75je.
+pixel.facebook.com.
+ninjaui.com.
+46.183.36.184.in-addr.arpa.
+pctelecom.com.
+twitter.com.
+fbcdn-photos-a.akamaihd.net.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+waittime.tsa.dhs.gov.
+eightyonedays.com.
+check4.facebook.com.
+valuta.se.
+a1.sphotos.ak.fbcdn.net.
+www.facebook.com.
+smtp.hot.glbdns.microsoft.com.
+www.lamonomagazine.com.
+ocsp.digicert.com.
+tgmedsystem.com.
+dns.msftncsi.com.
+www.mypinktasticlife.com.
+seodoktor.ru.
+b.scorecardresearch.com.
+www.cia.gov.
+248.103.68.201.in-addr.arpa.
+berkshiresgi.com.
+gibbonlaw-com.mail.eo.outlook.com.
+ksn2-12.kaspersky-labs.com.
+0-131.channel.facebook.com.
+mx2.wellsfargo.com.
+www.perunatural.com.
+autofotoexpress.com.
+michaelgerald.com.mail6.psmtp.com.
+137.52.137.85.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.geoturismoenbosquesdecafe.com.
+32.107.244.189.in-addr.arpa.
+fotografiainfo.ru.
+www.just-think-it.com.
+a3.sphotos.ak.fbcdn.net.
+235.105.250.190.in-addr.arpa.
+a.root-servers.net.
+jerryseinfeld.com.
+c-ak.static-rootmusic.com.
+averapharm.com.
+s-static.ak.fbcdn.net.
+animationprogression.blogspot.com.
+gallery.chantasbitches.com.
+p01-keyvalueservice.icloud.com.
+shoe-apparel.en.alibaba.com.
+a.prisacom.com.
+mareterra.com.br.
+b91.yahoo.co.jp.
+justinsky.de.
+developers.facebook.com.
+bransonultrasonics.com.
+a.root-servers.net.
+www.isg-apple.com.akadns.net.
+static.ak.fbcdn.net.
+shop.capcom.com.
+242.178.195.187.in-addr.arpa.
+res2.windows.microsoft.com.
+pixel.quantserve.com.
+www.sinograver.com.
+scottforesman.com.mail7.psmtp.com.
+profile.ak.fbcdn.net.
+client.akamai.com.
+sporthotel.ru.
+d3lvr7yuk4uaui.cloudfront.net.
+www.xfire.com.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+103.54.187.189.in-addr.arpa.
+a.root-servers.net.
+ad.doubleclick.net.
+cdn.kgyounginternet.com.c.footprint.net.
+vassilipuskas.com.
+dns.msftncsi.com.
+www.freeland.org.
+212.126.24.125.in-addr.arpa.
+99.42.105.71.in-addr.arpa.
+www.ancestry.myfamily.com.
+a763.phobos.apple.com.
+imgg.ru.
+roshen.com.ua.
+149.121.59.186.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+www.nicocig.co.uk.
+www.alaic.net.
+auracom.net.s6b1.psmtp.com.
+31.193.226.190.in-addr.arpa.
+a.root-servers.net.
+sgistuff.g-lenerz.de.
+16.246.175.187.in-addr.arpa.
+0-327.channel.facebook.com.
+jk87369ai.32qi.
+mail.orelholodmash.ru.
+mailinator2.com.
+c13.zedo.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+182.109.93.186.in-addr.arpa.
+c.trendpost.net.
+www.universia.com.ec.
+www.googleadservices.com.
+platform.twitter.com.
+itunes.apple.com.
+assets.macys.com.
+_795_67_9.
+labelall.com.
+liveupdate.symantecliveupdate.com.
+rockwell-solutions.com.
+smtp.urbas.net.
+static.ak.fbcdn.net.
+119.205.201.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+102.123.217.87.in-addr.arpa.
+img365.rockyou.com.
+img.youtube.com.
+0.191071.com.
+wcandw.com.
+s.ytimg.com.
+2.108.223.24.in-addr.arpa.
+otnusa.net.
+funcage.com.
+rupromo.ru.
+a.root-servers.net.
+www.museomigraciones.org.uy.
+www.facebook.com.
+berlee.net.
+www.facebook.com.
+jetmessenger.com.
+g.promosrv.com.
+209.210.211.76.in-addr.arpa.
+184.175.25.98.in-addr.arpa.
+www.myngle.com.
+tuug.net.ru.
+22.149.220.66.in-addr.arpa.
+www.facebook.com.
+igskins.googlecode.com.
+movies.netflix.com.
+www.awltovhc.com.
+mail.sfgiants.com.
+imagenen1.247realmedia.com.
+70.195.37.93.in-addr.arpa.
+165.132.37.190.in-addr.arpa.
+_823_08_2.
+mywebsiteadvisor.com.
+19.166.165.58.in-addr.arpa.
+naletu.ru.
+external.ak.fbcdn.net.
+0-244.channel.facebook.com.
+41.25.122.186.in-addr.arpa.
+cam-in-style.programas-gratis.net.
+eur.tlc-world.ru.
+a5.sphotos.ak.fbcdn.net.
+hydrokamaz.ru.
+globalwealthtrade.com.s8b2.psmtp.com.
+109.211.209.190.in-addr.arpa.
+a.root-servers.net.
+modelsilike.blogspot.com.
+hdp.zapto.org.
+229.149.59.187.in-addr.arpa.
+mircosoft.com.
+coco.metrogames.com.
+drakecooper.com.s9b2.psmtp.com.
+www.facebook.com.
+ngjmjdqhy.68nq.
+creative.ak.fbcdn.net.
+connect.facebook.net.
+aviakb.ru.
+gardiner-richardson.com.s200a2.psmtp.com.
+marketdoctors.com.
+a.root-servers.net.
+www.amazon.com.
+tulipanchile.com.
+cdn.filebulldog.com.
+bt1.btally.net.
+query.yahooapis.com.
+ads1.msads.net.
+web-zc1.cityville.zynga.com.
+yourfriendlymortgage.com.
+groups.google.com.mx.
+i1.ytimg.com.
+www.boddit.com.
+99.140.49.82.in-addr.arpa.
+www.facebook.com.
+mscrl.microsoft.com.
+172.15.32.186.in-addr.arpa.
+quevedo.mundoanuncio.ec.
+data.wa.marketingsolutions.yahoo.com.
+hotmail.com.
+www.cptm.com.mx.
+subs.hh-pub.com.
+bbsyd.dk.
+137.233.104.189.in-addr.arpa.
+24.139.131.190.in-addr.arpa.
+a.root-servers.net.
+www.youtube.com.
+www.idconline.com.mx.
+do.lysd.k12.ak.us.
+175.17.168.192.in-addr.arpa.
+nj.buric.com.
+dns.msftncsi.com.
+a1.twimg.com.
+gtu-ins.com.m4.mx-route.com.
+shasta-rrs.symantec.com.
+zvert.fcien.edu.uy.
+253.75.12.50.in-addr.arpa.
+da.wikipedia.org.
+b3mu3vqzc.j78m3i1x.
+www.google.com.
+alerts.conduit-services.com.
+a.root-servers.net.
+115.229.34.187.in-addr.arpa.
+decollage.nl.
+rad.msn.com.
+xquisiteonline.com.
+it.wikipedia.org.
+www.youtube.com.
+relay.ufanet.ru.
+24.123.219.190.in-addr.arpa.
+byfiles.storage.msn.com.
+www.thewarofthemutans.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.wardlestoreys.com.
+www.apqc.org.
+252.144.130.82.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+sljkllchl.12tr.
+xxxxxkronosxxxxx.blogspot.com.
+www.museopicassomalaga.org.
+inbound.luigisbakery.com.netsolmail.net.
+sites.google.com.
+fbcdn-profile-a.akamaihd.net.
+pix04.revsci.net.
+profile.ak.fbcdn.net.
+dragraceronline.net.
+152.227.76.151.in-addr.arpa.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+mail.cwo.com.
+109.173.148.46.in-addr.arpa.
+s1-excel.vo.msecnd.net.
+assets.cellphonebeat.com.
+linksynergy.overstock.com.
+jers2.info.
+spb.ltg.ru.home.
+photos-g.ak.fbcdn.net.
+ciscom.ru.home.
+dmcvw8a7s.l62m0b7k.
+a.root-servers.net.
+loansonly.com.
+doctor-muller.ru.
+ads1.msads.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+usa.acciontrabajo.com.
+www.missbellabellini.com.
+a3.sphotos.ak.fbcdn.net.
+s-static.ak.facebook.com.
+www.aitracing.com.
+cdn4b.youjizz.com.
+makavibe.ru.
+sync.mathtag.com.
+18.40.31.190.in-addr.arpa.
+elbarullodelolimpo.blogspot.com.
+google.com.
+0-161.channel.facebook.com.
+anboto.boj.org.
+m259.photobucket.com.
+mail.
+m6buels96.33sf.
+158.215.171.189.in-addr.arpa.
+thegoodtimber.com.
+s-static.ak.fbcdn.net.
+ifood.tv.
+ajax.googleapis.com.
+ipod-iphone.ru.
+xsltcache.alexa.com.
+t-one.net.
+a.root-servers.net.
+photos-f.ak.fbcdn.net.
+d1j68ux4ukg4g1.cloudfront.net.
+webres2.pand.ctmail.com.
+186.89.23.190.in-addr.arpa.
+avanta-group.ru.
+www.ourexplorer.com.
+sayedmokhtar.maktoobblog.com.
+139.103.215.118.in-addr.arpa.
+ad-g.doubleclick.net.
+rickyost.com.
+programmkalender.daserste.de.
+25.237.116.177.in-addr.arpa.
+login.toolbar.conduit-services.com.
+145.168.168.192.in-addr.arpa.
+t3.gstatic.com.
+developers.facebook.com.
+pixel.facebook.com.
+www.paraguaycoins.com.
+ic.tynt.com.
+ad-g.doubleclick.net.
+d1uysd8m4iv3h8.cloudfront.net.
+cdn.api.twitter.com.
+www.yahoo.com.
+www.video-lyrics.com.
+179.190.249.111.in-addr.arpa.
+www.upd.edu.mx.
+www.telmore.dk.
+im11.gulfup.com.
+allourfingersinthepie.blogspot.com.
+aimhigh.net.inbound10.mxlogicmx.net.
+api.conduit.com.
+145.65.92.201.in-addr.arpa.
+www.riffygit.com.
+www.cartoonnetwork.com.
+134.123.75.208.sbl-xbl.spamhaus.org.
+62.2.10.10.in-addr.arpa.
+www.souplantation.com.
+pixel.facebook.com.
+configure-cdn.us.dell.com.
+www.sektioneins.de.
+ns1v6.aketzu.net.
+a1.sphotos.ak.fbcdn.net.
+bzz.is.
+vanetaitao.blogspot.com.
+hlabs.spb.ru.
+www.facebook.com.
+36.135.189.195.in-addr.arpa.
+armmf.adobe.com.
+chacalx.blogspot.com.
+acpc.com.
+homedecorconcept.com.
+time.chttl.com.tw.
+www.dydacomp.com.
+goldenoak.org.mx1.realtimefilters.rcimx.net.
+ads.rambomedia.com.
+www.benwhite.com.
+a7.sphotos.ak.fbcdn.net.
+trade.bokecc.com.
+armmf.adobe.com.
+b._dns-sd._udp.lan.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ocsp.verisign.com.
+cdn01.oovoo.com.
+blogspot.l.google.com.
+www.chinaknowledge.com.
+pixel.facebook.com.
+24.251.223.186.in-addr.arpa.
+cbj-s-03025.africa-me.shell.com.
+68.124.59.186.in-addr.arpa.
+bks7.books.google.com.mx.
+146.69.112.190.in-addr.arpa.
+.
+imap.gmail.com.
+pt-br.facebook.com.
+ratings-wrs.symantec.com.
+209.72.235.68.in-addr.arpa.
+askwaltstollmd.com.
+244.219.229.201.in-addr.arpa.
+mail.welovethemtoo.com.
+120.188.25.108.in-addr.arpa.
+smtp.promflex.ru.
+secondlife.com.
+www.oyunkolay.com.
+siymca.org.
+cancionfrancesaenlos50y60.blogspot.com.
+it-it.facebook.com.
+www.l.google.com.
+lh3.googleusercontent.com.
+mail.diamond-edge.co.uk.
+barmatin.ru.
+fastcomm.ru.
+apps.facebook.com.
+18.48.55.74.in-addr.arpa.
+accounts.google.com.
+photos-b.ak.fbcdn.net.
+apoyo.expotodoparatustand.com.
+a2.sphotos.ak.fbcdn.net.
+hotelasia.com.tw.
+photos-f.ak.fbcdn.net.
+a1007.w43.akamai.net.
+static.ak.fbcdn.net.
+www.twitch.tv.
+www.blogcdn.com.
+updatekeepalive.mcafee.com.
+www.patrimoniosf.gov.ar.
+www.juntosporlaninez.com.
+de-de.facebook.com.
+a.root-servers.net.
+hvc.rr.com.
+external.ak.fbcdn.net.
+a.root-servers.net.
+www.freeworldgroup.com.
+toolbar.zynga.com.
+rs5.scribd.com.
+naryxpharma.com.
+rusremol.ru.
+www.jewelrymaking-beads-library.com.
+u.goal.com.
+www.facebook.com.
+mobinfo.ru.
+gifhorn.de.
+i3.ytimg.com.
+technorati.com.
+lh4.ggpht.com.
+somethinglikethis.net.
+allisfighter.com.
+a-0.19-23095281.c090083.1518.19d4.3ea1.210.0.4er73s9p55296jrntlrqiff28i.avqs.mcafee.com.
+m.hotmail.com.
+ocmyfvcty.d46y9e4l.
+www.tobaccolabels.ca.
+109.38.229.190.in-addr.arpa.
+mail.opelcar.ru.
+groups.google.com.
+carlos-arano.com.ar.
+129.40.233.201.in-addr.arpa.
+64.42.101.78.in-addr.arpa.
+dynamicads.g.doubleclick.net.
+photos-c.ak.fbcdn.net.
+www.google-analytics.com.
+www.umusicpub.com.
+sbcmx8.prodigy.net.
+img830.imageshack.us.
+adfarm.mediaplex.com.
+um14.eset.com.
+www.plusnetwork.com.
+googleads.g.doubleclick.net.
+yahoo.co.uk.
+ecx.images-amazon.com.
+blog.tirerack.com.
+i2.ytimg.com.
+brentwoodcorp.com.inbound30.mxlogic.net.
+google.com.
+fla.sinfindejuegos.com.
+rad.msn.com.
+www.spacepimping.com.
+www.taylormadegolf.cn.
+9selsop1h.71aq.
+uef.com.gt.
+www.facebook.com.
+static.ak.fbcdn.net.
+www.facebook.com.
+www.convertbinary.com.
+www.geeks.co.uk.
+fe.brandreachsys.com.
+a-0.19-a30f9081.c020081.1518.19d4.3ea1.210.0.qv4hsj5k25kw6keh54n91tkpqi.avqs.mcafee.com.
+109.87.54.65.in-addr.arpa.
+d2089760.xoom.it.
+www.facebook.com.
+a.root-servers.net.
+oajuvpeoiq.info.mshome.net.
+gj:zgkihg.v85a0m1p.
+12.59.193.186.in-addr.arpa.
+www2.animalsexfilms.nl.
+a.root-servers.net.
+files.video-loader.com.
+182.62.20.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.hampton.com.
+mili.im.
+ocsp.verisign.com.
+www.google-analytics.com.
+13409hotgogling.cn.
+www.facebook.com.
+profile.ak.fbcdn.net.
+mcm5.navy.mil.
+a.root-servers.net.
+69.238.254.188.in-addr.arpa.
+27.43.174.190.in-addr.arpa.
+geo.tp-cdn.com.
+www.siamfishingtours.com.
+www.parkinn.com.
+evsecure-ocsp.verisign.com.
+a.root-servers.net.
+creative.ak.fbcdn.net.
+wmr.ru.
+id.google.com.mx.
+vevideo.com.es.
+api.twitter.com.
+basicinstructions.net.
+tap2-cdn.rubiconproject.com.
+a.root-servers.net.
+10.1.168.192.in-addr.arpa.
+www.randrmagonline.com.
+157.234.28.95.in-addr.arpa.
+r.mzstatic.com.
+206.6.146.186.in-addr.arpa.
+argentinarrhh.blogspot.com.
+es-la.facebook.com.
+profile.ak.fbcdn.net.
+76live.com.
+agglo-nice.fr.
+external.ak.fbcdn.net.
+169.47.49.190.in-addr.arpa.
+pixel.facebook.com.
+creative.ak.fbcdn.net.
+_688_54_7.
+thereps.com.
+dc446.4shared.com.
+ssl.isg-apple.com.akadns.net.
+tboextra.com.
+daviskane.com.
+freemailng0406.web.de.
+108.114.133.217.in-addr.arpa.
+www.facebook.com.
+www.ingdirect.com.au.
+sp.cwfservice.net.
+www.weaverleather.com.
+goldensunwiki.net.
+a.root-servers.net.
+dl.google.com.
+hsnacpas.com.
+apps.facebook.com.
+tecnofull.com.
+bullz-eye.us.intellitxt.com.
+40.204.88.200.in-addr.arpa.
+dns.msftncsi.com.
+focuspg.com.s7b2.psmtp.com.
+google.com.
+segment-pixel.invitemedia.com.
+global-hunters.com.
+aseeva.ru.
+update.avg.com.
+apps.facebook.com.
+www.capes.gov.br.
+a1007.w43.akamai.net.
+178.160.255.190.in-addr.arpa.
+a2.kiev.ua.
+www.facebook.com.
+240.94.154.189.in-addr.arpa.
+a-0.19-2209a081.d060083.1518.19d2.3ea1.410.0.spqabajtl54hfqk97s33alujnv.avqs.mcafee.com.
+developers.facebook.com.
+www.talktom.
+blst.msn.com.
+photos-f.ak.fbcdn.net.
+plus.google.com.
+video.mx.msn.com.
+smtp.ins.dell.com.
+www.marcha.org.ar.
+a.root-servers.net.
+photos-e.ak.fbcdn.net.
+97.251.209.190.in-addr.arpa.
+www.idealmature.com.
+shared.live.com.
+a8.sphotos.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+view.atdmt.com.
+macrojuegos.juegosipo.com.
+www.linkedin.com.
+smtp.sub.net.au.
+www.sendspace.com.
+a2.sphotos.ak.fbcdn.net.
+images.apple.com.
+blogsochi.ru.
+creative.ak.fbcdn.net.
+mail.robotcombat.com.
+www.arkiva-shqip.com.
+proforg.com.
+_544_70_3.
+ads2.greystripe.com.
+147.20.127.115.in-addr.arpa.
+tags.expo9.exponential.com.
+alona.ru.
+mail.yimg.com.
+dc05.arabsh.com.
+81.154.213.201.in-addr.arpa.
+shapeways.com.
+42.183.138.189.in-addr.arpa.
+ksn1-11-part1.kaspersky-labs.com.
+safebrowsing-cache.google.com.
+pjduy2op7.53cq.
+finnishcharts.com.
+processor.netmgt.com.
+mail1.theron.com.
+a.root-servers.net.
+moscaphoto.com.
+crl3.digicert.com.
+m4v.tvolucion.com.
+loading.retry.widdit.com.
+s-static.ak.facebook.com.
+peas.compunass.org.
+72.202.205.112.in-addr.arpa.
+www.campuspdi.org.
+gorenje.si.
+i.ytimg.com.
+a-0.19-a30f8081.590.1518.19d4.3ea1.410.0.qfgwvgqafksp12wiunftlpnec5.avqs.mcafee.com.
+huertadelosrobles.wordpress.com.
+60.2.1.181.in-addr.arpa.
+250.131.235.201.in-addr.arpa.
+188.76.52.186.in-addr.arpa.
+a0.twimg.com.
+www.google.com.
+0.169.38.99.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+a4.sphotos.ak.fbcdn.net.
+dlarray-europ-ieupdate065.gdatasecurity.de.
+adventuregames.ht83.com.
+a6.sphotos.ak.fbcdn.net.
+fghgfhdhdg.blogspot.com.
+profile.ak.fbcdn.net.
+www.liali.net.
+www.spilgames.com.
+crl.microsoft.com.
+a.root-servers.net.
+128.168.122.186.in-addr.arpa.
+pagead2.googlesyndication.com.
+www.google.com.
+cuteskipbbthemes.blogspot.com.
+www.download.windowsupdate.com.
+it-it.facebook.com.
+.
+35.10.10.10.in-addr.arpa.
+42-courier.push.apple.com.
+mygnulinux.blogspot.com.
+www.google.com.
+132.245.190.81.in-addr.arpa.
+whpwireless.com.
+58.136.149.186.in-addr.arpa.
+portageco.com.
+homtial.com.
+twitter.com.
+www.wiroos.com.
+vlex.com.mx.
+1.189.137.201.in-addr.arpa.
+a.root-servers.net.
+mail.lovers.ru.
+www.gelifesciences.com.
+169.11.208.201.in-addr.arpa.
+ntl.fr.
+www.facebook.com.
+rs243l32.rapidshare.com.
+www.cbs.com.
+2.230.100.190.in-addr.arpa.
+www.medscape.com.
+geo.messenger.services.live.com.
+aka-cdn-ns.adtech.de.
+utils.babylon.com.
+a.root-servers.net.
+42.131.134.187.in-addr.arpa.
+videos.javahd.com.
+o-style.net.
+universalflooring.com.
+photos-a.ak.fbcdn.net.
+www.google.com.
+themes.googleusercontent.com.
+img.youtube.com.
+121.190.55.187.in-addr.arpa.
+57.206.55.189.in-addr.arpa.
+55.226.172.201.in-addr.arpa.
+171.211.10.85.in-addr.arpa.
+reddragonkungfu.com.
+www.sjwxzy.com.
+meria.net.
+www.patrickholford.com.
+a.root-servers.net.
+dns.msftncsi.com.
+152.26.161.201.in-addr.arpa.
+creativecommons.org.
+facebook.com.
+112.202.13.187.in-addr.arpa.
+api.facebook.com.
+lb._dns-sd._udp.lan.
+babycenter.ru.
+www.googil.com.
+238.130.168.192.in-addr.arpa.
+pfs.mozilla.org.
+b.scorecardresearch.com.
+ntp1.dlink.com.
+www.samsung.net.
+227.200.165.78.in-addr.arpa.
+r-data.adsrvr.org.
+_978_24_5.
+creative.ak.fbcdn.net.
+www.hao123.com.
+0.11-a307c089.e1032.1518.19d4.3ea1.410.0.j2rbre8jqblv9cw1kbbr2v6dm6.avqs.mcafee.com.
+kupiknigu.ru.
+www.angelacusumano.com.
+252.129.62.186.in-addr.arpa.
+click.allegiantdeals.com.
+www.adoretube.com.
+apps.facebook.com.
+resourcemedia.tv.
+www.bing.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+233.170.113.190.in-addr.arpa.
+163.38.63.200.in-addr.arpa.
+tobolsk.info.
+yahoo.com.
+usersystem783aa.ru.
+mail2.us.silhouette.com.
+kisales.com.
+rospres.com.
+creative.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+mail.lanaken.be.
+a.root-servers.net.
+a.root-servers.net.
+js.wlxrs.com.
+clients-cctld.l.google.com.
+tap2-cdn.rubiconproject.com.
+thailandlife.com.
+www.ebay.es.
+b.matrixsynth.com.
+www.google-analytics.com.
+osu.ru.
+l.yimg.com.
+cs272.vk.com.
+blog.twoo.com.
+203.110.214.186.in-addr.arpa.
+www.objectlabs.net.
+www.ebay.es.
+www.mytinyworld.co.uk.
+mx-2.superig.com.br.
+www.psiquiatraperu.net.
+games.yahoo.com.
+165.226.175.85.in-addr.arpa.
+profile.ak.fbcdn.net.
+87.148.59.199.in-addr.arpa.
+rock-com-mx.messaging.lotuslive.com.
+ville-bondy.fr.
+connect.facebook.net.
+s.youtube.com.
+4.116.26.201.in-addr.arpa.
+mail.
+amx.wimbledonwine.com.redcondor.net.
+manuel.sesamath.net.
+static.ak.fbcdn.net.
+144.96.186.93.in-addr.arpa.
+www.miscomentariosparahi5.com.
+alluretech.net.
+es.altavista.com.
+160.4.23.1.in-addr.arpa.
+yingwenlaoshi.files.wordpress.com.
+a7.sphotos.ak.fbcdn.net.
+www.facebook.com.
+a997.mm1.akamai.net.
+uza.s523ll5pu6s1.com.
+crl.microsoft.com.
+us.bc.yahoo.com.
+www.arkdiscovery.com.
+56.44.156.187.in-addr.arpa.
+ad.doubleclick.net.
+178.119.92.200.in-addr.arpa.
+nou-energetik.ru.
+mail.audiolot.com.
+75.140.22.96.in-addr.arpa.
+www.anewshit.com.
+profile.ak.fbcdn.net.
+hornmurdockcolesv.com.
+mediacenter.fedex.designcdt.com.
+citlink.ne.
+219.87.214.189.in-addr.arpa.
+www.youtube.com.
+57.25.53.186.in-addr.arpa.
+mailscan.hpcdsb.edu.on.ca.
+kmail.xanterra.com.
+billing.sharo4ka.ru.
+a2.twimg.com.
+seattlewireless.net.
+www.elgourmetonline.com.
+smtp.3web.com.
+80.193.93.186.in-addr.arpa.
+_268_50_2.
+94.89.168.192.in-addr.arpa.
+chromejs.s3.amazonaws.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+www.zodchiy.ru.
+uncmervenf.net.
+irrationalgames.com.
+a3.sphotos.ak.fbcdn.net.
+fsbbank.net.
+shared.live.com.
+www.gouwu265.com.
+implantedental1.wordpress.com.
+photos-b.ak.fbcdn.net.
+imap.gmail.com.
+multiply.multiply.com.
+a.root-servers.net.
+www.4nursingmanagers.com.
+244.16.26.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+.
+icb.uni-due.de.
+www.facebook.com.
+apple-mobile.query.yahooapis.com.
+149.135.117.79.in-addr.arpa.
+gfx5.hotmail.com.
+col.stb01.s-msn.com.
+insuramericapr.com.
+translate.google.com.mx.
+dc407.4shared.com.
+gm.fb.telaxo.com.
+www.hifx.co.uk.
+photos-h.ak.fbcdn.net.
+100.199.130.186.in-addr.arpa.
+zonanet.com.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+www.googleadservices.com.
+metagaming.co.uk.
+www.adoperator.com.
+plusone.google.com.
+racingplay.com.
+cf.addthis.com.
+stewie.wojas.nl.
+1omni.com.
+developers.facebook.com.
+www.m5zn.com.
+tv5i2f3bk.l99x6c1y.
+games.tvclip.biz.
+201.234.255.206.in-addr.arpa.
+eldiariodeunpoeta.blogspot.com.
+mail.catholic-dispatch.com.
+pixer.meaningtool.com.
+www.789son.com.
+a2.sphotos.ak.fbcdn.net.
+img851.imageshack.us.
+developers.facebook.com.
+b._dns-sd._udp.0.1.0.10.in-addr.arpa.
+a.root-servers.net.
+130.113.12.189.in-addr.arpa.
+27.25.27.190.in-addr.arpa.
+75.191.76.77.in-addr.arpa.
+sdelanovkitae.ru.
+it-it.facebook.com.
+ad.adnetwork.net.
+227.252.5.189.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+ssl.gstatic.com.
+www.tripadvisor.com.ar.
+luckywire.com.
+103.108.75.65.in-addr.arpa.
+232.228.227.76.in-addr.arpa.
+195.148.173.201.in-addr.arpa.
+static.ak.fbcdn.net.
+express10k.com.
+sp.cwfservice.net.
+photos-e.ak.fbcdn.net.
+al-shorfa.com.
+p0b.ru.
+teredo.ipv6.microsoft.com.
+huschoice.com.
+81.145.101.187.in-addr.arpa.
+a.rad.msn.com.
+canyonlakefun.com.
+www.heiferperu.org.
+static.ak.fbcdn.net.
+s.ytimg.com.
+www.freewebs.com.
+a6.sphotos.ak.fbcdn.net.
+encuesta.appinformatica.com.
+www.wall-maps.com.
+oascentral.yellowpages.com.
+warpdriveonline.com.
+linkhelp.clients.google.com.
+gl.wikipedia.org.
+ml1dc2.mfxservices.com.
+www.tripadvisor.com.
+glb1.rim.net.
+_370_54_5.
+239.131.131.41.in-addr.arpa.
+www.deal4loans.com.
+photos-f.ak.fbcdn.net.
+mx031.parking.ru.
+o-caso.blogspot.com.
+cs1716.vkontakte.ru.
+48.158.177.190.in-addr.arpa.
+safebrowsing.clients.google.com.
+.
+external.ak.fbcdn.net.
+clkads.com.
+www.googletagservices.com.
+static.ak.fbcdn.net.
+185.15.142.190.in-addr.arpa.
+t.co.
+www.youtube.com.
+220.117.223.87.in-addr.arpa.
+www.apple.com.
+faxcom.com.
+ssl.gstatic.com.
+giltgroup.tt.omtrdc.net.
+img1.blogblog.com.
+vbg.com.
+echo.edge.messenger.live.com.
+11.189.78.190.in-addr.arpa.
+mygames4girls.com.
+1804289383.localhost.
+s-static.ak.fbcdn.net.
+bar-navig.yandex.ru.
+static.ak.fbcdn.net.
+view.atdmt.com.
+a2.sphotos.ak.fbcdn.net.
+www.fundaciontelevisa.org.
+krauss.faculty.asu.edu.
+109.92.217.98.in-addr.arpa.
+mx01.altep.com.
+d3lvr7yuk4uaui.cloudfront.net.
+holmesmark.com.
+kof.net.
+a.root-servers.net.
+beocwjdrcmkagjvd.ac.
+i2.ytimg.com.
+125.220.9.186.in-addr.arpa.
+a.root-servers.net.
+time.windows.com.
+facemoods.com.
+spbmesi.ru.
+orcart.facebook.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+time.nist.gov.
+mycam.nl.softonic.com.
+mx2.wwecorp.com.gslb.pphosted.com.
+developers.facebook.com.
+translate.google.com.mx.
+static.ak.fbcdn.net.
+131.149.254.189.in-addr.arpa.
+clients1.google.com.
+a.root-servers.net.
+187.0.100.118.in-addr.arpa.
+www.youtube.com.
+www.alexa.com.
+www.facebook.com.
+saskeds.com.
+boskone.hmc.gotdns.org.
+e566.b.akamaiedge.net.
+cs5236.vkontakte.ru.
+templateswise.com.
+rogrs.com.
+216.29.32.189.in-addr.arpa.
+mscrl.microsoft.com.
+a.root-servers.net.
+www.cuadernalia.net.
+www.newsviva.com.
+kimpetoverby.museum.
+106.229.153.201.in-addr.arpa.
+www.facebook.com.
+airport.tomlin.yahoo.com.
+hotmail.com.rhsbl.ahbl.org.
+rfptemplates.technologyevaluation.com.
+nray.ru.
+www.newnavy.us.
+a.root-servers.net.
+www.crazycrow.com.
+a.root-servers.net.
+elpais.com.co.
+transgriot.blogspot.com.
+32.178.19.88.in-addr.arpa.
+stun.voip.blackberry.com.
+120.87.233.189.in-addr.arpa.
+hasack.com.s9a2.psmtp.com.
+102.246.50.200.in-addr.arpa.
+s-static.ak.facebook.com.
+s.youtube.com.
+bestcrystals.com.
+www.directorioxd.com.
+k2x1bals1.a05i0d3l.
+test.wpat.net.
+mail.intellichoicefs.com.
+laborum.files.wordpress.com.
+www.blend.nl.
+www.guardian.co.uk.
+m.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+cup.com.
+ad.adriver.ru.
+allmovie.com.
+www-x.antd.nist.gov.
+54.5.156.187.in-addr.arpa.
+www19.atwiki.jp.
+api.conduit.com.
+eset.ee.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a2.twimg.com.
+search.babylon.com.
+adfarm.mediaplex.com.
+centuryfitness.com.inbound15.mxlogic.net.
+a1.sphotos.ak.fbcdn.net.
+102.1.168.192.in-addr.arpa.
+www.e-belis.com.
+counter.yadro.ru.
+cdn1.predictad.com.
+jzabaleta.com.
+www.blankpaper.es.
+a.root-servers.net.
+wzus1.ask.com.
+136.198.188.78.in-addr.arpa.
+plusone.google.com.
+fcyt449ng.z12q4h0u.
+www.occidente.com.gt.
+130.188.111.200.in-addr.arpa.
+chat.5251.net.
+gafneyphoto.com.
+mifab.thomasnet-navigator.com.
+www.vsbag.com.
+www.union-web.com.
+fr-fr.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+210.64.35.177.in-addr.arpa.
+content.yieldmanager.edgesuite.net.
+www.google.com.
+static02.olx-st.com.
+orcart.facebook.com.
+whos.amung.us.
+negligee.ru.
+youtu.be.
+teredo.ipv6.microsoft.com.
+1.200.181.93.in-addr.arpa.
+a.root-servers.net.
+d3o96a3f9o7chl.cloudfront.net.
+250.93.54.200.in-addr.arpa.
+www.bittorrent.com.
+www.intermec.com.sg.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+b.scorecardresearch.com.
+apps.facebook.com.
+plugandplay.at.
+3.33.112.187.in-addr.arpa.
+165.116.98.171.in-addr.arpa.
+gfx2.hotmail.com.
+a.root-servers.net.
+iphone-wu.apple.com.
+6.54.222.67.rbl7.mailshell.net.
+12.44.31.190.in-addr.arpa.
+bt.btbbt.com.home.
+idh.ru.
+client61.dropbox.com.
+mail.recycling.ru.
+gfx1.hotmail.com.
+a4.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+messenger.hotmail.com.
+tryfaith.com.
+js.admeld.com.
+ksn2-12.kaspersky-labs.com.
+57.21.94.186.in-addr.arpa.
+vips.msk.rsnet.ru.
+fms.n-tv.de.
+www.dakotaraepatrick.com.
+www.boosterking.com.
+orig-10012.twitter.cotcdn.net.
+166.22.114.211.in-addr.arpa.
+97.198.133.110.in-addr.arpa.
+107.200.26.95.in-addr.arpa.
+www.google-analytics.com.
+www.7x24sex.net.
+profile.ak.fbcdn.net.
+saturn.ak.planet.gen.nz.
+list.cn99.com.
+hhreal.gratisforo.net.
+a.root-servers.net.
+graph.facebook.com.
+pagead2.googlesyndication.com.
+154.1.53.186.in-addr.arpa.
+mail2.korrus.ru.
+external.ak.fbcdn.net.
+sd2mbdavk.29df.
+202.128.71.190.in-addr.arpa.
+goodsonauto.com.s8a2.psmtp.com.
+d2107659.xoom.it.
+a.root-servers.net.
+login.live.com.
+tools.google.com.
+3.96.252.207.zen.spamhaus.org.
+mail.ivank.ru.
+www.mp3musichq.com.
+windows-xp-wallpaper.softonic.com.
+js.wlxrs.com.
+chemline.ru.
+www.cupchicks.com.
+s-static.ak.facebook.com.
+253.208.210.186.in-addr.arpa.
+cdn.api.twitter.com.
+mail.men-and-women.ru.
+a.root-servers.net.
+vancouver.conagramalt.com.
+98.92.238.190.in-addr.arpa.
+www.longliveyourdog.com.
+v2.lscache6.c.android.clients.google.com.
+a749.g.akamai.net.
+photos-a.ak.fbcdn.net.
+191.6.64.72.in-addr.arpa.
+134.59.7.187.in-addr.arpa.
+28.media.tumblr.com.
+connect.facebook.net.
+platform.twitter.com.
+photos-b.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+fagalab.com.
+js2.wlxrs.com.
+personalysis.com.inbound15.mxlogic.net.
+googleads.g.doubleclick.net.
+s10.es.ikariam.com.
+www.pistolpete.com.
+web66-vip.sdv.fr.
+52.7.25.190.in-addr.arpa.
+0-271.channel.facebook.com.
+static.ak.fbcdn.net.
+101.64.118.190.in-addr.arpa.
+b-0.19-210a0449.1581.1518.19d3.2f4a.210.0.ug7mmc32tu8lbeq56ja4dwta6i.avqs.mcafee.com.
+cf.addthis.com.
+ko.wikipedia.org.
+photos-e.ak.fbcdn.net.
+74.223.35.83.in-addr.arpa.
+barracuda.chatom.k12.ca.us.
+rhl8rwuh5.f79o2g9n.
+badgersportswear.com.
+webcache.googleusercontent.com.
+help.yahoo.com.
+michiganladder.com.
+a3.sphotos.ak.fbcdn.net.
+rekaone.com.
+a7dvqduqu.03hn.
+lf2-global.com.
+platform.twitter.com.
+mmoca.org.
+ads.publicidad.net.
+photos-f.ak.fbcdn.net.
+skogmar.com.
+a.root-servers.net.
+97.90.50.190.in-addr.arpa.
+61.245.1.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+firntool.ru.
+a8.sphotos.ak.fbcdn.net.
+accounts.google.com.
+snt132w.mail.live.com.akadns.net.
+au.download.windowsupdate.com.
+s-static.ak.fbcdn.net.
+91.40.188.119.in-addr.arpa.
+thumbs4.ebaystatic.com.
+mail2.sg.megachem.com.
+independent.net.
+59.31.23.186.in-addr.arpa.
+131.26.162.201.in-addr.arpa.
+news.google.es.
+kw.zain.com.
+39.60.54.151.in-addr.arpa.
+kk.wikipedia.org.
+clients1.google.com.
+cine.interbusca.com.
+urbanbarn.com.
+salvasainz.magix.net.
+www.google-analytics.com.
+view.atdmt.com.
+en.wikipedia.org.
+www.youtube-nocookie.com.
+sv1.readmangahentai.com.
+www.facebook.com.
+141.20.168.192.in-addr.arpa.
+cableone.net.
+www.juegos.com.
+mail.rochester.rr.com.
+8ninp3dbe.81ce.
+mail.google.com.
+local-bay.contacts.msn.com.
+evt.adrcntr.com.
+tutorialesdesing.mforos.com.
+134.197.136.186.in-addr.arpa.
+creative.ak.fbcdn.net.
+ydmd.msn.com.
+a4.sphotos.ak.fbcdn.net.
+232.210.152.189.in-addr.arpa.
+evileyetattoo.blogspot.com.
+cdn.rockyou.com.
+www.youtube.com.
+members.dyndns.org.
+www.sbfoot.com.
+overunity.com.
+servicios.prodigy.msn.com.
+www.ftalk.com.
+mail.dimensional.com.
+www.lge.com.
+bio-med.ru.
+www.ebusinessblog.org.
+clients1.google.com.
+www.hidramaq.com.
+aerocondor.com.pe.
+ntp.bluecoat.com.
+r.mzstatic.com.
+zynga1-a.akamaihd.net.
+pacman.net.
+www.facebook.com.
+fbeau.com.
+g.msn.com.
+inbound.cotham.org.netsolmail.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+login.live.com.
+87.89.172.187.in-addr.arpa.
+directory.services.live.com.
+42.19.35.188.in-addr.arpa.
+xnxbpnmag.60cu.
+f.h1.hiltonhhonors.com.
+a.root-servers.net.
+www.facebook.com.
+www.amazon.com.
+fbcdn-sphotos-a.akamaihd.net.
+chandlery.apolloduck.com.
+exceptnothing.com.
+a5.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+252.49.145.189.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+c29.smaato.net.
+maps.google.com.
+sp.cwfservice.net.
+internalcomms.com.ar.
+www.afrosomething.com.
+45.219.158.190.in-addr.arpa.
+6cylopnpm.08lw.
+solarcontroljackson.com.
+148.55.31.190.in-addr.arpa.
+aprn.org.
+s-static.ak.facebook.com.
+208.130.142.187.in-addr.arpa.
+cdn.ad4game.com.
+www.uccuyosl.edu.ar.
+webcache.googleusercontent.com.
+mailgate4.econ.usyd.edu.au.
+forum.techie-buzz.com.
+stromvergleich.freenet.de.
+developers.facebook.com.
+100.198.178.189.in-addr.arpa.
+circusdisco.com.
+stamm-mfg.com.
+photos-d.ak.fbcdn.net.
+matcher.bidder7.mookie1.com.
+163.229.183.212.in-addr.arpa.
+www.bloompapers.com.
+ox-d.liftdna.com.
+i2.ytimg.com.
+a8.sphotos.ak.fbcdn.net.
+www.garageflash.org.
+s1-word-view.vo.msecnd.net.
+googleads.g.doubleclick.net.
+a7.sphotos.ak.fbcdn.net.
+j1.tagstat.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+a1943.phobos.apple.com.
+fbcdn-profile-a.akamaihd.net.
+www.landroversuk.co.uk.
+cuantopuedecostar.blogspot.com.
+pinoy.top-site-list.com.
+thepartyworks.com.
+211.219.201.190.in-addr.arpa.
+weather.wapp.wii.com.
+developers.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+loading3.widdit.com.
+mail86a.rheinmetall-de.com.
+blumoe.com.
+phone.com.
+43region.ru.
+mscrl.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+61.87.163.189.in-addr.arpa.
+aol.com.
+v5.nonxt1.c.youtube.com.
+hopkinsonline.net.
+larompieron.cl.
+ap.faceboooky.com.ar.
+thumbs1.ebaystatic.com.
+mt1.google.com.
+kg3pzattr.66kk.
+57.203.230.190.in-addr.arpa.
+238.55.159.189.in-addr.arpa.
+a.root-servers.net.
+sitecheck2.opera.com.
+mail.mz.ru.
+25.1.1.10.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+130.52.82.200.in-addr.arpa.
+ecimages.kobobooks.com.
+www.caratulart.com.
+92yzc84ny.72iw.
+100.145.67.109.in-addr.arpa.
+grupos.emagister.com.
+debbiecutieface.com.
+www.thepowerbase.com.
+www.doublegames.ws.
+d2098683.xoom.it.
+mirror.fdcservers.net.localdomain.
+a.root-servers.net.
+api.facebook.com.
+www.ramnousia.com.
+a868.phobos.apple.com.
+checkip.dyndns.org.
+fbcdn-photos-a.akamaihd.net.
+www.sinmiedo.es.
+google.com.
+media.admob.com.
+www.facebook.com.
+www.orangerockcorps.co.uk.
+a2.mzstatic.com.
+218.182.34.189.in-addr.arpa.
+events.unesco.org.
+google.com.
+img5.catalog.video.msn.com.
+i1.ytimg.com.
+www.youtube.com.
+187.147.157.82.in-addr.arpa.
+mail.brandytrust.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+s.ytimg.com.
+www.hotvintagetube.com.
+adsx.greystripe.com.
+www.longzhiguang.cn.
+n02.nakanohito.jp.
+mail.lnisigns.com.
+www.gstatic.com.
+sac.gti.mcafee.com.
+www.fvc.org.br.
+cottoneyedjoe.com.
+services.addons.mozilla.org.
+www.nationwide.com.
+0.11-230f8081.8020081.1518.1945.3ea0.200.0.en9j4bbznzcg3nfde5c5ia2qrv.avqs.mcafee.com.
+img.pulsemgr.com.
+www.ker-mor.com.
+172.218.142.187.in-addr.arpa.
+mail2.itko.com.
+joker.u.pereslavl.ru.
+www.facebook.com.
+www.uruguay.com.
+sites.google.com.
+mta5.am0.yahoodns.net.
+owmd8hdae.98ui.
+en.wikipedia.org.
+photos-d.ak.fbcdn.net.
+de-de.facebook.com.
+www.trubka.ru.
+photos-c.ak.fbcdn.net.
+wbhsi.net.
+imgb.noticiascristianas.me.
+_794_46_0.
+a.root-servers.net.
+www.cgdd.org.
+developers.facebook.com.
+48.165.168.192.in-addr.arpa.
+20minutos.feedsportal.com.
+immunbio.mpg.de.
+a.root-servers.net.
+210.235.121.84.in-addr.arpa.
+login.toolbar.conduit-services.com.
+83.25.179.187.in-addr.arpa.
+11.176.88.174.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+api-read.facebook.com.
+mscrl.microsoft.com.
+teredo.ipv6.microsoft.com.
+94.222.91.186.in-addr.arpa.
+192.12.0.180.in-addr.arpa.
+alservice.com.
+inbound.medirattas.com.netsolmail.net.
+a.root-servers.net.
+esdc006.eame.global.sgs.com.
+74.209.216.41.in-addr.arpa.
+www.3lakeefk.blogspot.com.
+dowcorning.com.
+46.65.19.186.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+www.bbc.co.uk.
+ad.yieldmanager.com.
+ads.bluelithium.com.
+tilers.ru.
+107.204.103.189.in-addr.arpa.
+thecentergb.org.
+auditors.spb.ru.
+www.google-analytics.com.
+eo.wikipedia.org.
+remanage.otepremium.gr.
+95.231.41.126.in-addr.arpa.
+105.196.13.189.in-addr.arpa.
+www.galiciasustentable.com.
+www.blogger.com.
+rxservices.co.uk.
+www.socialgrowthtechnologies.com.
+lo393qwertasd.com.
+static.ak.connect.facebook.com.
+twitter.com.
+a.root-servers.net.
+www.aleks.com.
+facebook.farmville.com.
+www.google.com.
+ksn7-12.kaspersky-labs.com.
+a4.sphotos.ak.fbcdn.net.
+crl.geotrust.com.
+crecardoffer.com.
+191.29.95.201.in-addr.arpa.
+s-static.ak.fbcdn.net.
+desemejanza.br.dnsbl7.mailshell.net.
+z5riknayz.54ar.
+adonis.ru.
+imagen04.247realmedia.com.
+client.winamp.com.
+35.160.143.190.in-addr.arpa.
+a.root-servers.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+smtp.ftnewyorklife.com.
+translate.googleapis.com.
+www.loveland.k12.oh.us.
+nbase.com.
+resources.rosettastone.com.
+lyricswillnotreachtheaudience.blogspot.com.
+www.it-bs.com.ar.
+denis.stalker.h3q.com.
+js2.wlxrs.com.
+www.itinytits.com.
+110.88.96.99.in-addr.arpa.
+zao-gorod.ru.
+ro.wikipedia.org.
+login.live.com.
+jxe.com.
+concordehealth.net.
+46.42.171.189.in-addr.arpa.
+entertainmentwise.com.
+www.youtube.com.
+217.210.35.200.in-addr.arpa.
+91.125.47.189.in-addr.arpa.
+www.clinicaser.info.
+cdn2.stanleysupplyservices.com.
+syndication.exoclick.com.
+ltasconfig.ltassrv.com.
+181.113.112.186.in-addr.arpa.
+194.222.111.189.in-addr.arpa.
+dns.msftncsi.com.
+static.ak.facebook.com.
+49.200.19.204.in-addr.arpa.
+www.dressessalestore.com.
+www.twitter.com.
+189.104.93.186.in-addr.arpa.
+ussigns.com.inbound15.mxlogicmx.net.
+blackberrycool.com.
+92.165.202.64.in-addr.arpa.
+www.mp3sugar.com.
+hdarena.org.
+www.youtube.com.
+ksn2-12.kaspersky-labs.com.
+trend_micro_titanium_internet_security.en.softonic.com.
+platform.twitter.com.
+246.155.172.190.in-addr.arpa.
+ad.doubleclick.net.
+maps.google.com.
+pacific-islander.blogspot.com.
+www.juegosjuegos.com.
+noesporpresumir.blogspot.com.
+api.facebook.com.
+207.155.251.189.in-addr.arpa.
+d2089124.xoom.it.
+a.root-servers.net.
+loading321.com.
+drb.com.ru.
+profile.ak.fbcdn.net.
+easygoingscans.disqus.com.
+dnl-01.geo.kaspersky.com.
+www.escapade-media.com.
+www.facebook.com.
+photos-f.ak.fbcdn.net.
+i4.ytimg.com.
+www.google-analytics.com.
+api.facebook.com.
+photos-c.ak.fbcdn.net.
+d2107803.xoom.it.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.busty-teenager.com.
+p0.go2map.com.
+muppethouse.com.
+dns.msftncsi.com.
+rwwa.com.au.
+www.wintershoesforwomen.com.
+a1725.l.akamai.net.
+194.81.116.122.in-addr.arpa.
+sp.cwfservice.net.
+cdn.tynt.com.
+unterhaltung.freenet.de.
+www3.l.google.com.
+149.32.222.190.in-addr.arpa.
+gcecisp.com.
+mail.panthera-systems.net.
+amazing-3d-aquarium.softonic.com.
+www.facebook.com.
+platform.twitter.com.
+214.188.138.189.in-addr.arpa.
+s7.addthis.com.
+googleads.g.doubleclick.net.
+hcmintl.com.
+www.sepyme.gov.ar.
+interpartner-bg.ru.
+www.databasebasketball.com.
+130.146.92.114.in-addr.arpa.
+yjmkfhcul.14hi.
+connect.facebook.net.
+www.bonanzabucks.com.
+a3.sphotos.ak.fbcdn.net.
+gastro.org.
+a8.sphotos.ak.fbcdn.net.
+921lqelam.v68l4d9s.
+cydiahelp.com.
+acordespara-guitarra.blogspot.com.
+trucosparacityville.com.
+www.livetemplate.co.cc.
+rv.ginyas.com.
+a1148.phobos.apple.com.
+ajax.googleapis.com.
+ar-ar.facebook.com.
+15.28.248.99.in-addr.arpa.
+i3.ytimg.com.
+1.227.168.192.in-addr.arpa.
+212.246.160.190.in-addr.arpa.
+www.autocue.com.
+tg.9600518.com.
+a2.sphotos.ak.fbcdn.net.
+im.afy11.net.
+youtube.desifun.co.uk.
+www.sexonomotel.com.br.
+bitnova.info.
+event.republika.co.id.
+admin.nmt.edu.
+garywarnett.wordpress.com.
+attitudeclothing.co.uk.
+pyzxc32nm.k46s1e0x.
+photos-e.ak.fbcdn.net.
+195.139.213.186.in-addr.arpa.
+182.51.10.186.in-addr.arpa.
+www.merval.sba.com.ar.
+www.cintras.org.
+apps.facebook.com.
+www.linkedin.com.
+punk-medallo.blogspot.com.
+45.232.204.130.in-addr.arpa.
+112.59.51.201.in-addr.arpa.
+cdn.niche.videosz.com.
+sp.cwfservice.net.
+northcenter.com.
+gut.bmjjournals.com.
+sc21.rules.mailshell.net.
+fb-fb-0.castle.zynga.com.
+vk.com.
+.
+ihardlyknowher.com.
+moyaodejda.ru.
+pt-br.facebook.com.
+www.stephenking.com.
+www.google.com.
+www.longrangeweather.com.
+mls.softjoys.com.
+www-t.decisionnewsmedia.com.
+102.45.78.201.in-addr.arpa.
+coastallenv.com.
+coins.mochimedia.com.
+a5.sphotos.ak.fbcdn.net.
+142.192.56.190.in-addr.arpa.
+scholar.google.com.
+147.128.66.201.in-addr.arpa.
+vampiro.comze.com.
+h.live.com.
+mscrl.microsoft.com.
+googleads.g.doubleclick.net.
+tinyurl.com.
+go.srvnow.com.
+71.223.163.93.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+creative.ak.fbcdn.net.
+danielnylander.se.
+bwig.net.
+grooveshark.com.
+je.org.
+a.root-servers.net.
+a.root-servers.net.
+shares.ru.
+mystartantiphishing.com.
+143.244.165.83.in-addr.arpa.
+ednathomazini.blogspot.com.
+dns.msftncsi.com.
+ad-g.doubleclick.net.
+www.facebook.com.
+35.203.19.24.in-addr.arpa.
+inbound.pwpellets.com.netsolmail.net.
+rcp.na.blackberry.com.
+static.ak.fbcdn.net.
+plusone.google.com.
+evsecure-ocsp.verisign.com.
+fordhamgrad.com.
+24.132.217.190.in-addr.arpa.
+mismaderitascountry.blogspot.com.
+www.pediatraenlinea.com.
+download.windowsupdate.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.domainlogr.com.
+200.83.139.175.in-addr.arpa.
+krauscarpet.com.
+de.tynt.com.
+mail.rlcone.com.
+www.desafinacoes.pt.vu.
+43.236.20.186.in-addr.arpa.
+chromeupdate.dealply.com.
+csa.yahoo.com.
+photos-c.ak.fbcdn.net.
+zh-cn.facebook.com.
+186.169.209.190.in-addr.arpa.
+199.71.191.189.in-addr.arpa.
+pixel.facebook.com.
+a2.sphotos.ak.fbcdn.net.
+fabcon-usa.com.
+m.facebook.com.
+ns.rx.ru.
+www.google.com.
+photos-c.ak.fbcdn.net.
+dns.msftncsi.com.
+yaproffi.ru.
+google.com.
+211.72.223.71.in-addr.arpa.
+127.139.245.189.in-addr.arpa.
+attaboy.ru.
+fbcdn-sphotos-a.akamaihd.net.
+img-2006-07.photosight.ru.
+www.google-analytics.com.
+photos-g.ak.fbcdn.net.
+nicewallpaper.tk.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+orcart.facebook.com.
+www.google-analytics.com.
+www.facebook.com.
+us.mg5.mail.yahoo.com.
+e.travelocity.co.in.
+iso1200.blogspot.com.
+www.doulike.us.
+demo.templatepanic.com.
+244.42.182.190.in-addr.arpa.
+g.live.com.
+www.facebook.com.
+trcexcedg02.madisoncity.k12.al.us.
+a.root-servers.net.
+.
+www.facebook.com.
+peoplescube.com.
+ip1.dynupdate.no-ip.com.
+98.188.160.190.in-addr.arpa.
+announce.com.
+116.30.118.190.in-addr.arpa.
+smtp1.emv2.com.
+a4.sphotos.ak.fbcdn.net.
+226.103.213.189.in-addr.arpa.
+lasdinamicas12.blogspot.es.
+108.64.95.190.in-addr.arpa.
+a.root-servers.net.
+53.234.226.24.in-addr.arpa.
+tadufeu-lefilm.com.
+z-ecx.images-amazon.com.
+www.meet-teens.de.
+mta5.am0.yahoodns.net.
+42.60.122.186.in-addr.arpa.
+rs.gwallet.com.home.
+78.45.143.168.in-addr.arpa.
+www.uach.cl.
+197.255.179.190.in-addr.arpa.
+8zc5kyxmq.12pt.
+creative.ak.fbcdn.net.
+iesnorbabachillerato.files.wordpress.com.
+www.hairdirect.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+53.244.84.200.in-addr.arpa.
+136.234.38.81.in-addr.arpa.
+www.artplus.hr.
+www.update.microsoft.com.
+checkip.dyndns.com.
+www.msn.com.
+cs606.vk.com.
+www.google.com.
+www.eljusticiadearagon.com.
+mail.google.com.
+a1005.w42.akamai.net.
+a.root-servers.net.
+axcoto.com.
+mailstore1.secureserver.net.
+www.google.com.
+b-0.19-a3005008.1081.1518.19d3.3ea1.410.0.trqnb8j7c6bttppqf7njezi3zb.avqs.mcafee.com.
+190.249.169.189.in-addr.arpa.
+www.megavideo.com.
+165.25.173.190.in-addr.arpa.
+ise.qc.ca.
+240.153.68.190.in-addr.arpa.
+ci.santa-maria.ca.us.
+neustarinc.com.
+176.112.137.201.in-addr.arpa.
+insider.msg.yahoo.com.
+en.y8.com.
+utamie.com.
+a.root-servers.net.
+swxmail01.freddiemac.com.
+213.243.34.187.in-addr.arpa.
+www.alimam.ws.
+zh-cn.facebook.com.
+12.1.168.192.in-addr.arpa.
+rospres.com.
+a8.sphotos.ak.fbcdn.net.
+cdn.api.twitter.com.
+109.81.173.186.in-addr.arpa.
+www.googletagservices.com.
+50.37.253.88.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+csi.gstatic.com.
+29.156.226.189.in-addr.arpa.
+www.hds.com.
+a.root-servers.net.
+secure.wlxrs.com.
+82.8.241.85.in-addr.arpa.
+static.socialvi.be.
+calendar.live.com.
+127.246.143.189.in-addr.arpa.
+thebarefootcontessa.hautetfort.com.
+184.wap517.mobi.
+a.root-servers.net.
+mail.desmet.org.
+85.137.98.62.in-addr.arpa.
+orcart.facebook.com.
+www.fdf.ac.uk.
+website.informer.com.
+egeo.bcr.gob.sv.
+fbcdn-photos-a.akamaihd.net.
+da4:6z2::.r44a0i0s.
+61ov3xt8x.58ev.
+photos-e.ak.fbcdn.net.
+quick-876346.com.
+a1.sphotos.ak.fbcdn.net.
+c.prodigy.msn.com.
+s7.addthis.com.
+aurita.spb.ru.
+www.mansilla-lanzuela.com.
+photos-a.ak.fbcdn.net.
+bbvabancomer.com.
+webmail.woolemsinc.com.
+tmgnow.com.
+hi-in.facebook.com.
+timelinevideo.com.
+a2.sphotos.ak.fbcdn.net.
+mweb.co.za.
+capitalventureslc.com.
+sherl.ru.
+weglobal.com.mail1.psmtp.com.
+l18.member.mud.yahoo.com.
+glph.com.s7a1.psmtp.com.
+www.counterstrikestrats.com.
+2.bp.blogspot.com.
+elcharlas.com.
+s3dg.com.
+_568_97_3.
+www.jugos.com.
+appsuite-production.s3.amazonaws.com.
+blog.strava.com.
+www.bbc.co.uk.
+www.radioasturias.com.
+ip-science.thomsonreuters.com.
+a.root-servers.net.
+a.root-servers.net.
+mail.aplusdevelopment.ru.
+insightbb.com.
+csi.gstatic.com.
+cdn.api.twitter.com.
+adsbc.com.
+thegroovemusiclife.com.
+hzykvhi1q.07dd.
+223.46.141.201.in-addr.arpa.
+a.root-servers.net.
+desastrosamenteyo.blogspot.com.
+ajax.googleapis.com.
+p0b.ru.
+cpr.nipc.net.
+creative.ak.fbcdn.net.
+evapco.com.
+www.petter.nu.
+static3.spilcdn.com.
+cdn.mediafire.com.
+www.facebook.com.
+www.facebook.com.
+atypicalrealism.net.
+crl.verisign.com.
+mail.hexindo-tbk.co.id.
+www.facebook.com.
+ads2.msads.net.
+apps.facebook.com.
+pair.com.
+s2.youtube.com.
+monitel.ru.
+38.43.78.201.in-addr.arpa.
+a.c-0.19-230f8081.c120081.1518.19d2.3ea0.210.0.zjbe7f1jq5pn6gzubrpvg9q57b.avqs.mcafee.com.
+alamc.org.
+a8.sphotos.ak.fbcdn.net.
+ic1.apps.yahooapis.com.
+a7.sphotos.ak.fbcdn.net.
+mail.comestiblesalfa.com.
+bs.serving-sys.com.
+jumpsstars2ds.ms1.gs.nintendowifi.net.
+hot.mshome.net.
+spnoibapp02.emea.sas.com.
+pixel.facebook.com.
+msgnlaw.com.
+forums.vostu.com.
+noexcusesbbq.com.
+profile.ak.fbcdn.net.
+_sip._udp.callcentric.com.
+zanoga.znakomstva.ru.
+nascentric.com.
+sqm.microsoft.com.
+mx1.atlasta.us.
+240.58.219.190.in-addr.arpa.
+www.wepa-db.net.
+floyd-pflueger.com.
+ballaro.blog.rai.it.
+58.156.80.186.in-addr.arpa.
+1.194.176.190.in-addr.arpa.
+us.mg6.mail.yahoo.com.
+8.170.25.177.in-addr.arpa.
+hg.ca.
+3.240.176.189.in-addr.arpa.
+ajax.googleapis.com.
+127.7.138.190.in-addr.arpa.
+barracuda.hilbert.edu.
+www.google-analytics.com.
+tubescript.nubiles.net.
+9lzodgg65.h08p8m7y.
+www.you.
+a7.sphotos.ak.fbcdn.net.
+aus3.mozilla.org.
+photos-d.ak.fbcdn.net.
+52.86.190.190.in-addr.arpa.
+geoiplookup.wikimedia.org.
+bluewin.ch.
+252.208.208.77.in-addr.arpa.
+49.41.244.190.in-addr.arpa.
+broadway.com.
+www.gamenews.ne.jp.
+accounts.google.com.
+blog.focus.it.
+led.com.br.
+mx.comtenidos.com.
+www.gstatic.com.
+da.wikipedia.org.
+distilleryimage6.s3.amazonaws.com.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+lyjak.waw.pl.
+i26.lulzimg.com.home.
+google.com.
+media.solmelia.com.
+areku-desingblog.blogspot.com.
+a4.sphotos.ak.fbcdn.net.
+www.virtual-person.com.
+dragon.rioangrybirds.net.
+mx.painenterprises.com.
+www.fantastigames.com.
+intdoc.com.s5b1.psmtp.com.
+plusone.google.com.
+a.root-servers.net.
+affiliates.indialist.com.
+dns.msftncsi.com.
+hareega.blogspot.com.
+www.youtube.com.
+google.com.
+idcs.interclick.com.
+apis.google.com.
+ocsp.verisign.com.
+knitfamily.blogspot.com.
+246.109.53.186.in-addr.arpa.
+aol.com.
+a.root-servers.net.
+rjljz9jld.f77v7n9k.
+ovi.la.
+mob.adwhirl.com.
+146.103.117.200.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+a3.da1.akamai.net.
+mail.environmentalworks.com.
+cwclick.cingular.com.
+api.twitter.com.
+img4.pixhost.org.
+a6.sphotos.ak.fbcdn.net.
+66.253.63.200.in-addr.arpa.
+translate.googleapis.com.
+www.naviextras.com.
+124.119.195.207.in-addr.arpa.
+kingbulletmods.de.tl.
+bourbonhospital.com.
+avetisian.ru.
+a.root-servers.net.
+mail.klimenko.com.
+14.197.60.213.in-addr.arpa.
+literatura1.foroactivo.com.
+comunicaciondiegosaturno.wordpress.com.
+97.43.176.190.in-addr.arpa.
+tvshowfavs.com.
+124.255.193.71.in-addr.arpa.
+developers.facebook.com.
+fxfeeds.mozilla.com.
+www.hotmail.com.
+apps.facebook.com.
+www.tvazteca.com.
+www.youtube.com.
+inicioid.com.
+photos-a.ak.fbcdn.net.
+www.isegs.com.
+www.hawaiiantropic.com.
+198.79.18.177.in-addr.arpa.
+10.172.168.192.in-addr.arpa.
+img.hotwords.com.br.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.
+biologainteractiva.files.wordpress.com.
+3636.323230.313531.3830.80h42dc9750.webcfs00.com.
+plusone.google.com.
+academystudios.com.
+31.164.82.186.in-addr.arpa.
+mx293.emailfiltering.com.
+www.mobilerule.com.
+centraldoprog.blogspot.com.
+soa.md.
+www.5min.com.
+static.ak.fbcdn.net.
+blog.deepskycolors.com.
+www.wdc.com.
+gwc2.mine.nu.home.
+login.live.com.
+teredo.ipv6.microsoft.com.
+sbclgobla.net.
+www.job.ru.
+m.facebook.com.
+www.marquipwardunited.com.
+_kerberos._tcp.phl00._sites.dc._msdcs.gwamericas.corpnet1.com.
+www.google.com.
+www.facebook.com.
+ksn1-11-part2.kaspersky-labs.com.
+mashable.com.
+www.blogger.com.
+www.facebook.com.
+kinopodborka.ru.
+207.80.124.189.in-addr.arpa.
+mail.revealingtruth.org.
+cofetel.gob.mx.
+73.142.232.189.in-addr.arpa.
+echo.edge.messenger.live.com.
+tl.iek.ru.
+agt.p.360.cn.
+mail.barrengineering.com.
+walalabarker.no-ip.org.
+a.root-servers.net.
+225.0.109.200.in-addr.arpa.
+www.bridesmaiddressesnewyork.com.
+img.strictrestraint.com.
+219.65.226.190.in-addr.arpa.
+a1836.phobos.apple.com.
+thumbnails31.imagebam.com.
+clients1.google.com.
+rad.msn.com.
+oidossucios.com.
+a.tribalfusion.com.
+a1.sphotos.ak.fbcdn.net.
+medicosconscientes.com.
+crl3.digicert.com.
+linksv.com.
+googleads.g.doubleclick.net.
+101.158.66.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+staff.vault.com.inbound15.mxlogicmx.net.
+a6.sphotos.ak.fbcdn.net.
+js.wlxrs.com.
+ssl.gstatic.com.
+i2.ytimg.com.
+relay.globetrotter.net.
+cloud-search-msgplus.linkury.com.
+yui.yahooapis.com.
+www.youtube.com.
+2012carbentley.imagehostinghosting.com.
+21.70.111.200.in-addr.arpa.
+todomh.foros.ws.
+clients1.google.com.
+_740_69_7.
+s-static.ak.facebook.com.
+219.18.173.189.in-addr.arpa.
+s-static.ak.fbcdn.net.
+zone9.hotwords.com.br.
+messenger.providesupport.com.
+willowshields.net.
+igiva.net.
+accounts.google.com.
+a2.sphotos.ak.fbcdn.net.
+www.hygeiababy.com.
+accounts.google.com.
+48.87.16.186.in-addr.arpa.
+_009_26_4.
+mf2.ijnet.net.
+232.28.92.201.in-addr.arpa.
+www.ebay.com.
+www.ypagesminnesota.com.
+www.update.microsoft.com.
+cs10361.vk.com.
+content.yieldmanager.edgesuite.net.
+dns.msftncsi.com.
+.
+east.exch024.serverdata.net.
+loqo.ru.
+photos-a.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+dl-client6.dropbox.com.
+mail.uacparts.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+petanque.ru.
+udc.msn.com.
+feeds.the9513.com.
+alerts.conduit-services.com.
+www.buzzdock.com.
+mgks.ru.
+www.mundofox.com.
+5directconnection.sytes.net.
+56.150.168.192.in-addr.arpa.
+www.cpxadspace.com.
+wpad.belkin.
+cogito.co.uk.
+profile.ak.fbcdn.net.
+m.hardsextube.com.
+www.traductorgoogle.com.mx.
+geo.messenger.services.live.com.
+profile.ak.fbcdn.net.
+chong.paipai.com.
+231.109.180.173.in-addr.arpa.
+mail.live.com.
+www.youtube.com.
+70.103.62.190.in-addr.arpa.
+wr.com.au.
+xtwitcam-paulocoelhox.e.channel.livestream.com.
+pixel.facebook.com.
+xmpp.device05.prod.capptain.com.
+fbcdn-profile-a.akamaihd.net.
+mail.earh.com.
+docs.google.com.
+photos-h.ak.fbcdn.net.
+clubsearay.com.
+irc.purchaseservice.com.
+smtp2.i-wanna.com.
+www.hungriaturismo.com.
+rosecm.com.
+nethra.us.com.s6a2.psmtp.com.
+gfx2.hotmail.com.
+abmh.org.
+an.tacoda.net.
+photos-a.ak.fbcdn.net.
+config.conduitapps.com.
+_094_45_2.
+maps.googleapis.com.
+83.111.153.186.in-addr.arpa.
+114.166.113.24.in-addr.arpa.
+michgreatdane.com.
+74.141.162.192.in-addr.arpa.
+a.root-servers.net.
+www.adobe.com.
+63.246.247.190.in-addr.arpa.
+www.badanaclinic.com.
+132.6.199.190.in-addr.arpa.
+soymarketing.org.
+148.76.136.190.in-addr.arpa.
+www.fyoryi.com.
+amr.wuu.ru.
+mx1.nom-domaine.fr.
+10-razones-para-odiarte.seriespepito.com.
+www.sweetim.com.
+38.108.24.81.in-addr.arpa.
+5jekjdrb6.93gd.
+www.google.com.
+pespn.chartbeat.net.
+ameritimemortgage.com.
+extraodelirio.blogspot.com.
+a3.da1.akamai.net.
+138.122.191.202.in-addr.arpa.
+hotmail.com.
+api.twitter.com.
+www.mariangaspi.blogspot.com.
+200.240.135.189.in-addr.arpa.
+pmhd.org.
+add1-new.dir.vip.sp2.yahoo.com.
+lalunamedia.com.
+213.224.19.187.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+newsletter.yves-rocher.ru.
+162.23.204.190.in-addr.arpa.
+bbcc.com.relay1b.spamh.com.
+static.ulule.me.
+dns.msftncsi.com.
+medintelsolutions.com.inbound10.mxlogicmx.net.
+www.edwardandbella.net.
+236.169.205.190.in-addr.arpa.
+a.root-servers.net.
+www.generation5.org.
+csi.gstatic.com.
+cruisermotorcycles.co.uk.
+osce105.icrc.trendmicro.com.
+creative.ak.fbcdn.net.
+bbvabancoprovincial.blogspot.com.
+aaersystems.com.
+34.3.79.190.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+10.rarbg.com.
+google.com.
+funnysize.com.
+www.jurnii.com.
+www.wtfeed.com.
+fr-fr.facebook.com.
+mail.google.com.
+b.scorecardresearch.com.
+www4.pictures.zimbio.com.
+wpad.og.ge.com.
+pagead2.googlesyndication.com.
+content.yieldmanager.edgesuite.net.
+.
+qnu3yg7nl.l92v6p3x.
+voipb.sip.yahoo.com.
+cs10784.userapi.com.
+214.167.173.189.in-addr.arpa.
+31.199.116.194.in-addr.arpa.
+ads.us.e-planning.net.
+proshowlab.com.
+219.92.250.201.in-addr.arpa.
+11-courier.push.apple.com.
+a1623.phobos.apple.com.
+www.facebook.com.
+91.145.60.189.in-addr.arpa.
+gdbsa.com.
+cdn.api.twitter.com.
+_215_30_3.
+www.topflite.com.
+11.168.188.204.in-addr.arpa.
+blst.msn.com.
+jokerwebhosting.com.
+rvlzdqx8.emltrk.com.
+11111111.com.
+49.114.182.186.in-addr.arpa.
+spynet2.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+137.221.22.187.in-addr.arpa.
+img1.imagehyper.com.
+i16.servimg.com.
+hdwall.org.
+photos-g.ak.fbcdn.net.
+www.luckydrunks.com.
+pixel.facebook.com.
+alphratz.org.
+183.154.178.186.in-addr.arpa.
+dns.msftncsi.com.
+winclufzd.r49r4o9p.
+csi.gstatic.com.
+safebrowsing-cache.google.com.
+movies.getfreefiles.com.
+s167.videobb.com.
+.
+b._dns-sd._udp.lan.
+i381.odnoklassniki.ru.
+pixel.facebook.com.
+counter.yadro.ru.
+www.ogov.eu.
+106.72.203.190.in-addr.arpa.
+0.3696778.com.
+www.moblesvano.com.
+image2.pubmatic.com.
+uysb2jhh6.c09e9g7t.
+api.twitter.com.
+ow.ly.
+tkc-ostrova.ru.
+a.root-servers.net.
+images.wikia.com.
+a.root-servers.net.
+171.183.112.204.in-addr.arpa.
+www.facebook.com.
+rs70tl5.rapidshare.com.
+www.dsi.uniroma1.it.
+teredo.ipv6.microsoft.com.
+www.derbydiva.com.
+a575.b.akamai.net.
+kenta.ru.
+checkip.dyndns.org.
+praxisdesigners.com.
+rss.elmundo.es.
+singnet.com.sg.
+a2.mzstatic.com.
+dl.secunia.com.
+48.149.220.66.in-addr.arpa.
+mail.legalaid.qld.gov.au.
+girardwinery.com.mx2.mspportal.rcimx.net.
+a.root-servers.net.
+a.root-servers.net.
+b._dns-sd._udp.lan.
+helicongroup.com.
+a1.sphotos.ak.fbcdn.net.
+perdiendomiejem.blogspot.com.
+i.ytimg.com.
+jtrucks.com.
+platform.twitter.com.
+galleries.analhookers.com.
+i3.ytimg.com.
+mail.brmarketinggroup.com.
+invotexgroup.com.s6b2.psmtp.com.
+ocsp.thawte.com.
+132.162.208.201.in-addr.arpa.
+6.95.186.189.in-addr.arpa.
+ti2.auctiva.com.
+1.bp.blogspot.com.
+hirm.fr.
+www.fashionablynumb.com.
+www.cricbuzz.com.
+a.root-servers.net.
+m.city.zynga.com.
+a.root-servers.net.
+_965_56_7.
+js.admeld.com.
+a6.sphotos.ak.fbcdn.net.
+86.150.133.187.in-addr.arpa.
+ct.buzzfeed.com.
+zgn.static.zynga.com.
+193.120.33.83.in-addr.arpa.
+s.ytimg.com.
+age-of-empires-online.browsergamez.com.
+o-o.preferred.dfw06s10.v20.lscache8.c.youtube.com.
+www.andopobre.tv.
+a.root-servers.net.
+dns.msftncsi.com.
+blue29.com.
+newlightrealty-com.mail.eo.outlook.com.
+promel.biz.
+accounts.google.com.
+andreapatchwork.blogspot.com.
+www.nibco.com.
+photos-b.ak.fbcdn.net.
+1-213.channel.facebook.com.
+photos-d.ak.fbcdn.net.
+trendynewhairstyles.blogspot.com.
+210.21.175.78.in-addr.arpa.
+www.obsexxed.com.
+154.54.230.190.in-addr.arpa.
+clients.njoyn.com.
+www.olegvolk.net.
+maharaja-ki-raaz.blogspot.com.
+183.121.159.187.in-addr.arpa.
+www.google-analytics.com.
+r._dns-sd._udp.lan.
+papeplating.com.
+b.scorecardresearch.com.
+dennisbarnfield.co.uk.
+crl.microsoft.com.
+apps.facebook.com.
+134.199.121.109.in-addr.arpa.
+profile.ak.fbcdn.net.
+66.152.209.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+in.gotradio.sc.abacast.com.
+artabase.net.
+static.doubleclick.net.
+0.190.157.186.in-addr.arpa.
+17.76.102.109.in-addr.arpa.
+mail.google.com.
+wpad.
+abc123.ru.
+google.com.
+afilm.ru.
+abbottlabspharmaceuticals.com.
+milou-veronica.faithinpoison.com.
+32.49.58.90.in-addr.arpa.
+www.betroffen.at.
+24.147.73.46.in-addr.arpa.
+crl.comodoca.com.
+ib.adnxs.com.
+gcgvrg.com.
+redesdesolidaridad.files.wordpress.com.
+143.221.90.186.in-addr.arpa.
+justinbiebertube.net.
+berryautos.com.
+mail.circlecityvets.com.
+uaemail.com.
+ap.lijit.com.
+www.dunksbnikeheels.com.
+ajax.googleapis.com.
+83.170.181.189.in-addr.arpa.
+xr126envq.k36s6g2n.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+139.99.125.76.in-addr.arpa.
+bitly.com.
+www.virtusmedia.com.br.
+stats.buysellads.com.
+news.google.com.mx.
+a.root-servers.net.
+9sn91n:hs.v17p8q4h.
+www.bywifi.com.
+racheldangerw.files.wordpress.com.
+developers.facebook.com.
+press.dailymotion.com.
+88.68.224.41.in-addr.arpa.
+inbound.rfaxis.com.netsolmail.net.
+photos-h.ak.fbcdn.net.
+.
+www.google.com.
+db._dns-sd._udp.lan.
+hr.mt.com.
+i5.tagstat.com.
+a.root-servers.net.
+tgti.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+galeria.infojardin.com.
+devil76134.no-ip.org.
+pbid.iforex.com.
+a1769.phobos.apple.com.
+5.48.105.112.in-addr.arpa.
+rinco.su.
+packages.linuxmint.com.
+www.google.com.
+www.ant.com.
+royalmed.ru.
+www.google-analytics.com.
+www.things-to-do-barcelona.com.
+iwhome.com.
+mx.bwcutting.com.cust.b.hostedemail.com.
+shremont.ru.
+id.google.com.mx.
+1k8f5s8nv.46na.
+www.neogl.com.
+www.bajanreporter.com.
+acapellas4u.co.uk.
+works.tarefer.ru.
+i4.ytimg.com.
+mtalk.google.com.
+19.95.229.66.in-addr.arpa.
+www.gantuk.com.
+www.facebook.com.
+3-courier.push.apple.com.
+nwinsure.com.mx1.wooden-spoon.rcimx.net.
+pixel.facebook.com.
+api-public.addthis.com.
+partner.googleadservices.com.
+lucia-rg.blogspot.com.
+a.root-servers.net.
+159.63.226.213.in-addr.arpa.
+249.11.152.189.in-addr.arpa.
+tennis.bnpparibas.com.
+malpais.cancioneros.com.
+meta.wikimedia.org.
+mind-caster.com.
+a1886.g.akamai.net.
+byfiles.storage.msn.com.
+ad.yieldads.com.
+15.149.11.187.in-addr.arpa.
+134.158.65.190.in-addr.arpa.
+tucson-club.ru.
+206.45.168.192.in-addr.arpa.
+57.203.232.24.in-addr.arpa.
+bay.messenger.services.live.com.
+www.beckys-dungeon.com.
+neowa.ru.
+counter.yadro.ru.
+www.aol.com.
+jlsautomation.com.inbound15.mxlogic.net.
+www.sport.es.
+sergei-fil.j-net.ru.
+external.mediaworks.co.nz.
+i4.ytimg.com.
+185.189.179.190.in-addr.arpa.
+155.187.68.189.in-addr.arpa.
+t0.tagstat.com.
+mablaw.co.uk.
+emilyhaledesign.com.
+static0.thaitable.com.
+a6.sphotos.ak.fbcdn.net.
+en-us.fxfeeds.mozilla.com.
+s-static.ak.facebook.com.
+us1.badoo.com.
+rcp.na.blackberry.com.
+img.tradedoubler.com.
+tdkom.com.br.
+www.google-analytics.com.
+zgn.static.zynga.com.
+js.wlxrs.com.
+kindleheating.com.
+m.ak.fbcdn.net.
+rss.elmundo.es.
+mail2.ecdservices.com.
+i.w55c.net.
+143.118.203.71.in-addr.arpa.
+www.suma.org.ar.
+b.fenixblau.com.
+mail.neomorganics.com.
+www.facebook.com.
+www.needforspeed.com.
+juanpoeta.blogspot.com.
+www.ilep.org.uk.
+i1.ytimg.com.
+www.bywifi.com.
+static1.iphoneros.net.
+www.gtasa.jp.
+mx.cockrell-hill.tx.us.
+www.1f1f.net.
+muchoestilo.regalosi.com.
+iphone.audiofanzine.com.
+docs.google.com.
+140.68.103.189.in-addr.arpa.
+sswww.hotels.com.
+chefmail.de.
+64.137.151.46.in-addr.arpa.
+mastraveller.com.
+storage.conduit.com.
+photos-a.ak.fbcdn.net.
+104.18.188.186.in-addr.arpa.
+www.stocking-maniacs.com.
+thepiratebay.org.
+blog.sulcisiglesiente.eu.
+28.81.125.186.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+239.178.195.190.in-addr.arpa.
+a.root-servers.net.
+indymedia.org.uk.
+especiales.latam.msn.com.
+dnl-09.geo.kaspersky.com.
+www.professorshouse.com.
+sp.internet.com.
+a6.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+_999_68_0.
+photos.blogger.com.
+107.242.192.77.in-addr.arpa.
+www.facebook.com.
+ad.z5x.net.
+graph.facebook.com.
+symphonysoldiersuk.tumblr.com.
+rightkindofphrase.yuku.com.
+previnet.it.
+download116.avast.com.
+www.infoallen.com.ar.
+191.18.195.187.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+mail.google.com.
+krasdalefoods.com.
+desarrollogerencial.wordpress.com.
+tshore-com.relay1a.spamh.com.
+a.root-servers.net.
+129.253.47.188.in-addr.arpa.
+csi.gstatic.com.
+cti.w55c.net.
+www.mediafire.com.
+219.173.67.201.in-addr.arpa.
+www.yamntther.com.
+221.cim.meebo.com.
+secserv.adtech.de.
+kdc.uas.aol.com.
+104.0.194.98.in-addr.arpa.
+es-la.facebook.com.
+citytours.sg.
+a.root-servers.net.
+thatsmeandthecity.blogspot.com.
+201.227.200.112.in-addr.arpa.
+gs-loc.apple.com.
+apps.facebook.com.
+6.26.141.201.in-addr.arpa.
+literatehousewife.com.
+89.196.103.201.in-addr.arpa.
+susanguerin.com.
+www.goojue.com.
+www.yaracuy.gob.ve.
+ocsp.digicert.com.
+armmf.adobe.com.
+z020.fma.fb.me.
+www.facebook.com.
+photos-f.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+jfh51l6gc.99ew.
+colonialfarmcredit.com.mail4.psmtp.com.
+www.3tv.cl.
+profile.ak.fbcdn.net.
+graph.facebook.com.
+content.yepigames.net.
+carabobo.mundoanuncio.co.ve.
+85.83.149.98.in-addr.arpa.
+retroxpuntones.blogspot.com.
+freesite.com.
+www.youtube-nocookie.com.
+rivahistorical.org.
+a3.sphotos.ak.fbcdn.net.
+7o:hlcx1y.64bh.
+rcp.na.blackberry.com.
+e3191.c.akamaiedge.net.
+photos-b.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+2.129.37.10.in-addr.arpa.
+dns.msftncsi.com.
+www.pravoslavie.ru.
+166.35.47.201.in-addr.arpa.
+blog.alvarols.com.
+static.apk.hiapk.com.
+ts4.mm.bing.net.
+ad.z5x.net.
+a3.sphotos.ak.fbcdn.net.
+twitter.com.
+time.chttl.com.tw.
+www.google.com.
+www.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+www.maccaferri.com.
+49.149.135.190.in-addr.arpa.
+seg.sharethis.com.
+150.111.55.65.list.dsbl.org.
+static.ak.fbcdn.net.
+www.indigomedia.com.
+46.107.36.114.in-addr.arpa.
+sp.cwfservice.net.
+platform.ak.fbcdn.net.
+29.179.138.189.in-addr.arpa.
+ipdns1.hinet.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+97.72.143.201.in-addr.arpa.
+gfpa.ch.
+194.82.138.121.in-addr.arpa.
+babyfaithhope.blogspot.com.
+www.karmakerala.com.
+et1.xhamster.com.
+cantinelizzano.it.
+th.cam4.com.
+www.informador.com.mx.
+126.225.11.201.in-addr.arpa.
+34.85.51.190.in-addr.arpa.
+anycast.perf.glbdns.microsoft.com.
+ldayzv.com.
+telusplanet.net.
+ced.sascdn.com.
+pt.lagsoft.biz.
+itunes.apple.com.
+ksn5-12.kaspersky-labs.com.
+google.com.
+a.root-servers.net.
+excelir.com.
+sacu.com.
+www.holdenwiki.net.
+223.61.24.201.in-addr.arpa.
+ecn.dev.virtualearth.net.
+circleofcrafters.com.
+zcache.zgncdn.com.
+a.static-cdn.playfish.com.
+a.root-servers.net.
+cmnefktt.cc.lan.
+www.blabbers.com.
+sherpa-auto.ru.
+pamsa.com.
+237.222.105.186.in-addr.arpa.
+taggalicio.us.
+myaccount.k12.com.
+get.adobe.com.
+www.playblog.ws.
+support.google.com.
+109.213.184.78.in-addr.arpa.
+250.92.46.186.in-addr.arpa.
+www.hotlinkbanners.com.
+188.227.104.189.in-addr.arpa.
+125.108.142.98.in-addr.arpa.
+soldmedal.com.
+mob800.photobucket.com.
+49.208.140.79.in-addr.arpa.
+www.friendlyduck.com.
+cdn1.video.poshgay.com.
+a.root-servers.net.
+l.yimg.com.
+contatransparente.pt.
+blog.spafinder.com.
+weather.wapp.wii.com.
+www.motionempire.com.
+lovepoems.blog13.net.
+h.live.com.
+rad.msn.com.
+www.nytimes.com.
+developers.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+newsrss.bbc.co.uk.
+www.unicharm.co.jp.
+api.twitter.com.
+mail.vag.ru.
+xerocost.com.
+ns1.dvrtw.com.tw.
+smtp4.hamilton.net.
+affiliates.lelo.com.
+www.google.com.
+www.googletagservices.com.
+www.radiomuseum-bocket.de.
+www.ncjapan.co.jp.
+partner.googleadservices.com.
+cl.m.globedia.com.
+www.google-analytics.com.
+coroiepvina.blogspot.com.
+marialopez-orientacion.blogspot.com.
+www.asone.org.
+disqus.com.
+www.google.com.
+a4.sphotos.ak.fbcdn.net.
+arreclau.blogspot.com.
+images.channeladvisor.com.edgesuite.net.
+cronicas-urbanas.blogspot.com.
+mw.50cubes.com.
+i.ebayimg.com.
+barracuda.reliancemerchantservices.com.
+131.56.101.94.in-addr.arpa.
+pictures3.ebuddy.com.
+www.allmusic.com.au.
+peliculas-flv.com.
+est.msn.com.
+fashiontribe.net.
+_909_28_7.
+dparikh.com.
+gracobaby.com.
+243.212.172.190.in-addr.arpa.
+socium.info.
+photos-f.ak.fbcdn.net.
+73.20.136.78.in-addr.arpa.
+profile.ak.fbcdn.net.
+secure.shared.live.com.
+i1.ytimg.com.
+www.reliabilityweb.com.
+131.207.220.74.in-addr.arpa.
+169.71.142.189.in-addr.arpa.
+safebrowsing.clients.google.com.
+s.youtube.com.
+i38.tinypic.com.
+9x8wza:f8.u72s4u8p.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+inbound.peraragroup.com.netsolmail.net.
+a.root-servers.net.
+de-de.facebook.com.
+safebrowsing-cache.google.com.
+grapecreekisd.net.
+217.218.5.187.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+22.140.126.178.in-addr.arpa.
+static.2yourface.com.
+l.yimg.com.
+www.google-analytics.com.
+dualstack.ipv6-exp.l.google.com.
+www.objetivofamosos.com.
+v2.cache2.c.youtube.com.
+cachedcommons.org.
+skort.nnov.ru.
+annami43.gogvo.com.
+sp.cwfservice.net.
+www.mojoportal.com.
+a.root-servers.net.
+devices.live.com.
+adulteration.com.
+155.63.135.88.in-addr.arpa.
+www.pc-spielekostenlos.com.
+www.queennarriman.com.
+www.cdn.sherdog.com.
+www.facebook.com.
+api-read.facebook.com.
+www.conduit.com.
+sh.deviantart.net.
+hi-in.facebook.com.
+d.turn.com.
+images.synacor.com.
+apex.com.com.
+milcomhq.com.
+_ldap._tcp.ustc._sites.gc._msdcs.kcc.com.
+newtt.com.
+vpncasestudy.com.
+gfx3.hotmail.com.
+yui.yahooapis.com.
+cjs.cadmus.com.
+www.npcgo.com.
+www.gstatic.com.
+googleads.g.doubleclick.net.
+15.226.13.190.in-addr.arpa.
+time.nist.gov.
+27.147.220.66.in-addr.arpa.
+rad.msn.com.
+a.root-servers.net.
+js2.wlxrs.com.
+d2088610.xoom.it.
+www.anth.ucsb.edu.
+a1108.da1.akamai.net.
+upload.al-wed.com.
+sn145ds.mail.services.live.com.
+34.239.75.190.in-addr.arpa.
+sb.scorecardresearch.com.
+wpad.
+www.mytreedb.com.
+fa:2rgnd6.g99d9r7c.
+m.facebook.com.
+messenger.hotmail.com.
+88.235.159.10.dynamic.ttnet.com.tr.
+a7.sphotos.ak.fbcdn.net.
+8.5.6.189.in-addr.arpa.
+ipolone.com.
+d1se315fw1201h.cloudfront.net.
+www.greendayvideos.com.
+teredo.ipv6.microsoft.com.
+wickedfire.com.
+frankconsulting.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+bright.com.
+a1505.l.akamai.net.
+134.188.223.203.in-addr.arpa.
+www.ercrugby.com.
+hvgo.blogspot.com.
+go.srvnow.com.
+a.root-servers.net.
+214.203.9.190.in-addr.arpa.
+japc.demon.co.uk.
+p07-caldav.icloud.com.
+a.root-servers.net.
+www.gobiernodecanarias.org.
+i4.ytimg.com.
+ocsp.entrust.net.
+netsense.net.
+segments.adap.tv.
+clients1.google.com.
+photos-b.ak.fbcdn.net.
+time.stdtime.gov.tw.
+guessing-game.friv4.info.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+123.185.120.174.in-addr.arpa.
+y9pwdp6kw.u86k6q0b.
+208.105.145.187.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+96.200.168.1.in-addr.arpa.
+lapassucci.blogspot.com.
+1.bp.blogspot.com.
+www.facebook.com.
+circleoflifelabs.com.
+syndication.intel.com.
+www.vtsup.com.
+login.live.com.
+pixel.indieclick.com.
+ecards.emilatintools.com.
+www.360minutos.com.
+jodase19.tumblr.com.
+tnvalleyins.com.
+thetrucker.com.
+api.twitter.com.
+apps.facebook.com.
+tum.mvd.ru.
+www.google-analytics.com.
+www.melbournehandyman.com.au.
+inmo-balear.com.
+pics.ebaystatic.com.
+www.facebook.com.
+trac.torproject.org.
+sparling.com.
+fbcdn-profile-a.akamaihd.net.
+www.thef1.com.
+crmifetel.ife.org.mx.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+mail.connico.com.
+_134_81_8.
+www.je.
+creative.ak.fbcdn.net.
+.
+swiss-style.ru.
+static.ak.fbcdn.net.
+197.143.172.187.in-addr.arpa.
+pega.jorge.over-blog.es.
+static.ak.fbcdn.net.
+163.62.92.186.in-addr.arpa.
+www.airtel.net.
+157.100.205.87.in-addr.arpa.
+static.ak.fbcdn.net.
+ad-g.doubleclick.net.
+vcs1.msg.yahoo.com.
+www.controlatugastritis.com.mx.
+www.675bar.com.
+t2.gstatic.com.
+mailsiesta.dynalias.org.
+gratka.pl.
+res.media.net.
+a.imageshack.us.
+www.laps3.com.
+crl.microsoft.com.
+www.aspire-cs.com.
+au.download.windowsupdate.com.
+www.sabayacafe.com.
+26.media.tumblr.com.
+m45rft6a6.r20x4o5f.
+photos-c.ak.fbcdn.net.
+ads.tlvmedia.com.
+78.16.229.190.in-addr.arpa.
+bs.serving-sys.com.
+pt-br.facebook.com.
+labutacadelcinefilo.files.wordpress.com.
+86.218.171.187.in-addr.arpa.
+api-public.addthis.com.
+a.root-servers.net.
+d3lvr7yuk4uaui.cloudfront.net.
+pixel.facebook.com.
+mail.kis.ru.
+www.mediafire.com.
+travelport.com.
+b._dns-sd._udp.0.129.37.10.in-addr.arpa.
+20.208.208.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+160.112.61.186.in-addr.arpa.
+43.15.57.186.in-addr.arpa.
+giantmag.disqus.com.
+apple-mobile.query.yahooapis.com.
+c0014129.ssl.cf1.rackcdn.com.
+wcskids.net.
+edtechtalk.com.
+download670.avast.com.home.
+a5.sphotos.ak.fbcdn.net.
+i4.ytimg.com.
+js.imonografias.com.
+fcico.com.
+searchclient.live.net.
+cdn.advertserve.com.
+www.update.microsoft.com.
+188.253.163.71.in-addr.arpa.
+c2.softonicads.com.
+www.usefulcharts.com.
+mail.agr.state.nc.us.
+creative.ak.fbcdn.net.
+theseges.com.
+www.google.com.
+170.59.155.189.in-addr.arpa.
+162.197.124.189.in-addr.arpa.
+226.3.115.79.in-addr.arpa.
+dns.msftncsi.com.
+www.makemoneyandomainparking.info.
+www.aba.org.au.
+google.com.
+img29.elex-tech.org.
+mail.efonalledas.com.
+itunes.apple.com.
+ucentral.edu.co.
+profile.ak.fbcdn.net.
+www.download.windowsupdate.com.
+api-read.facebook.com.
+13.137.89.98.in-addr.arpa.
+agencias.ua.com.ar.
+dc466.4shared.com.
+179.156.92.186.in-addr.arpa.
+www.energycodes.gov.
+233.32.197.87.in-addr.arpa.
+a.root-servers.net.
+_752_77_8.
+www.metodocallan.net.
+mail.cri.org.uk.
+api.facebook.com.
+www.google.com.
+www.msftncsi.com.
+lb._dns-sd._udp.0.55.211.10.in-addr.arpa.
+p04-keyvalueservice.icloud.com.
+accounts.google.com.
+thumbs2.ebaystatic.com.
+97.140.172.190.in-addr.arpa.
+www.facebook.com.
+www.google.com.
+judaismohoy.com.
+dns.msftncsi.com.
+espanol.weather.com.
+49.149.220.66.in-addr.arpa.
+sprentpcs.com.
+photos-b.ak.fbcdn.net.
+geo.messenger.services.live.com.
+files.fatakat.com.
+wildcard.whitehouse.gov.edgekey.net.
+a.root-servers.net.
+231.3.39.184.in-addr.arpa.
+137.38.55.187.in-addr.arpa.
+sgpqv8gj3.91za.
+2.129.37.10.in-addr.arpa.
+208.103.206.190.in-addr.arpa.
+ccp.ucr.ac.cr.
+us.lrd.yahoo.com.
+202.184.1.88.in-addr.arpa.
+www.dpreview.com.
+www.targetingnow.com.
+www.damnfunnypictures.com.
+i4.ytimg.com.
+vkontakte.ru.
+clients2.google.com.
+www.facebook.com.
+hhi.fraunhofer.de.
+43.186.152.190.in-addr.arpa.
+aol.com.
+js.adsonar.com.
+photos-b.ak.fbcdn.net.
+kinshasa.usembassy.gov.
+mail-attachment.googleusercontent.com.
+photos-a.ak.fbcdn.net.
+mail.holmen.k12.wi.us.
+40.139.24.177.in-addr.arpa.
+159.201.157.186.in-addr.arpa.
+mx.mfua.ru.
+www.youtube.com.
+limao.com.
+littleceasars.com.
+21.25.19.186.in-addr.arpa.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+leetufrase.com.
+blogs.lavanguardia.es.
+pagead2.googlesyndication.com.
+i0.tagstat.com.
+129.5.78.186.in-addr.arpa.
+entretenimiento.prodigy.msn.com.
+mail.google.com.
+tags.bluekai.com.
+237.112.169.189.in-addr.arpa.
+s7.addthis.com.
+wu.apple.com.
+71.153.177.190.in-addr.arpa.
+worldcat.org.
+liveupdate.symantecliveupdate.com.
+kepler.vis.com.pe.
+www.es.vectoropenstock.com.
+cdnp1.quepasa.com.
+zh-cn.facebook.com.
+mail.vedenina.ru.
+api.midomi.com.
+bsf.smowtion.com.
+51.119.174.189.in-addr.arpa.
+api.chartbeat.com.
+54.81.220.189.in-addr.arpa.
+64.166.251.78.in-addr.arpa.
+twitter-widgets.s3.amazonaws.com.
+a-0.19-21090001.c010083.1518.19d4.3ea1.410.0.fkm9uk1mzlibf2ekqil21fqqdv.avqs.mcafee.com.
+www.liu.edu.lb.
+89.163.1.201.in-addr.arpa.
+:n3d3ucx4.n23l8n3d.
+hou.jumpskyhigh.com.
+112.23.32.99.in-addr.arpa.
+www.cubeforums.com.
+www.emici.net.
+www.g66.co.uk.
+dricompanies.com.
+s.youtube.com.
+5.164.209.61.in-addr.arpa.
+relay.platform.co.uk.
+yahoo.com.
+mail.caryfire.com.
+243.157.104.189.in-addr.arpa.
+www.lascaderasspain.com.
+profile.ak.fbcdn.net.
+external.ak.fbcdn.net.
+www.facebook.com.
+apps.facebook.com.
+citylin.ru.
+dnl-17.geo.kaspersky.com.
+clients2.google.com.
+s4.histats.com.
+groupeibidaa.com.inbound15.mxlogic.net.
+smtp.
+download810.avast.com.
+www.prtool.info.
+euro.mediotiempo.com.
+go.trafficshop.com.
+85.35.61.186.in-addr.arpa.
+49.50.250.189.in-addr.arpa.
+pixel-mixer.ru.
+www.glennsacks.com.
+mus.ch.
+18.2.168.192.in-addr.arpa.
+www.4shared.com.
+www.kreditrechner.be.
+www.davinci-barcelona.com.
+bay.messenger.services.live.com.
+shatteringdenial.com.
+hardee.k12.fl.us.
+circuitpeople.com.
+ads.bluelithium.com.
+hi-in.facebook.com.
+www.androidgames.com.
+cciorg.com.
+emotionsandfeelings.com.
+finance.fy6.b.yahoo.com.
+scholar.google.es.
+www.facebook.com.
+www.gstatic.com.
+alittlefoolish.tumblr.com.
+52.245.120.77.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+bar.pianomedia.eu.
+www.google.com.
+ww137.video7live.com.
+a.root-servers.net.
+onlysomewhatqueer.blogspot.com.
+ssl.gstatic.com.
+dns.msftncsi.com.
+ebm.cheetahmail.com.
+15.127.220.201.in-addr.arpa.
+a.root-servers.net.
+apps.facebook.com.
+federated-states-of-micronesia.evisos.com.
+www.youtube.com.
+21.30.4.31.in-addr.arpa.
+secure.shared.live.com.
+foroherramientavirtual.blogspot.com.
+rcp.eu.blackberry.com.
+i3.ytimg.com.
+ctstatic.dealply.com.
+214.118.20.187.in-addr.arpa.
+urs.microsoft.com.
+textual.net.
+a7.sphotos.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+picasaweb.google.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+albertcorp.com.
+descargar.mp3.es.
+241.143.117.200.in-addr.arpa.
+news.google.com.ar.
+t.ymlp204.net.
+mail.cyscosoft.com.
+isapi60.weatherbug.com.
+153.42.36.114.in-addr.arpa.
+207.100.134.174.in-addr.arpa.
+plusone.google.com.
+a3.sphotos.ak.fbcdn.net.
+142.223.54.189.in-addr.arpa.
+amarporamor.blogspot.com.
+www.nuriavilanova.com.
+a.root-servers.net.
+www.gdanskseguros.com.ar.
+verbosenfrances.com.
+groups.google.com.mx.
+145.208.247.92.in-addr.arpa.
+stats-incoming.reciva.com.
+a-0.19-23095000.c090083.1518.19d4.3ea1.410.0.4er73s9p55296jrntlrqiff28i.avqs.mcafee.com.
+mail2.quiktron.com.
+cadizmini.myminicity.es.
+www.pictureshack.us.
+photos-c.ak.fbcdn.net.
+t0.gstatic.com.
+ads.iforex.com.
+cutepuppiespictures.files.wordpress.com.
+tvj.ru.
+219.136.222.201.in-addr.arpa.
+245.200.229.190.in-addr.arpa.
+api.twitter.com.
+www.stupidexe.com.
+www.adobe.com.
+139.132.129.186.in-addr.arpa.
+a.root-servers.net.
+79.234.224.190.in-addr.arpa.
+www.conduit.com.
+grix:7pus.q47h6k9y.
+126.252.20.174.in-addr.arpa.
+go.microsoft.com.
+3.136.158.85.in-addr.arpa.
+js2.wlxrs.com.
+166.94.11.201.in-addr.arpa.
+123.247.20.71.in-addr.arpa.
+home.mcafee.com.
+msn.com.
+www.public-trust.com.
+mirrors.liquidweb.com.
+www.soundcloud.com.
+www.urbandictionary.com.
+platform.ak.fbcdn.net.
+www.eurospares.co.uk.
+mail.kahndesign.com.
+google.com.
+mail.unistroy.ru.
+www.lugardeorigen.net.
+piojodelibro.blogspot.com.
+maps.google.es.
+a.root-servers.net.
+srx.main.ebayrtm.com.
+f.hwa.me.
+plus.google.com.
+sandbridgehouses.com.
+i2.ytimg.com.
+primerosauxilios.8k.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+archive.slickdeals.net.
+a.root-servers.net.
+254.120.198.71.in-addr.arpa.
+246.77.137.24.in-addr.arpa.
+clk.atdmt.com.
+api.geo.kontagent.net.
+mx.youtube.com.
+vgh-gmbh.ru.
+www.lolochofun.blogspot.com.
+vso.org.uk.
+muprsp.ru.
+223.240.19.201.in-addr.arpa.
+bd0dc.v.fwmrm.net.
+es.data.toolbar.yahoo.com.
+mx.vistarealtyinc.com.
+mail.
+dental-tribune.com.
+oblfarm.yaroslavl.ru.
+a.root-servers.net.
+www.myrealty.com.
+sg.yimg.com.
+80.244.10.83.in-addr.arpa.
+en-us.start.mozilla.com.
+www.20minutos.es.
+sp.cwfservice.net.
+tienda.abc.es.
+10.207.61.67.in-addr.arpa.
+s.ytimg.com.
+search.conduit.com.
+147.163.174.190.in-addr.arpa.
+franciscoafilado.blogspot.com.
+a.root-servers.net.
+kermit.asvt.ru.
+ssl.facebook.com.
+ksn2-12.kaspersky-labs.com.
+mega.com.ru.
+outmail003.snc7.facebook.com.
+www.youtube.com.
+celebridez.files.wordpress.com.
+ad.yieldmanager.com.
+yweb.com.
+coastin.net.
+soul2soul.co.uk.
+74.204.29.186.in-addr.arpa.
+23.229.180.189.in-addr.arpa.
+joule.qfa.uam.es.
+pop.gmail.com.
+ustravelny.us.
+homelynxloans.com.
+230.88.42.186.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+ac.ebis.ne.jp.
+www.tracker-web-site.com.
+42.84.230.189.in-addr.arpa.
+tc.v5.cache2.c.youtube.com.
+45.93.155.46.in-addr.arpa.
+www.independentwestand.org.
+75.76.36.186.in-addr.arpa.
+183.74.8.83.in-addr.arpa.
+\006.
+167.8.239.201.in-addr.arpa.
+plastek.msk.ru.
+ds.addthis.com.
+mail.rugbymfg.com.
+www.control.com.
+www.facebook.com.
+syndication.traffichaus.com.
+isatap.home.
+r.nexac.com.
+newchapter.com.inbound20.mailprotector.net.
+photos-f.ak.fbcdn.net.
+s1.mindvalley.us.
+www.missy-elliott.com.
+google.com.mx.
+www.facebook.com.
+linda-goodman.com.
+msmedia.ru.
+www.twitter.com.
+superhembras.blogspot.com.
+profile.ak.fbcdn.net.
+www.zynga.com.
+mail.google.com.
+www.bizrate.com.
+quirkcars.com.
+a.root-servers.net.
+signatureloans100.com.
+mx.omg.yahoo.com.
+www.google-analytics.com.
+debelis.net.
+photos-e.ak.fbcdn.net.
+97.1.1.10.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+www.easy-dating.org.
+85.36.95.190.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.google.com.
+www.russian-women-personals.com.
+fbcdn-profile-a.akamaihd.net.
+www.maui.net.
+api.twitter.com.
+a3.twimg.com.
+a.root-servers.net.
+msn.foxsports.com.
+t3.tagstat.com.
+55.118.181.175.in-addr.arpa.
+dailyicon.net.
+static.ak.fbcdn.net.
+r._dns-sd._udp.lan.
+inbound.rwridley.com.netsolmail.net.
+onlinestores.metaservices.microsoft.com.
+137.211.193.186.in-addr.arpa.
+139.248.106.187.in-addr.arpa.
+news.google.com.mx.
+googlehosted.l.googleusercontent.com.
+updateservice.sonic.com.
+profile.ak.fbcdn.net.
+92.36.135.190.in-addr.arpa.
+hash.orbitdownloader.com.
+admin.inventarte.net.
+chip01.chipimages.de.
+img7.ask.fm.
+courtreoprt.com.
+ksn2-12.kaspersky-labs.com.
+lstk.ru.
+orcart.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+229.31.74.187.in-addr.arpa.
+exodus.desync.com.
+www.shopbrandclothes.com.
+google.com.
+a.root-servers.net.
+.
+oqsauiwk.info.
+static.ak.fbcdn.net.
+touch.www.linkedin.com.
+www.paypal.com.
+gbhcpas.com.pri-mx.na0104.smtproutes.com.
+_798_42_7.
+188.111.191.186.in-addr.arpa.
+detr.state.nv.us.
+140.13.104.200.in-addr.arpa.
+creative.ak.fbcdn.net.
+temptechno.ru.
+mujeres-de-lujo.seriespepito.com.
+warehouse.davematthewsband.com.
+lomanis.believeband.com.
+a4.sphotos.ak.fbcdn.net.
+www.kobakant.at.
+flashembed.xvideos.com.
+230.107.193.187.in-addr.arpa.
+skatechikar.blogspot.com.
+243.214.159.189.in-addr.arpa.
+ad.yieldmanager.com.
+creative.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+ib.adnxs.com.
+pagead2.googlesyndication.com.
+api.facebook.com.
+digiplotinc.com.
+www.youtube.com.
+mediacdn.disqus.com.
+www.google-analytics.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+btdinc.net.
+external.ak.fbcdn.net.
+imap.strato.com.
+151.95.141.201.in-addr.arpa.
+icogblogs.com.
+emailsecurity.eandggroup.com.
+file81.loadup.ru.
+ehot.biz.
+www.assaya.org.
+a.root-servers.net.
+www.youtube.com.
+katerine-fernandez.blogspot.com.
+s.ytimg.com.
+health.chinanews.com.
+www.topfoci.hu.
+michaelpatton.blogspot.com.
+idc091a05.parker.com.
+watson.microsoft.com.
+photos-e.ak.fbcdn.net.
+www2.buenacuerdo.com.ar.
+ocsp.thawte.com.
+mlbplayers.mlb.com.
+71.24.23.190.in-addr.arpa.
+webcache.googleusercontent.com.
+www.facebook.com.
+50.20.38.190.in-addr.arpa.
+www.english-to-go.com.
+ebsrealestate.com.
+underpagrounds.wordpress.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+75:6y6ton.44cs.
+a.rad.msn.com.
+rtc.sfsu.edu.
+www.microsoft.com.
+t2.gstatic.com.
+www.blacksbangblondes.com.
+smallmouthinyoursoup.blogspot.com.
+www.youtube.com.
+a1005.w42.akamai.net.
+yule.tom.com.
+ueh.dynamixsoftware.com.
+photos-h.ak.fbcdn.net.
+134.115.204.187.in-addr.arpa.
+ax.init.itunes.apple.com.
+api.twitter.com.
+www.tac.vic.gov.au.
+thecw.com.
+relay.mobilet.ru.
+wafi.com.
+www.update.microsoft.com.
+229.217.223.66.in-addr.arpa.
+231.135.31.88.in-addr.arpa.
+sphotos.ak.fbcdn.net.
+file.funitto.com.
+gate.ece.ucsb.edu.
+www.clubsaorihara.com.
+dns.msftncsi.com.
+www.reggae-blog.net.
+plus.google.com.
+fbcdn-video-a.akamaihd.net.
+www.bs-garden.com.
+240.204.160.187.in-addr.arpa.
+download326.avast.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+186.78.132.190.in-addr.arpa.
+www.gravatar.com.
+secure.leadback.advertising.com.
+46.190.3.201.in-addr.arpa.
+sumsung.com.
+microsoft-security-essentials.softonic.com.br.
+a.root-servers.net.
+responsiblemarketing.com.
+s-static.ak.fbcdn.net.
+www.puloinfo.net.
+s-static.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+market.ape-apps.com.
+au.download.windowsupdate.com.
+www.eltiempo.com.
+i4.ytimg.com.
+alliance.zap2it.com.
+www.whateats.com.
+www.pimms-pages.co.uk.
+energen.com.mail5.psmtp.com.
+158.30.158.200.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+123.47.184.81.in-addr.arpa.
+c143612.memecenter.com.
+www.facebook.com.
+signum.sivis.org.
+111.119.177.72.in-addr.arpa.
+i1.ytimg.com.
+client-software.real.com.
+api-read.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+114.53.155.187.in-addr.arpa.
+aoujaxpdw.m55v2v4g.
+www.youtube.com.
+www.bigactive.com.
+thehousespa.com.
+129.210.224.190.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+checalo.com.mx.
+enhancedc.co.za.
+ntp1.dlink.com.
+southernhomebuildersllc.com.
+a3.sphotos.ak.fbcdn.net.
+62.158.220.66.in-addr.arpa.
+a.root-servers.net.
+110.14.168.192.in-addr.arpa.
+63.115.111.189.in-addr.arpa.
+www.boi-mela.com.
+www.toyota.com.ar.
+sabores.com.
+www.turpoisk.ru.
+updates.installshield.com.
+www.apple.com.
+smtp.bb.din.or.jp.
+blugro3relay.groove.microsoft.com.
+240.104.126.27.in-addr.arpa.
+crm.digitalchocolate.com.
+livewiremultimedia.com.
+a8.sphotos.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+oi9.photobucket.com.
+farmpp.hakunagames.com.
+gfx2.hotmail.com.
+www.ft.com.
+hoetip.tumblr.com.
+proxify.biz.
+www.facebook.com.
+photos-b.ak.fbcdn.net.
+62ddb2yru.46uz.
+thisishorosho.mshome.net.
+ssl.gstatic.com.
+my.id.all.biz.
+birs.ru.
+www.lunarrepublic.com.
+duschy.ru.
+106.35.243.216.in-addr.arpa.
+rsjxdciym.r35t7e7m.
+informcomplex.ru.
+145.162.81.190.in-addr.arpa.
+safebrowsing.clients.google.com.
+papginos.com.
+entertainment.todaysgist.com.
+sharbell.com.
+48.159.192.187.in-addr.arpa.
+fonts.googleapis.com.
+a1.da1.akamai.net.
+www.cntt.vn.
+63.203.181.175.in-addr.arpa.
+jacona.olx.com.mx.
+apps.facebook.com.
+dns.msftncsi.com.
+www.garbarino.com.
+a.root-servers.net.
+col.stj.s-msn.com.
+cn1.redswoosh.akadns.net:443.
+farm3.static.flickr.com.
+premiergrouprealty.com.
+civilwarquilts.blogspot.com.
+ads.tlvmedia.com.
+api.twitter.com.
+safebrowsing.cache.l.google.com.
+connect.facebook.net.
+www.chw.net.
+_422_82_5.
+a2.sphotos.ak.fbcdn.net.
+www.bawazir.com.
+www.goojue.com.
+www.xango.fr.
+mail.ezmail.com.
+cdn.adnxs.com.
+5.19.200.189.in-addr.arpa.
+imap.gmail.com.
+33.3.223.201.in-addr.arpa.
+hi-in.facebook.com.
+pinnacle-game-profiler.programas-gratis.net.
+i3.ytimg.com.
+jers3.info.
+www.google.com.
+cccam.fanhow.com.
+15.43.34.190.in-addr.arpa.
+92.5.157.201.in-addr.arpa.
+chrispiascik.com.
+ads.espn.adsonar.com.
+ueharlax.ac.uk.
+a.root-servers.net.
+www.shamiphotos.com.
+static.ak.fbcdn.net.
+themovieblog.com.woopra-ns.com.
+reddit.com.
+www.coisasfowfaxdolls1.weblogger.com.br.
+www.thedevilsprophet.com.
+photos-a.ak.fbcdn.net.
+ad.adperium.com.
+it-it.facebook.com.
+145.70.26.190.in-addr.arpa.
+196.141.0.82.in-addr.arpa.
+www.distintivoh.com.mx.
+blog.girvin.com.
+profile.ak.fbcdn.net.
+mtlm.com.
+156.46.129.190.in-addr.arpa.
+youtu.be.
+www.google-analytics.com.
+3c9bb231773af1ee4011006baf65584f.info.
+oo7rzs2in.m26p7a2j.
+162.144.111.193.in-addr.arpa.
+www.pdfsearchs.in.
+worker2.live.kng.wooga.com.
+a.root-servers.net.
+mailgate1.centura.org.
+i2.ytimg.com.
+cephey.ru.
+mail.vision-financial.net.
+a.root-servers.net.
+a.root-servers.net.
+cdnis2.cam4.com.
+140.79.149.190.in-addr.arpa.
+173.53.230.190.in-addr.arpa.
+www.5b5.info.
+a.root-servers.net.
+www.msn.com.
+profile.ak.fbcdn.net.
+photos.aaca.org.
+mt2.google.com.
+www.maroc.ma.
+connect.facebook.net.
+simba.region-alsace.fr.
+login.live.com.
+www.jakegarn.com.
+ct.buzzfeed.com.
+153.95.149.187.in-addr.arpa.
+87.198.114.87.in-addr.arpa.
+toolbarqueries.google.com.
+52.101.173.189.in-addr.arpa.
+xbgoficialx.e.channel.livestream.com.
+sabinashidalgo.net.
+weather.wapp.wii.com.
+msc.wlxrs.com.
+ajax.googleapis.com.
+ad.z5x.net.
+www.google.com.
+www.pinturasrodafuerte.com.
+static.ak.fbcdn.net.
+www.facebook.com.
+seastrikeboats.com.
+www.periodicos.capes.gov.br.
+tsm05.eset.com.
+41.235.177.190.in-addr.arpa.
+orangebowl.org.s5b1.psmtp.com.
+www.vivastreet.fr.
+i2.ytimg.com.
+orlandochristianprep.org.
+images04.olx-st.com.
+biomechanic-8001.deviantart.com.
+videoseyredin.blogspot.com.
+124.22.209.201.in-addr.arpa.
+translate.googleapis.com.
+20.127.26.92.in-addr.arpa.
+mc.smtp.gapm.ru.
+psgw.t-mobilesgws.com.
+pross.ru.
+twitter.com.
+s.ytimg.com.
+154.175.100.122.in-addr.arpa.
+54.214.85.209.bl.spamcop.net.
+a1408.w43.akamai.net.
+fbcdn-photos-a.akamaihd.net.
+a7.sphotos.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+ixbt.biz.
+creative.ak.fbcdn.net.
+143.132.100.128.in-addr.arpa.
+86.1.101.85.in-addr.arpa.
+255.46.0.10.in-addr.arpa.
+ssl.gstatic.com.
+14.200.172.190.in-addr.arpa.
+65.194.222.186.in-addr.arpa.
+bl121w.blu121.mail.live.com.
+loading5.widdit.com.
+199.114.22.186.in-addr.arpa.
+google.com.
+designcore.net.
+ci.beaverton.or.us.
+_307_76_9.
+cmcst.netmng.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+img713.imageshack.us.
+rentalpro.graco.com.
+dohacks.activo.ws.
+www.tuteleonline.com.
+141.61.154.186.in-addr.arpa.
+static.ak.fbcdn.net.
+n6cp.akamai.net.
+webmail.tx.rr.com.
+ns1.dvrtw.com.tw.
+metalmeltdown.forumotion.com.
+kc2xowt8w.91kn.
+buffalohair.wordpress.com.
+usequitymortgage.com.
+profile.ak.fbcdn.net.
+s.youtube.com.
+a1408.w43.akamai.net.
+www.imss.gob.mx.
+inbound.ksoft-us.com.netsolmail.net.
+erc.unesco.org.
+46.236.22.187.in-addr.arpa.
+sovetporemontu.ru.
+teredo.ipv6.microsoft.com.
+pimg.chulojuegos.com.
+photos-a.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+www.daisydiskapp.com.
+static.ak.fbcdn.net.
+208.161.75.190.in-addr.arpa.
+119.54.250.189.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+mail.novogen.com.
+169.231.52.186.in-addr.arpa.
+counterb.statcounter.com.
+aim.pubmatic.com.
+ws.pusherapp.com.
+s-external.ak.fbcdn.net.
+www.myfinepix.com.mx.
+www.euroresidentes.com.
+www.fwiluminacionsrl.com.ar.
+_967_39_1.
+a6.sphotos.ak.fbcdn.net.
+theprettypoppy1.blogspot.com.
+jump.eudora.com.
+www.sauerandsteiner.com.
+photos-h.ak.fbcdn.net.
+ad.afy11.net.
+merky.de.
+a7.sphotos.ak.fbcdn.net.
+scootersplanet.com.
+mx.excelsior.ru.
+youtube.com.
+63.38.19.93.in-addr.arpa.
+www.english-heritageshop.org.uk.
+213.110.193.190.in-addr.arpa.
+icy-veins.com.
+static.filestube.com.
+photos-g.ak.fbcdn.net.
+185.147.81.189.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+197.32.153.193.in-addr.arpa.
+_205_47_3.
+g.msn.com.
+readinghospital.org.
+masajes-spa-relax.blogspot.com.
+botones.blogalaxia.com.
+89.247.169.182.in-addr.arpa.
+twitter.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.lge.com.
+145.227.4.187.in-addr.arpa.
+91.103.172.201.in-addr.arpa.
+sdw.ru.
+www.hookedonads.com.
+40.131.207.190.in-addr.arpa.
+m.addthisedge.com.
+m.yahoo.com.
+www.ujenawholesale.com.
+photos-g.ak.fbcdn.net.
+cameronfarley.com.
+azimut.ru.
+photos-e.ak.fbcdn.net.
+72.10.184.187.in-addr.arpa.
+s.youtube.com.
+137.156.243.201.in-addr.arpa.
+ads.yimg.com.
+a.root-servers.net.
+5l28a:nai.38py.
+www.google-analytics.com.
+www.conduit.com.
+shared.live.com.
+aalweb.net.
+dbcs2.htc.com.
+www.eluniversal.com.mx.
+a.root-servers.net.
+nabillionaire.se.
+www.mangaexpress.net.
+apis.google.com.
+a4.sphotos.ak.fbcdn.net.
+www.citytoo.fr.
+personaltraining.com.
+www.meiosepublicidade.pt.
+warrantiedservices.com.
+static.gunggo.com.
+a4.sphotos.ak.fbcdn.net.
+p.ebaystatic.com.
+www.hangfan.co.uk.
+a3.sphotos.ak.fbcdn.net.
+ask.com.
+www.fa.
+g0.gstatic.com.
+146.48.192.187.in-addr.arpa.
+as.webmd.com.
+safebrowsing.clients.google.com.
+fotosyvideosdehombres.blogspot.com.
+mail.greenville.k12.mi.us.
+mail.rroom.net.
+61.116.191.186.in-addr.arpa.
+dirette.sport.repubblica.it.
+a.root-servers.net.
+xjp.couzens.com.
+pixel.facebook.com.
+grimreaperracing.com.
+cs9872.vk.com.
+registrardominios.com.mx.
+by2msg3020217.gateway.messenger.live.com.
+221.161.6.92.in-addr.arpa.
+hi-in.facebook.com.
+a.root-servers.net.
+feeds2.feedburner.com.
+abricos.com.ru.
+pagead2.googlesyndication.com.
+www.consultorioveterinariolalinea.com.
+www.artesaniaelsol.es.
+ask3.three.co.uk.
+gigamag.ru.
+welcome.hp-ww.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+translate.googleapis.com.
+mettlerpr.com.
+s10.histats.com.
+www.yogaartandscience.com.
+p61.badoo.com.
+a2.sphotos.ak.fbcdn.net.
+a1.mzstatic.com.
+time.chttl.com.tw.
+apis.google.com.
+ax.init.itunes.apple.com.
+51.3.254.94.in-addr.arpa.
+ad-g.doubleclick.net.
+ingdirect.com.au.
+mw2.google.com.
+0-jw-w.channel.facebook.com.
+hostgrantor.org.
+followgrame.uservoice.com.
+wbmsepo03.wb.ad.worldbank.org.
+unapzq.net.
+accounts.bioware.com.
+147.71.43.208.in-addr.arpa.
+www.match.com.akadns.net.
+94.220.144.189.in-addr.arpa.
+151.58.46.207.in-addr.arpa.
+valencia.infoisinfo.es.
+dns.msftncsi.com.
+216.224.194.117.in-addr.arpa.
+www.juicycloseups.com.
+appworld.blackberry.com.
+lineup.aclfestival.com.
+a7.sphotos.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+_394_89_8.
+www.m-m-monsterhive.net.
+www.photosthatchangedtheworld.com.
+a8.sphotos.ak.fbcdn.net.
+clients2.google.com.
+www.google-analytics.com.
+clients1.google.com.
+img211.imagevenue.com.
+nationalpropertyresearch.com.
+embed.bambuser.com.
+www.pspgo1.com.
+hotmail.com.
+www.ribamatic.com.
+7.170.220.201.in-addr.arpa.
+islamiskaforbundet.se.
+a5.sphotos.ak.fbcdn.net.
+www.sims3cheatsanddownloads.com.
+en-us.fxfeeds.mozilla.com.
+santacruz.patch.com.
+www.google.com.
+static.ak.fbcdn.net.
+sp.cwfservice.net.
+123.112.104.189.in-addr.arpa.
+tc.v1.cache3.c.pack.google.com.
+a.root-servers.net.
+rotativo.com.mx.
+_744_76_8.
+87.148.14.181.in-addr.arpa.
+static.ak.fbcdn.net.
+mx00.ev1.net.
+s-static.ak.fbcdn.net.
+197.220.157.190.in-addr.arpa.
+www.google.com.
+165.33.5.108.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+baymsg1030118.gateway.messenger.live.com.
+c7.zedo.com.
+pagead2.googlesyndication.com.
+125.6.157.201.in-addr.arpa.
+autocosmos.terra.com.ar.
+rya.kfmads.com.
+39.111.237.71.in-addr.arpa.
+snelsonlights.com.
+www.javiergomeznoya.com.
+www.ukrainedate.com.
+safebrowsing.clients.google.com.
+profile.ak.fbcdn.net.
+tracker.v4en.com.
+www.dees.com.
+mtalk.google.com.
+hipstercore.tumblr.com.
+www.annunci.ilfattoquotidiano.it.
+hpvf.com.
+101.64.232.118.in-addr.arpa.
+70.169.60.186.in-addr.arpa.
+a.root-servers.net.
+relay.kw.ua.
+plusone.google.com.
+146.17.194.190.in-addr.arpa.
+www.caixun.com.
+3ivx-mpeg-4.softonic.com.
+chegadebagunca.blogspot.com.
+246.112.11.173.in-addr.arpa.
+ofiodameada.blogspot.com.
+photos-e.ak.fbcdn.net.
+www.gstatic.com.
+www.hu.ikariam.com.
+142.101.230.190.in-addr.arpa.
+api.recaptcha.net.
+a4.mzstatic.com.
+87.178.141.190.in-addr.arpa.
+api.twitter.com.
+a996.mm1.akamai.net.
+static.ak.fbcdn.net.
+newsrss.bbc.co.uk.
+.
+a4.sphotos.ak.fbcdn.net.
+www.addicitivetips.com.
+elsietedias.com.
+www.cakespy.com.
+comtel-vologda.ru.
+www.carolynsandstrom.com.
+www.ameristarcasinos.com.
+sph3re.tv.
+200.77.112.190.in-addr.arpa.
+wpad.genzyme.com.
+a.root-servers.net.
+v5.cache3.c.youtube.com.
+apis.google.com.
+s0.2mdn.net.
+228.93.70.208.in-addr.arpa.
+ur.bestpicturesof.com.
+41.9.133.189.in-addr.arpa.
+developers.facebook.com.
+webmail.midtechnologies.net.
+static.dealply.com.
+api.geo.kontagent.net.
+psych.urbanup.com.
+en.wikipedia.org.
+signup.wazzub.info.
+exmail.sina.com.
+www.onlineweblibrary.com.
+155.26.6.186.in-addr.arpa.
+s-external.ak.fbcdn.net.
+activatunegocio.com.ar.
+photos-f.ak.fbcdn.net.
+u20.eset.com.
+43.138.13.163.in-addr.arpa.
+snippets.mozilla.com.
+latam.msn.com.
+1056349545.mail.outlook.com.
+www.facebook.com.
+www.facebook.com.
+bs.serving-sys.com.
+fvlpl9k13.07re.
+214.105.34.190.in-addr.arpa.
+a.root-servers.net.
+www.juegosyonkis.com.
+syria.com.
+163.62.109.200.in-addr.arpa.
+70.119.21.187.in-addr.arpa.
+lurkerfaqs.com.
+56.168.36.186.in-addr.arpa.
+_autodiscover._tcp.nsn.com.apac.nsn-intra.net.
+hallmarksuites.com.
+losmundosdepipi.blogspot.com.
+hotmail.com.
+www.wamagic.com.
+a-0.19-230f7081.a0f0131.1518.197c.3ea0.200.0.hch9ftcmi5jjvej61skj7km8di.avqs.mcafee.com.
+128.127.148.189.in-addr.arpa.
+www.chelseafc4arab.com.
+external.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+52.179.179.190.in-addr.arpa.
+svod.espn.go.com.
+img131.imagevenue.com.
+www.pspgo1.com.
+mail2.phorn.hu.
+media.io.
+a5.sphotos.ak.fbcdn.net.
+graph.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+31.146.3.190.in-addr.arpa.
+123.251.168.192.in-addr.arpa.
+billing.sharo4ka.ru.
+207.237.53.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+77btddl2z.62he.
+www.brooonzyah.net.
+2.bp.blogspot.com.
+dns.msftncsi.com.
+googleads.g.doubleclick.net.
+cdn.loading321.com.
+www.thesunblog.com.
+ns3-uk.rapidwaters.net.
+a.root-servers.net.
+kinsha.msk.ru.
+93.136.138.201.in-addr.arpa.
+s4.histats.com.
+aol.com.
+sp.cwfservice.net.
+w12.myzcm.com.
+graphic-hub.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+hahah.com.
+edge.quantserve.com.
+rv.ginyas.com.
+www.consumer.es.
+photos-b.ak.fbcdn.net.
+malcerkov.ru.
+87.142.80.186.in-addr.arpa.
+e3353.c.akamaiedge.net.
+checkip.dyndns.org.
+www.simplemachines.org.
+mail1.crum.com.
+mail.jakers.com.
+116.23.55.189.in-addr.arpa.
+nowthestoryismine.tumblr.com.
+d12.laserdiscs.biz.
+a1505.l.akamai.net.
+mitchell.k12.ga.us.s10a1.psmtp.com.
+_330_05_1.
+179.145.73.189.in-addr.arpa.
+i4.ytimg.com.
+static.ak.facebook.com.
+graph.facebook.com.
+a.root-servers.net.
+tcr.tynt.com.
+promo.profitsdeluxe.com.
+blazinglizard.com.
+.
+a.root-servers.net.
+photos-e.ak.fbcdn.net.
+www.google.com.
+dns.msftncsi.com.
+www.gstatic.com.
+data.flurry.com.
+wyatt.edisonproject.com.
+tag.admeld.com.
+developers.facebook.com.
+141.197.1.181.in-addr.arpa.
+mail.lmpcorp.com.
+26.114.71.70.in-addr.arpa.
+inbound.lanhambros.com.netsolmail.net.
+163.com.cn.
+itunes.apple.com.
+167.19.225.69.in-addr.arpa.
+dns.msftncsi.com.
+www.update.microsoft.com.
+gateway.arrail-dental.com.
+24.media.tumblr.com.
+gomarmaris.ru.
+195-async.olark.com.
+www.google-analytics.com.
+lqwutrysqwqonloy.biz.
+www.bluecoat.com.
+newideamebel.ru.
+www.alfaguara.com.
+www.tafe.swinburne.edu.au.
+_124_17_8.
+www.dondebuscarpareja.com.
+graph.facebook.com.
+support.mozilla.com.
+243.140.255.201.in-addr.arpa.
+253.135.11.83.in-addr.arpa.
+google.com.
+37.66.190.189.in-addr.arpa.
+64.45.141.201.in-addr.arpa.
+wd-edge.sharethis.com.
+secure.shared.live.com.
+76.255.26.201.in-addr.arpa.
+accounts.google.com.
+www.rotahavik.co.nz.
+z61phxecs.71bd.
+219.145.48.65.in-addr.arpa.
+api-read.facebook.com.
+169.154.79.200.in-addr.arpa.
+geo.tp-cdn.com.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+webcache.googleusercontent.com.
+habraham.com.
+mdk.com.ru.
+felafacs.org.
+coastalfloorcovering.com.
+www.facebook.com.
+drawn-reality.org.
+_998_39_5.
+_548_79_4.
+i-0.19-2709f081.83.1518.19d4.3ea1.410.0.wh287b8bvp1cg27mr4pzcu9n5t.avqs.mcafee.com.
+www.facebook.com.
+eros.21.ru.
+tnswfs03.siderca.techint.net.
+s.gravatar.com.
+133.19.206.187.in-addr.arpa.
+microbanc.com.
+mail.vegalab.ru.
+www.update.microsoft.com.
+static.ak.facebook.com.
+www.espressoandcream.com.
+sn106w.snt106.mail.live.com.
+9.182.62.187.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+zh-cn.facebook.com.
+137.106.136.123.in-addr.arpa.
+isohunt.com.
+136.203.42.177.in-addr.arpa.
+boygj.com.
+au.bartercard.net.
+www.maturetubevids.com.
+144.106.87.190.in-addr.arpa.
+wpad.domain.name.
+mail2.unisale.ru.
+www.cladead.com.
+169.40.96.94.in-addr.arpa.
+cdn.wibiya.com.
+safebrowsing.clients.google.com.
+urs.microsoft.com.
+mrbronco.xomba.com.
+www.ardeaprints.com.
+19.210.217.87.in-addr.arpa.
+carriesyabookshelf.blogspot.com.
+192.248.205.109.in-addr.arpa.
+4x4mecca.com.
+a3.sphotos.ak.fbcdn.net.
+cdn.feeds.videosz.com.
+mx.ptmail.sapo.pt.
+www.downtownwomenscenter.com.
+203.100.108.186.in-addr.arpa.
+yenibiris.com.
+ns202.vpsland.com.
+alexandraboigerillustration.blogspot.com.
+173.167.161.46.in-addr.arpa.
+chilihead.com.
+www.tutarotgratis.com.
+pagead2.googlesyndication.com.
+www.facebook.com.
+214.69.175.187.in-addr.arpa.
+orate.burlingtoncoatfactory.com.
+a.root-servers.net.
+eltiempodelaspalabras.blogspot.com.
+avgtechnologies.112.2o7.net.
+chistesbajosengrasas.blogspot.com.
+jxubvflympq.info.lan.
+samwep.info.
+www.kuzey-guney-son-bolum-izle.com.
+dns.msftncsi.com.
+126.159.54.83.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+plus.google.com.
+mail2.kgoc.com.
+google.com.
+www.afterfivedesigns.com.
+232.8.55.157.in-addr.arpa.
+continental.grupobbv.com.
+www.facebook.com.
+106.44.225.82.in-addr.arpa.
+cs5874.vkontakte.ru.
+lep113:en.e01b9e0f.
+mscrl.microsoft.com.
+_970_23_6.
+balticbereg.ru.
+ad.doubleclick.net.
+id.furud.net.
+www.bogotalacandelaria.com.
+dns.msftncsi.com.
+time-nw.nist.gov.
+mail.italyrealty.ru.
+sc1.rules.mailshell.net.
+gawker.com.
+www.nude-perfection.com.
+www.bestcelebstube.com.
+189.254.172.190.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+time.windows.com.
+41.115.115.174.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+grafiq.com.co.
+foros.esmas.com.woopra-ns.com.
+2.177.35.187.in-addr.arpa.
+7.4.f.e.7.c.4.4.0.e.f.0.b.3.8.2.d.f.9.7.5.f.e.5.0.0.0.0.1.0.0.2.ip6.arpa.
+186.34.133.186.in-addr.arpa.
+techproekt.ru.
+a.root-servers.net.
+b.scorecardresearch.com.
+img84.imageshack.us.
+photos-d.ak.fbcdn.net.
+www.styling-deluxe.com.
+tap2-cdn.rubiconproject.com.
+ihlc.udea.edu.co.
+connect.facebook.net.
+api2.4shared.com.
+www.symphonyspace.org.
+www.asmallorange.com.
+comcast.net.
+abercromb.ie.
+197.201.153.201.in-addr.arpa.
+wazetv.com.
+www.tarimziraat.com.
+162.252.212.200.in-addr.arpa.
+creative.ak.fbcdn.net.
+help.slideshare.com.
+descargas.muyzorras.com.
+googleads.g.doubleclick.net.
+www.alacered.com.
+a.root-servers.net.
+adsfront.iminent.com.
+www.bioetica.ufrgs.br.
+safebrowsing-cache.google.com.
+www.wtp101.com.
+a.root-servers.net.
+upay-cdn2.playspan.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.siteadvisor.com.
+wdphoto.com.
+ad.globaltakeoff.net.
+www.google.com.
+.
+mx-64-60-33-242.newhorizonspix.com.
+s-static.ak.facebook.com.
+www.chasingeyes.com.
+4.69.255.76.in-addr.arpa.
+20.30.212.186.in-addr.arpa.
+krmuevizk47gsp62nwf22lqd20bxbqgqlsi15.biz.
+diss.com.
+xpnd.se.
+www.eviews.net.
+120.129.211.201.in-addr.arpa.
+static.ak.fbcdn.net.
+csi.gstatic.com.
+static.ak.fbcdn.net.
+twitter.com.
+pixel.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+desktopworld.disqus.com.
+www.fr-reiki.com.
+a5.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+repository.arrow.nokia.com.
+logs9.contadorwap.com.
+static.ak.fbcdn.net.
+233.246.114.59.in-addr.arpa.
+mx.news.search.yahoo.com.
+a3.sphotos.ak.fbcdn.net.
+231.237.27.50.in-addr.arpa.
+faebook.com.
+187.82.203.108.in-addr.arpa.
+:ttvkpspd.95ma.
+apis.google.com.
+151.19.249.89.in-addr.arpa.
+13-courier.push.apple.com.
+tracker.publicbt.com.
+teredo.ipv6.microsoft.com.
+transas.ru.
+d1.apktops.com.
+137.7.82.200.in-addr.arpa.
+es.wikipedia.org.
+mail2.furamavietnam.com.
+wild-berries-dw.blogspot.com.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+regentgroup.ru.
+20minutos.feedsportal.com.
+pjcvlau57.15vi.
+www.topappsquare.com.
+www.youtube.com.
+110.84.240.190.in-addr.arpa.
+sp.cwfservice.net.
+www.sdrifter-nismoracing.blogspot.com.
+grids.heroku.com.
+profile.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+www.portaventura.co.uk.
+de-de.facebook.com.
+static.ak.fbcdn.net.
+clients1.google.com.
+www.progressiveseminars.com.
+22.202.146.187.in-addr.arpa.
+node1.ecogeek-cdn.net.
+206.73.77.188.in-addr.arpa.
+sytrus.programas-gratis.net.
+137.89.250.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+s3.amazonaws.com.
+www.facebook.com.
+jack-fx.com.
+sn2files.storage.msn.com.
+platform.twitter.com.
+rcp.na.blackberry.com.
+s0.2mdn.net.
+.
+236.154.247.190.in-addr.arpa.
+www.frenchonfire.fr.nf.
+u-smile-jb-y-tu.metroblog.com.
+tracker.mightynova.com.
+225.22.126.190.in-addr.arpa.
+gc.peachnet.edu.
+a3.sphotos.ak.fbcdn.net.
+barrowwhanley.com.
+billing.sharo4ka.ru.
+www.essayandscience.com.
+i3.ytimg.com.
+static.ak.fbcdn.net.
+a749.g.akamai.net.
+219.225.58.201.in-addr.arpa.
+trificient.net.
+i4.ytimg.com.
+fxfeeds.mozilla.com.
+211.158.216.201.in-addr.arpa.
+www.googleadservices.com.
+pappasitos.com.
+www.game-advertising-online.com.
+milyunanochesconmiada.blogspot.com.
+blog.geeksaresexytech.netdna-cdn.com.
+a.root-servers.net.
+148.150.62.189.in-addr.arpa.
+105.20.174.190.in-addr.arpa.
+dns.msftncsi.com.
+www.facebook.com.
+a.root-servers.net.
+ksn2-12.kaspersky-labs.com.
+pixel.facebook.com.
+tags.bluekai.com.
+180.51.5.116.in-addr.arpa.
+www.texasarchive.org.
+support.google.com.
+t1.gstatic.com.
+www.apple.com.
+c.brightcove.com.
+s-static.ak.facebook.com.
+82.25.71.190.in-addr.arpa.
+s-static.ak.facebook.com.
+mi.adinterax.com.
+a2.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+www.googletagservices.com.
+34.115.59.187.in-addr.arpa.
+gcrm.com.
+48.144.171.201.in-addr.arpa.
+birdsfod.blogspot.com.
+145.212.157.186.in-addr.arpa.
+hotmail.com.
+www.google.com.
+c-0.19-a30fa081.30081.1518.1998.3ea0.200.0.rqw7f386mgq5i2vj71kkslquhj.avqs.mcafee.com.
+202.221.104.189.in-addr.arpa.
+www.theglobeandmail.com.
+price-n.ru.
+ads.trafficjunky.net.
+130.228.172.94.in-addr.arpa.
+www.mittelstandswiki.de.
+www.divine.ca.
+www.google-analytics.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.cv.vic.gov.au.
+www.facebook.com.
+www.linkbucksmedia.com.
+fs727.filepost.com.
+sn1msg1020220.gateway.messenger.live.com.
+a328.da1.akamai.net.
+ingenieria-de-yacimientos.blogspot.com.
+191.96.141.201.in-addr.arpa.
+lyuag9n2a.01rf.
+a4.sphotos.ak.fbcdn.net.
+wzb8a81il.q63j8e6r.
+www.a10studio.net.
+ajax.googleapis.com.
+infonet.tomsk.ru.
+170.219.185.187.in-addr.arpa.
+elk.mazury.pl.
+geo.messenger.services.live.com.
+gmedical.org.
+tracker.piecesnbits.net.
+mscrl.microsoft.com.
+144.161.254.190.in-addr.arpa.
+9ts.ru.
+www.facebwook.com.
+50.152.255.201.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.savella.com.
+ssl.gstatic.com.
+a.root-servers.net.
+_641_51_8.
+a998.mm1.akamai.net.
+174.1.168.192.in-addr.arpa.
+cdn.optmd.com.
+affiliates.excelcalcs.com.
+a.root-servers.net.
+accounts.google.com.
+www.googleadservices.com.
+beharrygroup.com.
+www.mediafire.com.
+www.mandco.com.
+ntp.glb.nist.gov.
+1580thelight.com.
+www.facebook.com.
+skp.com.
+rcp.eu.blackberry.com.
+zulu.tweetmeme.com.
+opencourseware.kfupm.edu.sa.
+apps.bittorrent.com.
+www.spiritualgangster.com.
+njmcli.com.
+amor.org.
+www.divx-es.com.
+a.root-servers.net.
+www.amateursexmovs.com.
+zjgefordtex.en.alibaba.com.
+www.honawahonak.com.
+www.youtube.
+teredo.ipv6.microsoft.com.
+167.142.64.98.in-addr.arpa.
+157.222.160.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+developers.facebook.com.
+42.109.45.187.in-addr.arpa.
+9gag.com.
+www.queenkate.com.
+profile.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+www.delphigroups.info.
+www.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+csi.gstatic.com.
+ad.yieldmanager.com.
+poe.perl.org.
+dyvzcu.com.
+offer.ebay.com.
+www.youtube.com.
+148.120.20.187.in-addr.arpa.
+blog.theicecreamists.com.
+evsecure-ocsp.verisign.com.
+burtkunihonda.com.inbound15.mxlogic.net.
+www.fontanka.ru.
+secure.wlxrs.com.
+developers.facebook.com.
+view.atdmt.com.
+172.1.80.2.in-addr.arpa.
+google.com.
+www.vbeda.com.
+239.98.184.201.in-addr.arpa.
+www.download.windowsupdate.com.
+83.186.56.186.in-addr.arpa.
+www.zmtcdn.com.
+photos-f.ak.fbcdn.net.
+253.76.123.189.in-addr.arpa.
+factoryartists.com.
+66.116.233.123.in-addr.arpa.
+d7.zedo.com.
+3etk2jtug.50bo.
+www.facebook.com.
+www.wkc-collection.de.
+www.withoutabox.com.
+mailb.aljazeera.net.
+a5.sphotos.ak.fbcdn.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+finlandiacheese.com.
+62.216.156.189.in-addr.arpa.
+twitter.com.
+:vxtra9b:.d77r1d0e.
+greatinsurancejobs.com.s8b1.psmtp.com.
+www.htia.org.
+moillusions.us.intellitxt.com.
+photos-c.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+global.ard.yahoo.com.
+s1-powerpoint.vo.msecnd.net.
+231.234.16.62.in-addr.arpa.
+www.saintaquinas.com.
+_624_97_4.
+blog.livestation.com.
+dl29.hotgoo.com.
+mail2.glmshows.com.
+fxfeeds.mozilla.com.
+mesianicos.net.
+letgetmorefollowers.info.
+accounts.google.com.
+mx2.smtp.gru.net.
+epic.com.
+171.19.135.190.in-addr.arpa.
+groupusa.com.
+www.loureed.8k.com.
+a.root-servers.net.
+iphone-wu.apple.com.
+gbd3d9b9e6e334abf.api.playtomic.com.
+mail.des.org.ua.
+external.ak.fbcdn.net.
+www.facebook.com.
+www.google.com.
+www.editions-larousse.fr.
+pixel.quantserve.com.
+www.eluniversal.com.mx.
+t-otaku-m.com.
+profile.ak.fbcdn.net.
+hotmail.com.
+a.root-servers.net.
+219.186.56.78.in-addr.arpa.
+a.root-servers.net.
+es.wikipedia.org.
+r1-ads.ace.advertising.com.
+sportsbybrooks.com.
+flyingfish.co.nz.
+www.jpbuzz.com.
+www.myspace.com.
+mail.amvest.com.
+www.venesistemas.net.
+www.gstatic.com.
+215.45.54.125.in-addr.arpa.
+132.69.42.83.in-addr.arpa.
+www.ipc.org.kw.
+forum.avscripts.net.
+webmail.radiomaranon.org.pe.
+18.152.172.201.in-addr.arpa.
+static.ak.fbcdn.net.
+mail.bankmeta.com.
+bin-short.whatsapp.net.
+i6.tagstat.com.
+www.sd.xinhuanet.com.
+vrgw.komsco.com.
+115.189.201.190.in-addr.arpa.
+csi.gstatic.com.
+www.google.com.
+es.dofusmagazine.com.
+169.75.213.190.in-addr.arpa.
+cn1.redswoosh.akadns.net.
+a.root-servers.net.
+msc.wlxrs.com.
+www.ejuegosdeben10.com.
+ad.foxnetworks.com.
+connect.facebook.net.
+arsavage.com.
+12.157.210.201.in-addr.arpa.
+armdl.adobe.com.
+arosauto.no.
+matrixmtgloans.com.
+clients4.google.com.
+a1720.phobos.apple.com.
+login.yahoo.net.
+tron.softonic.com.
+infor.pl.
+242.253.54.60.in-addr.arpa.
+es.wikipedia.org.
+925.nl.
+98.194.114.177.in-addr.arpa.
+ibtikar.twofour54.com.
+hmh.org.
+144.162.24.46.in-addr.arpa.
+ad.amgdgt.com.
+dns.msftncsi.com.
+www.mynewsjapan.com.
+tt.net.
+i.ebayimg.com.
+www.soccerstand.com.
+24.103.18.186.in-addr.arpa.
+hr3ajvxpd.g34d5k9x.
+reviews.cnet.com.
+www.sexfilms.com.
+61.88.160.189.in-addr.arpa.
+www.robotadserver.com.
+pttimqfovlnunn.net.
+sonalisangbad.com.
+169.162.121.84.in-addr.arpa.
+www.precisioninstrument.es.
+crl.microsoft.com.
+:krboeduf.23mv.
+genesis.1337x.org.
+tc24.easythumbhost.com.
+dns.msftncsi.com.
+a.root-servers.net.
+denegday.ru.
+92.106.83.189.in-addr.arpa.
+dr._dns-sd._udp.0.70.16.172.in-addr.arpa.
+mailer1.tablogix.ru.
+s2.youtube.com.
+hhholmestesting.com.
+cdn.api.twitter.com.
+hotmail.com.
+yknet.com.
+c3v68bgyf.l39g3w6s.
+125.68.132.223.in-addr.arpa.
+preparadelcamino.blogspot.com.
+www.epsco-group.com.
+a.root-servers.net.
+geo.messenger.services.live.com.
+ark.switnet.org.
+sunoptics.com.
+mx.belkozin.com.
+243.184.52.186.in-addr.arpa.
+fldeadhead.com.
+8.4.236.88.in-addr.arpa.
+0.79.6.88.in-addr.arpa.
+nc:rlx7yl.09rb.
+40.71.21.201.in-addr.arpa.
+sdau2.sdau.edu.cn.
+google.com.
+mx-int.sama.ru.
+com.
+i4.ytimg.com.
+102.69.188.189.in-addr.arpa.
+163.53.177.78.in-addr.arpa.
+developers.facebook.com.
+sacla-tm.com.
+support.dtsearch.com.
+creative.ak.fbcdn.net.
+trksrv10.doublefusion.com.
+gfx2.hotmail.com.
+www.googleapis.com.
+90.52.107.189.in-addr.arpa.
+206.141.110.189.in-addr.arpa.
+pointsul.com.br.
+arsclassicacoins.com.
+creative.ak.fbcdn.net.
+cdn.babble.com.
+zartarco.com.cy.
+tracker.ccc.de.
+a3.sphotos.ak.fbcdn.net.
+bvva62627661.ns02.biz.
+www.textpad.com.
+principia-group.com.
+apps.facebook.com.
+110.188.231.190.in-addr.arpa.
+asktoolbar.weather.com.
+www.pktienda.es.
+images.apple.com.
+keglerbrown.com.
+ds.addthis.com.
+mangham.com.
+www.gladiatus.lv.
+www.readerswivesmovies.com.
+27.147.220.66.in-addr.arpa.
+9.71.184.201.in-addr.arpa.
+s.ytimg.com.
+mx2.adamant.ru.
+primped4.hcdn1.net.
+rpt.ladyfootlocker.com.
+www.adaptelec.com.
+253.17.231.201.in-addr.arpa.
+b-0.19-23091008.481.1518.19d0.3ea1.410.0.cnvnzfragmddpldidjatrqqfmj.avqs.mcafee.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cursos-blogger.blogspot.com.
+mailin-01.mx.aol.com.
+widget-36.slide.com.
+154.217.73.190.in-addr.arpa.
+pjsml.50megs.com.
+156.187.192.173.in-addr.arpa.
+www.googleadservices.com.
+52.77.75.200.in-addr.arpa.
+www.adobe.com.
+redsys.ru.
+www.habbo.es.
+www.dlink.com.
+massena.com.
+thecollectivereview.com.
+kidsalive.com.au.
+242.214.56.200.in-addr.arpa.
+wpad.ad.local.
+www.topappsquare.com.
+www.addthis.com.
+0-jg-w.channel.facebook.com.
+www.ashesh.com.np.
+sp.cwfservice.net.
+lazerit.com.
+www.facebook.com.
+s4.histats.com.
+bookzone4boys.blogspot.com.
+sc17.rules.mailshell.net.
+accounts.google.com.
+gs-loc.apple.com.
+169.166.59.186.in-addr.arpa.
+de-de.facebook.com.
+time.windows.com.
+jim6.mail.ru.
+2.m0n0wall.pool.ntp.org.
+blastmagazine.net.
+col.stc.s-msn.com.
+graph.facebook.com.
+mashable.com.
+api.facebook.com.
+bits.wikimedia.org.
+clients2.google.com.
+www.auntruthskitchen.com.
+safebrowsing.cache.l.google.com.
+js.wlxrs.com.
+time.chttl.com.tw.
+mail.echolabs.net.
+google.com.
+0-56.channel.facebook.com.
+meg.drs.ca.
+a.root-servers.net.
+www.weef2012.edu.ar.
+teknopanel.com.tr.
+safebrowsing.clients.google.com.
+radiusventures.com.s6a2.psmtp.com.
+a.root-servers.net.
+studiocavallleri.it.
+emmail.com.
+www.aboutoracleapps.com.
+a7.sphotos.ak.fbcdn.net.
+www.quranrabbi.com.
+0.11-2109e021.c0c10b3.1518.19b2.410a.400.9d.gdjs2rgdr2gsw4wia8nflr2dsb.avqs.mcafee.com.
+59.157.145.186.in-addr.arpa.
+pop3.hiway.co.uk.
+buscadorares.com.
+www.youtube.com.
+dingtao333.3322.org.
+conelsolenleo.blogspot.com.
+bit.ly.
+juegosiphone.org.
+www.facebook.com.
+190.66.224.190.in-addr.arpa.
+a1408.w43.akamai.net.
+laberintos.itam.mx.
+yovfk6xm:.s00r1e0x.
+new.digg.com.
+39.113.2.187.in-addr.arpa.
+102.38.8.82.in-addr.arpa.
+28.26.123.201.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+relay.pholding.ru.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+63.221.212.190.in-addr.arpa.
+sdc.oocl.com.
+external.ak.fbcdn.net.
+i2.ytimg.com.
+nobu.backup.com.
+ksn2-12.kaspersky-labs.com.
+tiff.net.
+assets.pinterest.com.
+96.102.70.77.in-addr.arpa.
+alperjcc.org.
+wirr.com.
+mail2.gicec.net.
+a4.sphotos.ak.fbcdn.net.
+uni-ins.ru.
+tvcomedies.about.com.
+www.sonymusic.it.
+g.ceipmsn.com.
+a276.phobos.apple.com.
+lovelythings.typepad.co.uk.
+config.messenger.msn.com.
+www.orizaba.gob.mx.
+ytebgv7or.48ti.
+tyther.attmail.com.
+latam.preciomania.com.
+pixel.facebook.com.
+lab.org.
+a2.twimg.com.
+skanar.sk.
+www.restauranticemachine.org.
+158.182.9.201.in-addr.arpa.
+docs.google.com.
+www.indulgecakes.co.za.
+fdsn0.skype.net.
+www.giardiasis.org.
+i4.ytimg.com.
+rimail.interlan.com.
+plastikote.com.
+mscrl.microsoft.com.
+www.chch.ox.ac.uk.
+www.bestotools.com.
+news.iks.ru.
+static2.consumerreportscdn.org.
+helium.lunarpages.com.
+27.252.0.72.in-addr.arpa.
+m.twitter.com.
+secure.wlxrs.com.
+astaro.district106.net.
+k14.kn3.net.
+www.canadapost.co.uk.
+open.pc120.com.
+verpelis.ne.
+www.jewish-greetings.com.
+ahoo.it.
+dns.msftncsi.com.
+scgi.ebay.com.au.
+a.root-servers.net.
+mediacom.com.s200a1.psmtp.com.
+mebel2006.ru.
+214.148.173.190.in-addr.arpa.
+google.com.
+a4.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+en.wikipedia.org.
+www.americas-fr.com.
+www.facebook.com.
+a.root-servers.net.
+mail.crmsei.com.
+safeguard.concentric.com.
+load.exelator.com.
+127.0.0.1.
+www.fotosmix.com.
+www.foroz.org.
+ads.lfstmedia.com.
+issworldhistory.forumotion.net.
+www.kuponvilag.hu.
+www.google-analytics.com.
+us.js.yimg.com.
+db._dns-sd._udp.lan.
+a.c-0.19-a30f7081.c110000.1518.19d4.3ea1.210.0.jtjwp6s1mrce8pabffnu48rjd6.avqs.mcafee.com.
+www.snaponequipment.com.
+g.ceipmsn.com.
+s03.radikal.ru.
+webmedia.hrblock.com.
+photos-a.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+124.248.174.189.in-addr.arpa.
+130.190.109.200.in-addr.arpa.
+asktoolbar.weather.com.
+rad.msn.com.
+26.171.152.189.in-addr.arpa.
+prof-soft.com.
+fbcdn-photos-a.akamaihd.net.
+www.skillsconverged.com.
+pix04.revsci.net.
+s.youtube.com.
+external.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+23.209.18.87.in-addr.arpa.
+54.110.69.174.in-addr.arpa.
+newsrss.bbc.co.uk.
+194.186.7.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+1stsmg.com.
+www.addthis.com.
+84.1.204.190.in-addr.arpa.
+ad3.liverail.com.
+highrollerlimo.com.
+www.fiscalia.com.
+speedsend.net.
+www.si-la.org.
+113.52.235.201.in-addr.arpa.
+0.11-230f8081.c120081.1518.18a6.3ea0.210.0.m6aph9nmfpfelks3u9ztjvkb9b.avqs.mcafee.com.
+cacs.net.
+dc427.4shared.com.
+static.ak.fbcdn.net.
+serv01.colo.owned.hu.
+e1.docs.yahoo.com.
+saturn.pcb-me.net.
+www.yele.org.
+www.google.com.
+muttski-software.com.
+221.199.72.46.in-addr.arpa.
+g.promosrv.com.
+dns.msftncsi.com.
+618connect.com.
+www.facebook.com.
+pagead.l.doubleclick.net.
+www.xtremenutrition.co.nz.
+es.dragonball.wikia.com.
+safebrowsing.clients.google.com.
+external.ak.fbcdn.net.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+edgfdpipm.y75o6k0q.
+mikkai.com.
+a.root-servers.net.
+www.videos-it.com.
+228.13.188.190.in-addr.arpa.
+google.com.
+207.154.199.213.combined.njabl.org.
+pagead2.googlesyndication.com.
+accounts.google.com.
+www.historiadeldibujo.com.
+sos19shei.z89v3j1f.
+okatrauzdws.info.
+www.gangbangcathy.com.
+st.plenomedia.com.
+rpz-dvb.ru.
+ads.eluniversal.com.mx.
+www.soharuni.net.
+fr-fr.facebook.com.
+ds.serving-sys.com.
+fbcdn-profile-a.akamaihd.net.
+a.root-servers.net.
+m.hotmail.com.
+keepmybooks.net.
+227.36.154.165.in-addr.arpa.
+pomol.ru.
+edge.quantserve.com.
+mail2.cherisundae.com.
+gamerrr.com.
+macsecrets.ru.
+www.facebook.com.
+photos-a.ak.fbcdn.net.
+d5nxst8fruw4z.cloudfront.net.
+www.glenngoodman.com.
+www.google.com.
+.
+www.co2trees.com.au.
+ritterbush.com.
+astore.amazon.com.
+creative.ak.fbcdn.net.
+distilleryimage6.instagram.com.
+tracker.anime-miako.to.
+kapsch.com.
+unil.ch.
+time.chttl.com.tw.
+webmoney26.ru.
+top.habbolibre.org.
+f4999.mail.yahoo.com.
+static.geewa.net.
+photos-f.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+urs.microsoft.com.
+v2.nonxt3.googlevideo.com.
+a8.sphotos.ak.fbcdn.net.
+secure.wlxrs.com.
+ib.adnxs.com.
+www.google.com.
+api-read.facebook.com.
+35.79.106.186.in-addr.arpa.
+partsurfer.hp.com.
+a.root-servers.net.
+bloodless.ru.
+capristan.com.
+ad.adtegrity.net.
+profile.ak.fbcdn.net.
+www.distrikayser.com.
+yahoo.com.
+161.28.92.186.in-addr.arpa.
+_914_05_5.
+a.root-servers.net.
+antonio-pernas.es.
+secure.wlxrs.com.
+teredo.ipv6.microsoft.com.
+www.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.prayertimes.net.
+dr._dns-sd._udp.0.44.16.172.in-addr.arpa.
+suicide-isnt-painful.piczo.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+168.221.154.190.in-addr.arpa.
+crl.microsoft.com.
+linkscorp.com.
+www.youtube.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+golem.pixar.com.
+50.235.51.90.in-addr.arpa.
+196.88.217.24.in-addr.arpa.
+www.facebook.com.
+s-static.ak.fbcdn.net.
+static.pulse360.com.
+www.tabrizcartoons.com.
+s.ytimg.com.
+127.49.54.65.in-addr.arpa.
+www.geckowood.com.
+whos.amung.us.
+www.jobmeeting.it.
+accounts.youtube.com.
+hyacinth.org.
+cncbt2.the9.com.
+c.atdmt.com.
+86.26.176.189.in-addr.arpa.
+mx2.capgemini.com.
+ad.smowtion.com.
+224.169.9.186.in-addr.arpa.
+9gv7xkt4n.73dg.
+www.google.com.
+www.koniambonickel.nc.
+bontel.ru.
+ar-ar.facebook.com.
+twitter.com.
+s7.addthis.com.
+197.3.167.190.in-addr.arpa.
+dietasecreta.com.
+a3.sphotos.ak.fbcdn.net.
+d7.zedo.com.
+www.hilive.tv.
+wasio.net.
+www.google-analytics.com.
+fortheywerefishers.com.
+toolbarqueries.google.com.
+a.root-servers.net.
+photos-f.ak.fbcdn.net.
+widgets.twimg.com.
+www.facebook.com.
+selendangrakyat.blogspot.com.
+vistahospitality.com.2.0001.arsmtp.com.
+136.255.100.190.in-addr.arpa.
+172.157.131.187.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+willeybrothers.com.
+photos-d.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+221.189.180.189.in-addr.arpa.
+h9mjcy742.m44w5m1y.
+profile.ak.fbcdn.net.
+worldpress.org.
+api.facebook.com.
+loading7.widdit.com.
+creative.ak.fbcdn.net.
+www.megafilex.com.
+sp.cwfservice.net.
+12.140.251.190.in-addr.arpa.
+thumbs2.ebaystatic.com.
+197.208.29.96.in-addr.arpa.
+videosonline.petardas.com.
+61.168.255.201.in-addr.arpa.
+a.root-servers.net.
+accounts.google.com.
+creative.ak.fbcdn.net.
+fpp.pt.
+www.google.com.
+pagead2.googlesyndication.com.
+a6.sphotos.ak.fbcdn.net.
+www.hotrecruit.com.
+xtaz.ru.
+bs.net.
+142.78.99.74.in-addr.arpa.
+gci.net.s6a2.psmtp.com.
+d1.openx.org.
+fbcdn-sphotos-a.akamaihd.net.
+unifi.
+cdn1.thumbnails.4tube.com.rncdn1.com.
+107.92.182.189.in-addr.arpa.
+i2.ytimg.com.
+sierraelpaso.com.s7b2.psmtp.com.
+furniturefromhome.com.
+115.120.52.186.in-addr.arpa.
+developers.facebook.com.
+ofertas-empleos.vivastreet.com.mx.
+cdn.contentspread.net.
+mytime.com.s7a1.psmtp.com.
+tr.adinterax.com.
+alcatraz.wikia.com.
+news.google.com.
+203.223.177.190.in-addr.arpa.
+www.facebook.com.
+www.pretenders.org.
+ajax.googleapis.com.
+newsrss.bbc.co.uk.
+udc.msn.com.
+www.loreal-paris.sk.
+fr.wikipedia.org.
+pandehigo.net.
+bit.ly.
+s-external.ak.fbcdn.net.
+linkhelp.clients.google.com.
+ssl.gstatic.com.
+cs10668.vk.com.
+www.printglobe.com.
+www.aerith.net.
+co108w.col108.mail.live.com.
+s-static.ak.fbcdn.net.
+stellar.mit.edu.
+a.root-servers.net.
+local-bay.contacts.msn.com.nsatc.net.
+msc.wlxrs.com.
+csi.gstatic.com.
+145.8.203.190.in-addr.arpa.
+a1408.w43.akamai.net.
+219.107.5.187.in-addr.arpa.
+boulder.craigslist.org.
+a4.sphotos.ak.fbcdn.net.
+jlawit.com.
+ttk.dp.ua.
+vp.sip.messenger.msn.com.
+db._dns-sd._udp.home.
+39.228.35.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+ranero.ru.
+main.dl.wu.akadns.net.
+149.251.50.85.in-addr.arpa.
+www.facebook.com.
+a.root-servers.net.
+codegeasstheanime.weebly.com.
+www.mdf.nl.
+4.bp.blogspot.com.
+a.root-servers.net.
+cdn8.evendor.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+46.223.183.189.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ubuntugeek.uk.intellitxt.com.
+www.google.com.
+i1.ytimg.com.
+x80.xanga.com.
+mspmx2.redzonetech.net.
+trafficpython.com.
+138.115.207.186.in-addr.arpa.
+225.15.220.189.in-addr.arpa.
+modulos.grupojoly.com.
+sqis.net.
+api.facebook.com.
+49.147.220.66.in-addr.arpa.
+www.facebook.com.
+1.2.168.192.in-addr.arpa.
+162.91.141.201.in-addr.arpa.
+206.56.59.186.in-addr.arpa.
+62.0.172.190.in-addr.arpa.
+gandco.net.
+www.securecheckout.billmelater.com.
+www.facebook.com.
+www.youtube.com.
+na-baltike.com.
+pointdistribution.com.
+rtv4xy81o.w00b6y0f.
+a3.sphotos.ak.fbcdn.net.
+freemail.baden.ch.
+124.213.34.186.in-addr.arpa.
+lh3.googleusercontent.com.
+www.eppingclub.com.
+safebrowsing-cache.google.com.
+masonresearch.gmu.edu.
+www.srpnet.com.
+blst.msn.com.
+www.facebook.com.
+164.10.222.189.in-addr.arpa.
+9x2sgie28.w78j4w9o.
+185.36.78.85.in-addr.arpa.
+aguasdecauri.blogspot.com.
+e3167.c.akamaiedge.net.
+a8.sphotos.ak.fbcdn.net.
+a1.da1.akamai.net.
+www.pressenza.com.
+profile.ak.fbcdn.net.
+unipamplona.edu.co.
+www.apple.com.
+dandreamz.wordpress.com.
+mail.jetter.com.
+rcboat.ru.
+204.136.232.92.in-addr.arpa.
+37.77.165.189.in-addr.arpa.
+a.root-servers.net.
+bs.serving-sys.com.
+profile.ak.fbcdn.net.
+p0b.ru.
+craigrichard.com.
+client-log.amazon.com.
+westcoastwine.net.
+d.monetate.net.
+news.ycombinator.com.
+photos-c.ak.fbcdn.net.
+icons.iconarchive.com.
+jimmyskillerprawns.za.net.
+40.209.162.217.in-addr.arpa.
+127.65.201.187.in-addr.arpa.
+a.root-servers.net.
+forum1.netgear.com.
+www.juegosus.com.
+www.pixazza.com.
+fo5kjln:7.h75n1q8y.
+pod.xxxmatch.com.
+www.facebook.com.
+148.42.26.190.in-addr.arpa.
+blog.gkelite.com.
+googlehosted.l.googleusercontent.com.
+www.tirada-tarot-gratis.eu.
+images.habbo.com.
+hello.home.
+mundochess.blogspot.com.
+www.bdhs.org.
+101.205.237.189.in-addr.arpa.
+a.root-servers.net.
+fw2a.synexagroup.com.
+profile.ak.fbcdn.net.
+40.178.27.190.in-addr.arpa.
+www.google-analytics.com.
+7.5.22.187.in-addr.arpa.
+bwnews.us.
+136.219.192.173.in-addr.arpa.
+a.root-servers.net.
+thelookingspoon.com.
+93.81.167.190.in-addr.arpa.
+apis.google.com.
+a8.sphotos.ak.fbcdn.net.
+mx.bgeeng.com.
+api.twitter.com.
+231.68.17.95.in-addr.arpa.
+elespejosabio.blogspot.com.
+a1.sphotos.ak.fbcdn.net.
+226.121.172.76.in-addr.arpa.
+youtu.be.
+www.wctravel.com.
+www.tlucretius.net.
+43.116.82.70.in-addr.arpa.
+time.chttl.com.tw.
+a.root-servers.net.
+feeds.vocegiallorossa.it.
+u2:ny8de8.81ck.
+administradorfinanciero.wordpress.com.
+mail.ic-sol.net.
+securepubads.g.doubleclick.net.
+gap.mx.contego.net.
+tc19.easythumbhost.com.
+photos-g.ak.fbcdn.net.
+86.17.162.189.in-addr.arpa.
+mail.ibahn.com.
+www.google.com.
+www.spicymother.com.
+siyavooshan.blogfa.com.
+am.renesas.com.
+i4.ytimg.com.
+cdn.api.twitter.com.
+_ldap._tcp.
+30.25.31.88.in-addr.arpa.
+cdn.gotraffic.net.
+creative.ak.fbcdn.net.
+shinebythree.com.
+interjet.com.mx.
+www-google-analytics.l.google.com.
+179.208.255.206.in-addr.arpa.
+apps.skype.com.
+a.root-servers.net.
+a.1.s50.avatar.zdn.vn.
+a4.sphotos.ak.fbcdn.net.
+197.205.0.210.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.news-leader.com.
+pimpdrop.com.
+es-es.facebook.com.
+768ujb:6r.12tq.
+www.shop-summerland.com.
+www.wired.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+rnd4.myphotos.cc.
+ptcscrutiny.com.
+116.192.210.201.in-addr.arpa.
+a.root-servers.net.
+digiphoto.thepodcastnetwork.com.
+www.kt2syggf436dtag641.com.
+a.root-servers.net.
+mail.arkay.com.
+img101.herosh.com.
+clients1.google.com.
+.
+53.21.0.192.in-addr.arpa.
+rinconakibareload.blogspot.com.
+a7.sphotos.ak.fbcdn.net.
+heartbeat.dm.origin.com.
+www.mozilla.com.
+eternallycool.net.
+bda.cwplc.com.s200a2.psmtp.com.
+matrix-ibs.com.inbound10.mxlogicmx.net.
+65.207.63.78.in-addr.arpa.
+bdieguez-photography.blogspot.com.
+www.marblas.es.
+benpelzel.com.
+_692_78_7.
+a4.sphotos.ak.fbcdn.net.
+search.iminent.com.
+apps.facebook.com.
+www.diccionariodesinonimos.es.
+a1.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+www.google.com.
+safebrowsing-cache.google.com.
+201.137.194.187.in-addr.arpa.
+andrea453301.spaces.live.com.
+.
+buenos-aires.nexolocal.com.ar.
+76.71.140.201.in-addr.arpa.
+sedqwickcms.com.
+www.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+google.com.
+mail.google.com.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+pc7.
+www.tifflove.com.
+centellazul68.blogspot.com.
+softonic-toolbar.softonic.com.
+store.yahoo.net.
+dnl-01.geo.kaspersky.com.
+downings.com.au.
+metalbastard.blogspot.com.
+ic.tynt.com.
+189.125.38.190.in-addr.arpa.
+www.scribd.com.
+74.42.58.186.in-addr.arpa.
+53.73.136.14.in-addr.arpa.
+168.51.168.192.in-addr.arpa.
+40.171.112.187.in-addr.arpa.
+hbfel6pyi.q03j9f8u.
+www.facebook.com.
+atg-ispf-ex1.altuwairqi.com.sa.
+apps.facebook.com.
+cafe-buffet.ru.
+ntl.westcall.ru.
+t2.gstatic.com.
+www.allsaints.com.
+reynoldspkg.com.
+ssl.gstatic.com.
+express-inventory.softonic.com.
+_579_79_0.
+hash.orbitdownloader.com.
+251.65.36.187.in-addr.arpa.
+googleads.g.doubleclick.net.
+193.135.246.201.in-addr.arpa.
+7.36.215.189.in-addr.arpa.
+americas.orangeadvertisingnetwork.com.
+sp.cwfservice.net.
+frajumar.com.
+33.27.233.96.in-addr.arpa.
+73.155.243.201.in-addr.arpa.
+www.facebook.com.
+www.google.com.
+22.190.169.89.in-addr.arpa.
+idcs.interclick.com.
+themeservice.ebuddy.com.
+avow.org.
+a.root-servers.net.
+artistxite.com.
+safebrowsing-cache.google.com.
+et4.xhamster.com.
+hotmail.com.
+110.135.157.189.in-addr.arpa.
+sippican.com.
+clients2.google.com.
+wadakk.com.
+hi-in.facebook.com.
+platform.twitter.com.
+a4.sphotos.ak.fbcdn.net.
+51.41.145.189.in-addr.arpa.
+152.255.103.85.in-addr.arpa.
+17.104.232.190.in-addr.arpa.
+it-it.facebook.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+pixel.facebook.com.
+accounts.google.com.
+a8.sphotos.ak.fbcdn.net.
+www.childcarelounge.com.
+ads.adxpansion.com.
+eventsforum.net.
+17.236.178.186.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+m.facebook.com.
+zimplestuff.com.
+amimichi.blogspot.com.
+a2.twimg.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+126.95.112.99.in-addr.arpa.
+fayans.ru.
+www.facebook.com.
+it-it.facebook.com.
+fbcdn-profile-a.akamaihd.net.
+3.99.218.186.in-addr.arpa.
+ajsfinefoods.com.
+comeonaussie.com.
+mail.friendimobile.com.
+newwest.net.
+mail.mc2mm.com.
+www.ebook.honglinhsoft.com.
+assets.mcity.digitalchocolate.com.
+mozilla.cdn.leaseweb.com.
+webres1.pand.ctmail.com.
+cdn1.widdit.com.
+20.29.158.200.in-addr.arpa.
+googleads.g.doubleclick.net.
+support.sherweb.com.
+es-la.facebook.com.
+cis.rv.ua.
+www.msftncsi.com.
+0-299.channel.facebook.com.
+crunchpost.com.
+_130_54_9.
+adam.com.au.
+189.206.160.201.in-addr.arpa.
+donbass.ua.
+119.30.39.70.in-addr.arpa.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+a.root-servers.net.
+aloha.viber.com.
+www.viptranny.com.
+photos-d.ak.fbcdn.net.
+ipm.bitdefender.com.
+customer.accord5.com.
+185.59.42.62.in-addr.arpa.
+laformarock.com.ar.
+www.usatoday.com.
+www.textsrv.com.
+photos-f.ak.fbcdn.net.
+ori.com.
+2.104.31.151.in-addr.arpa.
+a.root-servers.net.
+e906.g.akamaiedge.net.
+a8.sphotos.ak.fbcdn.net.
+stun.client.akadns.net.
+a8.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+ee.port.ac.uk.
+cookex.amp.yahoo.com.
+espanol.bestbuy.com.
+mail.zaprib.ru.
+a2.sphotos.ak.fbcdn.net.
+www.activistasporelclima.com.
+mail.tameerbank.com.
+mail.unomail.dk.
+glu.com.
+photos-g.ak.fbcdn.net.
+public.cwgdogp.com.au.
+www.almacendesentimientos.com.
+www.google.com.
+safebrowsing.clients.google.com.
+thestaticfanatic.blogspot.com.
+www.microsoft.com.
+122.166.183.189.in-addr.arpa.
+www.youtube.com.
+clients2.google.com.
+234.142.125.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+220.178.202.190.in-addr.arpa.
+1.158.9.186.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+bbs.sx128.com.
+clock.sjc.he.net.
+safebrowsing.clients.google.com.
+www.gloryholedatabase.com.
+_969_33_5.
+a1.sphotos.ak.fbcdn.net.
+chromejs.s3.amazonaws.com.
+profile.ak.fbcdn.net.
+oscararizaleon.lacoctelera.net.
+mail.marshallbros.com.
+newsrss.bbc.co.uk.
+rblns49.mailshell.net.
+creative.ak.fbcdn.net.
+1stclassmortgagenv.com.
+www.youtube.
+ye02.ru.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+yahoo.com.
+a.root-servers.net.
+blu131w.mail.live.com.akadns.net.
+sisviso.plades.org.pe.
+kh.google.com.
+smtp-out2.electric.net.
+fbcdn-profile-a.akamaihd.net.
+www.todoesoterico.com.
+assine.uol.com.br.
+ocsp.digicert.com.
+cgvrl1bit.60gz.
+mail.rock108.com.
+ct-miramar.com.
+es.tangeroutlet.com.
+www.motorcycletouringpro.com.
+secure.wlxrs.com.
+r._dns-sd._udp.lan.
+photos-g.ak.fbcdn.net.
+www.jscount.com.
+safebrowsing-cache.google.com.
+platform.twitter.com.
+accounts.youtube.com.
+clients1.google.com.
+atlasip.com.
+se.itunes.apple.com.
+nefertarisims3.webcindario.com.
+www.cervantesvirtual.com.
+ox-op.com.
+keelerbrass.com.
+mail.marrs-sevier.com.
+airewaves.com.
+www.facebook.com.
+cigarfar.dk.
+googel.com.
+s-static.ak.fbcdn.net.
+mx.yahoo.com.
+www.visitraleigh.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+googleads.g.doubleclick.net.
+landrys.com.
+origin.games.yahoo.net.
+wdg8bg1w2.l63q0n1r.
+in.yahoo.com.
+www.searchqu.com.
+www.facebook.com.
+mail2.tao.aoins.com.
+.
+map.czechtrade.net.
+www.facebook.com.
+mobillacura.wordpress.com.
+alternativelnok.blog.hu.
+platform.twitter.com.
+news-w0rlds.ru.
+photos-g.ak.fbcdn.net.
+www.soktelefonu.com.
+0-jj-w.channel.facebook.com.
+connect.facebook.net.
+geekmail.de.
+a7.sphotos.ak.fbcdn.net.
+sn3.mailshell.net.
+www.ciberdvd.com.
+cdnstatic.visualizeus.com.
+b-0.19-22090008.2020580.1518.19d4.3ea1.410.0.w63gpf5wia6jnshhq6na3bjhnj.avqs.mcafee.com.
+fbcdn-photos-a.akamaihd.net.
+mx.astrology.yahoo.com.
+fluxblog.org.
+1.130.26.174.in-addr.arpa.
+203.36.117.212.in-addr.arpa.
+r._dns-sd._udp.lan.
+150.20.141.201.in-addr.arpa.
+129.100.10.94.in-addr.arpa.
+mobth566.photobucket.com.
+40.153.155.85.in-addr.arpa.
+ib.adnxs.com.
+hosezup.net76.net.
+pirarucu.galeon.com.
+dns.msftncsi.com.
+www.homemademoviez.com.
+a3.sphotos.ak.fbcdn.net.
+www.jiayuan.com.
+196.111.133.190.in-addr.arpa.
+42.2.97.186.in-addr.arpa.
+97.68.230.189.in-addr.arpa.
+rcp.eu.blackberry.com.
+v7.nonxt7.c.youtube.com.
+ffupdate.engine.conduit-services.com.
+plusone.com.
+143.243.19.50.in-addr.arpa.
+friends.totallynsfw.com.
+www.facebook.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.aboutamanda.com.
+a3.sphotos.ak.fbcdn.net.
+mail.bmxx.ru.
+jo:ksvpu5.05eq.
+eye.wplus.net.
+www8.gamatar.org.
+a.root-servers.net.
+107.170.39.190.in-addr.arpa.
+rumboacanada.blogspot.com.
+ic.tynt.com.
+guru.avg.com.
+platform.twitter.com.
+mntr.babcdn.com.
+adele.wikia.com.
+hyrogifs.com.
+a7.sphotos.ak.fbcdn.net.
+www.hallofplay.com.
+z021.fma.fb.me.
+dns.msftncsi.com.
+a6.sphotos.ak.fbcdn.net.
+www.elationlighting.eu.
+img512.imageshack.us.
+98.73.235.189.in-addr.arpa.
+mx0.safarisolutions.xrbs.com.
+zbar2.zynga.com.
+s-static.ak.fbcdn.net.
+safebrowsing.cache.l.google.com.
+www.apple.com.
+worldwidereferrals.pro.
+26.67.139.189.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+dns.msftncsi.com.
+www.unique-wedding-rings.com.
+tip.tv.sohu.com.
+tudoparafotografia.blogspot.com.
+informsystems.ru.
+argo.sourceforge.net.
+www.tharmac.de.
+ib.adnxs.com.
+in.pod01.imht.udc2.mx.trendmicro.com.
+26.185.104.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+197.235.225.212.in-addr.arpa.
+190.148.114.190.in-addr.arpa.
+a.root-servers.net.
+storagenerve.com.
+safebrowsing-cache.google.com.
+www.apple.com.
+news.google.com.mx.
+exp01.eset.com.
+dltdirect.com.
+landonjacob.com.
+gdata.youtube.com.
+www.humorsearch.com.
+a.root-servers.net.
+wellspeyton.com.
+i.ytimg.com.
+dns.msftncsi.com.
+developers.facebook.com.
+dns.msftncsi.com.
+relay.bodaclick.com.
+153.104.212.186.in-addr.arpa.
+www.nycewheels.com.
+iowaelecom.net.
+profile.ak.fbcdn.net.
+ee.duke.edu.
+baymsg1020130.by2.gateway.edge.messenger.live.com.
+mt2furia.zapto.org.
+www.alec.co.uk.
+doportugalprofundo.blogspot.com.
+uk-mkivs.net.
+68.29.199.87.in-addr.arpa.
+13.165.217.217.in-addr.arpa.
+siaws.fotolog.com.
+l.yimg.com.
+pixel.rubiconproject.com.
+i845.photobucket.com.
+hansens.com.s7b1.psmtp.com.
+photos-a.ak.fbcdn.net.
+www.rhythmsdelmundo.com.
+itunes.apple.com.
+mail.google.com.
+lifestyle.msn.com.
+go.microsoft.com.
+asktoolbar.weather.com.
+wolfrunstudio.com.
+mccabepromo.com.
+www.youtube.com.
+neonco.spb.ru.
+26.239.138.200.in-addr.arpa.
+mayads.com.mail6.psmtp.com.
+i1.ytimg.com.
+quicktwist.wordpress.com.
+t0.gstatic.com.
+www.letusreason.org.
+cnfg.montiera.com.
+apps.facebook.com.
+www.kantarworldpanel.com.
+47.134.48.96.in-addr.arpa.
+i0.tagstat.com.
+www.ebonyvideosex.com.
+187.59.91.186.in-addr.arpa.
+156.233.35.187.in-addr.arpa.
+m.facebook.com.
+1.bp.blogspot.com.
+eduardolakatos.wordpress.com.
+edge.sharethis.com.
+uddjinz9k.73hr.
+rss.msnbc.msn.com.
+www.a-trust.at.
+tienda.tucanarias.com.
+www.catchyoutube.com.
+mail.avantek.net.
+www.youtube.com.
+www.ponyforums.com.
+145.89.245.88.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+titanium30-en.nfc.trendmicro.com.
+ajax.googleapis.com.
+12.59.16.206.in-addr.arpa.
+251.125.145.99.in-addr.arpa.
+xcite.com.
+m.paypal.com.
+wearebinary.com.
+114.104.243.201.in-addr.arpa.
+immanent-god-blues.blogspot.com.
+www.google-analytics.com.
+tcr.tynt.com.
+inbound.pulseniagara.com.netsolmail.net.
+236.45.149.83.in-addr.arpa.
+220.162.34.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+googleapis.l.google.com.
+profile.ak.fbcdn.net.
+_127_39_5.
+99.192.8.95.in-addr.arpa.
+mail.
+rs730l35.rapidshare.com.
+20minutos.feedsportal.com.
+isearch.babylon.com.
+www.ephenic.com.
+jahudka.zoner.com.
+www.facebook.com.
+www.uncut.at.
+locat.it.
+76.108.179.78.in-addr.arpa.
+www.tnpesu.org.
+crl.globalsign.net.
+pagead2.googlesyndication.com.
+_090_31_5.
+partner.googleadservices.com.
+www.moonbingo.net.
+www.google.com.
+gfx4.hotmail.com.
+a1.sphotos.ak.fbcdn.net.
+latareadeldormilon.blogspot.com.
+mfs.portvancouver.com.
+www.articuloz.com.
+mahjong-escape.programas-gratis.net.
+www.ashrae.org.
+photos-a.ak.fbcdn.net.
+clanbtl.ru.
+vucjumfrv.com.
+cultretro.com.
+reggaetonlivetv.metroblog.com.
+www.ciberia.es.
+sports-memorabilia.shop.ebay.co.uk.
+254.47.153.189.in-addr.arpa.
+hlfraas.com.
+g.ceipmsn.com.
+s0.2mdn.net.
+external.ak.fbcdn.net.
+adspro.ru.
+googleads.g.doubleclick.net.
+www.hemorrhoids.net.
+82.134.14.187.in-addr.arpa.
+lt1o:3zvk.q41g8n5t.
+localhost.
+smtp1.vwtus.com.
+photos-b.ak.fbcdn.net.
+158.17.20.187.in-addr.arpa.
+www.annonsera.se.
+a.root-servers.net.
+7.220.89.186.in-addr.arpa.
+210.194.141.201.in-addr.arpa.
+trollsmyth.blogspot.com.
+www.jpclatam.org.
+www.bandeapart.fm.
+93.69.231.190.in-addr.arpa.
+espanol.answers.yahoo.com.
+a1003.w41.akamai.net.
+scsa.msg.yahoo.com.
+loading2.widdit.com.
+www.goojue.com.
+www.mojo.co.uk.
+c7.zedo.com.
+www.kingsofnewyork.net.
+roynat.com.
+nerve.myyearbook.com.
+caughtbytheriver.net.
+jooble-cl.com.
+102.64.139.187.in-addr.arpa.
+facebook.com.
+mail.alkhalidgroup.com.
+statik.nanopress.it.
+mms501.whatsapp.net.
+www.masterhack.20m.com.
+s3.memberclicks.com.
+241.94.191.186.in-addr.arpa.
+166.134.44.92.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+armaaaniihd.blogspot.com.
+luxury-ideas.net.
+www.facebook.com.
+weather.services.conduit.com.
+jolis.worldbankimflib.org.
+www.capeplc.com.
+sp.cwfservice.net.
+download342.avast.com.
+234.7.91.76.in-addr.arpa.
+facer-ins.com.
+kenametal.com.
+event-horizons.com.
+www.google.com.
+157.131.75.70.in-addr.arpa.
+timer.od.ua.
+tms30.icrc.trendmicro.com.
+www.best-iphone-deals.co.
+norecipes.stumbleupon.com.
+masterconn11.qq.com.
+9.230.147.190.in-addr.arpa.
+105.63.67.77.in-addr.arpa.
+46.185.176.190.in-addr.arpa.
+.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.windowslivemessenger.com.
+enpointetechnologies.com.
+myspace.com.
+b-0.19-a3097008.40080.1518.19d3.3ea1.410.0.msu8df338qwi2hlvilc94zsp65.avqs.mcafee.com.
+old.houstontexans.com.
+t5.tagstat.com.
+to-god-mcsong.blogspot.com.
+a8.sphotos.ak.fbcdn.net.
+www.adobe.com.
+www.redestelecom.es.
+www.tusartistas.com.
+losmejoresjuegosymasjuegos.blogspot.com.
+231.100.208.190.in-addr.arpa.
+www.blogus.cl.
+bs.serving-sys.com.
+users.conduit.com.
+cocinandoconkari.blogspot.com.
+francistuttle.com.inbound10.mxlogic.net.
+a.root-servers.net.
+www.undp.uz.
+admcnt.tlt.ru.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+accounts.google.com.
+b-0.19-2109b008.11081.1518.19d4.2f4a.410.0.5dathp7t43621rr8uue53752ai.avqs.mcafee.com.
+newwavecomm.net.
+activmedia.com.inbound15.mxlogic.net.
+msgr.updates.yahoo.com.
+209.231.167.209.list.dsbl.org.
+photos-d.ak.fbcdn.net.
+www.videowish.com.
+catalysteval.com.
+a1515.phobos.apple.com.
+www.ewg.org.
+babybook.91.com.
+www.leecooperjeans.com.
+a.root-servers.net.
+hpw.com.s5a1.psmtp.com.
+itunes.apple.com.
+getmail.no.
+10.mal.de.dos.free.fr.
+37.12.137.187.in-addr.arpa.
+www.knightrideronline.com.
+google.com.
+114.38.173.190.in-addr.arpa.
+badoo.com.
+mgmt.beta.toolbar.msn.com.
+yahoo.co.in.
+mt0.google.com.
+1.bp.blogspot.com.
+steviadolce.com.py.
+isatap.home.
+a8.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+loading4.widdit.com.
+googleads.g.doubleclick.net.
+www.despegar.com.ar.
+bdrco.com.
+www.mosquelife.com.
+www.hotgirlstoys.com.
+waterwatcher.net.
+a4.sphotos.ak.fbcdn.net.
+aixpanish.com.
+cf.kampyle.com.
+cache.adm.cnzz.net.
+119.217.119.174.in-addr.arpa.
+productos.weboperador.com.ar.
+su.pctools.com.
+8.150.57.187.in-addr.arpa.
+16-courier.push.apple.com.
+mail.sfsustudentcenter.com.
+titanium30-en.url.trendmicro.com.
+stgeorges.org.nz.
+www.raunchygfs.com.
+a591.da2.akamai.net.
+_325_10_8.
+aasp.net.
+external.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+cust5812-1.in.mailcontrol.com.
+sexymalecelebrities.blogspot.com.
+e5237.g.akamaiedge.net.
+i4.ytimg.com.
+www.adobe.com.
+fengnet.com.
+a.root-servers.net.
+a.root-servers.net.
+interactive.rogers.com.
+0.244.115.186.in-addr.arpa.
+33.42.4.181.in-addr.arpa.
+www.maplegrovebarefootguy.com.
+pcdirectbiz.com.
+s0.2mdn.net.
+152.237.253.190.in-addr.arpa.
+guido.kcumb.edu.
+www.cfnmguide.com.
+psb.state.in.us.
+hinsay.com.
+csi.gstatic.com.
+www.makecitation.com.
+www.google.com.
+instagram.com.
+mscrl.microsoft.com.
+moycomputer.ru.
+33.54.78.201.in-addr.arpa.
+cjgarland.com.
+www.links4vids.com.
+safebrowsing.clients.google.com.
+m1.mx.km.ru.
+teredo.ipv6.microsoft.com.
+ksn2-12.kaspersky-labs.com.
+smtp.live.com.
+a5.sphotos.ak.fbcdn.net.
+107.43.150.46.in-addr.arpa.
+143.166.125.86.in-addr.arpa.
+rosems.culligan.com.
+cdn.fastclick.net.
+sp.cwfservice.net.
+hitachisoftware.ru.
+mx.youtube.com.
+gbc.net.
+a749.g.akamai.net.
+bmsismtp03.bmsi.a-star.edu.sg.
+s1-onenote.vo.msecnd.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+api.facebook.com.
+update.utorrent.com.
+switchboard.real.com.
+www.applifier.com.
+arriva.ch.
+www.vallarta.com.mx.
+redstarenergy.net.
+fastspeedtest.com.
+93.39.122.190.in-addr.arpa.
+samet-russia.ru.
+code.google.com.
+106.176.66.201.in-addr.arpa.
+www.resourcesforlife.com.
+sp.cwfservice.net.
+netaddess.org.
+robgijsberts.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+47.1.168.192.in-addr.arpa.
+clients1.google.com.
+graph.facebook.com.
+7sov1arhz.13tf.
+fr-fr.facebook.com.
+245.102.55.157.in-addr.arpa.
+www.arthurgarrosmusic.com.
+www.envioscristianos.com.
+56.236.201.190.in-addr.arpa.
+eteria.net.
+free3dstuff.net.
+94.58.21.62.in-addr.arpa.
+www.cellappsite.com.
+s.ytimg.com.
+evrokam.ru.
+ladywankenobi.tumblr.com.
+dtboot.orbitdownloader.com.
+146.57.50.190.in-addr.arpa.
+153.178.153.187.in-addr.arpa.
+gazsvyaz.ru.
+dns.msftncsi.com.
+robertdice.com.
+www.facebook.com.
+aresbykes.com.
+45.52.246.24.in-addr.arpa.
+socpixel.bidsystem.com.
+orcart.facebook.com.
+bl127w.blu127.mail.live.com.
+www.youtube.com.
+google.com.
+5ced.com.
+sl.iciba.com.
+us.fluke.com.
+s-static.ak.facebook.com.
+www.mlr360.com.
+www.gstatic.com.
+ingrealestate.co.uk.
+a.root-servers.net.
+apps.facebook.com.
+elithetrader.com.
+ifpexpo.com.
+a2.sphotos.ak.fbcdn.net.
+www.quienignora.com.
+inbound.fsro.net.netsolmail.net.
+www.ohso.co.
+sn2files.storage.msn.com.
+a761.phobos.apple.com.
+cnt.tuberwyn.com.
+www.cpdftraining.org.
+jers2.info.
+gfx3.hotmail.com.
+c.prodigy.msn.com.
+www.facebook.com.
+a.root-servers.net.
+237.23.95.59.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+rd.rlcdn.com.
+a3.sphotos.ak.fbcdn.net.
+141.159.222.201.in-addr.arpa.
+epsovirtual.umh.es.
+thenewgeneration.foroactivo.com.
+mail.softbal.com.
+mci.savetrees.com.
+s0.2mdn.net.
+teredo.ipv6.microsoft.com.
+ayudaparamiweb.com.
+218.22.105.190.in-addr.arpa.
+ad.yieldmanager.com.
+a.ads2.msads.net.
+134.90.88.186.in-addr.arpa.
+townofluray.com.
+thesaturnalia.com.
+213.241.143.187.in-addr.arpa.
+www.google.com.
+www.mccordweb.com.
+1.pool.ntp.org.
+pmx5.unina.it.
+tap2-cdn.rubiconproject.com.
+zh-cn.facebook.com.
+www.oberholtzer-creative.com.
+207.205.71.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+blog.taguin.com.
+a2.sphotos.ak.fbcdn.net.
+google.com.
+rospres.com.
+www.adventuresinexpatland.com.
+221.101.113.189.in-addr.arpa.
+enyce.com.
+a2.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+98.4.205.190.in-addr.arpa.
+www9.effectivemeasure.net.
+pandorafb2.dk.
+lyonsautobody.com.
+157.4.55.67.in-addr.arpa.
+nr.myhost.ru.
+www.microsofttranslator.com.
+rizalmanibrahim.blogspot.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+google.com.
+lh6.ggpht.com.
+news.google.com.mx.
+www.coalitionofresistance.org.uk.
+206.54.115.186.in-addr.arpa.
+171.112.47.189.in-addr.arpa.
+a3.mzstatic.com.
+mtmi.net.
+32.125.17.31.in-addr.arpa.
+19.8.17.177.in-addr.arpa.
+s-external.ak.fbcdn.net.
+22.210.13.189.in-addr.arpa.
+evolutionworld.ru.
+a3.sphotos.ak.fbcdn.net.
+m.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+actorguide.org.
+photos-d.ak.fbcdn.net.
+200.126.247.190.in-addr.arpa.
+i4.ytimg.com.
+www.marsrecruitment.com.au.
+pixel.facebook.com.
+htcmovilperu.com.
+apps.facebook.com.
+www.mindmapper.com.
+friendscot.fsnet.co.uk.
+college.harvard.edu.
+mail.google.com.
+sahil-tech.blogspot.com.
+local-sn.contacts.msn.com.
+star.facebook.com.
+www.facebook.com.
+machens.com.
+www.google.com.
+content.yieldmanager.edgesuite.net.
+wxdata.weather.com.
+waykiria.hacerforos.com.
+bl159w.blu159.mail.live.com.
+247.113.103.2.in-addr.arpa.
+ns.sympatico.ca.
+wuntvor.pillar.com.
+www.eprensa.info.
+www.google.com.
+sfr.fr.
+mailproxy.durmusoglu.de.
+laurierelectric.ca.
+ns3.afroasia.ru.
+ganarporinternet.es.
+124.110.193.200.in-addr.arpa.
+67.165.48.190.in-addr.arpa.
+static.ak.fbcdn.net.
+8.62.222.189.in-addr.arpa.
+98.119.59.186.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+140.96.84.188.in-addr.arpa.
+18-courier.push.apple.com.
+rxhub.com.
+dreamers1.com.
+www.juegosdcocina.com.
+images.redflagdeals.com.
+38.147.220.66.in-addr.arpa.
+mx10.comparex-group.com.
+photos-d.ak.fbcdn.net.
+cs6083.vkontakte.ru.
+www.australia-alternativa.com.
+a3.sphotos.ak.fbcdn.net.
+k-swiss.com.s10b2.psmtp.com.
+apis.google.com.
+toorgle.com.
+r.mzstatic.com.
+www.facebook.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b._dns-sd._udp.0.55.211.10.in-addr.arpa.
+mail.nisursystems.com.
+s-static.ak.facebook.com.
+mail2.tcu.edu.tw.
+108.214.176.190.in-addr.arpa.
+translate.google.com.
+finance.google.com.
+search.twitter.com.
+img4-fotki.yandex.net.
+www.centcom.mil.
+129.205.53.70.in-addr.arpa.
+113.134.67.108.in-addr.arpa.
+mail.kwrtools.com.
+0-jf-w.channel.facebook.com.
+ircai.files.wordpress.com.
+_ldap._tcp.
+mail.lebelier.com.
+videopeeg.wordpress.com.
+mailbox.riga.lv.
+a4.sphotos.ak.fbcdn.net.
+serv.vip.qiyi.com.
+duscholux.de.
+x-developer.ru.
+13.203.221.190.in-addr.arpa.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+external.ak.fbcdn.net.
+www.iceage3.es.
+secure.wlxrs.com.
+.
+dns.msftncsi.com.
+iolfree.net.
+www.marcelamosca.com.ar.
+www.fuedin.org.
+ksn4.kaspersky-labs.com.
+15.236.245.189.in-addr.arpa.
+www.facebook.com.
+cmap.dc.ace.advertising.com.
+.
+cm.g.doubleclick.net.
+aleluya.com.
+valleysystem.com.
+s0.2mdn.net.
+cnavideo.cna.com.tw.
+api.facebook.com.
+en.wikipedia.org.
+klty.com.s7a1.psmtp.com.
+horoscopo.msn.es.
+angusbarn.com.s7a1.psmtp.com.
+elegantwooddesign.com.
+29.126.100.190.in-addr.arpa.
+estheticcore.com.
+66.13.248.190.in-addr.arpa.
+208.33.89.187.in-addr.arpa.
+apple.imap.mail.yahoo.com.
+27-courier.push.apple.com.
+a.root-servers.net.
+3l2ktck58.w08e9t2w.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ecn.t2.tiles.virtualearth.net.
+pt-br.facebook.com.
+a.root-servers.net.
+196.45.168.189.in-addr.arpa.
+202.124.149.186.in-addr.arpa.
+ny01sec007.mhc.mhc.
+2.6.3.188.in-addr.arpa.
+marv.mediatti.net.
+ib.adnxs.com.
+.
+www.kyu-jong.com.
+www.elizabethperry.com.
+www.chinesedragon.org.
+www.coet.es.
+sl.srcs.k12.ca.us.
+usctap3132.amer.schp.com.
+sudddenlink.net.
+profile.ak.fbcdn.net.
+www.google.com.
+166.10.168.192.in-addr.arpa.
+appleghost.deviantart.com.
+platform.twitter.com.
+external.clearchannel.com.
+185.176.88.186.in-addr.arpa.
+three-lakes.org.
+olivus.com.
+ad.yieldmanager.com.
+sonyla.112.2o7.net.
+static.ak.fbcdn.net.
+a.c-0.19-270f1000.c8b0091.1518.19b2.410a.400.9d.digvq3kjc8aazhra2vgn3zbigb.avqs.mcafee.com.
+ptc68.com.
+abycom.com.
+almojilgroup.com.
+people.iola.dk.
+photos6.pop6.com.
+205.212.142.190.in-addr.arpa.
+216.135.32.114.in-addr.arpa.
+e3821.c.akamaiedge.net.
+nogu.net.
+24.236.184.187.in-addr.arpa.
+99.152.104.187.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+ar.msn.com.
+fuelly.com.
+18.163.71.109.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+www.extremetube.com.
+m9exek:8f.j81a0l0i.
+intfrog.com.
+payrollnetwork.com.pri-mx.na0100.smtproutes.com.
+pop.linkservice.cl.
+a2.sphotos.ak.fbcdn.net.
+graph.facebook.com.
+251.249.179.118.in-addr.arpa.
+api.twitter.com.
+platform.ak.fbcdn.net.
+www.facebook.com.
+24.85.88.186.in-addr.arpa.
+hanusch.de.
+udc.msn.com.
+yahoo.com.
+download.windowsupdate.com.
+s-static.ak.fbcdn.net.
+bsf-01.sonnit.dk.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cdn.cpmstar.com.
+mtalk.google.com.
+136.16.118.200.in-addr.arpa.
+injesus.com.
+www.facebook.com.
+rcp.eu.blackberry.com.
+www.acousticmagazine.com.
+philwest.net.
+118.24.184.201.in-addr.arpa.
+t2.gstatic.com.
+148.147.82.200.in-addr.arpa.
+www.google.com.mx.
+www.usabledomainname.com.
+d2058628.instant.xoom.it.
+profile.ak.fbcdn.net.
+82.137.164.187.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+fbcdn-photos-a.akamaihd.net.
+secure.gravatar.com.
+sp.cwfservice.net.
+drm.mail.universal-music-services.de.
+trebaruna-lacocinademaria.blogspot.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cn1.redswoosh.akadns.net.
+a1108.da1.akamai.net.
+www.estadionacional.com.pa.
+a7.sphotos.ak.fbcdn.net.
+17.106.36.177.in-addr.arpa.
+t2.gstatic.com.
+platform.twitter.com.
+ajax.googleapis.com.
+www.justasiansluts.com.
+g.msn.es.
+6.99.19.46.in-addr.arpa.
+mail.penza-gorod.ru.
+200.108.145.89.in-addr.arpa.
+support.google.com.
+ns1.serverdns9.net.ru.
+fxfeeds.mozilla.com.
+www.google.com.
+time.chttl.com.tw.
+159.49.54.65.in-addr.arpa.
+www.xatech.com.
+167.101.179.190.in-addr.arpa.
+api.facebook.com.
+taoyt.ru.
+a.root-servers.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+trans-p2p.pandora.tv.
+photos-a.ak.fbcdn.net.
+spiderbites.about.com.
+www.adobe.com.
+ylxfavku5.49bm.
+dns.msftncsi.com.
+alumni.academyart.edu.
+fxfeeds.mozilla.com.
+developers.facebook.com.
+heritagebankofcommerce.com.
+s-static.ak.facebook.com.
+news.google.com.mx.
+images04.olx.com.
+videochat.sadismoxxx.com.
+gfx4.hotmail.com.
+a5.sphotos.ak.fbcdn.net.
+fr-fr.facebook.com.
+216.45.130.189.in-addr.arpa.
+vtaig.com.
+vywl6mish.28wx.
+digini.com.
+partners.poa.com.
+mystery-case-files-huntsville.softonic.com.
+mxproc.iseek.com.au.
+weather.wdtinc.com.
+ja-jp.facebook.com.
+233.7.249.189.in-addr.arpa.
+a.root-servers.net.
+116.59.34.212.in-addr.arpa.
+s430.photobucket.com.
+apps.facebook.com.
+russiansilver.ru.
+dc265.4shared.com.
+i2.ytimg.com.
+wp.bingvision.ar.glbdns.microsoft.com.
+utmtrk9.apn.ask.com.
+72.32.214.121.in-addr.arpa.
+static.ak.fbcdn.net.
+187.123.172.186.in-addr.arpa.
+developers.facebook.com.
+vn61ka3ch.p80m8q3l.
+spacm1.spac.spc.com.
+virtuosasetalentosas.blogspot.com.
+www.nissanplatina.com.mx.
+30.193.140.175.in-addr.arpa.
+s-static.ak.fbcdn.net.
+ns2.sparknet.net.
+assets.hi5.com.
+a6.sphotos.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+www.google.com.
+api.zynga.com.
+yahoo.com.
+blackfolkshair.net.
+mail.shogun.kiev.ua.
+a.root-servers.net.
+magicard.ru.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+searchclient.live.net.
+tx61opmwf.56lq.
+34.42.143.94.in-addr.arpa.
+158.77.123.189.in-addr.arpa.
+msc.wlxrs.com.
+e-items.com.
+58.10.173.190.in-addr.arpa.
+pixel.facebook.com.
+evsecure-ocsp.verisign.com.
+apis.google.com.
+a.root-servers.net.
+l.yimg.com.
+i2.ytimg.com.
+www.eluniversaldf.mx.
+www.chinamextrading.com.
+44.99.9.69.in-addr.arpa.
+ocsp.thawte.com.
+smtpmoko.sensoplan.com.
+static.ak.fbcdn.net.
+ars.oscar.aol.com.
+titanium30-en.url.trendmicro.com.
+submitworld.com.
+fcu.edu.
+g.microsoft.com.
+a.root-servers.net.
+banners3.spacash.com.
+zip.rincondelvago.com.
+a6.sphotos.ak.fbcdn.net.
+195.113.232.190.in-addr.arpa.
+fondos-de-crepusculo.softonic.com.
+penn.museum.
+it-it.facebook.com.
+galleries2.adult-empire.com.
+www.homeopatia-si.es.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.ucgs.com.ar.
+www.michaelpage.co.za.
+.
+adfarm.mediaplex.com.
+a.root-servers.net.
+dsn10.d.skype.net.
+adpgs9-bond0-3.jagex.com.
+ns2.tmag.de.
+bs.wikipedia.org.
+photos-f.ak.fbcdn.net.
+wyndhamworldwide.com.s8b2.psmtp.com.
+external.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+cs5590.vkontakte.ru.
+heybubbles.blogspot.com.
+wellsforgo.com.
+cs.wikipedia.org.
+webcache.googleusercontent.com.
+www.google.com.
+xm5oznl1b.g66h4b1o.
+s.youtube.com.
+vefwefwl1.65qk.
+i1.ytimg.com.
+warmingglow.uproxx.netdna-cdn.com.
+47.75.45.190.in-addr.arpa.
+dbcs1.htc.com.
+cdn.wibiya.com.
+belltowercourtyard.com.
+a-0.19-22097089.c030082.1518.19d3.3ea1.210.0.4bsgrcqmg7g9sjl34dbjsln36i.avqs.mcafee.com.
+summergirlz.net.
+evsecure-ocsp.verisign.com.
+s.ytimg.com.
+6-courier.push.apple.com.
+a6.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+a.root-servers.net.
+www.grupoandroid.com.
+a7.sphotos.ak.fbcdn.net.
+bintobottle.com.
+www.topcydiaapps.com.
+teredo.ipv6.microsoft.com.
+22.22.191.79.in-addr.arpa.
+nevada.unr.edu.
+spanish.dictionary.com.
+xmsecu.com.
+carrerasdemontana.wordpress.com.
+www-cctld.l.google.com.
+s0.2mdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+133.85.74.75.in-addr.arpa.
+112.69.220.95.in-addr.arpa.
+cvssystems.com.
+www.esurance.com.
+media2.myfoxny.com.
+s1-powerpoint.vo.msecnd.net.
+g4nij4dce.q65m4p1a.
+xmest.ru.
+157.20.139.190.in-addr.arpa.
+253.111.146.189.in-addr.arpa.
+img32.imageshack.us.
+www.dustloop.com.
+cdn.api.twitter.com.
+city.kherson.ua.
+api.twitter.com.
+inentertainment.disqus.com.
+xlab-0.ed.ac.uk.
+dawgbusiness.blogspot.com.
+miriamyeung.com.tw.
+s-static.ak.fbcdn.net.
+214.239.29.190.in-addr.arpa.
+www.attractivemoms.com.
+127.128.77.77.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+22.58.16.75.in-addr.arpa.
+aljazeera.net.
+94.219.111.189.in-addr.arpa.
+vexcorp.com.
+45.211.42.181.in-addr.arpa.
+249.146.84.188.in-addr.arpa.
+a995.mm1.akamai.net.
+183.84.149.187.in-addr.arpa.
+www.facebook.com.
+ksn1-11-part2.kaspersky-labs.com.
+nds2.nokia.com.
+159.106.45.190.in-addr.arpa.
+www.facebook.com.
+170.160.85.209.in-addr.arpa.
+static.ak.facebook.com.
+100.146.220.66.in-addr.arpa.
+download349.avast.com.
+origin-sp.ask.com.
+santander.cz.
+zonavi.com.
+apps.facebook.com.
+16.0.0.10.in-addr.arpa.
+www.coffeybuzz.com.
+xbzsjhgf7.62dp.
+fbcdn-photos-a.akamaihd.net.
+profile.ak.fbcdn.net.
+traductor.babylon.com.
+paloaltoinc.com.
+goku.brightcove.com.
+33.152.78.186.in-addr.arpa.
+by2msg4010509.gateway.messenger.live.com.
+emka.info.
+static.ak.fbcdn.net.
+cvtrucking.com.
+profile.ak.fbcdn.net.
+www.youtube.com.
+blog.myfuncards.com.
+photos-c.ak.fbcdn.net.
+118.97.1.181.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+lv.wikipedia.org.
+b-0.19-2109d809.5c0.1518.19d4.3ea1.410.0.dspijfrbvp4pa13bjgir5n38l6.avqs.mcafee.com.
+external.ak.fbcdn.net.
+218.85.57.187.in-addr.arpa.
+medicalblog.info.
+175.102.16.186.in-addr.arpa.
+styx.aw.net.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+shared.live.com.
+141.212.222.201.in-addr.arpa.
+i4.ytimg.com.
+relink.net.
+profile.ak.fbcdn.net.
+netvogator.com.
+mail2.agsworld.com.
+sites.google.com.
+93.224.191.79.in-addr.arpa.
+dsiserver.daystarsills.com.
+www.proargentina.gov.ar.
+s3.amazonaws.com.
+epix.xbox.com.
+livelifehappy.com.
+secure.shared.live.com.
+rookiemag.com.
+external.ak.fbcdn.net.
+mail.livotour.ru.
+th605.photobucket.com.
+orcart.facebook.com.
+demakova.net.
+configuration.apple.com.
+ldsqoigrp.l46s6s1m.
+idi-online.com.
+www.websitevaluebot.com.
+a2.sphotos.ak.fbcdn.net.
+yargroup.ru.
+www.oynabitir.com.
+photos-f.ak.fbcdn.net.
+lordkat.com.
+us.bc.yahoo.com.
+www.gillbreathing.com.
+a1.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+h.live.com.
+photos-b.ak.fbcdn.net.
+www.largodrive.com.
+www.facebook.com.
+audiblox.com.
+183.24.92.186.in-addr.arpa.
+a.root-servers.net.
+medals.moshimonsters.com.
+asktoolbar.weather.com.
+profile.ak.fbcdn.net.
+l.betrad.com.
+mob.adwhirl.com.
+205.241.74.190.in-addr.arpa.
+i4.ytimg.com.
+bannerassets.universalstudios.com.
+g.microsoft.com.
+26.250.158.189.in-addr.arpa.
+6-courier.push.apple.com.
+pool.ntp.org.
+14pbzarqh.16xr.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx.nrgsys.it.
+www.salsas.com.au.
+latinworks.com.
+www.socialgrowthtechnologies.com.
+www.bing.com.
+u20.eset.com.
+www.ftdimarketplace.com.
+luisaalexandramarques.blogspot.com.
+www.17tahun.com.
+www.majalisna.com.
+83.58.250.201.in-addr.arpa.
+multi76.thumb.edenflirt.com.
+5.38.168.192.in-addr.arpa.
+masholdings.com.
+s7.addthis.com.
+www.hardfest.com.
+wqlt5kt8b.h41d4z5a.
+185.132.174.118.in-addr.arpa.
+mail.isure.ca.
+www.sarayacdn.com.
+102.20.38.190.in-addr.arpa.
+84.112.240.189.in-addr.arpa.
+246.161.10.186.in-addr.arpa.
+eymuaqjzd20otpsfypymsjuirhxgud10nx.ru.
+ad.yieldads.com.
+159.140.237.87.in-addr.arpa.
+ax.init.itunes.apple.com.
+inbound.orionpress.com.netsolmail.net.
+gqepy2rg2.t33f2k3e.
+a5.sphotos.ak.fbcdn.net.
+img1.artron.net.
+login.toolbar.conduit-services.com.
+orlandoluispardolazo.blogspot.com.
+accounts.google.com.
+photos-e.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+forumdocumentos.blogspot.com.
+localhost.
+mail.cyberriver.net.
+d2094137.xoom.it.
+googleads.g.doubleclick.net.
+www.dogbreedinfo.com.
+mail1.ci.methuen.ma.us.
+www.circsource.com.
+ediscovery.com.
+so.ie.sogou.com.
+i2.ytimg.com.
+ads.bluelithium.com.
+died.org.ru.
+hivhotline.ru.
+190.109.114.97.in-addr.arpa.
+pech.elektra.ru.
+coneltiempoenmisbrazos.blogspot.com.
+yahoo.com.
+i3.ytimg.com.
+reztec.ru.
+svrintl-g3-crl.verisign.com.
+91.178.81.82.in-addr.arpa.
+228.235.116.93.in-addr.arpa.
+232.87.232.190.in-addr.arpa.
+academy.shoplocal.com.
+a.root-servers.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+maps.gstatic.com.
+api.zynga.com.
+55.15.194.190.in-addr.arpa.
+www.kci-world.com.
+40.7.223.201.in-addr.arpa.
+www.nuevodiarioweb.com.ar.
+img121.imageshack.us.
+36.74.42.114.in-addr.arpa.
+mail.
+www.facebook.com.
+s-static.ak.facebook.com.
+a.root-servers.net.
+156.176.92.91.in-addr.arpa.
+udc.msn.com.
+www.twitter.com.
+103.205.144.79.in-addr.arpa.
+filmin.ru.
+clients1.google.com.
+a5.sphotos.ak.fbcdn.net.
+sjbbs.pchome.net.
+a.root-servers.net.
+_470_27_6.
+i.promecal.es.
+7dslqccti.92aa.
+www.cucs.udg.mx.
+157.24.131.187.in-addr.arpa.
+api.twitter.com.
+m.addthisedge.com.
+safebrowsing.clients.google.com.
+land66.ru.
+mx2.bloodservices.ca.
+169.172.21.182.in-addr.arpa.
+74.186.222.203.in-addr.arpa.
+82peunix2.92qo.
+v1.cache8.c.youtube.com.
+stedbobleabarr.tk.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.carlsberggroup.com.
+www.kamusi.org.
+caruffo.com.
+mx.wrs.yahoo.com.
+unix.horizontes.com.
+couponbuddy.s3.amazonaws.com.
+www.delawaz.com.
+www.maquillajeojos.net.
+www.batman-on-film.com.
+clients2.google.com.
+photos-g.ak.fbcdn.net.
+www.facebook.com.
+pastpresenfuture.net.
+a.root-servers.net.
+netjetseurope.ru.
+www.pressafrik.com.
+www.deportesblog.es.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+lb._dns-sd._udp.lan.
+i3.ytimg.com.
+fbcdn-photos-a.akamaihd.net.
+connect.facebook.net.
+73.228.247.190.in-addr.arpa.
+jendiab.plusnet.com.
+cust20986-1.in.mailcontrol.com.
+eq4opeahl.94hq.
+www.facebook.com.
+a.root-servers.net.
+i3.ytimg.com.
+antibiotix1.net-cube.net.
+mitecnologico.com.
+bet.iba.org.il.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+gsmtp.gatewaycc.edu.
+ladys.su.
+photos-e.ak.fbcdn.net.
+eksmo-sale.ru.
+dr._dns-sd._udp.lan.
+songid.play.it.
+volgogradenergo.ru.
+www.usemod.com.
+160.46.75.187.in-addr.arpa.
+s-static.ak.facebook.com.
+accounts.google.com.
+bea4.v.fwmrm.net.
+healthbridgefitness.com.s8a1.psmtp.com.
+pridehealth.com.
+27.172.174.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+partner.googleadservices.com.
+0-161.channel.facebook.com.
+mymonthlycycles.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+maribeluxi.blogspot.com.
+www.memeadictos.tumblr.com.
+183.55.251.189.in-addr.arpa.
+207.168.168.192.in-addr.arpa.
+tiflocomp.net.ru.
+92.184.136.186.in-addr.arpa.
+www.mixpod.com.
+sp.cwfservice.net.
+i3.ytimg.com.
+royaldecree.bigcartel.com.
+melonball.com.
+secure.wlxrs.com.
+www.ipodarchive.com.
+i.ytimg.com.
+.
+a7.sphotos.ak.fbcdn.net.
+www.movistar.com.co.
+www.youtube.com.
+i2.ytimg.com.
+238.184.13.186.in-addr.arpa.
+www.gmodules.com.
+a1.sphotos.ak.fbcdn.net.
+a1907.w7.akamai.net.
+www.kaspersky.com.
+196.146.34.187.in-addr.arpa.
+distilleryimage3.instagram.com.
+api.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+heraldicasaltena.blogspot.com.
+google.com.
+daxstudios.net.
+static.ak.fbcdn.net.
+www.muchacarne.com.
+a.root-servers.net.
+www.webuzzapp.com.
+28.37.89.186.in-addr.arpa.
+74.198.24.201.in-addr.arpa.
+146.42.60.187.in-addr.arpa.
+montser.com.
+203.16.249.78.in-addr.arpa.
+www.natashasnylons.com.
+www.unac.edu.pe.
+veneconomia.com.
+profile.ak.fbcdn.net.
+85.200.244.88.in-addr.arpa.
+182.248.43.92.in-addr.arpa.
+1804289383.localhost.
+233.25.131.187.in-addr.arpa.
+instrument52.ru.
+www.cwa2222.org.
+150.90.13.75.in-addr.arpa.
+mail.papalote.org.mx.
+maximum-leverage.s3.amazonaws.com.
+a-0.19-a30f3081.90e0581.1518.19d4.3ea1.210.0.a7c3cqnnkpvzvcusnnb84wzp25.avqs.mcafee.com.
+photos-e.ak.fbcdn.net.
+.
+160.5.145.93.in-addr.arpa.
+rubhim.hugescock.com.
+168.144.110.84.in-addr.arpa.
+www-akm.imvu.com.
+_225_68_1.
+v3r2qhhdm.k58e5c9j.
+external.ak.fbcdn.net.
+_ldap._tcp.
+cartoon.iguw.tuwien.ac.at.
+ntlworld.com.
+www.oppuz.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+paris.lachainemeteo.com.
+photos-d.ak.fbcdn.net.
+235.178.10.187.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+mtkmobile.ru.
+adserver.bcfads.com.
+search.cnki.net.
+160.211.23.186.in-addr.arpa.
+plus.google.com.
+www.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+pimail.pi-isd.net.
+228.112.145.201.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+time.windows.com.
+cdn.loading321.com.
+www.klubskascena.com.
+sump.uniblue.com.s3.amazonaws.com.
+elsignodelostiempos.blogspot.com.
+pop3.hot.glbdns.microsoft.com.
+a.root-servers.net.
+api.facebook.com.
+citiintl.122.2o7.net.
+horosta.ru.
+www.slotmachines1.com.
+elderdemolition.com.inbound15.mxlogic.net.
+stroykey.ru.
+183.8.22.113.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+spanish.alibaba.com.
+157.96.16.177.in-addr.arpa.
+www.google-analytics.com.
+62.25.184.201.in-addr.arpa.
+nm8cjds19.06it.
+fr-fr.facebook.com.
+mail.satisfacts.com.
+a34.g.akamai.net.
+aktelux.com.
+www.usacoinbook.com.
+a.root-servers.net.
+i3.ytimg.com.
+www.proklamieren.de.
+www.enlace.sep.gob.mx.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+streamate.doublepimp.com.
+us.camfed.org.
+crl.globalsign.net.
+226.140.237.189.in-addr.arpa.
+www.staatsdruckerei.at.
+147.86.111.118.in-addr.arpa.
+i3.photobucket.com.
+\(none\).
+tns-mi.com.s200a2.psmtp.com.
+fxyi:pviv.e17r1d7z.
+www.christiananime.net.
+runbox.com.
+239.32.76.84.in-addr.arpa.
+a151.d.akamai.net.
+218.220.131.187.in-addr.arpa.
+a.root-servers.net.
+auto.mercadolibre.com.mx.
+enter.brazzerspass.com.
+bonellmfg.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+42.media.v4.skyrock.net.
+secure.localbillinglimited.com.
+img100.xvideos.com.
+auro.de.
+minipanel.qq.com.
+a3.mzstatic.com.
+schonerttile.com.
+thepattinsonproject.files.wordpress.com.
+google.com.
+a4.sphotos.ak.fbcdn.net.
+clients2.google.com.
+smtp.bcgassets.com.
+0.6171754.com.
+36.95.138.190.in-addr.arpa.
+i2.ytimg.com.
+s-external.ak.fbcdn.net.
+investfinancial.com.
+windows.download.hn.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.narutomanga.tk3.net.
+1.bp.blogspot.com.
+testdrive.apc.com.
+154.81.211.108.in-addr.arpa.
+www.edressme.com.
+www.youtube.com.
+partner37.mydomainadvisor.com.
+i3.ytimg.com.
+stats.jtvnw.net.
+30.23.168.189.in-addr.arpa.
+api.yontoo.com.
+252.9.10.186.in-addr.arpa.
+barracuda.lrcr.com.
+static.ak.fbcdn.net.
+219.213.25.201.in-addr.arpa.
+megusta.followland.com.
+crl3.digicert.com.
+dnl-13.geo.kaspersky.com.
+.
+www.facebook.com.
+healthcare-automations.com.
+skerneskopdo.mp.
+tracker.reprobate.se.
+leftwich.com.
+lo.wikipedia.org.
+sbcgoldal.net.
+willbear.com.
+clients1.google.com.
+servedby.adxpose.com.
+ad-g.doubleclick.net.
+kupinakleyki.ru.
+www.monografias.com.
+c13.zedo.com.
+t0.gstatic.com.
+101.9.168.192.in-addr.arpa.
+179.118.208.112.in-addr.arpa.
+static.editmysite.com.
+83.169.211.201.in-addr.arpa.
+www.aa.com.
+mx1.elektro.com.br.
+a.root-servers.net.
+diccionario.reverso.net.
+support.google.com.
+11.113.25.31.in-addr.arpa.
+u40.eset.com.
+124.193.232.109.in-addr.arpa.
+sngs.biz.
+a-0.19-2209b041.c010083.1518.19d3.3ea0.210.0.i9zvhvc5q66kz46p5713r2g3c6.avqs.mcafee.com.
+_396_31_4.
+pt-br.facebook.com.
+b.scorecardresearch.com.
+library.unt.edu.
+api.twitter.com.
+orcart.facebook.com.
+photos-b.ak.fbcdn.net.
+skylightpictures.com.
+a.root-servers.net.
+www.facebook.com.
+67.213.137.195.in-addr.arpa.
+android.clients.google.com.
+mail2.ebpoffice.net.
+www.dog-pictures.co.uk.
+portal.salud.gob.mx.
+developers.facebook.com.
+a-0.19-220f5081.9830081.1518.19d3.3ea1.200.0.1jpm1u6775pch7wi5lcncvkcl6.avqs.mcafee.com.
+time.chttl.com.tw.
+lists.chamilo.org.
+a.root-servers.net.
+google.com.
+yoga-ology.com.
+photos-a.ak.fbcdn.net.
+sp.cwfservice.net.
+216.44.159.189.in-addr.arpa.
+165.24.105.46.zz.countries.nerd.dk.
+www.google-analytics.com.
+photos-b.ak.fbcdn.net.
+www.google.com.
+aero.upm.es.
+intomega.ru.
+a3.sphotos.ak.fbcdn.net.
+unigrids.icm.edu.pl.
+ncswmf.com.
+www.ebay.com.
+a.root-servers.net.
+sticker.yadro.ru.
+93.230.222.189.in-addr.arpa.
+apps.facebook.com.
+pagead2.googlesyndication.com.
+www.allanaheimtours.com.
+ads.wicked.com.
+a.root-servers.net.
+tanner-informatik.ch.
+a.root-servers.net.
+www.youtube.com.
+aonetel.com.
+m8.house-mixes.com.
+a4.sphotos.ak.fbcdn.net.
+xtra.co.nz.
+pnwriders.com.
+176.169.78.187.in-addr.arpa.
+wholesale.alibaba.com.
+www.bleblenigi.miasta.pl.
+celebritybabies.people.com.
+pt-br.facebook.com.
+a.rad.msn.com.
+a3.sphotos.ak.fbcdn.net.
+_832_47_5.
+155.219.192.173.in-addr.arpa.
+c.learncodethehardway.org.
+dingtao333.3322.org.
+ssl.gstatic.com.
+mail.ru.
+94.7.219.62.in-addr.arpa.
+billing.sharo4ka.ru.
+facebook-sw.vo.llnwd.net.
+img204.imageshack.us.
+3.197.154.78.in-addr.arpa.
+wintertype101.blogspot.com.
+209.120.10.187.in-addr.arpa.
+mail.cascadetitlecompany.com.
+movinta.com.
+jumpy.it.
+www.facebook.com.
+thehawklovesyou.com.
+mypassionofficial.tumblr.com.
+www.tinkerbellcupcakes.com.
+ksn2-12.kaspersky-labs.com.
+bg.wikipedia.org.
+askville.amazon.com.
+180.144.22.201.in-addr.arpa.
+csi.gstatic.com.
+ir.ebaystatic.com.
+share-online.biz.
+251.110.189.72.in-addr.arpa.
+101.208.193.91.in-addr.arpa.
+pleated-jeans.com.
+ads2.msads.net.
+ksn3.kaspersky-labs.com.
+106.214.146.189.in-addr.arpa.
+axiomsmt.com.
+ns1.force9.net.
+3.223.124.220.in-addr.arpa.
+rbr-cards.ru.
+de-de.facebook.com.
+crazyquizs.com.
+fbcdn-profile-a.akamaihd.net.
+ads.us.e-planning.net.
+www.rakutenblog.jp.
+89wuyh3hn.d44g1q9s.
+lh5.googleusercontent.com.
+www.mobile24.com.
+www.adobe.com.
+js.microsoft.com.
+nextjam.blogspot.com.
+lbworks.com.
+134.182.84.89.in-addr.arpa.
+www.aadynd.org.ar.
+ntp.glb.nist.gov.
+8.192.8.201.in-addr.arpa.
+www.google-analytics.com.
+a3.twimg.com.
+lbc4nc.com.s9a1.psmtp.com.
+www2.twncs.com.
+a.analytics.yahoo.com.
+www.google.com.
+twitter.com.
+88.176.20.190.in-addr.arpa.
+ivfcenter.ru.
+cs504508.vkontakte.ru.
+ccbill.com.
+103.50.92.190.in-addr.arpa.
+drifting.chulojuegos.com.
+t-cartledge.com.
+widgets-lf.clearspring-lf.com.akadns.net.
+i.ytimg.com.
+static.ak.fbcdn.net.
+m.addthisedge.com.
+ksn2-12.kaspersky-labs.com.
+photos-e.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+30.196.109.200.in-addr.arpa.
+static.ak.fbcdn.net.
+79.34.104.186.in-addr.arpa.
+mailsrvr.libanpost.com.lb.
+training.cakephp.org.
+offsetti.com.
+www.bluntdelivery.com.
+www.histats.com.
+www.youtube.com.
+85.207.75.201.in-addr.arpa.
+www.mail-app.com.
+api.twitter.com.
+heritage-healthcare.com.s5a1.psmtp.com.
+103.53.0.123.in-addr.arpa.
+www.tux4kids.com.
+homain.com.
+57.148.58.201.in-addr.arpa.
+hytectelephone.com.inbound15.mxlogicmx.net.
+google.com.
+b-0.19-23092008.481.1518.19d3.3ea1.410.0.eigsnthbibb5sl1we17n13czpv.avqs.mcafee.com.
+niveud.com.
+mx.youtube.com.
+5syovpg5q.47hj.
+imvubling.com.
+mail.showcasemn.com.
+old.jurnalul.ro.
+medicalsupplycenter.com.
+200.41.94.200.in-addr.arpa.
+168.179.250.112.in-addr.arpa.
+apps.facebook.com.
+firstrealtybhg.com.
+a2.twimg.com.
+api.twitter.com.
+pt.veoh.com.
+static.ak.fbcdn.net.
+107.137.134.190.in-addr.arpa.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+www.leerburg.com.
+_333_63_6.
+brightcove.vo.llnwd.net.
+join.bangedbytrannies.com.
+a.root-servers.net.
+9.224.152.189.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+resources.contactlessnews.com.
+surftofind.com.
+www.pedaleachile.cl.
+udc.msn.com.
+aka-cdn-ns.adtech.de.
+196.187.137.190.in-addr.arpa.
+titanium30-en.url.trendmicro.com.
+www.iforex.ph.
+elmonoaullador.blogspot.es.
+promo.isharemycash.com.
+a.root-servers.net.
+chittenden.com.
+nske.ru.
+developers.facebook.com.
+www.localizador-telefonos-moviles-celulares-ringtones-movil-gsm-sms.com.
+9gag.com.
+teesvalleyarts.org.uk.
+feeds.feedburner.com.
+25.159.213.201.in-addr.arpa.
+10.110.103.201.in-addr.arpa.
+k.keyade.com.
+dns.msftncsi.com.
+52.65.202.98.in-addr.arpa.
+dnl-00.geo.kaspersky.com.
+pediatriaenlared.com.ar.
+googleads.g.doubleclick.net.
+www.google.com.
+185.212.191.186.in-addr.arpa.
+s60-store.ovi.com.
+www.ask.com.
+www.roninsolitario.es.
+hot-cam.en-vivo.es.
+sites.google.com.
+pr4.netatlantic.com.
+nobles.com.au.s9a2.psmtp.com.
+upload.facebook.com.
+static.ak.fbcdn.net.
+c4.zedo.com.
+31.77.224.189.in-addr.arpa.
+43.225.176.187.in-addr.arpa.
+poderyambiente.blogspot.com.
+adserver.gb5.motorpresse.de.
+creative.ak.fbcdn.net.
+ozzi.com.au.
+use.typekit.com.
+www.antsight.com.
+holdgruen.de.
+wbn.ru.
+50.192.82.200.in-addr.arpa.
+234.8.55.157.in-addr.arpa.
+budado.info.
+crl.geotrust.com.
+www.cucaboo.com.
+acmatcorp.com.inbound15.mxlogicmx.net.
+optonlinie.net.
+webmasters.tubewolf.com.
+mx.hftfund.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+theabysmal.wordpress.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+www.revolution-bars.co.uk.
+shadesofpa.com.
+magus.postgresql.org.
+.
+a172.w7.akamai.net.
+newsobserver.com.s8a1.psmtp.com.
+rvr.blogalia.com.
+a.root-servers.net.
+clients1.google.com.mx.
+a3.sphotos.ak.fbcdn.net.
+facebook.com.
+www.esearches.com.tw.
+43.201.3.196.in-addr.arpa.
+api.facebook.com.
+www.google.com.
+baptistretirement.org.inbound10.mxlogic.net.
+www.volta.alessandria.it.
+145.3.8.200.in-addr.arpa.
+worldblog.msnbc.msn.com.
+21.59.42.190.in-addr.arpa.
+209.246.53.83.in-addr.arpa.
+i.ytimg.com.
+dnl-01.geo.kaspersky.com.
+s.ytimg.com.
+kung-fu-panda-msn.programasgratis.es.
+hg.splayer.org.
+33.7.98.189.in-addr.arpa.
+a.root-servers.net.
+mintzfamily.com.
+123.103.205.190.in-addr.arpa.
+a.ads2.msads.net.
+8.46.13.190.in-addr.arpa.
+domino.ingo.com.ua.
+a7.sphotos.ak.fbcdn.net.
+www.ibima.org.
+evergreen-shipping.com.
+bluedogden.com.
+www.linkedin.com.
+plus.google.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.google.com.
+152.163.144.207.in-addr.arpa.
+commnat-cohort.ess.apple.com.akadns.net.
+a7.sphotos.ak.fbcdn.net.
+a-0.19-2109a801.d060083.1518.19d4.3ea1.410.0.spqabajtl54hfqk97s33alujnv.avqs.mcafee.com.
+225.103.95.190.in-addr.arpa.
+_311_78_5.
+a-0.19-230c8079.d160083.1518.19d4.3ea1.410.0.j8pw3bbzug8sm32di2bf42b4dq.avqs.mcafee.com.
+ksn2-12.kaspersky-labs.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+freewareforus.com.
+meta.p2.color.com.
+a7.sphotos.ak.fbcdn.net.
+newsrss.bbc.co.uk.
+tc.v13.cache3.c.youtube.com.
+184.199.125.84.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+193.61.58.186.in-addr.arpa.
+www.flashgalerie.com.
+rcp.na.blackberry.com.
+creative.ak.fbcdn.net.
+www.fantastigames.com.
+27.247.89.186.in-addr.arpa.
+115.194.179.187.in-addr.arpa.
+www.fgcuicehockey.com.
+utblive.com.
+fasgroup.ru.
+vyatskaya-matreshka.ru.
+orcart.facebook.com.
+a.root-servers.net.
+improveverywhere.com.
+servicemap.conduit-services.com.
+ilov.spb.ru.
+rest.motekmobile.com.
+i3.ytimg.com.
+a.root-servers.net.
+linkhelp.clients.google.com.
+www.l.google.com.
+apps.facebook.com.
+ocsp.verisign.com.
+ax.init.itunes.apple.com.
+google.com.
+tnams.com.
+mail2.somewhere.com.
+asic.gov.au.
+16.122.149.187.in-addr.arpa.
+4shared.co.
+sp.cwfservice.net.
+external.ak.fbcdn.net.
+tysvrmail.teckyork.com.
+abel.dk.
+darbylaw.com.
+colorquimica.com.co.
+sup.live.com.
+232.24.85.200.in-addr.arpa.
+esino.en.alibaba.com.
+a.root-servers.net.
+dasya.com.
+244.74.41.187.in-addr.arpa.
+79.16.21.201.in-addr.arpa.
+platform.twitter.com.
+creative.ak.fbcdn.net.
+shared.live.com.
+112.92.112.177.in-addr.arpa.
+external.ak.fbcdn.net.
+photos-b.ak.fbcdn.net.
+time.windows.com.
+www.htmlfirm.com.
+platform.ak.fbcdn.net.
+a1005.w42.akamai.net.
+profile.ak.fbcdn.net.
+www.facebook.com.
+www.gooogirl.com.
+pmkqrc8hg.66dq.
+www.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+google.com.
+adserver.adtechus.com.
+www.colsantamariaportu.com.
+laobserved.com.
+immunolabs.com.
+msgr.updates.yahoo.com.
+_757_34_5.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+97.165.198.74.in-addr.arpa.
+61.185.176.190.in-addr.arpa.
+us.starmedia.com.
+belorys-kh.livejournal.com.
+publimetro1.autoplaza.com.mx.
+pcweb.mycom.co.jp.
+info.yahoo.com.
+sc2.rules.mailshell.net.
+100.127.101.75.in-addr.arpa.
+.
+mail.google.com.
+191.140.84.200.in-addr.arpa.
+www.houseofdeals.com.
+js.wlxrs.com.
+246.227.171.69.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+content.yieldmanager.edgesuite.net.
+l.yimg.com.
+googleads.g.doubleclick.net.
+www.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+img301.imageshack.us.
+a1505.l.akamai.net.
+mail.global.ans-online.net.
+lh5.googleusercontent.com.
+www.google.com.
+www.licornpublishing.com.
+mail.ntnindia.com.
+stisd.esc2.net.
+145.219.110.189.in-addr.arpa.
+ns2.fibernet.ro.
+www.facebook.com.
+smtpfw.citybloom.org.
+www.google.com.
+92.28.252.189.in-addr.arpa.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+blog.beliefnet.com.
+aiolfi.ch.
+developers.facebook.com.
+125.162.168.192.in-addr.arpa.
+support.mediafire.com.
+116.57.64.62.in-addr.arpa.
+a1108.da1.akamai.net.
+secure.shared.live.com.
+a.root-servers.net.
+glayiueditorial.blogspot.com.
+pixel.facebook.com.
+162.198.143.187.in-addr.arpa.
+platform.ak.fbcdn.net.
+www.facebook.com.
+www.aepia.org.
+d-t.ru.
+www.bebo.com.
+adserver.adtech.de.
+1.0.0.127.in-addr.arpa.
+www.mujeresdeempresa.com.
+a-0.19-a3096081.c0b0002.1518.19d3.3ea1.210.0.wzmeesafj38nm94cm4dpwg8mai.avqs.mcafee.com.
+www.dodge.cl.
+productos.maycodelsureste.com.
+education.parts-express.com.
+www.slrphotographyguide.com.
+158.82.246.201.in-addr.arpa.
+m.addthisedge.com.
+www.facebook.com.
+carrental.enclick.com.
+ns20-f.bigfish.com.
+www.infolinks.com.
+dm-tech.net.
+de.tynt.com.
+mail.ce-easy.de.
+a2.sphotos.ak.fbcdn.net.
+147.255.191.220.in-addr.arpa.
+166.115.110.193.in-addr.arpa.
+secure.gravatar.com.
+elmusic.net.
+a1.sphotos.ak.fbcdn.net.
+api.bizographics.com.
+js2.wlxrs.com.
+736561726368636c69656e74.6c697665.6e6574.80h413650eb.webcfs00.com.
+146.253.183.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+pim.ram.htcsense.com.
+thumbs.ofmtvimg.info.
+5.166.171.69.in-addr.arpa.
+63.13.195.187.in-addr.arpa.
+admeld.adnxs.com.
+afs-seminars.com.
+r._dns-sd._udp.0.50.168.192.in-addr.arpa.
+www.youtube.com.
+www.facebook.com.
+186.91.73.190.in-addr.arpa.
+pipe-klup.ru.
+mail.xn.com.
+89.190.170.201.in-addr.arpa.
+wuiyue.com.
+gfx8.hotmail.com.
+_954_38_1.
+www.fregate.com.
+alumnos.unex.es.
+vogue.mundoforo.com.
+dstest.yahoo.com.
+cdn.search.sweetim.com.
+media.monster.com.
+mail.quartics.com.
+preved.bandoo.com.
+a.root-servers.net.
+mms602.whatsapp.net.
+inspecintl.com.
+dns.msftncsi.com.
+itx4.2-01-275d-0005.cdx.cedexis.net.
+cocinet.net.
+aboutfamilies.org.
+tissc.corp.travelport.com.
+teredo.ipv6.microsoft.com.
+libropadrericopadrepobre.wordpress.com.
+neksus.net.
+accounts.google.com.
+yts-blog.weblogs.jp.
+107.179.152.201.in-addr.arpa.
+copers.ru.
+cisadu2.let.uniroma1.it.
+www.facebook.com.
+www.google.com.
+www.googletagservices.com.
+ssl.gstatic.com.
+creative.ak.fbcdn.net.
+95.43.139.187.in-addr.arpa.
+a.root-servers.net.
+cnic.jp.
+www.fickdich.biz.
+api.oovoo.com.
+a2.sphotos.ak.fbcdn.net.
+support.google.com.
+203.175.179.60.in-addr.arpa.
+es-la.facebook.com.
+26.106.73.186.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+www.facebook.com.
+77.28.10.201.in-addr.arpa.
+row.bc.yahoo.com.
+americangaming.org.
+www.ociodf.net.
+a2.sphotos.ak.fbcdn.net.
+s1-s.licdn.com.
+a.root-servers.net.
+www.facebook.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+58.59.13.189.in-addr.arpa.
+www.itb.co.uk.
+rss.msnbc.msn.com.
+238.235.231.190.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+www.bing.com.
+www.shutterbug.net.
+hawaiicaterers.com.
+www.getitnearme.com.
+sites.google.com.
+www.mediawiki.org.
+mailsrv2.sofidel.com.
+jemsite.com.
+fotoramok.net.
+es.answers.yahoo.com.
+mailgate.burgoynes.com.
+ksn2-12.kaspersky-labs.com.
+ads.sumavisos.com.
+www.hsbc.co.mu.
+ocsp.verisign.com.
+www.worldlandtrust.org.
+winderhall.co.uk.
+snsgw.samsungmobile.com.
+www.google.com.
+safebrowsing-cache.google.com.
+static.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+107.146.220.66.in-addr.arpa.
+biblioteca.enah.edu.ni.
+loschicosenero.blogspot.com.
+creative.ak.fbcdn.net.
+www.todotorrents.com.
+253.248.72.184.in-addr.arpa.
+windcriesamy.blogspot.com.
+creative.ak.fbcdn.net.
+121.80.51.170.in-addr.arpa.
+46.33.119.200.in-addr.arpa.
+css.corriereobjects.it.
+224.225.173.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.qzal.net.
+46.171.168.67.in-addr.arpa.
+insites.com.au.
+94.86.110.79.in-addr.arpa.
+www.britishsupermarketworldwide.com.
+goo.gl.
+0-155.channel.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+1-nuncasabe.blogspot.com.
+s.youtube.com.
+googleads.g.doubleclick.net.
+14.38.34.156.in-addr.arpa.
+blogdegameloft.es.
+s-static.ak.facebook.com.
+mail4.syntec.carlisle.com.
+bolig.lokalavisen.dk.
+celebritybabies.people.com.
+p.twimg.com.
+www.fourwinds10.net.
+google.com.
+db._dns-sd._udp.lan.
+crl.microsoft.com.
+a.root-servers.net.
+a.root-servers.net.
+banners2.ero-advertising.com.
+web.ewu.edu.
+skydrive.live.com.
+a.root-servers.net.
+media.relay.voice.yahoo.com.
+developers.facebook.com.
+entertaintexas.com.
+118.82.106.189.in-addr.arpa.
+calendarmarks.xanga.com.
+va.px.invitemedia.com.
+supcisqslsyiqrs.biz.
+platform.twitter.com.
+seriesloads.com.ar.
+www.youtube.com.
+img216.imagevenue.com.
+pacificbmw.com.s9b1.psmtp.com.
+www.crunchbase.com.
+api.twitter.com.
+backupmx.mycompuworld.net.
+www.facebook.com.
+127.234.178.186.in-addr.arpa.
+greaterlexins.com.
+tms30.icrc.trendmicro.com.
+csi.gstatic.com.
+pnrws.skype.com.
+aeglegno.it.
+176.104.117.200.in-addr.arpa.
+mail.sleeppd.com.
+231.119.47.92.in-addr.arpa.
+219.219.91.186.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+pool.ntp.org.
+a.root-servers.net.
+i2.ytimg.com.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+fghyt.com.
+google.com.
+www.amorenlinea.biz.
+cdn.dnsmex.net.
+35.29.69.187.in-addr.arpa.
+knowco.com.
+www.mccannfiles.com.
+glenelg74.fsnet.co.uk.
+amer.rel.msn.com.
+webcache.googleusercontent.com.
+apps.facebook.com.
+251.15.236.189.in-addr.arpa.
+37.41.177.142.in-addr.arpa.
+by2msg4020708.gateway.messenger.live.com.
+55.92.161.189.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+www.bing.com.
+titanium30-en.url.trendmicro.com.
+www.doosaninfracore.com.
+www.dayspring.com.
+79.29.200.189.in-addr.arpa.
+centurioninsurance.net.
+www.mmsend1.com.
+a2.da1.akamai.net.
+afrada.com.ua.
+7.30.4.189.in-addr.arpa.
+l.yimg.com.
+dcads.sina.com.cn.
+pagead2.googlesyndication.com.
+s.youtube.com.
+viajedefrances2009.wordpress.com.
+accounts.google.com.
+cdn1.ads.contentabc.com.
+dimmitt.net.
+peru21.pe.
+newmonetarism.blogspot.com.
+i4.ytimg.com.
+a.root-servers.net.
+www.globus.org.
+news.search.yahoo.com.
+rest-img.msg.yahoo.com.
+historiasdeamor-mina.blogspot.com.
+www.juegos-diarios.org.
+soundeyet.blogspot.com.
+support.google.com.
+sonamywings.foroactivo.net.
+static.ak.fbcdn.net.
+5.p.s.mfcdn.net.
+zh-cn.facebook.com.
+i2.ytimg.com.
+google.com.
+mx2.dualog.no.
+service1.ess.apple.com.
+estonoesunblogdehistoria.blogspot.com.
+eysk.kuban.su.
+135.201.157.186.in-addr.arpa.
+www.potoandcabenga.com.
+55.181.63.69.in-addr.arpa.
+creative.ak.fbcdn.net.
+ds.serving-sys.com.
+a2.sphotos.ak.fbcdn.net.
+weather.ammonnews.net.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+_806_43_8.
+sp.cwfservice.net.
+www.statcounter.com.
+photos-d.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+20.83.187.190.in-addr.arpa.
+32.96.188.186.in-addr.arpa.
+176.220.85.209.sbl-xbl.spamhaus.org.
+www.facebook.com.
+marksstudio.com.
+a7.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+63.49.79.187.in-addr.arpa.
+relay.voice.messenger.msn.com.
+bleetz.wordpress.com.
+m.ak.fbcdn.net.
+es.wikipedia.org.
+www.global.hs-mittweida.de.
+lernet.ru.
+www.peopleeffect.com.au.
+www.facebook.com.
+dragon-ball-z-budokai-x.softonic.com.br.
+s2.youtube.com.
+m.hotmail.com.
+ad.adnetwork.net.
+mail2.americasvacationcenter.com.
+apps.facebook.com.
+rayman-raving-rabbids.programas-gratis.net.
+a8.sphotos.ak.fbcdn.net.
+7.37.215.186.in-addr.arpa.
+zynga.tm.
+music-vokal.ru.
+apir.webrep.avast.com.
+www.saartjeknits.nl.
+profile.ak.fbcdn.net.
+tc16.easythumbhost.com.
+wws.mcanime.net.
+code.jquery.com.
+122.173.180.186.in-addr.arpa.
+167.19.106.186.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+mashsf.tumblr.com.
+a.root-servers.net.
+53.50.27.201.in-addr.arpa.
+kdc.uas.aol.com.
+adm-saransk.ru.
+tc3.easythumbhost.com.
+m.addthisedge.com.
+ultrastardx.sourceforge.net.
+133.81.73.190.in-addr.arpa.
+www.bestbuy-walmart.com.
+dogparry.deviantart.com.
+thumbs2.ebaystatic.com.
+profile.ak.fbcdn.net.
+muscledmanmeat.bestmalediaries.com.
+134.56.5.190.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.64colors.com.
+api.facebook.com.
+www.google.com.
+www.adobe.com.
+107.187.153.186.in-addr.arpa.
+www.bravotube.net.
+googleads.g.doubleclick.net.
+news.google.com.
+partner.googleadservices.com.
+_922_37_6.
+www.wamgroup.com.
+1.207.239.71.in-addr.arpa.
+artesana.mejorforo.net.
+glamaur.ru.
+www.yx0077.com.
+s.youtube.com.
+145.7.173.201.in-addr.arpa.
+yahoo.com.
+bom3.vsnl.net.in.
+e-tard.tv.
+chy856n7f.18hx.
+adsfront.iminent.com.
+178.41.210.201.in-addr.arpa.
+bnlmail.com.
+img100.xvideos.com.
+sf-mailgate.hellerehrman.com.
+160.172.83.178.in-addr.arpa.
+facultalandia.blogia.com.
+insider.msg.yahoo.com.
+ytimg.l.google.com.
+adfactory.publicidees.net.
+sexy-1.momsfactory.com.
+a3.da1.akamai.net.
+safebrowsing.clients.google.com.
+alt1.aspmx.l.google.com.
+ever.ru.
+blufiles.storage.msn.com.
+a1.sphotos.ak.fbcdn.net.
+chromejs.s3.amazonaws.com.
+dcoxy4i5d.89bi.
+a.root-servers.net.
+www.toons-x.com.
+156.120.75.200.in-addr.arpa.
+109.31.156.187.in-addr.arpa.
+www.wetteronline.de.
+www.mi6-hq.com.
+137.131.170.118.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+www.usps.com.
+swaisland-ltd.com.
+dc.logmein-gateway.com.
+bible.christiansunite.com.
+jers2.info.
+s-static.ak.fbcdn.net.
+.
+104.217.237.78.in-addr.arpa.
+www.jumboacasa.com.ar.
+151.183.193.111.in-addr.arpa.
+i998.mangareader.net.
+www.tips4mums.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+developers.facebook.com.
+.
+relay1.delight2000.com.
+photos-b.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+id-id.facebook.com.
+www.bancobcr.com.
+csc3-2010-crl.verisign.com.
+www.gerencie.com.
+facebook.com.
+ocsp.digicert.com.
+download313.avast.com.
+angus.njcure.com.
+cs10124.vk.com.
+.
+200.27.81.187.in-addr.arpa.
+atlantichealth.com.
+loefflerrandall.com.
+c0013899.cdn1.cloudfiles.rackspacecloud.com.
+114.225.234.99.in-addr.arpa.
+mail1.mn-services.nl.
+maverickflooring.com.
+websearch.ask.com.
+fr-fr.facebook.com.
+static.ak.facebook.com.
+zammbkygf.76ul.
+q.ebaystatic.com.
+localhost.
+mail.jofair.com.
+a1997.b.akamai.net.
+78.50.170.201.in-addr.arpa.
+download.cartoonnetworkasia.com.
+cdn.rep.sc.sweetim.com.
+www.ambafrance-id.org.
+125.100.255.77.in-addr.arpa.
+api-read.facebook.com.
+205.113.102.201.in-addr.arpa.
+mail.flinteclk.com.
+www.adobe.com.
+wd-edge.sharethis.com.
+showtimepictures.com.
+ad.jumbaexchange.com.
+apis.google.com.
+wikileaks.org.
+sa.wikipedia.org.
+radoscorp.radoscompanies.com.
+63.90.30.190.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+102.214.231.89.in-addr.arpa.
+skj-advokat.dk.
+e4805.b.akamaiedge.net.
+a.root-servers.net.
+box425.bluehost.com.
+www.belkin.com.
+104.2.168.192.in-addr.arpa.
+238.62.248.201.in-addr.arpa.
+secure.gate2shop.com.
+ymail.com.
+74.166.58.187.in-addr.arpa.
+es-la.facebook.com.
+vstun.voipinfocenter.com.
+b._dns-sd._udp.0.55.211.10.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+236.73.243.201.in-addr.arpa.
+www.micasarevista.com.
+dinero.univision.com.
+126.39.213.186.in-addr.arpa.
+mis-3.pgi.citiesofgold.com.
+c-0.19-a309f481.483.1518.19d3.3ea1.410.0.i8p2s6m6vjskf3g8al12u1wpdq.avqs.mcafee.com.
+photos-d.ak.fbcdn.net.
+mercigod.com.
+www.losrecursoshumanos.com.
+www.calculadoradelamortotal.com.
+www.lyme.org.
+22.242.171.69.in-addr.arpa.
+79.189.245.190.in-addr.arpa.
+us.bc.yahoo.com.
+worldattnet.com.
+hst14.vault-it.ru.
+a.root-servers.net.
+s.youtube.com.
+profile.ak.fbcdn.net.
+201.204.177.189.in-addr.arpa.
+mail.fpalex.com.
+tuqbjzkbh.a99t7h1e.
+creative.ak.fbcdn.net.
+clients1.google.com.
+215.198.3.190.in-addr.arpa.
+107.69.210.201.in-addr.arpa.
+3oaks.com.
+ad-g.doubleclick.net.
+developers.facebook.com.
+mobileinsights.com.
+www.themotoguide.com.
+mail.fe-azp.com.
+zoo-tycoon-2-endangered-species.softonic.com.
+i1.ytimg.com.
+seversk.net.
+.
+a.root-servers.net.
+9.55.98.68.in-addr.arpa.
+aol.com.
+jcgodj7jq.43cc.
+98.165.66.66.in-addr.arpa.
+flashpirate.com.
+csi.gstatic.com.
+www.facebook.com.
+a13.t26.net.
+financialheritage.com.
+www.google.com.
+lawebdeidea.org.
+photos-h.ak.fbcdn.net.
+apps.facebook.com.
+www.googletagservices.com.
+us.bc.yahoo.com.
+a.c-0.19-1309d081.20400b3.1518.19d4.3ea1.210.0.upmrq98fnvwbita33avahwiqgi.avqs.mcafee.com.
+picasaweb.google.ru.
+d2095743.xoom.it.
+a.root-servers.net.
+adewumicollege.net.
+i3.ytimg.com.
+www.dollarparalelovenezuela.com.
+platform.twitter.com.
+js.aiya.com.cn.
+service.gc.apple.com.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+ideatrainingcenter.com.
+radoux.fr.
+161.0.94.208.in-addr.arpa.
+turismo.perfil.com.
+cluster2a.us.messagelabs.com.
+ntp1.cs.wisc.edu.
+hs9ba2qyg.49gr.
+cataclysm.wowmortal.com.
+smtp02-1.omse-rz.net.
+video.google.com.
+plus.google.com.
+dns.msftncsi.com.
+firsttennessee.com.
+55.69.108.118.in-addr.arpa.
+112.2.135.190.in-addr.arpa.
+229.110.14.186.in-addr.arpa.
+armmf.adobe.com.
+109.217.252.49.in-addr.arpa.
+xomediaxchange.voicenation.com.
+i3.ytimg.com.
+bookplatejunkie.blogspot.com.
+blog.4shared.com.
+rts.phn.doublepimp.com.
+his.se.
+caleidoscoop.net.
+manila.craigslist.com.ph.
+saransk.binbank.ru.
+www.restaurantsource.com.
+a1313.da1.akamai.net.
+www.google.com.
+biglonline.com.
+shared.live.com.
+o.analytics.yahoo.com.
+a5.sphotos.ak.fbcdn.net.
+55.19.118.75.in-addr.arpa.
+www.facebook.com.
+34.111.246.190.in-addr.arpa.
+market.android.com.
+creative.ak.fbcdn.net.
+www.new-hairgames.com.
+buildabearnews.com.
+ksn2-12.kaspersky-labs.com.
+fpdownload.adobe.com.
+dns.msftncsi.com.
+95.118.145.186.in-addr.arpa.
+a1701.v.phobos.apple.com.
+counterb.statcounter.com.
+css.wlxrs.com.
+photos-b.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+jjrinccpa.com.
+a.root-servers.net.
+cxz23.meaningtool.com.
+33.141.14.201.in-addr.arpa.
+145.122.255.200.in-addr.arpa.
+dns.msftncsi.com.
+backofficesite.epyte.com.
+platform.twitter.com.
+monitor.nsk.su.
+mx03.wow.synacor.com.
+rs570l3.rapidshare.com.
+www.druglib.com.
+201.120.141.99.in-addr.arpa.
+plus.google.com.
+download.cnet.com.
+latinoweb.com.
+222.73.109.79.in-addr.arpa.
+ax.su.itunes.apple.com.
+mobile.jang.com.pk.
+recall.com.s5a2.psmtp.com.
+photos-a.ak.fbcdn.net.
+141.190.106.177.in-addr.arpa.
+l.yimg.com.
+orovalleycam.webhop.net.
+ak1.abmr.net.
+80.76.132.190.in-addr.arpa.
+www.gatorade.com.mx.
+abnorth.com.
+download115.avast.com.
+www.care4babygallery.net.
+33.248.95.82.in-addr.arpa.
+39.68.172.123.in-addr.arpa.
+rt.liftdna.com.
+a749.g.akamai.net.
+platform.twitter.com.
+pics.ebaystatic.com.
+ads.zepterads.com.
+74.244.117.98.in-addr.arpa.
+186.185.208.189.in-addr.arpa.
+www.saunasol.com.
+wods.radio.com.
+personyze-ssl-399604307.eu-west-1.elb.amazonaws.com.
+hagenburgsrv3.hagenburg.se.
+cdn.api.twitter.com.
+www.m6m3.com.
+www.facebook.com.
+horizon.bcbsnj.com.
+fotografia.facilisimo.com.
+.
+www.tntla.com.
+122.117.250.201.in-addr.arpa.
+survey.westfalia-separator.com.
+www.efesis.cl.
+a3.sphotos.ak.fbcdn.net.
+ihatemyparents.tumblr.com.
+op.pl.
+www.prodiverstore.com.
+nimbus.com.
+photos-f.ak.fbcdn.net.
+69.206.84.200.in-addr.arpa.
+clutch.mtv.com.
+e554sgnyx.53kx.
+safebrowsing-cache.google.com.
+www.parroquiasanfranciscosj.com.
+www.google-analytics.com.
+a5.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+www.google-analytics.com.
+a.root-servers.net.
+alberdalellc.com.
+eyuon.net.
+www.hispatube.com.
+sundistasya-shx.blogspot.com.
+feeds.feedburner.com.
+.
+bitech.net.
+img.scoop.it.
+30.media.tumblr.com.
+l.yimg.com.
+www.google-analytics.com.
+twitter.com.
+www.facebook.com.
+isatap.cisco.
+fxfeeds.mozilla.com.
+mail.sabarch.com.
+www.bn.pt.
+igenbergs.de.
+safebrowsing-cache.google.com.
+carla.cg-models.net.
+ad-g.doubleclick.net.
+technorati.com.
+6.88.168.192.in-addr.arpa.
+121.2.54.121.in-addr.arpa.
+www.celebritiesdietplan.com.
+zh-cn.facebook.com.
+client-software.real.com.
+www.valuedgirls.com.
+gaoqing.baofeng.com.
+mysearchdock.com.
+130.45.42.200.in-addr.arpa.
+ad.yieldmanager.com.
+31.71.191.186.in-addr.arpa.
+antiaging.com.
+stats.update.microsoft.com.
+photos-e.ak.fbcdn.net.
+holaapple.com.
+laodontologia.blogspot.com.
+sports.espn.go.com.
+e1.extreme-dm.com.
+www.bollesafety.com.au.
+www.vuelos.com.
+profile.ak.fbcdn.net.
+174.96.122.190.in-addr.arpa.
+pagead2.googlesyndication.com.
+a5.da1.akamai.net.
+a.root-servers.net.
+d.shareaholic.com.
+a.root-servers.net.
+clients1.google.com.
+29.media.tumblr.com.
+creative.ak.fbcdn.net.
+www.dobrucki.com.
+65.68.69.189.in-addr.arpa.
+105.250.161.201.in-addr.arpa.
+i4.ytimg.com.
+www.rashed-elmajed.com.
+cdn1.finaltorrent.com.
+164.240.250.190.in-addr.arpa.
+www.altillo.com.
+smtp.ctshk.com.
+217.76.210.189.in-addr.arpa.
+isohunt.com.
+oh.rr.com.
+189.181.106.177.in-addr.arpa.
+nashvillemama.com.
+187.142.20.92.in-addr.arpa.
+mx03.peoplepc.com.
+safebrowsing.clients.google.com.
+www.facebook.com.
+c49cvdtnsjqhvprarmrjvdxe41e11a37nybu.info.
+profile.ak.fbcdn.net.
+www9.effectivemeasure.net.
+15.222.198.190.in-addr.arpa.
+rivergrovewinery.com.
+155.58.50.190.in-addr.arpa.
+a.root-servers.net.
+a1.sphotos.ak.fbcdn.net.
+badge.facebook.com.
+lafvb.com.
+a.root-servers.net.
+highbury.ac.uk.
+www.thehkaccess.com.
+uh9ql5i6u.k81a3t8z.
+www.waringcommercialproducts.com.
+a4.sphotos.ak.fbcdn.net.
+american-playboy-spread.peliculon.tv.
+checkip.dyndns.org.
+a.root-servers.net.
+13.252.241.201.in-addr.arpa.
+ib.adnxs.com.
+www.blingblog.info.
+icons.net.
+netrats.net.
+matedicc.blogspot.com.
+a6.sphotos.ak.fbcdn.net.
+55.9.2.187.in-addr.arpa.
+www.foxsoccer.com.
+api.twitter.com.
+81.178.31.88.in-addr.arpa.
+mx2.mail.eu.yahoo.com.
+i32.tinypic.com.
+fisgoneo.blogspot.com.
+google.com.
+www.joystiq.com.
+ovejaquebalabocadoquepierde.blogspot.com.
+mx.ntcom.ru.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+12.79.250.190.in-addr.arpa.
+mail.pioneeris.net.
+a.root-servers.net.
+devices.live.com.
+dns.msftncsi.com.
+mail2.idesign.com.
+64.202.128.189.in-addr.arpa.
+247.67.228.189.in-addr.arpa.
+www.torrentman.com.
+mvc.break.com.
+media.adxpansion.com.
+cerealmx.quepasa.com.
+clients1.google.com.
+email.dropsend.com.
+sn1msg2010531.gateway.messenger.live.com.
+www.comcast-deals.info.
+ds.serving-sys.com.
+oojk2ck8t.21sq.
+www.facebook.com.
+mail.bettysshop.com.
+dl.google.com.
+xentric.deviantart.com.
+mx.direxions.com.
+api.mybrowserbar.com.
+ssl.gstatic.com.
+b.scorecardresearch.com.
+hcjdazlivat.cc.domain_not_set.invalid.
+kbr.com.
+www.socialgrowthtechnologies.com.
+profile.ak.fbcdn.net.
+ohota-barex.ru.
+api.twitter.com.
+connect.facebook.net.
+gordon-silber.com.
+crl.microsoft.com.
+query.nytimes.com.
+164.115.172.201.in-addr.arpa.
+antonriot.ru.
+212.130.240.85.in-addr.arpa.
+mac.com.
+external.ak.fbcdn.net.
+2.224.195.176.in-addr.arpa.
+_164_71_9.
+img7.imagevenue.com.
+um18.eset.com.
+mail.awlindustries.com.
+qbar.book.qq.com.
+www.mspbs.gov.py.
+150.246.19.187.in-addr.arpa.
+cmts.cmm.msu.ru.
+checkip.dyndns.com.
+www.adobe.com.
+www.thegeneral.com.
+a.root-servers.net.
+75.95.218.186.in-addr.arpa.
+a.root-servers.net.
+m.addthisedge.com.
+up.e7s.net.
+pinme.ru.
+a.root-servers.net.
+arxivblog.com.
+www.apple.com.
+w:5lv9:ve.h26v8v6f.
+ds.serving-sys.com.
+www.statefarm.com.
+19.247.121.109.in-addr.arpa.
+parroquiadebarciela.org.
+flagerschools.com.
+d3lvr7yuk4uaui.cloudfront.net.
+73.91.68.94.in-addr.arpa.
+www.edenred.es.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.skykid.org.
+24.media.tumblr.com.
+www.cdevision.com.
+mypmfloan.com.
+photos-e.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+lienzogazules.wordpress.com.
+www.gstatic.com.
+mail.omnihomesinc.com.
+www.update.microsoft.com.
+es-es.facebook.com.
+www.google.com.
+l9h64srgl.k63c2y2h.
+forum.4shared.com.
+googleads.g.doubleclick.net.
+www.buzzeum.com.
+29.116.46.207.in-addr.arpa.
+mail2.ringpower.com.
+ottawaplastics.com.
+gimail.af.mil.
+60.70.38.186.in-addr.arpa.
+0-310.channel.facebook.com.
+api-read.facebook.com.
+88.80.130.213.in-addr.arpa.
+dns.msftncsi.com.
+platform.twitter.com.
+238.247.114.186.in-addr.arpa.
+planeta-hot.blogspot.com.
+google.com.
+www.youtube.com.
+sp.cwfservice.net.
+www.gstatic.com.
+95c91792.realfiles.net.
+162.252.9.177.in-addr.arpa.
+googleads.g.doubleclick.net.
+multimediajuegosyprogramas.blogspot.com.
+www.adultizle.net.
+sites.google.com.
+135.194.55.187.in-addr.arpa.
+75.41.165.83.in-addr.arpa.
+a.root-servers.net.
+www.sharethis.com.
+www.5starcosmetics.co.uk.
+84.18.76.189.in-addr.arpa.
+biltmorebaptist.com.
+163.51.173.201.in-addr.arpa.
+mailserver.rkprint.com.
+a1003.w41.akamai.net.
+s.youtube.com.
+_512_31_2.
+www.unitedelectricalservices.com.au.
+xefevsma1.69pe.
+dv57qk7uv.01kk.
+220.26.74.187.in-addr.arpa.
+_ldap._tcp.
+butterfield.k12.mn.us.
+degerencia.com.
+tc24.easythumbhost.com.
+api.twitter.com.
+104.139.17.201.in-addr.arpa.
+api-read.facebook.com.
+www.google.com.
+_282_00_4.
+sc2.rules.mailshell.net.
+6.105.68.201.in-addr.arpa.
+www.mayflowerfamilies.com.
+paradiseartists.com.s10a1.psmtp.com.
+www.bangkokbargirl.com.
+plus.google.com.
+jalisco.milenio.com.
+photos-c.ak.fbcdn.net.
+www.youtube.com.
+www.belote-en-ligne.fr.
+de-de.facebook.com.
+www.intel.com.
+ajax.googleapis.com.
+185.6.36.186.in-addr.arpa.
+www.google-analytics.com.
+ccso.fr.
+117.220.20.58.in-addr.arpa.
+ads.adxpose.com.
+stratus.com.br.
+css.wlxrs.com.
+js.revsci.net.
+www.wheredidugetthat.com.
+dotmed-images.s3.amazonaws.com.
+152.129.203.190.in-addr.arpa.
+inlinethumb09.webshots.com.
+viv.ebay.ie.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.facebook.com.
+suddenlinke.net.
+_ldap._tcp.
+www.searchqu.com.
+psgw.t-mobilesgws.com.
+rad.msn.com.
+madolcevita.canalblog.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+www.yangmi.com.
+vegweb.com.
+mavericklogistics.com.
+smtp.mourik.com.
+a2.sphotos.ak.fbcdn.net.
+translate.googleapis.com.
+google.com.
+inbound.trektours.com.netsolmail.net.
+pixel.quantserve.com.
+accounts.youtube.com.
+shop.frontarmy.com.
+62.101.69.189.in-addr.arpa.
+www.youtube.com.
+mx2.archirodon.net.
+35.238.57.62.in-addr.arpa.
+138.95.150.187.in-addr.arpa.
+support.google.com.
+a8.sphotos.ak.fbcdn.net.
+stats.beaconads.com.
+154.97.237.98.in-addr.arpa.
+ts3.mm.bing.net.
+a6.sphotos.ak.fbcdn.net.
+a78srlmfd.n17i7f6q.
+www.maltatexo.com.mx.
+0-167.channel.facebook.com.
+104.176.161.109.in-addr.arpa.
+74.8.238.189.in-addr.arpa.
+img703.imageshack.us.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+mangacan.blogspot.com.
+dhp.com.
+photos-b.ak.fbcdn.net.
+223.206.236.99.in-addr.arpa.
+www.facebook.com.
+chatenabled.mail.google.com.
+smtp1.qatar-med.cornell.edu.
+optimumreturn.com.s7a1.psmtp.com.
+andreaandreanavarretemarn04-andrea.blogspot.com.
+accountservices.msn.com.
+50.226.93.186.in-addr.arpa.
+absolute-bikini.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.googleadservices.com.
+smtp.cobantur.com.
+bbcore.cloudapp.net.
+developers.facebook.com.
+eolapaz2.blogspot.com.
+mail.google.com.
+_284_43_8.
+js.admeld.com.
+server1.torrenzano.com.
+188.177.232.190.in-addr.arpa.
+g-ecx.images-amazon.com.
+www.davedubya.com.
+pixel.facebook.com.
+39-courier.push.apple.com.
+hoymusic.com.
+creative.ak.fbcdn.net.
+www.citedusexe.com.
+a.root-servers.net.
+233.7.147.190.in-addr.arpa.
+ringo.com.
+davesnotepad.blogspot.com.
+10marnellcorrao.com.inbound10.mxlogic.net.
+img.youtube.com.
+external.ak.fbcdn.net.
+www.msftncsi.com.
+weddings.about.com.
+sro.whatsapp.net.
+pagead2.googlesyndication.com.
+fls-sccmgl01.pfaff.local.
+www.veithsymposium.org.
+mail.btc.net.
+notifier.avira.com.
+retracker.hotplug.ru.
+a1005.w42.akamai.net.
+static.4shared.com.
+mail.firstmerc.com.
+www.warrs.com.
+142.195.206.200.in-addr.arpa.
+a.root-servers.net.
+ipm.bitdefender.com.
+backup-bc.mail-relay.com.
+241.31.63.189.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+getprof.de.np.community.playstation.net.
+mail.eldacc.co.za.
+palax.kirov.ru.
+115.26.170.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+_303_11_0.
+aol.com.
+profile.ak.fbcdn.net.
+mystartantiphishing.com.
+mail.yiron.org.il.
+ch.roskzn.ru.
+www.laboratoryequipment.com.
+api.facebook.com.
+itunes.apple.com.
+www.facebook.com.
+www.googletagservices.com.
+www.google.com.
+www.maturetubesite.net.
+20minutos.feedsportal.com.
+www.facebook.com.
+fr.maps.yahoo.com.
+aka-cdn-ns.adtech.de.
+fr.webrep.avast.com.
+a.root-servers.net.
+caminosdepoesia123.foro-colombia.net.
+www.historyforsale.com.
+cgp.pu.ru.
+151.204.31.190.in-addr.arpa.
+ec.atdmt.com.
+www.infoempleo.com.
+203.107.25.84.in-addr.arpa.
+www.facebook.com.
+connect.facebook.net.
+thumbs.ass4all.com.
+wiredepicenter.disqus.com.
+www.google-analytics.com.
+groups.google.com.mx.
+solutionmyworking.com.
+janakipattiskitchen.blogspot.com.
+226.204.106.187.in-addr.arpa.
+aspuru.unix.fas.harvard.edu.
+gidrogroup.ru.
+www.tsumorichisato.com.
+imp-6.mail.tiscali.it.
+148.33.87.24.in-addr.arpa.
+flash.quantserve.com.
+photos-c.ak.fbcdn.net.
+m.google.com.
+c7.zedo.com.
+247.157.41.68.in-addr.arpa.
+estede-m.ru.
+www.jordanalmonds.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+107.234.251.88.in-addr.arpa.
+eramatarealty.com.
+plus.google.com.
+www.riotsweb.com.
+www.cineplus.ch.
+api.bing.com.
+8.105.127.200.in-addr.arpa.
+ap.jil.com.
+upload.traidnt.net.
+www.google-analytics.com.
+www.bywifi.com.
+facebook.net.dnsbl7.mailshell.net.
+dns.msftncsi.com.
+p.rightaction.com.
+104.12.169.189.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+stuy.edu.
+37.143.253.159.in-addr.arpa.
+x4w19xc8e.93wa.
+plusone.google.com.
+a.root-servers.net.
+apple-mobile.query.yahooapis.com.
+28.media.tumblr.com.
+cartas_clow.frikitest.com.
+s-static.ak.facebook.com.
+adrianarojaspacheco.wordpress.com.
+adserving.cpxinteractive.com.
+24.18.93.114.in-addr.arpa.
+toolbarqueries.clients.google.com.
+www.goojue.com.
+www.ultimatelakehouston.com.
+www.aastra.com.
+s0.2mdn.net.
+www.google-analytics.com.
+mail.nimi24.com.
+shore.net.
+pt-br.facebook.com.
+sp.cwfservice.net.
+mail.bannerbatterien.com.
+p06-contacts.icloud.com.
+clothing.shop.ebay.com.
+176.93.206.190.in-addr.arpa.
+s6asmj1zy.k08f7n4q.
+safebrowsing-cache.google.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.juegos.com.cdngc.net.
+plushkacraft.blogspot.com.
+58.29.53.186.in-addr.arpa.
+dns.msftncsi.com.
+www.wordreference.com.
+i3.ytimg.com.
+pubads.g.doubleclick.net.
+hatch.com.au.
+191.150.142.75.in-addr.arpa.
+anticap.files.wordpress.com.
+es.justin.tv.
+www.tirateunpalo.net.
+cs9663.vk.com.
+www.google-analytics.com.
+hplusson.com.
+175.241.23.186.in-addr.arpa.
+onelinkpr.net.
+personalityl.ru.
+ocsp.verisign.com.
+www.kwausa.com.
+cdn.api.twitter.com.
+hernanbartra.blogspot.com.
+www.youtube.com.
+newsrss.bbc.co.uk.
+211.9.139.190.in-addr.arpa.
+www.youtube.com.
+a4.sphotos.ak.fbcdn.net.
+cherryredcasino.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+musica.temadictos.org.
+postmaster.co.uk.
+external.ak.fbcdn.net.
+blog3.fc2.com.
+www.solounminuto.org.ar.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+newsinfo.inquirer.net.
+signlite.com.
+cdmsllc.com.
+megabook.ru.
+97.69.118.200.in-addr.arpa.
+static.adwired.mobi.
+www.facebook.com.
+a2.sphotos.ak.fbcdn.net.
+antologia-de-poesia.blogspot.com.
+amazon-s.maxthon.com.
+ads.yimg.com.
+slc.manserve.com.
+office.azbukavkusa.ru.
+www.bing.com.
+photos-b.ak.fbcdn.net.
+cf.rr.com.
+caballerosdelaordendelsol.blogspot.com.
+www.kpm-usa.com.
+mx3.hotmail.com.
+mail.cg02.fr.
+4luq47dwi.q62o6p8x.
+16.147.220.66.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+i4.ytimg.com.
+s0.2mdn.net.
+imgserv.co.uk.
+rad.msn.com.
+www.sep.pue.gob.mx.
+mx2.meisterseelig.com.
+fbcdn-photos-a.akamaihd.net.
+partner.directadvert.ru.
+royalsociety.ru.
+www.cafeteritas.com.
+carolwoods.org.
+72.51.7.199.in-addr.arpa.
+curtisbrown.com.au.
+84.25.168.192.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.nytimes.com.
+tsm05.eset.com.
+168.137.99.85.in-addr.arpa.
+www.public-trust.com.
+tc.v9.cache3.c.youtube.com.
+www.facebook.com.
+www.4kotob.com.
+www.digi-panel.com.
+trevorhowell.wanadoo.co.uk.
+snacho.ru.
+rssgov.windows.microsoft.com.
+advolution.de.
+152.11.243.201.in-addr.arpa.
+www.adobe.com.
+es-la.facebook.com.
+lqp1muko6.53us.
+static.ak.fbcdn.net.
+google.com.
+google.com.
+a4.sphotos.ak.fbcdn.net.
+176.228.148.90.in-addr.arpa.
+www.crunchbase.com.
+banashare.com.
+216.225.193.190.in-addr.arpa.
+218.216.87.186.in-addr.arpa.
+jjjjjjjjjj.xsocks.net.
+209.18.253.190.in-addr.arpa.
+www.shoutcastunlimited.com.
+fr-fr.facebook.com.
+d2089471.xoom.it.
+visualpeacemakers.org.
+92.105.127.201.in-addr.arpa.
+medals.bizrate.com.
+db11.spamcatcher.net.
+ds.addthis.com.
+redtube.com.hypestat.com.
+smtap1.systems.smu.edu.
+186.63.0.10.in-addr.arpa.
+safebrowsing.clients.google.com.
+latam.msn.com.
+prod-nr203.voxer.com.
+p.twimg.com.
+mail.dhart.net.
+cgjeaf.com.
+_035_61_8.
+usadanet.net.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+go.microsoft.com.
+warrendalesales.com.
+www.alpamare.ch.
+tv4s11nsq.24vh.
+www.facebook.com.
+s.ytimg.com.
+controldevices.com.
+38.8.171.189.in-addr.arpa.
+asdjk.com.
+graph.facebook.com.
+www.joepastry.com.
+bt.gamesir.com.
+modpodgerocks.blogspot.com.
+155.173.205.190.in-addr.arpa.
+elcomercio.pe.
+www.tecandsup.com.
+photos-f.ak.fbcdn.net.
+nxx.com.
+doc.verycd.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+mx.youtube.com.
+comevamail.com.
+www.completemedicalservices.com.
+www.bestmovietrailer.info.
+a5.sphotos.ak.fbcdn.net.
+leydig.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.softahead.com.
+a.root-servers.net.
+w.sharethis.com.
+a2.sphotos.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+www.lancope.com.
+photos-b.ak.fbcdn.net.
+mail.delphiconstruction.net.
+ttlrcct2.qianqian.com.
+plugins.longtailvideo.com.
+a151.d.akamai.net.
+a5.sphotos.ak.fbcdn.net.
+servedby.adxpose.com.
+203.15.0.192.in-addr.arpa.
+brianproperties.com.s8b2.psmtp.com.
+program.avast.com.
+146.16.0.186.in-addr.arpa.
+cjkingent.blogspot.com.
+apps.facebook.com.
+api.twitter.com.
+www.facebook.com.
+mi-touch-y-yo.blogspot.com.
+fbcdn-profile-a.akamaihd.net.
+download115.avast.com.
+www.saary-up.com.
+tag.admeld.com.
+e566.b.akamaiedge.net.
+yahoo.com.
+a.root-servers.net.
+evolutionsportsscience.com.
+231.186.198.187.in-addr.arpa.
+b.scorecardresearch.com.
+www.google-analytics.com.
+support.google.com.
+agro.com.ru.
+rocha.la.
+d3lyqimqlfvq37.cloudfront.net.
+acv.com.au.
+a.root-servers.net.
+a.root-servers.net.
+www.oxfamblogs.org.
+46.courier-push-apple.com.akadns.net.
+a948.g.akamai.net.
+www.pizap.com.
+ads2.iforex.com.
+a.root-servers.net.
+165.42.78.201.in-addr.arpa.
+t0.gstatic.com.
+denison01.denisonhydraulics.com.
+www.bywifi.com.
+t0.gstatic.com.
+hi-in.facebook.com.
+www.elbebedemama.net.
+177.245.153.189.in-addr.arpa.
+www.google.com.
+vector.info.
+miblog-especialdominiotk.blogspot.com.
+photos-c.ak.fbcdn.net.
+secure.wlxrs.com.
+bcovekk.fcod.llnwd.net.
+www.vintaxe.com.
+www.sennheiser-sites.com.
+clpav.fr.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+mx1.ceres.k12.ca.us.
+s-static.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+exitmedia.net.
+support.google.com.
+78.195.86.77.in-addr.arpa.
+im3yy873m.y29t3i4l.
+www.gstatic.com.
+144.201.207.190.in-addr.arpa.
+apis.google.com.
+98.147.227.190.in-addr.arpa.
+theswingingsixties.tumblr.com.
+csf2-1.yobt.tv.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+200.200.10.186.in-addr.arpa.
+_436_35_9.
+staging-beacon-1.newrelic.com.
+p.ebaystatic.com.
+88.70.249.201.in-addr.arpa.
+ads.tlvmedia.com.
+a998.mm1.akamai.net.
+232.240.58.201.in-addr.arpa.
+www.facebook.com.
+mail.porterkhouwconsulting.com.
+www.expansion.net.
+173.57.147.187.in-addr.arpa.
+reefdevelopment.com.
+dsn9.d.skype.net.
+7.77.51.190.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+96.242.84.200.in-addr.arpa.
+www.facebook.com.
+s.ytimg.com.
+www.eternellepharma.com.
+yahoo.com.
+85.102.160.187.in-addr.arpa.
+mail.crestfoods.com.
+groups.live.com.
+gfx2.hotmail.com.
+mail.sigmamail.com.
+www.facebook.com.
+ec2-50-19-48-225.compute-1.amazonaws.com.
+smtp.fairadsl.co.uk.
+chrome.google.com.
+apps.facebook.com.
+www.sony.com.mx.
+zopf.ru.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+83.230.212.186.in-addr.arpa.
+www.conduit.com.
+creative.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.fileserve.com.
+www.update.microsoft.com.
+rad.msn.com.
+mail.intermountaintruck.com.
+ads.weownthetraffic.com.
+www.hotels.com.
+fsldjx.en.made-in-china.com.
+simplifiedofficesystems.com.
+profile.ak.fbcdn.net.
+.
+connect.facebook.net.
+geoip.vmn.net.
+toons.kharabeesh.com.
+d1.openx.org.
+72.153.130.201.in-addr.arpa.
+www.careerjet.com.mt.
+www.suvtracker.com.
+books.google.com.
+mx1.vostok.ru.
+www.gritos.com.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+fettemama.org.
+www.facebook.com.
+a.root-servers.net.
+haymarket.subscribeonline.co.uk.
+apple.com.
+smtp.hereweare.de.
+images.cdn.redtube.com.
+s.youtube.com.
+animeone.com.
+www.google.com.
+mail.eyrisgroup.com.
+www.netvibes.com.
+www.enelsexo.com.
+dantextil.dk.
+aalcliquers.files.wordpress.com.
+250.236.242.88.in-addr.arpa.
+www.lpn-to-rn.org.
+31.58.200.190.in-addr.arpa.
+i.streetmobster.net.
+www.adobe.com.
+a3.sphotos.ak.fbcdn.net.
+mobiletg.com.
+majesticfunding.net.
+euro.mediotiempo.com.
+254.233.190.186.in-addr.arpa.
+apps.facebook.com.
+35.116.168.192.in-addr.arpa.
+speaklolcat.com.
+photos-a.ak.fbcdn.net.
+www.familiainstitucional.com.
+www.peliculas-flv.com.
+www.thefashionshow.com.
+ar-ar.facebook.com.
+mail.dthsculptor.com.
+static.ak.fbcdn.net.
+gfx2.hotmail.com.
+mail.orsin.net.
+toastmasters.org.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+earthworksstudio.co.uk.
+s1.lemde.fr.
+0-167.channel.facebook.com.
+imail.mk.
+google.com.
+www.unonoticias.com.
+a.root-servers.net.
+nsx.sec.np.dl.playstation.net.
+touch.facebook.com.
+208.212.158.95.in-addr.arpa.
+ads.yimg.com.
+footballer.com.
+adserving.cpxinteractive.com.
+login.oscar.aol.com.
+googleads.g.doubleclick.net.
+www.keeway-america.com.
+photos-a.ak.fbcdn.net.
+24.114.41.92.in-addr.arpa.
+17.119.201.187.in-addr.arpa.
+c0013680.r32.cf1.rackcdn.com.
+mailserver.the-hopes.com.
+pixel.facebook.com.
+profile.ak.fbcdn.net.
+r.l.admob.com.
+us.bc.yahoo.com.
+csi.gstatic.com.
+a.root-servers.net.
+thecodingmassacre.wordpress.com.
+mail.wpi-europe.com.
+www.facebook.com.
+plusone.google.com.
+r._dns-sd._udp.0.244.16.172.in-addr.arpa.
+a937.g.akamai.net.
+checkip.dyndns.com.
+pokah.ru.
+a1.sphotos.ak.fbcdn.net.
+del.icio.us.
+anthrowebstage.endecaondemand.net.
+206.13.14.88.in-addr.arpa.
+evsecure-ocsp.verisign.com.
+registration.mercadolibre.com.mx.
+150.171.176.190.in-addr.arpa.
+www.snowtoit.com.
+37.137.237.64.in-addr.arpa.
+44.183.82.189.in-addr.arpa.
+3-courier.push.apple.com.
+m.hotmail.com.
+www.facebook.com.
+hollyta.en.alibaba.com.
+www.youtube.com.
+sophos.cbtri.com.
+ads.united.no.
+static.ak.fbcdn.net.
+staff.detik.com.
+www.sound.org.
+enterprise-secure-registration.com.
+crl.verisign.com.
+80.166.125.186.in-addr.arpa.
+pneutronics.com.
+tcr.tynt.com.
+www.nondisco.com.
+ocio.mundijuegos.com.
+www.google-analytics.com.
+watashikimakesou.blogspot.com.
+www.fundacionclaudionaranjo.com.
+www.youtube.com.
+bdm.careerbuilder.com.
+238.113.166.190.in-addr.arpa.
+idrops.terra.com.pe.
+www.bridgetmonet.net.
+b._dns-sd._udp.lan.
+www.aljazeera.com.
+br.pps.tv.
+206.163.252.72.in-addr.arpa.
+widgets.amung.us.
+hightechadv.com.
+www.nlm.nih.gov.
+www.google.com.
+a.root-servers.net.
+www.dsttspain.com.
+www.facebook.com.
+rt.liftdna.com.
+www.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+s1-word-edit.vo.msecnd.net.
+clients2.google.com.
+www.yournextskirt.com.
+29.209.57.187.in-addr.arpa.
+a.root-servers.net.
+www.tecnologia-e.com.
+a.root-servers.net.
+a.root-servers.net.
+googleads.g.doubleclick.net.
+time.nist.gov.
+www.youtube.com.
+contrib.com.
+jndlparmbjimenvchwxek.sc.
+maktoob.omg.yahoo.com.
+s-static.ak.fbcdn.net.
+v1.nonxt1.c.android.clients.google.com.
+29.53.21.187.in-addr.arpa.
+w5v1ulxw2.04kd.
+a8.sphotos.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+dingtao333.3322.org.
+dc105.4shared.com.
+apps.facebook.com.
+platform.ak.fbcdn.net.
+csi.gstatic.com.
+tc23.easythumbhost.com.
+scripts.
+102.15.229.190.in-addr.arpa.
+fantasyart.ru.
+ad.doubleclick.net.
+heartbeat.belkin.com.
+usersystem783aa.ru.
+7mxjnpfl3.e01g5z0j.
+135.119.217.87.in-addr.arpa.
+130.153.56.186.in-addr.arpa.
+www.livejournal.com.
+paraguay.clasificadoya.com.
+karaokekm3.com.
+a6.sphotos.ak.fbcdn.net.
+174.230.209.201.in-addr.arpa.
+msnvidweb.vo.msecnd.net.
+mail.mnui.com.
+feeds.ovi.com.
+promo.badoink.com.
+www.fc-moto.com.
+static.nfilesystem.com.
+static.ak.fbcdn.net.
+intermed.com.
+132.95.158.200.in-addr.arpa.
+www.campbells.com.mx.
+a.mx.moatsconsulting.com.
+v3.nonxt5.c.youtube.com.
+30.227.107.46.in-addr.arpa.
+www.fayereaganclub.com.
+pixel.facebook.com.
+photos-a.ak.fbcdn.net.
+banners.killtro.com.
+apis.google.com.
+ads.bluelithium.com.
+switch.atdmt.com.
+132.113.97.93.in-addr.arpa.
+static.ak.fbcdn.net.
+dnl-01.geo.kaspersky.com.
+mail.betsbv.com.
+s3pu.blogspot.com.
+www.visa.com.ar.
+d2x3khweh61zds.cloudfront.net.
+a.root-servers.net.
+www.rockchalktalk.com.
+bloger.co.
+youcantcallitit.com.
+www.sparwelt.de.
+www.samwha.com.
+external.ak.fbcdn.net.
+_037_08_7.
+img.yktravelphoto.com.
+215.125.153.201.in-addr.arpa.
+ixefirl:h.57bm.
+yugiohsanluis.blogspot.com.
+a7.sphotos.ak.fbcdn.net.
+content.nuvid.com.
+kellpkthpxrmppdr.info.
+ot2wp1mu:.05yd.
+googleads.g.doubleclick.net.
+a-0.19-a20c8079.d1b0083.1518.19d4.3ea1.410.0.1pgnhn5gu7ln3cqlh44lr7nf2j.avqs.mcafee.com.
+47.149.220.66.in-addr.arpa.
+134.100.70.58.in-addr.arpa.
+9gag.com.
+mx.folksam.se.
+img843.imageshack.us.
+fbcdn-profile-a.akamaihd.net.
+230.104.111.78.in-addr.arpa.
+23.159.102.201.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+teredo.ipv6.microsoft.com.
+3.bp.blogspot.com.
+www.soloimportastu.com.
+a4.sphotos.ak.fbcdn.net.
+lycoos.com.
+counterpixel.beiersdorf.com.
+static.ak.fbcdn.net.
+hi-in.facebook.com.
+a.root-servers.net.
+239.203.14.187.in-addr.arpa.
+google.com.
+www.ownerchats.com.
+www.mugutu.com.
+221.165.83.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+mail.dgen.com.
+mfe5.polimi.it.
+www.wmaker.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+134.240.194.90.in-addr.arpa.
+dg.specificclick.net.
+85.167.21.189.in-addr.arpa.
+o1.t26.net.
+www.mercator-publicitor.fr.
+www2.cbox.ws.
+a1.sphotos.ak.fbcdn.net.
+1.bp.blogspot.com.
+.
+sites.google.com.
+balticbulges.blogspot.com.
+10.122.0.190.in-addr.arpa.
+cdn.ad4game.com.
+video.google.com.mx.
+api-read.facebook.com.
+camba.com.
+a4.sphotos.ak.fbcdn.net.
+87.190.56.186.in-addr.arpa.
+safebrowsing-cache.google.com.
+62.94.120.186.in-addr.arpa.
+nswlant.navy.mil.
+video-stats.l.google.com.
+myworld.ebay.com.
+time.windows.com.
+ocsp.verisign.com.
+syednetworks.com.
+246.53.66.187.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+tools.google.com.
+safebrowsing-cache.google.com.
+158.58.69.190.in-addr.arpa.
+152.129.79.84.in-addr.arpa.
+a.root-servers.net.
+saur.spbnit.ru.
+photos-a.ak.fbcdn.net.
+twitter.com.
+billing.sharo4ka.ru.
+elrecreodelasmamis.foroactivo.com.
+tetonvalley.net.microserv.s5a1.psmtp.com.
+local-bay.contacts.msn.com.
+clients1.google.com.
+ology.com.
+27.199.201.190.in-addr.arpa.
+www.juegosdiarios.com.
+vm1.yorku.ca.
+12.240.16.95.in-addr.arpa.
+cdn.api.twitter.com.
+juegosdemaquillar.com.mx.
+fr-fr.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+108.249.44.200.in-addr.arpa.
+echo.edge.messenger.live.com.
+140.208.224.189.in-addr.arpa.
+164.68.93.186.in-addr.arpa.
+www.awaite.
+d.mybustymilf.com.
+sundries.ru.
+tmss-p.activeupdate.trendmicro.com.
+platform.twitter.com.
+te.net.ru.
+13.129.156.75.in-addr.arpa.
+grossaer.ru.
+a5.sphotos.ak.fbcdn.net.
+homeinstead.com.s5a1.psmtp.com.
+a.root-servers.net.
+323436891.mail.outlook.com.
+coweta.lib.ok.us.
+www.allmetsat.com.
+tairesources.com.
+informativos.net.
+s-static.ak.fbcdn.net.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+www.bbc.co.uk.
+244.13.208.189.in-addr.arpa.
+a.root-servers.net.
+i2.ytimg.com.
+csi.gstatic.com.
+sn1msg2010733.gateway.messenger.live.com.
+photos-f.ak.fbcdn.net.
+_644_73_6.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+www.farmacopedia.com.mx.
+151.83.131.50.in-addr.arpa.
+srv.main.ebayrtm.com.
+atd.com.
+s.ytimg.com.
+kvnews.ru.
+photos-a.ak.fbcdn.net.
+www.listaviral.com.
+google.com.
+14.184.82.186.in-addr.arpa.
+ad.doubleclick.net.
+ecx.images-amazon.com.
+www.theserved.com.
+www.agri-pulse.com.
+cdn.tynt.com.
+7pdqahw6d.r80t1q9z.
+static.ak.fbcdn.net.
+147.9.109.79.in-addr.arpa.
+www.roshan.mobie.in.
+join.gayasianamateurs.com.
+www.blog-emprendedor.info.
+api-read.facebook.com.
+l.live.net.
+ci.atlanta.ga.us.
+10.1.168.192.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+comark.corp.com.
+.
+tc.v5.cache7.c.youtube.com.
+rospres.com.
+twitter.com.
+aka-cdn-ns.adtech.de.
+101.213.143.95.in-addr.arpa.
+www.filmdept.com.
+twitter.com.
+56.214.57.186.in-addr.arpa.
+a.root-servers.net.
+www.micro-machine-shop.com.
+ocsp.verisign.com.
+profile.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+www.facebook.com.
+profile.ak.fbcdn.net.
+fr.boats.com.
+rblns75.mailshell.net.
+developers.facebook.com.
+img802.imageshack.us.home.
+205.4.66.201.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+thesaurus.com.
+home.disneylatino.com.
+pmanet.org.
+jv.wikipedia.org.
+www.glendalenewspress.com.
+a.root-servers.net.
+mx1.gddinstrumentation.com.
+fm100.fm.monroeclinic.org.
+0-jf-w.channel.facebook.com.
+www.mintebay.com.
+apiit.edu.my.
+fbcdn-photos-a.akamaihd.net.
+i3.bzpics.com.
+fxozjsbm6.j35r5o3r.
+170.193.102.177.in-addr.arpa.
+170.21.220.189.in-addr.arpa.
+accreditation.aus.com.
+kerrmachine.com.
+a.root-servers.net.
+www.mikeybustos.ca.
+tcgroup.net.
+static02.linkedin.com.
+www.anyads.lk.
+oldnavy.gap.com.
+unifi.
+google.com.
+photos-d.ak.fbcdn.net.
+1.231.21.187.in-addr.arpa.
+www.vklogger.com.
+www.fizik.it.
+126.195.172.201.in-addr.arpa.
+mail.google.com.
+toolbar.google.com.mx.
+db2.stb00.s-msn.com.
+ppspackaging.com.inbound15.mxlogicmx.net.
+photos-c.ak.fbcdn.net.
+cust14283-2.in.mailcontrol.com.
+www.miniclip.com.
+mail.google.com.
+192.143.248.201.in-addr.arpa.
+rd.apmebf.com.
+master14.teamviewer.com.
+cdn.gigya.com.
+www.findppc.net.
+photos-f.ak.fbcdn.net.
+www.newy8games.com.
+mgw.serverparkering.no.
+profile.ak.fbcdn.net.
+217.163.186.86.in-addr.arpa.
+comcolease.com.s5b2.psmtp.com.
+mx3.start.ca.
+76.19.44.187.in-addr.arpa.
+02261e64b3.org.
+150.8.0.10.in-addr.arpa.
+lechim-bolezni.ru.
+50.177.168.192.in-addr.arpa.
+recover-my-files.softonic.com.
+api.modegallerian.se.
+fe.brandreachsys.com.
+62.29.117.200.in-addr.arpa.
+morrieabramson.com.
+scrub.bluekloud.com.
+titanium30-en.url.trendmicro.com.
+apps.facebook.com.
+51.0.0.192.in-addr.arpa.
+syndication.exoclick.com.
+ar.y8.com.
+cmbinfo.com.s8b1.psmtp.com.
+jj13bk2j1.91nd.
+gui.m.mofos.com.
+_045_80_9.
+isatap.uqc.ne.jp.
+orcart.facebook.com.
+138.171.48.190.in-addr.arpa.
+b-0.19-230f4008.1.1518.19d4.3ea1.410.0.65wlql4n1en4fh5da6mrnh7gai.avqs.mcafee.com.
+photos-b.ak.fbcdn.net.
+iitem.ru.
+ocsp.comodoca.com.
+pbsmnwubnxhutgmod.ms.
+posta39a.mailbeta.libero.it.
+badge.facebook.com.
+www.kmplayer.com.
+mail.wilcopm.com.
+bbmwlaw.com.1.arsmtp.com.
+www.videobb-ideal.com.
+ibahia.globo.com.
+.
+sobrecostarica.blogspot.com.
+a.root-servers.net.
+www.caltagironeeditore.it.
+59.2.164.189.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.google.com.
+the-uuu.com.
+i.w.inmobi.com.
+webcache.googleusercontent.com.
+131.114.139.187.in-addr.arpa.
+s-static.ak.fbcdn.net.
+mail.shoptools.ru.
+apps.facebook.com.
+ecosca.mass.rbc.ru.
+maconleadersrealtors.com.
+pipocacombo.com.
+www.youtube.com.
+api.facebook.com.
+dns.msftncsi.com.
+i1.uploadem.com.
+clickmaster.xtgem.com.
+6.51.67.70.in-addr.arpa.
+profile.ak.fbcdn.net.
+de.wikibooks.org.
+photos-f.ak.fbcdn.net.
+140.132.46.186.in-addr.arpa.
+48.81.95.201.in-addr.arpa.
+dns.msftncsi.com.
+84.228.102.201.in-addr.arpa.
+yavmamemo.deviantart.com.
+contacts.msn.com.nsatc.net.
+ocsp.verisign.com.
+aol.com.
+pabloyyo.com.
+german-uribe.blogspot.com.
+fr-fr.facebook.com.
+a.root-servers.net.
+218.84.12.189.in-addr.arpa.
+www.forosdelweb.com.
+a7.sphotos.ak.fbcdn.net.
+4-1.qlty.finarea.ch.
+a.root-servers.net.
+www.juegosdevestirfamosos.net.
+_924_86_1.
+claydyergess.tk.
+huaren.su.
+8.75.188.190.in-addr.arpa.
+s-static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+soundcloud.com.
+elminaya.blogspot.com.
+wlan.lycos.de.
+cdn.api.twitter.com.
+lubimoff.msk.ru.
+a.root-servers.net.
+205.166.141.120.in-addr.arpa.
+www.tubemonsoon.com.
+dibisrl.com.
+m.badjojo.com.
+a1404.w41.akamai.net.
+6.103.153.186.in-addr.arpa.
+static.ak.fbcdn.net.
+136.149.120.190.in-addr.arpa.
+googleads.g.doubleclick.net.
+www.peliculas21.com.
+229.144.179.189.in-addr.arpa.
+cache-download.real.com.
+c1617.sandai.net.
+polypeck.ru.
+www.solomonbrothers.com.
+www.alimtyaz.com.
+libera.com.
+dmsas.com.s8a1.psmtp.com.
+photos-g.ak.fbcdn.net.
+ssl.gstatic.com.
+www.amazon.com.
+bfgb.files.wordpress.com.
+_753_33_3.
+www.google.com.
+223.55.167.190.in-addr.arpa.
+google.com.
+mx1.iacna.com.
+167.127.144.187.in-addr.arpa.
+twitter.com.
+183.196.84.200.in-addr.arpa.
+servizio-pubblico.com.
+www.iconj.com.
+conduit.anybodyoutthere.com.
+crl.microsoft.com.
+www.mizukinana.jp.
+16.253.137.187.in-addr.arpa.
+www.adobe.com.
+20minutos.feedsportal.com.
+scholar.google.es.
+www.youtube.com.
+ajax.googleapis.com.
+www.foxsportsla.com.
+www.yorkpress.co.uk.
+215.238.247.189.in-addr.arpa.
+haverford.edu.s8a2.psmtp.com.
+www.archiexpo.com.
+i4.ytimg.com.
+jsbcglobal.net.
+www.robertbrault.com.
+cdn.api.twitter.com.
+news.err.ee.
+ajax.googleapis.com.
+a1.twimg.com.
+photos-e.ak.fbcdn.net.
+60.32.41.187.in-addr.arpa.
+brucellosis.com.
+fbcdn-sphotos-a.akamaihd.net.
+photos-d.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.beijingtoday.com.cn.
+hi-in.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+www.delirica.com.
+a7.sphotos.ak.fbcdn.net.
+253.104.217.81.in-addr.arpa.
+is.gd.
+www.dollstory.eu.
+i2.ytimg.com.
+www.ozgurkocaeli.com.tr.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+34.114.74.190.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+www.youtube.com.
+seabld.itn.ru.
+s-static.ak.fbcdn.net.
+cdn.flashtalking.com.
+k9bhl94w3.16gn.
+payment.socialgamenet.com.
+dnl-01.geo.kaspersky.com.
+_493_32_4.
+mail.hubbardberry.com.
+a.root-servers.net.
+thelawstore.co.uk.
+67.201.176.189.in-addr.arpa.
+jigsaw.w3.org.
+polskaviva.com.
+mail.avu.org.
+131.244.142.190.in-addr.arpa.
+a.root-servers.net.
+ad.adtegrity.net.
+masae.deviantart.com.
+www.pmi.org.in.
+149.150.195.187.in-addr.arpa.
+roverparts.spb.ru.
+takio.com.
+majeko.ru.
+support.google.com.
+banboon.com.
+vfs.com.s10a1.psmtp.com.
+www.eluniversaldelvalle.mx.
+a.root-servers.net.
+b._dns-sd._udp.0.73.168.192.in-addr.arpa.
+chesterfield.k12.va.us.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cache.internal.query.g06.yahoodns.net.
+xxzrg8djy.37xo.
+ingersoll-inc.com.
+i.cdn.turner.com.
+100.214.18.189.in-addr.arpa.
+view.atdmt.com.
+dl_dir.qq.com.
+dtboot.orbitdownloader.com.
+219.61.25.186.in-addr.arpa.
+platform.twitter.com.
+lyramondlicht.deviantart.com.
+www.idiomasonline-ba.com.ar.
+devices.live.com.
+126.39.51.96.in-addr.arpa.
+mail.cygnuscorp.com.
+sweetgum.nybg.org.
+www.panet.co.il.
+a8.sphotos.ak.fbcdn.net.
+4.1.168.192.in-addr.arpa.
+www.stopbadware.org.
+tmss.trendmicro.com.
+api.facebook.com.
+inbound.sgsproperties.com.netsolmail.net.
+d2089876.xoom.it.
+www.cakgames.com.
+fs.motorolasolutions.com.
+89.152.195.98.in-addr.arpa.
+extremetracking.com.
+crl3.digicert.com.
+prenoms.doctissimo.fr.
+webcache.googleusercontent.com.
+www.farsiweb.ir.
+mxh24.hichina.com.
+www.vizio.com.
+profile.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+mundicenter.pt.
+billing.sharo4ka.ru.
+mail.peteparks.com.
+a.root-servers.net.
+ntp.glb.nist.gov.
+a.root-servers.net.
+www.0zz0.com.
+verizon.net.
+grocerybiz.com.s8a1.psmtp.com.
+192.168.34.201.in-addr.arpa.
+76.217.139.190.in-addr.arpa.
+166.142.160.187.in-addr.arpa.
+jualanterkini.blogspot.com.
+fs11.myvi.ru.
+a4.sphotos.ak.fbcdn.net.
+theforwardforum.blogspot.com.
+safebrowsing-cache.google.com.
+nipinxofutbol.blogspot.com.
+ocsp.verisign.net.
+www.original-vision.com.
+249.108.79.187.in-addr.arpa.
+g.msn.com.nsatc.net.
+botrytis.polytechnique.fr.
+fifo.com.
+www.self.ox.ac.uk.
+j::88wcuv.r19p2l8b.
+87.16.57.187.in-addr.arpa.
+152.184.55.65.in-addr.arpa.
+cepram.org.ar.
+1.0.168.192.in-addr.arpa.
+twitter.com.
+www.google.com.
+clientalerts.ebay.com.
+sinobbs.com.
+independent.org.
+drugstorenews.com.
+a2.sphotos.ak.fbcdn.net.
+groups.l.google.com.
+mobilemaps.clients.google.com.
+s0.2mdn.net.
+a.root-servers.net.
+www.sonico.com.mx.
+lmliberty.files.wordpress.com.
+adserver.adtech.de.
+audit.303br.net.
+accounts.google.com.
+www.aewmerotica.com.
+photos-d.ak.fbcdn.net.
+max.ifd.uni.wroc.pl.
+news.yahoo.com.
+mx.harborinsurancegroup.com.
+mail.google.com.
+75.175.75.190.in-addr.arpa.
+130.71.15.187.in-addr.arpa.
+it-it.facebook.com.
+elbuenvecino.com.mx.
+a.root-servers.net.
+www.circuloempresariosune.com.
+touraero.spb.ru.
+mx1.unicitynetwork.com.
+pacificcoastimports.com.
+190.101.50.186.in-addr.arpa.
+4.77.168.66.in-addr.arpa.
+franklin.kyschools.us.
+qe8jid8px.12as.
+a0.twimg.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+srsg.violenceagainstchildren.org.
+588-async.olark.com.
+photos-a.ak.fbcdn.net.
+produccionmusical.org.
+fukuya-k.co.jp.
+balcakoyu.com.
+safebrowsing.clients.google.com.
+initialvision.com.
+www.facebook.com.
+img413.imageshack.us.
+190.147.229.190.in-addr.arpa.
+safebrowsing.clients.google.com.
+plugin.maldi.tv.
+aa.xml.slide.com.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+www.mozilla-europe.org.
+client.akamai.com.
+elsys.de.
+nxcache.nexon.net.
+perfectpay.com.
+tomam.ru.
+a1.sphotos.ak.fbcdn.net.
+63.6d6963726f736f6674.636f6d.80h40041e86.webcfs00.com.
+46.158.220.66.in-addr.arpa.
+www.infolinks.com.
+api.breaktimestudios.com.
+cncsjz.line.p2pdl.baofeng.net.
+49.30.78.189.in-addr.arpa.
+spotlight-verlag.de.
+84.211.144.189.in-addr.arpa.
+tamcar.galeon.com.
+sp.cwfservice.net.
+2:iw9t7:u.n05r1n1r.
+fbcdn-sphotos-a.akamaihd.net.
+wix.com.
+l.yimg.com.
+134.55.156.187.in-addr.arpa.
+facor.ru.
+www.google-analytics.com.
+time.stdtime.gov.tw.
+i4.ytimg.com.
+imgv2-4.scribdassets.com.
+0.gravatar.com.
+0.11-a30f2081.d0810b1.1518.19d4.3ea1.210.0.2pqgphplpzu9q1ej3p6m28uv2q.avqs.mcafee.com.
+www.etnopsico.org.
+sn3.mailshell.net.
+exchange.volioytrejos.com.
+365-async.olark.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+114.218.12.83.in-addr.arpa.
+5.1.168.192.in-addr.arpa.
+computerscan.com.
+a.root-servers.net.
+7nbeknju7.43vi.
+images.dvdcollects.com.
+static.app.widdit.com.
+platform.ak.fbcdn.net.
+_119_63_8.
+css.wlxrs.com.
+p2pupgrade.gamedl.qq.com.
+196.15.95.190.in-addr.arpa.
+js2.wlxrs.com.
+amosrivera.com.
+static.ak.fbcdn.net.
+download.xbox.com.
+www.blush4u.com.
+www.genteloca.com.
+crl.globalsign.net.
+infocentertour.ru.
+www.coniefoxdress.com.
+news.mongabay.com.
+231.230.121.76.in-addr.arpa.
+news.google.com.mx.
+mail.prodigy.net.mx.
+63.1.168.192.in-addr.arpa.
+0-257.channel.facebook.com.
+www.all-4-home.net.
+i4.ytimg.com.
+whos.amung.us.
+thecreaturehub.com.lan.
+a.root-servers.net.
+bitly.com.
+init.ess.apple.com.
+www.radiotorre.org.
+coralhotels.com.
+atna.net.
+d1z5wd2gcq19yd.cloudfront.net.
+ad.auditude.com.
+a5.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+142.134.175.187.in-addr.arpa.
+www.plusgay.es.
+www.facebook.com.
+especiales.latino.msn.com.
+google.com.
+vp.sip.messenger.msn.com.
+www.youtube.com.
+www.google.com.
+162.33.248.189.in-addr.arpa.
+pearsoncustom.com.mail6.psmtp.com.
+developers.facebook.com.
+lvb.avg.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+0.260214.com.
+lvb.avg.com.
+mail.eatrightamerica.com.
+www.facebook.com.
+a.root-servers.net.
+www.facebook.com.
+xdsmhost.wellmark.com.
+a.root-servers.net.
+www.google-analytics.com.
+mail.villagehamburg.com.
+adcode.adengage.com.
+a3.sphotos.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+www.trinityatierra.com.
+connect.facebook.net.
+parlament-kbr.ru.
+144.179.100.94.in-addr.arpa.
+static.ak.fbcdn.net.
+s0.2mdn.net.
+ocsp.digicert.com.
+www.acfas.org.
+barakus.tiscali.com.
+www.googleadservices.com.
+static.ak.fbcdn.net.
+blu.stj.s-msn.com.
+www.taringa.net.
+revistadcasa.uol.com.br.
+allstarhomeloans.com.
+letmewatch.name.
+a1.sphotos.ak.fbcdn.net.
+m.addthisedge.com.
+www.ferrovial.com.
+sterneagee.com.
+w1197.photobucket.com.
+224.147.99.190.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+s-external.ak.fbcdn.net.
+www.gstatic.com.
+www.juegosycoches.com.
+wikimediafoundation.org.
+www.geom.uiuc.edu.
+www.igihe.com.
+a4.sphotos.ak.fbcdn.net.
+www.linkwithin.com.
+gats.popcap.com.
+es.youtube.com.
+www.facetofacethemovie.com.
+189.224.188.88.in-addr.arpa.
+poetashispanicos.blogspot.com.
+ksn2-12.kaspersky-labs.com.
+zone28.hotwords.com.br.
+negro004.com.
+s.youtube.com.
+losfueroscf.com.
+wtol.com.
+32.170.248.189.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+www.facebook.com.
+www.limelife.com.
+ksn1-11-part2.kaspersky-labs.com.
+download767.avast.com.
+www.starmedia.com.
+82.247.231.201.in-addr.arpa.
+webmail.beumer.com.
+103.80.208.201.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+rules.securestudies.com.
+yahoo.com.
+ads.affbuzzads.com.
+clients1.google.com.
+photos-e.ak.fbcdn.net.
+foxdeportes.com.
+62.63.169.124.in-addr.arpa.
+tracker.torrentbay.to.
+www.sai.org.co.
+202.94.122.200.in-addr.arpa.
+track.hardcoretoons.com.
+0-292.channel.facebook.com.
+hi-in.facebook.com.
+www.google.com.
+www.revodvr.com.
+8muy7vane.88hx.
+schroff.com.
+flashpirate.com.
+a6.sphotos.ak.fbcdn.net.
+b7dktcdu4.k87r2j0h.
+jp.99chats.com.
+secure.jwatch.org.
+79.251.181.189.in-addr.arpa.
+59.125.191.190.in-addr.arpa.
+6.00.2900.3698.dnsbl7.mailshell.net.
+twimg0-a.akamaihd.net.
+t4.tagstat.com.
+a286.phobos.apple.com.
+profile.ak.fbcdn.net.
+58.82.42.62.in-addr.arpa.
+compfxnet.com.
+nice-puppy.com.
+sv.wikipedia.org.
+gdata.youtube.com.
+www.todoanimes.com.
+1.courier-push-apple.com.akadns.net.
+7daycatering.co.uk.
+s9.addthis.com.
+www.converthub.com.
+com.ua.
+25qd3ix24.i51d4x9f.
+translate.google.com.mx.
+hedltindia.com.
+www.genogenogeno.com.
+t2.gstatic.com.
+rmd.atdmt.com.
+bb624022.linkbucks.com.
+www.altoatacama.cl.
+valuerichonline.com.
+teredo.ipv6.microsoft.com.
+profile.ak.fbcdn.net.
+iparadigms.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+m.facebook.com.
+midas.org.uk.
+equest.com.
+21.152.248.201.in-addr.arpa.
+kyuketsuki-usagi.blogspot.com.
+www.vol-gta.com.
+a.root-servers.net.
+flindal.ru.
+sadasdnwqjrrww.net.
+a1984.phobos.apple.com.
+128.2.14.186.in-addr.arpa.
+uralsib-sk.ru.
+sc.tom.com.
+api.twitter.com.
+234.13.206.196.in-addr.arpa.
+phart.ru.
+www.mywebproxies.com.
+www.napcor.com.
+profile.ak.fbcdn.net.
+hgvjrr2pu.r86a6w5y.
+184.47.250.201.in-addr.arpa.
+www.dhl.com.uy.
+www.google.com.
+www.bezz41.skyrock.com.
+www.picshared4free.com.
+ke33aeg:m.a48a7y2z.
+video.humanesociety.org.
+vladgsound.wordpress.com.
+time.chttl.com.tw.
+columbuspolice.org.
+agromash.by.
+photos-h.ak.fbcdn.net.
+www.imiclk.com.
+oblogdeeoblogda.wordpress.com.
+pipic.com.s5a1.psmtp.com.
+187.63.111.189.in-addr.arpa.
+36.128.93.190.in-addr.arpa.
+data.mobclix.com.
+kupperberg.com.
+112.228.90.200.in-addr.arpa.
+storage.conduit.com.
+i4.ytimg.com.
+photos-c.ak.fbcdn.net.
+twoo.com.
+youtube-ui.l.google.com.
+telekbird.com.cn.
+www.animacor.com.
+_419_13_9.
+es.888.com.
+ocsp.verisign.com.
+profile.ak.fbcdn.net.
+apps.facebook.com.
+platform.twitter.com.
+ads.channelcapital.net.
+googleads.g.doubleclick.net.
+lazarus.elte.hu.
+mail.phillipsind.com.
+www.crankshaftcoalition.com.
+pixel.facebook.com.
+www.danielaperfumes.cl.
+www.microsoft.com.
+photos-b.ak.fbcdn.net.
+time-a.netgear.com.
+120.62.172.189.in-addr.arpa.
+robrprsmtp01.csavgroup.com.br.
+ad.xtendmedia.com.
+orcart.facebook.com.
+www.hoerzu.de.
+www.dripirrigation.org.
+tracker.bittorrent.am.
+photos-f.ak.fbcdn.net.
+not-mail.avfsrv.ru.
+a.root-servers.net.
+a.root-servers.net.
+131.70.239.189.in-addr.arpa.
+www.djcrazychris.de.
+.
+paris-dl.ru.
+114.130.189.79.in-addr.arpa.
+rwsytm82g.l62f8c0h.
+ronees.unets.ru.
+www.condusef.futbolfinanciero.com.mx.
+profile.ak.fbcdn.net.
+dj.renren.com.
+64.112.100.189.in-addr.arpa.
+ox-m.d.chango.com.
+ventechtrain.com.
+creative.ak.fbcdn.net.
+www.barranquilla.gov.co.
+www.facebook.com.
+d2091148.xoom.it.
+sk.wikipedia.org.
+login.live.com.
+49.133.168.192.in-addr.arpa.
+digital.com.
+www.stopbadware.org.
+login.live.com.
+tools.buzzwestcash.com.
+static.chartbeat.com.
+photos-b.ak.fbcdn.net.
+187.214.8.201.in-addr.arpa.
+wlcmail.com.
+rexel.cl.
+118.163.173.189.in-addr.arpa.
+bit.ly.
+dl34.hotgoo.com.
+luissanchez.deviantart.com.
+content.dl-rms.com.
+bit.ly.
+a.root-servers.net.
+14.144.148.46.in-addr.arpa.
+regalad.com.tw.
+go.srvnow.com.
+v4.cache5.c.youtube.com.
+171.228.244.190.in-addr.arpa.
+www.shesabetty.com.
+api-read.facebook.com.
+a.root-servers.net.
+chaussuralacarte.com.
+www.viewleicester.co.uk.
+newmail.to.pager.tascom.ru.
+baycom.com.tw.
+48.149.220.66.in-addr.arpa.
+_ldap._tcp.
+dns.msftncsi.com.
+_425_86_2.
+www.facebook.com.
+174.84.232.84.in-addr.arpa.
+ad.metanetwork.com.
+optusnet.coma.u.
+a.root-servers.net.
+correodepuntadeleste.com.
+ticketland.ru.
+174.86.214.189.in-addr.arpa.
+c.msn.com.
+holsten.gtn.ru.
+google.com.
+cdn.api.twitter.com.
+gohealthcast.com.inbound15.mxlogic.net.
+www.chandal.tv.
+mx1.comcast.com.
+www.hotmail.com.
+loieqeeu.name.
+api.geo.kontagent.net.
+www.comunio.es.
+0-44.channel.facebook.com.
+www.facebook.com.
+42.187.178.190.in-addr.arpa.
+www.surgedirect.com.
+www.peeperz.com.
+nakcumrrt.32lx.
+c-0.19-31096008.82.1518.19d4.36d4.400.0.3ku5gfh9hvtfb5rsdblk41wvsb.avqs.mcafee.com.
+www.milenio.com.
+ve.starmedia.com.
+creative.ak.fbcdn.net.
+www.scienceviews.com.
+7mo-cbime.blogspot.com.
+hotmail.com.
+pagead2.googlesyndication.com.
+www.britishmotorcyclegear.com.
+ciengarabatos.blogspot.com.
+www.stvgroup.cz.
+46.139.206.186.in-addr.arpa.
+179.134.247.72.in-addr.arpa.
+www.wooaudio.com.
+www.youtube.com.
+hi-in.facebook.com.
+a2.sphotos.ak.fbcdn.net.
+mango-skin-pack.softonic.com.
+malosocityperu.blogspot.com.
+60.218.9.70.in-addr.arpa.
+sissonscale.com.
+6.188.172.189.in-addr.arpa.
+a17.phobos.apple.com.
+d2092950.xoom.it.
+bgky.com.
+platform.twitter.com.
+sites.google.com.
+www.howtofixcomputers.com.
+4.20.12.108.in-addr.arpa.
+www.google.com.
+wz2s.taobao.com.
+104.2.4.64.in-addr.arpa.
+asset1.modelmanagement.com.
+apps.facebook.com.
+mailhost.dynaloy.com.
+87.8.34.186.in-addr.arpa.
+a.root-servers.net.
+dogtimemedia.squarespace.com.
+estilos.prodigy.msn.com.
+83.65.69.189.in-addr.arpa.
+kissphoto.net.
+ec.atdmt.com.
+wellthatsjustme.blogspot.com.
+t0.gstatic.com.
+google.com.
+bitkoo.com.
+fbcdn-sphotos-a.akamaihd.net.
+216.111.131.189.in-addr.arpa.
+google.com.
+photos-b.ak.fbcdn.net.
+girl.bodyartgo.com.
+ttjmhy6jq.23ra.
+smtp3.everyday.com.kh.
+ns.orenburg-cci.ru.
+linkhelp.clients.google.com.
+vostok.vladpost.marine.su.
+newsrss.bbc.co.uk.
+www.amazon.fr.
+api.twitter.com.
+dns.msftncsi.com.
+www.xemtiep.com.
+63.23.190.88.in-addr.arpa.
+www.astrobot.eu.
+img233.imageshack.us.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+pt-br.facebook.com.
+ping3.teamviewer.com.
+dinorun03.xgenstudios.com.
+csi.gstatic.com.
+wirelessretailinc.com.s8b2.psmtp.com.
+ds.serving-sys.com.
+www.be.
+71.169.55.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+windows-server-training.com.
+thebeaveronline.co.uk.
+www.youtube.com.
+wpad.
+mail.chtivo.ru.
+lolkaaaaa3.in.
+mccane.co.uk.
+www.criollosperuanos.com.
+251.159.200.112.in-addr.arpa.
+i3.ytimg.com.
+187.200.53.187.in-addr.arpa.
+www.el-guru.com.
+distfiles.macports.org.
+graph.facebook.com.
+6d70.61706d656266.636f6d.80hd822cfb1.webcfs00.com.
+lisa42.hubpages.com.
+video-1-11.rutube.ru.
+226.129.87.190.in-addr.arpa.
+antropologiayecologiaupel.blogspot.com.
+plugin.maldi.tv.
+a.root-servers.net.
+rcp.na.blackberry.com.
+97.231.134.115.in-addr.arpa.
+wanadoo.de.
+colingasm.tumblr.com.
+server4.operamini.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+ontariodie.com.s8b2.psmtp.com.
+43.146.106.186.in-addr.arpa.
+navy.net.
+i4.ytimg.com.
+marketing.menasoftware.com.
+houseplants-care.blogspot.com.
+powersonic.net.2.0001.arsmtp.com.
+85.239.65.187.in-addr.arpa.
+70.23.224.78.in-addr.arpa.
+selena-tour.ru.
+sbcglobal.net.
+www.obloggeral.com.
+api.facebook.com.
+2.bp.blogspot.com.
+www.irc-hispano.es.
+www.bluempegs.com.
+profile.ak.fbcdn.net.
+ssl.gstatic.com.
+autocrib.com.
+_042_76_7.
+mikutankyu.blog132.fc2.com.
+ist1-3.filesor.com.
+cdn-0.nflximg.com.
+110.251.64.202.in-addr.arpa.
+arizona.aaa.com.
+riskmetrics.com.inbound10.mxlogicmx.net.
+m1.fank.ru.
+s453.videobb.com.
+mtstravel.com.
+developers.facebook.com.
+widgets.amung.us.
+s-static.ak.facebook.com.
+hasslacher.at.
+profile.ak.fbcdn.net.
+www.chatvibes.com.
+85.237.65.187.in-addr.arpa.
+tapasmss-1.edwardjones.com.
+buodz2agl.80ph.
+static.ak.fbcdn.net.
+9.media.bustedtees.cvcdn.com.
+teredo.ipv6.microsoft.com.
+a1.sphotos.ak.fbcdn.net.
+en.wikipedia.org.
+www.vampire-diaries.es.
+www.cardiofy.com.
+a7.sphotos.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+www.videosvideojuegos.com.
+mail.playcore.com.
+segurosygarantias.com.ar.
+checkip.dyndns.org.
+bluestarbus.com.
+rbbyno:xe.e69k6l2n.
+steviadolce.com.py.
+bewag.se.
+photos-h.ak.fbcdn.net.
+www.feedburner.com.
+www.gra.gi.
+ar-ar.facebook.com.
+es.perfectworld.aeriagames.com.
+nocado.msk.ru.
+173.199.1.118.in-addr.arpa.
+hope-academies.com.
+a.root-servers.net.
+gamereleases.teamxbox.com.
+www.hentailoves.me.
+a.root-servers.net.
+www.sgourosmp3.com.
+3e-co.com.s8b2.psmtp.com.
+174.23.58.201.in-addr.arpa.
+kasdancommunications.com.
+marinaconcrete.com.
+1.201.85.75.in-addr.arpa.
+www.izaping.com.
+aol.com.
+www.google.com.
+graph.facebook.com.
+21.77.30.189.in-addr.arpa.
+player.nakedsword.com.
+246.109.28.99.in-addr.arpa.
+_902_76_6.
+www.hoobing.com.
+www.facebook.com.
+photos-d.ak.fbcdn.net.
+ad.doubleclick.net.
+hotmail.com.
+ia.media-imdb.com.
+fbcdn-profile-a.akamaihd.net.
+live6.truelook.com.
+tas.orangeads.fr.
+auditplusservice.ru.
+qyahds.com.
+en.wikipedia.org.
+gw.incompany.ru.
+melissamcclain.hubpages.com.
+nappanet.net.
+a.root-servers.net.
+pixel.facebook.com.
+96.225.46.189.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+mail.printecs.ru.
+barcampguayaquil.org.
+download.windowsupdate.com.
+external.ak.fbcdn.net.
+a1725.l.akamai.net.
+ece.cornell.edu.
+a.jango.com.
+comcluster.cxense.com.
+tander.kmv.ru.
+www.tickets.com.
+ad-g.doubleclick.net.
+dns.msftncsi.com.
+186.220.145.59.in-addr.arpa.
+s.youtube.com.
+static.ak.fbcdn.net.
+dmvs321.denken.or.jp.
+external.ak.fbcdn.net.
+143.172.246.203.in-addr.arpa.
+s2.youtube.com.
+b._dns-sd._udp.lan.
+mail.terra.es.
+api.twitter.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+berndrosinski.de.
+91.42.173.190.in-addr.arpa.
+platform.twitter.com.
+pixel.facebook.com.
+photos-d.ak.fbcdn.net.
+gift-order.ru.
+13.200.37.124.in-addr.arpa.
+mail.waveware.com.
+a1725.l.akamai.net.
+google.com.
+relay.voice.messenger.msn.com.
+_480_59_9.
+lookquick.com.
+dnl-01.geo.kaspersky.com.
+a.root-servers.net.
+www.wsoftlink.com.
+streams.fusionchicago.com.
+pixel.rubiconproject.com.
+sites.google.com.
+8.250.59.200.in-addr.arpa.
+rs115l3.rapidshare.com.
+iol.co.za.
+service2.pricegong.com.
+www.blackberry.com.
+ir.nielsen.com.
+mx01.simplesiteonline.com.
+www.youtube.com.
+www.facebook.com.
+login.live.com.
+vmwebfe.voice.yahoo.com.
+photos-g.ak.fbcdn.net.
+loading2.widdit.com.
+www.charitiesnfplaw.com.
+www.missionaccomplished.co.uk.
+api.twitter.com.
+ter4ik.ru.
+www.bonerowner.com.
+www.flycell.com.mx.
+platform.twitter.com.
+top-fwz1.mail.ru.
+virginradio.ca.
+mailin.v6.t-online.de.
+api.twitter.com.
+16.video.mystreamservice.com.
+www.savannajones.com.
+secure.shared.live.com.
+photos-e.ak.fbcdn.net.
+99.235.39.190.in-addr.arpa.
+acummy.com.
+82.72.204.190.in-addr.arpa.
+www.fa.domain_not_set.invalid.
+i-0.19-a30e3079.83.1518.19d4.3ea1.210.0.17bmp285vgz7ept5ngbp7d2itb.avqs.mcafee.com.
+gorgeous-teardrops.blogspot.com.
+o1.t26.net.
+developers.facebook.com.
+29.45.105.189.in-addr.arpa.
+tango.mybboard.net.
+adspaces.ero-advertising.com.
+154.200.208.77.in-addr.arpa.
+www.antena3.com.
+a1003.w41.akamai.net.
+www.washingtonpostreprints.com.
+a4.sphotos.ak.fbcdn.net.
+france24.mobiclip.com.
+zone104.hotwords.com.br.
+a.root-servers.net.
+p7-buy.itunes.apple.com.
+ksn2-12.kaspersky-labs.com.
+rpmffe.com.
+australia.newads.com.
+cid-0c4d020e598f0974.profile.live.com.
+csi.gstatic.com.
+native.np.ac.playstation.net.
+tkrdr.storage.msn.com.
+www.pixmac.de.
+www.rip-factor.com.
+49.139.20.190.in-addr.arpa.
+nwwlc.org.
+google.com.
+107.203.143.175.in-addr.arpa.
+www.mejor-sonido.com.
+static.cda.pl.
+andrews.esc18.net.
+blogs.aecomo.org.
+mexico.cnn.com.
+a.root-servers.net.
+s7.addthis.com.
+108.98.19.190.in-addr.arpa.
+webconferencing.avaya.com.
+r.nocouchpotato.com.
+124.141.219.87.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+api26.thetrafficstat.net.
+goo.gl.
+www.norden.lv.
+146.205.129.186.in-addr.arpa.
+campodemarte.com.
+video1.spunkybee.com.
+www.socialgrowthtechnologies.com.
+et8.xhamster.com.
+profile.ak.fbcdn.net.
+s-external.ak.fbcdn.net.
+216.220.152.201.in-addr.arpa.
+apps.mobilityware.com.
+nxcache.nexon.net.
+community.g4s.com.
+fbcdn-profile-a.akamaihd.net.
+mlssw.com.
+photos-a.ak.fbcdn.net.
+download332.avast.com.
+s10.histats.com.
+pubads.g.doubleclick.net.
+apps.facebook.com.
+sur.pep.pemex.com.
+81.78.248.87.in-addr.arpa.
+117.240.236.84.in-addr.arpa.
+.
+a1.sphotos.ak.fbcdn.net.
+25.164.191.190.in-addr.arpa.
+113.229.110.123.in-addr.arpa.
+bbklaw.com.mail11.psmtp.com.
+ca.yahoo.com.
+clk.atdmt.com.
+165.48.51.68.in-addr.arpa.
+photos6.pop6.com.
+cepheidpharmaceuticals.com.
+www.imef.org.mx.
+www.cocinaconrecetas.com.
+27.105.123.190.in-addr.arpa.
+.
+loansmadeeazy.com.
+peterharveyco.com.au.
+photos-f.ak.fbcdn.net.
+nude-males.nudeandcute.com.
+a7.sphotos.ak.fbcdn.net.
+scrat.hellocoton.fr.
+rt.legolas-media.com.
+urs.microsoft.com.
+mail.rhytec.com.
+99.194.231.190.in-addr.arpa.
+multiplos.hotwords.com.br.
+rover.ebay.com.
+photos-a.ak.fbcdn.net.
+174.207.133.124.in-addr.arpa.
+140.247.191.216.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+rendwell.ryazan.ru.
+acsi.org.
+girondinstv.com.
+weather.services.conduit.com.
+maie.com.
+dartt.net.
+download-judging-amy.edogo.com.
+agnifm.ru.
+profile.ak.fbcdn.net.
+p130.hmarzaber.com.
+creative.ak.fbcdn.net.
+w88.go.com.
+odata.intel.com.
+aff.publicdisgrace.com.
+www.dingin.com.
+coupons.walmart.com.
+safebrowsing.clients.google.com.
+photos-h.ak.fbcdn.net.
+clients1.google.com.
+ssl.gstatic.com.
+winecellarinnovations.com.s10a2.psmtp.com.
+sp.cwfservice.net.
+th04.deviantart.net.
+bfz.ru.
+gfx8.hotmail.com.
+a.root-servers.net.
+ips-invite.iperceptions.com.
+147.53.1.190.in-addr.arpa.
+twitter.com.
+stream66-he.grooveshark.com.
+www.alexa.com.
+mail.buildingengines.com.
+sms.mts.ru.
+138.65.23.186.in-addr.arpa.
+www.epoch.com.
+.
+187.253.195.187.in-addr.arpa.
+postman.gbh.com.
+obgyn.ru.
+static.ak.fbcdn.net.
+alisavet.ru.
+teredo.ipv6.microsoft.com.
+cluster1a.us.messagelabs.com.
+img.mediaplex.com.
+photos-a.ak.fbcdn.net.
+dmitriyev.ru.
+plus.google.com.
+program.avast.com.
+oysh4bj6p.28iz.
+sn1msg3020214.gateway.messenger.live.com.
+www.editorialtelevisa.com.mx.
+secure.victoriassecret.com.edgekey.net.
+industrial.clickyourproduct.com.
+66.39.236.189.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+140.247.141.201.in-addr.arpa.
+smx.westminstercollege.edu.redcondor.net.
+geoengineers.com.
+pe.starmedia.com.
+www.aeromexico.com.mx.
+maps.google.com.mx.
+www.chrisbartlett.org.
+vloox.com.
+mail.fitflat.de.
+ad.doubleclick.net.
+www.brooklynpubliclibrary.org.
+www.passionblogs.com.
+www.arthritishelpguide.com.
+banif.pt.
+mail.cnti-penza.ru.
+a.root-servers.net.
+bs.serving-sys.com.
+m.facebook.com.
+www.girlsnews.tv.
+i1.social.s-msft.com.
+a5.sphotos.ak.fbcdn.net.
+85.207.245.190.in-addr.arpa.
+24.media.tumblr.com.
+www.pantyhosesex.ws.
+bcoa.us.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+126.88.0.186.in-addr.arpa.
+23.59.174.190.in-addr.arpa.
+a.root-servers.net.
+smtp.fibrehost.net.
+platform.twitter.com.
+tools.google.com.
+sod-a.rsc-cdn.org.
+10.115.142.190.in-addr.arpa.
+gaming.stackexchange.com.
+support.google.com.
+mx01.windstream.net.
+www.facebook.com.
+www.freedownload3.com.
+76.66.151.189.in-addr.arpa.
+54.172.100.190.in-addr.arpa.
+static.ak.fbcdn.net.
+www.amazon.de.
+www.agoda.vn.
+graph.facebook.com.
+ksn7.kaspersky-labs.com.
+www.oipolloi.com.
+profile.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+cinepivates.blogspot.com.
+mail.zdrav.spb.ru.
+creative.ak.fbcdn.net.
+20minutos.feedsportal.com.
+cityvillefb1.static.zgncdn.com.
+www.paranominal.com.
+118.229.138.98.in-addr.arpa.
+pixel.quantserve.com.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+deportebase.elcomerciodigital.com.
+g.edu-servers.net.
+ma156-r.analytics.edgesuite.net.
+developers.facebook.com.
+j5d4gsftz.11or.
+noctambulo.com.
+carlosavelli.it.
+86.231.35.189.in-addr.arpa.
+www.blogger.com.
+a.root-servers.net.
+s-static.ak.facebook.com.
+www.premiumstorage.info.
+enkamoscity.com.home.
+www.bing.com.
+1001books.ru.
+dns.msftncsi.com.
+pbid.iforex.com.
+pixel.facebook.com.
+www.allaboutshoes.ca.
+s1-powerpoint.vo.msecnd.net.
+leyendasdelecuador.blogspot.com.
+a3.da1.akamai.net.
+accounts.google.com.
+photos-a.ak.fbcdn.net.
+75.44.218.121.in-addr.arpa.
+mail.kraski.spb.ru.
+offer.g.ebay.com.
+www.redflamencos.org.
+spotirama.blogspot.com.
+cp37902.edgefcs.net.
+css-ace.com.
+ksn2-12.kaspersky-labs.com.
+elvideoclubdelos80.blogspot.com.
+pagead2.googlesyndication.com.
+www.blackberry.com.
+williamson2012blog.dailymail.co.uk.
+236.125.126.206.in-addr.arpa.
+tutorial-para-blender.uptodown.com.
+0-292.channel.facebook.com.
+radicaepost.com.
+spopk.org.
+www.juegosdepalabras.com.
+profile.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+android.clients.google.com.
+elupus.com.
+nrjweggi.com.
+bit.ly.
+www.crosspoint.tv.
+www.youtube-nocookie.com.
+manhattancc.org.
+www.google-analytics.com.
+82.211.141.201.in-addr.arpa.
+funmoods.com.
+connect.facebook.net.
+romsfullworld.blogspot.com.
+csc3-2010-crl.verisign.com.
+155.212.230.190.in-addr.arpa.
+helpdesk.princeton.edu.
+sylvia.mmodels.net.
+79.231.2.187.in-addr.arpa.
+cafeycabaret.com.
+a6.sphotos.ak.fbcdn.net.
+aulatic.cl.
+cdn-1.nflximg.com.
+www.anasac.cl.
+29.media.tumblr.com.
+www.jscount.com.
+lookatmyhorsemyhorseisamazing.com.
+69.155.6.69.in-addr.arpa.
+36.13.7.89.in-addr.arpa.
+taztheambo.blogspot.com.
+www.asomagdalena.org.
+mx3.investici.org.
+s0.2mdn.net.
+a.root-servers.net.
+itc-01.ru.
+dns.msftncsi.com.
+s2.youtube.com.
+plus.google.com.
+ad.foxnetworks.com.
+eewine.com.
+dasgelbeforum.de.org.
+186.34.168.192.in-addr.arpa.
+ozum.ru.
+tour.jizz-on-my-gf.com.
+www.centraloutpost.com.
+scream-room.blogspot.com.
+137.147.85.85.in-addr.arpa.
+www.msftncsi.com.
+simple-timer-clocks.googlecode.com.
+ambar-jeans.ru.
+33.72.169.184.in-addr.arpa.
+dns.msftncsi.com.
+buildexpo.ru.
+e566.b.akamaiedge.net.
+a4.sphotos.ak.fbcdn.net.
+11.224.193.190.in-addr.arpa.
+citrys.ca.
+video.google.com.mx.
+csi.gstatic.com.
+www.niktutos.wordpress.com.
+169.151.160.201.in-addr.arpa.
+198.255.37.184.in-addr.arpa.
+db._dns-sd._udp.lan.
+mail.mbsuk.com.
+api.theknot.com.
+www.thisfellow.com.
+planet-group.co.uk.
+www.louisvuitton.org.in.
+developers.facebook.com.
+www.jpfgallery.com.
+www.corepredictivedialer.com.
+static02.olx-st.com.
+carpartsonsale.com.
+3.89.181.207.in-addr.arpa.
+www.advent.com.
+94.217.56.186.in-addr.arpa.
+21.228.171.69.in-addr.arpa.
+46.64.127.200.in-addr.arpa.
+73.26.0.10.in-addr.arpa.
+ph.jobomas.com.
+apps.facebook.com.
+cs.oag.state.tx.us.
+www.google.com.
+www.browtf.com.
+147.198.117.62.in-addr.arpa.
+www.wfn.org.
+twitter.com.
+mps.hwcdn.net.
+21.175.99.24.in-addr.arpa.
+edge-wunderkit.dotcloud.com.
+93.docs.google.com.
+suncars.com.tw.
+browse.postcards.org.
+up0002-blus30838-00.auth.np.ac.playstation.net.
+171.62.26.83.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+clkads.com.
+ryanbuildingmaterials.com.
+static.ak.fbcdn.net.
+srx.main.ebayrtm.com.
+photos-h.ak.fbcdn.net.
+57.34.169.1.in-addr.arpa.
+tinyurl.com.
+sonydadc.com.
+masco.cc.
+www.facebook.com.
+www.kunstkopie.at.
+post3.cox.com.
+.
+98.2.86.200.in-addr.arpa.
+252.91.45.200.in-addr.arpa.
+109.42.205.187.in-addr.arpa.
+shout2a.gnax.net.
+a.root-servers.net.
+www.freefullfrontals.co.uk.
+d15gt9gwxw5wu0.cloudfront.net.
+203.81.127.187.in-addr.arpa.
+numericafunding.com.
+www.google.com.
+kangarobin.cixx6.com.
+sbcglobal.net.
+www.alternativechannel.tv.
+gfx3.hotmail.com.
+www.ssn.org.
+plusone.google.com.
+126.165.240.89.in-addr.arpa.
+23.229.171.69.in-addr.arpa.
+a.root-servers.net.
+depacnglw0dc001.code1.emi.philips.com.
+144.140.235.24.in-addr.arpa.
+201.145.79.190.in-addr.arpa.
+57.ru.
+donsapaugh.com.
+studioscalia.com.
+223.78.250.190.in-addr.arpa.
+146.84.54.68.in-addr.arpa.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.nikonlinks.com.
+photos-f.ak.fbcdn.net.
+csi.gstatic.com.
+169.166.226.91.in-addr.arpa.
+dkz.info.
+mail.live.com.
+s.youtube.com.
+fbcdn-photos-a.akamaihd.net.
+assetman23.d1g.com.
+www.facebook.com.
+static.ak.fbcdn.net.
+edge1.catalog.video.msn.com.
+8.99.215.189.in-addr.arpa.
+static.ak.fbcdn.net.
+yfdb213o.com.
+oglobo.globo.com.
+wwf.org.uk.
+photos-h.ak.fbcdn.net.
+8.70.56.85.in-addr.arpa.
+dordrecht.nl.
+digg.com.
+www.spanish.audiogil.es.
+buynowfromusa.com.
+death-note-hentai.famous-toons-facial.com.
+_023_83_0.
+mail.newworldtrust.com.
+givision.net.
+www.charmbeadswholesale.com.
+photos-g.ak.fbcdn.net.
+us.data.toolbar.yahoo.com.
+196.0.168.192.in-addr.arpa.
+wat.com.
+inbound.edgewaterdesign.com.netsolmail.net.
+edentworld.com.
+groups.l.google.com.
+m.facebook.com.
+241.35.10.187.in-addr.arpa.
+leerlibros.com.
+59.188.20.186.in-addr.arpa.
+25.207.25.189.in-addr.arpa.
+38.147.220.66.in-addr.arpa.
+234.1.0.192.in-addr.arpa.
+troy30c.org.s5b1.psmtp.com.
+keine.at.
+podermilitar.blogspot.com.
+groundside.com.
+87.19.168.192.in-addr.arpa.
+a.root-servers.net.
+www.profilebanner.com.
+connect.facebook.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+189.85.104.200.in-addr.arpa.
+90elf.spiegel.de.
+www.wladhe.com.
+saabworkshop.com.
+www.mywebsearch.comm.
+www.justinpictures.org.
+www.yahoo.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+46.101.168.192.in-addr.arpa.
+productnews.link.net.
+ipblmg.com.
+googleads.g.doubleclick.net.
+www.belkin.com.
+193.1.170.85.in-addr.arpa.
+newsrss.bbc.co.uk.
+a8.sphotos.ak.fbcdn.net.
+eearthlink.com.
+www.flintshirechronicle.co.uk.
+abacushk.com.inbound10.ttasia.net.
+sites.google.com.
+www.saludmd.com.
+ec.atdmt.com.
+damianvoltes.com.
+k-s-p.ru.
+b.static-cdn.playfish.com.
+external.ak.fbcdn.net.
+emersonmgmt.com.
+231.43.143.189.in-addr.arpa.
+186.226.209.77.in-addr.arpa.
+conf.socialvi.be.
+webmail.villarrobledo.com.
+1.118.28.186.in-addr.arpa.
+mail34.opentransfer.com.
+static.ak.fbcdn.net.
+194.196.248.201.in-addr.arpa.
+157.122.41.190.in-addr.arpa.
+bar.leo.org.
+_ldap._tcp.dd273816-6837-406d-8b28-d47fdadd0ea3.domains._msdcs.ey.net.
+www.gstatic.com.
+yahoo.com.
+api.twitter.com.
+teredo.ipv6.microsoft.com.
+mail.gladcorp.com.
+informatika.net.ru.
+ad.yieldmanager.com.
+gg.google.com.
+ow.ly.
+www.gmperformanceparts.com.
+a.root-servers.net.
+livefilestore.com.multi.uribl.com.
+static.polldaddy.com.
+id.google.com.mx.
+static-resource.np.community.playstation.net.
+moranandco.com.s7b2.psmtp.com.
+bs.serving-sys.com.
+195.7.95.201.in-addr.arpa.
+yytayna.com.
+fetch.flashget.com.
+profile.ak.fbcdn.net.
+ff.connextra.com.
+es.wikipedia.org.
+fbcdn-profile-a.akamaihd.net.
+photos-a.ak.fbcdn.net.
+ruhlman.com.
+www.leverguns.com.
+static.ak.fbcdn.net.
+auto.mercadolibre.com.ar.
+8-courier.push.apple.com.
+www.facebook.com.
+getpersonas-cdn.mozilla.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.dietadiaria.com.
+a2.sphotos.ak.fbcdn.net.
+i3.ytimg.com.
+www.materialesparatocados.com.
+photos-f.ak.fbcdn.net.
+tock.usno.navy.mil.
+globaltranceinvasion.com.
+www.midespertardeconciencia.ning.com.
+apps.facebook.com.
+rospres.com.
+www.abcjuegos.net.
+plus.google.com.
+t.tmimgcdn.com.
+www.youtube.com.
+191.200.72.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+premierfitnessclubs.com.
+simdesk.com.
+wortschatz.informatik.uni-leipzig.de.
+terra.uplanet.ru.
+ur.wikipedia.org.
+endz.nne.elektra.ru.
+202.187.19.186.in-addr.arpa.
+images.google.com.
+explore.live.com.
+de.wikipedia.org.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+twitpic.com.
+ekpc.com.
+go.srvnow.com.
+17.98.56.85.in-addr.arpa.
+turnkeymarketing.us.
+google.com.
+a8.sphotos.ak.fbcdn.net.
+media2sm.firstshowing.net.
+forum.japantoday.com.
+a.root-servers.net.
+content.yieldmanager.edgesuite.net.
+static.ak.fbcdn.net.
+chhg.biz.
+bodyandhealth.canada.com.
+65.203.21.23.in-addr.arpa.
+mail.brprint.de.
+190.35.209.77.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+seriyps.ru.
+201.95.27.187.in-addr.arpa.
+csi.gstatic.com.
+profile.ak.fbcdn.net.
+babymaker.mauryshow.com.
+62.69.249.84.in-addr.arpa.
+alcatraz.wikia.com.
+pathwayproductions.com.
+www.facebook.com.
+74.201.0.10.in-addr.arpa.
+39.170.2.178.in-addr.arpa.
+emtec-group.com.
+amnet.net.au.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+game-gt.com.
+humour.wikinut.com.
+asktoolbar.weather.com.
+preveaclinic.com.
+api.twitter.com.
+a.rad.msn.com.
+photos-e.ak.fbcdn.net.
+webcache.googleusercontent.com.
+mail.successfactors.com.
+smtp.beagvs.com.
+91.44.51.190.in-addr.arpa.
+au.movies.yahoo.com.
+ekran-tv.ru.
+a.appbank.com.
+map.media6degrees.com.
+75.254.254.220.in-addr.arpa.
+www.homeinbayarea.com.
+gross.ru.
+mail.travesi.com.
+254.211.142.187.in-addr.arpa.
+local-sn.contacts.msn.com.
+www.businessweek.com.
+meridiansystems.com.
+shared.live.com.
+culturacomic.com.
+opisventures.com.
+www.inkapoker.com.
+sharethis.com.
+gliocchimarroni.blogspot.com.
+www.google.com.
+609.talkgadget.google.com.
+b-0.19-23096008.481.1518.19d3.3ea0.410.0.iksp3etvn9s9utfq893mqspvf5.avqs.mcafee.com.
+img6.ask.fm.
+thesecretworldofacraftaholic.blogspot.com.
+www.facebook.com.
+5735-100.cudamail.com.
+es-la.facebook.com.
+www.jkhglmncd48.com.
+www.youtravel.com.au.
+imgur.com.multi.uribl.com.
+215.245.206.190.in-addr.arpa.
+plusone.google.com.
+dns.msftncsi.com.
+aqgc545xp.31uw.
+187.126.25.189.in-addr.arpa.
+developers.facebook.com.
+inbound.scanlanfamilyfarms.com.namesecuremail.net.
+susu.ac.ru.
+dr._dns-sd._udp.0.2.168.192.in-addr.arpa.
+53.227.171.69.in-addr.arpa.
+www.belkin.com.
+www.facebook.com.
+photos-f.ak.fbcdn.net.
+_666_11_4.
+hubbell-canada.com.s7b1.psmtp.com.
+teredo.ipv6.microsoft.com.
+2.1.168.192.in-addr.arpa.
+udig.com.
+carlossotomorales.blogspot.com.
+pt.trafficjunky.net.home.
+static.ak.fbcdn.net.
+ba.ckground.com.
+a.root-servers.net.
+euro.mediotiempo.com.
+es-es.fxfeeds.mozilla.com.
+ru.wikipedia.org.
+data.flurry.com.
+sn1msg1020127.gateway.messenger.live.com.
+a.root-servers.net.
+96.45.25.80.in-addr.arpa.
+blitz.nocrawl.www.dik.nl.
+es-la.facebook.com.
+118.188.140.69.in-addr.arpa.
+lcbenefits.com.inbound15.mxlogicmx.net.
+www.mamemimo.com.
+110.30.31.190.in-addr.arpa.
+www.antena3tv.es.
+files.myopera.com.
+a4.sphotos.ak.fbcdn.net.
+manga.hentai.ms.
+toolbarqueries.google.com.
+photos-f.ak.fbcdn.net.
+api.twitter.com.
+www.jornada.unam.mx.
+penskemercedes.com.s8b1.psmtp.com.
+bay.messenger.services.live.com.
+wpad.
+bt.yikuai.com.
+avatar.nimbuzz.com.
+kinesis.co.uk.
+216.175.108.186.in-addr.arpa.
+201.132.43.178.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+gooble.com.
+hits.e.cl.
+248.154.158.189.in-addr.arpa.
+177.140.193.187.in-addr.arpa.
+s0.2mdn.net.
+www.ebayanuncios.es.
+www.airwick.com.mx.
+api.ak.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+meme-spot.tumblr.com.
+dns.msftncsi.com.
+bibriesca2009.keepandshare.com.
+www.givetoqueens.ca.
+mail.heliumm.com.
+dr._dns-sd._udp.lan.
+time.chttl.com.tw.
+ink.voskresensk.ru.
+54.254.56.190.in-addr.arpa.
+csc3-2010-crl.verisign.com.
+swcmail.net.
+arbia.it.
+www.airforce-magazine.com.
+51.127.0.190.in-addr.arpa.
+tr.dohop.com.
+theairloom.files.wordpress.com.
+147.19.125.84.in-addr.arpa.
+206.54.87.186.in-addr.arpa.
+a.root-servers.net.
+ax.init.itunes.apple.com.
+p1t.ru.
+profile.ak.fbcdn.net.
+pixel.facebook.com.
+www.buriedmirror.com.
+phone.com.
+es.y8.com.
+xrfelzx.rjzl.
+realnetworks.com.
+www.praben.cl.
+ad.doubleclick.net.
+michelleobamawatch.com.
+tech.tln.lib.mi.us.
+websearch.ask.com.
+198.10.176.190.in-addr.arpa.
+mailrelay01.virginmedia.co.uk.
+photos-d.ak.fbcdn.net.
+capitulosdenarutoshippuden.blogspot.com.
+woodstock.k12.vt.us.
+www.web-flv-player.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+z7mjefkuu.04zs.
+246.172.87.67.in-addr.arpa.
+gaom.hit.gemius.pl.
+content.yieldmanager.edgesuite.net.
+126.37.43.190.in-addr.arpa.
+cleanmymac.softonic.de.
+a.root-servers.net.
+intlreg.aol.com.
+54.111.162.189.in-addr.arpa.
+matcher-rbc.bidder7.mookie1.com.
+102.108.22.195.in-addr.arpa.
+www.echodesign.com.
+platform.ak.fbcdn.net.
+www.hovernauts.com.
+photos-e.ak.fbcdn.net.
+_185_82_0.
+202.161.97.76.in-addr.arpa.
+yahoo.ca.
+e1.f1213.mail.yahoo.com.
+map.no.
+198.184.176.189.in-addr.arpa.
+79.19.152.189.in-addr.arpa.
+chat.facebook.com.
+www.jmarcano.com.
+www.businessweek.com.
+ksn3-11.part1.kaspersky-labs.com.
+49.218.41.83.in-addr.arpa.
+36.213.10.82.in-addr.arpa.
+static.panoramio.com.
+s-static.ak.fbcdn.net.
+d2100708.xoom.it.
+a.root-servers.net.
+www.boxingbets.ru.
+28.176.19.95.in-addr.arpa.
+ls2web.redmond.corp.microsoft.com.
+safebrowsing-cache.google.com.
+apps.facebook.com.
+vpn-cc1.reliablehosting.com.
+98.146.82.189.in-addr.arpa.
+lh4.googleusercontent.com.
+114.39.79.94.in-addr.arpa.
+it-it.facebook.com.
+nsx-e.np.dl.playstation.net.
+apps.facebook.com.
+254.125.214.201.in-addr.arpa.
+227.39.135.187.in-addr.arpa.
+smtpin2.usinternet.com.
+18.137.91.186.in-addr.arpa.
+estebanfuentealba.files.wordpress.com.
+ad.yieldmanager.com.
+letter.ly.
+static.ak.facebook.com.
+www.abc.es.
+84.68.28.186.in-addr.arpa.
+133.75.220.95.in-addr.arpa.
+zaragozame.com.
+photos-f.ak.fbcdn.net.
+integration.klarna.com.
+freelink.org.
+www.facebook.com.
+22.90.248.189.in-addr.arpa.
+39.187.29.189.in-addr.arpa.
+0-125.channel.facebook.com.
+a1003.w41.akamai.net.
+_660_41_2.
+static.ak.fbcdn.net.
+freakshare.net.
+www.youtube.com.
+www.g4tv.com.
+70.71.33.190.in-addr.arpa.
+www.defensetech.org.
+dr._dns-sd._udp.lan.
+smtp.glittered-pastel.net.
+publicpolicy.com.1.arsmtp.com.
+161.14.179.190.in-addr.arpa.
+systems42ltd.com.
+angelesysuscuentos.blogspot.com.
+dns.msftncsi.com.
+vacsend.ru.
+w.sharethis.com.
+sbcgoabl.net.
+gnow.com.
+lifestream.glifestream.aim.com.
+52.17.66.87.in-addr.arpa.
+whlr9:vdj.84gg.
+84.5.216.203.in-addr.arpa.
+pixel.facebook.com.
+www.freehomemademovie.com.
+41.55.241.189.in-addr.arpa.
+68.12.59.186.in-addr.arpa.
+www.archivisionstudio.com.
+_940_20_1.
+mail.isgtechnologies.com.
+safebrowsing.clients.google.com.
+bluegraysky.blogspot.com.
+lh5.googleusercontent.com.
+careers.msn.com.
+www.google.com.
+www.hjkomr.com.
+sc19.rules.mailshell.net.
+s-external.ak.fbcdn.net.
+pixel.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+33.96.251.82.in-addr.arpa.
+es.wikipedia.org.
+mx0.uniserve.ca.
+gorrosdequirofanojaner.blogspot.com.
+api.tweetdeck.com.
+sux2cocuf.s19g9z0c.
+www.lamaripepa.com.
+photos-d.ak.fbcdn.net.
+lorillard.com.
+zynga1-a.akamaihd.net.
+up.ro7k.net.
+e-states.ru.
+a4.sphotos.ak.fbcdn.net.
+binarytech.wordpress.com.
+40.1.152.201.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+mail.google.com.
+argos.co.uk.
+8-courier.push.apple.com.
+152.193.18.186.in-addr.arpa.
+dx3723.tinyurl.com.
+shop.productwiki.com.
+s15279541.onlinehome-server.info.
+update.avg.com.
+premiersurgical.com.s7b2.psmtp.com.
+a.root-servers.net.
+time.chttl.com.tw.
+106.170.224.186.in-addr.arpa.
+google.com.
+adadvisor.net.
+photos-a.ak.fbcdn.net.
+a.root-servers.net.
+apps.facebook.com.
+secure.shared.live.com.
+yahoo.com.
+www.epicgameads.com.
+blufiles.storage.msn.com.
+ashfordsearch.com.s9a2.psmtp.com.
+v3.nonxt7.c.youtube.com.
+profile.chcf.org.
+busy-at-home.com.
+mail.mercergov.org.
+www.fb.telemakingweb.com.
+humorwit.com.
+www.xtrf.eu.
+www.100forexbrokers.com.
+70.79.73.78.in-addr.arpa.
+a.root-servers.net.
+126.116.45.190.in-addr.arpa.
+a.ads2.msads.net.
+www.alldemotivational.com.
+googleads.g.doubleclick.net.
+imagenes.es.sftcdn.net.
+freemarket.kiev.ua.
+ellarguero.info.
+tripletorsion.com.
+i1.images.mofosworldwide.com.
+www.facebook.com.
+i1.ytimg.com.
+profile.ak.fbcdn.net.
+www.alliedmoulded.com.
+www.mikelozano.com.mx.
+a.root-servers.net.
+kommarsolutions.com.
+arianacb.obolog.com.
+es.y8.com.
+oi560.photobucket.com.
+dailyfun4u.com.
+.
+profile.live.com.
+webmail.joyeriagutierrezsousa.com.
+www.facebook.com.
+www.socialgrowthtechnologies.com.
+arvidarealtor.com.
+photos-g.ak.fbcdn.net.
+6be7434q4.77ng.
+mail.fnmsbranch.com.
+dmntbank.msk.ru.
+pixel.facebook.com.
+www.solomotoparts.com.
+cn1.redswoosh.akadns.net:443.
+a0.twimg.com.
+content.yieldmanager.edgesuite.net.
+www.google.com.mx.
+mail.nabarreria.com.
+paramirarnos.blogspot.com.
+v15.lscache1.c.youtube.com.
+www.drm-x.com.
+cityvillefb1.static.zgncdn.com.
+www.googleadservices.com.
+y4aw25vth.57av.
+plusone.google.com.
+20.141.132.92.in-addr.arpa.
+coniferit.net.
+a.root-servers.net.
+250.48.105.190.in-addr.arpa.
+polkadotlighthouseuk.blogspot.com.
+addons.mozilla.org.
+teredo.ipv6.microsoft.com.
+it-it.facebook.com.
+192.64.144.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+s.ytimg.com.
+national1direct.com.
+www.facebook.com.
+vosmd.com.
+mdawmdexmjaxmjaxmg.info.
+49.137.249.186.in-addr.arpa.
+a.root-servers.net.
+www.food-allergy.org.
+dnstest.baofeng.com.
+www.google.com.
+a.root-servers.net.
+www.elblogdecineespanol.com.
+s1-excel.vo.msecnd.net.
+www.uz.
+213.241.209.201.in-addr.arpa.
+blog.gamesparadise.com.au.
+static.ak.fbcdn.net.
+loading3.widdit.com.
+a.root-servers.net.
+a.root-servers.net.
+254.48.17.190.in-addr.arpa.
+cloudtv.accu-weather.com.
+profile.ak.fbcdn.net.
+d2098308.xoom.it.
+um14.eset.com.
+asweetadventure.com.
+clients4.google.com.
+iscnvx.lmsc.lockheed.com.
+apps.facebook.com.
+191.96.15.129.in-addr.arpa.
+184.86.103.80.in-addr.arpa.
+us.img.e-planning.net.
+es-es.facebook.com.
+analyser.oli.tudelft.nl.
+11.8.34.201.in-addr.arpa.
+77.200.191.186.in-addr.arpa.
+www.googleadservices.com.
+a.root-servers.net.
+a.root-servers.net.
+108.157.202.190.in-addr.arpa.
+a.root-servers.net.
+money.msn.com.
+download858.avast.com.
+www.rotavirusvaccine.org.
+ranking.enfeel.com.
+s.youtube.com.
+rad.msn.com.
+steinberg2002.com.
+data.mxm.ch.
+a.root-servers.net.
+www.eraltd.org.
+b-0.19-21025008.1581.1518.19d4.3ea1.410.0.pqkwldtwiadawn4nfkewen5pvi.avqs.mcafee.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+mail.ivillage.com.
+mozilla.mirror.nexicom.net.
+classic.mountaingear.com.
+226.241.61.200.in-addr.arpa.
+reddog.net.au.
+download.windowsupdate.com.
+plus.google.com.
+creative.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+provo.edu.
+searchjustice.usdoj.gov.
+www.classically-elegant.com.
+web.csuchico.edu.
+www.laporteriadejorgejuan.com.
+a.root-servers.net.
+scrapsandthecity.gotop100.com.
+v2.cache8.c.youtube.com.
+jattgroup.com.
+static.ak.fbcdn.net.
+www.dosomethingamazing.com.
+ads.mobclix.com.
+search.softonic.com.
+tuckerlaw.net.p4.mx-route.com.
+inkman.co.th.
+yahoo.com.
+www.erica.biz.
+www.youtube.com.
+sales.vip.tom.com.
+a.root-servers.net.
+178.36.48.212.in-addr.arpa.
+apps.facebook.com.
+232.84.231.189.in-addr.arpa.
+mail.zublatt.com.
+_953_46_7.
+e5413.g.akamaiedge.net.
+platform.ak.fbcdn.net.
+www.yahoo.com.
+cheaptickets.com.s7a2.psmtp.com.
+respuestas.wikia.com.
+2.docs.google.com.
+125.166.89.108.in-addr.arpa.
+118.249.16.200.in-addr.arpa.
+blairschools.org.
+racetech.com.
+westwood-apartments.com.
+rpo.ru.
+ocsp.geotrust.com.
+www.google.com.
+it-it.facebook.com.
+191.204.107.189.in-addr.arpa.
+223.224.140.175.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+opessworprvygpj.net.
+ax26.a.cocolog-nifty.com.
+53.134.38.187.in-addr.arpa.
+pixel.facebook.com.
+43.163.20.190.in-addr.arpa.
+static.ak.fbcdn.net.
+www.vogue.fr.
+gmail.com.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.gstatic.com.
+aerolineasmexicanas.com.mx.
+127.67.164.58.in-addr.arpa.
+a4.mzstatic.com.
+89.54.198.190.in-addr.arpa.
+cdn3.cpmstar.com.
+mail.google.com.
+developers.facebook.com.
+content.yieldmanager.edgesuite.net.
+a.rad.msn.com.
+breakmysex.info.
+recep.com.
+t2.gstatic.com.
+it.carsmaniacs.com.
+u20.eset.com.
+www.lindsaylohanweb.com.
+www.facebook.com.
+209.51.194.187.in-addr.arpa.
+www.tatil-gunleri.com.
+sup.live.com.
+apus.edu.
+signup.wazzub.info.
+hog.assets2.zgncdn.com.
+fbcdn-profile-a.akamaihd.net.
+www.arpia.be.
+truevalue.com.
+130.137.148.190.in-addr.arpa.
+mt0.google.com.
+207.2.27.77.in-addr.arpa.
+imgs1.smutxx.com.
+img100.xvideos.com.
+153.250.103.80.in-addr.arpa.
+platform.twitter.com.
+29.53.222.189.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+images.amazon.com.
+atlantarubber.com.
+opentranslators.transifex.net.
+inbound.willistire.com.netsolmail.net.
+www.dokterdokter.nl.
+cdn.magiclevel.com.
+api-read.facebook.com.
+tools.google.com.
+levitontelcom.com.
+a.root-servers.net.
+www.facebook.com.
+ocsp.verisign.com.
+dy1719dhn.h86k5y2l.
+a2.sphotos.ak.fbcdn.net.
+www.diccionariopubli.com.
+s-external.ak.fbcdn.net.
+mail.google.com.
+28.78.59.85.in-addr.arpa.
+www.pautefacil.com.
+fbcdn-profile-a.akamaihd.net.
+77.206.222.190.in-addr.arpa.
+dnl-01.geo.kaspersky.com.
+www.oafiliado.com.br.
+www.superzooi.com.
+ad.harrenmedianetwork.com.
+virgin.net.
+platform.twitter.com.
+www.rasushi.com.
+4.220.71.190.in-addr.arpa.
+www.compunetsi.net.
+hg1.hitbox.com.
+safebrowsing.clients.google.com.
+your.schoolfeed.com.
+2.bp.blogspot.com.
+www.teleweb-mallorca.com.
+external.ak.fbcdn.net.
+mail.neemranahotels.com.
+106.229.80.188.in-addr.arpa.
+www.paragonco.com.
+wikipedia-lb.wikimedia.org.
+a2.sphotos.ak.fbcdn.net.
+data.flurry.com.
+g:ka9b7aa.17hk.
+52.68.173.190.in-addr.arpa.
+188.249.211.205.in-addr.arpa.
+m.facebook.com.
+teoten.wordpress.com.
+i.ebayimg.com.
+229.194.74.190.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+s.youtube.com.
+laopinionautos.com.
+www.cacillo.it.
+.
+112.114.156.187.in-addr.arpa.
+puzzle.gamesdidi.org.
+royaltyroofing.com.
+2.0.0.10.in-addr.arpa.
+ctdb.samba.org.
+rommai.com.
+211.225.77.190.in-addr.arpa.
+www.ivss.gov.ve.
+translate.google.com.mx.
+clients1.google.com.
+static.ak.fbcdn.net.
+www.youtube.com.
+dorado.cl06.ch.
+ns2.vclk.net.
+www.biotechniques.com.
+mail.dza.com.
+www.google.com.
+d3j5vwomefv46c.cloudfront.net.
+gay-dating-sites.no1reviews.com.
+www.luvsdiapers.com.
+a.root-servers.net.
+imadreamer.metroblog.com.
+55.61.93.58.in-addr.arpa.
+www.bahai-studies.ca.
+bettybeauty.com.
+ad-g.doubleclick.net.
+fr.webrep.avast.com.
+twitter.com.
+a.root-servers.net.
+54.43.208.201.in-addr.arpa.
+ocsp.thawte.com.
+169.5.126.188.in-addr.arpa.
+prospects4travel.com.
+doehler.com.
+177.31.111.189.in-addr.arpa.
+bendliving.com.
+gostosoflexsp.blogspot.com.
+pixel.quantserve.com.
+77.238.81.75.in-addr.arpa.
+safebrowsing.clients.google.com.
+lozzpfn46.u23k3m7e.
+orcart.facebook.com.
+www.youtube.com.
+pixel.facebook.com.
+greenflora.ru.
+fbcdn-photos-a.akamaihd.net.
+n.univision.com.
+chubarama.net.
+a4.da1.akamai.net.
+a.root-servers.net.
+m.facebook.com.
+218.42.198.187.in-addr.arpa.
+external.ak.fbcdn.net.
+it-it.facebook.com.
+twiconsol.com.
+rosautoprom.ru.
+www.flycell.com.ar.
+kaffeine.sourceforge.net.
+xbox360media.ign.com.
+o.httpcs102.wg.msg.sp1.yahoo.com.
+51.159.102.80.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+atlasfreight.net.inbound10.mxlogicmx.net.
+ad.lpxp.net.
+www.watchsolution.com.
+ksn1-12-part2.kaspersky-labs.com.
+www.licc.org.uk.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+40.89.102.187.in-addr.arpa.
+www.ihrtrauringjuwelier.de.
+105.216.72.187.in-addr.arpa.
+m002.maktoob.com.
+www.google.com.
+stepbystep.ru.
+online.casino.winner.com.
+web2.nidhog.com.
+www.redcultura.com.
+a.root-servers.net.
+220.110.120.200.in-addr.arpa.
+56.72.59.193.in-addr.arpa.
+243.51.2.187.in-addr.arpa.
+plusone.google.com.
+members.dyndns.org.
+photos-b.ak.fbcdn.net.
+mail.bcvt.tec.pa.us.
+gjsteel.com.s8b1.psmtp.com.
+www.eluniversal.com.mx.
+www.mozilla.com.
+skype2.en.softonic.com.
+flextel.ru.
+api.twitter.com.
+d3lvr7yuk4uaui.cloudfront.net.
+ja-jp.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+opora.org.ru.
+photos-f.ak.fbcdn.net.
+towersemi.com.
+133.202.79.188.in-addr.arpa.
+www.cantabriatorrent.es.
+www.autogasitalia.it.
+244.58.168.189.in-addr.arpa.
+37.0.215.201.in-addr.arpa.
+google.com.mx.
+www.facebook.com.
+profile.ak.fbcdn.net.
+105.153.122.186.in-addr.arpa.
+developers.facebook.com.
+f.root-servers.net.
+www.comechochos.com.
+server29.appriver.com.
+images.honda-tech.com.
+ad.103092804.com.
+a.root-servers.net.
+www.baskingsharks.org.
+153.121.75.187.in-addr.arpa.
+shepaug.com.inbound10.mxlogic.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.gillespieonline.com.
+mtg911.com.
+mail.italee.com.
+tuireg.9158.com.
+connect.facebook.net.
+www.amazon.ca.
+alerts.conduit-services.com.
+e5z1rcx96.n83u2i6c.
+www.zurich.com.ar.
+profile.live.com.
+blobcdn.iegallery.com.
+apps.facebook.com.
+pomogi-rebenku.ru.
+mirinfo.ru.
+www.anamardoll.com.
+32.84.158.79.in-addr.arpa.
+www.nj.com.
+a1003.w41.akamai.net.
+widget.plugrush.com.
+horoskop.vol.at.
+50.26.221.189.in-addr.arpa.
+forum.sh3bwah.maktoob.com.
+www.mizinapecuaro.com.
+apps.facebook.com.
+m.facebook.com.
+d1ros97qkrwjf5.cloudfront.net.
+cs.wikipedia.org.
+download695.avast.com.
+rsvl.unisys.com.
+www.belkin.com.
+www.skyhighlb.com.
+i35.tinypic.com.
+www.macrothink.org.
+rep.netel.net.
+hitltd.msk.su.
+lists-mx.mysql.com.
+connect.facebook.net.
+fxfeeds.mozilla.com.
+www.inspirational-motivational-quotes.com.
+api.twitter.com.
+support.google.com.
+www.conceptoam.com.ar.
+dns2.is.net.pl.
+wpad.
+11.21.206.24.in-addr.arpa.
+37.84.76.190.in-addr.arpa.
+apis.google.com.
+www.toplist.cz.
+photos-f.ak.fbcdn.net.
+_433_49_4.
+a.root-servers.net.
+tap.rubiconproject.com.
+finift.ru.
+video321.info.
+www.sigmabeauty.com.
+www.google.com.
+geo.yahoo.com.
+gamezadvisor.com.
+villakoenig.blogspot.com.
+rwc-temp7.openwave.com.
+portcontractors.com.inbound15.mxlogicmx.net.
+ir.ebaystatic.com.
+9.79.10.187.in-addr.arpa.
+twitter.com.
+www.berklee.edu.
+a4.sphotos.ak.fbcdn.net.
+230.114.172.201.in-addr.arpa.
+tracker.torrent.to.
+allconnect.ru.
+graphicsanddesigns.foroactivo.com.
+goo.gl.
+www.lumen.com.mx.
+16.7.168.192.in-addr.arpa.
+www.yahooka.com.
+mtnlmail.com.
+pagead2.googlesyndication.com.
+vgtribune.com.
+9.48.159.189.in-addr.arpa.
+api-read.facebook.com.
+s-static.ak.facebook.com.
+s-static.ak.fbcdn.net.
+photos-c.ak.fbcdn.net.
+shop.nakedfunny.com.
+mumfordcompany.com.inbound15.mxlogic.net.
+124.143.239.189.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+drlopez.com.
+video.google.com.mx.
+72.142.58.85.in-addr.arpa.
+www.hostweb.byethost2.com.
+globetour.ru.
+no-replay.alertreceived.com.
+51.list.themediafinder.com.
+www.codango.com.
+carnationbanc.com.
+being-glamorous.blogspot.com.
+www.lalibcosupport.com.
+api-read.facebook.com.7.
+lb._dns-sd._udp.0.0.168.192.in-addr.arpa.
+a.root-servers.net.
+berriojimenez.blogspot.com.
+imagengratis.org.
+www.ecampus.com.akadns.net.
+224.0.0.10.in-addr.arpa.
+73.140.100.70.in-addr.arpa.
+in.mx.skynet.be.
+apps.facebook.com.
+d2092610.xoom.it.
+www.thisislocallondon.co.uk.
+picasaweb.google.com.
+ufps.chukotka.ru.
+www.youtube.com.
+s2.googleusercontent.com.
+onet.pl.
+ssl.gstatic.com.
+26.23.18.89.in-addr.arpa.
+media02-ak.vivastreet.com.
+opel-werner.de.
+www.macromedia.com.
+www.4msa.com.
+local-bay.contacts.msn.com.
+166.11.234.201.in-addr.arpa.
+189.18.244.117.in-addr.arpa.
+google.com.
+mail.tehn.ru.
+ads.yimg.com.
+www.apple.com.
+merax.ru.
+isatap.home.
+que-video-loco.blogspot.co.nz.
+128.1.16.172.in-addr.arpa.
+www.worldofends.com.
+barracuda2.mbgpepsi.com.
+pixel.rubiconproject.com.
+www.neoteo.com.
+49.147.220.66.in-addr.arpa.
+hackosphere.blogspot.com.
+augmentedrealityblog.files.wordpress.com.
+raveassociates.net.
+a.root-servers.net.
+a4.sphotos.ak.fbcdn.net.
+google.com.
+exotherm.com.inbound10.mxlogicmx.net.
+us.bc.yahoo.com.
+apuntesdelprofesor.over-blog.es.
+www.penguinvids.com.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+quotations.about.com.
+api.zynga.com.
+sup.live.com.
+msigeek.disqus.com.
+puzzlingames.com.
+a8.sphotos.ak.fbcdn.net.
+api-read.facebook.com.
+searchclient.live.net.
+avrlider.ru.
+www.computerstore.co.nz.
+urs.microsoft.com.
+educacionmusical.es.
+www.dospuntocerovision.com.
+getlistedsd.com.
+creative.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+avril_lavigne-3454.tabsmetal.org.
+www.imagegroup.cl.
+conveyancepartners.com.
+nomoresabotage.com.
+www.rockmx.com.mx.
+s-static.ak.fbcdn.net.
+90.180.107.2.in-addr.arpa.
+www.facebook.com.
+_360_91_4.
+scores.espn.go.com.
+time.chttl.com.tw.
+fbcdn-profile-a.akamaihd.net.
+a5.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+developers.facebook.com.
+urlseek20.vmn.net.
+213.254.76.200.in-addr.arpa.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+88p.ru.
+group36.com.my.
+buoyweather.com.
+blst.msn.com.
+a.root-servers.net.
+ns02.cashparking.com.
+9gag.com.
+apps.facebook.com.
+a.root-servers.net.
+netbit.ru.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+news-assets.rovio.com.
+login.live.com.
+static.ak.fbcdn.net.
+s-external.ak.fbcdn.net.
+c-0.19-a30f1071.40081.1518.19d0.3ea1.400.0.kn9e331jip5d71gr69pjl3h56t.avqs.mcafee.com.
+www.dlpfoodguide.com.
+104.1.168.192.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+baketech.com.
+101.10.217.98.in-addr.arpa.
+a.root-servers.net.
+pmx1.prismnet.com.
+www.hese-project.org.
+vozenoff7.blogspot.com.
+ads.phonemates.com.
+67.200.177.189.in-addr.arpa.
+trastoteca.blogspot.com.
+a3.sphotos.ak.fbcdn.net.
+211.212.143.187.in-addr.arpa.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+rons-org.ru.
+ad.yieldmanager.com.
+klimat.vl.ru.
+calendarsglobal.office.glbdns.microsoft.com.
+money.cnn.com.
+apps.facebook.com.
+www.facebook.com.
+nichegohoroshego.narod.ru.
+165.91.132.189.in-addr.arpa.
+ali.shop.sportstoday.com.
+data.flurry.com.
+www.supersavertravel.se.
+es.mg40.mail.yahoo.com.
+msn.com.
+a.root-servers.net.
+cursos-computacion.vivavisos.com.ar.
+www.youtube.com.
+mail1.entertainment.com.
+s0.2mdn.net.
+_998_76_9.
+107.146.220.66.in-addr.arpa.
+pagead2.googlesyndication.com.
+crystalpeaks.com.
+aspmx3.googlemail.com.
+ads.adxpose.com.
+fbcdn-profile-a.akamaihd.net.
+csi.gstatic.com.
+a8.sphotos.ak.fbcdn.net.
+www.adcash.com.
+.
+nochesenlima.com.
+snipergirl.ru.
+tr.wikipedia.org.
+38.73.36.186.in-addr.arpa.
+_785_79_1.
+loquebuscabas.wordpress.com.
+apps.facebook.com.
+dns.msftncsi.com.
+s-static.ak.fbcdn.net.
+mail.de.ensinger-online.com.
+cust10074-1.in.mailcontrol.com.
+113.204.130.186.in-addr.arpa.
+wd-edge.sharethis.com.
+zayuwu.com.
+www.tashadelrae.com.
+appworld.blackberry.com.
+ns2.yr.com.
+visionexotik.com.
+linkhelp.clients.google.com.
+6ru3efog2.m14u0e0e.
+www.dating-chat.net.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+mail2.digipark.com.
+bmx.texasroyalty.com.redcondor.net.
+mailscan.au.edu.
+secure.internetdownloadmanager.com.
+brandonheath.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.l.google.com.
+cdn1.ads.contentabc.com.
+sn142w.snt142.mail.live.com.
+www.teenteddies.com.
+xcdn.xgraph.net.
+ar-ar.facebook.com.
+a.root-servers.net.
+accountservices.msn.com.
+allcranerentalgeorgia.com.s8b2.psmtp.com.
+bs.serving-sys.com.
+www.robtex.com.
+pottery.ebay.com.au.
+www.google.com.
+ad2games.com.
+246.107.4.171.in-addr.arpa.
+www.nokaut.pl.
+a.root-servers.net.
+download-games.juegosindie.net.
+facebook.com.
+whitestone.spb.ru.
+setup.fanhow.com.
+cdn-1.pics.hardsextubepremium.com.
+a2.twimg.com.
+cim-mf.tmbbank.com.
+ftgx.com.s5a2.psmtp.com.
+row.bc.yahoo.com.
+148.157.68.208.in-addr.arpa.
+245.90.250.190.in-addr.arpa.
+212.60.128.69.in-addr.arpa.
+8.19.170.118.in-addr.arpa.
+a.root-servers.net.
+148.3.62.186.in-addr.arpa.
+pop.asia.secureserver.net.
+l.yimg.com.
+47.208.242.212.in-addr.arpa.
+static.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+www.marcacamps.com.
+hi-techsystems.com.s10a2.psmtp.com.
+hall-chem.com.inbound15.mxlogic.net.
+111.184.188.190.in-addr.arpa.
+16.60.153.189.in-addr.arpa.
+ps3pirata.com.
+183.16.106.177.in-addr.arpa.
+check4.facebook.com.
+h20157.www2.hp.com.
+www.gdservice.piczo.com.
+a.root-servers.net.
+d7.zedo.com.
+48.149.220.66.in-addr.arpa.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+15.70.78.208.zen.spamhaus.org.
+176.64.32.189.in-addr.arpa.
+www.google-analytics.com.
+142.40.242.88.in-addr.arpa.
+ajax.googleapis.com.
+www.seek.com.au.
+hy.wikipedia.org.
+7.188.112.200.in-addr.arpa.
+eu.wikipedia.org.
+pool.ntp.org.
+www.google-analytics.com.
+vp.kis.ru.
+i4.ytimg.com.
+a4.sphotos.ak.fbcdn.net.
+pqj16dwcxpzn20puatg53jukxowmtp62ctjx.com.
+theeclecticlife.wordpress.com.
+b:hicg4zo.h67f8t0f.
+mail06.enterhost.com.
+www.premiere.frhttp.
+a6.sphotos.ak.fbcdn.net.
+www.potube.com.
+idmtfopfphqwp.biz.
+iphonesubmissions.apple.com.
+www.escolar.com.mx.
+sn116w.snt116.mail.live.com.
+_883_68_0.
+www.patentati.it.
+a3.sphotos.ak.fbcdn.net.
+striker-manager.blogspot.com.
+secure.shared.live.com.
+s1-word-edit.vo.msecnd.net.
+redir.metaservices.microsoft.com.
+sadfas.com.
+twedge02.ohsu.edu.
+8213l4dgx.h23f9j0q.
+135.247.228.94.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+external.ak.fbcdn.net.
+149.206.30.200.in-addr.arpa.
+ic.tynt.com.
+g.ceipmsn.com.
+thecalloflove.blogspot.com.
+denis.stalker.h3q.com.
+jameique.com.
+244.172.82.67.in-addr.arpa.
+svrsecure-g2-aia.verisign.com.
+maquerosmac.blogspot.com.
+i413.photobucket.com.
+www.google.com.
+distilleryimage7.s3.amazonaws.com.
+granvillehouse.blogspot.com.
+www.satireworld.com.
+multi96.thumb.edenflirt.com.
+_716_22_9.
+www.argentinaxplora.com.
+vindiaservices.com.
+www.edmaster.it.
+44.101.243.80.in-addr.arpa.
+nhahouston.com.
+ngf:gxuk1.c14y5u2a.
+www.google-analytics.com.
+ocsp.verisign.com.
+www.msftncsi.com.
+updatekeepalive.mcafee.com.
+a4.sphotos.ak.fbcdn.net.
+www.bryanreesman.com.
+www.ceajalisco.gob.mx.
+kontur-s.ru.
+t2.gstatic.com.
+teraprom.ru.
+76.186.190.189.in-addr.arpa.
+225.177.208.201.in-addr.arpa.
+lucernevalley.net.
+247.68.22.95.in-addr.arpa.
+altex.ru.
+fi.wikipedia.org.
+static.ak.fbcdn.net.
+javadl-esd.sun.com.
+anstracker.no-ip.org.
+www.google.com.
+id.etn.net.
+91.200.66.186.in-addr.arpa.
+correo.ugr.es.
+a1.sphotos.ak.fbcdn.net.
+dtboot.orbitdownloader.com.
+ads.movpod.net.
+48.248.107.189.in-addr.arpa.
+blu.stc.s-msn.com.
+stefi-tk.ru.
+photos-g.ak.fbcdn.net.
+www.tvnotas.com.
+asegenpropiedades.cl.
+a.root-servers.net.
+i2.ytimg.com.
+mail.cityoflafayette.com.
+www.pronosticssportif.com.
+cblproball.com.
+218.254.192.187.in-addr.arpa.
+sites.google.com.
+a2.sphotos.ak.fbcdn.net.
+ads16411.hotwords.es.
+twitter.com.
+a1001.w40.akamai.net.
+stk:zrmf8.b97d6e1h.
+www.mims.com.sg.
+staff.tabideru.com.
+andersenjoy.com.
+a1.sphotos.ak.fbcdn.net.
+71.242.143.187.in-addr.arpa.
+js.media.motortopia.com.
+charbonneau.com.
+www.googleadservices.com.
+www.afianza.com.mx.
+21.168.248.111.in-addr.arpa.
+www.carlkleiner.com.
+photos-a.ak.fbcdn.net.
+crl.usertrust.com.
+selenaweb.org.
+wootton-hall.com.
+236.29.2.24.in-addr.arpa.
+profile.ak.fbcdn.net.
+ssl.gstatic.com.
+64.92.213.201.in-addr.arpa.
+.
+amasscn.en.made-in-china.com.
+api-public.addthis.com.
+view.atdmt.com.
+cocomponents.com.
+www.youtube.com.
+twitter.com.
+a.root-servers.net.
+r.mzstatic.com.
+crprint.com.s6b2.psmtp.com.
+photos-f.ak.fbcdn.net.
+69.249.46.189.in-addr.arpa.
+es.avatars.yahoo.com.
+s-static.ak.facebook.com.
+sexyrebelde69.obolog.com.
+profiles.google.com.
+gfx4.hotmail.com.
+www.gayanime.com.
+berghof.de.
+47.174.1.24.in-addr.arpa.
+mail.wsasystems.com.
+148.121.230.201.in-addr.arpa.
+www.facebook.com.
+time.nist.gov.
+upctv.com.
+127.79.233.178.in-addr.arpa.
+mx.mail.sogou.com.
+api.mixpanel.com.
+a2.sphotos.ak.fbcdn.net.
+200.210.224.190.in-addr.arpa.
+affordableinsurance.us.
+www.colorearte.cl.
+www.uzai.com.
+us.lrd.yahoo.com.
+www.bbc.co.uk.
+recursos.espaciosexy.com.
+external.ak.fbcdn.net.
+136.71.43.208.in-addr.arpa.
+safebrowsing.clients.google.com.
+teredo.ipv6.microsoft.com.
+230.246.159.79.in-addr.arpa.
+64.1.168.192.in-addr.arpa.
+s-static.ak.facebook.com.
+madewithluv.com.
+e906.g.akamaiedge.net.
+a8.sphotos.ak.fbcdn.net.
+www.alfainmo.com.
+photos-c.ak.fbcdn.net.
+www.google.com.
+www.facebook.com.
+q75hrirce.99ax.
+inmortalyvampiros.blogspot.com.
+las-chicas-superpoderosas-z.blogspot.com.
+dns.msftncsi.com.
+51.174.126.2.in-addr.arpa.
+cliffordchance.com.
+www.potter.web.id.
+147.125.46.189.in-addr.arpa.
+gfxp.com.
+www.lifeyoyo.com.
+29.124.45.216.in-addr.arpa.
+vcs2.msg.yahoo.com.
+polychem-usa.com.
+liteonit.com.
+sinlatvcom.chatango.com.
+a.root-servers.net.
+cdn-6.pics.redtubeplatinum.com.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+www.facebook.com.
+ksn2-12.kaspersky-labs.com.
+photos-f.ak.fbcdn.net.
+jtaby.com.
+45.102.150.91.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ocsp.verisign.com.
+www.kinkydates.com.
+176.216.80.190.in-addr.arpa.
+www.tastygo.com.
+androidsdk.ads.mp.mydas.mobi.
+218.141.97.109.in-addr.arpa.
+noticias.terra.cl.
+www.zorritasconcam.com.
+a4.sphotos.ak.fbcdn.net.
+luciensteil.tripod.com.
+support.euro.dell.com.
+whyweightinternational.com.
+www.google-analytics.com.
+touch.facebook.com.
+validator.w3.org.
+seg.sharethis.com.
+www.super-science-fair-projects.net.
+check6.facebook.com.
+66.177.6.186.in-addr.arpa.
+partyreflections.com.
+74.95.135.187.in-addr.arpa.
+foundation-financial.com.
+a.root-servers.net.
+d2094073.xoom.it.
+jewel-staite.net.
+msc.wlxrs.com.
+c5.zedo.com.
+a.root-servers.net.
+photos-g.ak.fbcdn.net.
+rdgoodgebuilder.co.uk.
+243.102.51.72.in-addr.arpa.
+222.101.199.190.in-addr.arpa.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+es.astrology.yahoo.com.
+76.228.121.123.in-addr.arpa.
+63.42.223.189.in-addr.arpa.
+exp02.eset.com.
+photos-e.ak.fbcdn.net.
+mx2.interworld.net.
+t-online.de.
+www9.effectivemeasure.net.
+a.root-servers.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+96.179.165.58.in-addr.arpa.
+ajax.aspnetcdn.com.
+me-cdn.effectivemeasure.net.
+teredo.ipv6.microsoft.com.
+www.adobe.com.
+44-courier.push.apple.com.
+mail.sdoamg.com.
+264lpgc88.08gm.
+81.154.227.77.in-addr.arpa.
+kailea.com.
+114.21.101.187.in-addr.arpa.
+233.170.8.99.in-addr.arpa.
+42.106.81.75.in-addr.arpa.
+kayser-roth.com.s5b2.psmtp.com.
+landquestdevelopment.com.s5b2.psmtp.com.
+:xa96l8dm.75na.
+12.122.172.189.in-addr.arpa.
+ccpi-inc.com.s5b1.psmtp.com.
+photos-a.ak.fbcdn.net.
+163.148.134.174.in-addr.arpa.
+65.145.133.50.in-addr.arpa.
+ssl.gstatic.com.
+extremefitnessco.com.
+www.dofiscal.net.
+a.triggit.com.
+konata-station.net.
+www.mozilla.org.
+hofferflow.com.
+estrenosperu.jimdo.com.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+torrent.mangastream.to.
+local-sn.contacts.msn.com.
+a.root-servers.net.
+ns56.1und1.de.
+dns.msftncsi.com.
+creative.ak.fbcdn.net.
+66.172.22.190.in-addr.arpa.
+bin-short.whatsapp.net.
+www.ethorprotect.com.
+a8.sphotos.ak.fbcdn.net.
+www.chicasasiaticas.com.ar.
+distilleryimage9.s3.amazonaws.com.
+crl.microsoft.com.
+yunno.com.
+googleads.g.doubleclick.net.
+apple-mobile.query.yahooapis.com.
+www.google.com.
+en.wikipedia.org.
+ml-rl.fsbusiness.co.uk.
+www.ccee.ch.
+photos-a.ak.fbcdn.net.
+accounts.google.com.
+235.26.31.189.in-addr.arpa.
+l8qczsku7.87ct.
+www.lapopottedemanue.com.
+a.root-servers.net.
+50.195.249.190.in-addr.arpa.
+static.depers.nl.
+dr._dns-sd._udp.na.pg.com.
+itworks.com.
+www.google-analytics.com.
+d3lvr7yuk4uaui.cloudfront.net.
+agentphone.co.uk.
+31-courier.push.apple.com.
+britishmidland.co.uk.
+i.juegosdecartas.org.
+www.google-analytics.com.
+mail.infosys.ru.
+233.29.99.190.in-addr.arpa.
+sp.cwfservice.net.
+clock.fmt.he.net.
+hughdancy.info.
+api.webrep.avast.com.
+mami.
+youtube.com.
+www.mocacleveland.org.
+t.co.
+peloterosperuanos.blogspot.com.
+s-static.ak.facebook.com.
+profile.ak.fbcdn.net.
+a728.g.akamai.net.
+www.googleadservices.com.
+v3.cache3.c.youtube.com.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+www.roflzoo.com.
+photos-f.ak.fbcdn.net.
+s-static.ak.facebook.com.
+www.boost-your-low-testosterone.com.
+65.213.14.50.in-addr.arpa.
+39games.com.
+a.root-servers.net.
+actionteam.es.
+c247723.r23.cf1.rackcdn.com.
+introsco.ru.
+hi-in.facebook.com.
+domssl.mercadolibre.com.co.
+endirect.radio-canada.ca.
+a8.sphotos.ak.fbcdn.net.
+179.98.135.89.in-addr.arpa.
+www.meristation.es.
+49.216.141.75.in-addr.arpa.
+elite-traveller.ru.
+77.92.158.189.in-addr.arpa.
+badoo.com.
+www.epyte.com.
+ads1.msads.net.
+fontmatrix.net.
+www.jrhjw.com.
+cybercomp.com.
+s.ytimg.com.
+www.tourvenezuela.com.ve.
+uk.f1324.mail.yahoo.com.
+nothingtocontribute.tumblr.com.
+www.facebook.com.
+163.201.25.190.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.sithma.com.
+a4.sphotos.ak.fbcdn.net.
+laboratorio.clandlan.net.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+gfinpolish.blogspot.com.
+www.facebook.com.
+www.mandtbank.com.
+static.getclicky.com.
+205.141.157.189.in-addr.arpa.
+s-static.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+photos-h.ak.fbcdn.net.
+aussiemail.com.
+altfarm.mediaplex.com.
+www.deblancointernet.com.
+google.com.
+89.247.20.95.in-addr.arpa.
+mdsaude.disqus.com.
+scribe.twitter.com.
+leon.gob.mx.
+110.79.129.189.in-addr.arpa.
+ksn2-12.kaspersky-labs.com.
+svitanok.ru.
+tagmarks.jmin.net.
+ntp1.cs.wisc.edu.
+s3.amazonaws.com.
+145.236.230.91.in-addr.arpa.
+www.ebay.es.
+i1.ytimg.com.
+11.140.198.68.in-addr.arpa.
+external.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+catalog-retail.amazon.com.
+download330.avast.com.
+photos-d.ak.fbcdn.net.
+www.cpxadspace.com.
+a8.sphotos.ak.fbcdn.net.
+www.google.com.
+s0.2mdn.net.
+14.8.84.200.in-addr.arpa.
+ru.mirror.alawar.com.
+151.172.62.190.in-addr.arpa.
+mx2.neonhost.com.
+65.1.168.192.in-addr.arpa.
+226.2.172.190.in-addr.arpa.
+i1.ytimg.com.
+t1.gstatic.com.
+upload.itvnn.net.
+www.google.com.
+www.iamosx.com.
+65.250.120.124.in-addr.arpa.
+www.meowhoo.com.
+climatec.com.inbound15.mxlogic.net.
+s2.youtube.com.
+240.84.67.24.zz.countries.nerd.dk.
+www.kwinanatech.com.
+www.google-analytics.com.
+66.33.224.190.in-addr.arpa.
+sky.ee.
+64.141.53.201.in-addr.arpa.
+a.root-servers.net.
+39.152.101.75.in-addr.arpa.
+pegasusrealty.us.
+sigs.symantec.com.
+y2wkcl6ve.q54m2e9w.
+literariokapasulino.blogspot.com.
+a1767.phobos.apple.com.
+content.cricinfo.com.edgesuite.net.
+join.societysm.com.
+a.root-servers.net.
+a.root-servers.net.
+inbound.haakon.com.netsolmail.net.
+ut8.xhamster.com.
+21.201.34.187.in-addr.arpa.
+static.searchya.com.
+www.total3d.ru.
+ncbaptist.org.
+169.119.136.186.in-addr.arpa.
+connect.facebook.net.
+www.apetube.com.
+knockman.com.
+gta-nuevoleon.blogspot.com.
+i.i.com.com.
+any-global.mg.mail.am0.yahoodns.net.
+www.dpinterracial.com.
+pixel.33across.com.
+www.torrentzap.com.
+99.46.48.190.in-addr.arpa.
+a.root-servers.net.
+ajax.googleapis.com.
+teredo.ipv6.microsoft.com.
+hay.
+profiles.google.com.
+google.com.
+alerts.conduit-services.com.
+googleads.g.doubleclick.net.
+jcmountainview.com.
+pt-br.facebook.com.
+www.google.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.theydrawandtravel.com.
+19.228.171.69.in-addr.arpa.
+www.facebook.com.
+a.root-servers.net.
+a6.sphotos.ak.fbcdn.net.
+ocsp.verisign.net.
+www.facebook.com.
+132.15.152.187.in-addr.arpa.
+_080_08_2.
+login.live.com.
+photos-d.ak.fbcdn.net.
+ads.adxpose.com.
+s2.youtube.com.
+cdn.api.twitter.com.
+mail.abbottinsuranceagency.com.
+bateriaswillard.com.
+static.ak.fbcdn.net.
+clarence.com.
+26.6.106.201.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.msn.com.
+americansuburbx.com.
+freemail.com.ru.
+136.27.138.201.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+36.4.31.186.in-addr.arpa.
+a.root-servers.net.
+www.google.es.
+89.183.220.201.in-addr.arpa.
+49-courier.push.apple.com.
+84viwst58.32ta.
+ipad.91.com.
+paisleystclaire.typepad.com.
+books.google.com.mx.
+_854_29_8.
+a.root-servers.net.
+www.granch.ru.
+185.162.48.190.in-addr.arpa.
+9.229.194.186.in-addr.arpa.
+www.defiendetufamilia.com.
+static.ak.fbcdn.net.
+203.56.11.190.in-addr.arpa.
+www.star-wars3d.com.
+wo.wikipedia.org.
+43.96.189.24.in-addr.arpa.
+profile.ak.fbcdn.net.
+shop.broccoli.co.jp.
+pagead2.googlesyndication.com.
+aca.gov.au.
+eo.wikipedia.org.
+photos-g.ak.fbcdn.net.
+www.myhappyplanet.com.
+gmail.com.
+observatorio.atriumlinguarum.org.
+www.google-analytics.com.
+54.53.93.186.in-addr.arpa.
+external.ak.fbcdn.net.
+48.177.223.77.in-addr.arpa.
+70.12.14.125.in-addr.arpa.
+eriadi.elkhabar.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+iemcontractors.com.
+earth.google.co.uk.
+35.76.165.190.in-addr.arpa.
+s-static.ak.facebook.com.
+239.19.132.187.in-addr.arpa.
+gdata.youtube.com.
+www.lafd.org.
+4q7irqere.47qh.
+webng.com.
+79.22.245.190.in-addr.arpa.
+kekop.com.
+us.mc1215.mail.yahoo.com.
+y3.ifengimg.com.
+14.204.kam-telecom.ru.lan.
+84.113.159.187.in-addr.arpa.
+s-static.ak.fbcdn.net.
+214.16.125.74.in-addr.arpa.
+www.biodanza-adrian.com.ar.
+goglingb.org.
+eu.ecs.com.tw.
+hi-in.facebook.com.
+www.physiciansofficeresource.com.
+www.facebook.com.
+179.211.124.201.in-addr.arpa.
+a2.twimg.com.
+www.peliculastnt.com.
+download.microsoft.com.
+gaming.hardwareheaven.com.
+softwarena.com.
+ksn2-12.kaspersky-labs.com.
+www.kathyskakes.com.
+161.216.14.186.in-addr.arpa.
+embaqmail.com.
+65.88.54.75.in-addr.arpa.
+www.xtremethumbs.com.
+a.root-servers.net.
+blackmilkclothing.myshopify.com.
+www.mataderos.info.
+www.juegajuegosflash.com.
+71.94.172.189.in-addr.arpa.
+162.230.23.71.in-addr.arpa.
+ad-apac.doubleclick.net.
+www.time.com.
+105.186.191.186.in-addr.arpa.
+www.facebook.com.
+isearch.avg.com.
+helpcenter.spp.com.
+stanpark.com.
+.
+www.celebrityclubber.com.
+kadgeo.ru.
+nottango.bandcamp.com.
+code.jquery.com.
+cdn1.hitnettracer.com.
+6.28.39.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+www.facebook.com.
+mebeingcrafty.com.
+mail.danvadenchevrolet.com.
+sites.google.com.
+_023_46_3.
+www.facebook.com.
+a.root-servers.net.
+startechev.com.
+a.root-servers.net.
+es.msn.com.
+b._dns-sd._udp.belkin.
+es.answers.yahoo.com.
+translate.google.com.
+planetadepeliculaskriec.blogspot.com.
+a7.sphotos.ak.fbcdn.net.
+34.120.24.217.in-addr.arpa.
+www1.blogblog.com.
+zynga2-a.akamaihd.net.
+sp.cwfservice.net.
+97.245.77.188.in-addr.arpa.
+profile.ak.fbcdn.net.
+api.twitter.com.
+java-source.net.
+cutekittens.com.
+photos-f.ak.fbcdn.net.
+meredithtv.us.intellitxt.com.
+235.102.114.1.in-addr.arpa.
+228.29.76.189.in-addr.arpa.
+efacico.wordpress.com.
+www.facebook.com.
+google.com.
+thelariat.com.
+a.root-servers.net.
+238.30.142.79.in-addr.arpa.
+adops.alloy.com.
+docs.google.com.
+www.castillodearena.edu.mx.
+b-t.com.ua.
+apps.facebook.com.
+125.195.198.190.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+mx1.flirble.org.
+csi.gstatic.com.
+www.bywifi.com.
+186.46.30.83.in-addr.arpa.
+224.30.168.192.in-addr.arpa.
+s-static.ak.facebook.com.
+27.8.224.189.in-addr.arpa.
+static.ak.fbcdn.net.
+certificates.godaddy.com.
+137.196.141.201.in-addr.arpa.
+mail.goole.net.
+226.46.55.189.in-addr.arpa.
+enviayreporta.esmas.com.
+indieclick.3janecdn.com.
+photos-h.ak.fbcdn.net.
+79.75.220.87.in-addr.arpa.
+www.facebook.com.
+www.supercuts.com.au.
+myapself.blogspot.com.
+www.search-results.com.
+mailman2.youngsmarket-ut.com.
+www.google-analytics.com.
+inbound.dominiontruss.com.netsolmail.net.
+static.exoclick.com.
+ksn2-12.kaspersky-labs.com.
+mx01.comp-pro-dns.de.
+www.evostc.state.ak.us.
+photos-d.ak.fbcdn.net.
+www.joris-vervuurt.com.
+www.lsgmodelsnude.com.
+udc.msn.com.
+l.betrad.com.
+gamezer.com.
+www.mbtshoesdepot.com.
+a1.sphotos.ak.fbcdn.net.
+media.scenedaily.com.
+apps.facebook.com.
+quebecblogue.com.
+146.79.236.201.in-addr.arpa.
+i4.ytimg.com.
+www.google.com.
+safebrowsing-cache.google.com.
+leaderbusiness.com.
+l7dxx99jn.76zr.
+attachment.fbsbx.com.
+www.hk.com.
+charlesburt.com.
+4.177.244.207.in-addr.arpa.
+beatwolf.com.
+support.google.com.
+connect.facebook.net.
+sports.yahoo.com.
+y3agg2b81.36ej.
+www.gravatar.com.
+120.145.85.77.in-addr.arpa.
+.
+ssl.gstatic.com.
+1.234.10.83.in-addr.arpa.
+89.54.200.178.in-addr.arpa.
+nexisint.com.
+twitter.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+a.root-servers.net.
+st.p.360.cn.
+pt-br.facebook.com.
+a.root-servers.net.
+secure.wlxrs.com.
+2.m0n0wall.pool.ntp.org.
+www.precisiondrilling.com.
+apix.iminent.com.
+jhc.co.uk.
+stardock-logonstudio.softonic.com.
+jones-thomas-md.com.
+www.d365.org.
+profile.ak.fbcdn.net.
+www.peoplefinders.org.
+239.22.127.201.in-addr.arpa.
+244.239.229.88.in-addr.arpa.
+naruto.wikia.com.
+62.138.6.189.in-addr.arpa.
+www.godofwar.com.
+171.30.220.189.in-addr.arpa.
+mail1.westernrefining.com.
+www.maj.ie.edu.
+www.tequilabeachtours.com.
+208.126.233.201.in-addr.arpa.
+static.ak.facebook.com.
+mx.parktelusa.com.
+ocsp.thawte.com.
+a785.phobos.apple.com.
+mountaincreek.com.s5a1.psmtp.com.
+m.facebook.com.
+ms.adscope.co.kr.
+flow-entertainment.com.
+vivaldi-travel.ru.
+de.cliplike.net.
+hello.connectivity.me.com.
+widget.plugrush.com.
+200.151.252.201.in-addr.arpa.
+dns.msftncsi.com.
+www.3dtv.com.
+unifi.
+appsmetadata.toolbar.conduit-services.com.
+253.104.170.189.in-addr.arpa.
+catolicosfirmes.phpbbforo.com.
+maggiered.blogspot.com.
+www.chicaswebcam803.com.
+support.google.com.
+www.google-analytics.com.
+callwriter.com.
+dns.msftncsi.com.
+csi.gstatic.com.
+ns.dipmap.com.
+sup.arnuvo.ru.
+apps.facebook.com.
+fs_bt.qq.com.
+utm.trk.mywebsearch.com.
+ad.leadboltapps.net.
+feeds.bbci.co.uk.
+google.com.
+a3.sphotos.ak.fbcdn.net.
+splav.net.ru.
+pixel.facebook.com.
+careercenter.com.
+processanalyzers.net.
+v17.nonxt7.c.youtube.com.
+www.cssforum.com.pk.
+twitpic.com.
+stonehardware.com.
+shortstop-left-field.blogspot.com.
+www.djkrac.blogspot.com.
+www.oneclickshooting.com.
+frontend.weeds.mytopia.com.
+www.strefa.pl.
+197.51.93.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+servicenet.com.
+26.135.213.201.in-addr.arpa.
+12.122.113.195.in-addr.arpa.
+225.14.85.99.in-addr.arpa.
+profile.ak.fbcdn.net.
+external.ak.fbcdn.net.
+ellsworth.net.
+131.87.5.88.in-addr.arpa.
+www.hotelrua.com.
+17.15.208.95.in-addr.arpa.
+alfrasha.maktoob.com.
+img226.imagevenue.com.
+galleries.messygangbangs.com.
+www.facebook.com.
+argentinarrhh.blogspot.com.
+_527_09_1.
+google.com.
+a.root-servers.net.
+www.bing.com.
+aquanet.com.
+www.facebook.com.
+ic.tynt.com.
+rs38dt.rapidshare.com.
+es.answers.yahoo.com.
+a.root-servers.net.
+r.mzstatic.com.
+a.root-servers.net.
+a.root-servers.net.
+chokefrantic.hubpages.com.
+static.ak.fbcdn.net.
+ledergroup-com.mail.eo.outlook.com.
+push2check.com.
+embarazadafeliz.com.
+www.jethrotull.com.
+r1.gslb.ace.advertising.com.adcom.akadns.net.
+www.ideasdenegocio.com.co.
+platform0.twitter.com.
+a8.sphotos.ak.fbcdn.net.
+_378_56_8.
+pixel.facebook.com.
+www.nuevebits.com.
+a1174.g.akamai.net.
+250.146.42.201.in-addr.arpa.
+www.super8news.com.
+www.elcrimennopaga.com.
+a5.sphotos.ak.fbcdn.net.
+account.live.com.
+photos-h.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+news.google.com.
+www.jacksmannequin.com.
+mx2.oregonmetro.gov.
+cmdos.files.wordpress.com.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+l.yimg.com.
+agent.kuaiwan.com.
+photos-e.ak.fbcdn.net.
+www.youtube.com.
+photos-e.ak.fbcdn.net.
+wzus1.search-results.com.
+a.root-servers.net.
+www.hotelreservaciones.com.mx.
+newsrss.bbc.co.uk.
+www.stephisparadise.com.
+138.76.200.186.in-addr.arpa.
+8207.4.img98.net.
+mf.orkut.vostu.com.
+external.ak.fbcdn.net.
+8mln:f:84.k41w9z9y.
+www.facebook.com.
+optimized-by.rubiconproject.com.
+mobile.search.aol.com.
+www.crlsresearchguide.org.
+ds.serving-sys.com.
+149.168.9.61.in-addr.arpa.
+a.root-servers.net.
+www.volleyball-tours.com.
+lenix.com.br.
+68.84.224.125.in-addr.arpa.
+217.152.48.190.in-addr.arpa.
+prod-nr285.voxer.com.
+d2055523.instant.xoom.it.
+images.effexmedia.com.
+host.name.ru.
+permlight.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+www.1wanwan.com.
+static.ak.fbcdn.net.
+141.39.160.190.in-addr.arpa.
+www.baidu.com.
+gone-star.tumblr.com.
+www.sonesta.com.
+a.root-servers.net.
+208.72.131.82.in-addr.arpa.
+59.187.195.71.in-addr.arpa.
+ee:evptz7.l32p6r6o.
+satfile300.corp.kbr.com.beknet.us.
+a.root-servers.net.
+31.201.163.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+ad.adnetwork.net.
+img.android.maxpedia.org.
+cityvillefb1.static.zgncdn.com.
+www.allposters.com.tr.
+isiprint.net.
+hiphopgalaxy.com.
+www.ticketmaster.com.
+aneses.com.
+14.34.92.93.in-addr.arpa.
+cmapspublic2.ihmc.us.
+www.jocjuegos.com.
+login.skype.com.
+www.ocesa.com.mx.
+campusdigital.uag.mx.
+www.gstatic.com.
+google.com.
+celularessonyericsson.para-celulares.com.
+www.liverpool-live.info.
+vewrizon.net.
+photos-e.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+cirkor.se.
+reng.ru.
+www.apic.org.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+skhamp.files.wordpress.com.
+a1724.phobos.apple.com.edgesuite.net.
+fls.doubleclick.net.
+i2.ytimg.com.
+205.47.194.187.in-addr.arpa.
+mail2brussels.com.
+altaiagro.com.
+72.33.134.188.in-addr.arpa.
+b._dns-sd._udp.lan.
+s2.youtube.com.
+phxdata.com.
+shop65367577.taobao.com.
+apis.google.com.
+cdn.montiera.com.
+nvkz.net.
+static.ak.fbcdn.net.
+blufiles.storage.msn.com.
+www.harleyandharlett.blogspot.com.
+wii.mmgn.com.
+tobolsk.info.
+31.60.49.190.in-addr.arpa.
+ad.doubleclick.net.
+dtboot.orbitdownloader.com.
+cine.es.msn.com.
+www.strbk.fr.
+api.facebook.com.
+9gag.com.
+eldelyayo.blogspot.com.
+mlb.mlb.com.
+it-it.facebook.com.
+109.218.117.75.in-addr.arpa.
+au.download.windowsupdate.com.
+mta4.am0.yahoodns.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+148.88.145.201.in-addr.arpa.
+filter2.mittkontor.no.
+tracker.mightynova.com.
+ezay55cz5.65wy.
+www.google.com.
+gte.n.
+thumbs1.ebaystatic.com.
+purenetworks.com.
+.
+www.animal-games.biz.
+mail.v1mortgage.com.
+53.110.102.201.in-addr.arpa.
+b.scorecardresearch.com.
+ar-ar.facebook.com.
+static.ak.fbcdn.net.
+taipei.org.nz.
+infectomica.cinvestav.mx.
+bbfdyz3yz.57sl.
+m.facebook.com.
+www.google.com.
+taz.de.
+baymsg1010833.by2.gateway.edge.messenger.live.com.
+www.tarif-mobile.ru.
+newsrss.bbc.co.uk.
+a.root-servers.net.
+us.yimg.com.
+communityvoices.sites.post-gazette.com.
+ut2.xhamster.com.
+romana.babylon.com.
+humorvice.blogspot.com.
+a7.sphotos.ak.fbcdn.net.
+mx183.emialfiltering.com.
+www.socialmediasl.com.
+a.root-servers.net.
+c10038.ic-live.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sro.whatsapp.net.
+itunes.apple.com.
+external.ak.fbcdn.net.
+www.batanga.com.
+teredo.ipv6.microsoft.com.
+wheels.blogs.nytimes.com.
+23.242.163.189.in-addr.arpa.
+91.175.140.194.in-addr.arpa.
+www.plabell.com.
+a2.sphotos.ak.fbcdn.net.
+distilleryimage5.instagram.com.
+212.171.131.189.in-addr.arpa.
+ocsp.godaddy.com.
+yahoo.com.
+alger.ebuddy.com.
+35.207.23.92.in-addr.arpa.
+ae.adserver.yahoo.com.
+m.addthisedge.com.
+1.70.16.172.in-addr.arpa.
+crl.microsoft.com.
+hk.search.auctions.yahoo.com.
+tobolsk.info.
+9q5lzw5c2.n96f0r1q.
+46.117.103.201.in-addr.arpa.
+tools.google.com.
+update.messenger.yahoo.com.
+110.21.39.81.in-addr.arpa.
+241.116.172.187.in-addr.arpa.
+game.softick.com.
+www.siempreeducando.com.
+ad-g.doubleclick.net.
+us1.harunyahya.com.
+tko7ia.bay.livefilestore.com.
+82.107.39.190.in-addr.arpa.
+a.root-servers.net.
+mail.kcengineering.com.
+107.178.179.190.in-addr.arpa.
+mail.lobosservices.com.
+royalflush.ru.
+market.android.com.
+data.shopsavvy.mobi.
+www.gmflotillas.com.mx.
+235.189.26.201.in-addr.arpa.
+_818_12_0.
+adsfront.iminent.com.
+239.166.236.189.in-addr.arpa.
+apeco.org.pe.
+www.google.com.
+chicostara.com.
+urbanterror.mtc-team.fr.
+storage.conduit.com.
+cs1752.vkontakte.ru.
+photos-d.ak.fbcdn.net.
+\(none\).
+lavozdecristian.cl.woopra-ns.com.
+102.148.144.189.in-addr.arpa.
+www.google.com.
+partner.googleadservices.com.
+reawards.ru.
+smtp-in2.sfbcic.com.
+thedanisgroup.com.
+estate-insurance-credit-conference.ru.
+a997.mm1.akamai.net.
+ads.yimg.com.
+100.110.175.190.in-addr.arpa.
+hootsuite.com.
+16.79.31.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+207.42.42.186.in-addr.arpa.
+ar-ar.facebook.com.
+7.169.122.195.in-addr.arpa.
+aidps.atdmt.com.
+www.crushingonclothes.com.
+www.facebook.com.
+www.quiebro.com.
+www.facebook.com.
+ksn2-12.kaspersky-labs.com.
+profile.ak.fbcdn.net.
+ad-g.doubleclick.net.
+_653_20_8.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+download115.avast.com.
+ws-cloud-msgplus.linkury.com.
+30.117.5.189.in-addr.arpa.
+242.240.10.187.in-addr.arpa.
+wistron.com.
+biasabaeiki.blogspot.com.
+www.facebook.com.
+ie9cvlist.ie.microsoft.com.
+teredo.ipv6.microsoft.com.
+desmorrugador.bravehost.com.
+www.gocanvas.com.
+tallerdelibros.com.
+www.bostonherald.com.
+www.bilatinmen.com.
+photos-a.ak.fbcdn.net.
+diabetes.todominio.com.
+www.facebook.com.
+widgets.amung.us.
+195.252.127.187.in-addr.arpa.
+pagead.l.doubleclick.net.
+gfx4.hotmail.com.
+photos-g.ak.fbcdn.net.
+www.gpbatteries.com.
+mx.youtube.com.
+acordiare.com.
+unitmagazine.com.
+gymnasticbodies.com.
+ad.doubleclick.net.
+a1.sphotos.ak.fbcdn.net.
+223.128.121.94.in-addr.arpa.
+global.nytimes.com.
+accounts.google.com.
+www.69bits.com.
+fremont.downtown.net.
+nina.pagesz.net.
+www.woitalia.it.
+bravox.net.
+172.199.163.142.in-addr.arpa.
+navy.mil.
+182.69.46.189.in-addr.arpa.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+yaoi-haven.com.
+app54.logmein.com.
+geo.tp-cdn.com.
+s.mfcdn.net.
+p06-contacts.icloud.com.
+67.174.63.83.in-addr.arpa.
+www.ukwhitegoods.co.uk.
+cm.ac3.msn.com.
+dns.msftncsi.com.
+pixel.facebook.com.
+media.esmas.com.
+a1.sphotos.ak.fbcdn.net.
+242.30.62.186.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+admeld.adnxs.com.
+mx.youtube.com.
+118.199.216.89.in-addr.arpa.
+73.111.31.190.in-addr.arpa.
+zh-cn.facebook.com.
+google.com.
+186.14.229.201.in-addr.arpa.
+siteholder.ru.
+www.addthis.com.
+caldwellw.freeserve.co.uk.
+graph.facebook.com.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+109.75.105.75.in-addr.arpa.
+maldi.tv.
+apuntesparaestudiar.com.
+uralhosting.ru.
+www.belkin.com.
+156.46.83.78.in-addr.arpa.
+cborange.com.
+platform.twitter.com.
+www.google-analytics.com.
+fbcdn-profile-a.akamaihd.net.
+dfdffdf.com.
+www.battlefieldadventures.com.
+conn.skype.com.
+a.root-servers.net.
+tc.v23.cache5.c.youtube.com.
+scotia70657275.h1x.com.
+235.189.91.186.in-addr.arpa.
+115.53.48.190.in-addr.arpa.
+i4.ytimg.com.
+127.189.22.190.in-addr.arpa.
+a.root-servers.net.
+clients1.google.com.
+133.0.0.10.in-addr.arpa.
+54.55.82.200.in-addr.arpa.
+hypermetix.net.
+58.56.35.187.in-addr.arpa.
+www.milenio.com.
+www.gstatic.com.
+pushpoppress.com.
+2.174.254.201.in-addr.arpa.
+www.elsegundero.com.
+whiteandassociates.net.bak-mx.na0102.smtpbak.comcom.
+teredo.ipv6.microsoft.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+101.45.138.24.in-addr.arpa.
+www.msftncsi.com.
+a.ads2.msads.net.
+totallycellular.net.bak-mx.smtproutes.com.
+a1.sphotos.ak.fbcdn.net.
+68ohh6com6c1h-c.c.yom.mail.yahoo.com.
+9.233.174.190.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+freephotocalendar.net.
+a.root-servers.net.
+gmail.com.
+eivyaaox.info.
+cs221.stanford.edu.
+mailx.hoster.ru.
+a.root-servers.net.
+biowiki.ucdavis.edu.
+f741.mail.yahoo.com.
+iowa-city.org.inbound45.mxlogicmx.net.
+www.synonyms-antonyms.com.
+sumvm1.vnet.ibm.com.
+19.219.109.101.in-addr.arpa.
+152.23.50.190.in-addr.arpa.
+a.root-servers.net.
+202.11.19.189.in-addr.arpa.
+dns.msftncsi.com.
+beta.stun.voice.yahoo.com.
+www.facebook.com.
+246.200.57.186.in-addr.arpa.
+www.swallowsquirt.com.
+photos-e.ak.fbcdn.net.
+ksn1-11-part1.kaspersky-labs.com.
+static.ak.fbcdn.net.
+evssl-aia.geotrust.com.
+219.148.56.186.in-addr.arpa.
+signin.ebay.com.
+wpad.
+85.61.174.190.in-addr.arpa.
+wdg1.apple.com.
+97.73.105.187.in-addr.arpa.
+p1901.infolinks.com.
+t9ahqgs4m.06zw.
+infoworld.com.s6b1.psmtp.com.
+mail.onlinep2000.com.
+u1.ac.hk2.yahoo.com.
+a.root-servers.net.
+id.google.com.
+14.149.221.190.in-addr.arpa.
+creative.clicksor.com.
+a8.sphotos.ak.fbcdn.net.
+x264dev.multimedia.cx.
+ocsp.verisign.com.
+www.youtube-nocookie.com.
+rv.coupish.com.
+cdn2.pugetsystems.com.
+pagead2.googlesyndication.com.
+242.45.117.200.in-addr.arpa.
+.
+vidasilvestre.org.ar.
+107.111.143.89.in-addr.arpa.
+www.mmorpgranks.com.
+assets4.castle.zgncdn.com.
+www.bfeditor.org.
+expert.co.th.
+wixmobile.com.
+boblynchford.com.
+www.desafiointel.com.
+a.root-servers.net.
+stock.joinsmsn.com.
+123.69.59.186.in-addr.arpa.
+kaibacorp0.50megs.com.
+dbru.br.ns.els-gms.att.net.
+s3.sidereel.com.
+club-krasotki.ru.
+www.facebook.com.
+resources.search.conduit.com.
+app.appgefahren.de.
+_957_33_5.
+131.149.18.187.in-addr.arpa.
+agothsphere.com.
+a1113.da1.akamai.net.
+lgrlwq.bay.livefilestore.com.
+s5bi:uk6r.61le.
+179.17.46.208.in-addr.arpa.
+damonbraces.com.
+static.ak.fbcdn.net.
+www.google-analytics.com.
+gilat.net.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+www.facebook.com.
+www.google-analytics.com.
+ejabat.google.com.
+stun.client.akadns.net.
+safebrowsing.clients.google.com.
+www.valleviejo1041.com.ar.
+vcs1.msg.yahoo.com.
+www.facebook.com.
+www.cliphai.com.
+waggingthefox.blogspot.com.
+www.google.com.
+images.hornymatches.com.
+client.akamai.com.
+fbcdn-profile-a.akamaihd.net.
+creative.ak.fbcdn.net.
+anna-zont.blogspot.com.
+www.flickr.com.
+i2.ytimg.com.
+hotmail.com.
+fbcdn-profile-a.akamaihd.net.
+gpcom.srvc.metaboli.net.
+toolbarqueries.google.com.
+l.yimg.com.
+www.megaplay.ru.
+www.skipsnotes.com.
+wallet.google.com.
+mdawmdezmtaxmjaxmg.org.
+73.67.222.189.in-addr.arpa.
+143.239.200.112.in-addr.arpa.
+ad.harrenmedianetwork.com.
+connect.facebook.net.
+www.cosl.com.au.
+67.38.150.187.in-addr.arpa.
+220.95.192.187.in-addr.arpa.
+sharebit.net.
+www.poemaspoetas.com.
+vpaf.unr.edu.
+i4.ytimg.com.
+www.philippinen-life.de.
+indusladies.com.
+photos-f.ak.fbcdn.net.
+cnn.joins.com.
+a1003.w41.akamai.net.
+5y1r4y9fs.75xq.
+www.albercas.mx.
+udo.informatik.uni-dortmund.de.
+3alp17:cq.j75p7l0w.
+davidrio.com.
+www.arabize.com.eg.
+010c36352e35352e39302e3137320000.lbl8.mailshell.net.
+dns.msftncsi.com.
+www.twistedzones.com.
+169.200.138.190.in-addr.arpa.
+twitter.com.
+accounts.google.com.
+euro.mediotiempo.com.
+piensa-linux.programas-gratis.net.
+newsltd.com.au.
+email.80stees.com.
+37.105.202.81.in-addr.arpa.
+relay1.karelia.ru.
+static.addtoany.com.
+p0b.ru.
+home.live.com.
+www.map.utah.edu.
+webtrends1.taitra.org.tw.
+www.biblia12.com.
+s2.youtube.com.
+i1101.photobucket.com.
+tracker.dunnsearch.org.
+t2.gstatic.com.
+www.softonic.com.
+23.33.170.201.in-addr.arpa.
+googleads.g.doubleclick.net.
+prod2.rest-notify.msg.yahoo.com.
+voipc.sip.yahoo.com.
+ads1.msn.com.
+wzv6csg96.w17q2k2n.
+b.scorecardresearch.com.
+i1.ytimg.com.
+193.235.29.186.in-addr.arpa.
+funcampco.ca.
+www.salzburg-night.at.
+s.ytimg.com.
+clinicalconnexion.com.
+webcache.googleusercontent.com.
+cmc-loan.com.
+horoscopos.prodigy.msn.com.
+photos-f.ak.fbcdn.net.
+hotmail.com.
+s.ytimg.com.
+ratoactorework.ph.
+29.16.121.84.in-addr.arpa.
+201.171.57.186.in-addr.arpa.
+anunciosyavisos.com.pe.
+safebrowsing.clients.google.com.
+epacksolutions.com.
+sp.cwfservice.net.
+nem.com.s8a2.psmtp.com.
+217.90.223.189.in-addr.arpa.
+www.pspglobal.com.
+file4sharing.com.
+img.informer.com.
+103.54.96.200.in-addr.arpa.
+callejondeldeseo.blogspot.com.
+tee:f:op3.67nh.
+m4.licdn.com.
+215.186.127.201.in-addr.arpa.
+line-ra.ru.
+a.ittad.com.
+travelmarket.com.
+ksn1-12-part2.kaspersky-labs.com.
+relay.sobin.arh.ru.
+m.ak.fbcdn.net.
+212.1.168.192.in-addr.arpa.
+130.19.168.192.in-addr.arpa.
+127.92.137.187.in-addr.arpa.
+get.webwangwang.taobao.com.
+geo.tp-cdn.com.
+download348.avast.com.
+lt.navegg.com.
+a.root-servers.net.
+widget.ovo.com.
+www.google.com.
+83.105.188.71.in-addr.arpa.
+_582_97_7.
+ivrichpe.it.
+70.55.165.90.in-addr.arpa.
+www.stealth.nl.
+coruna-sec01.usersad.everis.int.
+zz.amur.su.
+www.twitter.com.
+rsc.co.uk.
+57.248.237.67.in-addr.arpa.
+roninpro.blogspot.com.
+apps.facebook.com.
+bs.serving-sys.com.
+www.acclimited.com.
+yakamar.com.
+rad.msn.com.
+www.telebasura.net.
+horoscopos.prodigy.msn.com.
+196.60.33.178.in-addr.arpa.
+i2.ytimg.com.
+mykadesigns.com.
+mediums.es.
+g.live.com.
+111.128.100.190.in-addr.arpa.
+eplresidential.com.
+a2.twimg.com.
+7-courier.push.apple.com.
+a.root-servers.net.
+www.cebupacificair.com.
+smtp.ru.
+www.wired.com.
+a.root-servers.net.
+a.root-servers.net.
+geometriagrafica.wordpress.com.
+relay.data.edge.messenger.live.com.
+farm6.staticflickr.com.
+ssl.gstatic.com.
+latimesblogs.latimes.com.
+casa.astoriail.net.
+get.adobe.com.
+akam.bing.com.
+archerac.com.s10a1.psmtp.com.
+186.129.171.201.in-addr.arpa.
+www.magdalenajalisco.gob.mx.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+client.akamai.com.
+168.227.161.189.in-addr.arpa.
+sfa.d300.kane.k12.il.us.
+jjfnj1poh.37jg.
+www.gilberdesigns.com.
+76.247.198.190.in-addr.arpa.
+226.20.199.190.in-addr.arpa.
+www.umontreal.ca.
+photos-g.ak.fbcdn.net.
+topvino.ru.
+zh-cn.facebook.com.
+adserver.adtech.de.
+londonamericantx.com.inbound15.mxlogicmx.net.
+mail.proinversion.gob.pe.
+93.45.9.201.in-addr.arpa.
+smtp.hallco.org.
+rcp.na.blackberry.com.
+download115.avast.com.
+alarabiya.lsops.net.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+safebrowsing-cache.google.com.
+api.mixpanel.com.
+153.230.79.184.in-addr.arpa.
+mailin-02.mx.aol.com.
+img4.imageshack.us.
+icons.wxug.com.
+teredo.ipv6.microsoft.com.
+teredo.ipv6.microsoft.com.
+www.stop-ciberbullying.info.
+98.240.89.200.in-addr.arpa.
+suxxessology.com.
+www.google.com.
+www.esprit.co.uk.
+whythetech.com.
+i4.ytimg.com.
+pop3.hot.glbdns.microsoft.com.
+shortstackapp.com.
+www.facebook.com.
+conn.skype.com.
+232.10.0.192.in-addr.arpa.
+203.233.172.201.in-addr.arpa.
+85.58.230.189.in-addr.arpa.
+ist1-2.filesor.com.
+eupen.us.
+dangg-amy.polyvore.com.
+236.60.103.201.in-addr.arpa.
+173.138.73.189.in-addr.arpa.
+www.juegosonline.com.py.
+mm3.no-ip.info.
+a1637.phobos.apple.com.
+accountservices.msn.com.
+www.universalairsuspension.com.
+lfgms.logica.com.
+a-0.19-a30fd081.c0b0580.1518.19d4.3ea1.410.0.mkhwv99ghppe6l4bjkfvsjc8pt.avqs.mcafee.com.
+groups.google.com.mx.
+twitter.com.
+168.170.48.190.in-addr.arpa.
+33.116.40.114.in-addr.arpa.
+74.222.160.118.in-addr.arpa.
+102.78.81.189.in-addr.arpa.
+gq7zzoav1.s42h4y6b.
+cityvillefb2.static.zgncdn.com.
+206.34.237.186.in-addr.arpa.
+20.228.125.64.in-addr.arpa.
+mail.tapco.ae.
+206.27.35.187.in-addr.arpa.
+230.89.19.186.in-addr.arpa.
+19.191.189.89.in-addr.arpa.
+cines.com.py.
+a5.sphotos.ak.fbcdn.net.
+www.acuale.com.
+61.36.153.187.in-addr.arpa.
+static.ak.fbcdn.net.
+dl21.ccb2.ru.
+external.ak.fbcdn.net.
+time.windows.com.
+i1101.photobucket.com.
+uac.advertising.com.
+13.136.83.186.in-addr.arpa.
+_577_55_7.
+ls.nexon.net.
+61.73.6.186.in-addr.arpa.
+fxfeeds.mozilla.com.
+a.root-servers.net.
+techreport.com.
+a.root-servers.net.
+www.maxmedals.com.
+addisonpools.com.
+ts4.travian.pk.
+kiva.net.
+buryclean.co.uk.
+coopatlantic.ca.
+creative.ak.fbcdn.net.
+t0.gstatic.com.
+mail.desertcard.com.
+128.168.253.201.in-addr.arpa.
+posterspoint.com.
+bsitecnologia.com.br.
+148.182.158.69.in-addr.arpa.
+mediacorppublishing.com.
+gogethealthynow.com.
+11.36.81.88.in-addr.arpa.
+wac.5f48.edgecastcdn.net.
+a.root-servers.net.
+a.root-servers.net.
+wljtzplr.net.
+eldy.softonic.com.
+www.biografias.pe.
+www.myspace.com.
+psprs.com.1.0001.arsmtp.com.
+mail.inlandcardiology.com.
+safebrowsing-cache.google.com.
+pbsc.co.uk.
+mail2.lanusa.com.
+img469.imageshack.us.
+clock.fmt.he.net.
+85.130.184.81.in-addr.arpa.
+login.toolbar.conduit-services.com.
+dv-region.ru.
+www.facebook.com.
+mgcr.wordpress.com.
+225.144.171.201.in-addr.arpa.
+static.ak.fbcdn.net.
+egyptiancastle.com.
+wwwimages.adobe.com.
+phone.com.
+71.12.179.189.in-addr.arpa.
+a.tribalfusion.com.
+dalk.ru.
+u.ywu.
+menupages.com.s8b1.psmtp.com.
+artisticas-normaldetorreon.blogspot.com.
+secure.wlxrs.com.
+lpcdn04.nflximg.com.
+wollive.windowsmedia.com.akadns.net.
+photos-d.ak.fbcdn.net.
+i.imwx.com.
+ngfts.lge.com.
+www.facebook.com.
+teamlatus.com.
+mail.orchardchurch.com.
+laptopstands.tv.
+static.ak.fbcdn.net.
+a.root-servers.net.
+24.173.122.84.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+mariamora.blogdiario.com.
+www.osstem.com.
+dl.gameplaylabs.com.s3.amazonaws.com.
+clientui.babylon.com.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.facebook.com.
+mail.ncs-law.com.
+imap.gmail.com.
+50.149.220.66.in-addr.arpa.
+google.com.
+ea:4uaxx8.44jg.
+mail.capcomp.com.
+www.groveatlantic.com.
+ministerioluzalasnaciones.com.
+www.louisvuittonpurses-bags.net.
+safebrowsing-cache.google.com.
+foros.3dgames.com.ar.
+49.93.47.189.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+word-search-maker.com.
+google.com.
+studiohilldesign.com.
+133.2.23.95.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+js2.wlxrs.com.
+104.159.100.190.in-addr.arpa.
+www.mooncandy.org.
+60.240.105.186.in-addr.arpa.
+37.30.170.189.in-addr.arpa.
+248.23.171.187.in-addr.arpa.
+support.google.com.
+247.35.237.186.in-addr.arpa.
+host-delay.logmein-gateway.com.
+i.ytimg.com.
+static0.kizi.com.
+specmetall.ru.
+static.gallendor.com.
+neron.ac-creteil.fr.
+apps.facebook.com.
+photos-c.ak.fbcdn.net.
+137.197.152.193.in-addr.arpa.
+www.freecaliforniawallpaper.com.
+143.21.163.190.in-addr.arpa.
+hotmail.com.
+a6.sphotos.ak.fbcdn.net.
+www.wikimediafoundation.org.
+www.rtl2.fr.
+a.root-servers.net.
+www.trackon.org.
+localad.walmart.com.
+searchclient.live.net.
+echo.edge.messenger.live.com.
+2.m0n0wall.pool.ntp.org.
+stardaily.ru.
+152.130.29.186.in-addr.arpa.
+5.239.196.90.in-addr.arpa.
+www.facebook.com.
+it-it.facebook.com.
+time.chttl.com.tw.
+alyeparusa.msk.ru.
+smtp.126.com.
+sgag.org.
+shasta-rrs.symantec.com.
+mail.turascandinavia.com.
+rt.rtoaster.jp.
+www.gagaplay.com.
+www.google.com.
+storage.conduit.com.
+25.201.52.186.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+support.google.com.
+ready-access.com.inbound25.mxlogic.net.
+richardhellergallery.com.
+photos-g.ak.fbcdn.net.
+ds.addthis.com.
+www.barraclou.com.
+bbcore.cloudapp.net.
+www.destroyplanethuman.com.
+youtu.be.
+static.ak.fbcdn.net.
+platform.twitter.com.
+www.apple.com.
+www.alltagz.de.
+56.42.171.201.in-addr.arpa.
+www.google.com.
+vpx8ezg4f.t20y4t4x.
+heyo.cc.
+www.esabmalaysia.com.
+umail.iu.edu.
+mycitybynight.co.za.
+rslonline.net.
+safebrowsing-cache.google.com.
+ksn2-12.kaspersky-labs.com.
+crissisideenschmiede.blogspot.com.
+mrc2.k12.mo.us.
+o.nimbuzz.com.
+elitebproductions.com.
+1.gvt0.com.
+webcache.googleusercontent.com.
+.
+www.facebook.com.
+www.shareasale.com.
+photos-a.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+www.jaimieveale.com.
+unhcr.ch.
+t.co.
+p05-contacts.icloud.com.akadns.net.
+msg2.caddock.com.
+mail.sikon.com.
+146.69.81.186.in-addr.arpa.
+amorconagujaylana.blogspot.com.
+h-oneindia.com.
+mjzjnlshsqzbqbg.biz.
+jiu66.cn.
+dc384.4shared.com.
+e.taxactonline.com.
+googleads.g.doubleclick.net.
+ad.yieldmanager.com.
+87.172.0.88.in-addr.arpa.
+accounts.google.com.
+mail.postjung.com.
+www.ivorde.ro.
+telvent.com.
+hotmail.com.
+s1-word-view.vo.msecnd.net.
+comluv.s3.amazonaws.com.
+www.ideastelcel.com.
+dns.msftncsi.com.
+appenda.com.
+adammesh.com.
+51.203.228.190.in-addr.arpa.
+data.mobclix.com.
+www.weather.com.
+clientes.hiltoncolon.com.
+a.root-servers.net.
+102.19.174.190.in-addr.arpa.
+148.196.212.186.in-addr.arpa.
+widgets.amung.us.
+32.60.61.85.in-addr.arpa.
+59.222.29.89.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+zao.spb.ru.
+228.80.72.190.in-addr.arpa.
+57.231.195.190.in-addr.arpa.
+241.42.166.77.in-addr.arpa.
+cy.sosiphone.com.
+pixer.meaningtool.com.
+crescentmoongames.com.
+googleblog.blogspot.com.
+pinoysila.blogspot.com.
+184.15.228.189.in-addr.arpa.
+www.babe-party.com.
+www.lawebdelprogramador.com.
+i.ytimg.com.
+internalcheck.apple.com.
+159.187.28.181.in-addr.arpa.
+dns.msftncsi.com.
+dns.msftncsi.com.
+201.94.60.177.in-addr.arpa.
+154.11.176.190.in-addr.arpa.
+api.facebook.com.
+galadrielcrea.blogspot.com.
+www.urbanartcore.eu.
+photos-c.ak.fbcdn.net.
+pixel.facebook.com.
+id25915.al16.luxup.ru.
+126.27.54.177.in-addr.arpa.
+www.analisisdemedios.com.
+d2100674.xoom.it.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+teredo.ipv6.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+e3191.c.akamaiedge.net.
+westplastgroup.ru.lan.
+checkip.dyndns.org.
+www.update.microsoft.com.
+c-0.19-210f8801.8020081.1518.19d4.3ea1.210.0.edipit6qmwhmvfd93tphlqk856.avqs.mcafee.com.
+csi.gstatic.com.
+a4.sphotos.ak.fbcdn.net.
+167.163.39.187.in-addr.arpa.
+www.google.com.me.
+sothorn.net.
+26.169.109.200.in-addr.arpa.
+rtb.pclick.yahoo.com.
+chevaliermalay.com.
+indid.ru.
+205.167.126.200.in-addr.arpa.
+88.33.155.189.in-addr.arpa.
+nyti.ms.
+photos-a.ak.fbcdn.net.
+photos-f.ak.fbcdn.net.
+www.gnomonwatches.com.
+imissyouif.blogspot.com.
+unblocker.me.
+kalamsetat.blogspot.com.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+api.facebook.com.
+photos-c.ak.fbcdn.net.
+mcmcorp.com.
+config.broadvoice.com.
+www.realtalkreggaeton.net.
+dmpas02.scig.gov.hk.
+www.gravatar.com.
+smx.rrt.net.redcondor.net.
+www.youtube.com.
+mobile.webroot.com.
+v8.cache5.c.youtube.com.
+admin.na5.acrobat.com.
+profile.ak.fbcdn.net.
+i3.ytimg.com.
+32.102.11.190.in-addr.arpa.
+www.ontronics.com.
+13.29.78.41.in-addr.arpa.
+binary-zone.com.
+125.240.72.189.in-addr.arpa.
+www.dmaranatha.com.
+widgets.amung.us.
+thequeensgalley.org.
+www.milfmature.net.
+macrae4.wanadoo.co.uk.
+.
+glassmenagerie.com.
+hibble.com.au.
+lh3.googleusercontent.com.
+a.root-servers.net.
+24.229.171.69.in-addr.arpa.
+g.ceipmsn.com.
+www.cuevana.tv.
+dns.msftncsi.com.
+a3.sphotos.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+24.159.89.186.in-addr.arpa.
+a.root-servers.net.
+cricinfo.co.
+bangbroscorp.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+inbound.stuartsofeldorado.com.netsolmail.net.
+www.futurocine.com.
+r.mzstatic.com.
+report.cedexis.com.
+akcontent.ebuddy.com.
+195.1.168.192.in-addr.arpa.
+i3.ytimg.com.
+www.facebook.com.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+alerts.conduit-services.com.
+62.72.221.190.in-addr.arpa.
+94.36.174.190.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+www.petnos.com.
+mx0.calcet.com.
+a2.sphotos.ak.fbcdn.net.
+cacheserve.williamhill.com.
+a-0.19-23090081.a020083.1518.19b2.410a.400.9d.u1s471dkqp57euv5pprpsp3jtb.avqs.mcafee.com.
+153.6.214.189.in-addr.arpa.
+l.yimg.com.
+pagead2.googlesyndication.com.
+162.235.94.82.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+translate.google.com.mx.
+40.153.11.94.in-addr.arpa.
+cdn3.api.openfeint.com.
+biometeurope.com.
+d7.zedo.com.
+api.facebook.com.
+.
+63.185.141.189.in-addr.arpa.
+bankri.com.s6a1.psmtp.com.
+metrics.target.com.
+177.220.10.187.in-addr.arpa.
+228.137.37.114.in-addr.arpa.
+forominecraft.foroactivo.com.
+s7.addthis.com.
+e7rk3dsv3.23ys.
+unifi.
+a.root-servers.net.
+pixel.quantserve.com.
+creative.ak.fbcdn.net.
+lunix.wscb.ru.
+198.102.131.189.in-addr.arpa.
+twitter.com.
+204.234.112.186.in-addr.arpa.
+247.176.178.190.in-addr.arpa.
+7.94.200.195.in-addr.arpa.
+226.171.204.130.in-addr.arpa.
+a.root-servers.net.
+gibbons.com.
+cmithum.com.
+34.111.149.187.in-addr.arpa.
+fa.wikipedia.org.
+106.21.251.201.in-addr.arpa.
+www.facebook.com.
+node.applifier.com.
+98.80.229.77.in-addr.arpa.
+myworkinet.ru.
+support.google.com.
+www.adobe.com.
+www.belkin.com.
+94.119.174.190.in-addr.arpa.
+resources.infolinks.com.
+creative.ak.fbcdn.net.
+homoclub.foroactivo.com.
+creative.ak.fbcdn.net.
+fbcdn-sphotos-a.akamaihd.net.
+212.190.51.190.in-addr.arpa.
+luchifeliz.lacoctelera.net.
+secure.wlxrs.com.
+235.71.224.189.in-addr.arpa.
+www.antiplagas.com.
+136.190.19.186.in-addr.arpa.
+www.genbeta.com.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+24.239.188.189.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+a1408.w43.akamai.net.
+www.facebook.com.
+img1.blogblog.com.
+i2.ytimg.com.
+a3.sphotos.ak.fbcdn.net.
+tiscali.it.
+plusone.google.com.
+safebrowsing-cache.google.com.
+a8.sphotos.ak.fbcdn.net.
+191.237.37.190.in-addr.arpa.
+gallospedragliofarm.com.
+27.147.220.66.in-addr.arpa.
+www.ginasommelier.com.mx.
+200.132.65.85.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+ad-g.doubleclick.net.
+power.alstom.com.
+cs792.vk.com.
+clients2.google.com.
+155.205.59.186.in-addr.arpa.
+mail.google.com.
+ocsp.thawte.com.
+fbcdn-profile-a.akamaihd.net.
+empresasinternacionales.com.
+www.yahoo.com.
+www.bestbuy.com.mx.
+214.189.144.186.in-addr.arpa.
+mta1.am0.yahoodns.net.
+127.87.91.186.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+www.twgirl.net.
+gotthard-karstens.de.
+9gag.com.
+support.google.com.
+41.175.106.200.in-addr.arpa.
+personnel.nsk.su.
+bf74c17fce5b72a5f98844a4f8446b2c.org.
+d2099252.xoom.it.
+solarwinds-tftp-server.softonic.com.
+uk.pwc.com.
+a2.sphotos.ak.fbcdn.net.
+231.137.82.189.in-addr.arpa.
+248.90.159.189.in-addr.arpa.
+csi.gstatic.com.
+crossdillon.com.
+unifi.lan.
+mt4-is02.fxsecure.com.
+pcwin.com.
+a2.sphotos.ak.fbcdn.net.
+reportlink.pbwdev.com.
+www.fineartsla.com.
+206.48.31.82.in-addr.arpa.
+www.anpad.org.br.
+youtube-ui.l.google.com.
+a1294.w20.akamai.net.
+a.root-servers.net.
+needless.jp.
+www.google.com.
+styletraxx.com.
+profile.ameba.jp.
+agzgcoo.info.
+www.facebook.com.
+teredo.ipv6.microsoft.com.
+a5.sphotos.ak.fbcdn.net.
+s.staticyonkis.com.
+twitter.com.
+www.stage6fullero.net.
+p04-caldav.icloud.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+google.com.
+nohaypan.blogspot.com.
+pixel.facebook.com.
+kosu.ru.
+br.weather.com.
+pix2pix.org.
+elblogdeledzeppelin.blogspot.com.
+www.gstatic.com.
+couponbuddy.s3.amazonaws.com.
+in.jagran.yahoo.com.
+19.136.194.187.in-addr.arpa.
+www.google.com.
+photos-a.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+shared.live.com.
+ryouae.com.
+linkhelp.clients.google.com.
+mosmas.ru.
+70.67.144.180.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+i30.tinypic.com.
+autos.aol.com.
+rssgov.windows.microsoft.com.
+155.165.201.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+sparkpeo.vo.llnwd.net.
+suoernet.com.
+fwaproducts.com.
+th239.photobucket.com.
+csi.gstatic.com.
+6.15.224.88.in-addr.arpa.
+pb.blabbers.com.
+hotmail.com.
+seal-alaskaoregonwesternwashington.bbb.org.
+badoo.com.
+a1.sphotos.ak.fbcdn.net.
+237.5.205.187.in-addr.arpa.
+17.121.207.82.in-addr.arpa.
+a.root-servers.net.
+www.ivb.cz.
+_394_85_9.
+rosefarm.com.
+smtp.live.com.
+www.ipkat.com.
+playig.com.
+download.windowsupdate.com.
+www.google.com.
+sp.cwfservice.net.
+touch.facebook.com.
+144.41.253.111.in-addr.arpa.
+domino.juegate.com.
+as-gest.com.
+6wlpnxaas.j92f5h4u.
+view.atdmt.com.
+137.203.132.189.in-addr.arpa.
+ad.wowtv.co.kr.
+marknet.ee.
+teredo.ipv6.microsoft.com.
+subseven90.no-ip.org.
+ns1.hsbc.com.sg.
+86.14.38.186.in-addr.arpa.
+link.nokia.com.
+www.facebook.com.
+tas.orangeads.fr.
+static.woopra.com.
+chinoataku.wordpress.com.
+es-la.facebook.com.
+iwebunlimited.com.
+mail.chronicleseries.com.
+www.foxrio2.com.
+secure.logmein.com.
+www.terra.com.
+67.36.138.187.in-addr.arpa.
+a.root-servers.net.
+www.portalminero.com.
+58.93.153.189.in-addr.arpa.
+103.216.177.190.in-addr.arpa.
+www.youtube.com.
+g.ceipmsn.com.
+35.227.239.189.in-addr.arpa.
+www.gameschecker.de.
+lh5.ggpht.com.
+blog.typograffit.com.
+ns1.scs-net.org.
+csmonolit.ru.
+233.108.156.114.in-addr.arpa.
+www.sciencebooksonline.info.
+214.245.43.190.in-addr.arpa.
+196.76.20.187.in-addr.arpa.
+webcache.googleusercontent.com.
+luckyemperor.tumblr.com.
+node.applifier.com.
+ihktech.net.
+localhost.
+b.scorecardresearch.com.
+a3.sphotos.ak.fbcdn.net.
+199.26.0.10.in-addr.arpa.
+.
+nextag.com.
+a4.sphotos.ak.fbcdn.net.
+mail.resheto.ru.
+pagead2.googlesyndication.com.
+riehle.org.
+tor-office.iqpartners.com.
+markoniya.ucoz.ru.
+delivery.trafficbroker.com.
+fr-fr.facebook.com.
+parana.tuentrerios.com.
+time.bora.net.
+seaborne-intl.com.
+220.176.88.186.in-addr.arpa.
+www.pension4armynews.co.uk.
+server.sportsawardsonline.com.
+43.106.148.190.in-addr.arpa.
+media.tumblr.com.
+teredo.ipv6.microsoft.com.
+221.62.232.189.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+apps.facebook.com.
+t.co.
+uluniwiming.com.
+nastymomvideo.com.
+www.muzik-torrent.net.
+18.4.183.65.in-addr.arpa.
+dns.msftncsi.com.
+s-static.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+auto.mail.ru.
+smk-iso9001.ru.
+5.237.223.201.in-addr.arpa.
+www.agame.me.
+175.74.31.189.in-addr.arpa.
+www.2dplan.com.
+dnl-01.geo.kaspersky.com.
+ciber.
+www.lotteryinsider.com.
+sgdc1max1.chevron.com.
+safebrowsing-cache.google.com.
+mx.xmission.com.
+41.146.230.99.in-addr.arpa.
+ipmsa.ru.
+skydrive.live.com.
+vietstar.info.
+tnbaptist.org.
+www.msftncsi.com.
+www.wtp101.com.
+dnl-01.geo.kaspersky.com.
+a7.sphotos.ak.fbcdn.net.
+nekrst.nek.ru.s200a1.psmtp.com.
+48.ns1631263.net.
+localhost.
+www.hotmail.com.
+www.cgsecurity.org.
+www.path.cam.ac.uk.
+ws.tapjoyads.com.
+platform.twitter.com.
+romsan.ru.
+76.31.2.187.in-addr.arpa.
+racismdaily.com.
+www.google.com.mx.
+167.78.247.88.in-addr.arpa.
+www.voayeurs.com.
+teredo.ipv6.microsoft.com.
+a5.sphotos.ak.fbcdn.net.
+netflix-login.com.
+www.newseasims.com.
+a.ads2.msads.net.
+img100.xvideos.com.
+mail.ppcserver.net.
+a1725.l.akamai.net.
+241.40.20.186.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+tj9w5jhz4.a72f1k2h.
+trendeotonyo.files.wordpress.com.
+68.90.53.187.in-addr.arpa.
+123.222.155.189.in-addr.arpa.
+qbtmwj.info.
+www.cahams.com.
+sofort-mail.de.
+i1.ytimg.com.
+84.21.221.189.in-addr.arpa.
+www.update-software.com.
+ksn2-12.kaspersky-labs.com.
+www.chemm.cn.
+www.goodwinmedia.com.
+1800sunstar.com.
+advanced-renamer.en.softonic.com.
+photos-h.ak.fbcdn.net.
+ad-emea.doubleclick.net.
+homethelovely.com.
+totao56.files.wordpress.com.
+stephenstimson.com.1.0001.arsmtp.com.
+www.homesearch.ph.
+safebrowsing.clients.google.com.
+mail.sierraconstruction.com.
+www.juegosdecrear.net.
+t3.gstatic.com.
+www.stnicholascenter.org.
+evsecure-ocsp.verisign.com.
+itcomp.pl.
+a.root-servers.net.
+radar.cedexis.com.
+en.bn.fb.igg.com.
+10.38.49.151.in-addr.arpa.
+pixel.facebook.com.
+bgnet.com.
+181.236.232.190.in-addr.arpa.
+mail.paquettewhite.com.
+www.mypursehandbag.com.
+melitusmen.podbean.com.
+249.35.193.187.in-addr.arpa.
+a.root-servers.net.
+crl.thawte.com.
+101.43.23.186.in-addr.arpa.
+a.root-servers.net.
+www.toshiba.com.mx.
+db2.stb01.s-msn.com.
+t.co.
+211.65.27.69.in-addr.arpa.
+s-static.ak.facebook.com.
+230.98.135.187.in-addr.arpa.
+www.blackberry.com.
+images.proxm.com.
+plus.google.com.
+www.pajamasmedia.com.
+time.chttl.com.tw.
+190.178.85.186.in-addr.arpa.
+mail.google.com.
+wearnesmotors.com.
+tap2-cdn.rubiconproject.com.
+170.252.6.190.in-addr.arpa.
+www.braillenet.org.
+photos-h.ak.fbcdn.net.
+trianguloequidlatere.blogspot.com.
+www.susanholmes.net.
+www.offshore-fox.com.
+apix.iminent.com.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+a771.da1.akamai.net.
+0-jg-w.channel.facebook.com.
+106.178.161.207.in-addr.arpa.
+couponbuddy.s3.amazonaws.com.
+crl.microsoft.com.
+groups.yahoo.com.
+a.rad.msn.com.
+apis.google.com.
+0-278.channel.facebook.com.
+cs4109.vkontakte.ru.
+cdn.lfstmedia.com.
+_293_69_4.
+docs.google.com.
+dns.msftncsi.com.
+photos-f.ak.fbcdn.net.
+163.141.109.190.in-addr.arpa.
+www.defensa.cl.
+ytimg.l.google.com.
+www.gmail.com.
+www.culioneros.com.
+sutrust.com.
+mcermalwbbes.nu.
+fbcdn-photos-a.akamaihd.net.
+236.93.121.190.in-addr.arpa.
+www.buenscoring.com.
+_883_08_2.
+ulead-gif-animator.softonic.pl.
+www.blogger.com.
+s-static.ak.facebook.com.
+i1.ytimg.com.
+a3.sphotos.ak.fbcdn.net.
+48.30.227.201.in-addr.arpa.
+captcha.naver.com.
+apps.facebook.com.
+200.253.171.200.in-addr.arpa.
+api.twitter.com.
+img.funenclave.com.
+blogs.visoftinc.com.
+www.google-analytics.com.
+photos-h.ak.fbcdn.net.
+cdn.at.atwola.com.
+a.root-servers.net.
+pool.ntp.org.
+ping1.unicast.com.
+client-software.real.com.
+a.root-servers.net.
+78.165.50.190.in-addr.arpa.
+dns.msftncsi.com.
+cp2.websolspk.com.
+www.linkmoz.org.
+i1.ytimg.com.
+www.bestellipticalreviews.org.
+apps.facebook.com.
+download943.avast.com.
+_712_11_0.
+100.248.211.201.in-addr.arpa.
+www.wandermap.net.
+weather.wapp.wii.com.
+www.funpic.in.
+23.74.61.186.in-addr.arpa.
+transparencia-economica.mef.gob.pe.
+.
+creative.ak.fbcdn.net.
+239.177.2.200.in-addr.arpa.
+stroytrek.ru.
+static.ak.fbcdn.net.
+www.lika-online.com.
+192.186.22.186.in-addr.arpa.
+238.96.133.115.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+bjklaw.us.2.arsmtp.com.
+www.facebook.com.
+www.ledmobile.net.
+static.ak.fbcdn.net.
+connect.facebook.net.
+api.twitter.com.
+stun.voip.blackberry.com.
+descargalosmejoresprogramasgratis.blogspot.com.
+googleads.g.doubleclick.net.
+www.amazon.ca.
+mail.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.labsdirect.com.
+62.219.124.202.in-addr.arpa.
+23.245.176.186.in-addr.arpa.
+sm9.sitemeter.com.
+www.twitter.com.
+www.google-analytics.com.
+www.microjuris.com.
+rldownload.com.
+ksn3-11.part1.kaspersky-labs.com.
+clients1.google.com.
+239.163.251.201.in-addr.arpa.
+safebrowsing-cache.google.com.
+www.justgayhardcore.com.
+youtu.be.
+www.comprarenmollet.com.
+a.root-servers.net.
+213.89.111.189.in-addr.arpa.
+www.ldsdudes.com.
+220.82.252.201.in-addr.arpa.
+s2j369:pg.m77t9e0x.
+ky3.com.s5a1.psmtp.com.
+m.youtube.com.
+s4.histats.com.
+152.192.54.190.in-addr.arpa.
+ns.nav.kiev.ua.
+dnl-06.geo.kaspersky.com.
+static.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+251.189.114.189.in-addr.arpa.
+a.root-servers.net.
+mailc.txdps.state.tx.us.
+sp.cwfservice.net.
+180.115.145.78.in-addr.arpa.
+www.thesound.co.nz.
+www.grupoimplantes.com.ar.
+crl.microsoft.com.
+s0.2mdn.net.
+blog.oafe.net.
+istatistikler.ligtv.com.tr.
+sulfatreat.com.
+ad.yieldmanager.com.
+plus.google.com.
+gtaonline.com.ar.
+profile.ak.fbcdn.net.
+tdsystems.org.
+www.ofertas-outlets.com.
+mx.msn.recepedia.com.
+fxfeeds.mozilla.com.
+www.toolguys.com.
+1.201.159.189.in-addr.arpa.
+sp.cwfservice.net.
+203.160.179.190.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s.ytimg.com.
+b-0.19-2309c008.c0c1081.1518.19ce.3ea1.410.0.5d7ar9ejb8b4z724c3w9ldp4p5.avqs.mcafee.com.
+www.dondeganardinero.com.
+tc22.easythumbhost.com.
+20.29.184.186.in-addr.arpa.
+antarcticsun.usap.gov.
+www.dailymail.pinkribbonbingo.com.
+a1.sphotos.ak.fbcdn.net.
+_853_37_3.
+go.microsoft.com.
+135.90.188.201.in-addr.arpa.
+www.minikmodaci.com.
+a6.sphotos.ak.fbcdn.net.
+ls57tiger.freepgs.com.
+phfilms.com.
+upload.wikimedia.org.
+twitter.com.
+pixel.facebook.com.
+chqronq5f.n56q7s1o.
+bnreview.lithium.com.
+mx.youtube.com.
+pivotnetworks.com.inbound15.mxlogicmx.net.
+31.65.252.117.in-addr.arpa.
+tarkett-ee.com.s200a2.psmtp.com.
+inbound.midtownhotel.com.netsolmail.net.
+rediffamil.com.
+i.ytimg.com.
+www.photorecept.ru.
+mx.youtube.com.
+peabodygallery.com.
+a.root-servers.net.
+a.root-servers.net.
+www.cheforopeza.com.mx.
+195.39.102.189.in-addr.arpa.
+www.photo-warping.com.
+play.jo.
+xagminecraft.blogspot.com.
+photos-a.ak.fbcdn.net.
+designerbagcatalog.com.
+61.99.112.112.in-addr.arpa.
+www.google-analytics.com.
+tatooshop.ru.
+d1ros97qkrwjf5.cloudfront.net.
+prodigy.msn.com.
+www.google-analytics.com.
+mail02.avmin.co.za.
+ns1.sitibroadband.in.
+244.136.6.74.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+ar.autos.yahoo.com.
+www.facebook.com.
+safebrowsing-cache.google.com.
+thraki-devil.blogspot.com.
+download624.avast.com.
+cetelbras.com.br.
+calgate01.a02.yahoodns.net.
+www.termofrigidus.com.
+parking.www.kilu.org.
+178.57.230.201.in-addr.arpa.
+www.bigfatass.org.
+44.150.14.88.in-addr.arpa.
+171.103.135.189.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.pipiota.blogspot.com.
+www.zfforum.es.
+pts.lockerz.com.
+mebelka.ru.
+www.botpa.co.kr.
+staleyplanning.com.
+push.apple.com.
+rpm.elmundoenlinea.com.mx.
+44.29.194.173.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+static.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+161.226.120.68.in-addr.arpa.
+css.wlxrs.com.
+a.root-servers.net.
+a.root-servers.net.
+a.root-servers.net.
+photos-e.ak.fbcdn.net.
+wakayama-med.ac.jp.
+db._dns-sd._udp.0.195.16.172.in-addr.arpa.
+198.114.4.171.in-addr.arpa.
+adserving.cpxinteractive.com.
+pcthings.org.uk.
+www.titsbig.net.
+view.atdmt.com.
+29.234.229.190.in-addr.arpa.
+114.45.87.186.in-addr.arpa.
+215.99.24.190.in-addr.arpa.
+s-external.ak.fbcdn.net.
+37.192.11.111.in-addr.arpa.
+dsn15.d.skype.net.
+challiance.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+149.250.16.190.in-addr.arpa.
+83.149.10.75.in-addr.arpa.
+calendar.live.com.
+google.com.
+a1108.da1.akamai.net.
+photos-b.ak.fbcdn.net.
+suggestqueries.google.com.
+elperro13.net.
+viajes-vuelos.agencias-de-viajes.com.
+es-la.facebook.com.
+photos-a.ak.fbcdn.net.
+ajax.googleapis.com.
+www.computadorasenlaeducacion.com.
+s0.2mdn.net.
+1.0.0.127.in-addr.arpa.
+sup.live.com.
+222.143.162.190.in-addr.arpa.
+es-la.facebook.com.
+apix.iminent.com.
+164.145.168.192.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+ipcast2.dynupdate.no-ip.com.
+myiafrica.com.
+www-fc-opensocial.googleusercontent.com.
+gfx2.hotmail.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+greystone.messagescreen.com.
+ad.yieldmanager.com.
+updates.sonic.com.
+profile.ak.fbcdn.net.
+twitter.com.
+www.xom.com.mx.
+a6.sphotos.ak.fbcdn.net.
+ajax.aspnetcdn.com.
+kidbleach.com.
+pop.theitmachine.com.
+player.vimeo.com.
+51.252.22.24.in-addr.arpa.
+www.gatitasconcam.com.
+ssl.gstatic.com.
+www.souleaterwallpaper.com.
+teredo.ipv6.microsoft.com.
+login.live.com.
+wpad.
+mail.brce.com.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+82.146.69.190.in-addr.arpa.
+174.169.245.190.in-addr.arpa.
+sac.gti.mcafee.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s.youtube.com.
+www.facebook.com.
+150.102.35.189.in-addr.arpa.
+nbmedia.com.
+776964676574.6265.6575.63726974656f.636f6d.80hb2fa014f.webcfs00.com.
+134.117.6.210.in-addr.arpa.
+rs931l3.rapidshare.com.
+lb._dns-sd._udp.lan.
+ns2.redbee.nl.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.stumbleupon.com.
+ssl.gstatic.com.
+pu.com.au.
+www.facebook.com.
+asia.battle.net.
+www.nhtbw.com.
+_ldap._tcp.
+xtra.co.nz.
+api.twitter.com.
+lh4.ggpht.com.
+220.103.174.190.in-addr.arpa.
+remote.dillonworks.com.
+www.twitter.com.
+76.245.24.88.in-addr.arpa.
+143.233.26.85.in-addr.arpa.
+geo.ltassrv.com.
+profile.ak.fbcdn.net.
+226.86.213.83.in-addr.arpa.
+32.6.22.95.in-addr.arpa.
+profile.ak.fbcdn.net.
+195.108.173.190.in-addr.arpa.
+www.facebook.com.
+rad.msn.com.
+profile.ak.fbcdn.net.
+210.9.0.10.in-addr.arpa.
+www.stopbadware.org.
+53.237.83.71.in-addr.arpa.
+147.61.81.186.in-addr.arpa.
+www.msftncsi.com.
+www.taringa.net.
+191.22.187.67.in-addr.arpa.
+marihuanacultivo.com.
+creative.ak.fbcdn.net.
+parenting.co.uk.
+item.taobao.com.
+www.freesexnavigator.com.
+t13.intelliad.de.
+www.youravon.com.
+mail.translabourage.ru.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.google.com.
+3j:onbsbh.87dl.
+236.127.171.189.in-addr.arpa.
+158.74.61.174.in-addr.arpa.
+19.191.55.72.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+thetastefulbasket.com.
+loading.retry.widdit.com.
+ulrtrxxhxonsyh.info.
+analyze.net.tf.
+27.42.56.190.in-addr.arpa.
+s.ytimg.com.
+multiplaz.ru.
+safebrowsing-cache.google.com.
+238.242.16.122.in-addr.arpa.
+www.altaro.com.
+www.calorieking.com.
+www.agenciaartistatv.com.
+www.google-analytics.com.
+groups.google.com.mx.
+www.homestayfinder.com.
+81.173.168.75.in-addr.arpa.
+www.facebook.com.
+107.1.168.192.in-addr.arpa.
+_ldap._tcp.
+234.31.232.189.in-addr.arpa.
+novar.com.
+www.dibujosdisney.org.
+creative.ak.fbcdn.net.
+7.129.234.119.in-addr.arpa.
+mx.katsinas.com.
+eltech.net.pl.
+v1.nonxt5.c.youtube.com.
+aig.com.co.
+55.31.142.187.in-addr.arpa.
+updatekeepalive.mcafee.com.
+242.132.123.84.in-addr.arpa.
+mail.foxriver.ru.
+billing.service.playfish.com.
+crl.microsoft.com.
+soporte.pandasecurity.com.
+entrysfo002a.skyfire.com.
+32.245.23.186.in-addr.arpa.
+m.facebook.com.
+162.135.84.41.in-addr.arpa.
+117.52.160.189.in-addr.arpa.
+214.12.146.187.in-addr.arpa.
+dsmllp.com.
+static.image-gmkt.com.
+static.ak.fbcdn.net.
+google.com.
+a.root-servers.net.
+it-it.facebook.com.
+s-static.ak.facebook.com.
+guru.avg.com.
+ad.lpxp.net.
+www.youtube.com.
+a.root-servers.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.linares.net.
+mailhost.tecrodpd.com.
+facebook.com.my.hostlogr.com.
+amitelco.com.
+15.93.131.187.in-addr.arpa.
+177.209.121.65.in-addr.arpa.
+a.root-servers.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx.alfacenter.it.
+pop3.live.com.
+buttons.reddit.com.
+www.game.ezfun.net.
+s.ytimg.com.
+developers.facebook.com.
+mk4099.spb.edu.
+actionplusrealty.com.
+mail.limbless-association.org.
+rss.cbc.ca.
+252.22.0.192.in-addr.arpa.
+creative.ak.fbcdn.net.
+msgr.updates.yahoo.com.
+www.chinaglia.com.br.
+s-static.ak.facebook.com.
+www.isabelaguera.com.
+pagead.l.doubleclick.net.
+www.10ka20.com.
+www.facebook.com.
+links.mkt1340.com.
+mail.rbi.com.
+www.todoar.com.ar.
+load.s3.amazonaws.com.
+thrice.net.
+sparks.city.nv.us.
+s1.ubalert.com.
+australiasevereweather.com.
+voipa.sip.yahoo.com.
+www.viendosexo.com.
+teredo.ipv6.microsoft.com.
+130.114.76.83.in-addr.arpa.
+www.6188.com.
+mail.google.com.
+ad-g.doubleclick.net.
+26.media.tumblr.com.
+eu.wikipedia.org.
+250.11.168.192.in-addr.arpa.
+cdduplicationdata.com.
+47.37.1.190.in-addr.arpa.
+www.nsoftware.com.
+156.155.195.90.in-addr.arpa.
+apps.facebook.com.
+tavi-dent.ru.
+a1.twimg.com.
+3.1.2.a.2.5.6.a.0.8.5.0.3.d.4.1.d.f.9.7.5.f.e.5.0.0.0.0.1.0.0.2.ip6.arpa.
+1africa.com.
+teredo.ipv6.microsoft.com.
+0-44.channel.facebook.com.
+profile.ak.fbcdn.net.
+51.99.223.87.in-addr.arpa.
+bt-srv01.bauschtech.com.
+creative.ak.fbcdn.net.
+mail.ourismanva.com.mx.swishmail.net.
+photos-f.ak.fbcdn.net.
+www.loyola.edu.mx.
+77.34.205.71.in-addr.arpa.
+7.90.119.177.in-addr.arpa.
+zeroz.biz.
+orkom1c.ru.
+courseroom2.capella.edu.
+sp.cwfservice.net.
+3.bp.blogspot.com.
+mx.sdelali.ru.
+server-28.reportgoogle.com.
+27.194.191.189.in-addr.arpa.
+_684_97_4.
+so-gi.spb.ru.
+rcl.ramsey.lib.mn.us.
+www.foscarini.com.
+ssl.gstatic.com.
+www.templaraz.com.
+movies.broadwayworld.com.
+a.root-servers.net.
+palsa.com.
+www.eurekasa.it.
+131.141.108.187.in-addr.arpa.
+dsn9.d.skype.net.
+mx2.sanet.ru.
+www.cookingforgirlz.com.
+26.255.57.69.in-addr.arpa.
+whisperedinspirations.com.
+img3.stripperparadise.com.
+www.divxmovieplayer.com.
+www.facebook.com.
+ad.yieldmanager.com.
+234.189.174.195.in-addr.arpa.
+cs1524.vkontakte.ru.
+69.177.171.187.in-addr.arpa.
+13.149.165.83.in-addr.arpa.
+bs.serving-sys.com.
+google.com.
+bbg.lt.
+piano.ocn.ne.jp.
+a.root-servers.net.
+r.turn.com.
+www.juegosjuegos.com.
+58.165.44.194.in-addr.arpa.
+videos.mundo.com.
+93.95.82.203.in-addr.arpa.
+m.wsj.net.
+mail02.gigalinkmail.com.
+zjam.com.
+beacon.shazam.com.
+www.facebook.com.
+205.20.243.88.in-addr.arpa.
+partner.googleadservices.com.
+adserver.adtech.de.
+tigerbeatdown.com.
+a1497.phobos.apple.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+fxfeeds.mozilla.com.
+6.15.122.84.in-addr.arpa.
+72ffkjpjn.07kc.
+juno.com.
+www.kaleykennedy.com.
+smtp.tmr-sa.co.za.
+a7.sphotos.ak.fbcdn.net.
+front.pyramid.kobojo.com.
+a.root-servers.net.
+techgage.com.
+az15112.vo.msecnd.net.
+anewmode.com.
+61.52.14.186.in-addr.arpa.
+www.vuelomania.com.
+sp.cwfservice.net.
+lakelanier.com.
+apps.facebook.com.
+ads.prisacom.com.
+v1kqf35es.27fg.
+apps.facebook.com.
+175.254.236.201.in-addr.arpa.
+c14152960.web.cddbp.net.
+slabberredux.blogspot.com.
+11.28.174.190.in-addr.arpa.
+xmpp003.hpeprint.com.
+dns.msftncsi.com.
+adsrv.deviantart.com.
+comptoncorp.com.
+lnhi.net.s7b2.psmtp.com.
+dns.msftncsi.com.
+www.cloudkillers.com.
+chi.rtkl.com.
+102.169.85.186.in-addr.arpa.
+localhost.
+static.ak.fbcdn.net.
+ar-ar.facebook.com.
+12.17.141.201.in-addr.arpa.
+developers.facebook.com.
+content.yieldmanager.edgesuite.net.
+www.youtube.com.
+www.segurosvip.com.
+amateur-pussy-finder.notlong.com.
+pagead2.googlesyndication.com.
+232.156.83.62.in-addr.arpa.
+mail.proitss.com.
+cure-net.com.
+f.funmoods.com.
+172.201.178.190.in-addr.arpa.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.tabletsandroid.com.ar.
+202.88.55.74.in-addr.arpa.
+forums.redcarpetrebellion.org.
+s-static.ak.fbcdn.net.
+board.airrivals.net.
+0-jx-w.channel.facebook.com.
+www.outlook-web-access.com.
+www.tibet-tour.com.
+9gag.com.
+creative.ak.fbcdn.net.
+www.yeze.us.
+a.analytics.yahoo.com.
+121.173.116.174.in-addr.arpa.
+external.ak.fbcdn.net.
+dnl-01.geo.kaspersky.com.
+a.root-servers.net.
+www.kenrockwell.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+su.wikipedia.org.
+fotolog.terra.com.co.
+mail.realdating.ru.
+ad.turn.com.
+85.61.24.190.in-addr.arpa.
+inglcarion.com.
+mindspring.com.
+a3.twimg.com.
+a7.sphotos.ak.fbcdn.net.
+storage.conduit.com.
+wd-edge.sharethis.com.
+www.tattooremoval.eu.
+time.vonage.net.
+dnl-01.geo.kaspersky.com.
+52.72.143.201.in-addr.arpa.
+cogame.timestorm.de.
+bostoncomedyfest.com.
+154.108.95.190.in-addr.arpa.
+v6.nonxt2.c.youtube.com.
+barcorgages.com.
+39.6.188.190.in-addr.arpa.
+hzs7.cnzz.com.
+206.164.141.69.in-addr.arpa.
+a.root-servers.net.
+www.seoghoer.dk.
+photos-f.ak.fbcdn.net.
+www.japanican.com.
+49.180.96.65.in-addr.arpa.
+7064612d6173.616d617a6f6e.636f6d.80h4815d64a.webcfs00.com.
+mail.nlicgulf.com.
+ikhr9bhww.y55i6n4r.
+www.google.com.
+a.root-servers.net.
+vfsuites.com.
+a7.sphotos.ak.fbcdn.net.
+203.3.23.113.in-addr.arpa.
+click.18clicks.com.
+richfaces.org.
+redsweetclubvip.com.multi.surbl.org.
+casiangelesymuchomas.blogspot.es.
+twitter.com.
+a1725.l.akamai.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+o-o.preferred.iad09s10.v14.lscache5.c.youtube.com.
+www.img.forogames.net.
+nflattorney.com.
+trsbattorneys.com.
+205.129.211.201.in-addr.arpa.
+6to4.ipv6.microsoft.com.
+127.77.144.79.in-addr.arpa.
+p0b.ru.
+dsn3.d.skype.net.
+sp.cwfservice.net.
+i49.tinypic.com.
+a.root-servers.net.
+www.bikegames247.com.
+136.177.111.89.in-addr.arpa.
+md:gm4wz9.c19f7a1y.
+carolina.cmac.com.
+43.134.187.67.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+ad.yieldmanager.com.
+es-es.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+apps.facebook.com.
+philadelphia.ebayclassifieds.com.
+baymsg1020124.gateway.messenger.live.com.
+www.gstatic.com.
+187.89.102.84.in-addr.arpa.
+apnstatic.ask.com.
+msg.jetapp.com.
+a.root-servers.net.
+torrentz.eu.
+app.crowdscience.com.
+www.google.com.
+pix04.revsci.net.
+login.yahoo.net.
+aol.com.
+lh5.googleusercontent.com.
+css.wlxrs.com.
+159.4.146.189.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+tralala.com.
+market.android.com.
+dns.msftncsi.com.
+pagead2.googlesyndication.com.
+www.google.gy.
+cisbec.net.
+a5.sphotos.ak.fbcdn.net.
+b-f-c.com.
+profile.ak.fbcdn.net.
+www.google-analytics.com.
+175.30.171.187.in-addr.arpa.
+0-68.channel.facebook.com.
+rad.msn.com.
+forums.extensis.com.
+safebrowsing-cache.google.com.
+ber.lesnoy.ru.
+319.ns1631263.info.
+safebrowsing-cache.google.com.
+pernod-ricard-canada.com.s7a2.psmtp.com.
+37.48.36.190.in-addr.arpa.
+liveupdate.symantecliveupdate.com.
+vcs2.msg.yahoo.com.
+www.addthis.com.
+ougsyrokrvoljtpz.net.
+www.desktopsmiley.com.
+sites.google.com.
+content.yieldmanager.edgesuite.net.
+saint-etienne.lachainemeteo.com.
+menofcolor.thumblogger.com.
+api.zynga.com.
+www.cbnicaragua.com.
+www.facebook.com.\255\255\255\255.
+lordbingo.co.uk.
+it-it.facebook.com.
+www.compassion-revolution.com.
+download.windowsupdate.com.
+images01.olx-st.com.
+mirabella.com.
+kaliman14.listen2myradio.com.
+www.fajarweb.com.
+142.145.87.187.in-addr.arpa.
+www.drmalpani.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+toolbar.live.com.
+2.149.120.187.in-addr.arpa.
+www.googleadservices.com.
+api.twitter.com.
+augustana.edu.s10b2.psmtp.com.
+translate.googleapis.com.
+varuc.com.
+www.tierradelfuego.gov.ar.
+embedhunter.com.
+alicexu59.en.made-in-china.com.
+ad.yieldmanager.com.
+search.babylon.com.
+203.233.100.74.in-addr.arpa.
+allo34.ru.
+sharptampa.com.
+crl.entrust.net.
+diq.wikipedia.org.
+www.nexteve.com.
+cdn.lfstmedia.com.
+www.google-analytics.com.
+www.coca-cola.ba.
+www.yourskin.nl.
+apix.iminent.com.
+ping3.dyngate.com.
+accounts.google.com.
+i4.ytimg.com.
+139.41.252.190.in-addr.arpa.
+synd.netseer.com.
+weather.wapp.wii.com.
+photos-a.ak.fbcdn.net.
+img520.imageshack.us.
+fxfeeds.mozilla.com.
+ut2.xhamster.com.
+clients.babylon.com.
+pubads.g.doubleclick.net.
+139.7.145.92.in-addr.arpa.
+api.twitter.com.
+mail.calparks.org.
+cdn.fastclick.net.
+resources1.search.conduit.com.
+safebrowsing-cache.google.com.
+scsd.msg.yahoo.com.
+204.99.102.189.in-addr.arpa.
+cdn.api.twitter.com.
+0-310.channel.facebook.com.
+hsym8ldfm.61ll.
+www.edifact.com.mx.
+www.astigresasdofunk.com.br.
+admiral-billiard.ru.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+evsecure-ocsp.verisign.com.
+guzzoni.apple.com.
+35.191.113.187.in-addr.arpa.
+hostmysite.javahd.com.
+213.203.91.76.in-addr.arpa.
+test-rt.liftdna.com.
+ppgnow.com.
+members.dyndns.org.
+photos-f.ak.fbcdn.net.
+www.google.com.
+crl.godaddy.com.
+carlosgivaja.blogspot.com.
+beon.ru.
+dr._dns-sd._udp.0.3.168.192.in-addr.arpa.
+zpay.static.zynga.com.
+techsfera.blogspot.com.
+171.41.141.201.in-addr.arpa.
+41.211.101.24.in-addr.arpa.
+tmss.trendmicro.com.
+www.amazon.co.jp.
+login.live.com.
+b.static.ak.fbcdn.net.
+az15112.vo.msecnd.net.
+mail.bobcatwireless.net.
+extra-tm.ru.
+dancinteens.com.
+211.161.255.201.in-addr.arpa.
+www.mybrowserbar.com.
+designchlorid.com.
+mail.tesmedsonic.com.
+wikiguate.com.gt.
+zpwrcqmtpdtiolr.biz.
+shared.live.com.
+a.root-servers.net.
+a.root-servers.net.
+j5.tagstat.com.
+time.windows.com.
+dns.msftncsi.com.
+imap.gmail.com.
+ucs.query.yahoo.com.
+a.root-servers.net.
+mx4.hotmail.com.
+mx.pchg.net.
+pixel.facebook.com.
+rtigaf.com.
+a1005.w42.akamai.net.
+www.defenderseguridad.com.ar.
+94.53.58.187.in-addr.arpa.
+ds.serving-sys.com.
+dainikbhaskarcom.ourtoolbar.com.
+relay.data.edge.messenger.live.com.
+a-0.19-a3090071.9050083.1518.19d3.3ea1.410.0.e5ngemfnasja57b2n97v98jpmv.avqs.mcafee.com.
+www.webstats.motigo.com.
+145.111.221.189.in-addr.arpa.
+lh3.googleusercontent.com.
+27.media.tumblr.com.
+rtf.com.
+www.scotiabank.com.mx.
+www.jtc1.org.
+107.145.96.177.in-addr.arpa.
+vivastil.ru.
+nmbar.org.
+ads.revsci.net.
+cn1.redswoosh.akadns.net.
+fsnp74.ucsnet.ru.
+cy.pwc.com.
+245.194.152.202.in-addr.arpa.
+twitter.com.
+rememberthewar.com.
+vision.ucdavis.edu.
+a2.sphotos.ak.fbcdn.net.
+116.92.127.201.in-addr.arpa.
+167.98.46.190.in-addr.arpa.
+carlsandburgvisits.com.
+www.googletagservices.com.
+a5.sphotos.ak.fbcdn.net.
+7vwaptlqn.27tm.
+smarturl.it.
+16.3.129.189.in-addr.arpa.
+platform.ak.fbcdn.net.
+www.downtownbatonrouge.org.
+kytubhtgf.34dx.
+ib7nqfu12.e97u8g4a.
+orange.fr.
+187.10.168.192.in-addr.arpa.
+3e-co.com.
+pixel.rubiconproject.com.
+hughes.net.
+sp.cwfservice.net.
+developers.facebook.com.
+open.bonniersciencegroup.com.
+srp-law.com.
+embed.jungroup.com.
+25.76.150.190.in-addr.arpa.
+www.firstrowsports.tv.
+creative.ak.fbcdn.net.
+s-static.ak.facebook.com.
+www.portalculturista.com.
+referentia.com.s8a2.psmtp.com.
+southernsecurity.org.
+23.227.48.65.in-addr.arpa.
+rs749tl2.rapidshare.com.
+www.coolrom.com.
+206.217.75.190.in-addr.arpa.
+www.ellencparkhurst.com.
+brand.blogs.com.
+mail1.mxsmtp.com.
+connect.facebook.net.
+222.157.215.201.in-addr.arpa.
+shaoranlds.blogspot.com.
+sp.cwfservice.net.
+250.9.186.190.in-addr.arpa.
+video.auto.sina.com.cn.
+api.twitter.com.
+220.194.97.59.in-addr.arpa.
+philou-traductions.fr.
+emai.com.
+a1533.da1.akamai.net.
+apis.google.com.
+ars.oscar.aol.com.
+www.wisteriaandcowparsley.com.
+profile.ak.fbcdn.net.
+updatekeepalive.mcafee.com.
+245.212.18.95.in-addr.arpa.
+106.241.209.201.in-addr.arpa.
+metallurgizdat.com.
+geo.messenger.services.live.com.
+6e3ff508.allanalpass.com.
+214.80.65.190.in-addr.arpa.
+164.11.1.121.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+mxmail.datamaticstech.com.
+a997.mm1.akamai.net.
+sqm.microsoft.com.
+profile.ak.fbcdn.net.
+psychiatry.wustl.edu.
+58.168.245.61.in-addr.arpa.
+mvtv.kr.
+a5.sphotos.ak.fbcdn.net.
+twitter.com.
+static.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+gentechcontrols.com.
+fbcdn-photos-a.akamaihd.net.
+59.0.249.46.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+msnads.vo.msecnd.net.
+es.data.toolbar.yahoo.com.
+smtp.ssvecnet.com.
+170.152.62.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+tallerdearquitectura.com.mx.
+dnl-00.geo.kaspersky.com.
+i52.tinypic.com.
+88.127.72.190.in-addr.arpa.
+ads2.msads.net.
+init.ess.apple.com.
+bs.serving-sys.com.
+static.ak.fbcdn.net.
+mail2hot.com.
+tracelabs.com.
+185.51.213.201.in-addr.arpa.
+npipb.com.s8b2.psmtp.com.
+50.29.102.201.in-addr.arpa.
+248.206.122.190.in-addr.arpa.
+fbcdn-profile-a.akamaihd.net.
+news.google.com.mx.
+gdgt.com.
+ville-antony.fr.
+www.sat.gob.mx.
+time.chttl.com.tw.
+37.111.56.87.in-addr.arpa.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sophiedahl.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.xhamster.com.
+154.215.120.203.in-addr.arpa.
+google.com.mx.
+wwerrsdf.blogspot.com.
+wooster.bur.ru.
+ajax.googleapis.com.
+creative.ak.fbcdn.net.
+a-tuin.t72.ru.
+www.austinwholesaledecking.com.
+photos-h.ak.fbcdn.net.
+80.61.147.79.in-addr.arpa.
+excessivesweatingtreatmentsite.com.
+365holiday.net.
+yudo-ch.com.
+a.root-servers.net.
+234.45.5.149.in-addr.arpa.
+www.facebook.com.
+a8.sphotos.ak.fbcdn.net.
+iabw:p6c6.y77u7t2n.
+voipb.sip.yahoo.com.
+www.peseatodo.com.ar.
+cbsradioguide.files.wordpress.com.
+ocsp.godaddy.com.
+www.weather.com.
+60.112.38.115.in-addr.arpa.
+roger.s.com.
+triumphstaffing.com.s5a2.psmtp.com.
+online.cartus.com.
+sd-cf.softonic.com.
+sn1sifs30001.unilever.com.
+citron.ru.
+plusone.google.com.
+tc.v17.cache3.c.youtube.com.
+barracuda.geneva.edu.
+by2msg3010506.gateway.messenger.live.com.
+photos-g.ak.fbcdn.net.
+nm28-vm1.bullet.mail.sp2.yahoo.com.
+_318_87_8.
+dns.msftncsi.com.
+translate.google.com.mx.
+104.182.200.189.in-addr.arpa.
+y5h7hfih1.98gu.
+dr._dns-sd._udp.lan.
+impaxlabs.com.
+a5.sphotos.ak.fbcdn.net.
+117.0.170.201.in-addr.arpa.
+media.singsnap.com.
+intaugol.portal.ru.
+support.google.com.
+c.admob.com.
+www.muslmh.com.
+external.ak.fbcdn.net.
+81.103.193.190.in-addr.arpa.
+119.154.128.189.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+www.carversation.com.
+239.94.72.82.in-addr.arpa.
+safebrowsing.clients.google.com.
+113.125.158.82.in-addr.arpa.
+profile.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+api.nanigans.com.
+83.229.248.189.in-addr.arpa.
+_vlmcs._tcp.
+a8.sphotos.ak.fbcdn.net.
+www.madera.gob.mx.
+google.com.
+titanium30-en.url.trendmicro.com.
+calculadora-cientifica.blogspot.com.
+mail2.easternandoriental.com.
+otonews.com.
+a7.sphotos.ak.fbcdn.net.
+m2.nsimg.net.
+www.last.fm.
+r.mzstatic.com.
+www.bustyivysnow.com.
+155.154.105.85.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+48.121.251.190.in-addr.arpa.
+ubas.ru.
+profile.ak.fbcdn.net.
+qbgmtqv7k.98zd.
+imetstuart.com.
+81.150.110.87.in-addr.arpa.
+203.85.146.189.in-addr.arpa.
+www.amle.org.
+photos-a.ak.fbcdn.net.
+usd368.k12.ks.us.
+i1.ytimg.com.
+167.174.173.218.in-addr.arpa.
+a.root-servers.net.
+24.39.111.198.in-addr.arpa.
+rad.msn.com.
+235.154.242.82.in-addr.arpa.
+dasfasdf.com.
+a.root-servers.net.
+c-0.19-220f9041.6010081.1518.19d4.3ea1.210.0.ar12mm2qe8znm1u6b3vqqwfhi6.avqs.mcafee.com.
+img546.imageshack.us.
+cm.ac3.msn.com.
+plusone.google.com.
+profile.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+webcache.googleusercontent.com.
+mail.austasia.net.
+photos-b.ak.fbcdn.net.
+d2060227.instant.xoom.it.
+s0.2mdn.net.
+217.92.192.88.in-addr.arpa.
+www.yiyi.cc.
+plusone.google.com.
+facebook.com.
+www.facebook.com.
+mpcstatic.com.
+dns.msftncsi.com.
+244.3.0.192.in-addr.arpa.
+sds.nus.ventura.xbox.com.
+barranquilla.vive.in.
+www.google.com.
+gplus.to.
+www.trailersdecine.com.
+a.root-servers.net.
+163.20.224.85.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+xtina-forum.com.
+d.foxadd.com.
+safebrowsing.clients.google.com.
+766.talkgadget.google.com.
+3.bp.blogspot.com.
+www.gtldna.com.
+media.secret.shooshtime.com.
+198.27.253.201.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+startsear.ch.
+inbound.jessicasoutlet.com.netsolmail.net.
+static.ak.fbcdn.net.
+www.googleadservices.com.
+a1005.w42.akamai.net.
+penxl.ru.
+tr.wikipedia.org.
+a2.sphotos.ak.fbcdn.net.
+3.121.121.192.in-addr.arpa.
+a.root-servers.net.
+www.codinginstinct.com.
+googleads.g.doubleclick.net.
+249.63.72.89.in-addr.arpa.
+col.stc.s-msn.com.
+engr.sgi.com.
+221.142.39.190.in-addr.arpa.
+handicapping.bloodhorse.com.
+a.root-servers.net.
+bersoaexpres.blogspot.com.
+soccergoals.com.
+www.facebook.com.
+a.root-servers.net.
+202.22.168.192.in-addr.arpa.
+webmail.conformis.com.
+secure.shared.live.com.
+mail2.ibmc.up.pt.
+cifraclub.terra.com.
+radio1.todostreaming.es.
+meronisrl.it.
+update.epyte.com.
+www.facebook.com.
+blog.wiggle.co.uk.
+pagead2.googlesyndication.com.
+sup.live.com.
+a.root-servers.net.
+h.live.com.
+27.60.124.190.in-addr.arpa.
+pixel.quantserve.com.
+xmails.org.
+40.114.167.189.in-addr.arpa.
+171.250.183.98.in-addr.arpa.
+106.214.94.98.in-addr.arpa.
+i1.ytimg.com.
+231.162.27.190.in-addr.arpa.
+sonefex.com.
+external.ak.fbcdn.net.
+scotiarewards.scotiabank.com.
+246.102.218.90.in-addr.arpa.
+download.windowsupdate.com.
+www.rsanow.com.au.
+jkl123.com.
+a.root-servers.net.
+www.google-analytics.com.
+www.facebook.com.
+www.voayeurs.com.
+sp.mx.ask.com.
+www.pablogeo.com.
+ad.yieldmanager.com.
+75.82.81.71.in-addr.arpa.
+platform.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+www.fiordland.org.nz.
+a7.sphotos.ak.fbcdn.net.
+rcp.eu.blackberry.com.
+yeglive.ca.
+www.momhairypussy.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+google.com.
+140.122.105.46.zz.countries.nerd.dk.
+edge.youtube-mp3.org.
+mail01.travelexamericas.com.
+71.98.49.190.in-addr.arpa.
+producciondelibros.blogspot.com.
+photos-d.ak.fbcdn.net.
+master7.teamviewer.com.
+mail1.sfisolutions.com.
+fpdownload.adobe.com.
+zulu.tweetmeme.com.
+santiago.boardwalk-internet.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+safebrowsing-cache.google.com.
+113.244.112.200.in-addr.arpa.
+.
+www.tienda-regalos-bautizo.com.
+cs11233.vk.com.
+educacion-virtualidad.blogspot.com.
+debryanskaya.ru.
+30.28.32.186.in-addr.arpa.
+cdn.dzone.com.
+www.google.com.
+a.root-servers.net.
+ocsp.digicert.com.
+86.160.144.189.in-addr.arpa.
+35.173.130.190.in-addr.arpa.
+a.root-servers.net.
+feeds.randyblue.com.
+www.3hhd.com.
+hmr.ms00.net.
+profile.ak.fbcdn.net.
+platform.ak.fbcdn.net.
+es-es.facebook.com.
+pixel.facebook.com.
+t2.gstatic.com.
+es-es.fxfeeds.mozilla.com.
+abpp01.albertapermitpro.com.
+convista.com.
+sac.gti.mcafee.com.
+ok.ru.
+191.248.168.192.in-addr.arpa.
+uniqlo.edgesuite.net.
+www.cuantamierda.com.
+s7.addthis.com.
+54.51.1.46.in-addr.arpa.
+youtu.be.
+_892_16_9.
+evenx.ru.
+236.146.151.190.in-addr.arpa.
+mail-s13.1gb.ru.
+ocsp.digicert.com.
+_682_27_1.
+go.purenetworks.com.
+rt.legolas-media.com.
+weekly.chosun.com.
+jameique.com.
+dl.pinyin.sogou.com.
+clients2.google.com.
+221.156.145.72.in-addr.arpa.
+niiide.com.
+loc7.eu1.badoo.com.
+photos-f.ak.fbcdn.net.
+44-courier.push.apple.com.
+mail.mavara.com.
+dns.msftncsi.com.
+cfs-p3.l3.fbcdn.net.
+2il3o8527.59tq.
+250.74.108.38.in-addr.arpa.
+medfordwomensclinic.com.
+christianwach.blogspot.com.
+c.msn.com.
+www.youtube.com.
+www.dosmildiez.net.
+www.fristam.de.
+s.youtube.com.
+www.plan-uk.org.
+fhstzigtc.55og.
+photos-g.ak.fbcdn.net.
+www.elbuscapersonas.com.pe.
+www.drjeffadams.com.
+pt-br.facebook.com.
+windowslive.com.
+cdn.vidigital.ru.
+www.youtube.com.
+main.exoclick.com.
+.
+fashionleague-uk.blogspot.com.
+profile.ak.fbcdn.net.
+creative.ak.fbcdn.net.
+223.224.83.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+216.7.19.187.in-addr.arpa.
+106.119.204.187.in-addr.arpa.
+r._dns-sd._udp.lan.
+ponchtomellh.nu.
+www.santanderempresarial.com.br.
+www.badoo.com.
+www.youtube.com.
+feeds.feedburner.com.
+dealers.autotrader.com.
+twitter.com.
+listado.mercadolibre.com.ar.
+t.co.
+uralan.ru.
+a.root-servers.net.
+www.facebook.com.
+photos-c.ak.fbcdn.net.
+w.sharethis.com.
+citu.info.
+122.173.31.88.in-addr.arpa.
+social.bidsystem.com.
+sharethis.com.
+130.27.242.201.in-addr.arpa.
+esemomentoesacancion.blogspot.com.
+45.6.106.84.in-addr.arpa.
+xads.zedo.com.
+mail.new.flexmail.ifxnetworks.com.
+www.facebook.com.
+photos-f.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+ssl.gstatic.com.
+apps.facebook.com.
+gwia1.eht.k12.nj.us.
+torrent.ibiblio.org.
+apis.google.com.
+244d9103.yyv.co.
+sea-latino.com.
+116.39.64.98.in-addr.arpa.
+nctinc.com.
+el.justin.tv.
+106.227.117.200.in-addr.arpa.
+dir.xiph.org.
+sn1msg3020109.gateway.messenger.live.com.
+us.mcafee.com.
+www.renuevodeplenitud.com.
+ads.trafficjunky.net.
+clients1.google.com.
+d1ros97qkrwjf5.cloudfront.net.
+www.google.com.
+cdn.siteanalytics.evolvemediametrics.com.
+www.facebook.com.
+apis.google.com.
+r-data.adsrvr.org.
+_631_30_5.
+105.164.164.187.in-addr.arpa.
+y97fysd1y.68qn.
+a926.da1.akamai.net.
+ar.wikipedia.org.
+api.twitter.com.
+www.youtube.com.
+dothehudson.net.
+shnotify.acer.com.tw.
+uphoto.doulike.com.
+www.net-tec-ag.de.
+210.31.225.189.in-addr.arpa.
+a.root-servers.net.
+google.com.
+fs476.uploading.com.
+4.map.pop6.com.
+supplementwarehouse.com.
+mx1.mailcleaner.pro.
+apps.facebook.com.
+0.pool.ntp.org.
+www.eliphone5.com.
+www.segundamano.com.mx.
+201.109.117.200.in-addr.arpa.
+www.expendablespremiere.com.
+_166_57_6.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mscrl.microsoft.com.
+vgn-xpromo.vostu.com.
+240.137.167.190.in-addr.arpa.
+www.petroleo-mexico.com.
+aurelinlul.fitepyciness.pw.
+onlinehelp.microsoft.com.
+a.root-servers.net.
+cuda4002.acc.org.
+www.google.com.
+s-static.ak.facebook.com.
+www.stopbadware.org.
+googleads.g.doubleclick.net.
+56.15.156.187.in-addr.arpa.
+a.root-servers.net.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+mt.livecamfun.com.
+41.249.193.186.in-addr.arpa.
+mailserver3.escatec.com.
+igor.facemoods.com.
+krona.obninsk.ru.
+littlehousedenoel.blogspot.com.
+urls.co.za.
+bloghelp.exblog.jp.
+s.aeriastatic.com.
+65.215.36.69.in-addr.arpa.
+a.root-servers.net.
+www.google.com.
+safebrowsing-cache.google.com.
+benihana.com.
+denmangroup.com.
+www.google.com.
+secure.wlxrs.com.
+www.youtube.com.
+sophtech.com.
+www.hixatselfridges.co.uk.
+www.mochiads.com.
+137.41.87.201.in-addr.arpa.
+12.217.58.71.in-addr.arpa.
+ttns.com.
+14.167.146.213.in-addr.arpa.
+elteatrito.com.
+a.root-servers.net.
+mail.pastadelcapitano.com.br.
+161.172.137.187.in-addr.arpa.
+www.mulletsighting.com.
+elblogdemariaelena.wordpress.com.
+m.hotmail.com.
+53.40.135.181.in-addr.arpa.
+8b.u.51img1.com.
+xulforge.com.
+_708_57_9.
+integrityhomelending.com.
+fcbarcelonanoticias.com.
+stateplanthire.com.
+anonysupermaguila.esforos.com.
+www.download.windowsupdate.com.
+nihonkiin.or.jp.
+sasvp.callvantage.att.com.
+109.171.161.187.in-addr.arpa.
+137.51.93.186.in-addr.arpa.
+46.92.199.190.in-addr.arpa.
+mail.printlux.com.
+0.11-a30fc081.80210b1.1518.19d2.3ea1.200.0.aziphaksrrcu4c52zmddfs4m4b.avqs.mcafee.com.
+mail01.agcs.allianz.com.ppde.azmx.de.
+static.ak.fbcdn.net.
+prpadi6nh.y98m8g1x.
+157.54.15.116.in-addr.arpa.
+ads2.iforex.com.
+www.gi.co.id.
+164.3.74.187.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tpb.tracker.thepiratebay.org.
+d3lvr7yuk4uaui.cloudfront.net.
+www.bestbuy.com.mx.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ksn1-11-part1.kaspersky-labs.com.
+225.123.231.190.in-addr.arpa.
+barkeeper.ie.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+us.battle.net.
+a.root-servers.net.
+60.57.109.70.in-addr.arpa.
+www.carapantalla.com.
+lb._dns-sd._udp.lan.
+fbcdn-profile-a.akamaihd.net.
+235.41.11.83.in-addr.arpa.
+j-osaka.net.
+www.mecanica-facil.com.
+www.lifebatch.com.
+3.162.30.186.in-addr.arpa.
+lsgip-com.relay1c.spamh.com.
+cdn.hegre-art.com.fpbns.net.
+a3.sphotos.ak.fbcdn.net.
+32.36.148.88.in-addr.arpa.
+dosrv.perry.k12.ms.us.
+www.ygexpert.com.
+49.192.64.195.in-addr.arpa.
+ozestretch.com.
+photos-e.ak.fbcdn.net.
+es.99counters.com.
+23.65.229.220.in-addr.arpa.
+for-my-wedding.com.
+css.wlxrs.com.
+a.root-servers.net.
+static.ak.facebook.com.
+mail.int.ru.
+www.google-analytics.com.
+www.gstatic.com.
+photos-h.ak.fbcdn.net.
+186.123.104.209.in-addr.arpa.
+apple.com.
+126.216.51.190.in-addr.arpa.
+www.youtube.com.
+a3.sphotos.ak.fbcdn.net.
+appspot.l.google.com.
+www.flexcourt.com.
+webassets3.sparkybee.com.
+wxdata.weather.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+gdgundem.com.
+thumbnail.api.livestream.com.
+ejabh.m5zn.com.
+connect.facebook.net.
+cxz23.meaningtool.com.
+apple.accuweather.com.
+youtube-global.blogspot.com.
+114.222.107.209.in-addr.arpa.
+thor24.com.s8a1.psmtp.com.
+111.15.238.173.in-addr.arpa.
+profile.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+www.juegosjuegos.asia.
+www.adobe.com.
+ipad.screensteps.com.
+api.quizlet.com.
+www.elle.es.
+col.stc.s-msn.com.
+conloscascospuestos.blogspot.es.
+66.21.71.190.in-addr.arpa.
+241.255.239.190.in-addr.arpa.
+contadorweb.net.
+www.jeuxfille.tv.
+teredo.ipv6.microsoft.com.
+250.249.230.190.in-addr.arpa.
+www.myfblikes.info.
+www.tibiawar.org.
+lassuperfotos.com.es.
+mail2a.smtproutes.org.
+connexions-durham.org.
+112.98.41.187.in-addr.arpa.
+dns.msftncsi.com.
+cs4499.vk.com.
+www.culosdetias.com.
+static.ak.fbcdn.net.
+e1310.vuclip.com.
+212.87.156.203.in-addr.arpa.
+ad.yieldmanager.com.
+dk.webcams.travel.
+dns.msftncsi.com.
+picasaweb.google.com.
+sprojects.mmi.mcgill.ca.
+checkip.dyndns.org.
+bit.ly.
+ssl.gstatic.com.
+www.nudelinkdump.com.
+cdn.api.twitter.com.
+nova100.evectors.it.
+mail.google.com.
+fromthepews.org.
+apple.com.
+i-cdn.servedbyopenx.com.
+tv2x2.ru.
+sn1msg2010522.gateway.messenger.live.com.
+acoupleofgurus.com.inbound10.mxlogicmx.net.
+crl.microsoft.com.
+photos-f.ak.fbcdn.net.
+www.facebook.com.
+www.google.com.
+secure.tours4fun.com.
+cm.g.doubleclick.net.
+www.navartur.es.
+a.root-servers.net.
+mx2c26.carrierzone.com.
+apis.google.com.
+th2.iwannajerk.com.
+ib.adnxs.com.
+msc.wlxrs.com.
+www.iesloscardones.es.
+view.atdmt.com.
+cdn0.sexysway.com.
+www.montanasilversmiths.com.
+213.45.171.118.in-addr.arpa.
+www.johnstonpress.co.uk.
+www.estilaestilo.cl.
+38.9.93.200.in-addr.arpa.
+v1es.sftcdn.net.
+webcompay.com.
+es.wikipedia.org.
+www.entretengo.com.
+www.comparaencasa.com.
+176.84.104.186.in-addr.arpa.
+m.facebook.com.
+a.root-servers.net.
+redirector.c.youtube.com.
+pixel.facebook.com.
+mx.youtube.com.
+noble.org.
+www.carhood.com.
+us.rd.yahoo.com.
+www.parafernalha.com.br.
+groups.google.com.mx.
+nsw.austutors.com.au.
+199.194.105.186.in-addr.arpa.
+urs.microsoft.com.
+_086_63_2.
+turneralternatives.com.
+s7.addthis.com.
+a.root-servers.net.
+developers.facebook.com.
+55.214.159.200.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+images.crocotube.com.
+checkip.dyndns.org.
+mexicanainforma.com.
+fbcdn-sphotos-a.akamaihd.net.
+developers.facebook.com.
+www.facebook.com.
+sosrecados.com.
+external.ak.fbcdn.net.
+external.ak.fbcdn.net.
+static.ak.fbcdn.net.
+i2.ytimg.com.
+a2.twimg.com.
+ads1.msads.net.
+johnhcarter.com.s7b1.psmtp.com.
+c-0.19-a3098481.483.1518.19d4.3ea1.410.0.96atjpzlesjf4k3w9ewwebnsl5.avqs.mcafee.com.
+www.teentiger.com.
+www.ig.gmodules.com.
+ssl.gstatic.com.
+photos-a.ak.fbcdn.net.
+external.ak.fbcdn.net.
+ar.finance.yahoo.com.
+www.gstatic.com.
+c.static-cdn.playfish.com.
+97.232.10.181.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+l.yimg.com.
+b._dns-sd._udp.belkin.
+220.171.152.79.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+cpssys.com.
+sevastopol.info.
+www.masimasd.blogspot.com.
+photos-g.ak.fbcdn.net.
+cssweat.com.
+prev.explabs.net.
+cwnt.com.
+217.26.108.190.in-addr.arpa.
+bikinibank.com.
+39.126.126.200.in-addr.arpa.
+topoaze.eu.
+sportingnews.checkm8.com.
+static.ak.connect.facebook.com.
+www.wftv.com.
+profile.ak.fbcdn.net.
+www.peyamner.com.
+mail.seec.com.tw.
+www.cnc.org.mx.
+profile.ak.fbcdn.net.
+cybershadow.com.
+groups.live.com.
+a.root-servers.net.
+41.23.8.176.in-addr.arpa.
+114.83.19.67.in-addr.arpa.
+forum.swzone.it.
+a.root-servers.net.
+mxytiqlgllxl.ac.
+xetgs.xboxlive.com.
+pagead2.googlesyndication.com.
+221.36.113.92.in-addr.arpa.
+dvlti.ru.
+ad.z5x.net.
+csi.gstatic.com.
+www.frederico-araujo.com.
+www.adobe.com.
+nullmx.matthew1.com.
+onlinux-it.setupdns.net.
+75.167.56.186.in-addr.arpa.
+nl.softonic.com.
+windowslivelatam.com.
+dns.msftncsi.com.
+mountainss.wordpress.com.
+95.181.11.88.in-addr.arpa.
+ksn1-11-part2.kaspersky-labs.com.
+eqekld.com.
+www.betweenthelines.net.au.
+mk3047.spb.edu.
+65.12.221.189.in-addr.arpa.
+external.ak.fbcdn.net.
+time.chttl.com.tw.
+_490_63_5.
+b.imwx.com.
+222.199.172.78.in-addr.arpa.
+237.73.167.190.in-addr.arpa.
+riyadhciti.com.
+1.134.113.186.in-addr.arpa.
+connect.facebook.net.
+a.root-servers.net.
+www.durometrosymicrodurometros.com.
+newsrss.bbc.co.uk.
+34.211.36.186.in-addr.arpa.
+sp.cwfservice.net.
+dns.msftncsi.com.
+clampfansub.foroes.net.
+77.82.187.93.in-addr.arpa.
+11.87.190.71.in-addr.arpa.
+134.149.83.200.in-addr.arpa.
+adsx.greystripe.com.
+www.psychiatry.ox.ac.uk.
+rad.msn.com.
+bs.eyeblaster.akadns.net.
+www.usdrybeans.com.
+all-hidden-object-games.com.
+a.root-servers.net.
+196.206.65.151.in-addr.arpa.
+.
+littlemayra.blogspot.com.
+234.6.179.190.in-addr.arpa.
+www.textsrv.com.
+www.youtube.com.
+tomkadlec.com.
+a-0.19-210f7001.a0e0131.1518.19d4.3ea1.210.0.gq4f3ru3uzzs8dk17ne1ngnvct.avqs.mcafee.com.
+storage.conduit.com.
+starnetworks.ru.
+photos-d.ak.fbcdn.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+dominformer.ru.
+a7.sphotos.ak.fbcdn.net.
+sc19.rules.mailshell.net.
+i4.ytimg.com.
+a.rad.msn.com.
+lb._dns-sd._udp.0.129.37.10.in-addr.arpa.
+2.197.253.201.in-addr.arpa.
+a0.twimg.com.
+120.44.37.190.in-addr.arpa.
+200.99.51.190.in-addr.arpa.
+156.101.138.187.in-addr.arpa.
+177.87.232.189.in-addr.arpa.
+tour.twistys.com.
+blufiles.storage.msn.com.
+static.ak.fbcdn.net.
+ak-media.soundcloud.com.
+static.app.widdit.com.
+teredo.ipv6.microsoft.com.
+www.dulcedecoracion.es.
+a-0.19-220f3081.9120081.1518.19d4.3ea0.200.0.btenq4pn4ldvwt3855u2t1jdnt.avqs.mcafee.com.
+106.254.238.201.in-addr.arpa.
+pres.us.mydlink.com.
+www.innovar.gov.ar.
+nsx.np.dl.playstation.net.
+a3.sphotos.ak.fbcdn.net.
+img100.xvideos.com.
+www.adobe.com.
+smtp.cimcast.net.
+www.dsri.dk.
+www.google.com.
+secure.shared.live.com.
+a5.sphotos.ak.fbcdn.net.
+anaggh.com.
+www.redphotophotography.com.
+136.200.89.87.in-addr.arpa.
+www.masmitja.net.
+images.digby.com.
+45.92.217.188.in-addr.arpa.
+twitter.com.
+photos-a.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+aaasea.org.
+velvac.com.inbound10.mxlogicmx.net.
+a.root-servers.net.
+www.opensong.org.
+developers.facebook.com.
+www.nitrohouse.com.
+check4.facebook.com.
+246.138.120.186.in-addr.arpa.
+www.releasedon.com.
+static.ak.fbcdn.net.
+a1725.l.akamai.net.
+mai.in.th.
+104.47.52.186.in-addr.arpa.
+matscanbaraney.museum.
+128.31.107.186.in-addr.arpa.
+214.39.254.201.in-addr.arpa.
+tc4.easythumbhost.com.
+246.198.239.85.in-addr.arpa.
+google.com.
+platform.ak.fbcdn.net.
+a.root-servers.net.
+comconcrp.com.
+www.gph.gov.sa.
+53.69.23.76.in-addr.arpa.
+vax.co.uk.
+a6.sphotos.ak.fbcdn.net.
+maerchen.woxikon.de.
+a3.sphotos.ak.fbcdn.net.
+www.facebook.com.
+allfreevectors.com.
+benelli.com.au.
+pfplace.com.
+www.hulkshare.com.
+a.root-servers.net.
+76.240.78.187.in-addr.arpa.
+apple.com.
+comentarios.esmas.com.
+230.89.88.200.in-addr.arpa.
+56.12.27.77.in-addr.arpa.
+img69.imageshack.us.
+_411_83_3.
+wk-diecast.blogspot.com.
+140.82.224.189.in-addr.arpa.
+img.tongji.linezing.com.
+s1.img.awempire.com.
+a.root-servers.net.
+mail.peakinsight.com.
+bolsaibex.com.
+www.younghegan.com.
+www.dahousecat.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+161.221.165.69.in-addr.arpa.
+clinedavis.com.
+api.twitter.com.
+a.root-servers.net.
+mail2.graymont.com.
+img.adverticum.net.
+33.66.179.190.in-addr.arpa.
+mx.alanet.com.br.
+24.177.176.78.in-addr.arpa.
+b.scorecardresearch.com.
+google.com.
+profile.ak.fbcdn.net.
+228.201.43.200.in-addr.arpa.
+adserving.cpxinteractive.com.
+botsikas.blogspot.com.
+26.media.tumblr.com.
+s1-word-edit.vo.msecnd.net.
+147.159.232.200.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+95.66.56.186.in-addr.arpa.
+22.6.168.192.in-addr.arpa.
+141.142.18.187.in-addr.arpa.
+www.teamopolis.com.
+161.68.232.82.in-addr.arpa.
+nteck.com.
+4sq.com.
+a.root-servers.net.
+mail.percarbonat.ru.
+sc62.engate.com.
+d2100638.xoom.it.
+www.barclays.mobi.
+photos-f.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+mx1.techintgroup.com.
+a.root-servers.net.
+www.myresortnetwork.com.
+rospres.com.
+ib.adnxs.com.
+static.ak.fbcdn.net.
+127.181.176.190.in-addr.arpa.
+eliocel.blogspot.com.
+38.82.153.201.in-addr.arpa.
+pixel.facebook.com.
+www9.effectivemeasure.net.
+a.root-servers.net.
+gtsru.com.
+www.changosmangos.net.
+_403_10_2.
+www.prontorotulo.com.
+226.236.62.95.in-addr.arpa.
+profile.ak.fbcdn.net.
+time.apple.com.
+a-0.19-2109e071.d0b0083.1518.19d4.3ea1.410.0.a8vnw6m6j8wv1hhrhb4gd6awlq.avqs.mcafee.com.
+mail.hhqc.com.
+pixel.quantserve.com.
+platform.twitter.com.
+yahoo.com.
+alicante.cochesdeocasion.com.
+www.facebook.com.
+74.12.45.86.in-addr.arpa.
+a.root-servers.net.
+habboon.com.
+www.abc.es.
+couponbuddy.s3.amazonaws.com.
+id.countrysearch.ec21.com.
+p04-bookmarks.icloud.com.
+google.com.
+apps.facebook.com.
+linux.ca.
+a.root-servers.net.
+70.235.189.184.in-addr.arpa.
+windows.microsoft.com.
+147.245.115.186.in-addr.arpa.
+appsforbb.com.
+creative.ak.fbcdn.net.
+www.sohubook.com.
+www2.netcom.com.
+photos-h.ak.fbcdn.net.
+www.google.com.
+a.root-servers.net.
+fls.doubleclick.net.
+coaching.35webs.com.
+twitter.com.
+rd.meebo.com.
+164.184.26.78.in-addr.arpa.
+www.rangeen.in.
+_213_07_1.
+88.104.88.186.in-addr.arpa.
+szwandu11.w91.516dns.com.
+tap2-cdn.rubiconproject.com.
+bkuxz526k.42wo.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+talk4.1.google.com.
+blyudo.org.ru.
+mvfhr.blogspot.com.
+centos.omnispring.com.
+pointa.autodesk.com.
+1257868.r.msn.com.
+www.guiadeestetica.com.
+51.239.168.192.in-addr.arpa.
+www.preferredhealthgroup.com.
+45.154.96.177.in-addr.arpa.
+atomicparsley.sourceforge.net.
+s7.addthis.com.
+kuv3wp1or.85nt.
+www.vjvdiamonds.com.
+static.only18teensex.com.
+www.connect.facebook.com.
+www.yahoo.com.
+www.richvomdorf.com.
+230.108.242.92.in-addr.arpa.
+icarly.co.
+sicurezza.ebay.it.
+s0.2mdn.net.
+ajax.googleapis.com.
+pagead2.googlesyndication.com.
+www.gstatic.com.
+126.9.0.192.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+213.22.95.190.in-addr.arpa.
+71.5.13.201.in-addr.arpa.
+creative.ak.fbcdn.net.
+russellandhazel.com.
+google.com.
+mowmgw02.mow.com.
+tracker.ccc.de.
+www.renegocios.com.
+www.peachygreen.com.
+voipc.sip.yahoo.com.
+6xgate.deviantart.com.
+www.ozu.es.
+a2.sphotos.ak.fbcdn.net.
+northshore-golfclub.com.
+ts.tsnet.ru.
+47j7b263u.j79b4r2u.
+www.policia.gov.co.
+a.root-servers.net.
+www.google.com.
+5h92qfb31.32kl.
+ltasconfig.ltassrv.com.
+www.facebook.com.
+www.effect.com.ve.
+www.nattoli.net.
+dfaasd.com.
+16.234.25.189.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b.scorecardresearch.com.
+126.0.20.212.in-addr.arpa.
+www.alawar.ru.
+www.switchplane.com.
+external.ak.fbcdn.net.
+11.105.247.189.in-addr.arpa.
+www.conduit.com.
+profile.ak.fbcdn.net.
+qiran.com.
+clients1.google.com.
+fxfeeds.mozilla.com.
+i4ucity.com.
+googleads.g.doubleclick.net.
+creative.ak.fbcdn.net.
+202.164.44.91.in-addr.arpa.
+vast.bp3846813.btrll.com.
+lhkha2sqv.m06m4m8c.
+external.ak.fbcdn.net.
+nt3.ggpht.com.
+profile.ak.fbcdn.net.
+www.dogpile.co.uk.
+profile.ak.fbcdn.net.
+134.143.86.186.in-addr.arpa.
+www.10stiri.ro.
+blog.mon-anniversaire.com.
+www.google-analytics.com.
+zynga2-a.akamaihd.net.
+missyfeelingaddicted.blogspot.com.
+mail.st-tula.ru.
+rs983l33.rapidshare.com.
+40-courier.push.apple.com.
+developers.facebook.com.
+smtp4.ocps.net.
+231.192.32.114.in-addr.arpa.
+pixel.facebook.com.
+110.237.211.201.in-addr.arpa.
+169.90.173.190.in-addr.arpa.
+es.babelfish.yahoo.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+rcp.na.blackberry.com.
+bcvideos.wwe.com.
+cdn-0.pics.hardsextubepremium.com.
+teredo.ipv6.microsoft.com.
+www.google.com.
+_280_38_3.
+152.10.90.208.in-addr.arpa.
+www.youtube.com.
+101.107.181.80.in-addr.arpa.
+smtp.divex.se.
+.
+jers3.info.
+photos-f.ak.fbcdn.net.
+vglgmtj.com.
+pixel.facebook.com.
+nvc.net.
+a8.sphotos.ak.fbcdn.net.
+58.189.15.216.zen.spamhaus.org.
+182.93.168.192.in-addr.arpa.
+a.ads2.msads.net.
+googleads.g.doubleclick.net.
+57.26.157.157.in-addr.arpa.
+250.45.228.91.in-addr.arpa.
+home.shop.ebay.com.
+fundacioncth.org.
+ratings-wrs.symantec.com.
+creative.ak.fbcdn.net.
+www.shantui-xcmg.ru.
+ibm-consultant.jobs.
+tts.hcs.k12.al.us.
+billing.sharo4ka.ru.
+p23.easybitsgo.net.
+www.dvdstore.com.
+172.154.102.189.in-addr.arpa.
+www.allteentits.com.
+mail2chile.com.
+pagead2.googlesyndication.com.
+0.
+9.65.57.187.in-addr.arpa.
+a-0.19-2309a081.d060083.1518.19b3.3ea1.210.0.spqabajtl54hfqk97s33alujnv.avqs.mcafee.com.
+www.bitefight.es.
+cdn.wibiya.com.
+ssl.gstatic.com.
+vthumb.ak.fbcdn.net.
+www.siteadvisor.com.
+4.bp.blogspot.com.
+zpzp2bd5d.84fm.
+csi.gstatic.com.
+www.microsoft.com.
+ubds.uniblue.com.
+photos-c.ak.fbcdn.net.
+ymail.com.
+mail.gmail.com.
+www.doc.mx.
+static.bergfex.at.
+www.crushingonclothes.com.
+m.wetter.net.
+www.slideshare.net.
+push.tagged.com.
+www.maxicon.com.
+173.151.22.190.in-addr.arpa.
+e7f964eb.rqq.co.
+plus.google.com.
+mail1.subrogation.net.
+photos-f.ak.fbcdn.net.
+a28.g.akamai.net.
+washingtondc.backpage.com.
+109.36.218.180.in-addr.arpa.
+183.119.56.187.in-addr.arpa.
+edge.quantserve.com.
+a.root-servers.net.
+hotmail.com.
+65.67.36.46.in-addr.arpa.
+227.253.174.189.in-addr.arpa.
+assets.tp-cdn.com.
+www.lanueva.com.
+137.158.45.70.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+blomasa.com.
+254.65.91.186.in-addr.arpa.
+resolver1.wguard.ctmail.com.
+ib.adnxs.com.
+rhrun.com.
+pix.fileratings.com.
+www.unydos.com.
+www.facebook.com.
+65.54.51.190.in-addr.arpa.
+irc.purchaseservice.com.
+fun.zynga.com.
+fbcdn-photos-a.akamaihd.net.
+northstar-service.com.
+tap.rubiconproject.com.
+tunnel.cfw.trustedsource.org.
+www.telalinks.com.
+marinerscovebayclub.org.
+24.42.76.189.in-addr.arpa.
+ohu32l2uu.l79o9n0a.
+www.americanyogaassociation.org.
+spamfilter.vpdinc.com.
+g12254.chrome.funnygames.org.
+219.73.43.114.in-addr.arpa.
+code.google.com.
+a.root-servers.net.
+216.107.66.75.in-addr.arpa.
+voipb.sip.yahoo.com.
+221.20.7.190.in-addr.arpa.
+www.youtube.com.
+www.fammed.ouhsc.edu.
+lukar.ru.
+lovewellmtn.com.
+mail.bazzillbasics.com.
+eser.cl.
+um16.eset.com.
+cloudav.updates.pandasecurity.com.
+photos-f.ak.fbcdn.net.
+mercuryapps.foxnews.com.
+_140_66_9.
+es.wikipedia.org.
+www.filestube.me.
+sisbib.unmsm.edu.pe.
+a4.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.3dtoontube.com.
+a.root-servers.net.
+photos-f.ak.fbcdn.net.
+rapidssl-crl.geotrust.com.
+a.root-servers.net.
+sp.cwfservice.net.
+fbcdn-photos-a.akamaihd.net.
+sandaraparkfashion.wordpress.com.
+a6.sphotos.ak.fbcdn.net.
+97.211.59.186.in-addr.arpa.
+www.youtube.com.
+ad.doubleclick.net.
+www.google.com.
+dns.msftncsi.com.
+jehzlau-concepts.com.
+ex.starwebnet.com.
+wirtschaftsschaufenster.augsburger-allgemeine.de.
+i.ytimg.com.
+rad.msn.com.
+_451_59_4.
+www.greenmanreview.com.
+201.102.172.81.in-addr.arpa.
+peseta.org.
+dns.msftncsi.com.
+tta.angel.googlepages.com.
+fpinsurance.com.s5b1.psmtp.com.
+photos-f.ak.fbcdn.net.
+denkermuscarello.com.pri-mx.na0100.smtproutes.com.
+itunes.apple.com.
+a.root-servers.net.
+utorak007.spreadshirt.net.
+api.facebook.com.
+orthoklahoma.com.
+118.244.78.186.in-addr.arpa.
+www.dlink-me.com.
+0.gravatar.com.
+tsi.com.
+67.1.144.187.in-addr.arpa.
+mail.webuzmani.net.
+time.chttl.com.tw.
+rusgai.ru.
+r._dns-sd._udp.0.79.168.192.in-addr.arpa.
+179.99.146.187.in-addr.arpa.
+www.roadsters.com.
+212.5.42.113.in-addr.arpa.
+20.224.171.69.in-addr.arpa.
+barracuda.networkpartners.com.
+static.ak.fbcdn.net.
+www.peliculasconpalomitas.com.
+vsal.ru.
+nccray.com.
+psrbb.com.s10b1.psmtp.com.
+a6.sphotos.ak.fbcdn.net.
+119.112.141.201.in-addr.arpa.
+c-0.19-a30fa081.8110000.1518.19d4.3ea1.410.0.e4w56fs4drhcime9zrg33i8qfv.avqs.mcafee.com.
+tagmanezt.terra.com.
+nenacho.blogspot.com.
+edgeyoke.com.
+pixel.facebook.com.
+135.141.24.189.in-addr.arpa.
+safe-mail.net.
+ocsp.godaddy.com.
+beta.hustlerstaboo.com.
+profile.ak.fbcdn.net.
+ns45.domaincontrol.com.
+190.29.126.77.in-addr.arpa.
+lcbcmail.com.
+dhs.state.tx.us.
+craneveyor.com.s7a2.psmtp.com.
+deltavalves.com.
+www.sqm.microsoft.com.
+profile.ak.fbcdn.net.
+ispro.de.
+api-read.facebook.com.
+adsfront.iminent.com.
+www.gstatic.com.
+a7.sphotos.ak.fbcdn.net.
+ctnzlauwgtgpryqp.net.
+ksn1-11-part1.kaspersky-labs.com.
+tubes.wamcash.com.
+www.thisislondon.co.uk.
+a.root-servers.net.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+www.activica.com.
+a.root-servers.net.
+twitter.com.
+tap2-cdn.rubiconproject.com.
+mail.google.com.
+143.124.222.189.in-addr.arpa.
+www.addthis.com.
+www.addthis.com.
+80.226.34.187.in-addr.arpa.
+pt-br.facebook.com.
+watson.microsoft.com.
+api.bing.net.
+mail.goodnessgreeness.com.
+yahoo.c.uk.lan.
+ggstat.flashget.com.
+es-la.facebook.com.
+s-static.ak.facebook.com.
+api.twitter.com.
+mscan.hortresearch.co.nz.
+www.emailmeform.com.
+dsd-www.nuts.co.uk.edgesuite.net.
+graph.facebook.com.
+0.gravatar.com.
+a.root-servers.net.
+142.12.185.201.in-addr.arpa.
+itunes.apple.com.
+backup35.url.trendmicro.com.
+itunes.apple.com.
+clients1.google.com.
+236.173.22.190.in-addr.arpa.
+galtime27.disqus.com.
+safebrowsing-cache.google.com.
+57.214.217.87.in-addr.arpa.
+225.8.175.187.in-addr.arpa.
+98.249.185.86.in-addr.arpa.
+www.kitco.com.
+urs.microsoft.com.
+cwine.com.
+safedrivingacademy.net.
+askville.amazon.com.
+pixel.quantserve.com.
+altfarm.mediaplex.com.
+51.117.111.87.in-addr.arpa.
+torem.ru.
+rct.ru.
+62.16.46.50.in-addr.arpa.
+mail.krata.ru.
+s.youtube.com.
+tools.google.com.
+huzzah.edublogs.org.
+global.cyworld.com.
+melco.com.
+feeds.bbci.co.uk.
+ms.aidc.com.tw.
+d15gt9gwxw5wu0.cloudfront.net.
+forums2.battleon.com.
+a1.sphotos.ak.fbcdn.net.
+mail.ideaspublishinggroup.com.
+26.120.112.190.in-addr.arpa.
+www.surveymonkey.com.
+188.187.93.173.in-addr.arpa.
+inglesperu.blogspot.com.
+a6.sphotos.ak.fbcdn.net.
+s.ytimg.com.
+beachcroft.co.uk.
+m.facebook.com.
+_123_71_9.
+a3.sphotos.ak.fbcdn.net.
+bloc.filantprim.com.
+www.putumayo-home.com.
+external.ak.fbcdn.net.
+weltonstreet.com.s10b2.psmtp.com.
+www.xat.org.
+teredo.ipv6.microsoft.com.
+a3dauto.com.
+99yahoo.com.
+www.facebook.com.
+152.222.247.189.in-addr.arpa.
+api-read.facebook.com.
+wmxzrgc4p.75ry.
+utmtrk9.apn.ask.com.
+checkip.dyndns.org.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+tp.socialvi.be.
+a85.phobos.apple.com.
+adframes.iminent.com.
+dt.tongji.linezing.com.
+blogis.in.
+banking.shinhan.com.
+l2.dmggroup.com.
+forums.theplanet.com.
+a8.sphotos.ak.fbcdn.net.
+sipc.org.rbl2.mcafee.com.
+static.ak.fbcdn.net.
+_391_24_4.
+61.178.210.186.in-addr.arpa.
+168.7.168.192.in-addr.arpa.
+bs.serving-sys.com.
+photos-e.ak.fbcdn.net.
+umcom.org.
+developers.facebook.com.
+tnn.ru.
+berega.net.
+mx02.vtb24.ru.
+db._dns-sd._udp.lan.
+karev.org.il.
+63.6d736e.636f6d.80h40041527.webcfs02.com.
+verizon.net.
+a6.sphotos.ak.fbcdn.net.
+245.64.161.190.in-addr.arpa.
+ny.goldenbridgeyoga.com.
+www.thehostmovienews.com.
+v7k5:a2rg.s27r4t9p.
+mx.masonattorneys.com.
+www8.babblar.org.
+a6.sphotos.ak.fbcdn.net.
+s-r.ru.
+234.92.169.189.in-addr.arpa.
+platform.twitter.com.
+picasaweb.google.com.
+73.215.248.74.in-addr.arpa.
+www.facebook.com.
+bkkok.com.
+www.google.com.
+js2.wlxrs.com.
+100.123.110.186.in-addr.arpa.
+sup.live.com.
+photos-h.ak.fbcdn.net.
+176.138.226.189.in-addr.arpa.
+www.meinsurancereview.com.
+www.americanplacetheatre.org.
+www.facebook.com.
+ssl.gstatic.com.
+paceproperties.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.w3api.com.
+ad.adnetwork.net.
+a6.sphotos.ak.fbcdn.net.
+itworld.simplyhired.com.
+l08.member.sp1.yahoo.com.
+136.89.229.189.in-addr.arpa.
+ad-g.doubleclick.net.
+chrisbblihy.mywibes.com.
+image2.pubmatic.com.
+www.linkbucks.com.
+hi-in.facebook.com.
+cdo.wikipedia.org.
+writetodone.com.
+test-rt.liftdna.com.
+filnaturalista.blogspot.com.
+p07-bookmarks.icloud.com.
+estaticos.diariodemallorca.es.
+www.futureelectronics.com.
+97.40.135.190.in-addr.arpa.
+motor.net.au.
+acegolfcars.com.
+fashionvibe-blog.blogspot.com.
+creative.ak.fbcdn.net.
+87.35.240.201.in-addr.arpa.
+www.diffuse-cpm.com.
+pek-nn.ru.
+profile.ak.fbcdn.net.
+www.download.windowsupdate.com.
+volga.customs.ru.
+sawall.de.
+www.movie1820.com.
+squarise.com.
+icon.daumcdn.net.
+a.root-servers.net.
+mbacm.com.
+a.root-servers.net.
+www.youtube-nocookie.com.
+castlocations.com.
+www.gratispeliculas.org.
+lh6.ggpht.com.
+piterspy.ru.
+creative.ak.fbcdn.net.
+hantech.com.
+rcp.na.blackberry.com.
+www.isg-apple.com.akadns.net.
+api-read.facebook.com.
+244.151.108.95.in-addr.arpa.
+video.google.com.
+220.193.122.84.in-addr.arpa.
+sync.search.spotxchange.com.
+www.adobe.com.
+profile.live.com.
+sn3.mailshell.net.
+www.deportemundial.net.
+fc07.deviantart.net.
+sneak.co.nz.
+bid.openx.net.
+s.amazon-adsystem.com.
+www.amyscott.com.
+www.unicef.org.
+16.133.25.210.in-addr.arpa.
+0-jh-w.channel.facebook.com.
+www.foxsportsla.com.
+bleached-to-the-bone-scene-3.ss.thirdmovies.com.
+cdn-a1.dvipcdn.com.
+partner.googleadservices.com.
+a.root-servers.net.
+mums.cl.
+99.139.172.189.in-addr.arpa.
+localhost.
+catgirlkawaii.deviantart.com.
+googlemail.l.google.com.
+hotmait.com.
+render.talk4free.com.
+61.208.179.189.in-addr.arpa.
+www.sanitaryum.com.
+119.228.51.190.in-addr.arpa.
+oxydo.ru.
+espn.co.
+iteccolorado.com.
+web360.com.
+a.root-servers.net.
+www.playflv.com.
+kfmg9lgzm.93kx.
+18.116.8.60.in-addr.arpa.
+dh.api.apptao.com.
+redffmaill.com.
+a.root-servers.net.
+toolbar.google.com.
+176.247.160.201.in-addr.arpa.
+topcharts.ru.
+xml.opera.com.
+photos-g.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+kft8nx7q:.57eg.
+billing.sharo4ka.ru.
+www.itknowledge24.com.
+139.203.41.200.in-addr.arpa.
+photos9.flickr.com.
+77867bf.net.
+profile.ak.fbcdn.net.
+126.96.48.60.in-addr.arpa.
+fl0.ru.
+r._dns-sd._udp.0.10.168.192.in-addr.arpa.
+e566.b.akamaiedge.net.
+pixel.facebook.com.
+12.109.122.200.in-addr.arpa.
+webyetis.com.
+developers.facebook.com.
+pixel.facebook.com.
+www.facebook.com.
+forum.axishistory.com.
+193.222.36.187.in-addr.arpa.
+www.lanvin.com.
+196.33.148.88.in-addr.arpa.
+gqlgroup.com.
+time.chttl.com.tw.
+a.root-servers.net.
+external.ak.fbcdn.net.
+grandgeneral.com.
+www.facebook.com.
+g0.gstatic.com.
+doha.frasershospitality.com.
+a.root-servers.net.
+kremino.com.
+photos-b.ak.fbcdn.net.
+network.incgamers.com.
+ir.ebaystatic.com.
+voipb.sip.yahoo.com.
+apple.com.
+ippi.msk.su.
+83.95.70.208.in-addr.arpa.
+us.kpmg.com.
+del.icio.us.
+37.95.190.189.in-addr.arpa.
+ayaks.ru.
+load.tubemogul.com.
+www.rallyandracing.com.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+pixel.facebook.com.
+rssc.com.
+106.185.134.187.in-addr.arpa.
+videodown.baofeng.com.
+elpasotimes.gannettonline.com.
+piesdefamosas.com.
+133.203.26.177.in-addr.arpa.
+1.bp.blogspot.com.
+graph.facebook.com.
+b.scorecardresearch.com.
+photos-b.ak.fbcdn.net.
+ezlip.com.
+media.fastcar.co.uk.
+a5.sphotos.ak.fbcdn.net.
+232.180.146.187.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+laminate-parquet.ru.
+db._dns-sd._udp.lan.
+clients1.google.com.
+www.unileon.es.
+creative.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+www.msftncsi.com.
+s7.addthis.com.
+be-x-old.wikipedia.org.
+www.nabdh-alm3ani.net.
+photos-h.ak.fbcdn.net.
+f:mw7gybl.h86d7r5b.
+www.foodreference.com.
+a.root-servers.net.
+tracker.csze.com.
+154.129.39.186.in-addr.arpa.
+platform.ak.fbcdn.net.
+227.173.123.84.in-addr.arpa.
+dcingredients.com.
+ladbrokesmobilebetting.com.
+103.187.12.186.in-addr.arpa.
+inky.tumblr.com.
+google.com.
+www.consoleaddiction.com.
+zipform.com.s8a2.psmtp.com.
+weather.wapp.wii.com.
+a.root-servers.net.
+8.24.220.189.in-addr.arpa.
+www.emesotherapy.com.au.
+download347.avast.com.
+r.openx.net.akadns.net.
+external.ak.fbcdn.net.
+www.linguee.com.ar.
+www.steampunkmagazine.com.
+a-0.19-a3092081.20200b3.1518.19d3.3ea1.410.0.eh5u9jzwkkcg57a42q646qaje6.avqs.mcafee.com.
+158.181.231.190.in-addr.arpa.
+s.ytimg.com.
+161.234.141.201.in-addr.arpa.
+resolutioncenter.ebay.com.
+flatfrogmusic.com.
+www.richtig-spielen.de.
+smtp-out.wplus.net.
+17.142.138.187.in-addr.arpa.
+anixter.net.
+rcw.wc24.wii.com.
+200.115.69.189.in-addr.arpa.
+0-jl-w.channel.facebook.com.
+www.facebook.com.
+www.msn.com.
+barracuda.cannondesign.com.
+52.239.68.66.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+online.unitconverterpro.com.
+ad.z5x.net.
+platform.ak.fbcdn.net.
+m.addthisedge.com.
+www.facebook.com.
+weather.services.conduit.com.
+www.juegos.com.
+a.root-servers.net.
+www.crecimiento-personal.com.
+185.227.195.187.in-addr.arpa.
+16.102.59.186.in-addr.arpa.
+image2.pubmatic.com.
+photos-h.ak.fbcdn.net.
+124.4.51.190.in-addr.arpa.
+famintl.com.
+ksn7-12.kaspersky-labs.com.
+newsrss.bbc.co.uk.
+by2msg4010517.gateway.messenger.live.com.
+73.22.31.77.in-addr.arpa.
+smtp.ravensport.com.
+scripts.demandmedia.com.
+dieterpreiser.de.
+blog.mundoanuncio.com.
+157.254.146.190.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+on.nba.com.
+websoilsurvey.nrcs.usda.gov.
+mail.nvdevelop.ru.
+17.254.216.189.in-addr.arpa.
+160.78.220.189.in-addr.arpa.
+www.discomuseum.com.
+tzzs888.com.
+a.root-servers.net.
+www.bywifi.com.
+cust13538-2.in.mailcontrol.com.
+a5.sphotos.ak.fbcdn.net.
+www.runningafrica.com.
+creative.ak.fbcdn.net.
+24.255.41.177.in-addr.arpa.
+239.109.10.46.in-addr.arpa.
+www.filesonic.com.
+www.google.com.
+90.239.164.190.in-addr.arpa.
+alt1.aspmx.l.google.com.
+stats.norton.com.
+swcdn.apple.com.
+a.root-servers.net.
+apps.facebook.com.
+249.42.80.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.viglink.com.
+www.hostk.info.
+www.msftncsi.com.
+connect.facebook.net.
+shop.jayalders.com.
+www.ustream.tv.
+79.202.8.200.in-addr.arpa.
+geo-science.ch.
+events.unisfair.com.
+mail.reactionlab.com.
+46-courier.push.apple.com.
+one-chord-wonders.blogspot.com.
+www.facebook.com.
+yahoo.com.
+www.presentationmagazine.com.
+asm.sourceforge.net.
+hotmail.com.
+www.engadget.com.
+1stholistic.com.
+frdiscovery.hosting.sca.
+ws-cloud-msgplus.linkury.com.
+www.visitlawrence.com.
+whos.amung.us.
+cvtrust.org.
+news.google.co.il.
+www.cu-g.com.
+20minutos.feedsportal.com.
+123.110.72.50.in-addr.arpa.
+static.da.com.ar.
+takenaka.com.sg.
+a.root-servers.net.
+pes.liaofoo.com.
+16.230.86.200.in-addr.arpa.
+promotionalptnr.com.
+billing.sharo4ka.ru.
+ad.reachjunction.com.
+voipa.sip.yahoo.com.
+miepspb.ru.
+www.xboxlc.com.
+myexceltemplates.com.
+quyettri.com.
+elaviadorcapotado.blogspot.com.
+5.9.38.196.in-addr.arpa.
+s-static.ak.facebook.com.
+www.google-analytics.com.
+solocinehd.blogspot.com.
+lpcnb.com.
+a.root-servers.net.
+158.10.242.46.in-addr.arpa.
+contemplator.com.
+239.47.243.123.in-addr.arpa.
+tools.google.com.
+mail.chiefexecutive.com.
+26-courier.push.apple.com.
+www.facebook.com.
+pixel.facebook.com.
+pixel.facebook.com.
+arabia.msn.com.
+www.adshow.eu.
+platform.ak.fbcdn.net.
+_765_80_1.
+campeaoprovincias.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+sidler.de.
+www.google.com.mx.
+teredo.ipv6.microsoft.com.
+disqus.com.
+73.157.252.83.in-addr.arpa.
+e.miniclip.com.
+i4.ytimg.com.
+findgift.com.
+creative.ak.fbcdn.net.
+cnrit.tamu.edu.
+millerbranding.com.
+accounts.google.com.
+189.118.255.190.in-addr.arpa.
+www.bidhere.com.
+121.78.22.186.in-addr.arpa.
+chinanav.com.
+www.losratonesdepablo.com.
+youtu.be.
+ukfinancehouse.com.
+radar.meteo.be.
+metalwarez.com.
+grupogal.com.
+ns3.eu.editdns.net.
+s.youtube.com.
+google.com.
+ds.addthis.com.
+ns2.unity-web.ch.
+wearethelaw.tk.
+es-la.facebook.com.
+153.125.114.201.in-addr.arpa.
+66.66.30.190.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+plus.google.com.
+etaion.com.
+mainlinemedianews.com.
+koreamedicaltravel.com.
+rrppnet.com.ar.
+92.41.75.190.in-addr.arpa.
+somtel.com.
+www.radiomuseum.org.
+70.92.144.216.in-addr.arpa.
+www.thedavidlawrenceshow.com.
+the-vault-surf-target-maker.com.
+ksn2-12.kaspersky-labs.com.
+www.facebook.com.
+scallywagandvagabond.com.
+del.icio.us.
+bigblue.com.
+lb._dns-sd._udp.0.2.168.192.in-addr.arpa.
+a.root-servers.net.
+ar-ar.facebook.com.
+7.0.0.10.in-addr.arpa.
+lomassexxx.blogspot.com.
+www.rinconjuegos.com.
+platform.twitter.com.
+dlvr.it.
+video.google.com.
+_ldap._tcp.dc._msdcs.hospira.corp.
+w40kespecialista.blogspot.com.
+inblindinglights.com.
+img.iwasinturkey.com.
+profile.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+s0.2mdn.net.
+i3.ytimg.com.
+z.alimama.com.
+108.28.64.115.in-addr.arpa.
+row.bc.yahoo.com.
+244.32.252.173.in-addr.arpa.
+www.gamer.ne.jp.
+webpark.rutube.ru.
+um10.eset.com.
+static.ak.fbcdn.net.
+feeds.videosz.com.
+a.root-servers.net.
+79.156.16.70.in-addr.arpa.
+static.ak.facebook.com.
+kacharin.ru.
+skipoleposition.com.
+photos-f.ak.fbcdn.net.
+www.mattcardlefansite.co.uk.
+edge.quantserve.com.
+mbpvideo.com.
+dsn3.d.skype.net.
+by2msg3020215.gateway.messenger.live.com.
+www.gstatic.com.
+www.chinesecars.net.
+119.37.42.186.in-addr.arpa.
+www.starphone.com.ar.
+webspin-design.com.
+pixel.facebook.com.
+46.201.54.85.in-addr.arpa.
+103.199.168.192.in-addr.arpa.
+95.220.132.217.in-addr.arpa.
+www.iphone-girl.jp.
+sp.cwfservice.net.
+airbrakeapp.com.
+ofurotaimu.dreamwidth.org.
+pagead2.googlesyndication.com.
+me-cdn.effectivemeasure.net.
+www.google-analytics.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+dingtao333.3322.org.
+platform.ak.fbcdn.net.
+172.66.27.201.in-addr.arpa.
+www.new.facebook.com.
+108.183.135.211.in-addr.arpa.
+223.227.51.190.in-addr.arpa.
+116.111.110.186.in-addr.arpa.
+243.126.75.200.in-addr.arpa.
+8.169.49.190.in-addr.arpa.
+tiwitter.com.
+up7y:ri5p.71sv.
+a.root-servers.net.
+nationaled.net.mail10.psmtp.com.
+oascentral.crainsnewyork.com.
+z022.fma.fb.me.
+119.62.81.151.in-addr.arpa.
+ctcinsurance.com.
+a.root-servers.net.
+secure.thinkstockphotos.com.
+googleads.g.doubleclick.net.
+www.expedia.co.kr.
+a1.sphotos.ak.fbcdn.net.
+156.53.56.200.in-addr.arpa.
+www.facebook.com.
+img-cdn.mediaplex.com.
+252.232.189.190.in-addr.arpa.
+_546_77_4.
+buschmanpartners.com.
+9.82.125.186.in-addr.arpa.
+grupoarion.com.mx.
+profile.ak.fbcdn.net.
+37.148.23.95.in-addr.arpa.
+monstrobe.com.
+m.facebook.com.
+elite-servers.com.ua.
+tudecidesmedia.com.
+csi.gstatic.com.
+www.facebook.com.
+franelasarepa.blogspot.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+denis.stalker.h3q.com.
+63.93.70.208.in-addr.arpa.
+static.ak.fbcdn.net.
+vcs2.msg.yahoo.com.
+_754_86_4.
+www.hostingz.com.
+profile.ak.fbcdn.net.
+adventcomms.com.
+fbcdn-profile-a.akamaihd.net.
+developers.facebook.com.
+www.facebook.com.
+planes.pensiones.ley.com.es.
+sp.cwfservice.net.
+upakkom.ru.
+televisa.esmas.com.
+capacidadesespeciales.blogspot.com.
+gablesigns.com.s8b1.psmtp.com.
+www.youtube.com.
+a.root-servers.net.
+mail.cablelite.com.
+doma-konsult.ru.
+a.root-servers.net.
+webserver4.pjq.ok.cl.
+kircherlandscape.blogspot.com.
+e4.ny.us.ibm.com.
+www.google-analytics.com.
+www.webshaper.com.my.
+a.root-servers.net.
+standard.image.draw.spankapps.com.
+a8.sphotos.ak.fbcdn.net.
+mail.google.com.
+t3.gstatic.com.
+safebrowsing.clients.google.com.
+click.infospace.com.
+bmsapedyuxz.org.
+facebook.com.
+pixel.quantserve.com.
+a.root-servers.net.
+s2.youtube.com.
+a7.sphotos.ak.fbcdn.net.
+tradebox.ru.
+mchsi.com.
+28.18.230.190.in-addr.arpa.
+a.root-servers.net.
+proxy.promenergoresurs.ru.
+www.indavideo.hu.
+king.jetztspielen.de.
+a.c-0.19-230fa081.8110000.1518.19d3.3ea1.210.0.3t5zbpee7lm5hpbj4udp5m4ql6.avqs.mcafee.com.
+pt-br.facebook.com.
+www.gstatic.com.
+s.xvideos.com.
+a7.sphotos.ak.fbcdn.net.
+125.161.0.24.in-addr.arpa.
+16.9.47.201.in-addr.arpa.
+241.39.121.200.in-addr.arpa.
+multi.xnxx.com.
+www.stopbadware.org.
+pascal-descharmes.fr.
+graph.facebook.com.
+95.228.31.190.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+92.167.29.78.in-addr.arpa.
+simpsongeneralhospital.com.
+bartowregional.com.
+rpmusic.com.
+113.1.95.184.in-addr.arpa.
+b.scorecardresearch.com.
+fbcdn-profile-a.akamaihd.net.
+gnnchannel.com.
+129.25.161.201.in-addr.arpa.
+aa.online-metrix.net.
+energiadeluz.com.
+216.9.36.187.in-addr.arpa.
+www.tecnomed2000.com.
+i1.ytimg.com.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+byfiles.storage.msn.com.
+bezar.ru.
+teredo.ipv6.microsoft.com.
+aha.msk.su.
+a.root-servers.net.
+107.117.64.75.in-addr.arpa.
+www.facebook.com.
+www.mdgfog.com.
+peter.com.
+beringov-proliv.ru.
+a756.r.akamai.net.
+cactusmat.com.
+12.65.52.201.in-addr.arpa.
+mail.philharmonia.spb.ru.
+googleads.g.doubleclick.net.
+t1.gstatic.com.
+osalotteries.net.
+nitrato-lirico.blogspot.com.
+v8.nonxt7.c.youtube.com.
+mail.organic-shop.ru.
+ads.admarvel.com.
+couponbuddy.s3.amazonaws.com.
+www.wwl.com.
+photos-b.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+www.rutschmann.biz.
+es.wikipedia.org.
+bbvaganadero1.bbva.com.co.
+realty.mail.ru.
+aquienaguas.com.
+zamunda.net.
+169.138.106.186.in-addr.arpa.
+europe.perf.glbdns.microsoft.com.
+a.root-servers.net.
+psgw.t-mobilesgws.com.
+a15.t26.net.
+mail.sacramentointernet.com.
+a.root-servers.net.
+s108.filesonic.com.
+86.140.176.190.in-addr.arpa.
+8ejb1eqrb.25zf.
+99.91.44.190.in-addr.arpa.
+ad.smowtion.com.
+200.13.153.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+235.72.31.80.in-addr.arpa.
+es.wikipedia.org.
+cpsfx.com.
+www.asian-boy-bondage.com.
+46.85.191.186.in-addr.arpa.
+pt-br.facebook.com.
+174.219.226.95.in-addr.arpa.
+buy.norton.com.
+secure.wlxrs.com.
+fbcdn-sphotos-a.akamaihd.net.
+nasascience.nasa.gov.
+merckx-nv.be.
+appenda.com.
+www.google-analytics.com.
+185.33.159.190.in-addr.arpa.
+73.238.191.189.in-addr.arpa.
+promo.meetatranny.com.
+pop3.live.com.
+a1814.g.akamai.net.
+a2.sphotos.ak.fbcdn.net.
+dns.msftncsi.com.
+suscom-main.net.
+ads.us.e-planning.net.
+www.gazzetta.it.
+www.stopbadware.org.
+www.happycow.net.
+analogmachine.com.
+www.myspacegens.com.
+europe.worldtraveler.biz.
+a4.sphotos.ak.fbcdn.net.
+ww2.nf.outerinfo.net.
+a.root-servers.net.
+a.root-servers.net.
+accounts.google.com.mx.
+66.130.255.222.in-addr.arpa.
+lobotuerto.com.
+creative.ak.fbcdn.net.
+l.yimg.com.
+cityofripon.org.
+homesteadlandscaping.com.
+connect.facebook.net.
+fbcdn-sphotos-a.akamaihd.net.
+khabarovsk.telephone.ru.
+mail.gmhca.com.
+www.facebook.com.
+www.doazafrandelamancha.com.
+laprincipianta.blogspot.com.
+chat.facebook.com.
+49.212.85.209.zen.spamhaus.org.
+fortax.ch.
+gospelmusicchannel.edgesuite.net.
+153.124.49.190.in-addr.arpa.
+post.centro.ru.
+nuestras.frasesdeface.net.
+www.google-analytics.com.
+mail2.sinclairresearch.com.
+chintels.com.
+nl.pollypocket.com.
+www.pixelpraise.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+119.247.119.75.in-addr.arpa.
+www.geeky-gadgets.com.
+www.senia.com.
+id.l.google.com.
+metrix.511tactical.com.
+tracker.bittorrent.am.
+mail.rwandair.com.
+google-analytics.com.
+mail.google.com.
+a1.sphotos.ak.fbcdn.net.
+83.186.101.78.in-addr.arpa.
+ak.imgfarm.com.
+197.36.52.186.in-addr.arpa.
+listen.grooveshark.com.
+a7.sphotos.ak.fbcdn.net.
+m.addthisedge.com.
+lumpeny.com.
+71.60.191.190.in-addr.arpa.
+instagram.com.
+beta.stun.voice.yahoo.com.
+mxa-0006fb01.gslb.pphosted.com.
+btonternet.com.
+100.33.148.58.in-addr.arpa.
+messenger.hotmail.com.
+www.gregbyng.com.
+abutik.hu.
+200.252.34.186.in-addr.arpa.
+ekaterinka.orthodoxy.ru.
+js.wlxrs.com.
+i3.ytimg.com.
+csi.gstatic.com.
+www.afrik-cuisine.com.
+platform.ak.fbcdn.net.
+cm.g.doubleclick.net.
+0-jx-w.channel.facebook.com.
+ns.neptun.spb.ru.
+adoholik.com.
+www.shubertticketing.com.
+sportshunter.eu.
+argentinahistorica.com.ar.
+agenbolaa.nuke.im.
+112.219.86.186.in-addr.arpa.
+blackvelvet.comastuff.com.
+www.facebook.com.
+188.250.78.74.in-addr.arpa.
+chmail.tecan.com.
+mail.carter.ru.
+download115.avast.com.
+a4.sphotos.ak.fbcdn.net.
+mail.regtime-k.ru.
+checkip.dyndns.org.
+afe.specificclick.net.
+mail1.sharafdg.com.
+sar.ws.kaleidescape.com.
+www.femeba.org.ar.
+www.alarabiya.net.
+a6.sphotos.ak.fbcdn.net.
+www.wwfca.org.
+16.118.51.190.in-addr.arpa.
+204.50.35.89.in-addr.arpa.
+_840_88_9.
+mail.safeinformationgroup.com.
+133.86.251.111.in-addr.arpa.
+creative.ak.fbcdn.net.
+a.root-servers.net.
+abuelos-manchegos.blogspot.com.
+photos-d.ak.fbcdn.net.
+_883_36_4.
+i.fr.imwx.com.
+mail.digitalsunrise.com.
+d2057300.instant.xoom.it.
+bl59naigc.z55v2e6t.
+search.pontofrio.com.br.
+csi.gstatic.com.
+reastructuralengineers.com.
+193.187.240.82.in-addr.arpa.
+googleads.g.doubleclick.net.
+adm-druckmedien.de.
+www.google.com.
+i4.ytimg.com.
+ads.yimg.com.
+vp.sip.messenger.msn.com.
+hitext.ru.
+www.google-analytics.com.
+creative.ak.fbcdn.net.
+www.iegallery.com.
+wpad.
+wpad.hotspot.
+s-static.ak.facebook.com.
+fbcdn-sphotos-a.akamaihd.net.
+181.223.155.189.in-addr.arpa.
+camcor.ru.
+fxfeeds.mozilla.com.
+168.137.12.118.in-addr.arpa.
+checkip.dyndns.org.
+118.162.255.201.in-addr.arpa.
+ocsp.thawte.com.
+s-static.ak.fbcdn.net.
+www.youtube.com.
+www.webcamscaseras.info.
+mail.ccli.co.uk.
+vivalaleydeltemor.blogspot.com.
+sites.google.com.
+ns1.cafe24.com.
+platform.twitter.com.
+mailgateway.studiobana.it.
+www.caughtpeeing.info.
+static.ak.fbcdn.net.
+106.89.161.113.in-addr.arpa.
+www.y8.com.
+rya.rockyou.com.
+69.107.10.46.in-addr.arpa.
+blog.mesmo.tv.
+185.232.226.202.in-addr.arpa.
+casa-italia.immobiliare.it.
+www.facebook.com.
+ec2-50-19-163-62.compute-1.amazonaws.com.
+errors.jawaker.com.
+kaplowe.com.
+d2105488.xoom.it.
+msn.com.
+7.226.149.213.in-addr.arpa.
+tc.v22.cache7.googlevideo.com.
+173.69.204.130.in-addr.arpa.
+www.ccchp-isys.edu.pa.
+244.195.157.186.in-addr.arpa.
+www.dvd-explorer.org.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+e4805.b.akamaiedge.net.
+cnref.com.s5a1.psmtp.com.
+safebrowsing.clients.google.com.
+camera1.mairie-brest.fr.
+api.oovoo.com.
+kanto.machi.to.
+accounts.google.com.
+es.answers.yahoo.com.
+ziafog.com.
+237.210.132.189.in-addr.arpa.
+gtamexico.com.
+4:hdifftw.92vi.
+46.234.94.190.in-addr.arpa.
+i4.ytimg.com.
+18.214.112.126.in-addr.arpa.
+a.root-servers.net.
+guiacinefila.com.
+3.140.69.189.in-addr.arpa.
+ftk.dk.
+medienhaus.nuggad.net.
+store.gcsis-apple.com.akadns.net.
+_155_62_1.
+apps.facebook.com.
+73.85.168.192.in-addr.arpa.
+www1.euro.dell-cidr.akadns.net.
+www.facebook.com.
+static.ak.fbcdn.net.
+222.168.232.190.in-addr.arpa.
+ecs.k12.ny.us.
+www.socialgrowthtechnologies.com.
+xxramneekxx.tumblr.com.
+i2.ytimg.com.
+95.177.102.201.in-addr.arpa.
+a.root-servers.net.
+protontech.com.
+csi.web.aol.com.
+connect.facebook.net.
+a.root-servers.net.
+c1.microsoft.com.
+b.vimeocdn.com.
+a4.sphotos.ak.fbcdn.net.
+newsrss.bbc.co.uk.
+125.197.172.199.in-addr.arpa.
+laotramitadelaverdad.nixiweb.com.
+safebrowsing-cache.google.com.
+www.facebook.com.
+mail.pycnogenol.com.
+teredo.ipv6.microsoft.com.
+es-la.facebook.com.
+clients2.google.com.
+q-love.ru.
+www.fimkastore.com.
+ejabat.google.com.
+dns.msftncsi.com.
+185.209.46.190.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+149.4.168.192.in-addr.arpa.
+ad-g.doubleclick.net.
+ddcm.wildtangent.com.
+distritofederal.olx.com.mx.
+www.thehairbowcompany.com.
+www.wubisheng.cn.
+www.google.com.
+gatvolinoman.blogspot.com.
+a.root-servers.net.
+.
+238.230.240.94.in-addr.arpa.
+www.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+assda.com.
+shiva.grozny.ru.
+genkienglish.net.
+secure.shared.live.com.
+seguros-automovil.mascoche.net.
+victorianus.com.
+74.244.253.190.in-addr.arpa.
+banners2.hollywoodaffiliates.com.
+protechnics.com.
+www.scopemed.org.
+blog.corporationwiki.com.
+i3.ytimg.com.
+244.83.144.187.in-addr.arpa.
+simplelifecorp.com.
+static.ak.fbcdn.net.
+htdogs.ru.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+42.213.26.216.in-addr.arpa.
+breakingmedia.com.
+fxfeeds.mozilla.com.
+gvnvbbpev.i51i0n3x.
+goldliger.evplayer.com.
+iklancoffee.blogspot.com.
+safepages.com.s6a2.psmtp.com.
+22.126.111.219.in-addr.arpa.
+commsoft.net.s8a2.psmtp.com.
+1xt1xik3b.65ct.
+237.183.131.190.in-addr.arpa.
+www.monitos.cl.
+www.ratteb.com.
+www.lifeinsurancechandigarh.com.
+router.infolinks.com.
+147.212.139.98.bl.spamcop.net.
+us.f1814.mail.yahoo.com.
+4.bp.blogspot.com.
+kut258r94.o01u8a6r.
+www.fhg.ladyboycandyshop.com.
+bl163w.blu163.mail.live.com.
+worldwildnessweb.blogspot.com.
+crl.microsoft.com.
+hipservice.live.com.
+connect.facebook.net.
+mail3.enorthfield.com.
+www.bcrae.es.
+dsn6.d.skype.net.
+www.celebboutique.com.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+mail.walshalbert.com.
+google.com.
+ar.ika-world.com.
+www.facebook.com.
+a.root-servers.net.
+www.facebook.com.
+241.134.144.187.in-addr.arpa.
+mail.spoon.org.
+time.chttl.com.tw.
+pedos.com.ar.
+click2.info.
+plusone.google.com.
+fbcdn-profile-a.akamaihd.net.
+apcarolinas.com.
+51.210.21.201.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+streetbundy.blogspot.com.
+yibrq4rmn.d64l7j1y.
+www.facebook.com.
+139.0.181.189.in-addr.arpa.
+215.84.156.187.in-addr.arpa.
+js.revsci.net.
+fr-talk.kakao.com.
+nightside.ksl.com.
+82.96.160.190.in-addr.arpa.
+rss.cnn.com.
+www.conocewordpress.com.
+toolbarqueries.google.com.
+www.investors.ups.com.
+1991.com.
+rwhois.net.
+www.google.com.
+www.google.com.
+a.root-servers.net.
+a.root-servers.net.
+25-courier.push.apple.com.
+mob.adwhirl.com.
+ic.s1.qzone.qq.com.
+profile.ak.fbcdn.net.
+twitter.co.
+l.yimg.com.
+168.225.126.200.in-addr.arpa.
+edge.quantserve.com.
+activesync.hot.glbdns.microsoft.com.
+www.google.com.
+a4.mzstatic.com.
+translate.google.com.
+www.google.com.
+plusone.google.com.
+sp.cwfservice.net.
+static.ak.fbcdn.net.
+developers.facebook.com.
+stitcheree.com.
+feeds.101cookbooks.com.
+ronacom.ru.
+yaahooo.ru.lan.
+vip.tracker.thepiratebay.org.
+228.126.90.189.in-addr.arpa.
+_440_07_5.
+mx.answers.yahoo.com.
+checkip.dyndns.com.
+gdata.youtube.com.
+photos-g.ak.fbcdn.net.
+firstdatabank.com.s7a1.psmtp.com.
+androidwallpaper.org.
+basslake.com.s8a1.psmtp.com.
+sites.vnuexhibitions.com.
+ib.adnxs.com.
+archive.wgnradio.com.
+28-courier.push.apple.com.
+entela.com.
+ad.adnetwork.net.
+123.94.232.190.in-addr.arpa.
+android.clients.google.com.
+www.e-ir.info.
+www.perfectweb.ro.
+time.windows.com.
+del.icio.us.
+2822.v.fwmrm.net.
+180.63.25.83.in-addr.arpa.
+www.streethandball.com.
+sn127w.snt127.mail.live.com.
+data.flurry.com.
+sp.cwfservice.net.
+www.google.com.mx.
+teredo.ipv6.microsoft.com.
+99.224.138.201.in-addr.arpa.
+www.facebook.com.
+www.google.com.
+es.wikiquote.org.
+a.root-servers.net.
+dinamicasvivenciales.blogspot.com.
+www.ipolitics360.com.
+0.4403013.com.
+static.ak.fbcdn.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+_622_01_9.
+joesixpack.net.
+gomortgageconcepts.com.
+bcinnkeepers.com.mail1.psmtp.com.
+michaelanthony.co.uk.
+apis.google.com.
+quieresadelgazar.tonykamo.com.
+www.facebook.com.
+55.218.180.180.in-addr.arpa.
+before-and-after-pics.com.
+63.141.129.189.in-addr.arpa.
+96.105.248.201.in-addr.arpa.
+efu.org.ua.
+login.live.com.
+www.youtube.com.
+46.223.74.201.in-addr.arpa.
+pankhurst.com.
+www.facebook.com.
+grannytubexxx.com.
+66.34.213.194.in-addr.arpa.
+gtp.ru.
+a.root-servers.net.
+denis.stalker.h3q.com.
+mail.
+73.236.178.186.in-addr.arpa.
+dns.msftncsi.com.
+34.9.157.187.in-addr.arpa.
+g-ecx.images-amazon.com.
+0-id-w.channel.facebook.com.
+www.woolandthegang.com.
+yahoo.com.
+1.0.0.127.in-addr.arpa.
+dm.ie.sogou.com.
+www.google.com.
+api.twitter.com.
+tcadops.leshebdos.com.
+www.monografias.com.
+sbs-solicitors.co.uk.
+8k8uznxyk.l61t7h0t.
+googleads.g.doubleclick.net.
+animeymanga4forever.foroactivo.com.
+140.180.86.85.in-addr.arpa.
+246.123.75.201.in-addr.arpa.
+telemedia.com.
+hcd-inc.com.
+n18.8-d.com.
+www.foroactivo.com.
+215.212.28.189.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+redirector.aaanet.ru.
+mwgxfzgzhyd40a47ltiqp22lygwnqcubvcy.biz.
+7.52.162.189.in-addr.arpa.
+im79.vk.com.
+gmll.com.
+p08-bookmarks.icloud.com.
+www.facebook.com.
+profile.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+members.dyndns.org.
+dama-de-agua.blogspot.com.
+teredo.ipv6.microsoft.com.
+swalif.net.
+20.50.169.118.in-addr.arpa.
+peru.ahk.de.
+csm.com.
+kuf.biglobe.ne.jp.
+encrypted-tbn0.google.com.
+a.root-servers.net.
+www.google.com.
+wpad.belkin.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+70.172.74.187.in-addr.arpa.
+developers.facebook.com.
+_200_46_7.
+www.16valvulas.com.ar.
+col.stc.s-msn.com.
+library.skillport.com.
+236.207.14.187.in-addr.arpa.
+www.allsaints.com.
+safebrowsing.clients.google.com.
+sites.google.com.
+pixel.facebook.com.
+101.153.138.187.in-addr.arpa.
+ct5:4y9rs.48jf.
+126.83.34.83.in-addr.arpa.
+horoscopos.prodigy.msn.com.
+www.historama.com.
+150.177.90.2.in-addr.arpa.
+ca-fr.norton.com.
+www.unixmanga.com.
+ad.adserverplus.com.
+ad-g.doubleclick.net.
+noemozica.files.wordpress.com.
+www.facebook.com.
+105.1.168.192.in-addr.arpa.
+www.facebook.com.
+s649.photobucket.com.
+mup.asu.edu.
+mail.firedog.cc.
+74.250.145.187.in-addr.arpa.
+ef.ewf.
+colunistas.ig.com.br.
+o.analytics.yahoo.com.
+photos-b.ak.fbcdn.net.
+img226.imagevenue.com.
+grgfood.com.
+a1325.phobos.apple.com.
+mx.msn.recepedia.com.
+160.66.114.190.in-addr.arpa.
+ipv6.msftncsi.com.
+srx.main.ebayrtm.com.
+talking-tom-cat.softonic.fr.
+standnow.org.
+i4.ytimg.com.
+www.radiomodelos.com.mx.
+orientexpress.forumcommunity.net.
+dnl-01.geo.kaspersky.com.
+nextramail.hu.
+192.152.29.70.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+webcache.googleusercontent.com.
+sru.ru.
+photos-b.ak.fbcdn.net.
+236.175.14.189.in-addr.arpa.
+www.smutdvds.com.
+static.ak.facebook.com.
+_662_98_2.
+0-jj-w.channel.facebook.com.
+multi.xnxx.com.
+190.184.241.92.in-addr.arpa.
+um10.eset.com.
+wpad.
+217.178.140.201.in-addr.arpa.
+www.autoepc.net.
+a.root-servers.net.
+120.153.212.201.in-addr.arpa.
+hightech-redneck.com.
+www.shy-models.org.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+translate.google.com.mx.
+acap.it.
+108.90.90.84.in-addr.arpa.
+hi5.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+24.233.35.177.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.vh1la.com.
+ads.themxua.net.
+aplisic.iese.edu.
+creative.ak.fbcdn.net.
+www.lasorquideashotel.com.
+cn1.redswoosh.akadns.net.
+mayaweb.upr.clu.edu.
+69.71.66.184.in-addr.arpa.
+wakmc.com.
+mohawk-radio.com.
+www.adbrite.com.
+lapaz-bajacaliforniasur.olx.com.mx.
+www.freeotoscript.com.
+a.root-servers.net.
+orttool.com.s7b2.psmtp.com.
+photos-d.ak.fbcdn.net.
+toolbarqueries.google.com.
+_ldap._tcp.
+nniline.naver.com.
+api.facebook.com.
+aspmx.l.google.com.
+69.227.131.189.in-addr.arpa.
+www.google.co.
+www.youtube-nocookie.com.
+photos-f.ak.fbcdn.net.
+dnn506yrbagrg.cloudfront.net.
+gdata.youtube.com.
+goamtel.com.
+swohio.twcbc.com.
+187.16.161.189.in-addr.arpa.
+i3.ytimg.com.
+pixel.facebook.com.
+179.82.231.189.in-addr.arpa.
+api.twitter.com.
+lasrecetasdesuli.blogspot.com.
+www5.tranexp.com.
+65.231.82.189.in-addr.arpa.
+www.archive.org.
+sourceforge.net.dnsbl7.mailshell.net.
+img129.imageshack.us.
+www.ambysoft.com.
+monchyvariedadesenfieltro.blogspot.com.
+photos-b.ak.fbcdn.net.
+prod2.rest-notify.msg.yahoo.com.
+a.root-servers.net.
+66.153.175.190.in-addr.arpa.
+si0.twimg.com.
+khm0.google.com.
+gmail.com.
+167.6.217.87.in-addr.arpa.
+metsco.com.
+a5.sphotos.ak.fbcdn.net.
+static.ak.connect.facebook.com.
+developers.facebook.com.
+196.72.75.201.in-addr.arpa.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+api.twitter.com.
+136.204.224.24.in-addr.arpa.
+benning.army.mil.
+horoscopos.euroresidentes.es.
+sawdustmaking.com.
+akitacopy.com.
+i48.tinypic.com.
+router.tlvmedia.com.
+benkovitz.com.
+a.root-servers.net.
+apps.facebook.com.
+205.168.57.186.in-addr.arpa.
+158.17.11.186.in-addr.arpa.
+img.babylon.com.
+photos-a.ak.fbcdn.net.
+85.43.24.189.in-addr.arpa.
+45.166.171.201.in-addr.arpa.
+clients1.google.com.
+184.2.219.85.in-addr.arpa.
+islambuddhism.com.
+65.189.241.60.in-addr.arpa.
+0sxx.com.
+platform.twitter.com.
+cm.g.doubleclick.net.
+a.root-servers.net.
+build.last.fm.
+133.204.184.88.in-addr.arpa.
+www.facebook.com.
+34.31.93.200.in-addr.arpa.
+131.97.161.189.in-addr.arpa.
+concilioshekinah.org.
+a.root-servers.net.
+76.190.10.201.in-addr.arpa.
+www.facebook.com.
+mail.cs181.xqx.cn.
+a8.sphotos.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ranking-view-c01.u0.np.community.playstation.net.
+fbcdn-photos-a.akamaihd.net.
+41.162.171.200.in-addr.arpa.
+golyon.com.
+www.scrumalliance.org.
+34.179.97.190.in-addr.arpa.
+gfx1.hotmail.com.
+a.root-servers.net.
+www.cbsinteractive.com.
+photos-d.ak.fbcdn.net.
+142.149.41.71.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+inbound.aabinc.net.netsolmail.net.
+disneyworldforum.disney.go.com.
+iappraise.com.
+www.googleadservices.com.
+up.rabe7.com.
+www.funtal.com.
+stankobank.ru.
+images.scanalert.com.
+ocsp.comodoca.com.
+www.sqm.microsoft.com.
+youtube-ui.l.google.com.
+230.115.125.186.in-addr.arpa.
+s3.buysellads.com.
+austin.slcs.slb.com.
+ksn6-12.kaspersky-labs.com.
+205.224.117.42.in-addr.arpa.
+lh6.ggpht.com.
+www.googleadservices.com.
+dj-nia.com.
+a5.sphotos.ak.fbcdn.net.
+broadband.cnet.com.au.
+www.masquefutbol.com.
+95.196.8.200.in-addr.arpa.
+media.victoriassecret.com.
+clients1.google.com.
+essensualsasia.com.
+www.christiansalerno.com.
+www.statcounter.com.
+yubless.org.
+a7.sphotos.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+204.79.18.76.in-addr.arpa.
+www.ticotimes.net.
+www.actionsprite.com.
+static.chartbeat.com.
+aspmx.spamjadoo.com.
+i4.ytimg.com.
+fezgu.com.
+www.sky4energy.com.
+ps.palmws.com.
+lkh-hoergas.at.
+e-mails.ru.
+spamassassin.idgcomm.com.
+22.183.121.84.in-addr.arpa.
+_086_72_7.
+a1.sphotos.ak.fbcdn.net.
+235.246.15.8.in-addr.arpa.
+a.root-servers.net.
+tebnfi.com.
+200.78.132.189.in-addr.arpa.
+zrein.artician.com.
+a1.sphotos.ak.fbcdn.net.
+developers.facebook.com.
+search.vuze.com.
+d2098724.xoom.it.
+www.ripleysthailand.com.
+azle.esc11.net.
+www.monitor.net.
+soulwire.co.uk.
+www.facebook.com.
+photos-e.ak.fbcdn.net.
+terceracultura.cl.
+bluepyramid.org.
+gallery.sourceforge.net.
+a749.g.akamai.net.
+24.90.55.65.psbl.surriel.com.
+cookex.amp.yahoo.com.
+th-p14.talk.kakao.co.kr.
+161.56.194.190.in-addr.arpa.
+safebrowsing.cache.l.google.com.
+connect.facebook.net.
+candymania.com.
+static.ak.fbcdn.net.
+time.chttl.com.tw.
+a1404.w41.akamai.net.
+104.202.48.186.in-addr.arpa.
+1212yahoo.com.
+www.facebook.com.
+3.242.18.177.in-addr.arpa.
+ad.smowtion.com.
+telstra.com.
+reggaetrain.com.
+www.upload2world.com.
+search.4shared.com.
+168.214.141.27.in-addr.arpa.
+relianceengineers.com.
+css.wlxrs.com.
+twitter.com.
+sp.cwfservice.net.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+www.basketball-bundesliga.de.
+7.224.160.193.in-addr.arpa.
+speedy.imo.im.
+profile.ak.fbcdn.net.
+izhauto.ru.
+energuia.com.
+nations.widmi.com.
+83.190.209.201.in-addr.arpa.
+www.facebook.com.
+a6.sphotos.ak.fbcdn.net.
+kalamullah.com.
+246.187.159.189.in-addr.arpa.
+s94.cnzz.com.
+e3646.b.akamaiedge.net.
+roband.com.
+profile.ak.fbcdn.net.
+61.232.39.187.in-addr.arpa.
+s21.bitshare.com.
+new.zveroforma.ru.
+www.pinkmgp.com.
+9.155.26.24.in-addr.arpa.
+a4.da1.akamai.net.
+pottermorewatch.tumblr.com.
+imshop.com.ru.
+pt-br.facebook.com.
+9.192.20.81.in-addr.arpa.
+resimail.beachfrontonline.com.
+165.107.91.186.in-addr.arpa.
+159.26.84.200.in-addr.arpa.
+cdn.lfstmedia.com.
+content.yieldmanager.edgesuite.net.
+external.ak.fbcdn.net.
+go.srvnow.com.
+mail2.hoksve.com.
+clients4.google.com.
+external.ak.fbcdn.net.
+www.inbursa.com.mx.
+tacoda.at.atwola.com.
+www.thestreet.com.
+www.bighdesign.com.
+mencey-al-mo.blogspot.com.
+au.download.windowsupdate.com.
+lanoire.wikia.com.
+www.facebook.com.
+m.ak.fbcdn.net.
+74.90.123.189.in-addr.arpa.
+i1.ytimg.com.
+a7.sphotos.ak.fbcdn.net.
+www.plusnetwork.com.
+s1.tanoth.com.mx.
+freudenberg-nw.com.
+motorcyclephilippines.com.
+img4.ask.fm.
+www.facebook.com.
+crl.verisign.net.
+mail.navcanada.ca.
+apis.google.com.
+www.witchhut.com.
+pop.180com.net.
+breedclub.ru.
+www13.0zz0.com.
+droidsecurity.appspot.com.
+g.microsoft.com.
+js.wlxrs.com.
+lists.xmission.com.
+already.com.
+.
+_ldap._tcp.
+115.158.115.140.in-addr.arpa.
+runonce.msn.com.
+intali.ru.
+www.facebook.com.
+www.oniichannoecchi.com.
+40.36.162.189.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+datingtools.spacash.com.
+images.hotnewnet.com.
+59.238.31.161.in-addr.arpa.
+c143528.memecenter.com.
+206.108.252.201.in-addr.arpa.
+158.144.112.212.in-addr.arpa.
+img.imobiletube.com.
+187.8.121.59.in-addr.arpa.
+googleads.g.doubleclick.net.
+test-rt.liftdna.com.
+photos-b.ak.fbcdn.net.
+239.202.8.200.in-addr.arpa.
+smtp5.smart.com.ph.
+eldoradofurniture.com.
+www.unrisd.org.
+player.radio.com.
+138.120.65.217.in-addr.arpa.
+translate.google.com.mx.
+mail.
+v14.nonxt2.c.youtube.com.
+josemariomourinho.com.
+www.entreprisescanada.ca.
+www.lacoteimmo.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+js.wlxrs.com.
+140.41.173.190.in-addr.arpa.
+achusnetgolf.com.
+www.visitehoteles.com.
+eloff.net.
+i2.ytimg.com.
+www.bywifi.com.
+ksn2-12.kaspersky-labs.com.
+unlibroabierto.tumblr.com.
+ad.yieldmanager.com.
+175.30.188.190.in-addr.arpa.
+pschmid.net.
+0.gravatar.com.
+vicentelopez0.tripod.com.
+www.solarsolar.com.au.
+www.apple.com.
+partner.googleadservices.com.
+www.gigisapparel.com.
+docs.google.com.
+images.scanalert.com.
+telodigo.com.
+stereosvit.ua.
+profile.ak.fbcdn.net.
+rcp.eu.blackberry.com.
+www.carsmexico.com.
+www.pubmedcentral.nih.gov.
+static2.dmcdn.net.
+d2.zedo.com.
+checkip.dyndns.org.
+photos-a.ak.fbcdn.net.
+175.220.31.190.in-addr.arpa.
+67.126.240.123.in-addr.arpa.
+atyourcervix.blogspot.com.
+safebrowsing.clients.google.com.
+www.google.com.
+husky.courant2.com.
+tcp.sagepub.com.
+correo.almacenes-si.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+ad.adnetwork.net.
+12.104.20.190.in-addr.arpa.
+graph.facebook.com.
+toolbarqueries.google.com.
+s-static.ak.facebook.com.
+_247_17_2.
+www3.zero-animation.net.
+smretina.s3.amazonaws.com.
+sevastopol.su.
+hiphop-ejay.softonic.com.
+i.imgur.com.
+solucionesbook.blogspot.com.
+ksn2-12.kaspersky-labs.com.
+kr.ec21.com.
+apps.facebook.com.
+a749.g.akamai.net.
+www.rapesin.com.
+www.leopardtrek.lu.
+a.root-servers.net.
+bfbc2.gos.ea.com.
+plus.google.com.
+platform.ak.fbcdn.net.
+developers.facebook.com.
+243.77.47.24.in-addr.arpa.
+234.8.55.157.in-addr.arpa.
+tools.google.com.
+stonesoft.com.
+download.microsoft.com.
+www.osl.no.
+78.245.105.119.in-addr.arpa.
+www.atbholidays.com.
+sanmiguel.mundoanuncio.cr.
+api.twitter.com.
+ar-ar.facebook.com.
+41.41.222.77.in-addr.arpa.
+www.travian.com.mx.
+dns.msftncsi.com.
+strollinfield.com.
+newsrss.bbc.co.uk.
+r._dns-sd._udp.lan.
+inf.sup.ru.
+corazondepoeta.obolog.com.
+api.twitter.com.
+ec2-50-16-50-154.compute-1.amazonaws.com.
+actsys.ru.
+243.205.225.190.in-addr.arpa.
+updatekeepalive.mcafee.com.
+apis.google.com.
+www.zmovie.tv.
+text.lan.
+www.softonic.com.
+smtp.gs-development.com.
+www.google.com.
+mx1.kcnet.org.
+36.23.90.186.in-addr.arpa.
+www.morphuk.com.
+sp.cwfservice.net.
+31.3.69.189.in-addr.arpa.
+global.ard.yahoo.com.
+profile.ak.fbcdn.net.
+i2.ytimg.com.
+a.root-servers.net.
+google.com.
+www.iriver.com.au.
+update.messenger.yahoo.com.
+_537_69_1.
+forbesbowman.com.
+webmail-ru.bul.net.
+w393jvnvr.t06l8i9s.
+profile.ak.fbcdn.net.
+www.kt.com.
+sfiles.d1g.com.
+www.doncellabeach.com.
+comocrecer.netfirms.com.
+30.211.27.194.in-addr.arpa.
+163.248.53.201.in-addr.arpa.
+enciclopedia.us.es.
+static.ak.fbcdn.net.
+ksn7-12.kaspersky-labs.com.
+webimgs.bevnet.com.
+pes6-club.pesgame.net.
+zone20.hotwords.com.br.
+95.155.23.186.in-addr.arpa.
+mrbursnuclearplant.blogspot.com.
+tima-xtreme.com.
+nokia-maps.softonic.com.
+v574.vkadre.ru.
+in.penguingroup.com.
+creaciones5semestre.blogspot.com.
+51.68.238.189.in-addr.arpa.
+lm.pcworld.com.
+connect.facebook.net.
+fbcdn-sphotos-a.akamaihd.net.
+www.google.com.
+s0.2mdn.net.
+sp.cwfservice.net.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+20.228.171.69.in-addr.arpa.
+mail-server.finist.ru.
+g.msn.com.
+148.32.134.188.in-addr.arpa.
+ael77kwzk.72bj.
+40.84.94.186.in-addr.arpa.
+img38.imageshack.us.
+a.root-servers.net.
+platform.twitter.com.
+www.youtube.com.
+_945_63_1.
+a.root-servers.net.
+a.root-servers.net.
+appframe.qq.com.
+bbshtml.shangdu.com.
+a.root-servers.net.
+exquisesensualite.blogspot.com.
+pt-br.facebook.com.
+time.chttl.com.tw.
+pagead2.googlesyndication.com.
+e566.b.akamaiedge.net.
+www.aggman.com.
+s0.2mdn.net.
+9.148.79.200.in-addr.arpa.
+144.36.134.190.in-addr.arpa.
+www.thenlpcompany.com.
+cl.msn.com.
+twitter.com.
+www.arzaworld.com.
+v2.cache7.c.youtube.com.
+geo.tp-cdn.com.
+ssl.gstatic.com.
+apps.facebook.com.
+e4805.b.akamaiedge.net.
+dt1pibe7d.01el.
+_453_58_7.
+hfmlegal.com.
+a-0.19-2309a081.c130083.1518.19d0.3ea1.210.0.sm6i6bzwl5spsqq1in31p8adb5.avqs.mcafee.com.
+googleads.g.doubleclick.net.
+static.ak.fbcdn.net.
+h.atdmt.com.
+meneame.wikispaces.com.
+nudeisfashion.wordpress.com.
+pixel.facebook.com.
+edge.quantserve.com.
+ajax.cloudflare.com.
+vesteon.en.alibaba.com.
+id.google.com.
+132.241.94.190.in-addr.arpa.
+112.120.43.190.in-addr.arpa.
+www.mozilla.com.
+time.chttl.com.tw.
+twitter.com.
+190.241.94.86.in-addr.arpa.
+www.wwe.com.
+www.untreueteens.com.
+112.173.240.201.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+www.johnsemper.com.
+cranepsych.edublogs.org.
+ib.adnxs.com.
+kote983vh.12dj.
+local-bay.contacts.msn.com.
+www.archizines.com.
+grijalva.house.gov.
+pyzizzle.com.
+tk2.greedland.net.
+developers.facebook.com.
+www.facebook.com.
+b._dns-sd._udp.lan.
+www.aapg.org.
+us-ads.openx.net.
+community.mtasa.com.
+google.com.
+boompa.ca.
+photos-d.ak.fbcdn.net.
+onevoicetech.com.
+242.79.14.187.in-addr.arpa.
+a2.mzstatic.com.
+pixel.invitemedia.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+emkegroup.ae.s200a2.psmtp.com.
+profile.ak.fbcdn.net.
+eledoz.ru.
+connect.facebook.net.
+tap2-cdn.rubiconproject.com.
+tools.google.com.
+www.google-analytics.com.
+vivendiwater.com.
+ksn1-12-part1.kaspersky-labs.com.
+s.youtube.com.
+www.addthis.com.
+26.195.135.66.in-addr.arpa.
+mpp.cpii.com.
+116.52.50.190.in-addr.arpa.
+hotcd.ru.
+animeid.com.
+lesbians.ru.
+tdy.prodigy.msn.com.
+248.228.78.195.in-addr.arpa.
+i4.ytimg.com.
+a.root-servers.net.
+www.blogger.com.
+a.root-servers.net.
+checkout1.gulfnews.com.
+www.casapilo.es.
+246.216.127.84.in-addr.arpa.
+cdn.qbo.intuit.com.
+www.update.microsoft.com.
+teredo.ipv6.microsoft.com.
+a6.sphotos.ak.fbcdn.net.
+armmf.adobe.com.
+a.root-servers.net.
+www.automobilesnews.com.
+tinypic.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+s2.youtube.com.
+login.live.com.
+a5.sphotos.ak.fbcdn.net.
+servicemap.conduit-services.com.
+tetercon.com.
+s.youtube.com.
+mx3.mail.buffalo.edu.
+a.root-servers.net.
+sewintriguing.blogspot.com.
+careers.herbertsmith.com.
+idpfilm.com.s7a1.psmtp.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+dcsbiz.com.
+_ldap._tcp.
+www.cpxadspace.com.
+api.facebook.com.
+a1.sphotos.ak.fbcdn.net.
+kina.net.
+time.stdtime.gov.tw.
+www.facebook.com.
+ghostscript.cvs.sourceforge.net.
+.
+checkip.dyndns.org.
+245.2.139.187.in-addr.arpa.
+s-tet.ru.
+116.192.38.24.in-addr.arpa.
+tenibacgraphion-com.relay1a.spamh.com.
+mail.armoremont.ru.
+t2.gstatic.com.
+www.w3.org.
+googleads.g.doubleclick.net.
+photos-h.ak.fbcdn.net.
+forums.cnet.com.
+www.masaat.com.
+photos-d.ak.fbcdn.net.
+www.peliculas-flv.com.
+thefrogseyebrows.blogspot.com.
+51.236.74.201.in-addr.arpa.
+bin-short.whatsapp.net.
+ikekox.net.
+www.aada.org.ar.
+web-zc1.cityville.zynga.com.
+130.70.30.177.in-addr.arpa.
+no.travellerspoint.com.
+distilleryimage9.s3.amazonaws.com.
+medicina-primitiva.blogspot.com.
+_ldap._tcp.
+mail.harrybrowns.com.
+30-courier.push.apple.com.
+download116.avast.com.
+www.reydelospernos.cl.
+mail.nysaver.com.
+94.98.29.186.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+_898_44_9.
+cbi-interiors.com.
+18-wheels-of-steel-extreme-trucker.en.softonic.com.
+s2.youtube.com.
+artegiron.com.
+msgr.zenfs.com.
+teredo.ipv6.microsoft.com.
+127.242.97.2.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+interactbp.com.s8b2.psmtp.com.
+crl.verisign.com.
+ceptoplist.com.
+www.bestbuy.com.mx.
+s4i.histats.com.
+startv.mncdn.net.
+isco.co.jp.
+a6.sphotos.ak.fbcdn.net.
+lasletrasmudas.com.
+www.deliciousvinyl.com.
+48.107.242.189.in-addr.arpa.
+www.zynga.com.
+photos-a.ak.fbcdn.net.
+vms.msn.com.
+www.release.fr.
+static.ak.fbcdn.net.
+e5237.g.akamaiedge.net.
+video.msnbc.msn.com.
+gdata.youtube.com.
+www.alnetsito.blogspot.com.
+37.223.127.201.in-addr.arpa.
+mhome.live.com.
+dev.galleries.aebn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+accounts.google.com.
+140.69.64.177.in-addr.arpa.
+74.79.178.190.in-addr.arpa.
+developers.facebook.com.
+cdn.mediafire.com.
+creative.ak.fbcdn.net.
+sp.cwfservice.net.
+jsrails.timeinc.net.
+254.82.130.189.in-addr.arpa.
+toscasatope.foro-espana.es.
+four-seasons-sunrooms.com.s7a2.psmtp.com.
+fr-fr.facebook.com.
+mail.florant.ru.
+spinworks.net.
+nbcpolitics.msnbc.msn.com.
+photos-g.ak.fbcdn.net.
+knoll.com.mail12.psmtp.com.
+www.baulsoft.com.
+cs10558.vkontakte.ru.
+img507.imageshack.us.
+it-it.facebook.com.
+www.google-analytics.com.
+geo.tp-cdn.com.
+196.101.152.201.in-addr.arpa.
+dns.msftncsi.com.
+sb-ssl.google.com.
+108.251.202.68.in-addr.arpa.
+29.221.141.201.in-addr.arpa.
+with-heart-and-hands.blogspot.com.
+oleg.lgg.ru.
+235.30.178.190.in-addr.arpa.
+sp.cwfservice.net.
+www.gstatic.com.
+privatemx.de.
+www.facebook.com.
+1s2qvh91x.site.aplus.net.
+photos-a.ak.fbcdn.net.
+connect.facebook.net.
+www.michaelpage.es.
+pki.dimc.dhs.gov.
+195.36.73.190.in-addr.arpa.
+i2.ytimg.com.
+translate.googleapis.com.
+www.musica21.net.
+media.admob.com.
+1.bp.blogspot.com.
+mail.ag-is.com.
+photos-e.ak.fbcdn.net.
+www.musicalion.com.
+ad.yieldmanager.com.
+a.root-servers.net.
+v5stats.windowsupdate.microsoft.com.
+a8.sphotos.ak.fbcdn.net.
+google.com.
+scholarshipfor.info.
+1314.qq.com.
+static.ak.fbcdn.net.
+westlakefg.com.
+kosa.baikal.ru.
+a.root-servers.net.
+wepales.subcultura.es.
+crl.godaddy.com.
+echonest.com.
+dns.msftncsi.com.
+image.tx.redbox.com.
+cpibeta.com.
+srv.main.ebayrtm.com.
+www.inmigracionmasiva.com.
+sp.cwfservice.net.
+services.conduit.com.
+www.canalesya.com.
+moderngrip.ru.
+a.root-servers.net.
+aeropostale.com.
+photos-g.ak.fbcdn.net.
+static.ak.fbcdn.net.
+www.hulkshare.com.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+macrogroup.com.
+a5.sphotos.ak.fbcdn.net.
+tracker.keyscore.com.
+teredo.ipv6.microsoft.com.
+0.11-a30f1071.40081.1518.18a4.3ea1.210.0.kn9e331jip5d71gr69pjl3h56t.avqs.mcafee.com.
+111.127.123.189.in-addr.arpa.
+pixel.facebook.com.
+delta.
+sp.cwfservice.net.
+www.aspiremag.net.
+miencarnacion.blogspot.com.
+limeodyssey.aeriagames.com.
+www.belkin.com.
+a.root-servers.net.
+plusone.google.com.
+mail.doctormortgage.com.
+www.private2atp.com.
+www.googleadservices.com.
+poemasdelpurgatorio.blogspot.com.
+eckstein-audit.ru.
+ce.lijit.com.
+reviews.latam.kaspersky.com.
+cdn82.atkingdom-network.com.
+www.continental.com.ar.
+rakeandback.ru.
+papyrefb2.net.
+hornecpa.com.
+231.254.168.192.in-addr.arpa.
+e4414.b.akamaiedge.net.
+a3.sphotos.ak.fbcdn.net.
+www.explorergirls.com.
+google.com.
+www.mobilizacaocontramalaria.org.br.
+timesaversmed.com.
+ssl.gstatic.com.
+157.80.102.201.in-addr.arpa.
+i4.tagstat.com.
+112.79.186.189.in-addr.arpa.
+backroads.net.
+bin-short.whatsapp.net.
+aidps.atdmt.com.
+liveperson.com.
+inbound.orionires.com.netsolmail.net.
+render.talk4free.com.
+css.wlxrs.com.
+165.175.230.201.in-addr.arpa.
+mail.bakerbonnigson.com.
+ds.addthis.com.
+avimex.ru.
+www.juegosdepacman.com.
+www.sharpbyte.net.
+t1.gstatic.com.
+legalterms.cbsinteractive.com.
+67.16.57.186.in-addr.arpa.
+www.mandco.com.
+7ria5s3ix.u00w0o7d.
+smtp2.nwths.com.
+api.facebook.com.
+mts.silvinit.ru.
+ad.xtendmedia.com.
+a.root-servers.net.
+.
+www.elgrandesconocido.es.
+210.174.252.201.in-addr.arpa.
+docs.google.com.
+www.steadywebs.com.
+234.70.90.200.in-addr.arpa.
+126.26.88.87.in-addr.arpa.
+a.root-servers.net.
+www.windows7library.com.
+rcp2.us.blackberry.com.
+garden.ebay.com.
+bits.wikimedia.org.
+hippoinbox.com.
+d2096563.xoom.it.
+go.srvnow.com.
+www.wemadethis.co.uk.
+surbc.ru.
+www.facebook.com.
+asiaintheheart.blogspot.com.
+www.speedsupplies.com.
+a.root-servers.net.
+www.websitestatscounter.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+developers.facebook.com.
+google.com.
+openreach.com.
+moellendorf.com.
+88.75.55.50.in-addr.arpa.
+apacs3000.ru.
+www.modernwarfare3forum.com.
+feeds.mydtzone.com.
+cf2.msn.com.
+view.atdmt.com.
+tick.stdtime.gov.tw.
+tv.seoul.co.kr.
+196.234.39.190.in-addr.arpa.
+11.25.83.189.in-addr.arpa.
+cdn.g.promosrv.com.
+dns.msftncsi.com.
+71.104.18.186.in-addr.arpa.
+js.admeld.com.
+mail.s360-1.charter-business.net.
+www.civilica.com.
+mail1.adax.com.
+profile.ak.fbcdn.net.
+mailin-01.mx.aol.com.
+www.copib.es.
+243.118.54.95.in-addr.arpa.
+i1.ytimg.com.
+zeus.ccu.umich.mx.
+a.root-servers.net.
+6135.7370686f746f73.616b.666263646e.6e6574.80h41c5f429.webcfs00.com.
+www.citi.com.
+55.199.148.159.in-addr.arpa.
+cdn.nextcenturyproductions.com.
+mobilemaps.clients.google.com.
+103.120.54.86.cbl.abuseat.org.
+0-jg-w.channel.facebook.com.
+www.spainthenandnow.com.
+www.retailonlineintegration.com.
+a8.sphotos.ak.fbcdn.net.
+webcache.googleusercontent.com.
+vjf.com.
+www.myhomedeco.com.
+api-public.addthis.com.
+msgr.updates.yahoo.com.
+www.google-analytics.com.
+a7.sphotos.ak.fbcdn.net.
+www.badassjv.com.
+mexicotop.com.
+3pb4d3ci5.03sh.
+www.wdr2.de.
+178.228.37.178.in-addr.arpa.
+mobilecom.gmarket.co.kr.
+a.root-servers.net.
+60.29.42.83.in-addr.arpa.
+www.google.com.
+lh3.ggpht.com.
+ssl.gstatic.com.
+www.amervets.com.
+aapt.net.au.
+ads.yimg.com.
+76.150.149.187.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+www.gstatic.com.
+mail.skanska.co.uk.
+christina.com.
+u3gkf7ab4.c47m3r8i.
+v99apuynw.75ow.
+flavioluccisano.cghub.com.
+136.78.78.201.in-addr.arpa.
+www.facebook.com.
+google.com.
+code.jquery.com.
+a.root-servers.net.
+ar-ar.facebook.com.
+best-tattoo.gnug.us.
+206.33.174.118.in-addr.arpa.
+creative.ak.fbcdn.net.
+115.195.194.14.in-addr.arpa.
+bsgsearch.com.
+cx.sts.ru.
+207.123.92.186.in-addr.arpa.
+24.249.163.90.in-addr.arpa.
+a.root-servers.net.
+www.gleason.com.
+geoiplookup.wikimedia.org.
+kisul.wordpress.com.
+ad-g.doubleclick.net.
+conntest.nintendowifi.net.
+scopeo.usal.es.
+unifi.
+www.jovencitasa9euros.com.
+www.blogmisterios.com.
+www2.whitney36dd.com.
+wiesnergroup.com.
+83.34.105.187.in-addr.arpa.
+ns1.networklayer.com.
+es-la.facebook.com.
+teredo.ipv6.microsoft.com.
+www.cafepress.com.
+groups.google.com.mx.
+a.root-servers.net.
+www.asslickingmovies.net.
+30.21.185.203.in-addr.arpa.
+bmgcontracting.com.
+cinci.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+talkingblocks.com.
+fei9988.3322.org.
+187.91.87.108.in-addr.arpa.
+support.maktoob.com.
+inbound.ashburngroup.com.netsolmail.net.
+202.94.223.201.in-addr.arpa.
+i1.ytimg.com.
+62.232.191.186.in-addr.arpa.
+www.bigfoot4x4.com.
+pagead2.googlesyndication.com.
+census.pewsocialtrends.org.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+creative.ak.fbcdn.net.
+time.chttl.com.tw.
+134.171.140.67.in-addr.arpa.
+scottbarnes.com.
+168.205.250.111.in-addr.arpa.
+emediawire.com.
+p07-contacts.icloud.com.
+exk7oqy5r.35tz.
+vipmutrpx001.tf1.fr.
+www.dico-definitions.com.
+rss.elmundo.es.
+mail.fstar.ru.
+www.facebook.com.
+comercial-lonco.blogspot.com.
+denis.stalker.h3q.com.
+moneycentral.msn.com.
+118.228.113.217.in-addr.arpa.
+fr-fr.facebook.com.
+i.ytimg.com.
+orcart.facebook.com.
+captainsof.com.
+www.iglesiabautistalagrancomision.com.
+123.82.0.190.in-addr.arpa.
+itunes.apple.com.
+224799.mimejorfrase2.info.
+213.139.176.190.in-addr.arpa.
+a1007.w43.akamai.net.
+mx.lumisys.com.
+117.247.1.181.in-addr.arpa.
+1.173.75.201.in-addr.arpa.
+fsarria.blogspot.com.
+www.quotesarena.com.
+pr.prchecker.info.
+kultmetro.ru.
+txu.ed.com.
+translate.google.com.
+geraxzz.blogspot.com.
+shared.live.com.
+pop.bogor.net.
+9.223.170.201.in-addr.arpa.
+www.adobe.com.
+www.municipios.com.mx.
+a3.sphotos.ak.fbcdn.net.
+www.charlottemagazine.com.
+185.132.91.76.in-addr.arpa.
+58.104.44.187.in-addr.arpa.
+stockindesign.com.
+plus.google.com.
+photos-d.ak.fbcdn.net.
+www.qaronline.org.
+dns.msftncsi.com.
+triplesphilippines.blogspot.com.
+162.86.54.189.in-addr.arpa.
+141.138.193.173.in-addr.arpa.
+www.blueaquarium.org.
+smx.twinwest.com.redcondor.net.
+ct.metrocast.net.
+pagead2.googlesyndication.com.
+gruporenacer.wordpress.com.
+195.23.75.201.in-addr.arpa.
+ss3.videosz.com.
+click.infospace.com.
+r12.lhr14g01.c.youtube.com.
+a.root-servers.net.
+r._dns-sd._udp.lan.
+pop.toserbayogya.com.
+www.ihsi.ht.
+rg-ap.ru.
+i-0.19-a30e0079.83.1518.19d4.3ea1.210.0.b8mvqdmsdsnmq1gtzs9ushe89q.avqs.mcafee.com.
+a.root-servers.net.
+s-static.ak.fbcdn.net.
+a1267.phobos.apple.com.
+dns.msftncsi.com.
+s-static.ak.fbcdn.net.
+_594_18_3.
+c.msn.com.
+likesfb.net.
+csi-las-vegas.seriespepito.com.
+dns.msftncsi.com.
+books.elsevier.com.
+static.ak.fbcdn.net.
+mymail.scc-fl.edu.
+apis.google.com.
+47.175.54.189.in-addr.arpa.
+secure-au.imrworldwide.com.
+a.root-servers.net.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+lagaleriadelkuxo.blogspot.com.
+static.dealply.com.
+20.133.29.77.in-addr.arpa.
+72.219.160.189.in-addr.arpa.
+hirecounsel.com.s5b2.psmtp.com.
+108.65.122.187.in-addr.arpa.
+blog.python.org.
+chat.facebook.com.
+a1404.w41.akamai.net.
+time.chttl.com.tw.
+www.sulis.net.
+163.14.185.187.in-addr.arpa.
+5.62.242.99.in-addr.arpa.
+122.63.113.186.in-addr.arpa.
+apps.facebook.com.
+0.gravatar.com.
+231.68.166.190.in-addr.arpa.
+www.google.com.
+www.fastfivemovie.com.
+mail.live.com.
+developers.facebook.com.
+www.facebook.com.
+accfle.nl.
+ntp.glb.nist.gov.
+a.root-servers.net.
+tags.bluekai.com.
+nemesis.1337x.org.
+91.229.159.190.in-addr.arpa.
+67.147.58.186.in-addr.arpa.
+s.ytimg.com.
+static.hqtubexxx.com.
+www.youyube.com.
+peisys.net.
+ssl.google-analytics.com.
+.
+edge.quantserve.com.
+platform0.twitter.com.
+166.171.107.186.in-addr.arpa.
+imk.es.
+i.gismeteo.com.
+photos-a.ak.fbcdn.net.
+249.225.151.68.in-addr.arpa.
+239.82.220.189.in-addr.arpa.
+au.download.windowsupdate.com.
+profile.ak.fbcdn.net.
+config.conduitapps.com.
+48.112.219.81.in-addr.arpa.
+urs.microsoft.com.
+apis.google.com.
+118.69.105.190.in-addr.arpa.
+209.159.125.124.in-addr.arpa.
+snowcrst.net.
+22.123.210.112.in-addr.arpa.
+naughtyamericans.com.
+a2.sphotos.ak.fbcdn.net.
+rvwc.com.
+131.232.42.177.in-addr.arpa.
+105.191.82.190.in-addr.arpa.
+182.243.178.186.in-addr.arpa.
+livecams.vol.at.
+localhost.
+micaela-thesims3.blogspot.com.
+profile.ak.fbcdn.net.
+124.127.122.70.in-addr.arpa.
+176.165.178.190.in-addr.arpa.
+vn-media.s3.amazonaws.com.
+msk.rusmarine.ru.
+mail.blackseek.com.
+a2.sphotos.ak.fbcdn.net.
+es-es.facebook.com.
+mediaoutletonline.com.
+7.87.128.78.in-addr.arpa.
+oktopod.ru.
+www.lasrecetasdecocina.com.
+data.mobclix.com.
+catemaco.info.
+m.dk.pp.ru.
+blogs.ligasilverlight.com.
+b._dns-sd._udp.lan.
+safebrowsing-cache.google.com.
+webmail1.cps.k12.va.us.
+img851.imageshack.us.
+xsltcache.alexa.com.
+profile.ak.fbcdn.net.
+forums.toshiba.com.
+a.root-servers.net.
+dealhojaye.rediff.com.
+112.132.246.201.in-addr.arpa.
+autos.trovit.com.mx.
+www.pocketpcmag.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+skins.gmodules.com.
+mx.elementstore.ru.
+www.natate.org.
+caseworkltd.com.s8b2.psmtp.com.
+mail.live.com.
+js.wlxrs.com.
+u20.eset.com.
+photos-b.ak.fbcdn.net.
+widgets.twimg.com.
+a.root-servers.net.
+thewhir.com.
+www.youtube.com.
+concordia-ny.edu.
+email-mx.baypointcorp.com.
+b._dns-sd._udp.lan.
+www.horsepowerfreaks.com.
+albaraqi.net.
+certrevoc.vo.msecnd.net.
+49.75.4.189.in-addr.arpa.
+g.ceipmsn.com.
+204.1.65.177.in-addr.arpa.
+224.71.209.201.in-addr.arpa.
+www.tilannehuone.fi.
+v6.nonxt3.c.youtube.com.
+governor.state.al.us.
+www.goojue.com.
+apple.com.
+storage.conduit.com.
+176.11.185.72.in-addr.arpa.
+euro.mediotiempo.com.
+36.222.113.186.in-addr.arpa.
+mx2.r-kh.ru.
+a8.sphotos.ak.fbcdn.net.
+toolbarqueries.google.com.
+yahoo.com.
+i4.ytimg.com.
+ad.doubleclick.net.
+photos-d.ak.fbcdn.net.
+toolbar.live.com.
+a.root-servers.net.
+sellstatenj.net.
+u01.gate01.com.
+creative.ak.fbcdn.net.
+yqeycyvfc.05zr.
+alltherage4u.blogspot.com.
+www.beatmybox.com.
+ad.auditude.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+p0b.ru.
+photos-f.ak.fbcdn.net.
+a5.sphotos.ak.fbcdn.net.
+euqvuzvufyvmssxg.com.
+blekko.com.
+flashresults.com.
+www.gatovolador.net.
+photos-a.ak.fbcdn.net.
+crest.tudou.com.
+a.root-servers.net.
+www.youtube.com.
+www.iplay.com.br.
+finance.my.freeze.com.
+oimg.nbcuni.com.
+safebrowsing-cache.google.com.
+zgfma1t88.11mz.
+ssl.gstatic.com.
+profile.ak.fbcdn.net.
+ingdirect.com.au.
+com-fallback.pandonetworks.com.
+81.10.168.192.in-addr.arpa.
+payload8.cargocollective.com.
+tile24.mqcdn.com.
+relay.vostok-invest.ru.
+69.164.156.82.in-addr.arpa.
+apk-prioritet.ru.
+static01.olx-st.com.
+www.casakeim.cl.
+dmail.cobaltgroup.com.
+www.productiveramadan.com.
+js.wlxrs.com.
+ticketmaster.com.mx.
+download338.avast.com.
+www.facebook.com.
+byfiles.storage.msn.com.
+www.testfreaks.com.pt.
+www.facebook.com.
+b-0.19-a309c009.8020580.1518.19d4.3ea1.410.0.kp16q82qf2989s62frjgvpw4pj.avqs.mcafee.com.
+83.98.200.88.in-addr.arpa.
+31.73.35.186.in-addr.arpa.
+pamjeshqiptare.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mx.sincrono.it.
+a-0.19-21097081.d010583.1518.19d4.2f4a.210.0.qzzi6qttfmt4136j9flfm6aq7j.avqs.mcafee.com.
+mail.verizon.net.
+www.therioruminant.ulg.ac.be.
+www.nvnet.org.
+rs854dt.rapidshare.com.
+178.87.204.187.in-addr.arpa.
+gwde2.linde.com.
+a749.g.akamai.net.
+www.onyxcollection.com.
+veracruz.campusanuncios.com.mx.
+55.245.179.190.in-addr.arpa.
+creativecommons.org.
+24.117.60.78.in-addr.arpa.
+mail.yahoo.com.
+rt-soft.ru.
+www.gameportal.net.
+mail.sembutilities.co.uk.
+pixel.facebook.com.
+204.195.50.99.in-addr.arpa.
+www.danniesdesigns.com.
+s0.wp.com.
+www.gstatic.com.
+tourblackstone.com.
+www.fastbooking.co.uk.
+plus.google.com.
+unilever.com.
+plus.google.com.
+static.ak.fbcdn.net.
+www.tfg.com.
+www.facebook.com.
+google.com.
+117.203.26.80.in-addr.arpa.
+www.extremetube.com.
+fbcdn-photos-a.akamaihd.net.
+cgi.una.ac.cr.
+profile.ak.fbcdn.net.
+www.metacafe.com.
+www.youtube.com.
+heartbeat.belkin.com.
+a5.sphotos.ak.fbcdn.net.
+i1.ytimg.com.
+v17.nonxt8.c.pack.google.com.
+cdn1.inner-active.mobi.
+s440.photobucket.com.
+genderoutlaw.wordpress.com.
+bserver.npfszma.ru.
+www.gstatic.com.
+141.47.79.189.in-addr.arpa.
+ccb.edu.co.
+aprenspan.blogspot.com.
+138.39.86.186.in-addr.arpa.
+i2.ytimg.com.
+twenty04.com.
+43.101.140.187.in-addr.arpa.
+94.55.237.80.in-addr.arpa.
+116.231.240.189.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+evrophone.ru.
+mail.collisiononwheels.com.
+hfry3pd5s.12dl.
+thehospital.bligoo.com.
+a8.sphotos.ak.fbcdn.net.
+ubuvepyn.etcampaigns.com.
+innovationliving.com.
+cdn.tynt.com.
+us.js.yimg.com.
+scholar.google.com.
+fr.astrology.yahoo.com.
+_918_80_5.
+clients2.google.com.
+38.101.0.123.in-addr.arpa.
+79.206.22.71.in-addr.arpa.
+83.65.72.189.in-addr.arpa.
+i4.ytimg.com.
+bauerpublishing.sl.advertising.com.
+hitsports.info.
+photos-a.ak.fbcdn.net.
+www-google-analytics.l.google.com.
+www.videoweed.es.
+sn1msg3020306.sn1.gateway.edge.messenger.live.com.
+.
+www.google.com.
+www.google.com.
+videotron.ca.
+35.10.168.192.in-addr.arpa.
+_ldap._tcp.
+www.google-analytics.com.
+i1.ytimg.com.
+a4.sphotos.ak.fbcdn.net.
+205.37.97.190.in-addr.arpa.
+emout11.mail.aol.com.
+www.fontifier.com.
+semeini.ru.
+www.livejasmin.com.
+darkenedcultuszepharis2.blogspot.com.
+230.141.153.201.in-addr.arpa.
+.
+mail.mpe.lv.
+26.161.7.58.in-addr.arpa.
+www.justintimberlake.com.
+scpet.net.
+he.y8.com.
+cs575.vk.com.
+s.youtube.com.
+best-toys-for-toddler.blogspot.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+images.thalia.de.
+167.207.83.189.in-addr.arpa.
+static.ak.fbcdn.net.
+www.solarturbines.com.
+t1.gstatic.com.
+search.ewebse.com.
+bs.serving-sys.com.
+ceradyne.com.s9a1.psmtp.com.
+x83xxsyua.i29u4v6u.
+plus.google.com.
+sterh.ru.
+uu4371ywt.14ip.
+dns.msftncsi.com.
+138.155.211.189.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+etas.us.s201a1.psmtp.com.
+csi.gstatic.com.
+tobolsk.info.
+88.159.147.49.in-addr.arpa.
+86.41.53.186.in-addr.arpa.
+sanjudastadeo.foroactivo.com.
+b.scorecardresearch.com.
+www.touchmymelons.com.
+content.yieldmanager.edgesuite.net.
+www.topcatcomputing.com.
+pixel.facebook.com.
+ksn1-11-part1.kaspersky-labs.com.
+tic.sepdf.gob.mx.
+www.youtube.com.
+avis-moscow.ru.
+mclean.k12.ky.us.
+attglobal.com.lan.
+gateway.messenger.hotmail.com.
+9gag.com.
+174.1.168.192.in-addr.arpa.
+mail.ezcorp.com.
+www.vuelos-sevilla.es.
+hemeroteca.elimparcial.es.
+s.ytimg.com.
+www.usajordanshops.com.
+secure.wlxrs.com.
+smtp.abelia.ocn.ne.jp.
+www.amazon.com.
+buttholesandtoys.blogspot.com.
+www-open-opensocial.googleusercontent.com.
+gmx.gameduell.de.
+bugnbird.com.
+lxzh2wjil.r69b3e6k.
+a771.da1.akamai.net.
+www.motorsportinsurance.com.au.
+reckittcolman.com.
+www.gamert.nl.
+mx.lomsys.net.
+www.mab.com.au.
+107.66.43.62.in-addr.arpa.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+imtgapp.com.
+a.root-servers.net.
+silverlight.dlservice.microsoft.com.
+static.ak.fbcdn.net.
+144.5.134.187.in-addr.arpa.
+www.aerochambervhc.com.
+ads.intergi.com.
+static.panoramio.com.
+_315_80_9.
+awesomebarnhart.wordpress.com.
+ads1.msads.net.
+any-fam.data.fy2.b.yahoo.com.
+m.addthisedge.com.
+consalting-secrets.ru.
+88.136.25.114.in-addr.arpa.
+safebrowsing-cache.google.com.
+data.mobclix.com.
+a1408.w43.akamai.net.
+a.root-servers.net.
+40.128.163.189.in-addr.arpa.
+hotmailhot.com.
+91.156.205.66.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+www.google.com.
+teredo.ipv6.microsoft.com.
+eth0.
+a7.sphotos.ak.fbcdn.net.
+trophy.ww.np.community.playstation.net.
+177.228.197.46.in-addr.arpa.
+xslt.alexa.com.
+a3.sphotos.ak.fbcdn.net.
+i2.ytimg.com.
+www.audionur.com.
+83.210.73.69.in-addr.arpa.
+searchjs.s3.amazonaws.com.
+ct57f4z9b.07tb.
+help.social.ea.com.
+f21.360tag.com.
+www.care-et-entreprise.eu.
+www.macos.utah.edu.
+www.wwe.com.
+thematchettgroup.com.
+a.root-servers.net.
+hotmail.com.
+apis.google.com.
+ftp.lug.ro.
+i1av:1uho.46nq.
+3.139.159.94.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.google.com.
+a.root-servers.net.
+pfchre.co.zw.
+order.store.yahoo.net.
+photos-a.ak.fbcdn.net.
+mail.znaki-pr.ru.
+177.103.222.189.in-addr.arpa.
+svpeds.net.
+www.kvministries.com.
+bkktonight.com.
+www.circiruj.edilaser.net.
+72.30.229.189.in-addr.arpa.
+yojuegomagic.blogspot.com.
+shops.oscommerce.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+celebsforsale.files.wordpress.com.
+aixnet.com.
+www.fullpelis.com.
+ds.addthis.com.
+i3.ytimg.com.
+zbar2.zynga.com.
+profile.ak.fbcdn.net.
+113.203.237.81.in-addr.arpa.
+cwcapital.com.
+aladas-palabras.blogspot.com.
+204.225.195.187.in-addr.arpa.
+mxcluster2.tieto.com.
+sp.cwfservice.net.
+zm17aos3a.l15o7t7n.
+content.gamezer.com.
+content.yieldmanager.edgesuite.net.
+hi-in.facebook.com.
+97e1e8g68.e44h6x0w.
+http://google.com/.
+www.welovehappy.com.
+akamai.invitemedia.com.
+edge.quantserve.com.
+clients1.google.com.
+a8.sphotos.ak.fbcdn.net.
+www.giving.ox.ac.uk.
+entrevistas.sport.es.
+www.position-monitoring.de.
+s.ytimg.com.
+lhospitalarias.com.
+114.35.121.91.in-addr.arpa.
+login.yahoo.com.
+apis.google.com.
+del.icio.us.
+www.male-sexual-dysfunction.com.
+infomanspec.com.
+wwwimages.adobe.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+img59.imageshack.us.
+pixel.facebook.com.
+9.178.51.190.in-addr.arpa.
+dns.msftncsi.com.
+photos-c.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+5e2neyv9u.h79b0j1h.
+11.8.43.200.in-addr.arpa.
+242.26.231.201.in-addr.arpa.
+noticias.prodigy.msn.com.
+blogs.elcomercio.pe.
+cdn.applifier.com.
+www.paisajeculturalcafetero.org.co.
+17.242.58.83.in-addr.arpa.
+plusone.google.com.
+a-0.19-22098081.c0c0083.1518.19b2.410a.400.9d.qfptcsf437v6s7kaak2qs267pq.avqs.mcafee.com.
+nxcache.nexon.net.
+instagram.com.
+www.imdb.com.
+cdn1.techbang.com.tw.
+138.211.112.204.in-addr.arpa.
+plus.google.com.
+relay.voice.messenger.msn.com.
+mail.riverbluff.com.
+188.85.61.174.in-addr.arpa.
+www.komputronik.pl.
+a5.sphotos.ak.fbcdn.net.
+85.112.86.188.in-addr.arpa.
+stud.hib.no.
+mx.jobrapido.com.
+static.ak.fbcdn.net.
+vsofte.ru.
+www.google.com.
+15eb7bh0.aime5.eu.
+checkip.dyndns.org.
+landmarkcu.com.
+a5e327c6.linkbucks.com.
+188.177.249.115.in-addr.arpa.
+www.facebook.com.
+232.61.168.192.in-addr.arpa.
+www.factoriadoson.com.
+243.154.48.190.in-addr.arpa.
+96.171.158.200.in-addr.arpa.
+thumbs4.ebaystatic.com.
+clubs-kids.scholastic.co.uk.
+240.219.60.151.in-addr.arpa.
+apis.google.com.
+www.compumundo.com.ar.
+a1.sphotos.ak.fbcdn.net.
+mx3.hotmail.com.
+www.cdl55.com.
+nko88bgkb.t19z7h1t.
+a.root-servers.net.
+photos-d.ak.fbcdn.net.
+23k938zvm.k99d2w7z.
+198.225.23.186.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+www.mobile-free-calls.blogspot.com.
+94.220.227.71.in-addr.arpa.
+www.google.com.
+mail.atlasswitch.com.
+www.google-analytics.com.
+cox.net.
+firsthomemortgage.com.
+babader.com.
+creative.ak.fbcdn.net.
+103.250.131.187.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+227.131.141.190.in-addr.arpa.
+pixel.quantserve.com.
+myperfectgame.ru.
+choose-happiness.com.au.
+186.95.173.90.in-addr.arpa.
+static.ak.fbcdn.net.
+www.revistabuenasalud.com.
+www.unidad094.upn.mx.
+31.120.110.175.in-addr.arpa.
+troi.csw.net.
+222.120.40.177.in-addr.arpa.
+crary.com.s8b1.psmtp.com.
+photos-h.ak.fbcdn.net.
+ads.clicksor.com.
+ads.sonobi.com.
+gajigratis.com.
+a.root-servers.net.
+www.conduit.com.
+mobileeurope.co.uk.
+api.digitalhomeservices.yahoo.com.
+ssl.gstatic.com.
+gardenvariety.com.
+photos-b.ak.fbcdn.net.
+kamiahproperties.com.
+a7.sphotos.ak.fbcdn.net.
+173.135.26.174.in-addr.arpa.
+google.com.
+accounts.google.com.
+a1007.w43.akamai.net.
+msc.wlxrs.com.
+fotografiska.eu.
+mail.jsprinting.com.
+topshop.chtah.com.
+static.ak.fbcdn.net.
+www.insuagro.com.ar.
+photos-f.ak.fbcdn.net.
+asia.perf.glbdns.microsoft.com.
+a.root-servers.net.
+wpad.
+members.sneakypeek.net.
+mail.btinternet.com.
+edition.cn.
+a.root-servers.net.
+www.gravatar.com.
+s2.youtube.com.
+alame2009.pixnet.net.
+27.198.48.65.in-addr.arpa.
+google.com.
+twoomail.com.multi.surbl.org.
+x3wi43b7t.j25g9o0l.
+188.170.100.190.in-addr.arpa.
+www.google.com.
+100.127.109.85.in-addr.arpa.
+humblebundle.appspot.com.
+construction.kizifriv.com.
+52.197.106.89.in-addr.arpa.
+sites.google.com.
+cresswellservices.co.uk.
+www.floweroflife.org.
+images.google.com.
+mail3.xchanging.com.
+www.adobe.com.
+pagead2.googlesyndication.com.
+ese1.com.s9a2.psmtp.com.
+160.60.158.200.in-addr.arpa.
+www.google.com.
+drakausa.com.
+s-static.ak.fbcdn.net.
+tepic.olx.com.mx.
+gorx9395.files.wordpress.com.
+mail.yoursmilecenter.com.
+cs-g2-crl.thawte.com.
+yulianacreations.blogspot.com.
+b-0.19-a7063079.31002.1518.19bc.3ea1.210.0.qa7p2li2mpzdei6l82mr51e5mv.avqs.mcafee.com.
+www.google-analytics.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.aseguratuauto.com.ar.
+tracker.thepiratebay.org.
+l.yimg.com.
+blog.joachim.at.
+eroticplanet.ru.
+clock.fmt.he.net.
+api-read.facebook.com.
+a7.sphotos.ak.fbcdn.net.
+forum.safecreative.net.
+reporting.fl.skype.net.
+googleads.g.doubleclick.net.
+www.tratamientohemorroidesefectivo.com.
+a.root-servers.net.
+runninglip.com.
+8.128.207.190.in-addr.arpa.
+gmail.ci.
+whos.amung.us.
+importnut.net.
+84.231.123.188.in-addr.arpa.
+0-271.channel.facebook.com.
+ssl.google-analytics.com.
+hsbc.com.hk.
+115.72.156.79.in-addr.arpa.
+219.119.170.72.in-addr.arpa.
+matcher.bidder8.mookie1.com.
+time.chttl.com.tw.
+static.ak.fbcdn.net.
+turkish.keyboard.su.
+mail.giv.it.
+es-la.facebook.com.
+s-static.ak.facebook.com.
+tierrainfinitaz.chatango.com.
+a.root-servers.net.
+www.facebook.com.
+www.yendit.com.
+161.42.59.82.in-addr.arpa.
+navidadd.com.
+img.youtube.com.
+all-kids.us.
+apkbank.ru.
+nodrivetime.com.
+brocktonautomile.com.
+testinfo007.blogspot.com.
+www.urbian.biz.
+www.laverdad.es.
+it-it.facebook.com.
+48.178.168.189.in-addr.arpa.
+external.ak.fbcdn.net.
+grafedia.net.
+s3.amazonaws.com.
+celulasabundancia.blogspot.com.
+www.facebook.com.
+a.root-servers.net.
+l.yimg.com.
+borovit.ru.
+ssl.gstatic.com.
+spiritually.com.
+download351.avast.com.
+www.youtube.com.
+plusone.google.com.
+fotografiaecuador.com.
+167.148.146.24.in-addr.arpa.
+ciudadanotasca.blogspot.com.
+92.54.192.190.in-addr.arpa.
+52.173.30.189.in-addr.arpa.
+open.spotify.com.
+battlefield-2142.en.softonic.com.
+dns.msftncsi.com.
+ocw.uniovi.es.
+profile.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+researchreports.sdcexec.com.
+ashtontechgroup.com.
+kulturmejeriet.se.
+plusone.google.com.
+a7.sphotos.ak.fbcdn.net.
+sac.gti.mcafee.com.
+data.tvdownload.microsoft.com.
+p07-contacts.icloud.com.
+buiembtyd.88ya.
+www.akm.com.
+www.toptanciyiz.net.
+ntp.glb.nist.gov.
+ceoiq.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+d2uukq5a8vhcuo.cloudfront.net.
+whos.amung.us.
+search.twitter.com.
+www.juegosagogo.com.
+kalachev.ru.
+www.alliedtime.com.
+support.google.com.
+61.127.10.189.in-addr.arpa.
+a.root-servers.net.
+smtp01.swisscenter.com.
+cdn-0.pics.dvdcdn.com.
+photos-c.ak.fbcdn.net.
+services.net.au.
+reddit.com.
+zh-cn.facebook.com.
+adpcos.com.
+tc.v3.cache4.c.youtube.com.
+a1.sphotos.ak.fbcdn.net.
+help.yahoo.com.
+8.154.243.201.in-addr.arpa.
+groups.google.com.mx.
+mcfarren-assoc.com.
+channing-t.com.
+librerias.idoneos.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+alert.services.conduit.comalerts.
+145.18.57.187.in-addr.arpa.
+descargar.mp3.es.
+reelclipx.com.
+www.torrentrg.com.
+57.228.211.201.in-addr.arpa.
+buenosaires.evisos.net.
+udc.msn.com.
+i1.ytimg.com.
+151.44.173.190.in-addr.arpa.
+wpad.
+www.toxinology.com.
+cs9571.vkontakte.ru.
+v9.nonxt7.c.youtube.com.
+www.live.com.
+169.47.34.189.in-addr.arpa.
+117.111.83.75.in-addr.arpa.
+www.facebook.com.
+a3.sphotos.ak.fbcdn.net.
+36.196.143.187.in-addr.arpa.
+api.cbssports.com.
+teredo.ipv6.microsoft.com.
+at.atwola.com.
+www.reidsteel.aero.
+profile.ak.fbcdn.net.
+mail.tsibridges.com.
+mail.conmed.com.
+meritas.net.s5a2.psmtp.com.
+s.ytimg.com.
+a.root-servers.net.
+ksn4-12.kaspersky-labs.com.
+www.nokiakiller.com.
+ca.com.s9b1.psmtp.com.
+ci33hiu3l.c96u9z1g.
+twitter.com.
+img.babcdn.com.
+latino.msn.com.
+profile.ak.fbcdn.net.
+www.curr.it.
+a3.twimg.com.
+tc.v6.cache3.c.youtube.com.
+www.loocks.com.
+sde7a1j4m.55ic.
+a7.sphotos.ak.fbcdn.net.
+email.it.
+prowlapp.com.
+a.root-servers.net.
+bt.e-burg.org.
+yahoo.com.
+unifi.
+macdougalls.com.
+widgets.digg.com.
+a2.sphotos.ak.fbcdn.net.
+www.pixoto.com.
+123.217.92.75.in-addr.arpa.
+logv33.xiti.com.
+s.youtube.com.
+api.facebook.com.
+www.cwdkids.com.
+fbcdn-photos-a.akamaihd.net.
+backdoorjobs.com.
+fxfeeds.mozilla.com.
+mrb.mail.ru.
+66.99.164.67.in-addr.arpa.
+ipom.ru.
+photos-d.ak.fbcdn.net.
+cat.frivjuegos.info.
+dr._dns-sd._udp.home.
+b.scorecardresearch.com.
+content.yieldmanager.edgesuite.net.
+81.173.95.89.in-addr.arpa.
+www.jobstreet.com.my.
+fbcdn-profile-a.akamaihd.net.
+202.248.248.92.in-addr.arpa.
+i4.ytimg.com.
+www.m5zn.com.
+www.driftlive.com.
+download.paltalk.com.
+google.com.
+reddit.com.
+static.ak.fbcdn.net.
+mserver.etn.com.mx.
+u21.eset.com.
+a4.sphotos.ak.fbcdn.net.
+www.google-analytics.com.
+6j5oyw99u.n49e0t9j.
+8.mails4e.com.
+97.145.55.190.in-addr.arpa.
+254.200.65.190.in-addr.arpa.
+nemesis.1337x.org.
+a5.sphotos.ak.fbcdn.net.
+googleads.g.doubleclick.net.
+www.allsaints.com.
+campaign.constantcontact.com.
+a.root-servers.net.
+www.apple.com.
+175.114.83.200.in-addr.arpa.
+galleries.bunnygirlz.com.
+p.d.ovi.com.
+a4.sphotos.ak.fbcdn.net.
+wxdata.weather.com.
+71.23.149.98.in-addr.arpa.
+107.41.20.187.in-addr.arpa.
+payments.makemytrip.com.
+ns3.avira-ns.net.
+www.banamex.com.
+vonxfuupyyxino.org.
+www.missdriftedsnowwhite.com.
+www.update.microsoft.com.
+balu.us.
+a1003.w41.akamai.net.
+support.google.com.
+videos.drole.ch.
+api-public.addthis.com.
+onetidbit.wordpress.com.
+45.155.90.208.in-addr.arpa.
+ltd.br.dnsbl7.mailshell.net.
+www.myus.com.
+fbcdn-profile-a.akamaihd.net.
+irresistablefilms.com.
+uristspb.ru.
+intranet.adecco.com.mx.
+promedica.com.br.
+www.blackberry.com.
+97.49.186.201.in-addr.arpa.
+glimages.graphicleftovers.com.
+mail.moltoni.com.au.
+ocsp.digicert.com.
+mail.pofboxing.perm.ru.
+www.facebook.com.
+top100-images.rambler.ru.
+197.69.40.114.in-addr.arpa.
+128.19.237.78.in-addr.arpa.
+www.miguelcarrasco.net.
+beta.stun.voice.yahoo.com.
+101.252.168.78.in-addr.arpa.
+js1.infoseek.co.jp.
+35.39.157.189.in-addr.arpa.
+api.facebook.com.
+photos-e.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+water.friv-y8.com.
+a.root-servers.net.
+crl3.digicert.com.
+external.ak.fbcdn.net.
+www.joshstrength.com.
+www.indiana.edu.
+mail.m-s.de.
+a1294.w20.akamai.net.
+proxy.yospb.yahoo.com.
+2.0.0.10.in-addr.arpa.
+api.facebook.com.
+_255_92_6.
+155.232.171.69.list.dsbl.org.
+i2.ytimg.com.
+mt1.google.com.
+87.124.141.69.in-addr.arpa.
+static.ifa.camads.net.
+www.eurocampings.es.
+nnov.ancor.ru.
+105.1.168.192.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+mobileads.nimbuzz.com.
+pt-br.facebook.com.
+cf.addthis.com.
+xtra1.gpsonextra.net.
+allan-knox.com.
+227.201.49.85.in-addr.arpa.
+s-static.ak.fbcdn.net.
+www.bustyashlynnbrooke.com.
+125.102.202.125.in-addr.arpa.
+prodel.ru.
+dmgrealty.com.
+media.oh-barcelona.com.
+_233_86_3.
+www.afforums.com.
+photos-a.ak.fbcdn.net.
+viocast.net.
+jewelryconcepts.com.s7b1.psmtp.com.
+videos.flv2.redtubefiles.com.
+a6.sphotos.ak.fbcdn.net.
+www.drtuberpremium.com.
+cohutta.tdesystems.com.
+accounts.google.com.
+www.juntandocorazones.com.
+a.root-servers.net.
+affordablebusinesssystems.com.inbound15.mxlogic.net.
+www.vidz.com.
+4148091.frasesinolvidables1.com.ar.
+google.com.
+images.2.bangyoulater.com.
+ganemasociados.com.
+mitsubishi-forums.us.intellitxt.com.
+odisea.activoforo.com.
+mt1.googleapis.com.
+newhopetel.net.
+mh-mx1.onderwijsgroeptilburg.nl.
+s0.2mdn.net.
+161.adsina.allyes.com.
+www.tienda.telmex.com.
+www.jolintsai.net.
+www.msftncsi.com.
+fxfeeds.mozilla.com.
+accounts.google.com.
+www.y8.com.
+www.ortsbo.com.
+wls-mail.whitelodging.com.
+api.facebook.com.
+external.ak.fbcdn.net.
+ddserv.com.
+italianfarmacieonline.com.
+www.casaensamble.com.
+sparklepainting.com.
+loading1.widdit.com.
+player.slipstreamradio.com.
+ivxwk:zko.f28v1y3s.
+www.canidouafavor.com.
+seven.net.
+mail.waroundtable.com.
+2.211.141.201.in-addr.arpa.
+smtp.live.com.
+plus.google.com.
+a7.sphotos.ak.fbcdn.net.
+d2092558.xoom.it.
+rich.igg.com.
+ak.search.mywebsearch.com.
+ssl.google-analytics.com.
+www.bomc2.com.
+mail.carpentedil.com.
+proyectodocumenta.org.
+wmp.audible.com.
+api.conduit.com.
+otb-games.com.
+infonavitpuntos.net.
+112.12.252.189.in-addr.arpa.
+lb._dns-sd._udp.lan.
+b._dns-sd._udp.0.129.37.10.in-addr.arpa.
+mx.youtube.com.
+1.0.0.127.in-addr.arpa.
+_vlmcs._tcp.
+www.xstarsvod.com.
+switch.atdmt.com.
+mx2-exc.dgx.com.br.
+_140_36_2.
+130.10.174.190.in-addr.arpa.
+kleartextbook.com.
+ssl.gstatic.com.
+imzh.ru.
+225.100.40.178.in-addr.arpa.
+news.google.com.mx.
+llll.
+_208_51_6.
+www.google-analytics.com.
+www.filthcafe.com.
+verviers.lameuse.be.
+etrn.turk.net.
+249.144.73.189.in-addr.arpa.
+aweza.co.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+checkip.dyndns.org.
+1.77.176.187.in-addr.arpa.
+usea.org.
+hahnfamily.com.
+www.bioterraviva.com.
+233.132.62.189.in-addr.arpa.
+js.anonym.to.
+217.173.125.186.in-addr.arpa.
+www.powerhomepages.com.
+pap.wikipedia.org.
+a5.da1.akamai.net.
+.
+dimassimo.com.
+apple.com.
+www.radiozu.ro.
+a-0.19-23091081.c070083.1518.19d4.3ea1.210.0.4nckv22dv8e58ggm6pdvqgragj.avqs.mcafee.com.
+mainstreamp.com.
+www.googleadservices.com.
+jacksonville.com.
+ipowersolutions.net.s5b2.psmtp.com.
+a.root-servers.net.
+rincon-grafico.blogspot.com.
+a997.mm1.akamai.net.
+www.jazzpublishing.co.uk.
+developers.facebook.com.
+_886_50_8.
+dibels.org.
+apps.facebook.com.
+www.youtube-nocookie.com.
+.
+103.4.148.64.in-addr.arpa.
+www.bobsboots.com.
+197.167.98.87.in-addr.arpa.
+mail.systeminplace.net.
+a.root-servers.net.
+mxtls.expurgate.net.
+tools.google.com.
+clients1.google.com.
+xtn.net.mx2.jonesmedia.rcimx.net.
+profile.ak.fbcdn.net.
+levoyage.ru.
+www.zebra.com.
+photos-c.ak.fbcdn.net.
+teacherswithoutborders.org.
+kilikahechoamano.blogspot.com.
+noxius.wordpress.com.
+t0.gstatic.com.
+ec.atdmt.com.
+mansfeld.ipk-gatersleben.de.
+d2095607.xoom.it.
+www.msftncsi.com.
+vladasvet.ru.
+mkusdc.com.
+79.211.72.121.in-addr.arpa.
+a.root-servers.net.
+www.pianoaprimeravista.com.
+www.aswwaq.com.
+dl-client89.dropbox.com.
+smtp.omniprint.com.
+external.ak.fbcdn.net.
+ads.bluelithium.com.
+creative.ak.fbcdn.net.
+beybladebattles.hn.
+t2.gstatic.com.
+7.90.91.186.in-addr.arpa.
+www.facebook.com.
+105.17.156.190.in-addr.arpa.
+67.216.107.186.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+enter.premium.moviebox.com.
+a.root-servers.net.
+84.107.127.201.in-addr.arpa.
+blog-albertosaez.blogspot.com.
+educaresensenaravivir.blogspot.com.
+34.153.0.88.in-addr.arpa.
+creative.ak.fbcdn.net.
+197.233.141.201.in-addr.arpa.
+dm-download02.mozilla.org.
+mail.woo-hoo.com.
+www.places-to-visit.co.uk.
+www.transalpworldtour.com.
+www.wweplus.net.
+adsm.gameforge.de.
+external.ak.fbcdn.net.
+www.33tres.com.
+a1.da1.akamai.net.
+epcs.com.
+a8.sphotos.ak.fbcdn.net.
+photos-a.ak.fbcdn.net.
+70.219.25.218.in-addr.arpa.
+wdmpyj.com.
+h3plus.uiuc.edu.
+150.69.104.95.in-addr.arpa.
+d2058412.instant.xoom.it.
+www.theradiancefoundation.org.
+webcache.googleusercontent.com.
+www.regnumchristi.org.
+ilovepoems.com.
+googleads.g.doubleclick.net.
+dl.com.
+a5.sphotos.ak.fbcdn.net.
+2fyfmek2w.51tg.
+www.facebook.com.
+mail.ksshp.fi.
+surftheplanet.com.
+creative.ak.fbcdn.net.
+235.243.63.92.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+accounts.google.com.
+collection.theaa.com.
+feeds.feedburner.com.
+piedrasenlavesicula.org.
+a.root-servers.net.
+i4.ytimg.com.
+partner.googleadservices.com.
+photos-e.ak.fbcdn.net.
+sky.geocities.jp.
+www.pensador.info.
+mchst.com.
+121.2.16.172.in-addr.arpa.
+richmond.craigslist.org.
+s-static.ak.fbcdn.net.
+mail.yimg.com.
+e1.mc1615.mail.yahoo.com.
+fonts.gawker.com.
+adelphia.net.
+orh.ch.
+a5.sphotos.ak.fbcdn.net.
+img.myfreecams.com.
+www.jesustebusca.com.ar.
+www.formula-romantica.com.
+www.worldtangsoodo.com.
+hurdrolland.co.uk.
+_640_41_4.
+.
+thrd.com.
+accounts.google.com.
+exclusivepress.net.
+s-static.ak.fbcdn.net.
+.
+id.wikipedia.org.
+135.215.240.201.in-addr.arpa.
+blogsoloeducacion.blogspot.com.
+external.ak.fbcdn.net.
+program.avast.com.
+t-online.de.
+accounts.google.com.
+us.bc.yahoo.com.
+usuarios.multimania.es.
+fbcdn-profile-a.akamaihd.net.
+api.recaptcha.net.
+i3.ytimg.com.
+i9.mangareader.net.
+b.scorecardresearch.com.
+ricercashopping.virgilio.it.
+brownchecco.com.
+mail.carsondixie.com.
+109.60.168.192.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+l.yimg.com.
+c.msn.com.
+boysyes.blogspot.com.
+www.stats.gov.ck.
+p49-buy.itunes.apple.com.
+profile.ak.fbcdn.net.
+prod.support.belgacom.be.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+apps.facebook.com.
+206.33.173.190.in-addr.arpa.
+www.mounteverest.net.
+www-akm.imvu.com.
+mail.vermilionriverrealty.com.
+sopris.net.
+www.myxboxspot.com.
+www.entrebits.com.
+profile.ak.fbcdn.net.
+download.live.com.
+api.webrep.avast.com.
+192.161.202.94.in-addr.arpa.
+www.sullysrants.com.
+www.consultoresvalencia.com.
+a.root-servers.net.
+www.banquemondiale.org.lbe.worldbank.org.
+grin.khv.ru.
+yui.yahooapis.com.
+univ.oryol.ru.
+www.google.com.
+www.sofitel.com.
+photos-h.ak.fbcdn.net.
+otcnet.org.
+www.antiqueswords.com.
+toolbarqueries.google.com.
+a.root-servers.net.
+static.ak.fbcdn.net.
+aplcenmp.apl.jhu.edu.
+s-static.ak.fbcdn.net.
+vp.sip.messenger.msn.com.
+imagen01.247realmedia.com.
+64.105.105.190.in-addr.arpa.
+superiortanklines.com.mx2.superiortanklines.rcimx.net.
+digitalmudstudio.com.
+www.iteracion.cl.
+wallpapers4iphone.net.
+248.52.124.201.in-addr.arpa.
+teknicote.com.s7b1.psmtp.com.
+a2.sphotos.ak.fbcdn.net.
+ad.yieldmanager.com.
+154.77.161.189.in-addr.arpa.
+skyder.ru.
+www.ankeligteringen.nl.
+46.116.161.190.in-addr.arpa.
+efgoze.com.
+mail.dfo.gov.ru.
+ts4.mm.bing.net.
+error.flashget.com.
+www.e-belis.com.
+photos-g.ak.fbcdn.net.
+news.google.es.
+abudhabienv.com.
+100.148.252.201.in-addr.arpa.
+flowhot.info.
+bitty.com.
+pt-br.facebook.com.
+es-la.facebook.com.
+112.54.156.187.in-addr.arpa.
+www.fmjfee.com.
+www.pillositio.com.
+_355_12_0.
+a1.twimg.com.
+73.0.175.190.in-addr.arpa.
+94.180.3.76.in-addr.arpa.
+dnl-08.geo.kaspersky.com.
+219.26.163.189.in-addr.arpa.
+rougehotel.com.inbound15.mxlogicmx.net.
+news.barrons.com.
+a.root-servers.net.
+qestest.com.
+pricepricemech.com.
+39.8.47.186.in-addr.arpa.
+a.root-servers.net.
+a6.sphotos.ak.fbcdn.net.
+u-tlnrn2o7o.clb1.com.
+sqm.microsoft.com.
+www.google-analytics.com.
+photos-g.ak.fbcdn.net.
+webcache.googleusercontent.com.
+sites.google.com.
+a.root-servers.net.
+www.vinosdeargentina.com.
+www.hispanicprblog.com.
+footysphere.com.
+asa-schalttechnik.de.
+m.shopeuro.angrybirds.com.
+www.latinlover.com.au.
+www.freakquotes.com.
+cf.addthis.com.
+cocinarparalosmios.blogspot.com.
+193.38.210.94.in-addr.arpa.
+197.152.143.201.in-addr.arpa.
+uponor.ru.
+ct.ebis.ne.jp.
+5.252.190.189.in-addr.arpa.
+43.203.176.190.in-addr.arpa.
+mail.bemco-ipp.com.
+bs.serving-sys.com.
+belleza.facilisimo.com.
+adin.com.
+caminoholistico-mabel.blogspot.com.
+mail.legalcolombia.com.
+xtremespeeds.net.home.
+3lbvurryv.91ot.
+images.instagram.com.
+geo.messenger.services.live.com.
+www.pixelradio.com.mx.
+www.biggercity.com.
+addon.onlinevideoconverter.com.
+y25aks6xm.68yt.
+www.truckads.com.
+secure.wlxrs.com.
+premieralliance.com.mx3.at-net.rcimx.net.
+suggestqueries.google.com.
+www.twitter.com.
+www.ach.com.
+acorn.org.
+mtalk.google.com.
+55.183.168.192.in-addr.arpa.
+safebrowsing-cache.google.com.
+relay.data.edge.messenger.live.com.
+www.youtube.com.
+246.25.93.186.in-addr.arpa.
+m.facebook.com.
+www.tattoofinder.com.
+www-us.softsalad.com.
+peliculasonline2.com.
+ad-emea.doubleclick.net.
+www.unefilledulimmatquai.ch.
+www.bondagedesigns.com.
+mail.scrtc.com.
+pagead2.googlesyndication.com.
+www.prettyteenpictures.com.
+free-ebook-download-links.blogspot.com.
+twitter.com.
+checkip.dyndns.org.
+www.arcelormittal.tv.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+newtab.conduit-hosting.com.
+i4.ytimg.com.
+qu.wikipedia.org.
+www.facebook.com.
+palabradeclio-mepi.blogspot.com.
+www.youtube.com.
+www.facebook.com.
+www.google-analytics.com.
+89.71.55.65.in-addr.arpa.
+platform.stumbleupon.com.
+profile.ak.fbcdn.net.
+wps-dfp.com.
+www.hp.com.
+map.media6degrees.com.
+easy-google-search.blogspot.com.
+cs4341.vkontakte.ru.
+om.recruit.net.
+5-courier.push.apple.com.
+0-74.channel.facebook.com.
+by161w.bay161.mail.live.com.
+184.162.50.66.in-addr.arpa.
+www.balivillapoint.com.
+9gag.com.
+192.36.155.122.in-addr.arpa.
+a1737.g.akamai.net.
+speedtest.tune-up.com.
+a.root-servers.net.
+time.apple.com.
+a209.phobos.apple.com.edgesuite.net.
+www.googleadservices.com.
+gfx1.hotmail.com.
+www.mindeporte.gob.ve.
+163.27.7.189.in-addr.arpa.
+_772_41_0.
+218.36.155.189.in-addr.arpa.
+cf.addthis.com.
+www.icap.org.
+fbcdn-photos-a.akamaihd.net.
+a.root-servers.net.
+comcluster.cxense.com.
+g.ceipmsn.com.
+photos-e.ak.fbcdn.net.
+android.clients.google.com.
+acetec.com.mx.
+\(none\).
+www.youtube-nocookie.com.
+210.43.255.201.in-addr.arpa.
+87.57.238.166.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+mob.adwhirl.com.
+nww6j6151.60lh.
+ytimg.l.google.com.
+a.root-servers.net.
+158.42.192.190.in-addr.arpa.
+la.wikipedia.org.
+download304.avast.com.
+www.freerealms.com.
+box582.bluehost.com.
+i1b95ewnr.33en.
+www.alejandronogueira.com.
+filter1.lach.net.
+cameronparkcc.com.
+photos-e.ak.fbcdn.net.
+sfo.sysco.com.
+a14.t26.net.
+www.movieposteraddict.com.
+www.lair2000.net.
+ajax.googleapis.com.
+mail.yahoo.com.
+a1294.w20.akamai.net.
+a5.sphotos.ak.fbcdn.net.
+images04.olx.com.
+actife.com.
+safebrowsing.clients.google.com.
+ksn1-12-part2.kaspersky-labs.com.
+us.social.s-msn.com.
+uu1.orbitdownloader.com.
+download.windowsupdate.com.
+photos-a.ak.fbcdn.net.
+www.google.com.
+pt-br.facebook.com.
+js2.wlxrs.com.
+45.85.188.189.in-addr.arpa.
+newsrss.bbc.co.uk.
+download-akm.skype.com.
+sp.ask.com.
+sp.cwfservice.net.
+a1.sphotos.ak.fbcdn.net.
+riskyregencies.blogspot.com.
+accountservices.msn.com.
+www.y8.com.
+encuentromegaproyectosymineria.blogspot.com.
+a.root-servers.net.
+_965_19_2.
+il-solito-potere.blogspot.com.
+www.janes-kitchen-table.co.uk.
+pagead2.googlesyndication.com.
+a.root-servers.net.
+a7.sphotos.ak.fbcdn.net.
+scribe.twitter.com.
+www.tusletras.com.
+ws-cloud-msgplus.linkury.com.
+mail.dariusunrise.com.
+_859_19_7.
+ntp.glb.nist.gov.
+colstb.msn.com.
+50.4.204.190.in-addr.arpa.
+169.77.194.108.in-addr.arpa.
+gmpcompanies.com.
+guitar.nmts.ru.
+30.192.2.201.in-addr.arpa.
+au.download.windowsupdate.com.
+openxfront.iminent.com.
+youtu.be.
+229.101.15.88.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+45.65.32.196.in-addr.arpa.
+www.usp.com.au.
+blogs.microsoftvip.net.
+webcache.googleusercontent.com.
+sn3.mailshell.net.
+relay.voice.messenger.msn.com.
+405.webim0268.webim.myspace.com.
+jooble-br.com.
+plantasdeacuarios.com.
+s7.addthis.com.
+r._dns-sd._udp.0.55.211.10.in-addr.arpa.
+235.8.55.157.in-addr.arpa.
+_696_50_5.
+login.live.com.
+mobile.inova.si.
+www.lwflowers.com.
+www.jhj-consultancy.com.
+205.28.215.186.in-addr.arpa.
+graco.112.2o7.net.
+23.196.124.186.in-addr.arpa.
+mail.solve.net.
+jacaro.es.
+app.appatyze.com.
+a.root-servers.net.
+a3.sphotos.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+b3ck.blogspot.com.
+blog.es.twitter.com.
+maps.google.com.mx.
+msainc.us.
+www.music4games.net.
+time.windows.com.
+yo-conmigo.blogspot.com.
+lb._dns-sd._udp.lan.
+63.51.152.189.in-addr.arpa.
+pascual.com.mx.
+ad-apac.doubleclick.net.
+photos-g.ak.fbcdn.net.
+fntp.fr.
+a.root-servers.net.
+www.fwol.cn.
+.
+ec.atdmt.com.
+mail.ppcse.ru.
+www.google.com.
+b2p1anxd4.05ab.
+a1170.g.akamai.net.
+planetek.it.
+www.yaelsyummies.blogspot.com.
+adspaces.ero-advertising.com.
+a4.sphotos.ak.fbcdn.net.
+www2.cinetux.org.
+domino.harrassowitz.de.
+by2msg4020715.gateway.messenger.live.com.
+www.mini01.com.
+post.sotcom.ru.
+brilliantvoices.com.
+media.winamp.com.
+www.sqm.microsoft.com.
+a.ads2.msads.net.
+vp.sip.messenger.msn.com.
+networkworld.com.
+mistermaid.com.
+aide.livenet.fr.
+www.facebook.com.
+6f74db9c.filesonthe.net.
+254.19.145.78.in-addr.arpa.
+dudnyk.com.
+mail001.uniquemail.com.
+api.facebook.com.
+www.hammdann.net.
+96.148.59.199.in-addr.arpa.
+buildingcolorado.com.
+s-static.ak.fbcdn.net.
+77.10.26.83.in-addr.arpa.
+43.217.6.88.in-addr.arpa.
+by2msg3020417.gateway.messenger.live.com.
+p6y.ru.
+www.customgraffiti.net.
+liero.it.
+webres3.bullguard.ctmail.com.
+becauseiamagirl.ca.
+27-courier.push.apple.com.
+safebrowsing.clients.google.com.
+www.magictoolbox.com.
+84.106.229.71.in-addr.arpa.
+re-board.ru.
+io.bucyrus.cl.
+afiliados-natural.com.s108-67.furanet.com.
+external.ak.fbcdn.net.
+www.facebook.com.
+www.out-there.com.
+compras.periodistadigital.com.
+platform.twitter.com.
+cuanta-alegria-en-vidoes.blogspot.co.nz.
+live-ciner.mncdn.net.
+recetasdelaabuela.blogia.com.
+developers.facebook.com.
+www.onlineslotsentertainment.com.
+mx2.iweb.com.
+233.253.215.207.in-addr.arpa.
+www.nicosia.sgul.ac.cy.
+cdn.api.twitter.com.
+dulcelife.com.
+_336_36_1.
+sharphomeloans.com.
+ksn4-12.kaspersky-labs.com.
+gotovaja-rabota.ru.
+www.myspace.com.
+mta6.am0.yahoodns.net.
+s-external.ak.fbcdn.net.
+ns.r-style.ru.
+maps.googleapis.com.
+cri.crinet.com.
+136.89.75.190.in-addr.arpa.
+www.google.com.
+www.osirisibiza.com.
+halo-zero.softonic.com.
+eo-eo.facebook.com.
+partner.googleadservices.com.
+www.itsthecat.com.
+a6.sphotos.ak.fbcdn.net.
+www.mobileelements.com.
+www.pelo10.com.
+s-external.ak.fbcdn.net.
+db._dns-sd._udp.lan.
+www.morhipo.com.
+s.ccdn.ur-img.com.
+30.246.166.189.in-addr.arpa.
+aspweb.gslb.monster.com.
+www.gruposancorseguros.com.
+42.244.9.65.in-addr.arpa.
+www.litainete.lt.
+fbcdn-sphotos-a.akamaihd.net.
+orkut.com.
+68.171.13.187.in-addr.arpa.
+messenger.hotmail.com.
+a.root-servers.net.
+lemonodor.com.
+233.112.53.60.in-addr.arpa.
+free-php.net.ru.
+a.root-servers.net.
+www.elpalaciodehierro.com.mx.
+150.2.132.189.in-addr.arpa.
+im1.garenaconnect.com.
+pop3.hot.glbdns.microsoft.com.
+99.118.1.201.in-addr.arpa.
+artofflight-contest.fr.
+bachelorgirl.zzn.com.
+www.systems-biology.org.
+ib.adnxs.com.
+georgiabulletin.org.
+img3.pcpop.com.
+magrec.de.
+larcoco.wordpress.com.
+97.211.127.201.in-addr.arpa.
+capital-funding.com.
+a3.sphotos.ak.fbcdn.net.
+elizabethmelendez.com.
+alteks-servis.com.
+www.generadordenicks.com.
+sevenstar.spb.ru.
+singularlabs.com.
+www.tarot-numerologie.fr.
+lxt.com.
+mail.
+32.122.18.95.in-addr.arpa.
+www.olga-kurylenko.net.
+a.root-servers.net.
+b.scorecardresearch.com.
+a5.sphotos.ak.fbcdn.net.
+103.237.252.186.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+sp.cwfservice.net.
+photos-d.ak.fbcdn.net.
+chile.infomine.com.
+pixel.facebook.com.
+jenniferdelonge.tumblr.com.
+creative.ak.fbcdn.net.
+i1.ytimg.com.
+236.223.135.189.in-addr.arpa.
+vqu9:dodh.r57s2x9f.
+d2103197.xoom.it.
+254.234.254.190.in-addr.arpa.
+6uz6psorh.61il.
+highlandsinsurance.com.
+78.145.109.62.in-addr.arpa.
+js.dmtry.com.
+download339.avast.com.
+mystart.incredibar.com.
+i3.ytimg.com.
+www.pokeyplay.com.
+bmx.onxlti.com.redcondor.net.
+61.160.209.201.in-addr.arpa.
+www.dickinsonstate.edu.
+static.ak.facebook.com.
+238.29.116.174.in-addr.arpa.
+r.turn.com.
+plusone.google.com.
+www.agiletelecom.com.
+a995.mm1.akamai.net.
+163.42.140.89.in-addr.arpa.
+ece.ucdavis.edu.
+www.google.com.
+www.photomediashop.com.
+teredo.ipv6.microsoft.com.
+news.google.com.
+youtube-ui.l.google.com.
+www.descomsms.com.
+update.epyte.com.
+hotleathers.com.s9b2.psmtp.com.
+isatap.swdl.com.
+mediashifting.com.
+a8.sphotos.ak.fbcdn.net.
+download-soft.ru.
+14.229.152.187.in-addr.arpa.
+graph.facebook.com.
+ihl.state.ms.us.
+gamelux.ru.
+gnguttrnc.61uh.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+google-analytics.com.
+a.root-servers.net.
+a3.da1.akamai.net.
+59.21.254.201.in-addr.arpa.
+www.jcortazar.udg.mx.
+walgreens.vo.llnwd.net.
+a.root-servers.net.
+static.ak.fbcdn.net.
+33.117.200.190.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+webcache.googleusercontent.com.
+156.226.35.187.in-addr.arpa.
+www.fuelcells.us.
+95.11.243.189.in-addr.arpa.
+171.8.76.188.in-addr.arpa.
+cdn-static.liverail.com.
+89.152.99.213.in-addr.arpa.
+translate.google.com.mx.
+214.190.241.201.in-addr.arpa.
+es.noticias.yahoo.com.
+dns.msftncsi.com.
+a3.sphotos.ak.fbcdn.net.
+www.youtube.com.
+m.facebook.com.
+dns.msftncsi.com.
+archive.rec.org.
+130.210.138.189.in-addr.arpa.
+shiroin.deviantart.com.
+204.191.214.186.in-addr.arpa.
+docs.google.com.
+39.197.250.189.in-addr.arpa.
+tools.google.com.
+_503_33_5.
+livejournalgaua.hit.gemius.pl.
+g.ceipmsn.com.
+124.221.124.189.in-addr.arpa.
+time.chttl.com.tw.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+tracker.openbittorrent.com.
+www.fujifilm.eu.
+www.youtube.com.
+mail.izreps.com.
+4thletter.net.
+220.144.162.112.in-addr.arpa.
+mtalk.google.com.
+ajax.googleapis.com.
+accounts.google.com.
+131.22.55.190.in-addr.arpa.
+www.mardev.com.au.
+204.169.250.201.in-addr.arpa.
+s2.youtube.com.
+e3191.c.akamaiedge.net.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+a.root-servers.net.
+on.fb.me.
+mailwash46.pair.com.
+pccbs8i93.k35m2u0m.
+dibujandosonrisas.blogspot.com.
+178.137.255.83.in-addr.arpa.
+developers.facebook.com.
+.
+swarthmore.edu.
+falconvision.ru.
+www.editorialmerial.es.
+205.26.43.201.in-addr.arpa.
+www.trucoteca.com.
+vwsouth.com.
+www.hiderefer.com.
+www.facebook.com.
+mail.ugvclmail.com.
+www.toptyt.com.
+www.eset-la.com.
+purchase.mydirtyhobby.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+hp.zumodrive.com.
+hr.pce-group.com.
+www.facebook.com.
+windeslive.com.
+12.81.66.190.in-addr.arpa.
+213.190.54.65.zen.spamhaus.org.
+a8.sphotos.ak.fbcdn.net.
+centralizedlab.com.
+api.gamatar.org.
+conn.skype.com.
+79.169.160.189.in-addr.arpa.
+a3.da1.akamai.net.
+media.columbiamissourian.com.
+r._dns-sd._udp.lan.
+www.google.com.
+rs1.scribd.com.
+nasch-chat.ru.
+244.232.26.85.in-addr.arpa.
+www.losmejoresvideosdeinternet.net.
+www.romacess.com.
+a1957.da1.akamai.net.
+static.ak.fbcdn.net.
+c13.zedo.com.
+190.68.173.190.in-addr.arpa.
+connect.facebook.net.
+mjqwmtiwmtia.info.
+dvd.box.sk.
+82.85.164.189.in-addr.arpa.
+bank10.mi.ads.mp.mydas.mobi.
+mail.htc.nett.
+download712.avast.com.
+a1.sphotos.ak.fbcdn.net.
+webcache.googleusercontent.com.
+199.96.172.201.in-addr.arpa.
+checkip.dyndns.org.
+photobucket.com.
+greenfieldpro.com.
+dispatch.lite.adlesse.com.
+distilleryimage10.instagram.com.
+p04-fmfmobile.icloud.com.akadns.net.
+creareconilcuore.blogspot.com.
+35.28.94.186.in-addr.arpa.
+www.facebook.com.
+quintess.com.inbound15.mxlogic.net.
+sup.live.com.
+db._dns-sd._udp.0.0.168.192.in-addr.arpa.
+jsbin.tumblr.com.
+senderra.com.
+u24.eset.com.
+en-us.fxfeeds.mozilla.com.
+miscritscdn.brokenbulbstudios.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+b-0.19-2305f479.8030081.1518.19d3.3ea1.210.0.h16pz26nu19r8ezkn3t14c9lli.avqs.mcafee.com.
+ibizabeatreview.podbean.com.
+photos-f.ak.fbcdn.net.
+blazemail.com.
+r.turn.com.akadns.net.
+143.139.229.77.in-addr.arpa.
+www.ricardosalinas.com.
+karelia-granit.ru.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.facebook.com.
+142.8.17.190.in-addr.arpa.
+165.22.82.62.in-addr.arpa.
+191.192.194.117.in-addr.arpa.
+www.paypalbisnis.com.
+a1.sphotos.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+axa-sunlife.co.uk.
+a.root-servers.net.
+altfarm.mediaplex.com.
+www.crunchbase.com.
+newtscape.com.
+platform.twitter.com.
+151.153.101.118.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+developers.facebook.com.
+45.241.155.72.in-addr.arpa.
+_417_71_1.
+crl.microsoft.com.
+239.247.141.201.in-addr.arpa.
+www.bbc.co.uk.
+amsprd0104.outlook.com.
+203.33.168.192.in-addr.arpa.
+mx.procilia.com.
+oboedit.org.
+pablo-javier-perez-fuentes.suite101.net.
+talongroup.biz.
+used.guitarcenter.com.
+a.root-servers.net.
+iad09s10.iad09s11.iad09s14.iad09s15.iad09s16.iad09s17.iad09s20.iad09s21.o-o.v2.lscache6.c.youtube.com.
+_114_92_8.
+fusion.google.com.
+fbcdn-profile-a.akamaihd.net.
+254.83.186.190.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+www.decolar.com.
+mapscroll.blogspot.com.
+static-0.farmville.zgncdn.com.
+logictel.ru.
+tracking.novem.pl.
+baysidecontractors.com.
+profile.ak.fbcdn.net.
+todointeresante.wordpress.com.
+ping3.teamviewer.com.
+.
+developers.facebook.com.
+media.admob.com.
+toolbarqueries.google.com.
+studyworld.us.intellitxt.com.
+212.93.44.190.in-addr.arpa.
+relay2.sitel.com.ua.
+www.avisooportuno.mx.
+250.147.209.39.in-addr.arpa.
+tvmax-9.com.
+teredo.ipv6.microsoft.com.
+www.historiasdechile.cl.
+safebrowsing.clients.google.com.
+www.update.microsoft.com.
+89.80.198.190.in-addr.arpa.
+meridiem91.blogspot.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+7.6.107.186.in-addr.arpa.
+www.wikio.es.
+omniamerican.org.
+129.18.28.98.in-addr.arpa.
+us.blackberry.com.
+berniekeating.com.
+www.gmail.com.
+mail.proviewrussia.ru.
+clock.nyc.he.net.
+glb-ads.intergi.adtechus.com.
+100.98.157.189.in-addr.arpa.
+rcp.na.blackberry.com.
+xzn8e9tc2.y47u6p1u.
+www.facebook.com.
+www.celebuzz.com.
+a-0.19-a309d000.130092.1518.19d4.3ea1.210.0.cvtecms8k26gt7dsd4f6hnaeht.avqs.mcafee.com.
+apps.facebook.com.
+captcha.chat.yahoo.com.
+eqxe7nppd.53fx.
+mail.google.com.
+mscrl.microsoft.com.
+www.starnow.ie.
+malakhov.spb.su.
+wombat.nen-inc.com.
+75.10.85.186.in-addr.arpa.
+ds.serving-sys.com.
+lucyhaleweb.org.
+236.32.34.187.in-addr.arpa.
+visitarmexico.net.
+top.amateuralbum.net.
+artidd.com.
+www.netgear.com.
+accidentalmommies.com.
+aux.planetmath.org.
+www.neruda.cl.
+a6.sphotos.ak.fbcdn.net.
+mail.google.com.
+tbr.ask.com.
+sdbs.adb.org.
+www.rabobank.jobs.
+plus.google.com.
+cdn.fastclick.net.
+profile.ak.fbcdn.net.
+www.pacoelviraenglish.blogspot.com.
+marketplace.honda-tech.com.
+www.facebook.com.
+edge.bredg.com.
+mx1c11.megamailservers.com.
+ballingerpublishing.com.1.arsmtp.com.
+.
+cf.cgl.com.
+csi.gstatic.com.
+fujitsugeneral.com.au.
+a.root-servers.net.
+ns3.mgn.net.
+www.aquariuscasinoresort.com.
+il06edm06.corp.mot.com.
+www.leisuretown.com.
+6.125.252.46.in-addr.arpa.
+m.xp1.ru4.com.
+tracking.batanga.com.
+miis.edu.ru.
+csi.gstatic.com.
+lovelineshow.com.
+lost.seriesasd.com.
+dtboot.orbitdownloader.com.
+86.117.19.177.in-addr.arpa.
+134.61.194.68.in-addr.arpa.
+assets2.helium.com.
+pbelec.com.
+a.root-servers.net.
+time.windows.com.
+apis.google.com.
+external.ak.fbcdn.net.
+img100.xvideos.com.
+zyryanov.ru.
+external.ak.fbcdn.net.
+85.71.27.108.in-addr.arpa.
+tudvdrip.blogspot.com.
+casalelizrodri.blogspot.com.
+30.media.tumblr.com.
+www.vintageprojects.com.
+mail-2.diabet-news.ru.
+wer.microsoft.com.
+loto.scn.ru.
+tools.google.com.
+www.thepier.org.
+images04.olx-st.com.
+81.185.15.180.in-addr.arpa.
+r._dns-sd._udp.lan.
+con8sylo6.q08v3j2n.
+faqa.net.
+mx.answers.yahoo.com.
+db._dns-sd._udp.0.147.168.192.in-addr.arpa.
+www.extremetube.com.
+photos-g.ak.fbcdn.net.
+img6.planetadelibros.com.
+d2092951.xoom.it.
+123.180.138.190.in-addr.arpa.
+instagr.am.
+s-translate.ru.
+sc.sweetim.com.
+60.1.1.10.in-addr.arpa.
+ads.contentabc.com.
+hearth.is.
+38.143.25.201.in-addr.arpa.
+www.hermesmedical.com.
+teolatosno.ru.
+video.xnxx.com.
+254.66.61.189.in-addr.arpa.
+ad.doubleclick.net.
+birch.ssec.wisc.edu.
+b.scorecardresearch.com.
+www.star-advertising.com.
+profile.ak.fbcdn.net.
+upload.streamzoo.com.
+www.ebaybag.com.
+mail.informedx.com.
+www.anunciadero.com.
+juridicosonline.bligoo.com.
+themasterstouch.com.
+54.248.222.189.in-addr.arpa.
+202.29.36.186.in-addr.arpa.
+www.imperialinnovations.co.uk.
+www.davidtutera.com.
+www.girlsgogames.ru.
+www.facebook.com.
+dr._dns-sd._udp.0.101.168.192.in-addr.arpa.
+s0.uvnimg.com.
+db8.net-filter.com.
+www.bmwra.org.
+mail.google.com.
+sites.google.com.
+www.whoisthisphone.com.
+api.pixel-mags.com.
+teredo.ipv6.microsoft.com.
+116.54.226.189.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+photos-h.ak.fbcdn.net.
+st.oros.karelia.ru.
+164.8.0.10.in-addr.arpa.
+nimir.com.
+169796.frases10.info.
+7pcl2kcwo.o53j1c5j.
+zgn.static.zynga.com.
+s10.histats.com.
+i818.photobucket.com.
+plus.google.com.
+ic.tynt.com.
+ar-ar.facebook.com.
+shop.ebay.com.
+3cp9lcoq32dpn-c.c.yom.mail.yahoo.com.
+46.100.173.190.in-addr.arpa.
+bellsouth.net.
+yakimaclarion.com.
+www.google.com.
+t1.gstatic.com.
+hosthotels.com.
+109.216.136.82.in-addr.arpa.
+147.148.141.189.in-addr.arpa.
+147.51.42.190.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+www.ingenierocivilinfo.com.
+153.130.9.186.in-addr.arpa.
+mfddlaw.com.
+loadbalancer.jn3jokm.com.
+mk.wikipedia.org.
+3b363b2490002cd1e5b508a91d696810.info.
+223.181.127.200.in-addr.arpa.
+kuige1cti.33pc.
+a6.sphotos.ak.fbcdn.net.
+www.southwillard.com.
+donking.com.
+teredo.ipv6.microsoft.com.
+inbound.informfitness.com.netsolmail.net.
+apps.facebook.com.
+ratasyrockabilly.blogspot.com.
+mail-attachment.googleusercontent.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+esonora.gob.mx.
+a3.sphotos.ak.fbcdn.net.
+66.177.9.186.in-addr.arpa.
+profile.ak.fbcdn.net.
+a1.sphotos.ak.fbcdn.net.
+am686op8ejk5aahb9kk6k985qk.gcdn.biz.
+a.root-servers.net.
+157.125.14.181.in-addr.arpa.
+www.sexscience.org.
+api.facebook.com.
+a.root-servers.net.
+celularesnokiasamsungmotorolalg.blogspot.com.
+mail.guardiancomfort.com.
+tommy2.net.
+a6.sphotos.ak.fbcdn.net.
+e-2dj6wjkockcjkhp.stats.esomniture.com.
+www.isimarsivi.com.
+161.123.235.201.in-addr.arpa.
+166.113.251.189.in-addr.arpa.
+feokon.ru.
+operadays.eu.
+35.76.236.63.in-addr.arpa.
+www.monsterdivx.com.
+100-litsa.ru.
+fqsf.com.
+www.baseball-almanac.com.
+psgw.t-mobilesgws.com.
+20.75.179.190.in-addr.arpa.
+www.youtube.com.
+a8.sphotos.ak.fbcdn.net.
+oficedepot.com.
+memolaesto.blogspot.com.
+www.m.
+www.ucdenver.edu.
+rd-legal.com.
+18.250.115.200.in-addr.arpa.
+pop3.live.com.
+147.44.6.108.in-addr.arpa.
+creative.ak.fbcdn.net.
+booksbikesboomsticks.blogspot.com.
+forum.khoone.org.
+www.facebook.com.
+mail2.angara.ru.
+ccl.rutgers.edu.
+www.nmc.edu.
+foto-natura-huesca.blogspot.com.
+widgets.amung.us.
+fbcdn-profile-a.akamaihd.net.
+a1.sphotos.ak.fbcdn.net.
+time.chttl.com.tw.
+newtab.conduit-hosting.com.
+57.98.244.71.in-addr.arpa.
+www.l.google.com.
+accounts.google.com.
+oscex-en.url.trendmicro.com.
+250.252.16.190.in-addr.arpa.
+5.96.134.189.in-addr.arpa.
+241.23.250.189.in-addr.arpa.
+www.ratesupermarket.ca.
+elm.cl.
+apps.facebook.com.
+25.231.88.79.in-addr.arpa.
+amoviesz.com.
+peeterha.erroratyou.pw.
+pheedo.msnbc.msn.com.
+pagead2.googlesyndication.com.
+www.avionews.com.
+tools.l.google.com.
+golosnadezhdi.ru.
+www.ufs.ac.za.
+178.86.177.195.in-addr.arpa.
+24.109.222.201.in-addr.arpa.
+plusone.google.com.
+www.stopbadware.org.
+a.root-servers.net.
+photos-h.ak.fbcdn.net.
+gfx1.hotmail.com.
+config.mobile.wxbug.com.
+photos-h.ak.fbcdn.net.
+200.90.157.123.in-addr.arpa.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.gamebasics.co.uk.
+vp.sip.messenger.msn.com.
+ad-dc2.adtech.de.
+yahoo.com.
+midominio.com.
+a.root-servers.net.
+ar-ar.facebook.com.
+savingssavingsandmoresavings.net.
+p08-keyvalueservice.icloud.com.
+www.seti-inst.edu.
+udc.msn.com.
+1.bp.blogspot.com.
+wserectors.com.
+b-0.19-2309b089.715c0.1518.19d4.3ea1.410.0.l48wk63hd6u11dcp1quez3wqmq.avqs.mcafee.com.
+rt.com.
+rotativover.com.mx.
+a.root-servers.net.
+beacon-1.newrelic.com.
+knicksfanaticsblog.com.
+www.apuntesgestion.com.
+a.root-servers.net.
+www.como-e.com.
+www.facebook.com.
+www.folder-guard.com.
+commons.wikimedia.org.
+www.belkin.com.
+softel.ntl.ru.
+a4.da1.akamai.net.
+malah.biz.
+91.87.229.189.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+hardwarefan.com.
+it.coinmill.com.
+www.casualadultgamers.com.
+realplayer.com.
+otz2diys3.d23o8z3w.
+log.client.akadns.net.
+41.45.134.190.in-addr.arpa.
+apple.com.
+21diciembre2012.foroes.net.
+xwall.bridgecom.com.
+72.206.154.62.in-addr.arpa.
+cuc.claremont.edu.s7a2.psmtp.com.
+philadelphia.cbslocalfanshop.com.
+dfrf.daisypath.com.
+www.naturaltranssexuals.com.
+167.40.46.83.in-addr.arpa.
+194.65.141.201.in-addr.arpa.
+a.root-servers.net.
+a.root-servers.net.
+byfiles.storage.msn.com.
+jeep.com.
+l.yimg.com.
+cs10526.vk.com.
+164.233.48.178.in-addr.arpa.
+exsib.ru.
+140.202.68.76.in-addr.arpa.
+ads1.msads.net.
+jm-ingles.foroactivo.net.
+130.18.204.67.in-addr.arpa.
+rochester.it.com.
+_674_32_5.
+secure.wlxrs.com.
+mail.gladtech.netd.com.
+sbcglobal.net.
+smtp.monavie.com.
+cdn.api.twitter.com.
+mail.dentforcongress.com.
+idigjesus.com.
+a2.sphotos.ak.fbcdn.net.
+s.youtube.com.
+marshallhotels.com.
+pan.starmedia.com.
+cityvillefb1.static.zgncdn.com.
+account.live.com.
+profile.ak.fbcdn.net.
+proyectofueradeserie.blogspot.com.
+41.62.44.190.in-addr.arpa.
+122.165.1.88.in-addr.arpa.
+191.147.137.186.in-addr.arpa.
+_ldap._tcp.4577284e-c7dc-4f42-9890-bae63effdf68.domains._msdcs.vetco.com.
+mx1.effortel.ru.
+www.df-gay.com.mx.
+www.pancrase.org.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.yimg.com.
+a.root-servers.net.
+www.facebook.com.
+fortune-int.en.alibaba.com.
+seabretelon.blogspot.com.
+www.hipertimestico.com.
+kisianmail1.kisian.mimcom.net.
+touch.net.
+cluster8a.us.messagelabs.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+s.ytimg.com.
+247.96.76.188.in-addr.arpa.
+mail.crewing.ru.
+p012a.polyvore.com.
+worldgeo.ru.
+clients4.google.com.
+dl.jav4u.net.
+matrixres.com.
+s2.youtube.com.
+ksn2-12.kaspersky-labs.com.
+0-278.channel.facebook.com.
+sro.whatsapp.net.
+m.facebook.com.
+www.sabidurias.com.
+docs.google.com.
+www.massiveattack.clan.su.
+pixel.quantserve.com.
+ksn2-12.kaspersky-labs.com.
+static.ak.fbcdn.net.
+static.ak.fbcdn.net.
+sp.cwfservice.net.
+www.google.com.
+www.facebook.com.
+a5.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+pagead2.googlesyndication.com.
+18girls.ru.
+zsnes.programas-gratis.net.
+m.accuweather.com.
+a.root-servers.net.
+concheck.nimbuzz.com.
+www.dominiopublico.gov.br.
+www.behindthathole.com.
+a.root-servers.net.
+dsn4.d.skype.net.
+49.132.46.118.in-addr.arpa.
+platform.twitter.com.
+90.185.91.80.in-addr.arpa.
+t.co.
+dc446.4shared.com.
+twitter.com.
+a5.sphotos.ak.fbcdn.net.
+tbcocala.com.
+ads1.msn.com.
+google.com.
+smtp02.radioholland.net.
+34.26.62.186.in-addr.arpa.
+platform.ak.fbcdn.net.
+253.108.136.186.in-addr.arpa.
+poker-academy.com.
+static.ak.fbcdn.net.
+0.5852475.com.
+fbcdn-profile-a.akamaihd.net.
+r._dns-sd._udp.x\001h.
+12.165.14.217.in-addr.arpa.
+s.youtube.com.
+us.mc1813.mail.yahoo.com.
+www.zwinky.com.
+cachecasino.ll.eurogrand.com.
+www.davidellischrysler.com.
+www.facebook.com.
+www.patrimoniohistorico.org.ar.
+223.69.134.187.in-addr.arpa.
+22.224.171.69.in-addr.arpa.
+mobile-3g-dyn-bu-48-172.zappmobile.ro.
+mihijoconbuenanotaenmate.com.
+m.webtrends.com.
+microsoft.com.mx.
+www.myspace.com.
+www.l.google.com.
+www.googleadservices.com.
+www.alcoulson.com.
+www.verdaderaseduccion.com.
+ja.y8.com.
+et7jzfujd.28xt.
+www.msnarea.com.
+posicionesalhacerelamor.com.
+ec.atdmt.com.
+api-read.facebook.com.
+hebbo-chilexx.ciudadhabbo.com.
+223.236.229.190.in-addr.arpa.
+deucescrackedrakeback.net.
+22.17.191.189.in-addr.arpa.
+ksn1-11-part1.kaspersky-labs.com.
+connect.facebook.net.
+syrcafe.com.
+formatfactory.softpedia.com.
+182.234.63.178.bl.spamcop.net.
+www.google-analytics.com.
+a.root-servers.net.
+de.wikipedia.org.
+sup.live.com.
+ocsp.webspace-forum.de.
+www.anunciosdeveracruz.com.
+prideofthetide.com.
+it-it.facebook.com.
+www.fuerteloko.com.
+162.79.9.177.in-addr.arpa.
+sedecalusa.com.
+www.truste.org.
+166.1.123.187.in-addr.arpa.
+www.alarab.net.
+cwuk.com.
+www.drleonards.com.
+www.google.com.
+113.34.110.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+i1.ytimg.com.
+twitter.com.
+eu.wikipedia.org.
+googleads.g.doubleclick.net.
+105.224.233.190.in-addr.arpa.
+pixel.invitemedia.com.
+cdn.api.twitter.com.
+www.eku.edu.
+secure.etype.com.
+directory.services.live.com.
+content.dl-rms.com.
+a.root-servers.net.
+apis.google.com.
+tayabeixo.org.
+194.93.24.195.in-addr.arpa.
+messager.com.
+a.root-servers.net.
+th.wikipedia.org.
+smtp.mailserv.in.
+teredo.ipv6.microsoft.com.
+mscrl.microsoft.com.
+c0.echoenabled.com.
+77.178.243.201.in-addr.arpa.
+www.ownedcore.com.
+embutidosrios.blogspot.com.
+frogs.org.au.
+www.youtube.com.
+158.13.141.201.in-addr.arpa.
+theansiblog.wordpress.com.
+xmat.com.
+42.156.244.189.in-addr.arpa.
+222.163.166.189.in-addr.arpa.
+tiendamexico.com.mx.
+www.bestgolftipsandtricks.com.
+www.google.com.
+nl.wikipedia.org.
+ms.samwellg.com.
+wikimediafoundation.org.
+c.atdmt.com.
+29.205.233.46.in-addr.arpa.
+pixel.facebook.com.
+download.windowsupdate.com.
+www.youtube.com.
+www.expedia.co.in.
+www.kshe95.com.
+photos-c.ak.fbcdn.net.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+healthy-ojas.com.
+mail.citymt.ru.
+60.66.111.95.in-addr.arpa.
+google.com.
+ads.yimg.com.
+millaray.un-clic-por-el-bosque.com.
+profile.ak.fbcdn.net.
+google.com.mx.
+a.root-servers.net.
+www.penguin.co.nz.
+city.yatsushiro.lg.jp.
+webcache.googleusercontent.com.
+a.root-servers.net.
+88.142.249.77.in-addr.arpa.
+safebrowsing-cache.google.com.
+billing.sharo4ka.ru.
+torrentz.eu.
+uidai.sifyitest.com.
+a.root-servers.net.
+csi.gstatic.com.
+images.google.com.
+facebook.com.
+emailium.com.
+creditway.ru.
+c.atdmt.com.
+cedasecuador.com.
+a5.sphotos.ak.fbcdn.net.
+www.facebook.com.
+127.0.0.1.
+infothread.org.
+www.coachsfactory-online.net.
+a.root-servers.net.
+a.root-servers.net.
+m.trendenciasbelleza.com.
+email.1800baskets.com.
+www.facebook.com.
+profile.ak.fbcdn.net.
+www.crookedtimber.org.
+www.google.com.
+2bebullyfree.com.
+www.air.flyingway.com.
+teredo.ipv6.microsoft.com.
+237.18.17.76.in-addr.arpa.
+platform.twitter.com.
+pagead2.googlesyndication.com.
+www.youtube.com.
+mail.reycorporacion.com.
+a.root-servers.net.
+40.197.202.190.in-addr.arpa.
+www.google-analytics.com.
+sqqamnjx7.o13l3h8q.
+rio-toys.ru.
+webcache.googleusercontent.com.
+ocsp.thawte.com.
+static.ak.fbcdn.net.
+edge.hostuc.com.
+136.153.63.24.in-addr.arpa.
+trucosmasgame.blogspot.com.
+secure.wlxrs.com.
+fbcdn-photos-a.akamaihd.net.
+226.84.178.190.in-addr.arpa.
+www.wmnf.org.
+www.mcity.com.au.
+banner-in.net.
+creative.ak.fbcdn.net.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+jqtxjs6qs.24tg.
+r.co.igameunion.com.
+b.scorecardresearch.com.
+1804289383.localhost.
+nyxstyle.com.
+174.214.92.201.in-addr.arpa.
+www.20minutos.es.
+33.161.225.77.in-addr.arpa.
+a.root-servers.net.
+translate.googleapis.com.
+photos-g.ak.fbcdn.net.
+www.dvrserver.net.
+gfx3.hotmail.com.
+187.113.227.77.in-addr.arpa.
+84.136.114.200.in-addr.arpa.
+www.facebook.com.
+www.equipodinero.com.
+zumo.at.
+225.30.82.190.in-addr.arpa.
+www.allvideotrafficschool.com.
+secure.wlxrs.com.
+dftuz.unizar.es.
+b.f.8.8.5.3.f.8.b.1.f.3.9.1.0.2.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+a1725.l.akamai.net.
+www.ci.lafayette.or.us.
+www.yugiohtheabridgedseries.com.
+mulkcpulx.88wg.
+tc11.easythumbhost.com.
+a7.sphotos.ak.fbcdn.net.
+167.161.26.201.in-addr.arpa.
+175.9.248.62.in-addr.arpa.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+179.60.139.98.in-addr.arpa.
+mx.mikecorey.com.
+check6.facebook.com.
+pic.zdface.com.
+252.67.11.187.in-addr.arpa.
+twitter.com.
+api.twitter.com.
+252.1.84.78.in-addr.arpa.
+245.198.30.186.in-addr.arpa.
+twitter.com.
+grupoautofin.com.
+developers.facebook.com.
+profile.ak.fbcdn.net.
+vaiogatenotifications2.sony-europe.com.
+171.252.184.67.in-addr.arpa.
+harrisonsmythe.com.
+www.bocetoweb.net.
+mail.bhc.car-crm.com.
+mail.kalleh.com.
+a3.sphotos.ak.fbcdn.net.
+catholicspotlight.com.
+seguros-moto.arpem.com.
+ghandshake.com.
+im12.gulfup.com.
+a.root-servers.net.
+s.youtube.com.
+www.google.com.mx.
+www.canew.org.
+google.com.
+www.mindfly.com.
+www.argentinabusca.com.
+www.microsoft.com.
+www.rulez.org.ua.
+102.155.145.201.in-addr.arpa.
+p.twimg.com.
+luber.obladm.msk.su.
+ytimg.l.google.com.
+a2.sphotos.ak.fbcdn.net.
+www.google.com.
+share.lockerz.com.
+svcs.ebay.com.
+au.download.windowsupdate.com.
+32.43.214.201.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+hi-in.facebook.com.
+58.45.194.180.in-addr.arpa.
+firstunion.com.
+media.pron.com.
+latinax100pre.blogspot.com.
+mail.google.com.
+www.tv.nu.
+90.172.160.201.in-addr.arpa.
+124.74.37.190.in-addr.arpa.
+d15gt9gwxw5wu0.cloudfront.net.
+googleads.g.doubleclick.net.
+test-rt.liftdna.com.
+allaccess.biancabeauchamp.com.
+os.evoice.com.
+bet.iach.cz.
+mosdomen.ru.
+syndication.traffichaus.com.
+fr-fr.facebook.com.
+cookingquinn.blogspot.com.
+configuration.apple.com.
+remaxcedarrapids.com.
+osxbook.com.
+docs.portfoliodesign.org.
+a.root-servers.net.
+static2.avast.com.
+pt-br.facebook.com.
+sfg.ru.
+ksn1-11-part2.kaspersky-labs.com.
+cermics.enpc.fr.
+219.250.220.186.in-addr.arpa.
+www.canterburytales.org.uk.
+21.0.168.192.in-addr.arpa.
+mail.ukrpromtrans.com.
+www.thevoicemyanmar.com.
+ksn2-12.kaspersky-labs.com.
+ip1.dynupdate.no-ip.com.
+ftp.uu.net.
+b.scorecardresearch.com.
+i38.tinypic.com.
+www.enlacespanama.com.
+204.73.12.88.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+regrus.spb.ru.
+a2.sphotos.ak.fbcdn.net.
+widgets.twimg.com.
+suburbanhockey.com.1.0001.arsmtp.com.
+ars.oscar.aol.com.
+static.ak.fbcdn.net.
+171.29.11.186.in-addr.arpa.
+mail.google.com.
+233.241.143.71.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+sanyopg.com.my.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+fxfeeds.mozilla.com.
+static.ak.fbcdn.net.
+128.176.170.201.in-addr.arpa.
+www.lancel.com.
+semstroy.ru.
+123.247.32.189.in-addr.arpa.
+www.droitpublic.net.
+a.root-servers.net.
+a.root-servers.net.
+sf2.yourpractice.com.
+ccbltd.com.
+www.pem.org.
+safebrowsing-cache.google.com.
+www.thomascrampton.com.
+download661.avast.com.
+eco-forest.com.
+bud.indirect.com.
+photos-e.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+mail.alfaplast.ru.
+bluevalleybrand.com.s6b1.psmtp.com.
+wpad.
+vb.qloob.com.
+26.230.228.189.in-addr.arpa.
+126.219.0.123.in-addr.arpa.
+social.successtelevision.com.
+download.microsoft.com.
+a.root-servers.net.
+sebringraceway.com.
+ebrinc.com.s8a2.psmtp.com.
+dasletzteeinhorn.ch.
+deathgrindfreak.blogspot.com.
+linkhelp.clients.google.com.
+apps.facebook.com.
+www.produ.com.
+api.geo.kontagent.net.
+www.facebook.com.
+a.root-servers.net.
+trophy01.np.community.playstation.net.
+ow.ly.
+www.otomania.net.
+shawcomm.com.
+clients1.google.com.
+profile.ak.fbcdn.net.
+dl-client477.dropbox.com.
+blair.tcaps.net.
+pubads.g.doubleclick.net.
+118.205.255.84.in-addr.arpa.
+blog.mercadoshops.com.
+a.root-servers.net.
+ads.hotgirlsgames.net.
+terra.alts.net.
+enlightenhairstudio.com.
+0-250.channel.facebook.com.
+dtphila.com.
+profile.ak.fbcdn.net.
+i1.ytimg.com.
+fbcdn-profile-a.akamaihd.net.
+ncmail.net.
+photos-c.ak.fbcdn.net.
+62.154.84.86.in-addr.arpa.
+people.uleth.ca.
+sexcamy.ch.
+lookworldusa.com.
+www.kizi-games.com.
+a749.g.akamai.net.
+www.chillout.fm.
+blog.open-office.es.
+alweeam.com.
+pixel.facebook.com.
+a.root-servers.net.
+graph.facebook.com.
+84.114.27.46.in-addr.arpa.
+www.a12.ro.
+s.youtube.com.
+es-la.facebook.com.
+safebrowsing-cache.google.com.
+www.androidenea.com.
+facebook.comac.
+budget101.com.
+iloveyouman.com.
+www.imdb.com.
+spam.globaltac.com.
+maiquiflores.over-blog.es.
+pagead2.googlesyndication.com.
+pixel.facebook.com.
+centralamericadata.com.
+achtenberg.com.
+www.locosporlastelas.com.ar.
+support.google.com.
+db._dns-sd._udp.0.55.211.10.in-addr.arpa.
+mitecnologico.com.
+www.google.com.
+mx3.ksk.co.in.
+www.ojocientifico.com.
+ladificilsencillez-online.blogspot.com.
+29.37.173.190.in-addr.arpa.
+243.34.114.174.in-addr.arpa.
+login.yahoo.com.
+136.9.168.192.in-addr.arpa.
+135.111.55.65.zen.spamhaus.org.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+billcam.axiscam.net.
+a1.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+backgroundlayoutsforfacebook.com.
+sns.goodgamestudios.com.
+gfx3.hotmail.com.
+147.128.92.201.in-addr.arpa.
+streaming.playwire.com.
+facedesign.us.
+l1.yimg.com.
+graph.facebook.com.
+hoteliers.wego.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cherrysage.com.
+130.86.227.189.in-addr.arpa.
+gfx2.hotmail.com.
+www.siuxy-pets.com.
+smak.ru.
+alleytheatre.com.
+ja-jp.facebook.com.
+www.google-analytics.com.
+mail.tgk13.ru.
+cust22700-1.in.mailcontrol.com.
+newsletter.iciparisxl.nl.
+www.correo.unam.mx.
+login.live.com.
+photos-b.ak.fbcdn.net.
+www.getios.com.
+www.elnuevoherald.com.
+161.100.9.186.in-addr.arpa.
+72.148.45.189.in-addr.arpa.
+bit.ly.
+mail.iristel.com.
+187.65.66.186.in-addr.arpa.
+www.facebook.com.
+www.yahoo.com.
+mail.centreprint.net.
+my.bta.kz.
+centrodecocinaygastronomia.com.
+cheriefm.radio.fr.
+correo.adylog.com.
+app140895852605282.socialappspot.com.
+350letras.blogspot.com.
+158.5.168.192.in-addr.arpa.
+251.217.176.187.in-addr.arpa.
+newtab.conduit-hosting.com.
+www.comipems.org.mx.
+orcart.facebook.com.
+www.facebook.com.
+136.209.57.186.in-addr.arpa.
+i.ytimg.com.
+twitter.com.
+static.xvideos.com.
+apex.bryansk.ru.
+0-299.channel.facebook.com.
+google.com.
+media.mpgomatic.com.
+www.facebook.com.
+www.tsa.es.
+cdn.api.twitter.com.
+safebrowsing.clients.google.com.
+todosobrenickelodeon.blogspot.com.
+a.root-servers.net.
+lakelandproair.com.
+lostandfoundandconnectionsabound.blogspot.com.
+5oyystxh5.94od.
+yuec7yln9.90bc.
+250.103.58.201.in-addr.arpa.
+s.youtube.com.
+putlockersearch.com.
+fonts.googleapis.com.
+www.google.es.
+dracoandginny.com.
+www.google.com.
+163.245.3.211.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+www.mosaizer.com.
+t0.gstatic.com.
+ad.harrenmedianetwork.com.
+accountservices.msn.com.
+234.69.91.190.in-addr.arpa.
+143.138.126.122.in-addr.arpa.
+www.google.com.
+a489.w11.akamai.net.
+view.atdmt.com.
+www.jane-wyman.com.
+a.root-servers.net.
+ad.handycafe.com.
+ks-v.ru.
+237.224.124.113.in-addr.arpa.
+badges.coroflot.com.
+www.visto-eua.com.br.
+1-i.ru.
+fs-wti9.wavetechinc.com.
+a-0.19-23091081.c8a0082.1518.19d4.3ea1.210.0.fgsm3869zqsua6rhzrlaju4v6t.avqs.mcafee.com.
+a.root-servers.net.
+img115.imageshack.us.
+www.cinescape.tv.
+254.95.48.190.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ad.yieldmanager.com.
+www.microsoft.com.
+www.baidu.com.
+www.yomolomazo.es.vg.
+moscow-offices.ru.
+44.35.43.186.in-addr.arpa.
+www.facebook.com.
+1st-line.com.
+fctoplist.uuuq.com.
+32.250.49.95.in-addr.arpa.
+creative.ak.fbcdn.net.
+104.212.1.99.in-addr.arpa.
+ns2.colocationamerica.com.
+profile.ak.fbcdn.net.
+s5.scribdassets.com.
+tk6pjyxt:.31al.
+25.media.tumblr.com.
+safebrowsing.clients.google.com.
+mail.antenne-wien.at.
+giraffeelizabeth.wordpress.com.
+asseeninbyjosia.wordpress.com.
+pixel.facebook.com.
+ksn2-12.kaspersky-labs.com.
+pro-sham.travail.gouv.fr.
+tamammennah.blogspot.com.
+safebrowsing-cache.google.com.
+41-courier.push.apple.com.
+parse.howdesign.com.
+iamx.eu.
+djox4jhho.p51u7m9o.
+ruban1.kiwito.com.
+photos-c.ak.fbcdn.net.
+qd7fvzqhx.73tr.
+tangspac.com.
+download795.avast.com.
+1.everystudent.com.
+www.ordinarypastor.com.
+orcart.facebook.com.
+www.google-analytics.com.
+www.vbulletin.com.
+letsbuycom.ugc.bazaarvoice.com.
+ip52-60.cbn.net.id.
+csi.gstatic.com.
+google.com.
+a5.sphotos.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+mx1.ahold.ru.
+www.ilgiornaledelpiemonte.com.
+safebrowsing.clients.google.com.
+22.228.171.69.in-addr.arpa.
+static.ning.com.
+9recvkqi8.54hn.
+enazuero.com.
+www.anikovillalba.com.
+www.facebook.com.
+www.google-analytics.com.
+img2.catalog.video.msn.com.
+safebrowsing.clients.google.com.
+thewoostergroup.org.
+www.elong.net.
+welcome.colostate.edu.
+profile.ak.fbcdn.net.
+mail.comhem.basefarm.net.
+www.bigtunainteractive.com.
+photos-b.ak.fbcdn.net.
+rcp.na.blackberry.com.
+217.96.237.189.in-addr.arpa.
+www.facebook.com.
+dns.msftncsi.com.
+252.146.131.187.in-addr.arpa.
+s-static.ak.fbcdn.net.
+gfx4.hotmail.com.
+pixel.quantserve.com.
+lumpyfame.ru.
+apis.google.com.
+remote.innovativedrivers.com.
+7616-574.cudamail.com.
+stat1.moneycontrol.com.
+js.wlxrs.com.
+ajax.googleapis.com.
+i4.ytimg.com.
+g.juegosdebob.com.
+www.megafitness.es.
+246.20.107.189.in-addr.arpa.
+www.addthis.com.
+es.translatedsongs.com.
+toolbar.baidu.com.
+colomsat.net.
+p0b.ru.
+elguiondecine.blogspot.com.
+dl5.avgate.net.
+photos-f.ak.fbcdn.net.
+vqhekvup4.j01i4q1l.
+developers.facebook.com.
+client-software.real.com.
+twitter.com.
+www.annapolishomebrew.com.
+zynga2-a.akamaihd.net.
+france.usembassy.gov.
+101.212.45.201.in-addr.arpa.
+res-66.ru.
+dns.msftncsi.com.
+en-us.fxfeeds.mozilla.com.
+ldlocke.com.
+mail.theofficeconnection.com.
+87.28.215.176.in-addr.arpa.
+www.bedfed.org.uk.
+kevinoleary.ie.
+www.tattooheaven.com.
+a.root-servers.net.
+camelliaandmain.com.
+ticketweb.ca.
+c0.cctld.afilias-nst.info.
+mail02.ifxnetworks.com.
+k:29m8d4f.a17u5d1m.
+katherineisawesome.com.
+laangostura.com.
+205.9.135.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+taxicorona.ru.
+utrish.com.ru.
+179.229.132.187.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+antropologiafisica.cl.
+login.yahoo.com.
+developers.facebook.com.
+beta.rocket-bird.com.
+lissyhistorias.blogspot.com.
+229.29.220.76.in-addr.arpa.
+178.206.10.190.in-addr.arpa.
+mail.mflandtitle.com.
+5.88.144.189.in-addr.arpa.
+teamnrn.com.
+ludowthompson.com.
+mx2.krasnoe-beloe.ru.
+91.86.187.221.in-addr.arpa.
+ib.adnxs.com.
+img705.imageshack.us.
+www.google.com.mx.
+plusone.google.com.
+dvt.vn.
+59.122.129.24.in-addr.arpa.
+albertomielgo.blogspot.com.
+a.root-servers.net.
+115.242.85.24.in-addr.arpa.
+www.moneymanagement.com.au.
+28.134.163.90.in-addr.arpa.
+r73.kadastr.ru.
+32.49.174.190.in-addr.arpa.
+www.google.com.
+www.cyberxbabes.net.
+www.guillaume-tesson.com.
+a5.sphotos.ak.fbcdn.net.
+mail.dbylaw.com.
+68.230.231.189.in-addr.arpa.
+mbcpepsi.com.
+external.ak.fbcdn.net.
+static.app.widdit.com.
+ads-vrx.adbrite.com.
+home24bank.com.s9a2.psmtp.com.
+99.45.115.186.in-addr.arpa.
+www.roboelectro.com.
+mail.711.ru.
+www.cooking.info.
+ramrealestate.com.
+tools.google.com.
+54.189.117.62.in-addr.arpa.
+www.google.com.
+explorermusic.com.
+www.thedigitalangel.co.uk.
+www.telme.sg.
+43.115.220.190.in-addr.arpa.
+xclick.ru.
+www.mountainweb.com.
+a.root-servers.net.
+terrehaute.in.gov.
+www.ladyfist.com.
+dereusarch.com.
+www.mobiusinstitute.com.
+i1.ytimg.com.
+pagead2.googlesyndication.com.
+www.tophotrod.net.
+www.nh2007.com.
+mail.furtherfilms.com.
+www.eurocopter.com.
+js.microsoft.com.
+69.212.122.190.in-addr.arpa.
+developers.facebook.com.
+www.free-hideip.com.
+www.alarab.net.
+tags.toolbarsmedia.com.
+a.root-servers.net.
+dr._dns-sd._udp.lan.
+download323.avast.com.
+photos-f.ak.fbcdn.net.
+www.scenesix.com.
+mail.krline.net.
+zkudoc.com.
+janaschi.deviantart.com.
+nikkibeach.com.
+proidy.net.
+connect.facebook.net.
+a2.sphotos.ak.fbcdn.net.
+www.heywhatsthat.com.
+www.facebook.com.
+y7mjd5lwc.s78z8n1e.
+www.berlin.es.
+0.11-a70e9079.8140083.1518.18bb.3ea1.210.0.ir328glk7gtudi9qpucepaen55.avqs.mcafee.com.
+www.google.com.
+relay.505010.ru.
+sut1.co.uk.
+a5.sphotos.ak.fbcdn.net.
+78.24.1.181.in-addr.arpa.
+215.38.168.192.in-addr.arpa.
+www.google.com.
+i4.ytimg.com.
+a.root-servers.net.
+anywhere.platform.twitter.com.
+hoster-1.ru.
+a1920.g.akamai.net.
+static.ak.fbcdn.net.
+i4.ytimg.com.
+66.130.37.2.in-addr.arpa.
+a.root-servers.net.
+www.marben.net.
+cdn1.clkads.com.
+cs5279.vk.com.
+106.2.139.189.in-addr.arpa.
+188.229.21.190.in-addr.arpa.
+au.download.windowsupdate.com.
+156.148.113.187.in-addr.arpa.
+rol.paraguay.com.
+n7b.akamaiedge.net.
+mail.yahoo.com.
+www.google.com.
+momentumplanet.com.
+pmstrk.mercadolibre.com.
+mail.ietf.org.
+blog.astrakhan.ru.
+28.174.102.85.in-addr.arpa.
+dns.msftncsi.com.
+fbcdn-sphotos-a.akamaihd.net.
+go3.trekaklik.com.
+mta.pacific-textiles.com.
+www.blogaditas.com.
+auxilor.com.
+a.root-servers.net.
+titanium30-en.url.trendmicro.com.
+www.spss.com.ar.
+iieh5fqs1.10ui.
+www.exzellenz.rwth-aachen.de.
+www.naimnet.com.
+yahoo.com.
+p.twimg.com.
+244.1.19.190.in-addr.arpa.
+www.coolmsn.com.
+www.google.com.
+s.ytimg.com.
+s.ytimg.com.
+mappe.regioneveneto.net.
+38.92.177.190.in-addr.arpa.
+cuadernosdealfonsosalazar.blogspot.com.
+14.55.14.201.in-addr.arpa.
+creative.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.youtube.com.
+adserver.adtech.de.
+tags.expo9.exponential.com.
+ex.urlux.ru.
+ass-1.buttscrewing.com.
+133.71.126.69.in-addr.arpa.
+ec.atdmt.com.
+186.146.27.114.in-addr.arpa.
+anythingfree4you.com.
+dbcmedia.com.s7a2.psmtp.com.
+s-static.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+www.segurosrossi.com.ar.
+www.facebook.com.
+ww.npr.org.
+bookclubs.barnesandnoble.com.
+download-31.blogspot.com.
+www.recoleta.com.ar.
+sdsd.com.
+www.eltiempo.com.
+lh6.ggpht.com.
+bkmx.jicjo.com.
+146.201.42.186.in-addr.arpa.
+www.google.com.
+a7.sphotos.ak.fbcdn.net.
+lakeareabank.com.inbound10.mxlogicmx.net.
+www.okaris.com.
+a1732.v.phobos.apple.com.
+24.169.149.99.in-addr.arpa.
+www.unitec.mx.
+www.7peliculas.com.
+tsc-corp.com.
+d98klhsqa.97kp.
+shad.pp.ru.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+244.177.209.190.in-addr.arpa.
+platform.stumbleupon.com.
+ovg.ru.
+227.1.213.201.in-addr.arpa.
+cr.loszona.com.
+www.stardoll.com.
+kolkata.craigslist.co.in.
+au.download.windowsupdate.com.
+pagead2.googlesyndication.com.
+time.nist.gov.
+gonewiththetwins.com.
+219.251.63.204.in-addr.arpa.
+wkowtv-com.mail.eo.outlook.com.
+toolbox.contentspread.net.
+www.google.com.
+quarantine.royallepage.ca.
+www.facebook.com.
+i2.ytimg.com.
+www.scientology.pt.
+www.wineselect.com.uy.
+www.garbarino.com.
+41.38.106.187.in-addr.arpa.
+71.33.223.201.in-addr.arpa.
+www.africanaquatics.co.za.
+buzzbox.buzzfeed.com.
+connect.facebook.net.
+i1.ytimg.com.
+www.usavetoday.co.uk.
+profile.ak.fbcdn.net.
+smtp.provcombank.com.
+gtinsurance.net.
+crl.microsoft.com.
+ade.k12.ms.us.
+www.facebook.com.
+www2.una.edu.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+17.168.138.187.in-addr.arpa.
+ctn.it.
+guard.nexon.net.
+login.live.com.
+www.youjel.ly.
+youtube-ui.l.google.com.
+www.a-m-o-r.blogspot.com.
+matejacro.polyvore.com.
+blog-frasescelebres.blogspot.com.
+indiaplazamail.com.
+ns4.mentora.biz.
+nspmotion.com.
+6.190.171.88.in-addr.arpa.
+www.breakmedia.com.
+www.eatis.org.
+hub5idx.shub.sandai.net.
+a7.sphotos.ak.fbcdn.net.
+33.253.195.187.in-addr.arpa.
+multimedia.nydailynews.com.
+plusone.google.com.
+95.229.134.187.in-addr.arpa.
+a.root-servers.net.
+www.kaspersky.com.
+us.data.toolbar.yahoo.com.
+static4.videobam.com.
+s.ytimg.com.
+myspread.co.uk.
+profile.ak.fbcdn.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.digitape.com.
+237.60.175.189.in-addr.arpa.
+i4.ytimg.com.
+inbound1.metrocast.net.
+time.windows.com.
+es.lyricsgaps.com.
+a.root-servers.net.
+profile.ak.fbcdn.net.
+141.179.247.190.in-addr.arpa.
+img100.xvideos.com.
+228.18.111.189.in-addr.arpa.
+fxfeeds.mozilla.com.
+228.7.169.89.in-addr.arpa.
+26.107.93.186.in-addr.arpa.
+heritubsyose.com.
+tpprm.ru.
+feeds.bbci.co.uk.
+dns.ystrad-mynach.ac.uk.
+www.nbc40.net.
+apps.facebook.com.
+static.ak.facebook.com.
+feeds.feedburner.com.
+js2.wlxrs.com.
+pixel.facebook.com.
+developers.facebook.com.
+redeoxi.net.
+onsecurityvid.pearson.libsynpro.com.
+dinsmoreworkshop.blogspot.com.
+teredo.ipv6.microsoft.com.
+a4.sphotos.ak.fbcdn.net.
+236.170.12.186.in-addr.arpa.
+strollinfield.com.
+d2100109.xoom.it.
+techbroker.com.
+27.130.127.84.in-addr.arpa.
+mail.divinesearch.com.
+relay.lafondiariatreviglio.it.
+a5.sphotos.ak.fbcdn.net.
+overseasjobs.escapeartist.com.
+tips.kuwo.cn.
+a4.sphotos.ak.fbcdn.net.
+accounts.google.com.
+apps.facebook.com.
+a4.sphotos.ak.fbcdn.net.
+az15112.vo.msecnd.net.
+js.pokernet.dk.
+a8.sphotos.ak.fbcdn.net.
+mail.dottikon.com.
+mail1.iship.com.
+www.youtube.com.
+www.veterinariaexoticos.com.ar.
+www.donnelly24.com.
+ev.ib-ibi.com.
+photos-h.ak.fbcdn.net.
+173.141.78.89.in-addr.arpa.
+www.update.microsoft.com.
+nspmotion.com.
+relay.edison.com.hk.
+manosurbanasscrap.blogspot.com.
+www.nic.com.kw.
+qualitytech.com.
+74.15.124.189.in-addr.arpa.
+189.4.157.201.in-addr.arpa.
+s.ytimg.com.
+bit.ly.
+smtpmail1.xvand.com.
+fluidpowernet.com.
+sr0.comstar.ru.
+static.avast.com.
+a.root-servers.net.
+b-0.19-230a1089.1081.1518.19d3.3ea1.410.0.am9iezikd1d13rw9j23eaurksb.avqs.mcafee.com.
+photos-b.ak.fbcdn.net.
+loading6.widdit.com.
+193.93.125.74.in-addr.arpa.
+216.111.25.190.in-addr.arpa.
+acenexus.com.
+www.facebook.com.
+wlc.hebrewtanakh.com.
+imap.gmail.com.
+qki.bg.
+d.5.9.f.8.8.1.5.f.5.5.2.e.1.c.1.6.7.e.9.7.3.1.4.0.0.0.0.1.0.0.2.ip6.arpa.
+midcountypc.com.
+dc392.4shared.com.
+us.data.toolbar.yahoo.com.
+fun.techradium.com.
+connect.facebook.net.
+static.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+i727.photobucket.com.
+i-o.net.au.
+jiu66.cn.
+empoweredbiblestudy.blogspot.com.
+pagead2.googlesyndication.com.
+www.squareinsider.com.
+7tools.ru.
+down.sjxyx.com.
+www.update.microsoft.com.
+msn.levelup.com.mx.
+249.55.228.85.in-addr.arpa.
+apps.facebook.com.
+mangans.blogspot.com.
+www.googleadservices.com.
+e3191.c.akamaiedge.net.
+inbound.mole-end.com.netsolmail.net.
+www.smarturl.it.
+105.23.75.187.in-addr.arpa.
+appworld.blackberry.com.
+www.rpp.com.pe.
+static.zsl.org.
+com-services.pandonetworks.com.
+.
+bit.ly.
+17.148.182.93.zz.countries.nerd.dk.
+mail.ridex.ru.
+56.67.215.189.in-addr.arpa.
+tagler.cl.
+x-images1.bangbros.com.
+ssl.gstatic.com.
+r._dns-sd._udp.lan.
+www.twitter.com.
+antivirus5.cynet.co.jp.
+ar.games.yahoo.com.
+photos-g.ak.fbcdn.net.
+www.gaystack.com.
+apps.tianya.cn.
+static.scanscout.com.
+132.176.126.87.in-addr.arpa.
+84.45.55.186.in-addr.arpa.
+cdn1.videothumbs.xtube.com.
+www.duramerica.com.
+249.147.50.95.in-addr.arpa.
+www.iduplicate.us.
+secure.gaug.es.
+26.127.227.190.in-addr.arpa.
+partner.vrvm.com.
+profile.ak.fbcdn.net.
+top-sc.daum.net.
+a.root-servers.net.
+pixel.quantserve.com.
+ibo2gusli.25tu.
+static.ak.fbcdn.net.
+westerndiatoms.colorado.edu.
+de-de.facebook.com.
+www.decolar.com.
+q.home.
+teredo.ipv6.microsoft.com.
+adeiphia.net.
+beattylumber.com.
+rss.my.nero.com.
+docs.google.com.
+lh5.ggpht.com.
+www.hhizle.com.
+widgets.api.ebay.com.
+htmlentities.net.
+ticknthistle.com.
+crl.geotrust.com.
+static4.filefront.com.
+www.tecnocemento.com.
+www.creativaint.com.
+67.202.230.190.in-addr.arpa.
+a1505.l.akamai.net.
+2.246.1.187.in-addr.arpa.
+www.lubosa.com.mx.
+33-courier.push.apple.com.
+www.lolshock.com.
+99.23.248.63.in-addr.arpa.
+plusone.google.com.
+centurrytel.net.
+i.ytimg.com.
+98.6.62.120.in-addr.arpa.
+creative.ak.fbcdn.net.
+1m:ip6jj1.12iz.
+xxx.nick-toons.net.
+www.lasa.com.mx.
+ns2.webkontrol.doruk.net.tr.
+a4.sphotos.ak.fbcdn.net.
+mail.dakota.com.br.
+80.85.171.201.in-addr.arpa.
+www.bluesfestivals.com.
+kinnofilm.ru.
+www.andorraguia.com.
+pixel.quantserve.com.
+19.76.228.165.in-addr.arpa.
+firesafetysystems.com.
+a-0.19-26091081.e0b0083.1518.19d4.3ea1.210.0.vmlhtvjuflgiddme6imndigcd6.avqs.mcafee.com.
+la-uno.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+233.254.75.86.in-addr.arpa.
+120.234.221.87.in-addr.arpa.
+mail.nnex.net.
+www.webstore.softexpert.com.
+resp.survey01.net.
+s.chzbgr.com.
+146.70.251.212.in-addr.arpa.
+mx.youtube.com.
+photos-a.ak.fbcdn.net.
+static.ak.fbcdn.net.
+dl2.htc.com.
+5.87.240.201.in-addr.arpa.
+dr._dns-sd._udp.lan.
+30.23.232.189.in-addr.arpa.
+219.10.206.196.in-addr.arpa.
+netscaper.net.
+im.messenger-update.com.
+s.youtube.com.
+atlasdmt.vo.msecnd.net.
+a6.sphotos.ak.fbcdn.net.
+wzeu.ask.com.
+www.elnaveghable.cl.
+t2.gstatic.com.
+7.162.160.189.in-addr.arpa.
+60.61.34.186.in-addr.arpa.
+blue.plala.or.jp.
+realnw.ru.
+photos-c.ak.fbcdn.net.
+www.avsim.su.
+m.facebook.com.
+campbell.k12.va.us.
+sp.cwfservice.net.
+a2.sphotos.ak.fbcdn.net.
+247.21.226.189.in-addr.arpa.
+a-0.19-210f1001.c080081.1518.19d4.3ea1.210.0.56w5db9fams4nfne7us43b3qk6.avqs.mcafee.com.
+voipa.sip.yahoo.com.
+a1.sphotos.ak.fbcdn.net.
+lrmail.com.
+netpay31.sdo.com.
+www.mommynature.com.
+28-courier.push.apple.com.
+llorca-enriqueta.blogspot.com.
+230.11.207.178.in-addr.arpa.
+78.29.133.186.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+log.client.akadns.net.
+edag.com.br.
+144.113.39.216.in-addr.arpa.
+fdh5xuxdk.02ct.
+vaniava.wordpress.com.
+www.compumundo.com.ar.
+mx.aisco-yemen.com.
+cdn.api.twitter.com.
+s-static.ak.fbcdn.net.
+toolbarqueries.clients.google.com.
+t0.gstatic.com.
+sohumx.h.a.sohu.com.
+teamrepro.com.
+sllimages.s3.amazonaws.com.
+www.histats.com.
+affluence.ru.
+foxnetsolutions.com.s5b1.psmtp.com.
+slys.ru.
+serv11.boxca.com.
+royalinteriors.ru.
+93.22.189.190.in-addr.arpa.
+www.boostindependentmusic.com.
+mx.smtnw.com.
+secure.shared.live.com.
+api.tweetmeme.com.
+tilsted.com.
+139.42.134.188.in-addr.arpa.
+tas.orangeads.fr.
+rpg-maker-xp.softonic.com.
+clients2.google.com.
+dns.msftncsi.com.
+www.macappfans.org.
+46.214.6.189.in-addr.arpa.
+25.220.64.199.in-addr.arpa.
+thmarine.com.s8b1.psmtp.com.
+stroudcenter.org.s7a2.psmtp.com.
+icons.cubics.com.
+compsourceok.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+www.immunoconcepts.com.
+ecn.t1.tiles.virtualearth.net.
+17iywqlpz.i60v6h0d.
+external.ak.fbcdn.net.
+www.coloriuris.net.
+teredo.ipv6.microsoft.com.
+v3.cache1.c.youtube.com.
+240.154.74.108.in-addr.arpa.
+igor.funmoods.com.
+googleads.g.doubleclick.net.
+pix.lfstmedia.com.
+xm.xtendmedia.com.
+hdfsi.com.
+www.losangelesinternships.com.
+srpmic.com.
+a.root-servers.net.
+departmanmedya.com.
+a4.sphotos.ak.fbcdn.net.
+orangemail.com.
+delta-kr.ru.
+www.textsrv.com.
+go.srvnow.com.
+www.recapist.com.
+a8.sphotos.ak.fbcdn.net.
+5littles.com.
+www.interpretamos.com.
+98.231.3.190.in-addr.arpa.
+s-static.ak.fbcdn.net.
+183.58.138.187.in-addr.arpa.
+salterlabs.com.2.arsmtp.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+67.198.86.208.in-addr.arpa.
+175.197.14.187.in-addr.arpa.
+253.7.91.77.in-addr.arpa.
+www.myshoutbox.com.
+www.autoresponseplus.com.
+173.8.177.72.in-addr.arpa.
+arsecurity.com.
+m.facebook.com.
+pic2.bai.sohu.com.cn.
+teredo.ipv6.microsoft.com.
+sunflower.bio.indiana.edu.
+_767_78_3.
+a.root-servers.net.
+rek.irk.ru.
+s.openad.tf1.fr.
+a1.sphotos.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+ilaaheb14.28xc.
+yahoo.co.ae.
+profile.ak.fbcdn.net.
+www.9v8v.com.
+www.maleikie.blogspot.com.
+www.facebook.com.
+186.209.154.109.in-addr.arpa.
+3.bp.blogspot.com.
+downloads8.uptodown.net.
+yahoo.com.
+teeworlds.softonic.com.
+redjellyfish.com.
+a8.sphotos.ak.fbcdn.net.
+media.ticketmaster.com.
+remanage.otepremium.gr.
+www.evanbot.com.
+safebrowsing-cache.google.com.
+www.heat-pump-systems.org.
+forum.say7.info.
+6sigmasolution.com.
+www.hookah-pipe.com.
+104.17.195.68.in-addr.arpa.
+jlisigns.com.
+www.hitachi.com.
+dmail.com.
+g4w0041.americas.hpqcorp.net.
+www.chistesinternet.com.
+es.wikipedia.org.
+a.root-servers.net.
+www.flynetonline.com.
+232.228.74.89.in-addr.arpa.
+firefox01.taobao.com.
+outbound.mailhop.org.
+ar.fifa.com.
+ad.turn.com.
+s.ytimg.com.
+www.divenewzealand.com.
+allsignsdirect.com.
+newsrss.bbc.co.uk.
+gallantsys.com.
+www.google.com.
+teredo.ipv6.microsoft.com.
+dns.msftncsi.com.
+linbox.ru.
+us.mg4.mail.yahoo.com.
+google.com.
+poutres.com.
+ecuamagazine.com.
+musyuseidougamura.blog134.fc2.com.
+www.makrama.es.
+profile.ak.fbcdn.net.
+youtu.be.
+18.116.55.65.sbl.spamhaus.org.
+a2.sphotos.ak.fbcdn.net.
+iafrica.com.
+vt1b741ks.q92l1m6s.
+51.219.252.72.in-addr.arpa.
+developers.facebook.com.
+www.canonusa.com.
+gg24t6oom.b19i4v0q.
+www.aviacion.mil.ve.
+msntest.serving-sys.com.
+isearch.babylon.com.
+727431333032.696e666f6c696e6b73.636f6d.80h4ac8e4a3.webcfs00.com.
+75.154.45.190.in-addr.arpa.
+m.facebook.com.
+132.249.66.152.in-addr.arpa.
+jenners.com.
+mx.mediagroup-consulting.com.cust.b.hostedemail.com.
+www.fanmexico.net.
+a8.sphotos.ak.fbcdn.net.
+es.aliexpress.com.
+wp.me.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+hmit.ww.msn.com.
+www.google.com.
+creative.ak.fbcdn.net.
+extranet.ufc.tv.
+www.bearnet.eu.
+99.87.136.220.in-addr.arpa.
+www.ots.ac.cr.
+dyn-images.hsn.com.
+a.root-servers.net.
+www.themetal-spirit.com.
+100.96.191.209.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+219.77.91.190.in-addr.arpa.
+www.adobe.com.
+theglamourwhore.blogspot.com.
+profile.ak.fbcdn.net.
+static.ak.fbcdn.net.
+mclaire.ru.
+200.232.187.189.in-addr.arpa.
+124.22.38.190.in-addr.arpa.
+42.123.158.187.in-addr.arpa.
+www.steel-sci.org.
+192.107.105.189.in-addr.arpa.
+a-0.19-23094081.c0f0083.1518.19d0.3ea1.210.0.zp77cr5ulnlsmfvftm57rc5mgq.avqs.mcafee.com.
+equestria-prevails.deviantart.com.
+0-jw-w.channel.facebook.com.
+de.tynt.com.
+mail.ccmadocs.com.
+www.wildtangent.com.
+bit.ly.
+list.bentium.net.
+cn.pool.ntp.org.
+start.facemoods.com.
+arcade.y8-y8.com.
+img4.catalog.video.msn.com.
+pmcarpenter.blogs.com.
+www.facebook.com.
+46.224.150.64.in-addr.arpa.
+static.ak.fbcdn.net.
+csc.beap.ad.yieldmanager.net.
+checkip.dyndns.org.
+www.facebook.com.
+235.19.214.186.in-addr.arpa.
+www.airgraver.com.
+rumahmadu.com.
+l.yimg.com.
+rosarioout.blogspot.com.
+pixel.facebook.com.
+asalallenaonline.com.ar.
+230.61.137.187.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+5449380.ru.
+205.78.167.79.in-addr.arpa.
+partner.googleadservices.com.
+romanticlub.en.alibaba.com.
+myfacebooktoolbar.s3.amazonaws.com.
+google.com.
+a.root-servers.net.
+battlefield2.ru.
+amer.rel.msn.com.
+82.66.110.189.in-addr.arpa.
+creative.ak.fbcdn.net.
+bellsou1h.net.
+196.174.83.200.in-addr.arpa.
+nancythomas.blogspot.com.
+montbleau.com.
+165.240.254.99.in-addr.arpa.
+www.flirtfair.it.
+www.2gaypasswords.com.
+mx.263.net.
+profile.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+c-0.19-210fc271.8020081.1518.19d3.3ea1.210.0.9mdra7zszvzfpdszhrtwc9k4jj.avqs.mcafee.com.
+dns.msftncsi.com.
+a2.sphotos.ak.fbcdn.net.
+cdn.mdotm.com.
+www.godmammon.com.
+concheck.nimbuzz.com.
+accounts.google.com.
+a5.sphotos.ak.fbcdn.net.
+threadedrod.com.
+jmwelectric.com.
+www.msftncsi.com.
+a.root-servers.net.
+show.kirov.ru.
+ccandw.com.
+t.co.
+96.170.6.200.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+rocktheworld.polyvore.com.
+d3dqyhyld.39sf.
+www.bravoteens.com.
+ymcamontgomery.org.
+sp.cwfservice.net.
+sync.mathtag.com.
+www.socialsafety.org.
+apps.facebook.com.
+ne1.wac.edgecastcdn.net.
+g.msn.com.
+bcge.ch.
+content.yieldmanager.edgesuite.net.
+spe.atdmt.com.
+www.conspiracybomb.com.
+0.57.29.186.in-addr.arpa.
+83.63.168.94.in-addr.arpa.
+www.boats.net.
+clients1.google.com.
+gocanada.about.com.
+www.vodafone.ie.
+a.root-servers.net.
+a.root-servers.net.
+media.adamdodson.org.woopra-ns.com.
+jisublover.blogspot.com.
+a.root-servers.net.
+kyno.ru.
+log.client.akadns.net.
+photos-b.ak.fbcdn.net.
+www.invodo.com.
+altfarm.mediaplex.com.
+files.adbrite.com.
+www4.l.google.com.
+mail.solarsilicon.com.
+www.picnik.com.
+mfspex.com.
+appworld.blackberry.com.
+www.guyana.com.
+photos-b.ak.fbcdn.net.
+_031_06_2.
+portugues.vacationstogo.com.
+84.247.164.190.in-addr.arpa.
+nba2karg.forolatin.com.
+marketing.iprofesional.com.
+a.root-servers.net.
+dns.msftncsi.com.
+mail-2.galenica.ch.
+de-de.facebook.com.
+mksound.com.
+214.33.136.187.in-addr.arpa.
+az.wikipedia.org.
+a4.da1.akamai.net.
+codep30rollerskating.fr.
+darkbattm14-videos.blogspot.com.
+www.transparency.org.
+www.adobe.com.
+92.97.82.108.in-addr.arpa.
+35.147.179.189.in-addr.arpa.
+feeds.videosz.com.
+dns.msftncsi.com.
+dr._dns-sd._udp.0.0.168.192.in-addr.arpa.
+safebrowsing.clients.google.com.
+29.150.16.181.in-addr.arpa.
+93.57.40.190.in-addr.arpa.
+41.247.143.189.in-addr.arpa.
+static.ak.fbcdn.net.
+stagemoscow.ru.
+120.165.98.85.in-addr.arpa.
+www.ascensionenergyprogram.com.
+moda.aukro.ua.
+the.illusionist.tracker.prq.to.
+80.181.88.186.in-addr.arpa.
+www.allcelebritiessex.net.
+eemeasess07.eemea.ericsson.se.
+mail.google.com.
+phuketgolf.com.
+faith.rydia.net.
+am.ricardo.ch.
+content.yieldmanager.edgesuite.net.
+liveupdate.symantecliveupdate.com.
+google.com.
+177.148.99.190.in-addr.arpa.
+169.cim.meebo.com.
+dealcom.ru.
+a1505.l.akamai.net.
+ad.yieldmanager.com.
+supremeflooring.net.
+external.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+a998.mm1.akamai.net.
+232.101.171.189.in-addr.arpa.
+si0.twimg.com.
+marquettenatl.com.
+103.151.109.190.in-addr.arpa.
+190.170.36.186.in-addr.arpa.
+checkip.dyndns.com.
+a.root-servers.net.
+38.189.7.81.in-addr.arpa.
+www.facebook.com.
+158.166.138.187.in-addr.arpa.
+google.com.
+c247723.r23.cf1.rackcdn.com.
+s-static.ak.fbcdn.net.
+petersresort.com.
+www.facebook.com.
+allconnex.com.s7b1.psmtp.com.
+1.53.44.176.in-addr.arpa.
+apis.google.com.
+www.scp-wiki.net.
+_061_46_9.
+a.root-servers.net.
+www.noveldadigital.es.
+photos-d.ak.fbcdn.net.
+profile.ak.fbcdn.net.
+b-0.19-22016008.580.1518.19d4.3ea1.410.0.7akhquus6vkutd5v1vntgif765.avqs.mcafee.com.
+refresh.monohrome.com.
+google.com.
+a.root-servers.net.
+4e1q7m25n.c48r4d0p.
+b._dns-sd._udp.lan.
+greenpeace.ru.
+76.67.36.46.in-addr.arpa.
+s-static.ak.fbcdn.net.
+hwcdn.net.
+r._dns-sd._udp.lan.
+photos-c.ak.fbcdn.net.
+a.root-servers.net.
+search.bearshare.com.
+photos1.hi5.com.
+statusformaturas.com.br.
+www.google-analytics.com.
+static.ak.fbcdn.net.
+gallery.hartmannwheels.com.
+120.142.90.78.in-addr.arpa.
+162.158.224.190.in-addr.arpa.
+hortonsigns.co.nz.
+www.belkin.com.
+a1.sphotos.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+mail.live.com.
+www.fal.com.mx.
+105.94.19.201.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+mail.kop.ru.
+photos-e.ak.fbcdn.net.
+a377.w23.akamai.net.
+hotmail.com.
+photos-h.ak.fbcdn.net.
+a.root-servers.net.
+148.239.29.202.in-addr.arpa.
+yoshifuji.org.
+227.60.237.189.in-addr.arpa.
+pixel.facebook.com.
+cgigroup.com.
+tsm04.eset.com.
+genieind.com.
+mail.vision2results.com.
+a1.sphotos.ak.fbcdn.net.
+bit.ly.
+58.95.145.64.in-addr.arpa.
+cronistadearena.blogspot.com.
+a1406.w42.akamai.net.
+pixel.facebook.com.
+www.juicygoo.com.
+www.vanguardia.com.mx.
+ssl.gstatic.com.
+messenger.yahoo.com.
+www.nikonhq.com.
+myomnicomp.com.s8a1.psmtp.com.
+207.96.102.201.in-addr.arpa.
+bghgmi85m.49cw.
+weekly.ua.
+147.99.48.190.in-addr.arpa.
+www.facebook.com.
+groups.yahoo.com.
+53.73.187.78.in-addr.arpa.
+www.3dtoontube.com.
+cdn.loading321.com.
+fbcdn-profile-a.akamaihd.net.
+www.lafolia.com.
+www.extremetube.com.
+a5.sphotos.ak.fbcdn.net.
+d2107725.xoom.it.
+6-courier.push.apple.com.
+ielu.wamani.apc.org.
+photos2.pop6.com.
+trissalicious.com.
+mx3.rowan.edu.
+inetsite.ru.
+www.popinstituut.nl.
+adserver.adtechus.com.
+212.62.6.186.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+moris.ru.
+static.hotelsone.com.
+us.data.toolbar.yahoo.com.
+a4.sphotos.ak.fbcdn.net.
+spb.nek.ru.s200a1.psmtp.com.
+dns.msftncsi.com.
+secure-uk.imrworldwide.com.
+a.root-servers.net.
+www.kerri.
+photos-b.ak.fbcdn.net.
+a.root-servers.net.
+cdna.pics.youjizz.com.
+ksn1-11-part1.kaspersky-labs.com.
+px.owneriq.net.
+a1.sphotos.ak.fbcdn.net.
+www.gruposantillana.com.
+48.25.145.186.in-addr.arpa.
+exitrealtyabacus.com.
+pagead2.googlesyndication.com.
+79.52.92.186.in-addr.arpa.
+www.courthouse.kay.ok.us.
+lazarusfoundation-asiapacific.org.
+c-0.19-230f6041.10081.1518.19d3.2f4e.10.0.zneg8jpfq12mrtk94v6p4ibuei.avqs.mcafee.com.
+a1108.da1.akamai.net.
+mail.bolo.com.
+www.causes.com.
+b._dns-sd._udp.home.
+162.74.156.93.in-addr.arpa.
+www.ojogo.pt.
+lcbf-com.relay1b.spamh.com.
+r20.rs6.net.
+www.pellegrinocattolico.com.
+16.147.220.66.in-addr.arpa.
+ns.linkexplore.ro.
+6-courier.push.apple.com.
+167.219.206.91.in-addr.arpa.
+greenslip.com.
+e-premieradvantage.com.
+support.live.com.
+110.192.201.173.sbl.spamhaus.org.
+cakecreate.co.uk.
+56.55.123.69.in-addr.arpa.
+www.fswshoes.com.au.
+www.mp3-codes.com.
+a.root-servers.net.
+dmsr.files.wordpress.com.
+l.sharethis.com.
+loading321.com.
+mail.benchmarklends.com.
+105.219.120.187.in-addr.arpa.
+verbes.woxikon.fr.
+images.habbo.com.
+statcounter.com.
+94.35.12.88.in-addr.arpa.
+agrimedia.info.
+a.root-servers.net.
+www.wanderlust-movie.com.
+www.facebook.com.
+hairsaloon.com.
+www.go-video-ltd.co.uk.
+txtmpmnn.com.
+hotmail.com.
+elartedelacomunicacion.blogspot.com.
+natadosromances.blogspot.com.
+139.70.27.188.in-addr.arpa.
+forestcity.net.s7a2.psmtp.com.
+www.facebook.com.
+crl.microsoft.com.
+www.wikimediafoundation.org.
+www.jornada.unam.mx.
+27.164.112.76.in-addr.arpa.
+www.musiikkitalo.fi.
+www.lomejordelheavy.com.
+consfab.com.
+e3167.c.akamaiedge.net.
+86.183.57.187.in-addr.arpa.
+images.images4us.com.
+translate.googleapis.com.
+mail.imobileus.com.
+us1.badoo.com.
+energia.corriere.it.
+photos-a.ak.fbcdn.net.
+rmd.atdmt.com.
+healthguide.howstuffworks.com.
+whatdoesthebiblesayabout.com.
+wpad.
+www.queregalo.cl.
+redir.metaservices.microsoft.com.
+www.c24.com.br.
+plusone.google.com.
+getdocumentary.com.
+www.match4me.be.
+www.flowers24hours.co.uk.
+google.com.
+apps.facebook.com.
+google.com.
+platform.ak.fbcdn.net.
+www.justin.tv.
+124.210.131.74.in-addr.arpa.
+api.twitter.com.
+video.google.es.
+imap.gmail.com.
+www.audible.com.
+a.root-servers.net.
+a.root-servers.net.
+club.astro.sina.com.cn.
+www.facebook.com.
+power.ru.
+107.37.10.187.in-addr.arpa.
+fatmaturebbw.thumblogger.com.
+23.191.25.187.in-addr.arpa.
+www.lesbianascolegialas.com.
+hfns.com.
+pinterest.com.
+x4.xvideohost.com.
+transporteskortmann.cl.
+eulcpf2v2.90mk.
+datitoos.org.
+ad.foxnetworks.com.
+a.root-servers.net.
+ouest-france.fr.
+impes.tradedoubler.com.
+78.147.214.189.in-addr.arpa.
+ent.paris-sorbonne.fr.
+awe-newtech.com.
+google.com.
+c3christiancounseling.com.
+ppenet.com.s8a2.psmtp.com.
+em.tenant401.ovi.messaging.nokia.com.
+bitacoras.com.
+st.chatango.com.
+s-external.ak.fbcdn.net.
+237.66.0.10.in-addr.arpa.
+114.113.7.187.in-addr.arpa.
+developers.facebook.com.
+ihzoopy14.77ki.
+www.facebook.com.
+a7l8ctpwo.m64f9a0x.
+static.ak.facebook.com.
+ssl.gstatic.com.
+tecnobreros.wordpress.com.
+profile.ak.fbcdn.net.
+a.root-servers.net.
+12.187.88.208.in-addr.arpa.
+www.facebook.com.
+biz52.ru.
+thumbnails34.imagebam.com.
+profile.ak.fbcdn.net.
+.
+orr99bcq6.00vy.
+www.ritamitsouko.com.
+www.harley-bobbers.com.
+mx1.snapnames.com.
+mematodelarisa.blogspot.com.
+pagead2.googlesyndication.com.
+petronmarketing.com.
+merida.adoos.com.mx.
+www.alexanderneumann.com.
+fisinc.com.
+s4.histats.com.
+premiermtg1.com.
+cydia.saurik.com.cdngc.net.
+www.dpreview.com.
+38.162.43.200.in-addr.arpa.
+ufojeans.tumblr.com.
+125.120.234.98.in-addr.arpa.
+bluelawllp.com.
+download.juegos.com.
+addacover.com.
+50.253.101.174.in-addr.arpa.
+id.google.com.
+nicolas_17_n.tripod.com.mx.
+geokite.com.
+yahoo.com.
+pass.yandex.ru.
+cinergymetronet.com.
+zonamanga.com.
+images.yodibujo.es.
+aspmx.l.google.com.
+v14.nonxt3.c.youtube.com.
+torrntdao.blog129.fc2.com.
+www.eluniversal.com.mx.
+paragondm.com.
+www.mercedes.de.
+bs.serving-sys.com.
+s.ytimg.com.
+mx.posluh.hr.
+k2vm6jz5y.l34v9b3f.
+mobth198.photobucket.com.
+mx2.talk21.mail.yahoo.com.
+culture.alwatanyh.com.
+www.womensgolf.org.au.
+fwgapp.net.s200b1.psmtp.com.
+www.godney.fan-strefa.pl.
+lighthousetoyota.com.inbounda.reyrey.net.
+api-global.netflix.com.
+funt.ru.
+mx1.earthlink.net.
+3cwboio1p.g20r0n5k.
+hqde.infrabrk.com.
+233.165.102.97.in-addr.arpa.
+24.187.23.95.in-addr.arpa.
+profile.ak.fbcdn.net.
+www.medieval-castle-siege-weapons.com.
+spbmetro.ru.
+teredo.ipv6.microsoft.com.
+ajax.googleapis.com.
+www.orthocast-online.com.
+251.21.0.192.in-addr.arpa.
+soap.bmstu.ru.
+speedy.imo.im.
+photos-f.ak.fbcdn.net.
+sites.google.com.
+www.geotenis.com.
+studentschile.tripod.com.
+www.cdmale.com.
+www.google-analytics.com.
+ib.adnxs.com.
+adwhirllb-473732162.us-east-1.elb.amazonaws.com.
+www.uaz.edu.mx.
+27.109.250.189.in-addr.arpa.
+img.youtube.com.
+bobschwab.com.
+88.59.191.189.in-addr.arpa.
+reports.montiera.com.
+surfsurd.hubpages.com.
+friends.doubledowncasino.com.
+incorporation.ru.
+a.root-servers.net.
+pheedo.msnbc.msn.com.
+a3.sphotos.ak.fbcdn.net.
+crl.globalsign.net.
+a.root-servers.net.
+www.googleadservices.com.
+19.128.100.190.in-addr.arpa.
+www.youtube.com.
+www.facebook.com.
+ax.search.itunes.apple.com.
+mailgw.deerfieldpartners.com.
+213.209.94.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+cdn.feeds.videosz.com.
+190.136.105.92.in-addr.arpa.
+www.zingy.fr.
+webassets3.sparkybee.com.
+g.espncdn.com.
+8.138.162.184.in-addr.arpa.
+del.icio.us.
+121.151.24.88.in-addr.arpa.
+rya.rockyou.com.
+a.root-servers.net.
+es.tatsuorg.wikia.com.
+www.lotto-results.co.za.
+152.25.48.190.in-addr.arpa.
+www.cotifiesta.cl.
+ad.e-viral.com.
+www.movistar.com.pe.
+reachandrich.antevenio.com.
+253.7.105.201.in-addr.arpa.
+photos-c.ak.fbcdn.net.
+teredo.ipv6.microsoft.com.
+mail.giumarravineyards.com.
+grindesign.tumblr.com.
+p0b.ru.
+t1.gstatic.com.
+_866_03_6.
+235.83.137.118.in-addr.arpa.
+creative.ak.fbcdn.net.
+_ldap._tcp.
+mail.bkrlaw.com.
+141.194.245.189.in-addr.arpa.
+www.periodicoadarve.com.
+strsd.southwick.ma.us.
+14.174.240.67.in-addr.arpa.
+a.root-servers.net.
+ksn7.kaspersky-labs.com.
+canitscan1.cal.net.
+180.201.48.190.in-addr.arpa.
+sub-talk.net.
+press.ba.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+apple.com.
+img-cdn.mediaplex.com.
+profile.ak.fbcdn.net.
+_480_84_7.
+69.148.214.189.in-addr.arpa.
+crona-m.ru.
+158.198.174.190.in-addr.arpa.
+www.leivankash.com.
+197.26.128.188.in-addr.arpa.
+26438.envacaciones.info.
+media-cdn.tripadvisor.com.
+100.3.59.186.in-addr.arpa.
+adserver.adtech.de.
+fbcdn-profile-a.akamaihd.net.
+www.genomereviews.ebi.ac.uk.
+in.getclicky.com.
+ledfordmed.secure-enterprise.com.
+img100.xvideos.com.
+chocoline.ru.
+sites.google.com.
+cs9345.vk.com.
+a.root-servers.net.
+1diet.jp.
+137.25.130.189.in-addr.arpa.
+a.root-servers.net.
+img298.imagevenue.com.
+static.ak.fbcdn.net.
+73.17.213.186.in-addr.arpa.
+173.199.15.95.in-addr.arpa.
+img124.hotlinkimage.com.
+www.ifixit.com.
+mail.b2buying.com.
+161.131.194.187.in-addr.arpa.
+prgschultz.net.
+teredo.ipv6.microsoft.com.
+87.85.237.189.in-addr.arpa.
+www.update.microsoft.com.
+53.193.226.189.in-addr.arpa.
+238.250.253.190.in-addr.arpa.
+sites.google.com.
+111.230.231.77.in-addr.arpa.
+piuv5.francetv.fr.
+teredo.ipv6.microsoft.com.
+tempfile.ru.
+119.78.201.41.in-addr.arpa.
+229.52.74.190.in-addr.arpa.
+mamasita.wordpress.com.
+cdn.ubergizmo.com.
+agriproj.com.
+pixel.facebook.com.
+orcart.facebook.com.
+atube-catcher.uptodown.com.
+_ldap._tcp.
+15.175.192.94.in-addr.arpa.
+any-ycpi.aycpi.b.yahoodns.net.
+ndt.iupui.ath01.measurement-lab.org.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cloutieretfils.com.
+d2055705.instant.xoom.it.
+15.92.82.203.in-addr.arpa.
+www.wguaba.com.
+228.26.126.187.in-addr.arpa.
+advancemfg.com.
+www.cam4com.info.
+77.161.100.118.in-addr.arpa.
+ksn3-11.part1.kaspersky-labs.com.
+peopleschoicesurgical.com.
+www.google.com.
+www.clickondetroit.com.
+www.agiteysirva.com.
+arcade-classic-arcade-pack.softonic.com.
+nichegeek.com.
+andreaslagerkvist.com.
+s-static.ak.facebook.com.
+www.facebook.com.
+www.moviezet.com.
+a.root-servers.net.
+151.11.46.24.in-addr.arpa.
+bypalisades.com.inbound10.mxlogicmx.net.
+cuenca.anuxi.ec.
+www.digiturk.gen.tr.
+radiodisney.disneylatino.com.
+ph.priceprice.com.
+63.162.32.114.in-addr.arpa.
+webconfig.merck.com.nch.intra.
+zh-cn.facebook.com.
+250.69.237.189.in-addr.arpa.
+60.249.191.186.in-addr.arpa.
+www.walmart.com.mx.
+179.54.186.189.in-addr.arpa.
+176.111.55.65.in-addr.arpa.
+comunidad.levante-emv.com.
+213.198.19.201.in-addr.arpa.
+mm3.no-ip.info.
+a.root-servers.net.
+smtp.wpcind.com.
+apps.bittorrent.com.
+onemain-mx.earthlink.net.
+a7.sphotos.ak.fbcdn.net.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cmknn.ru.
+48.163.46.208.in-addr.arpa.
+config.pinballbu1.com.
+careers.nyumc.org.
+ezfwpdp.die.net.
+jobs.careerbuilder.com.
+226.248.132.82.in-addr.arpa.
+larrygibbons.com.
+www.google.com.mx.
+a7.sphotos.ak.fbcdn.net.
+9.239.193.212.in-addr.arpa.
+_155_52_3.
+www.brendanemmettquigley.com.
+207.246.54.96.in-addr.arpa.
+twitter.com.
+imgfinance.naver.net.
+www.facebook.com.
+latitudeds.com.
+132.52.123.88.in-addr.arpa.
+wwwimages.adobe.com.
+www.infometeo.es.
+ile-tropicale.com.
+mx.sotcom.ru.ryazan.ru.
+s.sputnik.mail.ru.
+img18.mediafire.com.
+www.download.windowsupdate.com.
+_741_39_8.
+dano-uso-audifonos.blogspot.com.
+www.zonafandom.com.
+www.google-analytics.com.
+e269.b.akamaiedge.net.
+rdr.leeds.ac.uk.
+cl1bak2smtp1.na.epidm.net.
+ftryea.com.
+cdnis3.cam4.com.
+sony-928.vo.llnwd.net.
+dns.msftncsi.com.
+www.farmacia-espana.org.
+www.futuredimensions.net.
+www.carrera-toys.com.
+0.242.144.186.in-addr.arpa.
+albatros.spb.ru.
+www.qcmp3.com.
+sirius-art.spb.ru.
+cap1.conduit-apps.com.
+rad.msn.com.
+www.imgclck.com.
+main.dl.wu.akadns.net.
+feeds.bbci.co.uk.
+rapidssl-aia.geotrust.com.
+ajga.org.
+un4rwezip.i32j0r6q.
+safdf.com.
+witer.bitacoras.com.
+weldinghouse.com.
+eaglemortgageloan.com.
+feeds.feedburner.com.
+.
+hotmail.com.
+231.152.25.46.in-addr.arpa.
+www.sepyme.gov.ar.
+pixel.facebook.com.
+223.71.191.189.in-addr.arpa.
+121.135.121.74.in-addr.arpa.
+philippineamericanwar.webs.com.
+au.download.windowsupdate.com.
+www.sanook.at.
+www.novacreations.net.
+pagead2.googlesyndication.com.
+xsltcache.alexa.com.
+apple.imap.mail.yahoo.com.
+co.tvunetworks.com.
+101.66.97.129.in-addr.arpa.
+a.root-servers.net.
+214.53.19.186.in-addr.arpa.
+foodtrade.ru.
+adi-martinique.fr.
+www.rhapsody-fr.com.
+oms.sakhanet.ru.
+cdn.phonezoo.com.
+www.myoutdoortv.com.
+egaservicios.com.
+152.71.43.208.in-addr.arpa.
+touch.facebook.com.
+nht-2.extreme-dm.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+chatyahoo.blogspot.com.
+a.root-servers.net.
+a.root-servers.net.
+mail2.teknoloji.com.
+www.facebook.com.
+a.root-servers.net.
+wakegov.com.
+www.fho-emden.de.
+rs292dt.rapidshare.com.
+media.v55v.net.
+sddic9gzp.26uj.
+bz:74n6ge.z49t8n4r.
+photos-c.ak.fbcdn.net.
+allergan.com.s7b2.psmtp.com.
+photos-a.ak.fbcdn.net.
+caroserena.blogspot.com.
+lineage2.free.fr.
+www.cablemas.com.mx.
+mail.goozmo.com.
+110.99.81.186.in-addr.arpa.
+c-0.19-a309d481.50483.1518.19d4.3ea1.410.0.dvvkjbg3g7rbsew6n8rdutm2wv.avqs.mcafee.com.
+weather.wapp.wii.com.
+evangeliodeldia.org.
+tms5.icrc.trendmicro.com.
+_877_92_6.
+mail.scarsdaledentistry.com.
+a5.sphotos.ak.fbcdn.net.
+static.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+b.scorecardresearch.com.
+www.update.microsoft.com.
+215.125.178.31.in-addr.arpa.
+goosebox.net.lan.
+www.http.
+ssl.gstatic.com.
+apps.facebook.com.
+240.112.36.177.in-addr.arpa.
+api.twitter.com.
+www.humeseeds.com.
+ad.doubleclick.net.
+disneysjessie.com.
+a5.sphotos.ak.fbcdn.net.
+www.free-tv-video-online.me.
+151.61.141.201.in-addr.arpa.
+218.240.26.80.in-addr.arpa.
+www.icameltoes.com.
+load.s3.amazonaws.com.
+pagead2.googlesyndication.com.
+142.3.44.81.in-addr.arpa.
+cf.addthis.com.
+.
+pixel.facebook.com.
+149.130.50.201.in-addr.arpa.
+c0013999.ssl.cf1.rackcdn.com.
+e906.g.akamaiedge.net.
+espanol.support.vonage.com.
+softpro.msk.ru.
+www.google.com.
+a-0.19-230fd081.a060131.1518.19d4.3ea0.210.0.555215vife6tps7czkhjhiiz15.avqs.mcafee.com.
+81.93.5.88.in-addr.arpa.
+226.139.85.186.in-addr.arpa.
+a995.mm1.akamai.net.
+218.143.209.201.in-addr.arpa.
+a8.sphotos.ak.fbcdn.net.
+safebrowsing.clients.google.com.
+www.xperthr.co.uk.
+a1.sphotos.ak.fbcdn.net.
+images03.olx-st.com.
+cstheory.stackexchange.com.
+www.youtube.com.
+a.root-servers.net.
+mail.96861mail.com.
+trigate.com.
+de-de.facebook.com.
+www.adobe.com.
+www.e-belis.com.
+deltavolt.pe.
+t3.gstatic.com.
+lizzie-mcguire.seriespepito.com.
+www.google.com.
+ajax.googleapis.com.
+g.ceipmsn.com.
+a.root-servers.net.
+s.youtube.com.
+www.what-time-is-it.com.
+25.174.219.190.in-addr.arpa.
+mx1.mac.com.akadns.net.
+www.hotmail.com.
+www.metroscubicos.com.
+static.ak.fbcdn.net.
+pixel.facebook.com.
+teacher.ocps.net.
+202.218.11.200.in-addr.arpa.
+profile.ak.fbcdn.net.
+5.99.184.81.in-addr.arpa.
+beta.stun.voice.yahoo.com.
+www.segurosrossi.com.ar.
+a.root-servers.net.
+apps.facebook.com.
+a.root-servers.net.
+mashable.com.
+58.147.87.186.in-addr.arpa.
+195.103.16.186.in-addr.arpa.
+www.trogontours.net.
+127.104.4.186.in-addr.arpa.
+fbcdn-photos-a.akamaihd.net.
+qaxp.com.
+sqm.microsoft.com.
+pagead2.googlesyndication.com.
+youtube.com.
+a7.sphotos.ak.fbcdn.net.
+mscrl.microsoft.com.
+hoy-sa.com.
+www.bebesymas.com.
+a.root-servers.net.
+209.ns1631262.net.
+directas-descargas-rapidshare.blogspot.com.
+210.59.187.115.in-addr.arpa.
+211.94.138.189.in-addr.arpa.
+43.62.75.187.in-addr.arpa.
+api-public.addthis.com.
+97.106.161.189.in-addr.arpa.
+220.227.31.190.in-addr.arpa.
+grupocolmenar.com.
+www.kut-friends.com.
+yahoo.com.
+_895_96_3.
+www.maslacasassa.com.
+photos-e.ak.fbcdn.net.
+developers.facebook.com.
+www.use.com.ph.
+communityhospital.com.
+197.57.159.189.in-addr.arpa.
+profile.ak.fbcdn.net.
+badoo.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.google-analytics.com.
+ninjasaga.superforos.org.
+www.google-analytics.com.
+harborexpress.com.inbound10.mxlogicmx.net.
+pan.starmedia.com.
+s7.addthis.com.
+_134_50_9.
+elpollohipnotico.wordpress.com.
+168.215.228.77.in-addr.arpa.
+fbcdn-sphotos-a.akamaihd.net.
+c-0.19-a3094081.4010082.1518.19d4.3ea1.210.0.7u8bgmsrtmk94dmjibw29c4sq5.avqs.mcafee.com.
+a.root-servers.net.
+photos-b.ak.fbcdn.net.
+s10.histats.com.
+fxfeeds.mozilla.com.
+i4.ytimg.com.
+diad.capex.com.ar.
+z1851z6rp.10zi.
+clients4.google.com.
+156.227.84.200.in-addr.arpa.
+toolfarm.com.
+www.youpouch.com.
+harpiesbizarre.com.
+a.root-servers.net.
+mscrl.microsoft.com.
+t0.gstatic.com.
+41.244.197.65.in-addr.arpa.
+check4.facebook.com.
+weather.msn.com.
+cs5.wac.edgecastcdn.net.
+86.120.184.88.in-addr.arpa.
+www.goddiva.co.uk.
+gouvisgroup.com.s10a1.psmtp.com.
+s0.2mdn.net.
+creative.ak.fbcdn.net.
+e566.b.akamaiedge.net.
+i.ytimg.com.
+www.paypalobjects.com.
+31.73.171.201.in-addr.arpa.
+ironport-mx-vip.maxnet.net.nz.
+www.csidata.com.
+live4this.com.
+api.conduit.com.
+www.brooklyn.liu.edu.
+mx.zarlene.com.
+prophotos.ru.
+102.23.171.78.in-addr.arpa.
+connect.facebook.net.
+217.139.46.189.in-addr.arpa.
+apps.facebook.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+au.download.windowsupdate.com.
+kclinc.org.
+www.amazinghotgirls.com.
+profile.ak.fbcdn.net.
+plusone.google.com.
+spam.phison.com.
+static.ak.fbcdn.net.
+news.google.com.
+maps.google.com.
+28.126.156.201.in-addr.arpa.
+b-0.19-210d2479.1f0000.1518.19d4.3ea0.410.0.57n2b377h7e4m77in2dvzq28lq.avqs.mcafee.com.
+m.hotmail.com.
+75.140.141.190.in-addr.arpa.
+so35j64ls.x85r8p9k.
+sp.cwfservice.net.
+www.iegallery.com.
+upload.wikimedia.org.
+144.172.212.64.in-addr.arpa.
+downloads.bf-servers.com.
+9uaxokfq5.i77i8k7m.
+mail.capitalconservator.com.
+meengle.net.
+213.101.99.86.in-addr.arpa.
+www.coursokado.fr.
+api.bestvideodownloader.com.
+photos-b.ak.fbcdn.net.
+download.windowsupdate.com.
+stronzodimerda.it.
+dvdfab-hd-decrypter.malavida.com.
+m.hotmail.com.
+sup.live.com.
+static.ak.fbcdn.net.
+.
+searchjs.s3.amazonaws.com.
+www.apple.com.
+130.205.61.69.in-addr.arpa.
+a21a.com.
+_613_48_2.
+teredo.ipv6.microsoft.com.
+122.169.158.187.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.resonancechina.com.
+scripts.affiliatefuture.com.
+download.windowsupdate.com.
+pepsico.trabajo.infojobs.net.
+www.keys4.me.
+ak1.abmr.net.
+beta.stun.voice.yahoo.com.
+developers.facebook.com.
+umunu.com.
+multiparking.com.
+profile.ak.fbcdn.net.
+gdata.youtube.com.
+1np4eey8c.y44y3o0i.
+252.220.51.190.in-addr.arpa.
+luttner.com.
+mobile.blackberry.com.
+dr._dns-sd._udp.0.0.0.5.in-addr.arpa.
+maps.google.com.
+ag-c.ru.
+122.188.66.187.in-addr.arpa.
+microtekmed.com.s8b1.psmtp.com.
+a.root-servers.net.
+www.baropen.com.au.
+53.32.56.85.in-addr.arpa.
+nt.go.th.
+146.194.51.190.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+cyberlife.co.uk.
+moonconnection.com.
+dr._dns-sd._udp.0.129.37.10.in-addr.arpa.
+sitno.mgn.ru.
+benjaesoptimus.spaces.live.com.
+ppc.2-01-282a-0002.cdx.cedexis.net.
+www.bandoo.com.
+www.google-analytics.com.
+platform.twitter.com.
+ksn1-12-part2.kaspersky-labs.com.
+unreasonableness.com.
+_901_68_5.
+connect.facebook.net.
+safebrowsing.clients.google.com.
+frontiermedical.net.inbound15.mxlogic.net.
+223.152.123.201.in-addr.arpa.
+static.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+9.8.23.190.in-addr.arpa.
+live-radio.net.
+a3.sphotos.ak.fbcdn.net.
+apps.facebook.com.
+mail.alarm-plus.ru.
+62.71.112.87.in-addr.arpa.
+profile.ak.fbcdn.net.
+nvtc.org.
+clients1.google.com.
+fb-client-0.castle.zynga.com.
+dpz14.cocolog-nifty.com.
+35.45.132.144.in-addr.arpa.
+www.alean.ru.
+img.constantcontact.com.
+download.windowsupdate.com.
+amcourier.com.
+ecc.elevatorcontrols.com.
+pixel.facebook.com.
+www.frwl7.com.
+kxgdv4yc9.15rb.
+www.fortunebeach.com.
+www.cbox.ws.
+www.cenidiap.net.
+scripts.verticalacuity.com.
+a3.sphotos.ak.fbcdn.net.
+176.185.253.201.in-addr.arpa.
+a852.phobos.apple.com.
+a-0.19-2209e071.d0b0083.1518.19d3.3ea1.410.0.2jh8jqwju5dctz3u8lweue22q6.avqs.mcafee.com.
+a.root-servers.net.
+edge.sharethis.com.
+profiles.google.com.
+ad.doubleclick.net.
+a.root-servers.net.
+weather.services.conduit.com.
+tribalectic.com.
+www.google.com.
+a8.sphotos.ak.fbcdn.net.
+www.google.com.
+connect.facebook.net.
+ocsp.verisign.com.
+mujer.es.msn.com.
+adserver.itsfogo.com.
+v17.hispavista.com.
+www.tube43.com.
+www.google-analytics.com.
+safebrowsing-cache.google.com.
+es-es.facebook.com.
+photos-d.ak.fbcdn.net.
+bingo.bitrhymes.com.
+pubads.g.doubleclick.net.
+belarustime.ru.
+i5.cmail2.com.
+www.bywifi.com.
+116.183.0.186.in-addr.arpa.
+www.facebook.com.
+google.com.
+181.43.130.24.in-addr.arpa.
+googleads.g.doubleclick.net.
+218.107.107.190.in-addr.arpa.
+scapegoat.ru.
+s.whatsapp.net.
+linkhelp.clients.google.com.
+4ubpva8bj.o36h0o8j.
+www.youtube.com.
+www.eric-clapton.co.uk.
+149.84.160.189.in-addr.arpa.
+ad.foxnetworks.com.
+www.en.bpl.admcsport.com.
+140.122.168.192.in-addr.arpa.
+www.hotxxxasia.com.
+beacon-1.newrelic.com.
+136.150.32.114.in-addr.arpa.
+wzpo1.ask.com.
+photos-a.ak.fbcdn.net.
+a2.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+www.lrc.rpi.edu.
+dns.camcctv.com.
+facemoods.com.
+25.231.31.190.in-addr.arpa.
+version.com.
+60.223.212.186.in-addr.arpa.
+queesproyecto.wordpress.com.
+sinar.co.id.
+s.stpost.com.
+a6.sphotos.ak.fbcdn.net.
+s-static.ak.fbcdn.net.
+landom.com.
+maps.google.de.
+safebrowsing.clients.google.com.
+www.gstatic.com.
+a.root-servers.net.
+www.nitzanonline.com.
+82.17.22.95.in-addr.arpa.
+mail.gosiger.com.
+asturaleza.blogspot.com.
+www.citydom24.pl.
+maxcdn.fooyoh.com.
+www.facebook.com.
+home.speedbit.com.
+teredo.ipv6.microsoft.com.
+static.ak.fbcdn.net.
+bhrei-com.relay1b.spamh.com.
+189.38.206.187.in-addr.arpa.
+profile.ak.fbcdn.net.
+d5nxst8fruw4z.cloudfront.net.
+ru.wikipedia.org.
+xxlss.com.
+s-static.ak.fbcdn.net.
+www.google.com.mx.
+www.facebook.com.
+www.goojue.com.
+ns1.dyndns.org.
+a749.g.akamai.net.
+cerato.wordpress.com.
+support.urbanairship.com.
+35.44.90.87.in-addr.arpa.
+wyq6l1:ds.o39m4e3c.
+a.root-servers.net.
+daddygrognard.blogspot.com.
+16.144.2.186.in-addr.arpa.
+mx.youtube.com.
+94.203.87.203.in-addr.arpa.
+atelier.org.
+170.216.108.114.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+a.root-servers.net.
+genevatypewriters.blogspot.com.
+platform.ak.fbcdn.net.
+ajax.googleapis.com.
+lifeinfomation.com.
+119.176.155.79.in-addr.arpa.
+www.famosasmexicanas.net.
+mx.lasallegroup.com.
+v4.cache5.c.youtube.com.
+www.csmonitor.com.
+eltc.com.
+90.7.221.190.in-addr.arpa.
+www.youtube.com.
+www.sinais.salud.gob.mx.
+www.pangolin.com.
+179.250.18.189.in-addr.arpa.
+88.79.55.65.in-addr.arpa.
+up4.m5zn.com.
+external.ak.fbcdn.net.
+pagead2.googlesyndication.com.
+www.spaziogames.it.
+i4.ytimg.com.
+photos-g.ak.fbcdn.net.
+www.thebookyard.com.
+teredo.ipv6.microsoft.com.
+alerts.conduit-services.com.
+a5.da1.akamai.net.
+www.www.facebook.com.
+e566.b.akamaiedge.net.
+puzolencontrol.blogspot.com.
+www.pulpijuegos.com.
+googleads.g.doubleclick.net.
+a1.twimg.com.
+173.244.246.99.in-addr.arpa.
+www.onlinefunarcade.com.
+www.comunidadyprevencion.org.
+69.139.110.189.in-addr.arpa.
+d15gt9gwxw5wu0.cloudfront.net.
+mta5.am0.yahoodns.net.
+ads.matomy.com.
+teredo.ipv6.microsoft.com.
+19-courier.push.apple.com.
+msratingbureau.com.
+yxmpofgx6.z08f6u9x.
+dr._dns-sd._udp.0.129.37.10.in-addr.arpa.
+ytimg.l.google.com.
+1.gvt0.com.
+a3.sphotos.ak.fbcdn.net.
+194.227.122.128.in-addr.arpa.
+7yqllhxyp.31jx.
+support.google.com.
+www.googleadservices.com.
+a.root-servers.net.
+a.root-servers.net.
+liberomx4.libero.it.
+googleads.g.doubleclick.net.
+a.root-servers.net.
+6.227.224.190.in-addr.arpa.
+www.trialpay.com.
+www.friv2.org.
+adserver.adtech.de.
+polenimplement.com.
+omp1040.mail.ne1.yahoo.com.
+32.26.230.201.in-addr.arpa.
+hit.sunnydollars.net.
+www.facebook.com.
+sp.search-results.com.
+www.alejandramatus.cl.
+fqqyd171h.44mg.
+datafeed.weatherbug.com.
+244.144.254.180.in-addr.arpa.
+61.144.119.189.in-addr.arpa.
+djesibonajeb.com.
+russian-girls.name.
+lh6.googleusercontent.com.
+translate.google.com.mx.
+femalepop.tumblr.com.
+www.icams.es.
+17.203.240.195.in-addr.arpa.
+a.rad.msn.com.
+mail.gordos.com.
+www.facebook.com.
+www.umeng.com.
+pinklaserspa.com.
+www.amo.qc.ca.
+aybk.ru.
+brasil.babycenter.com.
+a.root-servers.net.
+71.208.97.94.in-addr.arpa.
+www.allhandbagfashion.com.
+mail.fanafel.pt.
+www.sohokid.com.ar.
+inxs.phpbbforum.eu.
+35.175.123.84.in-addr.arpa.
+122.173.102.201.in-addr.arpa.
+popravu.ru.
+www.mistressdemonic.com.
+connect.facebook.net.
+s7.addthis.com.
+freetrafficbar.com.
+img198.imageshack.us.
+intrawesttremblant.112.2o7.net.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.mineros.com.co.
+m.addthisedge.com.
+de-de.facebook.com.
+199.221.21.23.in-addr.arpa.
+jenchina.ucoz.ru.
+a.root-servers.net.
+syndication.mmismm.com.
+u3.hazipatika.com.
+www.google.com.
+emelian.ru.
+utils.babylon.com.
+www.google-analytics.com.
+195.80.139.69.in-addr.arpa.
+t.fuziontech.net.
+udc.msn.com.
+_107_11_9.
+teredo.ipv6.microsoft.com.
+132.157.229.77.in-addr.arpa.
+crown-energy.com.
+mp.rj.gov.br.
+www.jacklalanne.com.
+www.brits.co.uk.
+profile.ak.fbcdn.net.
+www.copa.com.
+iaechina.net.
+www.geekbecois.com.
+9-0.qlty.finarea.ch.
+138.147.232.201.in-addr.arpa.
+manahair.blogspot.com.
+talan.udm.ru.
+114.55.24.189.in-addr.arpa.
+www.cuadherpetol.com.ar.
+developers.facebook.com.
+218.191.77.190.in-addr.arpa.
+a.root-servers.net.
+zh-cn.facebook.com.
+ugbmzq.com.
+84.160.191.189.in-addr.arpa.
+www.radiorhemapresencia.com.
+fi-fi.facebook.com.
+182.251.56.187.in-addr.arpa.
+localhost.
+ocsp.geotrust.com.
+www.redpymes.org.ar.
+a.root-servers.net.
+smtp5.acsu.buffalo.edu.
+contentfilter.futuragts.com.
+howchi.net.
+shortime.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.polfa-tarchomin.ru.
+yogi.apps.bittorrent.com.
+made-to-travel.com.
+25.241.232.66.in-addr.arpa.
+pacific.net.au.
+teredo.ipv6.microsoft.com.
+www.elcinema.com.
+www.facebook.com.
+www.divyy.net.
+224.138.242.88.in-addr.arpa.
+csi.gstatic.com.
+e566.b.akamaiedge.net.
+4.bp.blogspot.com.
+www.segob.gob.mx.
+internet-explorer-7.fr.malavida.com.
+ad.doubleclick.net.
+imap.gmail.com.
+163.137.234.201.in-addr.arpa.
+pixel.facebook.com.
+www.bangavet.com.
+platform.ak.fbcdn.net.
+a6.sphotos.ak.fbcdn.net.
+trgc.opt.fimserve.com.
+us.mg6.mail.yahoo.com.
+in.loreal.com.
+www.naturhome.org.
+i.microsoft.com.
+www.ecopics.com.
+janics.com.
+www.youtube.com.
+bicentenario.tamaulipas.gob.mx.
+126.37.37.190.in-addr.arpa.
+mail2mars.com.
+www.mininova.org.
+84.191.192.187.in-addr.arpa.
+safebrowsing-cache.google.com.
+wap.id.samsungmobile.com.
+www.speeduppro.com.
+131.236.206.190.in-addr.arpa.
+apps.facebook.com.
+www.29content14.com.
+84.208.0.181.in-addr.arpa.
+r1rk9np7bpcsfoeekl0khkd2juj27q3o-a-fc-opensocial.googleusercontent.com.
+thousidis.no-ip.biz.
+www.shopbenchmark.com.
+metrics.skype.com.
+vzlettime.ru.
+twimg0-a.akamaihd.net.
+178.195.124.70.in-addr.arpa.
+s.youtube.com.
+a0.twimg.com.
+solar.dp.ua.
+troyafotos.galeon.com.
+safebrowsing-cache.google.com.
+cargocollective.com.
+_305_41_3.
+davenportfoundationrepair.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.imagengratis.org.
+l3.image.peepeebabes.com.
+www.iafa.go.cr.
+cullprop.com.s5b2.psmtp.com.
+www.andrevanamstel.nl.
+a.root-servers.net.
+www.thegemstoneconnection.com.
+www.google-analytics.com.
+243.77.81.201.in-addr.arpa.
+enact.com.
+society6.com.
+marcusevans.com.rbl2.mcafee.com.
+0-143.channel.facebook.com.
+r._dns-sd._udp.lan.
+static.ak.fbcdn.net.
+www.mtvla.com.
+i.imgur.com.
+220.11.168.192.in-addr.arpa.
+byfiles.storage.msn.com.
+www.diariopuntual.com.
+www.weather.com.
+v6.nonxt8.c.pack.google.com.
+12.254.29.186.in-addr.arpa.
+s.pcdcdn.com.
+microtechnica.com.
+relay1.fitolek.com.
+orwells1984oregon.files.wordpress.com.
+mx2.mailhop.org.
+trixsters.net.
+www.wernerlau.com.
+m.addthisedge.com.
+mediageekzone.blip.tv.
+castalia.es.
+.
+www.chubbysistas.com.
+boing4u.net\032.
+creative.ak.fbcdn.net.
+matcher.bidder7.mookie1.com.
+www.msftncsi.com.
+www.fincasriazor.com.
+www.heylittledick.com.
+a.root-servers.net.
+www.nathalieschuterman.com.
+gateways2.aep.com.
+b-0.19-230e7219.11081.1518.19d4.3ea1.410.0.14kg454zt8ib4fr3gsldv6ejw5.avqs.mcafee.com.
+ak1s.abmr.net.
+148.26.156.201.in-addr.arpa.
+www.clearleadinc.com.
+bulbyonder.co.uk.
+d.p-td.com.
+www.y8.com.
+plus.google.com.
+60.45.35.173.in-addr.arpa.
+photos-b.ak.fbcdn.net.
+i4.ytimg.com.
+oipikrprhtzxtcp.biz.
+a1222.phobos.apple.com.edgesuite.net.
+checkip.dyndns.org.
+_541_39_7.
+181.142.155.93.in-addr.arpa.
+4.109.123.84.in-addr.arpa.
+www.chicaspilladas.com.ar.
+szchaoyueic.en.alibaba.com.
+15-courier.push.apple.com.
+mail.google.com.
+59.81.19.186.in-addr.arpa.
+a7.sphotos.ak.fbcdn.net.
+o-o.preferred.fra02s03.v1.lscache8.c.youtube.com.
+lh6.googleusercontent.com.
+80.56.92.186.in-addr.arpa.
+static.exoclick.com.
+sp.cwfservice.net.
+a.root-servers.net.
+pbttbc.bt.motive.com.
+barracuda.priocom.com.
+barras.virgula.com.br.
+appworld.blackberry.com.
+curious-george13.polyvore.com.
+fftoday.com.
+www.youtube.com.
+198.181.240.189.in-addr.arpa.
+176.151.83.98.in-addr.arpa.
+fr.y8.com.
+137.192.152.190.in-addr.arpa.
+a.root-servers.net.
+m.addthisedge.com.
+www.kenwoodvineyards.com.
+www.yaguar.com.
+19.78.61.74.in-addr.arpa.
+180.254.166.76.in-addr.arpa.
+www.twitter.com.
+6.66.158.187.in-addr.arpa.
+a.root-servers.net.
+a3.mzstatic.com.home.
+mx3.gcmhmr.com.
+58.226.237.189.in-addr.arpa.
+teredo.ipv6.microsoft.com.
+developers.facebook.com.
+cot7jg:al.g56k6i4k.
+artofdavidwalker.com.
+external.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+54.235.159.189.in-addr.arpa.
+www.adivinalesuscositas.blogspot.com.
+1.167.50.190.in-addr.arpa.
+t0.gstatic.com.
+fxfeeds.mozilla.com.
+ucci.org.ua.
+platform.twitter.com.
+updates3.pc-fix-cleaner.com.
+i1.ytimg.com.
+byfiles.storage.msn.com.
+28oawqsur.00kp.
+veronicauribe.wordpress.com.
+creative.ak.fbcdn.net.
+www-google-analytics.l.google.com.
+cdn3.rocketlanguages.com.
+js.wlxrs.com.
+en.mobile.wikipedia.org.
+nailpolishenthusiast.blogspot.com.
+a8.sphotos.ak.fbcdn.net.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail2.nwave.com.
+ssl.gstatic.com.
+www.foxsportsla.com.
+233.4.56.187.in-addr.arpa.
+litehosting.ru.
+www.supercardds.es.
+whos.amung.us.
+89.151.168.192.in-addr.arpa.
+fireclad.com.
+www.zkoss.org.
+googleads.g.doubleclick.net.
+cdylk4zdy.60ov.
+api.searchvideo.com.
+service.gc.apple.com.akadns.net.
+a1.twimg.com.
+65.173.89.85.in-addr.arpa.
+www.facebook.com.
+www.bingolines.com.
+yorktech.com.
+www.papeleriaalbe.com.uy.
+www.google.com.
+thejetpacker.com.
+a5.da1.akamai.net.
+i3.ytimg.com.
+connect.facebook.net.
+www.wosa.co.za.
+a.rad.msn.com.
+login.zoosk.com.
+bqzvet.com.
+mso61bybwcqlyd60pyl48hzc69n20n40dtj46bz.org.
+www.facebook.com.
+en.wordpress.com.
+www.roundup.com.
+photos-a.ak.fbcdn.net.
+www.google-analytics.com.
+ssl.gstatic.com.
+mail.sia-r.ru.
+www.20minutos.es.
+147.12.46.184.in-addr.arpa.
+84.199.1.181.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+static.ak.fbcdn.net.
+apps.facebook.com.
+193.83.144.189.in-addr.arpa.
+shell.windows.com.
+rcp.na.blackberry.com.
+237.157.234.190.in-addr.arpa.
+ccc.usccb.org.
+clearance.cnet.com.
+a3.sphotos.ak.fbcdn.net.
+heartindiana.com.
+0-155.channel.facebook.com.
+103.9.76.95.in-addr.arpa.
+clients.teamtalk.com.
+met.adwhirl.com.
+teredo.ipv6.microsoft.com.
+apps.facebook.com.
+s.jimdo.com.
+srchsugg.funwebproducts.com.
+iphone.facebook.com.
+widergastro.ch.
+a5.sphotos.ak.fbcdn.net.
+www.d2open.com.
+www.littleariel.com.
+www.nsaayat.com.
+98.117.94.201.in-addr.arpa.
+pagead2.googlesyndication.com.
+93yhpjk9s.x26q2s6m.
+www.elgrafico.mx.
+159.254.234.190.in-addr.arpa.
+prse.de.
+knowle.fslife.co.uk.
+syndication.norton.com.
+buscador.emol.com.
+teredo.ipv6.microsoft.com.
+noticias.prodigy.msn.com.
+lenaten.ru.
+30.217.9.186.in-addr.arpa.
+finks.com.
+add.my.yahoo.com.
+a3.sphotos.ak.fbcdn.net.
+external.ak.fbcdn.net.
+a.root-servers.net.
+toys-house.kiev.ua.
+ksn2-12.kaspersky-labs.com.
+profilecommunication.com.
+119.103.201.190.in-addr.arpa.
+axifer.net.
+www.google.com.
+ib.adnxs.com.
+edge-mt.datpiff.com.
+kwo31n50l48n10lsp32bqivlvjviulynxnvl38.com.
+fishermfg.com.
+125.35.168.192.in-addr.arpa.
+apps.facebook.com.
+mail.in2m.com.
+www.facebook.com.
+bluebanana.ch.
+www.facebook.com.
+rhpmlgknnklmtyzn.biz.
+www.google-analytics.com.
+bay.messenger.services.live.com.
+www.casadellibro.com.
+msntest.serving-sys.com.
+206.86.51.190.in-addr.arpa.
+themes.googleusercontent.com.
+motorcyclepictures.faqih.net.
+img.foroalfa.org.
+ssl2.twitter.com.edgekey.net.
+ocsp.entrust.net.
+tunein.defjay.com.
+vcs1.msg.yahoo.com.
+apple.com.
+41.94.170.212.in-addr.arpa.
+twitter.com.
+sync.mathtag.com.
+a.root-servers.net.
+156.80.67.201.in-addr.arpa.
+checkip.dyndns.com.
+dns.msftncsi.com.
+gfx4.hotmail.com.
+www.belkin.com.
+51.89.194.122.in-addr.arpa.
+www.931amor.com.
+whk.com.au.
+mailgate.childsoc.org.uk.
+hubster.ru.
+ad.z5x.net.
+appenda.com.
+www.facebook.com.
+www.facebook.com.
+a.root-servers.net.
+203.194.239.189.in-addr.arpa.
+armada-ra.ru.
+kent157-visions.tumblr.com.
+planetaciclista.blogspot.com.
+s1.us.imgsrc.ru.
+106.144.222.189.in-addr.arpa.
+a.root-servers.net.
+clients4.google.com.
+247.80.67.201.in-addr.arpa.
+a1851.phobos.apple.com.edgesuite.net.
+freebaselibs.com.
+g.ceipmsn.com.
+www.google-analytics.com.
+www.feldmanns.com.
+external.ak.fbcdn.net.
+petsalon-ipa.animoca.com.
+go-usa.com.
+su.pr.
+yogananda-srf.org.
+1-courier.push.apple.com.
+156.92.166.88.in-addr.arpa.
+charteroakmedical.com.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+27.media.tumblr.com.
+jrwheel.com.
+android.clients.google.com.
+profile.ak.fbcdn.net.
+235.13.24.190.in-addr.arpa.
+www.lost-away.org.
+zulu.tweetmeme.com.
+sp.cwfservice.net.
+i4.ytimg.com.
+www.animalarchitecture.org.
+ocsp.digicert.com.
+isprime.com.fpbns.net.
+224.27.171.189.in-addr.arpa.
+www.boobies.pro.
+nigelgearing.com.
+i2.ytimg.com.
+www.milfstalker.com.
+ssl.gstatic.com.
+gleeph.blogspot.com.
+253.0.162.190.in-addr.arpa.
+cdn-5.nflximg.com.
+d.yimg.com.
+a1402.w40.akamai.net.
+bodacion.com.
+118.217.82.200.in-addr.arpa.
+www.chandia.net.
+static.ak.fbcdn.net.
+cmodules.com.
+mb.vodch.mgn.ru.
+www.crafterscompanion.com.
+css.wlxrs.com.
+upnufyam.net.
+motturaspa.ru.
+eusors.com.
+36.212.84.200.in-addr.arpa.
+widgets.amung.us.
+135.11.97.189.in-addr.arpa.
+s2.youtube.com.
+5.232.88.186.in-addr.arpa.
+edison.upc.es.
+i4.ytimg.com.
+api.facebook.com.
+www.facebook.com.
+themeworxmedia.com.
+bestbooks.net.ru.
+cdn.api.twitter.com.
+26.220.44.194.in-addr.arpa.
+105.208.85.200.in-addr.arpa.
+aziacarpets.com.
+179.134.170.193.in-addr.arpa.
+www.facebook.com.
+66.223.232.200.in-addr.arpa.
+tracker.openbittorrent.com.
+sites.google.com.
+mail.tnx.net.
+s2.macupdate.com.
+44.247.50.200.in-addr.arpa.
+imap.gmail.com.
+247.151.201.112.in-addr.arpa.
+www.googleadservices.com.
+tonycpa.com.
+origin.by167w.bay167.mail.live.com.
+45.238.168.192.in-addr.arpa.
+thebetterlenders.com.
+6.214.247.88.in-addr.arpa.
+motox.accu-weather.com.
+mx10.who.int.
+libpacmed.com.
+25.123.32.190.in-addr.arpa.
+118.199.55.177.in-addr.arpa.
+www.pourquois.com.
+a.root-servers.net.
+accounts.google.com.
+juanalvarezm.blogspot.com.
+photos-e.ak.fbcdn.net.
+95.5.0.10.in-addr.arpa.
+d1j68ux4ukg4g1.cloudfront.net.
+i1.ytimg.com.
+39.220.226.63.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+t2.gstatic.com.
+profile.ak.fbcdn.net.
+www.google.com.
+dns1.southeast-pa.com.
+plitka.spb.ru.
+www.facebook.com.
+www.elconfidencial.com.
+js.wlxrs.com.
+136.162.131.95.in-addr.arpa.
+shyr.sumy.org.
+sc.msn.com.
+186.242.19.187.in-addr.arpa.
+ax.su.itunes.apple.com.
+198.184.45.200.in-addr.arpa.
+a.root-servers.net.
+www.ddm.org.au.
+244.157.210.201.in-addr.arpa.
+www.comedy104.com.
+a4.sphotos.ak.fbcdn.net.
+www.youtube.com.
+eurosocialfiscal.org.
+www.wikipedia.nl.
+conf.socialvi.be.
+starwars.wikia.com.
+shared.live.com.
+talent-scale.com.
+www.braintreegateway.com.
+drayok.deviantart.com.
+imap.gmail.com.
+rktm.spb.ru.
+www.google-analytics.com.
+www.conama.cl.
+251.188.142.187.in-addr.arpa.
+scotia70657275.h1x.com.
+b.scorecardresearch.com.
+a.root-servers.net.
+a1505.l.akamai.net.
+swim-online.foroac.org.
+a.root-servers.net.
+secure-uk.imrworldwide.com.
+mtalk.google.com.
+conjugator.reverso.net.
+www.motors.ebay.com.
+apis.google.com.
+58.5.21.201.in-addr.arpa.
+www.vaginamaster.com.
+a.root-servers.net.
+0-292.channel.facebook.com.
+pterlink.ru.
+www.gayblacksexguide.com.
+smtp.touchpoint.co.nz.
+zh-cn.facebook.com.
+rs154dt.rapidshare.com.
+twitter.com.
+pixel.invitemedia.com.
+yoco-fashion.com.
+31.104.142.187.in-addr.arpa.
+dthesurfacingjungle.com.
+gfx3.hotmail.com.
+apps.facebook.com.
+a.c-0.19-230f5000.10011.1518.19d3.3ea1.210.0.rc42tqj7mtqr7ic8vlvkbc55nb.avqs.mcafee.com.
+csi.gstatic.com.
+press-centre.ru.
+www.tigersandstrawberries.com.
+casalcasadosp.blogspot.com.
+amigurumi-montse.blogspot.com.
+photos-f.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+www.iogear.com.
+aeggroup.net.s5a2.psmtp.com.
+140.2.133.86.in-addr.arpa.
+mr.vipmed.ru.
+apps.facebook.com.
+purosvideos.net.
+a8.sphotos.ak.fbcdn.net.
+yahoo.es.
+smtp4.absinternet.com.
+fy.wikipedia.org.
+freetelecom.fr.
+thumbs3.ebaystatic.com.
+creative.ak.fbcdn.net.
+heartbeat.dm.origin.com.
+channelgroup.net.
+msiv.com.
+checkip.dyndns.org.
+164.69.146.187.in-addr.arpa.
+interserve.org.
+mail.dyc.edu.
+googleads.g.doubleclick.net.
+au.answers.yahoo.com.
+urs.microsoft.com.
+filminfo.ru.
+smtp.siscom.net.
+twitter.com.
+safebrowsing.clients.google.com.
+fbtrn-lash.net.
+bps-stage.takeda.it.
+apps.facebook.com.
+pnrws.skype.com.
+developers.facebook.com.
+162.24.11.186.in-addr.arpa.
+a4.sphotos.ak.fbcdn.net.
+t.co.
+www.se-te.com.
+www.google.com.
+terra.com.br.
+www.xvideos.com.
+0.11-a309c081.21033.1518.19d4.3ea1.410.0.qtm62tr24fszzi9mickjf2p4tt.avqs.mcafee.com.
+rh99vd:it.83ec.
+go.srvnow.com.
+time.nist.gov.
+mail.idcfinancial.com.
+dfwgroup.com.
+sn1.gateway.messenger.live.com.
+dns.msftncsi.com.
+fr-fr.facebook.com.
+google.com.
+emediate.apmmedia.net.
+farm1.static.flickr.com.
+tmhomes.co.uk.
+.
+ar-ar.facebook.com.
+ns2.globalsources.com.
+ssl.gstatic.com.
+41.39.57.82.in-addr.arpa.
+enidnews.com.
+bashinform.ru.
+192.87.146.93.in-addr.arpa.
+pixel.facebook.com.
+profile.ak.fbcdn.net.
+apis.google.com.
+xmpp.device07.prod.capptain.com.
+www.linguee.es.
+safebrowsing-cache.google.com.
+www.xing.com.
+download.xbox.com.
+click.emailinfo2.bestbuy.com.
+teredo.ipv6.microsoft.com.
+www.youtube.com.
+nimbus.bitdefender.net.
+www.scubadivingphuket.net.
+amateursextapes.adultvideobuzz.com.
+bf74c17fce5b72a5f98844a4f8446b2c.co.cc.
+pixerloadbalancer-126298269.us-east-1.elb.amazonaws.com.
+www.statcounter.com.
+pixel.facebook.com.
+suggestqueries.google.com.
+contact.ebay.com.
+migbank.com.
+video.gazetevatan.com.
+zfxug.com.
+online-au.objective.com.
+developers.facebook.com.
+snippets.mozilla.com.
+www.clubofthewaves.com.
+_457_26_1.
+smtp.subscribe.ru.
+doug1izaerwt3.cloudfront.net.
+mx2.unccd.int.
+kermarak.radiolivre.org.
+www.masajecorporal.com.
+plugin.maldi.tv.
+i3.ytimg.com.
+a1505.l.akamai.net.
+nicholsonintl.com.
+18.151.155.178.in-addr.arpa.
+207.0.86.186.in-addr.arpa.
+www.wholesale-luxury.com.
+www.google.com.mx.
+ssl.gstatic.com.
+cdn.gigya.com.
+adobe.ugc.bazaarvoice.com.
+images.anniesattic.com.
+s-static.ak.fbcdn.net.
+89.111.46.186.in-addr.arpa.
+828vdo66y.p89s8x4y.
+jackinworld.com.
+www2.smartadserver.com.
+diamondtrustgame.com.
+s.youtube.com.
+filial.vrn.ru.
+ratchet.dayspring.com.
+info.juridicas.unam.mx.
+a.root-servers.net.
+www.z7mh.com.
+ns2.cheat.net.ru.
+pixel.facebook.com.
+xtu.me.
+bs.serving-sys.com.
+a.root-servers.net.
+s-static.ak.facebook.com.
+content.imorphosis.com.
+time.windows.com.
+mail.yimg.com.
+wwww.siliconera.com.
+a.root-servers.net.
+a.root-servers.net.
+169.163.29.89.in-addr.arpa.
+messenger.hotmail.com.
+photos-a.ak.fbcdn.net.
+89.221.25.190.in-addr.arpa.
+31.37.55.187.in-addr.arpa.
+www.almightycontent.com.
+images.apple.com.
+a.root-servers.net.
+sex-4.shemalepuzzle.com.
+10.152.3.108.in-addr.arpa.
+au.download.windowsupdate.com.
+www.davidemaggio.it.
+79.91.116.82.in-addr.arpa.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+plus.google.com.
+mx5.mail.yahoo.co.jp.
+cars.bookit.com.
+google.com.
+www.facebook.com.
+wwwimages.adobe.com.
+220.246.206.190.in-addr.arpa.
+developers.facebook.com.
+api.twitter.com.
+claremontounry.com.
+839.coll.ning.com.
+photos-b.ak.fbcdn.net.
+elvensoft.net.
+www.googleadservices.com.
+mail2.bravehost.com.
+online.speedbit.com.
+www.bing.com.
+13.55.157.186.in-addr.arpa.
+download744.avast.com.
+cemwxo1b6.14ta.
+a1157.phobos.apple.com.edgesuite.net.
+19.88.122.74.in-addr.arpa.
+13.160.224.195.in-addr.arpa.
+dns.msftncsi.com.
+an.d.chango.com.
+251.175.42.201.in-addr.arpa.
+www.facebook.com.
+checkip.dyndns.org.
+profile.ak.fbcdn.net.
+mx1.decknet.fr.
+jolenesbeenwriting.blogspot.com.
+www.ratepoint.com.
+horwath.co.uk.
+shorinryu.ru.
+csi.gstatic.com.
+www.bluegala.com.
+www.rumbo.es.
+ds.addthis.com.
+yahoo.com.
+237.209.168.192.in-addr.arpa.
+newsrss.bbc.co.uk.
+capital-network.net.
+profile.live.com.
+acatoday.org.inbound15.mxlogicmx.net.
+75.66.105.190.in-addr.arpa.
+ngmknaflk.o43q6v1v.
+buick.riobrancofac.edu.br.
+www.ee77ee.com.
+time.chttl.com.tw.
+google.com.
+www.teamtoyminator.org.
+teredo.ipv6.microsoft.com.
+www.facebook.com.
+ksn2-12.kaspersky-labs.com.
+www.granttube.com.
+mscmags.com.
+60.148.168.192.in-addr.arpa.
+galkasoft.ru.
+sleinous.dyndns.info.
+www.time.com.
+207.239.171.111.in-addr.arpa.
+dns.detroit.net.
+cde.unibe.ch.
+alerts.conduit-services.com.
+o-o.preferred.atl14s01.v24.lscache5.c.youtube.com.
+rostovinfo.ru.
+ar.answers.yahoo.com.
+www.coolrom.com.
+m.addthisedge.com.
+metrodotpop.com.
+remydumont.net.
+r._dns-sd._udp.0.55.211.10.in-addr.arpa.
+www.animal-crossing.com.
+www.internal.schools.net.au.
+50.174.244.190.in-addr.arpa.
+a.root-servers.net.
+photos-ugc.l.google.com.
+3h93lxn4m.90kd.
+202.68.21.187.in-addr.arpa.
+web38.jimdo-server.com.
+torontoboatshow.com.
+uaqxj:1oo.32xl.
+s.youtube.com.
+twitter.com.
+mozilla.pettay.fi.
+mail.live.com.
+www.libremercado.com.
+mail.samswope.com.
+unifi.lan.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+10.147.6.203.in-addr.arpa.
+mlonlinegeneration.wordpress.com.
+a.root-servers.net.
+2.63.139.178.in-addr.arpa.
+.
+mx.bmb.com.
+d2syub29v5lge2.cloudfront.net.
+tap2-cdn.rubiconproject.com.
+acte.org.2.arsmtp.com.
+clients1.google.com.
+p130.s523ll5pu6s1.com.
+balharbourflorida.com.
+a.root-servers.net.
+www.faperos.com.
+maps.gstatic.com.
+pixel.quantserve.com.
+www.facebook.com.
+52.102.66.187.in-addr.arpa.
+11.112.194.91.in-addr.arpa.
+api.myprecisionads.com.
+233.80.190.189.in-addr.arpa.
+addons.mozilla.org.
+williamzhou.com.
+i.dailymail.co.uk.
+a.root-servers.net.
+mail.defythis.com.
+gosprod-qos01.m3d-syd.ea.com.
+msn.match.com.akadns.net.
+www.lifestreetmedia.com.
+www.jorigames.com.
+www.facebook.com.
+demilovato.com.
+www.todopapas.com.
+msgr.updates.yahoo.com.
+i3.ytimg.com.
+215.57.110.201.in-addr.arpa.
+www.google.com.
+www.betaarchive.co.uk.
+i1.ytimg.com.
+yahoo.co.uk.
+astiline.ru.
+sktuote.ru.
+performair.com.
+altfarm.mediaplex.com.
+smtp3.wescorp.org.
+a6.sphotos.ak.fbcdn.net.
+s7.addthis.com.
+server82.appriver.com.
+urs.microsoft.com.
+rusneft.ru.
+www.felixjpalma.es.
+ksn1-12-part1.kaspersky-labs.com.
+mscrl.microsoft.com.
+133.171.82.200.in-addr.arpa.
+www.google.com.
+249.79.96.114.in-addr.arpa.
+snaps.vidiemi.com.
+b._dns-sd._udp.0.0.168.192.in-addr.arpa.
+a.rad.msn.com.
+pubads.g.doubleclick.net.
+a2.sphotos.ak.fbcdn.net.
+82.230.132.144.in-addr.arpa.
+www.bestcupon.com.ar.
+i3.ytimg.com.
+b3.mookie1.com.
+184.195.235.189.in-addr.arpa.
+_031_79_0.
+www.librolibro.es.
+unthb9r8d.20gt.
+ad.doubleclick.net.
+mia.mediaedgecia.com.
+110.133.23.62.in-addr.arpa.
+google.com.
+profile.ak.fbcdn.net.
+71.104.237.189.in-addr.arpa.
+cstdata.com.
+profile.ak.fbcdn.net.
+195.143.138.187.in-addr.arpa.
+amebasaladeriva.com.
+sympatico.ca.
+www.mozilla.org.
+nbyouthsoccer.com.
+15.187.245.190.in-addr.arpa.
+unisys.fr.
+jardines.ydecoraciondeinteriores.com.
+www.brokenbells.com.
+www.strictlysudoku.com.
+eo.wikipedia.org.
+www.aircharter-international.com.
+www.facebook-mp3.co.
+main.exoclick.com.
+a.root-servers.net.
+pixel.facebook.com.
+www.internostrum.com.
+_942_63_3.
+149.12.168.192.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+photos-e.ak.fbcdn.net.
+cinemaggel.blogspot.com.
+thetelephoneconnection.com.s7b2.psmtp.com.
+kbp.ru.
+208.122.82.200.in-addr.arpa.
+search-results.site90.net.
+pixel.facebook.com.
+www.googleadservices.com.
+a.root-servers.net.
+80.230.22.202.in-addr.arpa.
+static.ak.fbcdn.net.
+guspereyra.blogspot.com.
+abzurdah-filosofia.blogspot.com.
+hotelcall.ru.
+nineviya.ru.
+i4.ytimg.com.
+salud.regioncallao.gob.pe.
+profile.ak.fbcdn.net.
+connect.facebook.net.
+googleads.g.doubleclick.net.
+60.239.53.83.in-addr.arpa.
+228.66.19.61.in-addr.arpa.
+a.root-servers.net.
+ddns.iview-ddns.com.
+117.225.145.187.in-addr.arpa.
+tritiumband.com.
+luismartinez4.files.wordpress.com.
+amxinternational.com.
+a8.sphotos.ak.fbcdn.net.
+sin.net.
+p.rightaction.com.
+a.root-servers.net.
+distilleryimage4.instagram.com.
+s0.2mdn.net.
+dns.msftncsi.com.
+www.astroscu.unam.mx.
+corp.badoo.com.
+apps.facebook.com.
+weibo.pp.cc.
+a2.sphotos.ak.fbcdn.net.
+39.198.69.24.in-addr.arpa.
+espanol.answers.yahoo.com.
+www.jasonmomoa.com.
+164.241.182.189.in-addr.arpa.
+abbottcapital.com.s8a1.psmtp.com.
+photos-g.ak.fbcdn.net.
+0.13.123.94.in-addr.arpa.
+www.mokkabisuteria.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+news.buzzbox.com.
+hi-in.facebook.com.
+68.38.168.192.in-addr.arpa.
+profile.ak.fbcdn.net.
+docs.google.
+www.pokerroom.com.
+euroionia.com.
+108.135.168.192.in-addr.arpa.
+x-top.info.
+rubikspark.jimdo.com.
+clfrates.com.s8a2.psmtp.com.
+pegaso.ific.uv.es.
+me-cdn.effectivemeasure.net.
+ssl.gstatic.com.
+hootsuite.com.
+sp.cwfservice.net.
+a2.twimg.com.
+refundhomeloans.com.
+en.netlog.com.
+www.boardingschoolreview.com.
+gmaccmahd.com.
+www.mamafaiz.com.
+180.60.126.24.in-addr.arpa.
+r._dns-sd._udp.lan.
+d2108679.xoom.it.
+ssl.gstatic.com.
+firstchoice.ru.
+adserver.duetads.com.
+14.161.210.62.in-addr.arpa.
+rad.msn.com.
+www.howtogardenadvice.com.
+mail.vertex.com.ar.
+3ie33cpgj6dhi-c.c.yom.mail.yahoo.com.
+media.y8.com.
+147.210.211.220.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+www.todoanimes.com.
+a.root-servers.net.
+www.donutey.com.
+s2.youtube.com.
+10.35.62.177.in-addr.arpa.
+www.hotmail-iniciar-sesion.com.
+a639.da1.akamai.net.
+148.255.199.197.in-addr.arpa.
+me.effectivemeasure.net.
+www.symantec.com.akadns.net.
+graph.facebook.com.
+a1001.w40.akamai.net.
+r8b7ydgpg.e66c6k6z.
+ifreest.ru.
+onegaprim.ru.
+234.163.87.85.in-addr.arpa.
+208.50.126.123.in-addr.arpa.
+img1.blogblog.com.
+a2.sphotos.ak.fbcdn.net.
+232.131.162.189.in-addr.arpa.
+de-de.facebook.com.
+www.americanexpressfhr.com.
+m.facebook.com.
+a.root-servers.net.
+reidsteel.co.uk.
+www.wikimediafoundation.org.
+a5.sphotos.ak.fbcdn.net.
+ayudatec.cl.
+fbcdn-photos-a.akamaihd.net.
+clients1.google.com.br.
+89.55.36.174.in-addr.arpa.
+jrw.com.
+i.walmartimages.com.
+a7.sphotos.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+mensmodelstalk.blog8.fc2.com.
+stun.client.akadns.net.
+s.youtube.com.
+www.ansp.gob.sv.
+gfx1.hotmail.com.
+a8.sphotos.ak.fbcdn.net.
+js.psp.guias-trucos-juegos.com.
+a.root-servers.net.
+plusone.google.com.
+a5.sphotos.ak.fbcdn.net.
+d37ts36x2rbd21.cloudfront.net.
+145.241.222.24.in-addr.arpa.
+www.gq.com.tw.
+www.update.microsoft.com.
+204.157.82.190.in-addr.arpa.
+d2098481.xoom.it.
+dam.cloud.kargo.com.
+safebrowsing-cache.google.com.
+photos-d.ak.fbcdn.net.
+ad.yieldmanager.com.
+a.root-servers.net.
+www.syriarose.com.
+swkins.com.s8a1.psmtp.com.
+a2.sphotos.ak.fbcdn.net.
+172.203.175.189.in-addr.arpa.
+gfx1.hotmail.com.
+86.147.156.78.in-addr.arpa.
+dns.msftncsi.com.
+a.root-servers.net.
+53.237.183.212.in-addr.arpa.
+mx.youtube.com.
+a8.sphotos.ak.fbcdn.net.
+www.youtube.com.
+www.geocities.com.
+migranviaje.wordpress.com.
+ssl.gstatic.com.
+downloads.networkmagic.com.
+connect.facebook.net.
+www.farskids168.com.
+asrengineering.com.
+static.ak.fbcdn.net.
+c-0.19-a309f481.483.1518.19d4.3ea1.210.0.gqsznzg3zhr6v264pgdsuub4vi.avqs.mcafee.com.
+a1001.w40.akamai.net.
+229.89.233.220.in-addr.arpa.
+120.3.198.72.in-addr.arpa.
+www.clubmed.com.my.
+3.233.10.186.in-addr.arpa.
+api.twitter.com.
+viagem.br.msn.com.
+aol.com.
+s-external.ak.fbcdn.net.
+client.akamai.com.
+247.16.33.46.in-addr.arpa.
+tdbde6gz7.g93z8f0c.
+80.23.222.189.in-addr.arpa.
+www.hotmail.com.
+169.35.145.189.in-addr.arpa.
+www.warezmedia.net.
+ssl.gstatic.com.
+kailep.deviantart.com.
+vote.mmosite.com.
+www.morevisits.info.
+www.grape-info.com.
+powerwall.msnbc.msn.com.
+a1505.l.akamai.net.
+211.217.131.187.in-addr.arpa.
+m.addthisedge.com.
+plus.google.com.
+rs424l33.rapidshare.com.
+www.ridemygirls.com.
+a7.sphotos.ak.fbcdn.net.
+theageofreason.org.
+grants1.nih.gov.
+tcfhlaw.com.s8a2.psmtp.com.
+static.ak.fbcdn.net.
+elsphiprtp001.science.regn.net.
+click.info.simpletuition.com.
+a.root-servers.net.
+photos-a.ak.fbcdn.net.
+a7.sphotos.ak.fbcdn.net.
+euro.mediotiempo.com.
+m.addthisedge.com.
+wordpress.com.dob.sibl.support-intelligence.net.
+navnbwnscwa.cc.
+a1507.b.akamai.net.
+a.root-servers.net.
+tssl.kewego.com.
+www.ero-advertising.com.
+armmf.adobe.com.
+i-55.com.
+zacapacity.mundoanuncio.com.gt.
+pup.raz.htcsense.com.
+services.windowsmedia.com.
+99.154.92.201.in-addr.arpa.
+85.163.79.201.in-addr.arpa.
+sp.cwfservice.net.
+safebrowsing.clients.google.com.
+cqrjcpb9x.c09h8i7w.
+www.erpsoftwaredownload.com.
+dns2.easydns.net.
+safebrowsing.clients.google.com.
+ksn2-12.kaspersky-labs.com.
+mail.
+vivalamodaa.blogspot.com.
+dpmconsult.de.
+www.humpingbunny.com.
+92.43.90.190.in-addr.arpa.
+www.loscostos.info.
+teamxenon.com.
+www.bago.com.
+r._dns-sd._udp.0.0.2.10.in-addr.arpa.
+cbkservices.com.
+201.201.58.71.in-addr.arpa.
+28.media.tumblr.com.
+www.reforma.com.
+170.159.52.83.in-addr.arpa.
+i3.ytimg.com.
+ap.lijit.com.
+dns.msftncsi.com.
+ssl.gstatic.com.
+bs.serving-sys.com.
+249.50.215.109.in-addr.arpa.
+228.135.178.190.in-addr.arpa.
+sites.google.com.
+pixel.facebook.com.
+external.ak.fbcdn.net.
+www.shiou.ws.
+bestflatironsforhair.com.
+172.142.54.187.in-addr.arpa.
+external.ak.fbcdn.net.
+a.root-servers.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+239.237.137.186.in-addr.arpa.
+185.15.157.201.in-addr.arpa.
+174.37.152.189.in-addr.arpa.
+secure.logmein.com.
+asiancondition.blogspot.com.
+154.102.144.186.in-addr.arpa.
+r._dns-sd._udp.0.129.37.10.in-addr.arpa.
+g77l:yezr.u06v0k8p.
+external.ak.fbcdn.net.
+unsubscribe.fromdoppler.com.
+cdn.foxadd.com.
+myimg.zhaopin.com.
+daddyforever.com.
+www.strawsticksandbricks.com.
+sc19.rules.mailshell.net.
+a659.b.akamai.net.
+636f6e74656e74.6e657773696e63.636f6d.80hcfaba321.webcfs00.com.
+www.flashvault.net.
+firma.eniro.dk.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+vmx.shiplpskey.com.redcondor.net.
+fxprofsignal.ru.
+static.ak.fbcdn.net.
+ksn2-12.kaspersky-labs.com.
+i3.ytimg.com.
+30-60-90-day-sales-plan.com.
+a2.sphotos.ak.fbcdn.net.
+csi.gstatic.com.
+lyricskeeper.fr.
+232.148.42.95.in-addr.arpa.
+s-static.ak.fbcdn.net.
+v8.nonxt3.c.youtube.com.
+clients2.google.com.
+api-read.facebook.com.
+www.balnaves.com.
+clock.fmt.he.net.
+ufrnet.ufrn.br.
+mx.mechel.com.
+a.root-servers.net.
+a-0.19-25093001.c0a0083.1518.19c4.3ea1.210.0.hr8fzrijs2f2fuk2bz5jqjl3fj.avqs.mcafee.com.
+g.ceipmsn.com.
+rcfesq.com.
+www.skins.tv.
+www.cooperativa.cl.
+i.ytimg.com.
+www.vpnpop.com.
+a7.sphotos.ak.fbcdn.net.
+pphsh2lx2.p76t7s5s.
+a8.sphotos.ak.fbcdn.net.
+travel.wikia.com.
+a3.da1.akamai.net.
+www.buildabear.ae.
+www.frype.lt.
+94.5.1.181.in-addr.arpa.
+poemi-carolina.blogspot.com.
+csi.gstatic.com.
+fashionloven.com.
+nuvxak1h1.99fb.
+www.1musica.com.
+plusone.google.com.
+bluemars.com.
+johnconti.com.s6a2.psmtp.com.
+a.root-servers.net.
+completecolour.com.au.
+b-0.19-a30e8008.10081.1518.19d3.3ea1.410.0.gu1k3w3q7l4hm126j4jqbi9ldb.avqs.mcafee.com.
+b.scorecardresearch.com.
+www.judithpaton.com.
+ad.z5x.net.
+fbcdn-photos-a.akamaihd.net.
+s0.2mdn.net.
+hazuki-pat.com.
+fashion4chill.com.
+tiresias.gr.
+planetfallas.com.
+90.40.58.186.in-addr.arpa.
+www.nobodycares.ca.
+ads.adxpansion.com.
+clxrcvnsse.ms.
+ds.serving-sys.com.
+google.com.mx.
+www.squashleon.com.
+pegasus.baltmd.ru.
+crl.thawte.com.
+gfx1.hotmail.com.
+profiles.google.com.
+247.109.126.80.in-addr.arpa.
+mail.msss.ru.
+www.bigtitsroundasses.com.
+t0.gstatic.com.
+www.google-analytics.com.
+time.chttl.com.tw.
+mail2.abena.dk.
+pixel.facebook.com.
+bejomi1.es.tl.
+www.google.com.
+doglover.com.
+es-es.facebook.com.
+alfon.org.
+ns1.comtelligence.net.
+kordp.ru.
+141.1.168.192.in-addr.arpa.
+api.tweetmeme.com.
+tqbnngfpzworfmp.biz.
+mail.live.com.
+a1007.w43.akamai.net.
+18.9.168.192.in-addr.arpa.
+us.mg4.mail.yahoo.com.
+a.root-servers.net.
+www.bywifi.com.
+static2.embarazoymas.com.
+directcopiersupplies.com.
+_481_76_9.
+photos-f.ak.fbcdn.net.
+eltiomananero.blogspot.com.
+www.giochislot.com.
+liranroll.com.mx.
+a0.twimg.com.
+a998.mm1.akamai.net.
+platform.twitter.com.
+s-static.ak.fbcdn.net.
+www.gda.com.
+www.juegosdecarrosgratis.co.
+external.ak.fbcdn.net.
+42.168.243.148.in-addr.arpa.
+img7.sencha.com.
+www.google.com.
+mx2.hotmail.com.
+tag.admeld.com.
+15.216.51.68.in-addr.arpa.
+www.cachador.co.
+vocid-cdn.elnortedecastilla.es.
+saiteprice.ru.
+www.wikimediafoundation.org.
+www.mostonline.org.
+pixel.facebook.com.
+api.twitter.com.
+buddgroup.com.s5a1.psmtp.com.
+www.zeplan.biz.
+google.com.
+ntn-group.ru.
+reddit.com.
+220.131.221.87.in-addr.arpa.
+pt-br.facebook.com.
+www.redtube.com.
+www.playing2.com.
+liken0ther.no-ip.biz.
+framanc.com.
+89.180.248.70.in-addr.arpa.
+fne.net.
+www.e-computo.net.
+91.92.231.190.in-addr.arpa.
+www.google.com.mx.
+72.107.11.201.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+api.facebook.com.
+ax.init.itunes.apple.com.
+m2m1.inner-active.com.
+sp.cwfservice.net.
+www.facebook.com.
+static.ak.fbcdn.net.
+www.dramainnature.com.
+26.194.232.24.in-addr.arpa.
+www.vjoon.com.
+data.flurry.com.
+mexico32.com.
+pituco.com.
+side2.no.
+om98.ru.
+med.uni-heidelberg.de.
+es-la.facebook.com.
+bjjweekly.com.
+155.7.177.189.in-addr.arpa.
+www.ledevoir.com.
+117.137.37.190.in-addr.arpa.
+peliculasinmegavideo.com.
+hammerson.com.s200a1.psmtp.com.
+bankom.ru.
+kamidesunya.blogspot.com.
+api.twitter.com.
+crl.microsoft.com.
+widgets.amung.us.
+syndication.exoclick.com.
+120.52.18.211.in-addr.arpa.
+vthumb.ak.fbcdn.net.
+shioz.jp.
+tsm01.eset.com.
+77.39.225.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+us1.badoo.com.
+adsx.greystripe.com.
+ptgh.co.uk.pri-mx.uk0109.smtproutes.com.
+ccm.imn.intel.com.
+www.tumblr.com.
+naturalmedications.com.
+220.173.103.201.in-addr.arpa.
+76.147.15.194.in-addr.arpa.
+www.metalicas.estimulaciontemprana.org.
+zhz.ivanovo.ru.
+92.91.38.186.in-addr.arpa.
+iphone-wu.apple.com.
+creative.ak.fbcdn.net.
+231.101.24.190.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+infinitos.es.
+mail1.trellist.com.
+api-read.facebook.com.
+ocs.ebay.com.
+external.ak.fbcdn.net.
+20.184.251.189.in-addr.arpa.
+static-cdn2.ustream.tv.
+35-courier.push.apple.com.
+creative.ak.fbcdn.net.
+gumaih.com.
+mail.
+tiny.cc.
+yahoo.com.
+a.root-servers.net.
+dns.msftncsi.com.
+www.vintageandchiclove.com.
+www.routledgementalhealth.com.
+apps.facebook.com.
+14.134.110.186.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+jbzuu.beastavsclub.com.
+www.soc-neuro-onc.org.
+arabidopsis.info.
+shop.tfl.gov.uk.
+themnaxs.deviantart.com.
+janegrey.hubpages.com.
+moreapps.droidhen.com.
+an.tacoda.net.
+tair.by.
+dsn5.d.skype.net.
+uzhnp.gng.com.ua.
+platform.twitter.com.
+211.57.167.218.in-addr.arpa.
+l.yimg.com.
+hamachi-dc.logmein-gateway.com.
+www.1001postales.com.
+www8.agame.com.
+a3.twimg.com.
+developers.facebook.com.
+billing.sharo4ka.ru.
+dns.msftncsi.com.
+www.youtube.com.
+www.google-analytics.com.
+idpix.media6degrees.com.
+blst.msn.com.
+a1.sphotos.ak.fbcdn.net.
+c479837.r37.cf2.rackcdn.com.
+a.root-servers.net.
+sp.cwfservice.net.
+profile.ak.fbcdn.net.
+fb-zc1.cityville.zynga.com.
+mfaltd.com.s8b2.psmtp.com.
+ma90-r.analytics.edgesuite.net.
+www2.cromos.com.co.
+88.236.82.186.in-addr.arpa.
+141.217.212.201.in-addr.arpa.
+www.youtube.com.
+www.rctopsites.com.
+i4.ytimg.com.
+c.statcounter.com.
+thehizoku.com.
+57.226.142.187.in-addr.arpa.
+124.webim0230.webim.myspace.com.
+profile.ak.fbcdn.net.
+2.160.108.216.in-addr.arpa.
+www.cameras.co.uk.
+www.youtube.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+matineeashell.net.
+proxy.yospb.yahoo.com.
+prttravel.net.
+17.217.134.216.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+nimdev.com.2.0001.arsmtp.com.
+www.synchrondatenbank.de.
+www.lokotop.net.
+www.google.com.
+graph.facebook.com.
+mail.google.com.
+a.ads2.msads.net.
+ocsp.verisign.com.
+www.emol.com.
+profile.ak.fbcdn.net.
+mx.youtube.com.
+www.facebook.com.
+rubennavarrofilms.com.
+immo-trend.at.
+track.bobs-tgirls.com.
+abcblobal.net.
+bs.serving-sys.com.
+166.94.233.99.in-addr.arpa.
+flippingtypical.com.
+photos-h.ak.fbcdn.net.
+www.imagenesdemaria.com.
+nospam.chilitech.net.
+video.google.com.mx.
+a.root-servers.net.
+2.bp.blogspot.com.
+de08vphraus02.honeywell.com.
+yyy.com.
+bitbucket.fastpace.org.
+147.132.162.189.in-addr.arpa.
+anywhere.platform.twitter.com.
+edge.quantserve.com.
+api-read.facebook.com.
+aqxok8whh.04dd.
+www.meusrecados.com.
+juegos.latingames.com.
+www.update.microsoft.com.
+safebrowsing-cache.google.com.
+www.freesexnavigator.com.
+dvanemorris.com.
+www.fempclm.com.
+xml12es.farolatino.com.
+twitter.com.
+getmortgagez.com.
+ib.mookie1.com.
+a3.sphotos.ak.fbcdn.net.
+photos-d.ak.fbcdn.net.
+www.gourmetfly.com.
+www.deviantart.com.
+www.illinoishistory.gov.
+b92.yahoo.co.jp.
+yahoo.com.
+cdn.yottos.com.
+a.root-servers.net.
+3runescape8.no-ip.biz.
+forum.playfish.com.
+www.16bitsoft.com.
+204.3.135.186.in-addr.arpa.
+a.root-servers.net.
+aspmx.datainfosys.net.
+static.ak.facebook.com.
+a.root-servers.net.
+lasersafety.com.
+emotion-photo.ru.
+gw-mail6.3rdstudio.net.
+mikewarez.disqus.com.
+c:emeiy98.p00s4w0z.
+www.facebook.com.
+redirector.c.youtube.com.
+e4805.b.akamaiedge.net.
+3wmexico.com.dnsbl7.mailshell.net.
+a.root-servers.net.
+a2.sphotos.ak.fbcdn.net.
+english.mag2.com.
+www.facebook.com.
+53.72.25.95.in-addr.arpa.
+116.5.74.180.in-addr.arpa.
+sp.cwfservice.net.
+subarcade.com.
+120.39.151.79.in-addr.arpa.
+2007.ispace.ci.fsu.edu.
+zww.me.
+a3.sphotos.ak.fbcdn.net.
+fbio.uh.cu.
+55.181.160.187.in-addr.arpa.
+24.154.72.190.in-addr.arpa.
+pagead2.googlesyndication.com.
+imgtech.ru.
+tropiezosdelavida.blogspot.com.
+hotmail.it.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+mosrembyt.ru.
+2.38.133.174.in-addr.arpa.
+www.trenesmls.es.
+plus.google.com.
+accounts.google.com.
+ads.yimg.com.
+www.noticiasdelcosmos.com.
+122.163.149.109.in-addr.arpa.
+googleads.g.doubleclick.net.
+amadeus.lv.
+counter.yadro.ru.
+toabonothfaci.ph.
+90.164.222.189.in-addr.arpa.
+translation.toolbar.conduit-services.com.
+staticapp.icpsc.com.
+screamtour.com.
+173.100.132.190.in-addr.arpa.
+zoomyummy.com.
+surveyclub.com.
+z58lfabb3.j23h7z2t.
+dns.msftncsi.com.
+a8.sphotos.ak.fbcdn.net.
+229.75.154.187.in-addr.arpa.
+a.root-servers.net.
+_137_19_1.
+a1.twimg.com.
+www.underwaterjournal.com.
+www.update.microsoft.com.
+www.youtube.com.
+compartiendoconmisamigas.blogspot.com.
+accounts.google.com.
+randyfox.com.
+77.161.240.201.in-addr.arpa.
+videos.starmedia.com.
+101.249.201.86.in-addr.arpa.
+207.54.181.189.in-addr.arpa.
+google-earth.windows.brothersoft.com.
+d2058743.instant.xoom.it.
+wsihawaii.com.
+www.detail-mania.com.
+www.statcounter.com.
+platform.ak.fbcdn.net.
+www.youtube.com.
+www.arr-tv.com.
+prodigy.msn.com.
+a1.sphotos.ak.fbcdn.net.
+127.0.0.1.
+entretenimiento.latam.msn.com.
+149.18.224.159.in-addr.arpa.
+wpad.
+www.gstatic.com.
+a.root-servers.net.
+thrashers.nhl.com.
+i.ytimg.com.
+mail1.imco-inc.net.
+a1003.w41.akamai.net.
+www.paranormalhaven.com.
+www.historiacocina.com.
+spamfilter.rclick.com.
+235.225.39.187.in-addr.arpa.
+37.23.168.192.in-addr.arpa.
+shared.live.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+i.indiafm.com.
+static.ak.connect.facebook.com.
+i34.tinypic.com.
+connect.facebook.net.
+ad.harrenmedianetwork.com.
+25.53.149.187.in-addr.arpa.
+_452_73_8.
+inkincpr.com.
+groups.google.com.mx.
+kln.com.inbound15.mxlogic.net.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+nuevaspeliculas.info.
+a.root-servers.net.
+pagead2.googlesyndication.com.
+a372.phobos.apple.com.
+201.66.208.84.in-addr.arpa.
+flyadi-com.relay1c.spamh.com.
+elclubdelaslocaspositivas.blogspot.com.
+frankrewold.com.
+bilder.clipfish.de.
+210.254.198.190.in-addr.arpa.
+193.40.55.187.in-addr.arpa.
+gfx3.hotmail.com.
+3.51.160.187.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+docs.google.com.
+127.0.0.1.
+b._dns-sd._udp.belkin.
+91.230.132.189.in-addr.arpa.
+www.youtube.com.
+www.incredimailshop.com.
+mail.poyatos.ru.
+marketpioneer.com.s7a2.psmtp.com.
+83.1.217.74.in-addr.arpa.
+segutronic.com.
+view.atdmt.com.
+chromejs.s3.amazonaws.com.
+7.155.93.195.in-addr.arpa.
+www.google.com.
+2kme3ic3a.f48m4o4f.
+67.208.114.187.in-addr.arpa.
+ft.ntvspor.net.
+mail.southtel.ru.
+imytravel.ru.
+img824.imageshack.us.
+creatives.livejasmin.com.
+mail.ufps.tmb.ru.
+js.wlxrs.com.
+93.74.137.190.in-addr.arpa.
+profile.ak.fbcdn.net.
+elektron.pl.
+blog.apesoft.es.
+linuxsix.blogspot.com.
+www.nu.edu.sa.
+t1.gstatic.com.
+esphoto500x500.mnstatic.com.
+sfx.en.alibaba.com.
+cnfg.montiera.com.
+www.jazztelydigitalplus.com.
+www.cinmaeg.com.
+pofboxing.perm.ru.
+static.ak.fbcdn.net.
+a.root-servers.net.
+googlemail.l.google.com.
+snt0-omc1-s21.snt0.hotmail.com.
+mx1.canterburycoffee.com.
+crl.microsoft.com.
+ad.smowtion.com.
+en-us.fxfeeds.mozilla.com.
+239.102.80.201.in-addr.arpa.
+photos-g.ak.fbcdn.net.
+api.twitter.com.
+mbsg.intel.com.
+external.ak.fbcdn.net.
+www.rootsweb.ancestry.com.
+profile.ak.fbcdn.net.
+b.scorecardresearch.com.
+beita-misstrapitos.blogspot.com.
+emob220.photobucket.com.
+231.185.211.189.in-addr.arpa.
+autoroom-usa.tk.
+ssl.gstatic.com.
+smallenginewarehouse.com.s9b1.psmtp.com.
+www.nickarcade.com.
+a996.mm1.akamai.net.
+static.ak.fbcdn.net.
+toolbarqueries.l.google.com.
+i4.ytimg.com.
+www.macizorras.com.
+196.70.188.201.in-addr.arpa.
+www.manukau.ac.nz.
+gomezdecadiz.blogspot.com.
+106.161.193.190.in-addr.arpa.
+245.203.103.190.in-addr.arpa.
+www.advancescripts.com.
+www.tiedtortured.com.
+bbcore.cloudapp.net.
+gfx2.hotmail.com.
+hfengine.com.
+yui.yahooapis.com.
+www.bywifi.com.
+7md1loq:t.49rf.
+ironplanet.com.
+i52.tinypic.com.
+233.28.109.200.in-addr.arpa.
+www.decentral.com.ar.
+113.153.231.190.in-addr.arpa.
+s10.histats.com.
+a995.mm1.akamai.net.
+yhhlptf2u.n31p9a6l.
+www.google.com.mx.
+167.64.82.200.in-addr.arpa.
+www.pathology.vcu.edu.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+brig.spb.ru.
+maktoob.news.yahoo.com.
+www.polskastacja.pl.
+mail.live.com.
+goldbarshop.com.
+microsoft-netmeeting.archivospc.com.
+a1408.w43.akamai.net.
+skydrive.live.com.
+public.blu.livefilestore.com.
+235.156.104.186.in-addr.arpa.
+wiprospectramind.com.
+120.254.43.99.in-addr.arpa.
+malah.biz.
+it-it.facebook.com.
+www.imparoax.com.mx.
+strangefunnyworld.com.
+hombrerefranero.blogspot.com.
+www.philcollins.
+silverstockreport.com.
+osnovnoy.ru.
+adobe-acrobat-professional.softonic.com.
+centes01.cuttingedgenet.com.
+gud.com.
+workface.com.
+photos-e.ak.fbcdn.net.
+apple.ease.lsoft.com.
+231.47.25.125.in-addr.arpa.
+www.everestauction.com.au.
+lucasboutique.bigcartel.com.
+www.academiademusica.cl.
+_321_49_5.
+relay.voice.edge.messenger.live.com.
+bluebird2.betonmarkets.com.
+apis.google.com.
+photos-f.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+a-0.19-a30a6089.c010082.1518.19d3.3ea1.210.0.k4zg82371ek3ijdgpn6qls1b1j.avqs.mcafee.com.
+static.www.occ.com.mx.
+225.51.115.186.in-addr.arpa.
+aarabladies.com.
+marymount.fr.
+inferno.demonoid.com.
+googleapis.l.google.com.
+m.adnxs.com.
+www.pymeservices.com.
+cdn1.thumbs.xogogo.com.
+7.152.30.194.in-addr.arpa.
+ssl.gstatic.com.
+www.puebla.com.mx.
+adc-orbit.telefonica.com.
+dinell.ru.
+55.158.157.190.in-addr.arpa.
+m.addthisedge.com.
+cf.addthis.com.
+orlandoenespanol.com.
+190.2.133.186.in-addr.arpa.
+ad.yieldmanager.com.
+csi.gstatic.com.
+129.53.246.190.in-addr.arpa.
+a.root-servers.net.
+pagead2.googlesyndication.com.
+www.ciat.cgiar.org.
+www.faceinhole.co.
+platform.twitter.com.
+time.stdtime.gov.tw.
+profile.ak.fbcdn.net.
+www.sepomexyuc.gob.mx.
+170.231.160.190.in-addr.arpa.
+a.root-servers.net.
+175.37.18.177.in-addr.arpa.
+google.com.
+136.31.12.190.in-addr.arpa.
+www.efectivale.com.mx.
+billing.sharo4ka.ru.
+www.kardelenyucel.com.
+safebrowsing-cache.google.com.
+34.236.172.190.in-addr.arpa.
+gvntv.gvnstudio.com.
+eset.122.2o7.net.
+www.facebook.com.
+cfile157.uf.daum.net.
+www.mbt-shoes-sale.info.
+s3.amazonaws.com.
+id.wikipedia.org.
+98.241.153.189.in-addr.arpa.
+moviestarpets.com.
+v12.lscache2.c.youtube.com.
+code.jquery.com.
+.
+vecinos-1.blogspot.com.
+www.google.com.
+www.conchamayordomo.com.
+localcardonors.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+mail.okhammaren.se.
+75.195.104.186.in-addr.arpa.
+theclaw.net.
+nombresdebebe.blogspot.com.
+thwfx.piczo.com.
+laurelriverdesigns.com.
+adsx.greystripe.com.
+seymourjohnson.af.mil.
+yeyeolade.files.wordpress.com.
+local-bay.contacts.msn.com.
+41.240.185.190.in-addr.arpa.
+rtduuo8c1.02pn.
+i-lensk.ru.
+www.apple.com.
+myintelligentlife.wordpress.com.
+aidps.atdmt.com.
+blog.pressdisplay.com.
+west.thomson.com.
+www.manga.it.
+a.root-servers.net.
+www.google.com.
+partner.googleadservices.com.
+www.childrensbooksforever.com.
+montel.isa-geek.org.
+11.48.168.192.in-addr.arpa.
+164.146.161.189.in-addr.arpa.
+_692_60_6.
+www.decentral.com.ar.
+a.root-servers.net.
+tap-cdn.rubiconproject.com.
+blogs.nybooks.com.
+s-static.ak.facebook.com.
+a.root-servers.net.
+lavieenrosegirl.blogspot.com.
+www.tvdoo.it.
+ansonic.com.au.
+www.hfcbank.co.uk.
+p08-mobilebackup.icloud.com.akadns.net.
+www.endandit.nl.
+havenrefuge.org.uk.
+www.populars.ru.
+155.135.120.69.in-addr.arpa.
+80.134.41.187.in-addr.arpa.
+photos-d.ak.fbcdn.net.
+bomberos.cl.
+icaewmessaging.net.
+68.106.80.88.in-addr.arpa.
+static.ak.facebook.com.
+ahhelp.me.
+secure.wlxrs.com.
+atconnercpa.com.
+a.root-servers.net.
+b._dns-sd._udp.0.2.168.192.in-addr.arpa.
+154.200.83.186.in-addr.arpa.
+anycast.perf.glbdns.microsoft.com.
+ajax.googleapis.com.
+jaclninc.com.
+ad.adnetwork.net.
+orcart.facebook.com.
+i4.ytimg.com.
+photos-h.ak.fbcdn.net.
+www.facebook.com.
+pubads.g.doubleclick.net.
+a.root-servers.net.
+sidroga.com.
+graph.facebook.com.
+alerts.conduit-services.com.
+mail.adelphia.net.
+accountservices.msn.com.
+www.nonude-free-photos.com.
+googleads.g.doubleclick.net.
+s1-word-view.vo.msecnd.net.
+28.75.96.58.in-addr.arpa.
+tc6.easythumbhost.com.
+alerts.conduit-services.com.
+profile.ak.fbcdn.net.
+translate.google.com.
+www.google-analytics.com.
+au.download.windowsupdate.com.
+www.goodlightscraps.com.
+56.251.131.187.in-addr.arpa.
+spring-board.info.
+southampton.ac.uk.
+profile.ak.fbcdn.net.
+251.76.159.110.in-addr.arpa.
+mx.alegro.com.
+a4.sphotos.ak.fbcdn.net.
+163.231.27.190.in-addr.arpa.
+250.10.82.190.in-addr.arpa.
+9.217.31.189.in-addr.arpa.
+a1.sphotos.ak.fbcdn.net.
+211.151.146.91.in-addr.arpa.
+photos-h.ak.fbcdn.net.
+www.crea.org.mx.
+quick-slide-show.malavida.com.
+i2.ytimg.com.
+csi.gstatic.com.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+d15gt9gwxw5wu0.cloudfront.net.
+profile.ak.fbcdn.net.
+docs.google.com.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.facebook.com.
+etisbew.com.
+malmalloy.com.
+a.root-servers.net.
+biplan.ru.
+129.129.165.66.in-addr.arpa.
+www.logoblog.org.
+www.google.com.
+api.twitter.com.
+espndeportes.espn.go.com.
+daligallery.com.
+it-it.facebook.com.
+support.google.com.
+74.0.78.89.in-addr.arpa.
+www.condominiobahiainglesa.cl.
+utopiaverde.org.
+rn9bzlfj8.f13o5k1f.
+www.subhavaastu.com.
+golge.net.
+assine.mundodositio.com.br.
+www.facebook.com.
+corneredge.com.
+www.20minutos.es.
+feeds.reuters.com.
+clients1.google.com.
+blog-imgs-1.fc2.com.
+gfx3.hotmail.com.
+www.oagaviation.com.
+www.google.com.
+243.112.75.190.in-addr.arpa.
+uniglobecandes.com.
+external.ak.fbcdn.net.
+www.mysexgames.com.
+w88.go.com.
+local-bay.contacts.msn.com.
+www.ehealthcentral.com.au.
+64.116.51.190.in-addr.arpa.
+api-read.facebook.com.
+photos-b.ak.fbcdn.net.
+hotmail.com.
+it-it.facebook.com.
+kb.bizagi.com.
+es1.zcominc.com.
+a.root-servers.net.
+req.appads.com.
+a.root-servers.net.
+twitter.com.
+timexgroup.com.s6a2.psmtp.com.
+www.gstock.com.
+100.27.81.189.in-addr.arpa.
+um16.eset.com.
+www.google.com.
+6.243.224.186.in-addr.arpa.
+www.lojamusica.com.
+sc21.rules.mailshell.net.
+117.117.149.186.in-addr.arpa.
+www.bing.com.
+4913559952871923121-a-1802744773732722657-s-sites.googlegroups.com.
+a4.sphotos.ak.fbcdn.net.
+cdn.dsultra.com.
+www.gstatic.com.
+games.khleeg.com.
+upload.wikimedia.org.
+lapoliciaca.disqus.com.
+_625_72_5.
+rosepacking.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+134.43.148.79.in-addr.arpa.
+hyperlink.net.au.
+ct.buzzfeed.com.
+a1230.b.akamai.net.
+mail.hcgmedical.com.
+dnl-01.geo.kaspersky.com.
+nievestoledo.wikispaces.com.
+t3.gstatic.com.
+www.master.com.
+maktoob.yahoo.com.
+checkip.dyndns.org.
+fracpump.com.
+a.root-servers.net.
+s4.histats.com.
+www.facebook.com.
+b:qevtu6p.86dd.
+hwtaa::mz.p01q2r2q.
+yahoo.com.hk.
+linkhelp.clients.google.com.
+unpacked2012.org.
+155.195.141.201.in-addr.arpa.
+download891.avast.com.
+purpletriangle.co.uk.
+s.yimg.com.
+185.181.32.216.dnsbl.sorbs.net.
+photos-f.ak.fbcdn.net.
+rrjobs.com.s6a1.psmtp.com.
+profile.ak.fbcdn.net.
+loading2.widdit.com.
+cs9227.vk.com.
+89.13.224.90.in-addr.arpa.
+www.facebook.com.
+www.joshgentry.com.
+87.12.234.189.in-addr.arpa.
+api.twitter.com.
+jigsaw.w3.org.
+mscrl.microsoft.com.
+profile.ak.fbcdn.net.
+mx.caixacatalunya.es.
+stats.bloggvarde.se.
+84.143.158.187.in-addr.arpa.
+eskup.elpais.com.
+7hbzxg46w.i35o9w6b.
+img802.imageshack.us.
+apps.facebook.com.
+a2.sphotos.ak.fbcdn.net.
+groups.google.com.mx.
+mail1.eircom.net.
+40.82.26.190.in-addr.arpa.
+02011808.com.
+221.21.219.218.in-addr.arpa.
+kronen.net.
+www.sexchat.pl.
+m.google.com.
+teredo.ipv6.microsoft.com.
+tourneytime.com.
+bbs.py168.com.
+zegna.com.
+resident-evil-5-benchmark.softonic.fr.
+180.255.185.190.in-addr.arpa.
+a.root-servers.net.
+songreader.softonic.com.
+91.103.43.186.in-addr.arpa.
+a.root-servers.net.
+plus.l.google.com.
+www.sectormatematica.cl.
+pogodavsamare.ru.
+ib.adnxs.com.
+myinahar67.blogspot.com.
+lb._dns-sd._udp.0.1.168.192.in-addr.arpa.
+www.mandco.com.
+api-read.facebook.com.
+youtube.com.
+lanuevaeconomia.com.
+www.googleapis.com.
+235.144.14.186.in-addr.arpa.
+202.100.91.75.in-addr.arpa.
+mail.sinolines.com.
+static.ak.fbcdn.net.
+52.12.193.190.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+static.ak.fbcdn.net.
+ip1-02.patriarch.ru.
+wjvtke.com.
+ns3.freescale.com.
+www.asociaciongrama.org.
+www.emi.ae.
+email.com.
+fbcdn-photos-a.akamaihd.net.
+photos-e.ak.fbcdn.net.
+a4.sphotos.ak.fbcdn.net.
+8.235.217.111.in-addr.arpa.
+fredericton.kijiji.ca.
+divamission.com.
+1.gravatar.com.
+isatap.domain_not_set.invalid.
+www.insistecweb.com.
+176.131.11.189.in-addr.arpa.
+www.oyunlar1.com.
+bay.gateway.messenger.live.com.
+95.99.0.186.in-addr.arpa.
+cima.ng-london.org.uk.
+advantagesurveillance-net.mail.eo.outlook.com.
+shared.live.com.
+10.api.urban-rivals.com.
+images.francisfrith.com.
+220.78.146.189.in-addr.arpa.
+www.rackitup.com.au.
+130.13.168.192.in-addr.arpa.
+rogers.com.
+4.111.43.200.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+6.1.168.192.in-addr.arpa.
+apps.facebook.com.
+a.root-servers.net.
+bob.jncb.com.
+a.root-servers.net.
+www.facebook.com.
+external.ak.fbcdn.net.
+www.foxsportsla.com.
+179.46.135.71.in-addr.arpa.
+mail.readingworks.net.
+a4.sphotos.ak.fbcdn.net.
+plusone.google.com.
+pixel.quantserve.com.
+240.52.29.186.in-addr.arpa.
+js2.wlxrs.com.
+res5.windowsmedia.com.
+148.192.10.8.in-addr.arpa.
+ad.metanetwork.com.
+api.twitter.com.
+terratv.terra.com.mx.
+mail.loadedimage.com.
+maps.k12.wi.us.s6a1.psmtp.com.
+static.chartbeat.com.
+trilleros.activoforo.com.
+1.0.0.127.dnsbugtest.1.0.0.127.in-addr.arpa.
+googleads.g.doubleclick.net.
+chat.shopjimmy.com.
+ra4king.is-a-geek.net.
+static.ak.fbcdn.net.
+a.root-servers.net.
+www.rro.ch.
+photos-b.ak.fbcdn.net.
+www.misputillas.com.
+video.es.msn.com.
+lesmash.spb.ru.
+sac.gti.mcafee.com.
+clients2.google.com.
+congdongvip.com.
+swcdn.apple.com.
+pixer.meaningtool.com.
+hjk01.hjklaw.com.
+twitter.com.
+a5.sphotos.ak.fbcdn.net.
+www.stumbleupon.com.
+162.67.246.190.in-addr.arpa.
+booklistonline.com.
+56.107.236.190.in-addr.arpa.
+24.2.129.174.in-addr.arpa.
+dns.msftncsi.com.
+www.isg-apple.com.akadns.net.
+mail.missioncarwash.com.
+justjared.
+canon-photo-club.ru.
+180.4.19.187.in-addr.arpa.
+ad-g.doubleclick.net.
+235.110.201.187.in-addr.arpa.
+www.howtoattractagirl.org.
+www.google.com.mx.
+jeved.com.
+146.52.123.201.in-addr.arpa.
+hotel-femida.ru.
+100.94.75.195.in-addr.arpa.
+474.ns1631262.org.
+games.yahoo.com.
+mob.adwhirl.com.
+estad.emagister.com.
+132.106.35.190.in-addr.arpa.
+_353_17_6.
+rad.msn.com.
+fr-fr.facebook.com.
+rspl:6uc1.q00t4x6x.
+34.95.130.174.in-addr.arpa.
+translate.google.es.
+eserviceinfo.com.
+149.38.54.208.in-addr.arpa.
+marriott.weather.com.
+a.root-servers.net.
+225.198.192.173.in-addr.arpa.
+163.168.235.190.in-addr.arpa.
+pakistanimedia-thewaythingsare.blogspot.com.
+140.219.111.190.in-addr.arpa.
+weather.service.msn.com.
+photos-e.ak.fbcdn.net.
+www.globalfundforwomen.org.
+212.168.60.83.in-addr.arpa.
+adelia.net.
+a7.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+creative.ak.fbcdn.net.
+payment.socialgamenet.com.
+fixounet.free.fr.
+www.apple.com.
+www.facebook.com.
+missjordanlee.blogspot.com.
+topgsite.com.
+72.76.91.190.in-addr.arpa.
+citationstyles.org.
+136.105.77.79.in-addr.arpa.
+ksn6-12.kaspersky-labs.com.
+93.35.139.189.in-addr.arpa.
+news.google.com.mx.
+www.hispanicad.com.
+ntp1.tummy.com.
+www.cmpadministration.com.
+www.wustemcells-arabic.com.
+www.fragilestory.com.
+117.130.193.113.in-addr.arpa.
+img838.imageshack.us.
+translate.googleapis.com.
+www.yahoo.com.
+favbrowser.disqus.com.
+119.174.35.213.in-addr.arpa.
+rdav1.blogspot.com.
+xiangjishi.taobao.com.
+232.205.29.196.in-addr.arpa.
+autos.trovitargentina.com.ar.
+udc.udc0.glbdns.microsoft.com.
+www.bcsf.com.ar.
+56.165.77.190.in-addr.arpa.
+157.207.109.200.in-addr.arpa.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+105.33.192.123.in-addr.arpa.
+www.guia.hipnosis.org.es.
+lostrabajosdemarianelaguerrerosanchez.blogspot.com.
+american.idolblog.com.
+js01.pixelsnippet.com.
+www.ncca.ie.
+accounts.google.com.
+187.34.104.189.in-addr.arpa.
+mx2.mail.eu.yahoo.com.
+a.root-servers.net.
+rtr8.m9.ru.
+gruposinos.com.br.
+www.yahoo.com.
+112.110.249.201.in-addr.arpa.
+login.yahoo.com.
+fdgdfgdfg.com.
+119.10.39.190.in-addr.arpa.
+accidentexchange.com.s200a2.psmtp.com.
+platform.ak.fbcdn.net.
+www.google.com.
+adsfront.iminent.com.
+i4.ytimg.com.
+ntp.glb.nist.gov.
+absolut.fr.
+netmail.hetnet.nl.
+support.google.com.
+a1738.phobos.apple.com.
+29.174.78.186.in-addr.arpa.
+210.237.94.66.in-addr.arpa.
+photos-f.ak.fbcdn.net.
+s-static.ak.facebook.com.
+www.google-analytics.com.
+a.root-servers.net.
+plusone.google.com.
+eos.hs-niederrhein.de.
+www.good.is.
+esjatologico.files.wordpress.com.
+152.182.130.27.in-addr.arpa.
+www.flydreamers.com.
+a2.sphotos.ak.fbcdn.net.
+udc.msn.com.
+simpy.com.
+api.zynga.com.
+data.flurry.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+girlytattoosforgirls.com.
+yahoo.com.
+c.prodigy.msn.com.
+0-jf-w.channel.facebook.com.
+dns.msftncsi.com.
+irregularly.com.
+adx.adnxs.com.
+a.root-servers.net.
+ntp.glb.nist.gov.
+cnainsurance.com.
+espanol.answers.yahoo.com.
+a3.sphotos.ak.fbcdn.net.
+atlanta.uwservices.com.
+encielodeloceano.blogspot.com.
+.
+db._dns-sd._udp.0.129.37.10.in-addr.arpa.
+s0.2mdn.net.
+a8.sphotos.ak.fbcdn.net.
+122hotmail.com.
+luma.pt.
+developers.facebook.com.
+www.xuvn.com.
+api.facebook.com.
+93.178.145.189.in-addr.arpa.
+manualguides.info.
+www.msftncsi.com.
+mx1.nebutel.com.
+0.226.179.85.in-addr.arpa.
+v3.nonxt2.c.youtube.com.
+time.chttl.com.tw.
+154.88.59.209.in-addr.arpa.
+santacru2mortgage.com.
+hosted.analrecruiters.com.
+static.ak.fbcdn.net.
+_016_38_9.
+140.18.67.201.in-addr.arpa.
+zackandres.hi5.com.
+download843.avast.com.
+s-static.ak.fbcdn.net.
+seal.verisign.com.
+a.root-servers.net.
+87.68.92.186.in-addr.arpa.
+img07.b2b.hc360.com.
+m.addthisedge.com.
+mail.co.campbell.va.us.
+static.ak.fbcdn.net.
+js.admeld.com.
+dsn8.d.skype.net.
+206.196.165.46.in-addr.arpa.
+mscrl.microsoft.com.
+content.thermoinformatics.com.
+www.sentadoenelaire.com.
+www.crackberrista.com.
+photos-b.ak.fbcdn.net.
+238.166.227.2.in-addr.arpa.
+mail.yorktownenergy.com.
+d2089620.xoom.it.
+mail.sevel.com.uy.
+www.intercambiosbarcelona.com.
+sp.cwfservice.net.
+www.wdc.com.
+profile.ak.fbcdn.net.
+evrostroydom.ru.
+levuaf:j8.b14a5m1n.
+187.27.35.189.in-addr.arpa.
+0.7050456.com.
+183.86.11.189.in-addr.arpa.
+www.gstatic.com.
+newsrss.bbc.co.uk.
+54.181.125.99.in-addr.arpa.
+flexplan.com.
+yui.yahooapis.com.
+tcr.tynt.com.
+c1:2rzehs.i88y9e5d.
+mail25.arinc.com.
+v24.nonxt3.googlevideo.com.
+tools.google.com.
+content.yieldmanager.edgesuite.net.
+s-fitness.ru.
+www.specialops.org.
+ndhsb.org.
+global.mitsubishielectric.com.
+s-static.ak.fbcdn.net.
+busites-legacy-elb-9-1502350783.us-east-1.elb.amazonaws.com.
+foto-natura-huesca-2.blogspot.com.
+mail.cpfuinc.com.
+danielatamayo.com.
+ie9cvlist.ie.microsoft.com.
+p06-keyvalueservice.icloud.com.
+khm0.googleapis.com.
+secure.worldspot.net.
+nccpr.p2p.baofeng.net.
+lancastersys.com.
+tag.admeld.com.
+sls2ns215.y57p7f0m.
+www.youtube.com.
+www.gadgetrynews.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+hindi.babylon.com.
+static.ak.fbcdn.net.
+d2059613.instant.xoom.it.
+209.247.74.187.in-addr.arpa.
+bentvip.com.
+www.foxsportsla.com.
+www.google-analytics.com.
+www.cpxadspace.com.
+download337.avast.com.
+couponbuddy.s3.amazonaws.com.
+lexx.ru.
+musica.descarga-gratis.org.
+www.buono.aipop.cl.
+s-static.ak.fbcdn.net.
+67.109.220.201.in-addr.arpa.
+pixel.facebook.com.
+topfuelwebdesign.com.
+p698wia5n.a77p0x6r.
+isatap.pxe.acer.com.
+125.194.237.166.in-addr.arpa.
+www.msftncsi.com.
+viamail.ru.
+139.94.91.190.in-addr.arpa.
+a5.mzstatic.com.
+sp-avto.ru.
+apps.facebook.com.
+megusta.fraseshit.com.
+p02-bookmarks.icloud.com.
+.
+tierrasdemiscelanea.wordpress.com.
+81.103.43.186.in-addr.arpa.
+_114_99_7.
+callway.ru.
+www.18to19teenies.com.
+hdp.zapto.org.
+mscrl.microsoft.com.
+google.com.
+219.31.115.189.in-addr.arpa.
+benito-juarez.alumnosonline.com.
+www.kt2syggf436dtag162.com.
+www.myaddressus.com.
+optimodal.com.
+timberfinec.com.
+mx1.riseup.net.
+m2.nsimg.net.
+www.anime-sharing.com.
+plusone.google.com.
+5.251.254.188.in-addr.arpa.
+www.sitedefou.com.
+a.root-servers.net.
+exp01.eset.com.
+dr._dns-sd._udp.0.42.168.192.in-addr.arpa.
+www.ericas.com.
+api.facebook.com.
+secure.shared.live.com.
+fbcdn-sphotos-a.akamaihd.net.
+250.27.242.85.in-addr.arpa.
+digg.com.
+www.socialgrowthtechnologies.com.
+time.stdtime.gov.tw.
+cdn-4.nflximg.com.
+myspace.com.
+42.160.116.122.in-addr.arpa.
+155.78.34.187.in-addr.arpa.
+i.walmartimages.com.edgesuite.net.
+www.google-analytics.com.
+0-250.channel.facebook.com.
+profile.ak.fbcdn.net.
+229.153.252.109.in-addr.arpa.
+alerts.conduit-services.com.
+s0.2mdn.net.
+www.ecologiapolitica.info.
+buck.de.
+smtp.loyalistc.on.ca.
+www.tudiscovery.com.
+68.95.80.72.in-addr.arpa.
+www.optimus.se.
+36.14.12.204.in-addr.arpa.
+189.249.244.201.in-addr.arpa.
+custmx.cscdns.net.
+mx.youtube.com.
+apple.com.
+platform.ak.fbcdn.net.
+ads1.msads.net.
+descargargratis.com.
+oppty4u.com.
+27.165.42.62.in-addr.arpa.
+www.mypagerank.net.
+gaizhaohua.blog.sohu.com.
+www.google.com.
+pixel.facebook.com.
+www.joancollins.net.
+.
+www.cochesdeimportacion.com.
+instaar.metapress.com.
+www.cerberusftp.com.
+lw19w1:a5.o76u5f4s.
+162.128.129.186.in-addr.arpa.
+a6.sphotos.ak.fbcdn.net.
+skahunter.com.
+p2.trrsf.com.
+13.20.193.190.in-addr.arpa.
+newsnetinfo.com.
+merera.ru.
+musahim.maktoob.com.
+estilos.prodigy.msn.com.
+mail.google.com.
+42.82.224.190.in-addr.arpa.
+www.bestday.com.ar.
+mx.sherl.ru.
+feeds.bbci.co.uk.
+tital.com.
+www.thenewstribune.com.
+www.facebook.com.
+static-resource.np.community.playstation.net.
+r._dns-sd._udp.0.1.168.192.in-addr.arpa.
+75.78.132.190.in-addr.arpa.
+186.201.177.187.in-addr.arpa.
+allana.ru.
+expresscarpet.net.
+35.155.202.190.in-addr.arpa.
+col.stc.s-msn.com.
+s.ytimg.com.
+loadbalancing.modaco.com.
+photographypros.com.
+tagps.ru.
+rad.msn.com.
+megapolis-st.ru.
+www.wrightangle.com.
+plusone.google.com.
+istockanalyst.com.
+www.rubyrobot.org.
+20.1.168.192.in-addr.arpa.
+invite.youmint.net.
+aol.com.
+103.28.241.119.in-addr.arpa.
+3o4aldia.blogspot.com.
+heartbeat.belkin.com.
+dss1.siteadvisor.com.
+mail.sutd.ru.
+176.171.215.81.in-addr.arpa.
+248.36.251.146.in-addr.arpa.
+profile.ak.fbcdn.net.
+forums.zynga.com.
+112.216.84.186.in-addr.arpa.
+mail2.phyton.ru.
+www.hyruledynasty.com.
+mypage.rediff.com.
+ksn1-11-part1.kaspersky-labs.com.
+es-la.facebook.com.
+js.admeld.com.
+70.54.243.189.in-addr.arpa.
+www.facebook.com.
+www.aarinfantasy.com.
+www.1st-class-software.com.
+www.blovers4.tumblr.com.
+pixel.facebook.com.
+2.61.120.189.in-addr.arpa.
+rv.ginyas.com.
+fxfeeds.mozilla.com.
+e-2dj6aemiwidpmgp.stats.esomniture.com.
+a771.da1.akamai.net.
+ye3bcopsm.18ms.
+www.google.com.
+precisionprint.com.
+ssl.gstatic.com.
+www.lan.com.
+mcasteei.com.
+fasims.fasi.com.
+19.207.78.188.in-addr.arpa.
+geckofx.org.
+static.ak.fbcdn.net.
+fbcdn-profile-a.akamaihd.net.
+www.agoda.es.
+appsmetadata.toolbar.conduit-services.com.
+api.skype.com.
+www.chollywood.tv.
+station.netmarble.com.
+facebook.betterflashgames.com.
+teredo.ipv6.microsoft.com.
+googleblog.blogspot.com.
+clients1.google.com.
+231.51.21.187.in-addr.arpa.
+searchclient.live.net.
+img-cdn.mediaplex.com.
+static.ak.facebook.com.
+159.7.173.186.in-addr.arpa.
+api.twitter.com.
+zmsegamat.blogspot.com.
+mobilemaps.clients.google.com.
+modernismvintage.blogspot.com.
+204.45.13.200.in-addr.arpa.
+bpifunds.com.
+cbbc.org.
+static.pcomperf.com.
+i48.tinypic.com.
+a.root-servers.net.
+api.twitter.com.
+app102194446556627.socialappspot.com.
+photos1.pop6.com.
+115.139.68.189.in-addr.arpa.
+ns1.denisovv.ru.
+www.zonafutbolera.com.
+mx2.safe4mail.cz.
+mail.p106.ru.
+a.root-servers.net.
+s1-word-edit.vo.msecnd.net.
+entretenimiento.univision.com.
+ads.trafficjunky.net.
+34.39.94.189.in-addr.arpa.
+www.capplustech.com.
+www.prtool.info.
+www.easymix.co.nz.
+alerts.conduit-services.com.
+yahoo.com.
+m5fib7l68.88ma.
+podiumdist.com.
+30.media.tumblr.com.
+www.bywifi.com.
+beach.orangecounty.com.
+photos-f.ak.fbcdn.net.
+5.134.93.75.in-addr.arpa.
+fashion.sabayagazine.com.
+cs13076.vk.com.
+evbeacon.starfieldtech.com.
+a7.sphotos.ak.fbcdn.net.
+autobirga.ru.
+smetrics.mindjet.com.
+www.strato.it.
+www.coloradomusicbuzz.com.
+www.facebook.com.
+110.129.144.189.in-addr.arpa.
+lul.es.multi.surbl.org.
+platform.ak.fbcdn.net.
+uses.strawberrynet.com.
+trlf.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+feeds.qzone.qq.com.
+149.222.175.79.in-addr.arpa.
+fr-fr.facebook.com.
+watson.microsoft.com.
+www.buenaspracticas.com.
+a.root-servers.net.
+tools.google.com.
+studiotaro.ru.
+www.hotmail.com.
+tunnel.cfw.trustedsource.org.
+social.bidsystem.com.
+teredo.ipv6.microsoft.com.
+db._dns-sd._udp.0.1.168.192.in-addr.arpa.
+api.facebook.com.
+smogy.galya.ru.
+safebrowsing.clients.google.com.
+gorr.state.ny.us.
+ns3.apollo.lv.
+a.root-servers.net.
+hotmail.com.
+adv.yidaba.com.
+www.love-personals.co.uk.
+twitter.com.
+scqekuakauie.com.
+www.facebook.com.
+facebook-video-call-plug-in-installer.softonic.com.
+153.178.92.91.in-addr.arpa.
+db._dns-sd._udp.0.2.168.192.in-addr.arpa.
+81.236.15.209.in-addr.arpa.
+candpmachine.com.2.0001.arsmtp.com.
+www.google.com.
+www.discipulosdecristoemanuel.org.
+pixel.facebook.com.
+65.237.34.177.in-addr.arpa.
+mail.rngroup.ru.
+mail.dyerferris.com.
+www.votocatolico.com.
+75.128.122.123.in-addr.arpa.
+a.root-servers.net.
+unilever-foodsolutions.ru.
+fadevicelilaof.nu.
+196.192.9.65.in-addr.arpa.
+ocsp.verisign.com.
+www.revoltinstyle.com.
+a-0.19-230960c1.a030083.1518.19b2.410a.400.9d.atuj1gaj4zc4gimumscaulqzpv.avqs.mcafee.com.
+212.146.11.187.in-addr.arpa.
+response.jp.
+107.254.56.190.in-addr.arpa.
+external.ak.fbcdn.net.
+koran-jakarta.com.
+imagesperiodicook.s3.amazonaws.com.
+apps.facebook.com.
+dr._dns-sd._udp.0.1.168.192.in-addr.arpa.
+twitter.com.
+_ldap._tcp.
+nnsqi223b.81zq.
+zhetus.esir.ru.
+profile.ak.fbcdn.net.
+www.vardai.org.
+wpad.home.
+loading.retry.widdit.com.
+48.102.191.79.in-addr.arpa.
+static.ak.fbcdn.net.
+clock.nyc.he.net.
+157.252.168.216.in-addr.arpa.
+oborudunion.ru.
+laminaters.ru.
+a.root-servers.net.
+2.150.35.177.in-addr.arpa.
+photos-a.ak.fbcdn.net.
+a-0.19-23074089.30133.1518.19cf.3ea1.410.0.s8t4djrgtphuf24aed6r4tgiv6.avqs.mcafee.com.
+media.liquidx.net.
+v6:rixtv6.58je.
+profile.ak.fbcdn.net.
+59.158.241.201.in-addr.arpa.
+db._dns-sd._udp.lan.
+191.30.147.79.in-addr.arpa.
+164.155.49.178.in-addr.arpa.
+a.root-servers.net.
+js.wlxrs.com.
+external.ak.fbcdn.net.
+nsx.sec.np.dl.playstation.net.
+time.chttl.com.tw.
+209.163.160.190.in-addr.arpa.
+resi.com.au.
+www.fcyt.umss.edu.bo.
+r._dns-sd._udp.0.2.168.192.in-addr.arpa.
+i4.ytimg.com.
+saintpetersbasilica.org.
+cowboyuk.com.
+redir.metaservices.microsoft.com.
+sd-ansp02-m-dc1.pic.com.kw.
+imaverystylishgirl.blogspot.com.
+upay-cdn0.playspan.com.
+www.elprisma.com.
+maycot.com.au.
+ping3.dyngate.com.
+casas.aki.com.mx.
+_089_17_5.
+rihanna.wikia.com.
+statse.webtrendslive.com.
+paramountcoffee.com.s10a1.psmtp.com.
+sat.utm.ru.
+www.fourthwish.com.
+forums.surclaro.com.
+accumalax.com.
+platform.twitter.com.
+a.analytics.yahoo.com.
+125.250.1.181.in-addr.arpa.
+dns.msftncsi.com.
+fengshuiclassic.blogspot.com.
+yomismamayte.blogspot.com.
+plus.google.com.
+a.root-servers.net.
+aphrodite5239.livejournal.com.
+www.libertystickers.com.
+a40.phobos.apple.com.
+www.google.com.
+teredo.ipv6.microsoft.com.
+a.root-servers.net.
+186.83.249.201.in-addr.arpa.
+www.adobe.com.
+www.insurekidsnow.gov.
+mail.paramountmanufacturing.com.
+mail.nordicbioscience.com.
+179.2.137.190.in-addr.arpa.
+estrenoesp.blogspot.com.
+a.root-servers.net.
+fastracksoftware.co.uk.
+www.gstatic.com.
+215.1.168.192.in-addr.arpa.
+225.49.190.190.in-addr.arpa.
+161.61.32.83.in-addr.arpa.
+www.facebook.com.
+safebrowsing.clients.google.com.
+215.77.82.189.in-addr.arpa.
+hetnet.nl.
+176.15.251.146.in-addr.arpa.
+zona-anime.org.
+1.118.122.201.in-addr.arpa.
+www.futbolsantander.com.
+240.50.193.190.in-addr.arpa.
+oxfordinc.com.
+88.19.237.92.in-addr.arpa.
+laofficesupply.com.inbound15.mxlogicmx.net.
+local.msn.com.
+i4.ytimg.com.
+www.googleadservices.com.
+jaytees.com.
+cc.peralta.edu.
+saucontech.com.
+215.189.108.101.in-addr.arpa.
+s2.youtube.com.
+cdn.farmsrv.com.
+154.73.139.175.in-addr.arpa.
+mq3sgyg76.70hw.
+ja-jp.facebook.com.
+www.bluecoat.com.
+a7.sphotos.ak.fbcdn.net.
+37.250.24.75.in-addr.arpa.
+61.68.33.190.in-addr.arpa.
+echo.edge.messenger.live.com.
+www.vendorportal.ecms.va.gov.
+www.facebook.com.
+www.candiceaccolaweb.com.
+eagleaircraft.com.
+www.culosadictos.com.
+a.root-servers.net.
+inbound.gasworks.com.netsolmail.net.
+dns.msftncsi.com.
+rtmlwise.com.
+92.174.174.189.in-addr.arpa.
+246.165.72.190.in-addr.arpa.
+netdizain.ru.
+www.juegospm.com.
+static.ak.fbcdn.net.
+www.menoboys.fr.
+werewolf.solarcinc.com.
+baymsg1030111.gateway.messenger.live.com.
+193.31.108.76.in-addr.arpa.
+a.root-servers.net.
+safebrowsing-cache.google.com.
+static.ak.fbcdn.net.
+www.clr.net.
+a5.sphotos.ak.fbcdn.net.
+insurancefirstinc.com.s9a1.psmtp.com.
+tags.bluekai.com.
+www.promocionesweb.com.
+platform.ak.fbcdn.net.
+123.60.26.190.in-addr.arpa.
+a.root-servers.net.
+r._dns-sd._udp.0.0.168.192.in-addr.arpa.
+smtp.gallerycafe.ru.
+photos-b.ak.fbcdn.net.
+video.dainutekstai.lt.
+www.kayture.com.
+www.freevintagegames.com.
+135.229.97.174.in-addr.arpa.
+www.salazitarrosa.com.uy.
+www.facebook.com.
+data.flurry.com.
+s.youtube.com.
+photos-e.ak.fbcdn.net.
+i1.ytimg.com.
+mail.sktemp.ru.
+www9.effectivemeasure.net.
+194.243.4.181.in-addr.arpa.
+my.ebay.com.
+ez5zaky97.85hj.
+n2.panthercdn.com.
+api.facebook.com.
+35.3.61.186.in-addr.arpa.
+docs.google.com.
+a995.mm1.akamai.net.
+apis.google.com.
+us.perf.glbdns.microsoft.com.
+i1.ytimg.com.
+_800_02_2.
+us.headlines.vivanews.com.
+1.pool.ntp.org.
+184.93.89.186.in-addr.arpa.
+www.mcpvirtualbusinesscard.com.
+videoiline.ru.
+fbcdn-profile-a.akamaihd.net.
+bestworkathomechoices.com.
+cr7nimy7c.78bi.
+www.facebook.com.
+a.root-servers.net.
+7.165.69.161.in-addr.arpa.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+spam2.smarsh.com.
+ftp.relline.ru.
+io9.com.
+b.static-cdn.playfish.com.
+apps.facebook.com.
+1cfl.rr.com.
+yahoo.com.
+static.iminent.com.
+162.144.79.200.in-addr.arpa.
+i4.ytimg.com.
+lonestar.co.nz.
+reg.usps.com.
+www.cytotecblog.com.mx.
+rube.at.
+www.youtube.com.
+img5.pengfu.com.
+pantyhoseladies.net.
+rewards.ebay.com.
+zh-cn.facebook.com.
+oplin.org.
+tap-cdn.rubiconproject.com.
+s0.2mdn.net.
+t.co.
+static.ak.fbcdn.net.
+a8.sphotos.ak.fbcdn.net.
+80.54.5.187.in-addr.arpa.
+pokerface.com.
+photos-c.ak.fbcdn.net.
+mx1.hausnet.ru.
+www.5t.by.
+32.76.231.76.in-addr.arpa.
+141.67.133.115.in-addr.arpa.
+175.202.5.187.in-addr.arpa.
+www.soontobemums.com.
+www.erictradings.com.
+pl.wikipedia.org.
+samuelalonso.blogspot.com.
+www.uniteasy.com.
+www.pokerroom.com.
+static.ak.fbcdn.net.
+photos-g.ak.fbcdn.net.
+xcfoundations.com.lan.
+69.10.175.190.in-addr.arpa.
+macromedia-fireworks.en.softonic.com.
+13.219.153.201.in-addr.arpa.
+adpgr1-bond0-24.jagex.com.
+a1811.g.akamai.net.
+www.akbotong.com.
+mail.broadstarwindsystems.com.
+pagead2.googlesyndication.com.
+smtp.dcminc.com.
+www.google-analytics.com.
+news.cis.dfn.de.
+yanndex.ru.
+masterconn11.qq.com.
+www.isg-apple.com.akadns.net.
+distilleryimage10.instagram.com.
+www.facebook.com.
+cendes.com.
+avto.omsk.ru.
+itunes.apple.com.
+www.youtube.com.
+www.mums.org.
+www.googleadservices.com.
+photos-f.ak.fbcdn.net.
+mail.grinn-corp.ru.
+mailhost00.cfi.co.ug.
+developers.facebook.com.
+www.google.com.
+34344mailermailer.com.
+a3.sphotos.ak.fbcdn.net.
+154.74.53.83.in-addr.arpa.
+ns2.dnsstreet.ru.
+redirector.audiogalaxy.com.
+www.facebook.com.
+steri-flow.com.
+159.39.213.49.in-addr.arpa.
+akcontent.ebuddy.com.
+web.hurriyetdailynews.com.
+_293_74_0.
+btfans.3322.org.
+abto4.ru.
+241.180.72.200.in-addr.arpa.
+angelaseeangelablog.files.wordpress.com.
+www.technorati.com.
+proscada.ru.
+www.julienlecomte.net.
+youtube.com.
+minerkennedy.com.s9b1.psmtp.com.
+lb._dns-sd._udp.lan.
+130.20.132.190.in-addr.arpa.
+sp.cwfservice.net.
+qrgen.mobile.yahoo.co.jp.
+iprep3.elitec.ctmail.com.
+a.root-servers.net.
+225.144.168.88.zz.countries.nerd.dk.
+101.65.21.201.in-addr.arpa.
+support.google.com.
+99.17.238.189.in-addr.arpa.
+www.facebook.com.
+i.xanga.com.
+pt-br.facebook.com.
+messer-mg.com.
+static.ak.fbcdn.net.
+billing.sharo4ka.ru.
+17.132.217.190.in-addr.arpa.
+.
+aspirin-m.ru.
+cabovillasresort.com.
+www.datingbridgelp.info.
+helios.gamerdna.com.
+5cbbb1399.06zy.
+thumbs1.billclips.com.
+i4c.eu.
+190.195.42.190.in-addr.arpa.
+photos-e.ak.fbcdn.net.
+bmigaming.com.
+www.davidbelbin.com.
+ubumedia.wordpress.com.
+tragicodrama.blogspot.com.
+a.root-servers.net.
+explain-and-send-screenshots.softonic.com.
+teredo.ipv6.microsoft.com.
+www.argentinawarez.com.
+photos-h.ak.fbcdn.net.
+252.243.2.201.in-addr.arpa.
+dalfetco.khv.ru.
+www.comptoir.fr.
+statweb.dreamx.com.
+ssl.gstatic.com.
+sarobcoq8.62mt.
+descargas.juegos.com.
+developers.facebook.com.
+www.bayersanidadanimal.com.mx.
+www.minijuegos.com.
+www.google.com.
+mscrl.microsoft.com.
+a5.sphotos.ak.fbcdn.net.
+195.174.94.201.in-addr.arpa.
+norwegian.ruvr.ru.
+65.71.241.201.in-addr.arpa.
+plus.google.com.
+dns.msftncsi.com.
+202.204.157.186.in-addr.arpa.
+www.avideode.com.
+a1505.l.akamai.net.
+nlp.fi.muni.cz.
+26.75.220.85.in-addr.arpa.
+view.atdmt.com.
+17.22.159.189.in-addr.arpa.
+ads.bluelithium.com.
+ads.lfstmedia.com.
+mail.acadental.com.
+www.christianrock.net.
+7.135.166.189.in-addr.arpa.
+aol.com.
+docs.google.com.
+254.188.110.189.in-addr.arpa.
+239.14.222.189.in-addr.arpa.
+rcp.na.blackberry.com.
+7y2xr1wlp.83do.
+photos-g.ak.fbcdn.net.
+86.203.14.186.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+mco.com.
+20.202.75.190.in-addr.arpa.
+meteo.ieec.uned.es.
+aligrant.spb.ru.
+164.89.87.85.in-addr.arpa.
+arkansasonline.112.2o7.net.
+www.bestweb.net.
+galeriasgay.biengay.com.
+176.30.152.190.in-addr.arpa.
+feeds.delicious.com.
+www.bottledwaterweb.com.
+attanticbb.net.
+sn1msg3020410.gateway.messenger.live.com.
+101.1.168.192.in-addr.arpa.
+hotmail.com.
+s-static.ak.facebook.com.
+stratexllc.com.
+a.root-servers.net.
+cnfg.montiera.com.
+resources.infolinks.com.
+photos-g.ak.fbcdn.net.
+a3.sphotos.ak.fbcdn.net.
+mra.mail.ru.
+44.228.171.69.in-addr.arpa.
+pool.ntp.org.
+go-gelendgik.ru.
+quetzal.ru.
+s-external.ak.fbcdn.net.
+api.conduit.com.
+s.youtube.com.
+dentals.ru.
+media.fastclick.net.
+pagead2.googlesyndication.com.
+pixel.facebook.com.
+inbound.infoestrategica.com.netsolmail.net.
+time.windows.com.
+rats-images.rise.za.net.
+photos-g.ak.fbcdn.net.
+a.root-servers.net.
+ajax.googleapis.com.
+fbcdn-sphotos-a.akamaihd.net.
+www.inamay.com.
+tunnel.cfw.trustedsource.org.
+www.google.com.
+www.iecologia.com.
+ssl.gstatic.com.
+iamalreadyinuse.livejournal.com.
+www.insurancebreakdown.com.
+mx.udo.mx.
+www.shareaholic.com.
+media.officialplaystationmagazine.co.uk.
+au.download.windowsupdate.com.
+londeninc.com.
+at.atwola.com.
+pixel.facebook.com.
+b._dns-sd._udp.0.1.168.192.in-addr.arpa.
+meta.wikimedia.org.
+www.cah.utexas.edu.
+de-de.facebook.com.
+wo.appwill.com.
+moscow.com.ru.
+www.stylezone.bg.
+customers.imt.ru.
+vanmark.com.
+164.40.6.210.in-addr.arpa.
+r.mzstatic.com.
+www.blogger.com.
+www.mylovedmoms.com.
+mail.
+6to4.ipv6.microsoft.com.
+64.227.225.189.in-addr.arpa.
+a.root-servers.net.
+photos-c.ak.fbcdn.net.
+29.media.tumblr.com.
+securepics.ebaystatic.com.
+157.254.223.95.in-addr.arpa.
+a.root-servers.net.
+a5.sphotos.ak.fbcdn.net.
+c-0.19-210fd000.8020081.1518.19d4.3ea1.410.0.6lkbugnfdecm8p4jn9zbvz8p6j.avqs.mcafee.com.
+www.eyebuydirect.com.
+www.ad-serve.co.uk.
+reboot-it.com.
+149.53.191.190.in-addr.arpa.
+www.cumfiesta.com.
+juegosvestirmoda.blogspot.com.
+oi708.photobucket.com.
+www.epgonline.org.
+a425.w11.akamai.net.
+a8.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+a8.sphotos.ak.fbcdn.net.
+sm.mcafee.com.
+mx1.csusb.edu.
+a.root-servers.net.
+188.254.53.85.in-addr.arpa.
+spam.allardjohnson.com.
+c-0.19-a30f8081.60081.1518.19cf.3ea1.410.0.8t3jdvna6tmcvzmdssun2j9q2q.avqs.mcafee.com.
+health-worx.net.
+js.dailypainters.com.
+w-h.co.uk.
+172.70.101.78.in-addr.arpa.
+creative.ak.fbcdn.net.
+www.mysteryteam-movie.com.
+a.root-servers.net.
+blog.zippyshare.com.
+metcombank.msk.ru.
+cshell.com.
+mail.imagine-publishing.co.uk.
+kcpoets.com.
+www.ses-worldskies.com.
+umziqe.com.
+s.clicktale.net.
+a.root-servers.net.
+www.hotel-wellington.com.
+assets.tumblr.com.
+photos-h.ak.fbcdn.net.
+gelosea.deviantart.com.
+es-la.facebook.com.
+cotgs.com.
+mail.elasteks.com.
+s46.chatango.com.
+services.addons.mozilla.org.
+static.ak.facebook.com.
+dns.msftncsi.com.
+mail.ncstu.ru.
+www.delunaresynaranjas.com.
+193.144.87.85.in-addr.arpa.
+simpleforex.ru.
+elizabethsmarts.blogspot.com.
+0-jl-w.channel.facebook.com.
+www.facebook.com.
+img.youtube.com.
+www.colegioscolombia.com.
+dns.msftncsi.com.
+s0.img.awempire.com.
+74.76.140.201.in-addr.arpa.
+49.149.220.66.in-addr.arpa.
+a5.sphotos.ak.fbcdn.net.
+16.241.19.190.in-addr.arpa.
+apps.facebook.com.
+sp.cwfservice.net.
+s-static.ak.fbcdn.net.
+b._dns-sd._udp.lan.
+www.google.com.
+www.fandemia.com.
+android.clients.google.com.
+www.xxxspacegirls.us.
+ipyxxtb.cc.
+p02-caldav.icloud.com.
+i2.ytimg.com.
+95.156.32.173.in-addr.arpa.
+130.235.55.74.in-addr.arpa.
+a2.sphotos.ak.fbcdn.net.
+www.lelabofragrances.com.
+234.190.150.79.in-addr.arpa.
+appworld.blackberry.com.
+126.250.168.192.in-addr.arpa.
+68.196.22.177.in-addr.arpa.
+s.meebocdn.net.
+mail.valuehost.ru.
+www.clocklink.com.
+_791_96_0.
+lb._dns-sd._udp.0.55.211.10.in-addr.arpa.
+www.everardoherrera.com.
+pre.nextworth.com.
+txdps.state.tx.us.
+a5.sphotos.ak.fbcdn.net.
+jeanneillenye.blogspot.com.
+62s1jicq1.49vj.
+a6.sphotos.ak.fbcdn.net.
+foodconsumer.org.
+www.myownpublishing.com.
+dansleplacarddemaxime.blogspot.com.
+48.28.138.208.in-addr.arpa.
+149.145.71.70.in-addr.arpa.
+uniway.ru.
+armchairgeneral1.blogspot.com.
+www.secretease.com.
+mx1.rosbank.ru.
+profile.ak.fbcdn.net.
+redirector.c.youtube.com.
+ec.atdmt.com.
+93.172.243.201.in-addr.arpa.
+crl.microsoft.com.
+dtboot.orbitdownloader.com.
+download.surfcanyon.com.
+3ymei12ii.60xw.
+ice.friv4.info.
+rs499l33.rapidshare.com.
+www.adobe.com.
+213.180.183.189.in-addr.arpa.
+aprendercantandopersa.blogspot.com.
+support.google.com.
+241.100.136.190.in-addr.arpa.
+a3.sphotos.ak.fbcdn.net.
+a.root-servers.net.
+ngc.tgc6.ru.
+www.tumblr.com.
+a.root-servers.net.
+by146w.bay146.mail.live.com.
+mtalk.google.com.
+preujct.cl.
+oebe.com.
+dns-chj.sh.cncnet.net.
+libya.visahq.com.
+instagram.com.
+119.48.173.90.in-addr.arpa.
+www.creditrepairmagic.com.
diff --git a/ci/README.md b/ci/README.md
new file mode 100644
index 0000000..be6d75d
--- /dev/null
+++ b/ci/README.md
@@ -0,0 +1,21 @@
+Docker Build
+------------
+
+* debian-stable / debian-unstable
+
+```
+$ export KNOT_BRANCH=2.7
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/debian-stable:knot-$KNOT_BRANCH --build-arg KNOT_BRANCH=$KNOT_BRANCH debian-stable
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/debian-unstable:knot-$KNOT_BRANCH --build-arg KNOT_BRANCH=$KNOT_BRANCH debian-unstable
+
+$ docker login registry.labs.nic.cz
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/debian-stable:knot-$KNOT_BRANCH
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/debian-unstable:knot-$KNOT_BRANCH
+```
+
+* fedora
+
+```
+$ docker build -t registry.labs.nic.cz/knot/knot-resolver/ci/fedora fedora
+$ docker push registry.labs.nic.cz/knot/knot-resolver/ci/fedora
+```
diff --git a/ci/debian-stable/Dockerfile b/ci/debian-stable/Dockerfile
new file mode 100644
index 0000000..ab9b828
--- /dev/null
+++ b/ci/debian-stable/Dockerfile
@@ -0,0 +1,92 @@
+FROM debian:stable
+MAINTAINER Knot Resolver <knot-resolver@labs.nic.cz>
+ARG KNOT_BRANCH=master
+
+WORKDIR /root
+CMD ["/bin/bash"]
+
+RUN echo "deb http://ftp.debian.org/debian stretch-backports main" >> /etc/apt/sources.list
+
+# generic cleanup
+RUN apt-get update -qq
+RUN apt-get upgrade -y -qqq
+
+# Knot and Knot Resolver dependecies
+RUN apt-get -t stretch-backports install -y git
+RUN apt-get install -y -qqq make cmake pkg-config build-essential bsdmainutils libtool autoconf liburcu-dev libgnutls28-dev libedit-dev liblmdb-dev libcap-ng-dev libsystemd-dev libidn11-dev protobuf-c-compiler libfstrm-dev libuv1-dev libcmocka-dev libluajit-5.1-dev lua-sec lua-socket lua-http
+# documentation dependecies
+RUN apt-get install -y -qqq doxygen python3-sphinx python3-breathe python3-sphinx-rtd-theme
+
+# Python packags required for Deckard CI
+# Python: grab latest versions from PyPi
+# (dnspython and Augeas binding in Debian packages are slow and buggy)
+RUN apt-get install -y -qqq python3-pip wget augeas-tools
+RUN pip3 install --upgrade pip
+RUN pip3 install pylint
+RUN pip3 install pep8
+RUN pip3 install pytest-xdist
+# tests/pytest dependencies
+RUN pip3 install dnspython jinja2 pytest pytest-html pytest-xdist
+
+# C dependencies for python-augeas
+RUN apt-get install -y -qqq libaugeas-dev libffi-dev
+# Python dependencies for Deckard
+RUN wget https://gitlab.labs.nic.cz/knot/deckard/raw/master/requirements.txt -O /tmp/deckard-req.txt
+RUN pip3 install -r /tmp/deckard-req.txt
+
+# build and install latest version of Knot DNS
+# (kresd depends on libknot and libdnssec)
+RUN git clone --depth=1 --branch=$KNOT_BRANCH https://gitlab.labs.nic.cz/knot/knot-dns.git /tmp/knot
+WORKDIR /tmp/knot
+RUN pwd
+RUN autoreconf -if
+RUN ./configure --prefix=/usr
+RUN make
+RUN make install
+RUN ldconfig
+
+# Valgrind for kresd CI
+RUN apt-get install valgrind -y -qqq
+RUN wget https://raw.githubusercontent.com/LuaJIT/LuaJIT/v2.0.4/src/lj.supp -O /lj.supp
+# TODO: rebuild LuaJIT with Valgrind support
+
+# Lua lint for kresd CI
+RUN apt-get install luarocks -y -qqq
+RUN luarocks install luacheck
+
+# respdiff for kresd CI
+RUN apt-get install lmdb-utils -y -qqq
+RUN git clone --depth=1 https://gitlab.labs.nic.cz/knot/respdiff /var/opt/respdiff
+RUN pip3 install -r /var/opt/respdiff/requirements.txt
+
+# Python static analysis for respdiff
+RUN pip3 install mypy
+RUN pip3 install flake8
+
+# Python requests for CI scripts
+RUN pip3 install requests
+
+# Unbound for respdiff
+RUN apt-get install unbound unbound-anchor -y -qqq
+RUN printf "server:\n interface: 127.0.0.1@53535\n use-syslog: yes\n do-ip6: no\nremote-control:\n control-enable: no\n" >> /etc/unbound/unbound.conf
+
+# BIND for respdiff
+RUN apt-get install bind9 -y -qqq
+RUN printf '\nOPTIONS="-4 $OPTIONS"' >> /etc/default/bind9
+RUN printf 'options {\n directory "/var/cache/bind";\n listen-on port 53533 { 127.0.0.1; };\n listen-on-v6 port 53533 { ::1; };\n};\n' > /etc/bind/named.conf.options
+
+# PowerDNS Recursor for Deckard CI
+RUN apt-get install pdns-recursor -y -qqq
+
+# code coverage
+RUN apt-get install -y -qqq lcov
+RUN luarocks install luacov
+
+# LuaJIT binary for stand-alone scripting
+RUN apt-get install -y -qqq luajit
+
+# OpenBuildService CLI tool
+RUN apt-get install -y osc
+
+# curl (API)
+RUN apt-get install -y curl
diff --git a/ci/debian-unstable/Dockerfile b/ci/debian-unstable/Dockerfile
new file mode 100644
index 0000000..19315d9
--- /dev/null
+++ b/ci/debian-unstable/Dockerfile
@@ -0,0 +1,43 @@
+FROM debian:unstable
+MAINTAINER Knot Resolver <knot-resolver@labs.nic.cz>
+ARG KNOT_BRANCH=2.7
+
+WORKDIR /root
+CMD ["/bin/bash"]
+
+# generic cleanup
+RUN apt-get update -qq
+RUN apt-get upgrade -y -qqq
+
+# Knot and Knot Resolver dependecies
+RUN apt-get install -y -qqq make cmake pkg-config git build-essential bsdmainutils libtool autoconf liburcu-dev libgnutls28-dev libedit-dev liblmdb-dev libcap-ng-dev libsystemd-dev libidn11-dev protobuf-c-compiler libfstrm-dev libuv1-dev libcmocka-dev libluajit-5.1-dev lua-sec lua-socket lua-http
+
+# build and install latest version of Knot DNS
+# (kresd depends on libknot and libdnssec)
+RUN git clone --depth=1 --branch=$KNOT_BRANCH https://gitlab.labs.nic.cz/knot/knot-dns.git /tmp/knot
+WORKDIR /tmp/knot
+RUN pwd
+RUN autoreconf -if
+RUN ./configure --prefix=/usr
+RUN make
+RUN make install
+RUN ldconfig
+
+# Valgrind for kresd CI
+RUN apt-get install valgrind wget -y -qqq
+RUN wget https://raw.githubusercontent.com/LuaJIT/LuaJIT/v2.0.4/src/lj.supp -O /lj.supp
+# TODO: rebuild LuaJIT with Valgrind support
+
+# Lua lint for kresd CI
+RUN apt-get install luarocks -y -qqq
+RUN luarocks install luacheck
+
+# code coverage
+RUN apt-get install -y -qqq lcov
+RUN luarocks install luacov
+
+# LuaJIT binary for stand-alone scripting
+RUN apt-get install -y -qqq luajit
+
+# clang for kresd CI, version updated as debian updates it
+RUN apt-get install -y -qqq clang clang-tools clang-tidy
diff --git a/ci/debian-unstable/README b/ci/debian-unstable/README
new file mode 100644
index 0000000..4dbcd40
--- /dev/null
+++ b/ci/debian-unstable/README
@@ -0,0 +1 @@
+Docker image based on debian-unstable specifically for newer Clang.
diff --git a/ci/fedora/Dockerfile b/ci/fedora/Dockerfile
new file mode 100644
index 0000000..0997a1e
--- /dev/null
+++ b/ci/fedora/Dockerfile
@@ -0,0 +1,22 @@
+FROM fedora:29
+
+WORKDIR "/tmp"
+CMD ["/bin/bash"]
+
+RUN dnf install -y mock rpkg git
+
+# for scripts/make-distrofiles.sh
+RUN dnf install -y dpkg-dev perl-Digest-*
+
+# add OBS repo with Knot DNS to mock
+RUN curl -Lo obs-epel7.repo 'https://download.opensuse.org/repositories/home:CZ-NIC:knot-resolver-testing/CentOS_7_EPEL/home:CZ-NIC:knot-resolver-testing.repo'
+RUN sed -i -e "/^config_opts\[.yum.conf.]/r obs-epel7.repo" /etc/mock/epel-7-x86_64.cfg
+RUN curl -Lo obs-fedora.repo 'https://download.opensuse.org/repositories/home:CZ-NIC:knot-resolver-testing/Fedora_29/home:CZ-NIC:knot-resolver-testing.repo'
+RUN sed -i -e "/^config_opts\[.yum.conf.]/r obs-fedora.repo" /etc/mock/fedora-29-x86_64.cfg
+
+# cache packages in mock to speed up CI tests
+# This would require privileged build: https://github.com/moby/moby/issues/1916
+# RUN dnf download --source knot-resolver
+# RUN mock --no-clean --dnf --old-chroot -r epel-7-x86_64 --rebuild knot-resolver-*.src.rpm
+# RUN mock --no-clean --old-chroot -r fedora-29-x86_64 --rebuild knot-resolver-*.src.rpm
+# RUN rm *.src.rpm
diff --git a/ci/pytests/lint.sh b/ci/pytests/lint.sh
new file mode 100755
index 0000000..b6c0bfc
--- /dev/null
+++ b/ci/pytests/lint.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+python3 -m flake8 --max-line-length=100 tests/pytests
+FLAKE8=$?
+
+ci/pytests/pylint-run.sh
+PYLINT=$?
+
+if [ $PYLINT -ne 0 ]; then
+ exit 1
+fi
+if [ $FLAKE8 -ne 0 ]; then
+ exit 1
+fi
+
+exit 0
diff --git a/ci/pytests/pylint-run.sh b/ci/pytests/pylint-run.sh
new file mode 100755
index 0000000..159a830
--- /dev/null
+++ b/ci/pytests/pylint-run.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+
+# Find Python modules and standalone Python scripts
+FILES=$(find ./tests/pytests \
+ -type d -exec test -e '{}/__init__.py' \; -print -prune -o \
+ -name '*.py' -print)
+
+python3 -m pylint -j 0 --rcfile ./tests/pytests/pylintrc ${FILES}
diff --git a/ci/pytests/run-extended.sh b/ci/pytests/run-extended.sh
new file mode 100755
index 0000000..694fba5
--- /dev/null
+++ b/ci/pytests/run-extended.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# Execute extended, long-running test suite
+
+python3 -m pytest -ra --capture=no tests/pytests/conn_flood.py
diff --git a/ci/pytests/run.sh b/ci/pytests/run.sh
new file mode 100755
index 0000000..e1b55af
--- /dev/null
+++ b/ci/pytests/run.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+python3 -m pytest --html pytests.html --self-contained-html -dn 24 tests/pytests
diff --git a/ci/respdiff/kresd.config b/ci/respdiff/kresd.config
new file mode 100644
index 0000000..c733601
--- /dev/null
+++ b/ci/respdiff/kresd.config
@@ -0,0 +1,24 @@
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+-- Listen on localhost and external interface
+net.listen('127.0.0.1', 5353)
+net.listen('127.0.0.1', 8853, { tls = true })
+net.ipv6=false
+
+-- Auto-maintain root TA
+trust_anchors.file = '.local/etc/knot-resolver/root.keys'
+
+-- Large cache size, so we don't need to flush often
+-- This can be larger than available RAM, least frequently accessed
+-- records will be paged out
+cache.size = 1024 * MB
+
+-- Load Useful modules
+modules = {
+ 'workarounds < iterate',
+ 'policy', -- Block queries to local zones/bad sites
+ 'view', -- Views for certain clients
+ 'hints', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+}
+
+verbose(true)
diff --git a/ci/respdiff/respdiff-tcp.conf b/ci/respdiff/respdiff-tcp.conf
new file mode 100644
index 0000000..3d42c31
--- /dev/null
+++ b/ci/respdiff/respdiff-tcp.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 5353
+transport = tcp
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/respdiff-tls.conf b/ci/respdiff/respdiff-tls.conf
new file mode 100644
index 0000000..9f44cea
--- /dev/null
+++ b/ci/respdiff/respdiff-tls.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 8853
+transport = tls
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/respdiff-udp.conf b/ci/respdiff/respdiff-udp.conf
new file mode 100644
index 0000000..4db7da0
--- /dev/null
+++ b/ci/respdiff/respdiff-udp.conf
@@ -0,0 +1,50 @@
+[sendrecv]
+# in seconds
+timeout = 11
+# number of queries to run simultaneously
+jobs = 64
+# in seconds (float); delay each query by a random time (uniformly distributed) between min and max; set max to 0 to disable
+time_delay_min = 0
+time_delay_max = 0
+
+[servers]
+names = kresd, bind, unbound
+# symbolic names of DNS servers under test
+# separate multiple values by ,
+
+# each symbolic name in [servers] section refers to config section
+# containing IP address and port of particular server
+[kresd]
+ip = 127.0.0.1
+port = 5353
+transport = udp
+graph_color = #00a2e2
+restart_script = ./ci/respdiff/restart-kresd.sh
+
+[bind]
+ip = 127.0.0.1
+port = 53533
+transport = udp
+graph_color = #e2a000
+restart_script = ./ci/respdiff/restart-bind.sh
+
+[unbound]
+ip = 127.0.0.1
+port = 53535
+transport = udp
+graph_color = #218669
+restart_script = ./ci/respdiff/restart-unbound.sh
+
+[diff]
+# symbolic name of server under test
+# other servers are used as reference when comparing answers from the target
+target = kresd
+
+# fields and comparison methods used when comparing two DNS messages
+criteria = opcode, rcode, flags, question, answertypes, answerrrsigs
+# other supported criteria values: authority, additional, edns, nsid
+
+[report]
+# diffsum reports mismatches in field values in this order
+# if particular message has multiple mismatches, it is counted only once into category with highest weight
+field_weights = timeout, malformed, opcode, question, rcode, flags, answertypes, answerrrsigs, answer, authority, additional, edns, nsid
diff --git a/ci/respdiff/restart-bind.sh b/ci/respdiff/restart-bind.sh
new file mode 100755
index 0000000..89fd832
--- /dev/null
+++ b/ci/respdiff/restart-bind.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+service bind9 restart
diff --git a/ci/respdiff/restart-kresd.sh b/ci/respdiff/restart-kresd.sh
new file mode 100755
index 0000000..dfe82cf
--- /dev/null
+++ b/ci/respdiff/restart-kresd.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+exec > /dev/null
+exec 2>&1
+
+PREFIX=$(pwd)/.local
+killall -w kresd
+rm -f '*.mdb'
+LD_LIBRARY_PATH=$PREFIX/lib $PREFIX/sbin/kresd -f 1 -q -c $(pwd)/ci/respdiff/kresd.config &>>kresd.log &
+
+# wait until socket is receiving connections
+sleep 1
diff --git a/ci/respdiff/restart-unbound.sh b/ci/respdiff/restart-unbound.sh
new file mode 100755
index 0000000..c9525c0
--- /dev/null
+++ b/ci/respdiff/restart-unbound.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+service unbound restart
diff --git a/ci/respdiff/run-respdiff-tests.sh b/ci/respdiff/run-respdiff-tests.sh
new file mode 100755
index 0000000..c55243f
--- /dev/null
+++ b/ci/respdiff/run-respdiff-tests.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# $1 == udp/tcp/tls, it selects configuration file to use
+# respdiff scripts must be present in /var/opt/respdiff
+set -o errexit -o nounset -o xtrace
+
+NDIFFREPRO=3
+
+wget -qO- https://gitlab.labs.nic.cz/knot/respdiff/snippets/238/raw?inline=false | head -n 5000 > /tmp/queries.txt
+mkdir results
+rm -rf respdiff.db
+
+CONFIG="$(pwd)/ci/respdiff/respdiff-${1}.conf"
+/var/opt/respdiff/qprep.py respdiff.db < /tmp/queries.txt
+time /var/opt/respdiff/orchestrator.py respdiff.db -c "${CONFIG}"
+time /var/opt/respdiff/msgdiff.py respdiff.db -c "${CONFIG}"
+for i in $(seq $NDIFFREPRO); do
+ time /var/opt/respdiff/diffrepro.py -c "${CONFIG}" respdiff.db
+done
+/var/opt/respdiff/diffsum.py respdiff.db -c "${CONFIG}" > results/respdiff.txt
+/var/opt/respdiff/histogram.py respdiff.db -c "${CONFIG}" -o results/histogram.svg
+: minimize LMDB and log size so they can be effectively archived
+mkdir results/respdiff.db
+mdb_copy -c respdiff.db results/respdiff.db
+xz -9 results/respdiff.db/data.mdb
+xz kresd.log
diff --git a/ci/respdiff/start-resolvers.sh b/ci/respdiff/start-resolvers.sh
new file mode 100755
index 0000000..1a63de4
--- /dev/null
+++ b/ci/respdiff/start-resolvers.sh
@@ -0,0 +1,11 @@
+#run unbound
+service unbound start && service unbound status;
+# dig @localhost -p 53535
+
+#run bind
+service bind9 start && service bind9 status;
+# dig @localhost -p 53533
+
+#run kresd
+LD_LIBRARY_PATH=$PREFIX/lib $PREFIX/sbin/kresd -f 1 -q -c $(pwd)/ci/respdiff/kresd.config &>kresd.log &
+# dig @localhost -p 5353
diff --git a/ci/travis.py b/ci/travis.py
new file mode 100755
index 0000000..f0909ae
--- /dev/null
+++ b/ci/travis.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+import json
+import time
+import sys
+
+import requests
+
+
+BRANCH_API_ENDPOINT = "https://api.travis-ci.com/repos/CZ-NIC/knot-resolver/branches/{branch}"
+JOB_URL = "https://travis-ci.com/CZ-NIC/knot-resolver/jobs/{job_id}"
+TIMEOUT = 600 # 10 mins max
+POLL_DELAY = 15
+
+job_id = None
+
+
+def exit(msg='', code=1):
+ print(msg, file=sys.stderr)
+ if job_id is not None:
+ print(JOB_URL.format(job_id=job_id))
+ sys.exit(code)
+
+
+end_time = time.time() + TIMEOUT
+while time.time() < end_time:
+ response = requests.get(
+ BRANCH_API_ENDPOINT.format(branch=sys.argv[1]),
+ headers={"Accept": "application/vnd.travis-ci.2.1+json"})
+ if response.status_code == 404:
+ pass # not created yet?
+ elif response.status_code == 200:
+ data = json.loads(response.content.decode('utf-8'))
+ state = data['branch']['state']
+ try:
+ job_id = data['branch']['job_ids'][0]
+ except KeyError:
+ pass
+
+ if state == "errored":
+ exit("Travis CI Result: ERRORED!")
+ elif state == "passed":
+ exit("Travis CI Result: PASSED!", code=0)
+ else:
+ exit("API Response Code: {code}".format(response.status_code), code=2)
+ time.sleep(POLL_DELAY)
+
+exit("Timed out!")
diff --git a/client/client.mk b/client/client.mk
new file mode 100644
index 0000000..f303945
--- /dev/null
+++ b/client/client.mk
@@ -0,0 +1,14 @@
+# Experimental client requires libedit
+
+ifeq ($(HAS_libedit), yes)
+kresc_SOURCES := client/kresc.c
+kresc_CFLAGS += -fPIE $(libedit_CFLAGS)
+kresc_LIBS += $(contrib_TARGET) $(libedit_LIBS)
+kresc_DEPEND := $(libkres) $(contrib)
+$(eval $(call make_sbin,kresc,client,yes))
+client: $(kresc)
+client-install: kresc-install
+client-clean: kresc-clean
+
+endif
+.PHONY: client client-install client-clean
diff --git a/client/kresc.c b/client/kresc.c
new file mode 100644
index 0000000..42dba34
--- /dev/null
+++ b/client/kresc.c
@@ -0,0 +1,471 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#include <arpa/inet.h>
+#include <assert.h>
+#include <contrib/ccan/asprintf/asprintf.h>
+#include <editline/readline.h>
+#include <errno.h>
+#include <histedit.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#define HISTORY_FILE "kresc_history"
+#define PROGRAM_NAME "kresc"
+
+FILE *g_tty = NULL; //!< connection to the daemon
+
+static char *run_cmd(const char *cmd, size_t * out_len);
+
+const char *prompt(EditLine * e)
+{
+ return PROGRAM_NAME "> ";
+}
+
+bool starts_with(const char *a, const char *b)
+{
+ if (strncmp(a, b, strlen(b)) == 0)
+ return 1;
+ return 0;
+}
+
+//! Returns Lua name of type of value, NULL on error. Puts length of type in name_len;
+const char *get_type_name(const char *value)
+{
+ if (value == NULL) {
+ return NULL;
+ }
+
+ for (int i = 0; value[i]; i++) {
+ if (value[i] == ')') {
+ //Return NULL to prevent unexpected function call
+ return NULL;
+ }
+ }
+
+ char *cmd = afmt("type(%s)", value);
+
+ if (!cmd) {
+ perror("While tab-completing.");
+ return NULL;
+ }
+
+ size_t name_len;
+ char *type = run_cmd(cmd, &name_len);
+ if (!type) {
+ return NULL;
+ } else {
+ free(cmd);
+ }
+
+ if (starts_with(type, "[")) {
+ //Return "nil" on non-valid name.
+ free(type);
+ return "nil";
+ } else {
+ type[(strlen(type)) - 1] = '\0';
+ return type;
+ }
+}
+
+static void complete_function(EditLine * el)
+{
+ //Add left parenthesis to function name.
+ el_insertstr(el, "(");
+}
+
+static void complete_members(EditLine * el, const char *str,
+ const char *str_type, int str_len, char *dot)
+{
+ char *table = strdup(str);
+ if (!table) {
+ perror("While tab-completing");
+ return;
+ }
+ //Get only the table name (without partial member name).
+ if (dot) {
+ *(table + (dot - str)) = '\0';
+ }
+ //Insert a dot after the table name.
+ if (!strncmp(str_type, "table", 5)) {
+ el_insertstr(el, ".");
+ str_len++;
+ }
+ //Check if the substring before dot is a valid table name.
+ const char *t_type = get_type_name(table);
+ if (t_type && !strncmp("table", t_type, 5)) {
+ //Get string of members of the table.
+ char *cmd =
+ afmt
+ ("do local s=\"\"; for i in pairs(%s) do s=s..i..\"\\n\" end return(s) end",
+ table);
+ if (!cmd) {
+ perror("While tab-completing.");
+ goto complete_members_exit;
+ }
+ size_t members_len;
+ char *members = run_cmd(cmd, &members_len);
+ free(cmd);
+ if (!members) {
+ perror("While communication with daemon");
+ goto complete_members_exit;
+ }
+ //Split members by newline.
+ char *members_tok = strdup(members);
+ free(members);
+ if (!members_tok) {
+ goto complete_members_exit;
+ }
+ char *token = strtok(members_tok, "\n");
+ int matches = 0;
+ char *lastmatch = NULL;
+ if (!dot || dot - str + 1 == strlen(str)) {
+ //Prints all members.
+ while (token) {
+ char *member = afmt("%s.%s", table, token);
+ const char *member_type = get_type_name(member);
+ if (member && member_type) {
+ printf("\n%s (%s)", member, member_type);
+ free(member);
+ free((void *)member_type);
+ } else if (member) {
+ printf("\n%s", member);
+ free(member);
+ }
+ token = strtok(NULL, "\n");
+ matches++;
+ }
+ } else {
+ //Print members matching the current line.
+ while (token) {
+ if (str && starts_with(token, dot + 1)) {
+ const char *member_type =
+ get_type_name(afmt
+ ("%s.%s", table,
+ token));
+ if (member_type) {
+ printf("\n%s.%s (%s)", table,
+ token, member_type);
+ free((void *)member_type);
+ } else {
+ printf("\n%s.%s", table, token);
+ }
+ lastmatch = token;
+ matches++;
+ }
+ token = strtok(NULL, "\n");
+ }
+
+ //Complete matching member.
+ if (matches == 1) {
+ el_deletestr(el, str_len);
+ el_insertstr(el, table);
+ el_insertstr(el, ".");
+ el_insertstr(el, lastmatch);
+ }
+ }
+ if (matches > 1) {
+ printf("\n");
+ }
+ free(members_tok);
+ }
+
+complete_members_exit:
+ free(table);
+ if(t_type) {
+ free((void*)t_type);
+ }
+}
+
+static void complete_globals(EditLine * el, const char *str, int str_len)
+{
+ //Parse Lua globals.
+ size_t globals_len;
+ char *globals = run_cmd("_G.__orig_name_list", &globals_len);
+ if (!globals) {
+ perror("While tab-completing");
+ return;
+ }
+ //Show possible globals.
+ char *globals_tok = strdup(globals);
+ free(globals);
+ if (!globals_tok) {
+ return;
+ }
+ char *token = strtok(globals_tok, "\n");
+ int matches = 0;
+ char *lastmatch = NULL;
+ while (token) {
+ if (str && starts_with(token, str)) {
+ printf("\n%s (%s)", token, get_type_name(token));
+ lastmatch = token;
+ matches++;
+ }
+ token = strtok(NULL, "\n");
+ }
+ if (matches > 1) {
+ printf("\n");
+ }
+ //Complete matching global.
+ if (matches == 1) {
+ el_deletestr(el, str_len);
+ el_insertstr(el, lastmatch);
+ }
+ free(globals_tok);
+}
+
+static unsigned char complete(EditLine * el, int ch)
+{
+ int argc, pos;
+ const char **argv;
+ const LineInfo *li = el_line(el);
+ Tokenizer *tok = tok_init(NULL);
+
+ //Tokenize current line.
+ int ret = tok_line(tok, li, &argc, &argv, NULL, &pos);
+
+ if (ret != 0) {
+ perror("While tab-completing.");
+ goto complete_exit;
+ }
+ //Show help.
+ if (argc == 0) {
+ size_t help_len;
+ char *help = run_cmd("help()", &help_len);
+ if (help) {
+ printf("\n%s", help);
+ free(help);
+ } else {
+ perror("While communication with daemon");
+ }
+ goto complete_exit;
+ }
+
+ if (argc > 1) {
+ goto complete_exit;
+ }
+ //Get name of type of current line.
+ const char *type = get_type_name(argv[0]);
+
+ if (!type) {
+ goto complete_exit;
+ }
+ //Get position of last dot in current line (useful for parsing table).
+ char *dot = strrchr(argv[0], '.');
+
+ if (strncmp(type, "table", 5) != 0 && !dot) {
+ //Line is not a name of some table and there is no dot in it.
+ complete_globals(el, argv[0], pos);
+ } else if ((dot && strncmp(type, "nil", 3) == 0)
+ || strncmp(type, "table", 5) == 0) {
+ //Current line (or part of it) is a name of some table.
+ complete_members(el, argv[0], type, pos, dot);
+ } else if (strncmp(type, "function", 8) == 0) {
+ //Current line is a function.
+ complete_function(el);
+ }
+ if (type) {
+ free((void *)type);
+ }
+
+complete_exit:
+ tok_reset(tok);
+ tok_end(tok);
+ return CC_REDISPLAY;
+}
+
+//! Initialize connection to the daemon; return 0 on success.
+static int init_tty(const char *path)
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ return 1;
+
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ size_t plen = strlen(path);
+ if (plen + 1 > sizeof(addr.sun_path)) {
+ fprintf(stderr, "Path too long\n");
+ close(fd);
+ return 1;
+ }
+ memcpy(addr.sun_path, path, plen + 1);
+ if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr))) {
+ perror("While connecting to daemon");
+ close(fd);
+ return 1;
+ }
+ g_tty = fdopen(fd, "r+");
+ if (!g_tty) {
+ perror("While opening TTY");
+ close(fd);
+ return 1;
+ }
+
+ // Switch to binary mode and consume the text "> ".
+ if (fprintf(g_tty, "__binary\n") < 0 || !fread(&addr, 2, 1, g_tty)
+ || fflush(g_tty)) {
+ perror("While initializing TTY");
+ fclose(g_tty);
+ g_tty = NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+//! Run a command on the daemon; return the answer or NULL on failure, puts answer length to out_len.
+static char *run_cmd(const char *cmd, size_t * out_len)
+{
+ if (!g_tty || !cmd) {
+ assert(false);
+ return NULL;
+ }
+ if (fprintf(g_tty, "%s", cmd) < 0 || fflush(g_tty))
+ return NULL;
+ uint32_t len;
+ if (!fread(&len, sizeof(len), 1, g_tty))
+ return NULL;
+ len = ntohl(len);
+ char *msg = malloc(1 + (size_t) len);
+ if (!msg)
+ return NULL;
+ if (len && !fread(msg, len, 1, g_tty)) {
+ free(msg);
+ return NULL;
+ }
+ msg[len] = '\0';
+ *out_len = len;
+ return msg;
+}
+
+static int interact()
+{
+ EditLine *el;
+ History *hist;
+ int count;
+ const char *line;
+ HistEvent ev;
+ el = el_init(PROGRAM_NAME, stdin, stdout, stderr);
+ el_set(el, EL_PROMPT, prompt);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_ADDFN, PROGRAM_NAME "-complete",
+ "Perform " PROGRAM_NAME " completion.", complete);
+ el_set(el, EL_BIND, "^I", PROGRAM_NAME "-complete", NULL);
+
+ hist = history_init();
+ if (hist == 0) {
+ perror("While initializing command history");
+ return 1;
+ }
+ history(hist, &ev, H_SETSIZE, 800);
+ el_set(el, EL_HIST, history, hist);
+
+ char *hist_file = NULL;
+
+ char *data_home = getenv("XDG_DATA_HOME");
+
+ //Check whether $XDG_DATA_HOME is set.
+ if (!data_home || *data_home == '\0') {
+ const char *home = getenv("HOME"); //This should be set on any POSIX compliant OS, even for nobody
+
+ //Create necessary folders.
+ char *dirs[3] =
+ { afmt("%s/.local", home), afmt("%s/.local/share", home),
+ afmt("%s/.local/share/knot-resolver/", home)
+ };
+ bool ok = true;
+ for (int i = 0; i < 3; i++) {
+ if (mkdir(dirs[i], 0755) && errno != EEXIST) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ hist_file =
+ afmt("%s/.local/share/knot-resolver/" HISTORY_FILE, home);
+ }
+ } else {
+ if (!mkdir(afmt("%s/knot-resolver/", data_home), 0755)
+ || errno == EEXIST) {
+ hist_file = afmt("%s/knot-resolver/" HISTORY_FILE, data_home);
+ }
+ }
+
+ //Load history file
+ if (hist_file) {
+ history(hist, &ev, H_LOAD, hist_file);
+ } else {
+ perror("While opening history file");
+ }
+
+ while (1) {
+ line = el_gets(el, &count);
+ if (count > 0) {
+ history(hist, &ev, H_ENTER, line);
+ size_t msg_len;
+ char *msg = run_cmd(line, &msg_len);
+ if (!msg) {
+ perror("While communication with daemon");
+ history_end(hist);
+ el_end(el);
+ free(msg);
+ return 1;
+ }
+ printf("%s", msg);
+ if (msg_len == 0 || msg[msg_len - 1] != '\n') {
+ printf("\n");
+ }
+ if (hist_file) {
+ history(hist, &ev, H_SAVE, hist_file);
+ }
+ free(msg);
+ }
+ }
+ history_end(hist);
+ free(hist_file);
+ el_end(el);
+ if (feof(stdin))
+ return 0;
+ perror("While reading input");
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ fprintf(stderr, "Warning! %s is highly experimental, use at own risk.\n", argv[0]);
+ fprintf(stderr, "Please tell authors what features you expect from client utility.\n");
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s tty/xxxxx\n", argv[0]);
+ return 1;
+ }
+
+ int res = init_tty(argv[1]);
+
+ if (!res)
+ res = interact();
+
+ if (g_tty)
+ fclose(g_tty);
+ return res;
+}
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..7a652c9
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,45 @@
+# Project
+MAJOR := 3
+MINOR := 2
+PATCH := 1
+EXTRA ?=
+ABIVER := 9
+BUILDMODE := dynamic
+HARDENING := yes
+
+VERSION := $(MAJOR).$(MINOR).$(PATCH)$(EXTRA)
+
+# Paths
+PREFIX ?= /usr/local
+BINDIR ?= $(PREFIX)/bin
+SBINDIR ?= $(PREFIX)/sbin
+LIBDIR ?= $(PREFIX)/lib
+PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
+MANDIR ?= $(PREFIX)/share/man
+INCLUDEDIR ?= $(PREFIX)/include
+MODULEDIR ?= $(LIBDIR)/kdns_modules
+ETCDIR ?= $(PREFIX)/etc/knot-resolver
+ROOTHINTS ?= $(ETCDIR)/root.hints
+COVERAGE_STAGE ?= gcov
+COVERAGE_STATSDIR ?= $(CURDIR)/coverage.stats
+TOPSRCDIR := $(CURDIR)
+KEYFILE_DEFAULT ?=
+
+# Tools
+CC ?= cc
+RM := rm -f
+LN := ln -s
+XXD_LUA := ./scripts/embed-lua.sh
+INSTALL := install
+
+# Flags
+BUILD_LDFLAGS += $(LDFLAGS)
+BUILD_CFLAGS := -std=c99 -D_GNU_SOURCE $(CFLAGS) $(CPPFLAGS)
+BUILD_CFLAGS += -Wtype-limits -Wformat -Wformat-security -Wshadow -Wall
+BUILD_CFLAGS += -I$(abspath .) -I$(abspath lib/generic) -I$(abspath contrib)
+BUILD_CFLAGS += -DPACKAGE_VERSION="\"$(VERSION)\"" -DPREFIX="\"$(PREFIX)\"" -DMODULEDIR="\"$(MODULEDIR)\""
+BUILD_CFLAGS += -fvisibility=hidden
+
+ifeq (,$(findstring -O,$(CFLAGS)))
+ BUILD_CFLAGS += -O2
+endif
diff --git a/contrib/base32hex.c b/contrib/base32hex.c
new file mode 100644
index 0000000..1684ac9
--- /dev/null
+++ b/contrib/base32hex.c
@@ -0,0 +1,289 @@
+/* Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "contrib/base32hex.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/*! \brief Maximal length of binary input to Base32hex encoding. */
+#define MAX_BIN_DATA_LEN ((INT32_MAX / 8) * 5)
+
+/*! \brief Base32hex padding character. */
+static const uint8_t base32hex_pad = '=';
+/*! \brief Base32hex alphabet. Beware: original code was upper-case. */
+static const uint8_t base32hex_enc[] = "0123456789abcdefghijklmnopqrstuv";
+
+/*! \brief Indicates bad Base32hex character. */
+#define KO 255
+/*! \brief Indicates Base32hex padding character. */
+#define PD 32
+
+/*! \brief Transformation and validation table for decoding Base32hex. */
+static const uint8_t base32hex_dec[256] = {
+ [ 0] = KO, [ 43] = KO, ['V'] = 31, [129] = KO, [172] = KO, [215] = KO,
+ [ 1] = KO, [ 44] = KO, ['W'] = KO, [130] = KO, [173] = KO, [216] = KO,
+ [ 2] = KO, [ 45] = KO, ['X'] = KO, [131] = KO, [174] = KO, [217] = KO,
+ [ 3] = KO, [ 46] = KO, ['Y'] = KO, [132] = KO, [175] = KO, [218] = KO,
+ [ 4] = KO, [ 47] = KO, ['Z'] = KO, [133] = KO, [176] = KO, [219] = KO,
+ [ 5] = KO, ['0'] = 0, [ 91] = KO, [134] = KO, [177] = KO, [220] = KO,
+ [ 6] = KO, ['1'] = 1, [ 92] = KO, [135] = KO, [178] = KO, [221] = KO,
+ [ 7] = KO, ['2'] = 2, [ 93] = KO, [136] = KO, [179] = KO, [222] = KO,
+ [ 8] = KO, ['3'] = 3, [ 94] = KO, [137] = KO, [180] = KO, [223] = KO,
+ [ 9] = KO, ['4'] = 4, [ 95] = KO, [138] = KO, [181] = KO, [224] = KO,
+ [ 10] = KO, ['5'] = 5, [ 96] = KO, [139] = KO, [182] = KO, [225] = KO,
+ [ 11] = KO, ['6'] = 6, ['a'] = 10, [140] = KO, [183] = KO, [226] = KO,
+ [ 12] = KO, ['7'] = 7, ['b'] = 11, [141] = KO, [184] = KO, [227] = KO,
+ [ 13] = KO, ['8'] = 8, ['c'] = 12, [142] = KO, [185] = KO, [228] = KO,
+ [ 14] = KO, ['9'] = 9, ['d'] = 13, [143] = KO, [186] = KO, [229] = KO,
+ [ 15] = KO, [ 58] = KO, ['e'] = 14, [144] = KO, [187] = KO, [230] = KO,
+ [ 16] = KO, [ 59] = KO, ['f'] = 15, [145] = KO, [188] = KO, [231] = KO,
+ [ 17] = KO, [ 60] = KO, ['g'] = 16, [146] = KO, [189] = KO, [232] = KO,
+ [ 18] = KO, ['='] = PD, ['h'] = 17, [147] = KO, [190] = KO, [233] = KO,
+ [ 19] = KO, [ 62] = KO, ['i'] = 18, [148] = KO, [191] = KO, [234] = KO,
+ [ 20] = KO, [ 63] = KO, ['j'] = 19, [149] = KO, [192] = KO, [235] = KO,
+ [ 21] = KO, [ 64] = KO, ['k'] = 20, [150] = KO, [193] = KO, [236] = KO,
+ [ 22] = KO, ['A'] = 10, ['l'] = 21, [151] = KO, [194] = KO, [237] = KO,
+ [ 23] = KO, ['B'] = 11, ['m'] = 22, [152] = KO, [195] = KO, [238] = KO,
+ [ 24] = KO, ['C'] = 12, ['n'] = 23, [153] = KO, [196] = KO, [239] = KO,
+ [ 25] = KO, ['D'] = 13, ['o'] = 24, [154] = KO, [197] = KO, [240] = KO,
+ [ 26] = KO, ['E'] = 14, ['p'] = 25, [155] = KO, [198] = KO, [241] = KO,
+ [ 27] = KO, ['F'] = 15, ['q'] = 26, [156] = KO, [199] = KO, [242] = KO,
+ [ 28] = KO, ['G'] = 16, ['r'] = 27, [157] = KO, [200] = KO, [243] = KO,
+ [ 29] = KO, ['H'] = 17, ['s'] = 28, [158] = KO, [201] = KO, [244] = KO,
+ [ 30] = KO, ['I'] = 18, ['t'] = 29, [159] = KO, [202] = KO, [245] = KO,
+ [ 31] = KO, ['J'] = 19, ['u'] = 30, [160] = KO, [203] = KO, [246] = KO,
+ [ 32] = KO, ['K'] = 20, ['v'] = 31, [161] = KO, [204] = KO, [247] = KO,
+ [ 33] = KO, ['L'] = 21, ['w'] = KO, [162] = KO, [205] = KO, [248] = KO,
+ [ 34] = KO, ['M'] = 22, ['x'] = KO, [163] = KO, [206] = KO, [249] = KO,
+ [ 35] = KO, ['N'] = 23, ['y'] = KO, [164] = KO, [207] = KO, [250] = KO,
+ [ 36] = KO, ['O'] = 24, ['z'] = KO, [165] = KO, [208] = KO, [251] = KO,
+ [ 37] = KO, ['P'] = 25, [123] = KO, [166] = KO, [209] = KO, [252] = KO,
+ [ 38] = KO, ['Q'] = 26, [124] = KO, [167] = KO, [210] = KO, [253] = KO,
+ [ 39] = KO, ['R'] = 27, [125] = KO, [168] = KO, [211] = KO, [254] = KO,
+ [ 40] = KO, ['S'] = 28, [126] = KO, [169] = KO, [212] = KO, [255] = KO,
+ [ 41] = KO, ['T'] = 29, [127] = KO, [170] = KO, [213] = KO,
+ [ 42] = KO, ['U'] = 30, [128] = KO, [171] = KO, [214] = KO,
+};
+
+int32_t base32hex_decode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
+{
+ // Checking inputs.
+ if (in == NULL || out == NULL) {
+ return -1;
+ }
+ if (in_len > INT32_MAX || out_len < ((in_len + 7) / 8) * 5) {
+ return -1;
+ }
+ if ((in_len % 8) != 0) {
+ return -1;
+ }
+
+ const uint8_t *stop = in + in_len;
+ uint8_t *bin = out;
+ uint8_t pad_len = 0;
+ uint8_t c1, c2, c3, c4, c5, c6, c7, c8;
+
+ // Decoding loop takes 8 characters and creates 5 bytes.
+ while (in < stop) {
+ // Filling and transforming 8 Base32hex chars.
+ c1 = base32hex_dec[in[0]];
+ c2 = base32hex_dec[in[1]];
+ c3 = base32hex_dec[in[2]];
+ c4 = base32hex_dec[in[3]];
+ c5 = base32hex_dec[in[4]];
+ c6 = base32hex_dec[in[5]];
+ c7 = base32hex_dec[in[6]];
+ c8 = base32hex_dec[in[7]];
+
+ // Check 8. char if is bad or padding.
+ if (c8 >= PD) {
+ if (c8 == PD && pad_len == 0) {
+ pad_len = 1;
+ } else {
+ return -1;
+ }
+ }
+
+ // Check 7. char if is bad or padding (if so, 6. must be too).
+ if (c7 >= PD) {
+ if (c7 == PD && c6 == PD && pad_len == 1) {
+ pad_len = 3;
+ } else {
+ return -1;
+ }
+ }
+
+ // Check 6. char if is bad or padding.
+ if (c6 >= PD) {
+ if (!(c6 == PD && pad_len == 3)) {
+ return -1;
+ }
+ }
+
+ // Check 5. char if is bad or padding.
+ if (c5 >= PD) {
+ if (c5 == PD && pad_len == 3) {
+ pad_len = 4;
+ } else {
+ return -1;
+ }
+ }
+
+ // Check 4. char if is bad or padding (if so, 3. must be too).
+ if (c4 >= PD) {
+ if (c4 == PD && c3 == PD && pad_len == 4) {
+ pad_len = 6;
+ } else {
+ return -1;
+ }
+ }
+
+ // Check 3. char if is bad or padding.
+ if (c3 >= PD) {
+ if (!(c3 == PD && pad_len == 6)) {
+ return -1;
+ }
+ }
+
+ // 1. and 2. chars must not be padding.
+ if (c2 >= PD || c1 >= PD) {
+ return -1;
+ }
+
+ // Computing of output data based on padding length.
+ switch (pad_len) {
+ case 0:
+ bin[4] = (c7 << 5) + c8;
+ case 1:
+ bin[3] = (c5 << 7) + (c6 << 2) + (c7 >> 3);
+ case 3:
+ bin[2] = (c4 << 4) + (c5 >> 1);
+ case 4:
+ bin[1] = (c2 << 6) + (c3 << 1) + (c4 >> 4);
+ case 6:
+ bin[0] = (c1 << 3) + (c2 >> 2);
+ }
+
+ // Update output end.
+ switch (pad_len) {
+ case 0:
+ bin += 5;
+ break;
+ case 1:
+ bin += 4;
+ break;
+ case 3:
+ bin += 3;
+ break;
+ case 4:
+ bin += 2;
+ break;
+ case 6:
+ bin += 1;
+ break;
+ }
+
+ in += 8;
+ }
+
+ return (bin - out);
+}
+
+int32_t base32hex_encode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
+{
+ // Checking inputs.
+ if (in == NULL || out == NULL) {
+ return -1;
+ }
+ if (in_len > MAX_BIN_DATA_LEN || out_len < ((in_len + 4) / 5) * 8) {
+ return -1;
+ }
+
+ uint8_t rest_len = in_len % 5;
+ const uint8_t *stop = in + in_len - rest_len;
+ uint8_t *text = out;
+
+ // Encoding loop takes 5 bytes and creates 8 characters.
+ while (in < stop) {
+ text[0] = base32hex_enc[in[0] >> 3];
+ text[1] = base32hex_enc[(in[0] & 0x07) << 2 | in[1] >> 6];
+ text[2] = base32hex_enc[(in[1] & 0x3E) >> 1];
+ text[3] = base32hex_enc[(in[1] & 0x01) << 4 | in[2] >> 4];
+ text[4] = base32hex_enc[(in[2] & 0x0F) << 1 | in[3] >> 7];
+ text[5] = base32hex_enc[(in[3] & 0x7C) >> 2];
+ text[6] = base32hex_enc[(in[3] & 0x03) << 3 | in[4] >> 5];
+ text[7] = base32hex_enc[in[4] & 0x1F];
+ text += 8;
+ in += 5;
+ }
+
+ // Processing of padding, if any.
+ switch (rest_len) {
+ case 4:
+ text[0] = base32hex_enc[in[0] >> 3];
+ text[1] = base32hex_enc[(in[0] & 0x07) << 2 | in[1] >> 6];
+ text[2] = base32hex_enc[(in[1] & 0x3E) >> 1];
+ text[3] = base32hex_enc[(in[1] & 0x01) << 4 | in[2] >> 4];
+ text[4] = base32hex_enc[(in[2] & 0x0F) << 1 | in[3] >> 7];
+ text[5] = base32hex_enc[(in[3] & 0x7C) >> 2];
+ text[6] = base32hex_enc[(in[3] & 0x03) << 3];
+ text[7] = base32hex_pad;
+ text += 8;
+ break;
+ case 3:
+ text[0] = base32hex_enc[in[0] >> 3];
+ text[1] = base32hex_enc[(in[0] & 0x07) << 2 | in[1] >> 6];
+ text[2] = base32hex_enc[(in[1] & 0x3E) >> 1];
+ text[3] = base32hex_enc[(in[1] & 0x01) << 4 | in[2] >> 4];
+ text[4] = base32hex_enc[(in[2] & 0x0F) << 1];
+ text[5] = base32hex_pad;
+ text[6] = base32hex_pad;
+ text[7] = base32hex_pad;
+ text += 8;
+ break;
+ case 2:
+ text[0] = base32hex_enc[in[0] >> 3];
+ text[1] = base32hex_enc[(in[0] & 0x07) << 2 | in[1] >> 6];
+ text[2] = base32hex_enc[(in[1] & 0x3E) >> 1];
+ text[3] = base32hex_enc[(in[1] & 0x01) << 4];
+ text[4] = base32hex_pad;
+ text[5] = base32hex_pad;
+ text[6] = base32hex_pad;
+ text[7] = base32hex_pad;
+ text += 8;
+ break;
+ case 1:
+ text[0] = base32hex_enc[in[0] >> 3];
+ text[1] = base32hex_enc[(in[0] & 0x07) << 2];
+ text[2] = base32hex_pad;
+ text[3] = base32hex_pad;
+ text[4] = base32hex_pad;
+ text[5] = base32hex_pad;
+ text[6] = base32hex_pad;
+ text[7] = base32hex_pad;
+ text += 8;
+ break;
+ }
+
+ return (text - out);
+}
diff --git a/contrib/base32hex.h b/contrib/base32hex.h
new file mode 100644
index 0000000..561d9ff
--- /dev/null
+++ b/contrib/base32hex.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file
+ *
+ * \brief Base32hex implementation (RFC 4648).
+ *
+ * \note Input Base32hex string can contain a-v characters. These characters
+ * are considered as A-V equivalent.
+ *
+ * \addtogroup contrib
+ * @{
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/*!
+ * \brief Decodes text data using Base32hex.
+ *
+ * \note Input data needn't be terminated with '\0'.
+ *
+ * \note Input data must be continuous Base32hex string!
+ *
+ * \param in Input text data.
+ * \param in_len Length of input string.
+ * \param out Output data buffer.
+ * \param out_len Size of output buffer.
+ *
+ * \retval >=0 length of output data.
+ * \retval KNOT_E* if error.
+ */
+int32_t base32hex_decode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
+
+
+/*!
+ * \brief Encodes binary data using Base32hex. Lower case is used!
+ *
+ * \note Output data buffer contains Base32hex text string which isn't
+ * terminated with '\0'!
+ *
+ * \param in Input binary data.
+ * \param in_len Length of input data.
+ * \param out Output data buffer.
+ * \param out_len Size of output buffer.
+ *
+ * \retval >=0 length of output string.
+ * \retval <0 if error.
+ */
+int32_t base32hex_encode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
+
+/*! @} */
diff --git a/contrib/base64.c b/contrib/base64.c
new file mode 100644
index 0000000..e577901
--- /dev/null
+++ b/contrib/base64.c
@@ -0,0 +1,268 @@
+/* Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "contrib/base64.h"
+#include "libknot/errcode.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/*! \brief Maximal length of binary input to Base64 encoding. */
+#define MAX_BIN_DATA_LEN ((INT32_MAX / 4) * 3)
+
+/*! \brief Base64 padding character. */
+static const uint8_t base64_pad = '=';
+/*! \brief Base64 alphabet. */
+static const uint8_t base64_enc[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*! \brief Indicates bad Base64 character. */
+#define KO 255
+/*! \brief Indicates Base64 padding character. */
+#define PD 64
+
+/*! \brief Transformation and validation table for decoding Base64. */
+static const uint8_t base64_dec[256] = {
+ [ 0] = KO, ['+'] = 62, ['V'] = 21, [129] = KO, [172] = KO, [215] = KO,
+ [ 1] = KO, [ 44] = KO, ['W'] = 22, [130] = KO, [173] = KO, [216] = KO,
+ [ 2] = KO, [ 45] = KO, ['X'] = 23, [131] = KO, [174] = KO, [217] = KO,
+ [ 3] = KO, [ 46] = KO, ['Y'] = 24, [132] = KO, [175] = KO, [218] = KO,
+ [ 4] = KO, ['/'] = 63, ['Z'] = 25, [133] = KO, [176] = KO, [219] = KO,
+ [ 5] = KO, ['0'] = 52, [ 91] = KO, [134] = KO, [177] = KO, [220] = KO,
+ [ 6] = KO, ['1'] = 53, [ 92] = KO, [135] = KO, [178] = KO, [221] = KO,
+ [ 7] = KO, ['2'] = 54, [ 93] = KO, [136] = KO, [179] = KO, [222] = KO,
+ [ 8] = KO, ['3'] = 55, [ 94] = KO, [137] = KO, [180] = KO, [223] = KO,
+ [ 9] = KO, ['4'] = 56, [ 95] = KO, [138] = KO, [181] = KO, [224] = KO,
+ [ 10] = KO, ['5'] = 57, [ 96] = KO, [139] = KO, [182] = KO, [225] = KO,
+ [ 11] = KO, ['6'] = 58, ['a'] = 26, [140] = KO, [183] = KO, [226] = KO,
+ [ 12] = KO, ['7'] = 59, ['b'] = 27, [141] = KO, [184] = KO, [227] = KO,
+ [ 13] = KO, ['8'] = 60, ['c'] = 28, [142] = KO, [185] = KO, [228] = KO,
+ [ 14] = KO, ['9'] = 61, ['d'] = 29, [143] = KO, [186] = KO, [229] = KO,
+ [ 15] = KO, [ 58] = KO, ['e'] = 30, [144] = KO, [187] = KO, [230] = KO,
+ [ 16] = KO, [ 59] = KO, ['f'] = 31, [145] = KO, [188] = KO, [231] = KO,
+ [ 17] = KO, [ 60] = KO, ['g'] = 32, [146] = KO, [189] = KO, [232] = KO,
+ [ 18] = KO, ['='] = PD, ['h'] = 33, [147] = KO, [190] = KO, [233] = KO,
+ [ 19] = KO, [ 62] = KO, ['i'] = 34, [148] = KO, [191] = KO, [234] = KO,
+ [ 20] = KO, [ 63] = KO, ['j'] = 35, [149] = KO, [192] = KO, [235] = KO,
+ [ 21] = KO, [ 64] = KO, ['k'] = 36, [150] = KO, [193] = KO, [236] = KO,
+ [ 22] = KO, ['A'] = 0, ['l'] = 37, [151] = KO, [194] = KO, [237] = KO,
+ [ 23] = KO, ['B'] = 1, ['m'] = 38, [152] = KO, [195] = KO, [238] = KO,
+ [ 24] = KO, ['C'] = 2, ['n'] = 39, [153] = KO, [196] = KO, [239] = KO,
+ [ 25] = KO, ['D'] = 3, ['o'] = 40, [154] = KO, [197] = KO, [240] = KO,
+ [ 26] = KO, ['E'] = 4, ['p'] = 41, [155] = KO, [198] = KO, [241] = KO,
+ [ 27] = KO, ['F'] = 5, ['q'] = 42, [156] = KO, [199] = KO, [242] = KO,
+ [ 28] = KO, ['G'] = 6, ['r'] = 43, [157] = KO, [200] = KO, [243] = KO,
+ [ 29] = KO, ['H'] = 7, ['s'] = 44, [158] = KO, [201] = KO, [244] = KO,
+ [ 30] = KO, ['I'] = 8, ['t'] = 45, [159] = KO, [202] = KO, [245] = KO,
+ [ 31] = KO, ['J'] = 9, ['u'] = 46, [160] = KO, [203] = KO, [246] = KO,
+ [ 32] = KO, ['K'] = 10, ['v'] = 47, [161] = KO, [204] = KO, [247] = KO,
+ [ 33] = KO, ['L'] = 11, ['w'] = 48, [162] = KO, [205] = KO, [248] = KO,
+ [ 34] = KO, ['M'] = 12, ['x'] = 49, [163] = KO, [206] = KO, [249] = KO,
+ [ 35] = KO, ['N'] = 13, ['y'] = 50, [164] = KO, [207] = KO, [250] = KO,
+ [ 36] = KO, ['O'] = 14, ['z'] = 51, [165] = KO, [208] = KO, [251] = KO,
+ [ 37] = KO, ['P'] = 15, [123] = KO, [166] = KO, [209] = KO, [252] = KO,
+ [ 38] = KO, ['Q'] = 16, [124] = KO, [167] = KO, [210] = KO, [253] = KO,
+ [ 39] = KO, ['R'] = 17, [125] = KO, [168] = KO, [211] = KO, [254] = KO,
+ [ 40] = KO, ['S'] = 18, [126] = KO, [169] = KO, [212] = KO, [255] = KO,
+ [ 41] = KO, ['T'] = 19, [127] = KO, [170] = KO, [213] = KO,
+ [ 42] = KO, ['U'] = 20, [128] = KO, [171] = KO, [214] = KO,
+};
+
+int32_t base64_encode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
+{
+ // Checking inputs.
+ if (in == NULL || out == NULL) {
+ return KNOT_EINVAL;
+ }
+ if (in_len > MAX_BIN_DATA_LEN || out_len < ((in_len + 2) / 3) * 4) {
+ return KNOT_ERANGE;
+ }
+
+ uint8_t rest_len = in_len % 3;
+ const uint8_t *stop = in + in_len - rest_len;
+ uint8_t *text = out;
+
+ // Encoding loop takes 3 bytes and creates 4 characters.
+ while (in < stop) {
+ text[0] = base64_enc[in[0] >> 2];
+ text[1] = base64_enc[(in[0] & 0x03) << 4 | in[1] >> 4];
+ text[2] = base64_enc[(in[1] & 0x0F) << 2 | in[2] >> 6];
+ text[3] = base64_enc[in[2] & 0x3F];
+ text += 4;
+ in += 3;
+ }
+
+ // Processing of padding, if any.
+ switch (rest_len) {
+ case 2:
+ text[0] = base64_enc[in[0] >> 2];
+ text[1] = base64_enc[(in[0] & 0x03) << 4 | in[1] >> 4];
+ text[2] = base64_enc[(in[1] & 0x0F) << 2];
+ text[3] = base64_pad;
+ text += 4;
+ break;
+ case 1:
+ text[0] = base64_enc[in[0] >> 2];
+ text[1] = base64_enc[(in[0] & 0x03) << 4];
+ text[2] = base64_pad;
+ text[3] = base64_pad;
+ text += 4;
+ break;
+ }
+
+ return (text - out);
+}
+
+int32_t base64_encode_alloc(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t **out)
+{
+ // Checking inputs.
+ if (out == NULL) {
+ return KNOT_EINVAL;
+ }
+ if (in_len > MAX_BIN_DATA_LEN) {
+ return KNOT_ERANGE;
+ }
+
+ // Compute output buffer length.
+ uint32_t out_len = ((in_len + 2) / 3) * 4;
+
+ // Allocate output buffer.
+ *out = malloc(out_len);
+ if (*out == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ // Encode data.
+ int32_t ret = base64_encode(in, in_len, *out, out_len);
+ if (ret < 0) {
+ free(*out);
+ }
+
+ return ret;
+}
+
+int32_t base64_decode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
+{
+ // Checking inputs.
+ if (in == NULL || out == NULL) {
+ return KNOT_EINVAL;
+ }
+ if (in_len > INT32_MAX || out_len < ((in_len + 3) / 4) * 3) {
+ return KNOT_ERANGE;
+ }
+ if ((in_len % 4) != 0) {
+ return KNOT_BASE64_ESIZE;
+ }
+
+ const uint8_t *stop = in + in_len;
+ uint8_t *bin = out;
+ uint8_t pad_len = 0;
+ uint8_t c1, c2, c3, c4;
+
+ // Decoding loop takes 4 characters and creates 3 bytes.
+ while (in < stop) {
+ // Filling and transforming 4 Base64 chars.
+ c1 = base64_dec[in[0]];
+ c2 = base64_dec[in[1]];
+ c3 = base64_dec[in[2]];
+ c4 = base64_dec[in[3]];
+
+ // Check 4. char if is bad or padding.
+ if (c4 >= PD) {
+ if (c4 == PD && pad_len == 0) {
+ pad_len = 1;
+ } else {
+ return KNOT_BASE64_ECHAR;
+ }
+ }
+
+ // Check 3. char if is bad or padding.
+ if (c3 >= PD) {
+ if (c3 == PD && pad_len == 1) {
+ pad_len = 2;
+ } else {
+ return KNOT_BASE64_ECHAR;
+ }
+ }
+
+ // Check 1. and 2. chars if are not padding.
+ if (c2 >= PD || c1 >= PD) {
+ return KNOT_BASE64_ECHAR;
+ }
+
+ // Computing of output data based on padding length.
+ switch (pad_len) {
+ case 0:
+ bin[2] = (c3 << 6) + c4;
+ case 1:
+ bin[1] = (c2 << 4) + (c3 >> 2);
+ case 2:
+ bin[0] = (c1 << 2) + (c2 >> 4);
+ }
+
+ // Update output end.
+ switch (pad_len) {
+ case 0:
+ bin += 3;
+ break;
+ case 1:
+ bin += 2;
+ break;
+ case 2:
+ bin += 1;
+ break;
+ }
+
+ in += 4;
+ }
+
+ return (bin - out);
+}
+
+int32_t base64_decode_alloc(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t **out)
+{
+ // Checking inputs.
+ if (out == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ // Compute output buffer length.
+ uint32_t out_len = ((in_len + 3) / 4) * 3;
+
+ // Allocate output buffer.
+ *out = malloc(out_len);
+ if (*out == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ // Decode data.
+ int32_t ret = base64_decode(in, in_len, *out, out_len);
+ if (ret < 0) {
+ free(*out);
+ }
+
+ return ret;
+}
diff --git a/contrib/base64.h b/contrib/base64.h
new file mode 100644
index 0000000..0684274
--- /dev/null
+++ b/contrib/base64.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file
+ *
+ * \brief Base64 implementation (RFC 4648).
+ *
+ * \addtogroup contrib
+ * @{
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/*!
+ * \brief Encodes binary data using Base64.
+ *
+ * \note Output data buffer contains Base64 text string which isn't
+ * terminated with '\0'!
+ *
+ * \param in Input binary data.
+ * \param in_len Length of input data.
+ * \param out Output data buffer.
+ * \param out_len Size of output buffer.
+ *
+ * \retval >=0 length of output string.
+ * \retval KNOT_E* if error.
+ */
+int32_t base64_encode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
+
+/*!
+ * \brief Encodes binary data using Base64 and output stores to own buffer.
+ *
+ * \note Output data buffer contains Base64 text string which isn't
+ * terminated with '\0'!
+ *
+ * \note Output buffer should be deallocated after use.
+ *
+ * \param in Input binary data.
+ * \param in_len Length of input data.
+ * \param out Output data buffer.
+ *
+ * \retval >=0 length of output string.
+ * \retval KNOT_E* if error.
+ */
+int32_t base64_encode_alloc(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t **out);
+
+/*!
+ * \brief Decodes text data using Base64.
+ *
+ * \note Input data needn't be terminated with '\0'.
+ *
+ * \note Input data must be continuous Base64 string!
+ *
+ * \param in Input text data.
+ * \param in_len Length of input string.
+ * \param out Output data buffer.
+ * \param out_len Size of output buffer.
+ *
+ * \retval >=0 length of output data.
+ * \retval KNOT_E* if error.
+ */
+int32_t base64_decode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
+
+/*!
+ * \brief Decodes text data using Base64 and output stores to own buffer.
+ *
+ * \note Input data needn't be terminated with '\0'.
+ *
+ * \note Input data must be continuous Base64 string!
+ *
+ * \note Output buffer should be deallocated after use.
+ *
+ * \param in Input text data.
+ * \param in_len Length of input string.
+ * \param out Output data buffer.
+ *
+ * \retval >=0 length of output data.
+ * \retval KNOT_E* if error.
+ */
+int32_t base64_decode_alloc(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t **out);
+
+/*! @} */
diff --git a/contrib/ccan/asprintf/LICENSE b/contrib/ccan/asprintf/LICENSE
new file mode 100644
index 0000000..89de354
--- /dev/null
+++ b/contrib/ccan/asprintf/LICENSE
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/contrib/ccan/asprintf/_info b/contrib/ccan/asprintf/_info
new file mode 100644
index 0000000..f72d668
--- /dev/null
+++ b/contrib/ccan/asprintf/_info
@@ -0,0 +1,45 @@
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * asprintf - asprintf wrapper (and if necessary, implementation).
+ *
+ * This provides a convenient wrapper for asprintf, and also implements
+ * asprintf if necessary.
+ *
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * License: MIT
+ *
+ * Example:
+ * #include <ccan/asprintf/asprintf.h>
+ * #include <unistd.h>
+ * #include <err.h>
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * char *p = afmt("This program has %i arguments", argc);
+ * int ret;
+ *
+ * while ((ret = write(STDOUT_FILENO, p, strlen(p))) > 0) {
+ * p += ret;
+ * if (!*p)
+ * exit(0);
+ * }
+ * err(1, "Writing to stdout");
+ * }
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/compiler\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/contrib/ccan/asprintf/asprintf.c b/contrib/ccan/asprintf/asprintf.c
new file mode 100644
index 0000000..9e66e13
--- /dev/null
+++ b/contrib/ccan/asprintf/asprintf.c
@@ -0,0 +1,56 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#include <ccan/asprintf/asprintf.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+char *PRINTF_FMT(1, 2) afmt(const char *fmt, ...)
+{
+ va_list ap;
+ char *ptr;
+
+ va_start(ap, fmt);
+ /* The BSD version apparently sets ptr to NULL on fail. GNU loses. */
+ if (vasprintf(&ptr, fmt, ap) < 0)
+ ptr = NULL;
+ va_end(ap);
+ return ptr;
+}
+
+#if !HAVE_ASPRINTF && !defined(__USE_FORTIFY_LEVEL)
+#include <stdarg.h>
+#include <stdlib.h>
+
+int vasprintf(char **strp, const char *fmt, va_list ap)
+{
+ int len;
+ va_list ap_copy;
+
+ /* We need to make a copy of ap, since it's a use-once. */
+ va_copy(ap_copy, ap);
+ len = vsnprintf(NULL, 0, fmt, ap_copy);
+ va_end(ap_copy);
+
+ /* Until version 2.0.6 glibc would return -1 on truncated output.
+ * OTOH, they had asprintf. */
+ if (len < 0)
+ return -1;
+
+ *strp = malloc(len+1);
+ if (!*strp)
+ return -1;
+
+ return vsprintf(*strp, fmt, ap);
+}
+
+int asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = vasprintf(strp, fmt, ap);
+ va_end(ap);
+
+ return len;
+}
+#endif /* !HAVE_ASPRINTF */
diff --git a/contrib/ccan/asprintf/asprintf.h b/contrib/ccan/asprintf/asprintf.h
new file mode 100644
index 0000000..37da83e
--- /dev/null
+++ b/contrib/ccan/asprintf/asprintf.h
@@ -0,0 +1,50 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#ifndef CCAN_ASPRINTF_H
+#define CCAN_ASPRINTF_H
+#include "config.h"
+#include <ccan/compiler/compiler.h>
+
+/**
+ * afmt - allocate and populate a string with the given format.
+ * @fmt: printf-style format.
+ *
+ * This is a simplified asprintf interface. Returns NULL on error.
+ */
+char *PRINTF_FMT(1, 2) afmt(const char *fmt, ...);
+
+#if HAVE_ASPRINTF || defined(__USE_FORTIFY_LEVEL)
+#include <stdio.h>
+#else
+#include <stdarg.h>
+/**
+ * asprintf - printf to a dynamically-allocated string.
+ * @strp: pointer to the string to allocate.
+ * @fmt: printf-style format.
+ *
+ * Returns -1 (and leaves @strp undefined) on an error. Otherwise returns
+ * number of bytes printed into @strp.
+ *
+ * Example:
+ * static char *greeting(const char *name)
+ * {
+ * char *str;
+ * int len = asprintf(&str, "Hello %s", name);
+ * if (len < 0)
+ * return NULL;
+ * return str;
+ * }
+ */
+int PRINTF_FMT(2, 3) asprintf(char **strp, const char *fmt, ...);
+
+/**
+ * vasprintf - vprintf to a dynamically-allocated string.
+ * @strp: pointer to the string to allocate.
+ * @fmt: printf-style format.
+ *
+ * Returns -1 (and leaves @strp undefined) on an error. Otherwise returns
+ * number of bytes printed into @strp.
+ */
+int vasprintf(char **strp, const char *fmt, va_list ap);
+#endif
+
+#endif /* CCAN_ASPRINTF_H */
diff --git a/contrib/ccan/compiler/LICENSE b/contrib/ccan/compiler/LICENSE
new file mode 100644
index 0000000..feb9b11
--- /dev/null
+++ b/contrib/ccan/compiler/LICENSE
@@ -0,0 +1,28 @@
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
+
+ the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
+ moral rights retained by the original author(s) and/or performer(s);
+ publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
+ rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
+ rights protecting the extraction, dissemination, use and reuse of data in a Work;
+ database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
+ other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
+ Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
+ Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
+ Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
diff --git a/contrib/ccan/compiler/_info b/contrib/ccan/compiler/_info
new file mode 100644
index 0000000..d60dff4
--- /dev/null
+++ b/contrib/ccan/compiler/_info
@@ -0,0 +1,64 @@
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+
+/**
+ * compiler - macros for common compiler extensions
+ *
+ * Abstracts away some compiler hints. Currently these include:
+ * - COLD
+ * For functions not called in fast paths (aka. cold functions)
+ * - PRINTF_FMT
+ * For functions which take printf-style parameters.
+ * - CONST_FUNCTION
+ * For functions which return the same value for same parameters.
+ * - NEEDED
+ * For functions and variables which must be emitted even if unused.
+ * - UNNEEDED
+ * For functions and variables which need not be emitted if unused.
+ * - UNUSED
+ * For parameters which are not used.
+ * - IS_COMPILE_CONSTANT()
+ * For using different tradeoffs for compiletime vs runtime evaluation.
+ *
+ * License: CC0 (Public domain)
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ *
+ * Example:
+ * #include <ccan/compiler/compiler.h>
+ * #include <stdio.h>
+ * #include <stdarg.h>
+ *
+ * // Example of a (slow-path) logging function.
+ * static int log_threshold = 2;
+ * static void COLD PRINTF_FMT(2,3)
+ * logger(int level, const char *fmt, ...)
+ * {
+ * va_list ap;
+ * va_start(ap, fmt);
+ * if (level >= log_threshold)
+ * vfprintf(stderr, fmt, ap);
+ * va_end(ap);
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * if (argc != 1) {
+ * logger(3, "Don't want %i arguments!\n", argc-1);
+ * return 1;
+ * }
+ * return 0;
+ * }
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/contrib/ccan/compiler/compiler.h b/contrib/ccan/compiler/compiler.h
new file mode 100644
index 0000000..bce4f25
--- /dev/null
+++ b/contrib/ccan/compiler/compiler.h
@@ -0,0 +1,231 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#ifndef CCAN_COMPILER_H
+#define CCAN_COMPILER_H
+#include "config.h"
+
+#ifndef COLD
+#if HAVE_ATTRIBUTE_COLD
+/**
+ * COLD - a function is unlikely to be called.
+ *
+ * Used to mark an unlikely code path and optimize appropriately.
+ * It is usually used on logging or error routines.
+ *
+ * Example:
+ * static void COLD moan(const char *reason)
+ * {
+ * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
+ * }
+ */
+#define COLD __attribute__((__cold__))
+#else
+#define COLD
+#endif
+#endif
+
+#ifndef NORETURN
+#if HAVE_ATTRIBUTE_NORETURN
+/**
+ * NORETURN - a function does not return
+ *
+ * Used to mark a function which exits; useful for suppressing warnings.
+ *
+ * Example:
+ * static void NORETURN fail(const char *reason)
+ * {
+ * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno));
+ * exit(1);
+ * }
+ */
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#endif
+#endif
+
+#ifndef PRINTF_FMT
+#if HAVE_ATTRIBUTE_PRINTF
+/**
+ * PRINTF_FMT - a function takes printf-style arguments
+ * @nfmt: the 1-based number of the function's format argument.
+ * @narg: the 1-based number of the function's first variable argument.
+ *
+ * This allows the compiler to check your parameters as it does for printf().
+ *
+ * Example:
+ * void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...);
+ */
+#define PRINTF_FMT(nfmt, narg) \
+ __attribute__((format(__printf__, nfmt, narg)))
+#else
+#define PRINTF_FMT(nfmt, narg)
+#endif
+#endif
+
+#ifndef CONST_FUNCTION
+#if HAVE_ATTRIBUTE_CONST
+/**
+ * CONST_FUNCTION - a function's return depends only on its argument
+ *
+ * This allows the compiler to assume that the function will return the exact
+ * same value for the exact same arguments. This implies that the function
+ * must not use global variables, or dereference pointer arguments.
+ */
+#define CONST_FUNCTION __attribute__((__const__))
+#else
+#define CONST_FUNCTION
+#endif
+
+#ifndef PURE_FUNCTION
+#if HAVE_ATTRIBUTE_PURE
+/**
+ * PURE_FUNCTION - a function is pure
+ *
+ * A pure function is one that has no side effects other than it's return value
+ * and uses no inputs other than it's arguments and global variables.
+ */
+#define PURE_FUNCTION __attribute__((__pure__))
+#else
+#define PURE_FUNCTION
+#endif
+#endif
+#endif
+
+#if HAVE_ATTRIBUTE_UNUSED
+#ifndef UNNEEDED
+/**
+ * UNNEEDED - a variable/function may not be needed
+ *
+ * This suppresses warnings about unused variables or functions, but tells
+ * the compiler that if it is unused it need not emit it into the source code.
+ *
+ * Example:
+ * // With some preprocessor options, this is unnecessary.
+ * static UNNEEDED int counter;
+ *
+ * // With some preprocessor options, this is unnecessary.
+ * static UNNEEDED void add_to_counter(int add)
+ * {
+ * counter += add;
+ * }
+ */
+#define UNNEEDED __attribute__((__unused__))
+#endif
+
+#ifndef NEEDED
+#if HAVE_ATTRIBUTE_USED
+/**
+ * NEEDED - a variable/function is needed
+ *
+ * This suppresses warnings about unused variables or functions, but tells
+ * the compiler that it must exist even if it (seems) unused.
+ *
+ * Example:
+ * // Even if this is unused, these are vital for debugging.
+ * static NEEDED int counter;
+ * static NEEDED void dump_counter(void)
+ * {
+ * printf("Counter is %i\n", counter);
+ * }
+ */
+#define NEEDED __attribute__((__used__))
+#else
+/* Before used, unused functions and vars were always emitted. */
+#define NEEDED __attribute__((__unused__))
+#endif
+#endif
+
+#ifndef UNUSED
+/**
+ * UNUSED - a parameter is unused
+ *
+ * Some compilers (eg. gcc with -W or -Wunused) warn about unused
+ * function parameters. This suppresses such warnings and indicates
+ * to the reader that it's deliberate.
+ *
+ * Example:
+ * // This is used as a callback, so needs to have this prototype.
+ * static int some_callback(void *unused UNUSED)
+ * {
+ * return 0;
+ * }
+ */
+#define UNUSED __attribute__((__unused__))
+#endif
+#else
+#ifndef UNNEEDED
+#define UNNEEDED
+#endif
+#ifndef NEEDED
+#define NEEDED
+#endif
+#ifndef UNUSED
+#define UNUSED
+#endif
+#endif
+
+#ifndef IS_COMPILE_CONSTANT
+#if HAVE_BUILTIN_CONSTANT_P
+/**
+ * IS_COMPILE_CONSTANT - does the compiler know the value of this expression?
+ * @expr: the expression to evaluate
+ *
+ * When an expression manipulation is complicated, it is usually better to
+ * implement it in a function. However, if the expression being manipulated is
+ * known at compile time, it is better to have the compiler see the entire
+ * expression so it can simply substitute the result.
+ *
+ * This can be done using the IS_COMPILE_CONSTANT() macro.
+ *
+ * Example:
+ * enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON };
+ *
+ * // Out-of-line version.
+ * const char *greek_name(enum greek greek);
+ *
+ * // Inline version.
+ * static inline const char *_greek_name(enum greek greek)
+ * {
+ * switch (greek) {
+ * case ALPHA: return "alpha";
+ * case BETA: return "beta";
+ * case GAMMA: return "gamma";
+ * case DELTA: return "delta";
+ * case EPSILON: return "epsilon";
+ * default: return "**INVALID**";
+ * }
+ * }
+ *
+ * // Use inline if compiler knows answer. Otherwise call function
+ * // to avoid copies of the same code everywhere.
+ * #define greek_name(g) \
+ * (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g))
+ */
+#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr)
+#else
+/* If we don't know, assume it's not. */
+#define IS_COMPILE_CONSTANT(expr) 0
+#endif
+#endif
+
+#ifndef WARN_UNUSED_RESULT
+#if HAVE_WARN_UNUSED_RESULT
+/**
+ * WARN_UNUSED_RESULT - warn if a function return value is unused.
+ *
+ * Used to mark a function where it is extremely unlikely that the caller
+ * can ignore the result, eg realloc().
+ *
+ * Example:
+ * // buf param may be freed by this; need return value!
+ * static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size)
+ * {
+ * return realloc(buf, (*size) *= 2);
+ * }
+ */
+#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#else
+#define WARN_UNUSED_RESULT
+#endif
+#endif
+#endif /* CCAN_COMPILER_H */
diff --git a/contrib/ccan/compiler/test/compile_fail-printf.c b/contrib/ccan/compiler/test/compile_fail-printf.c
new file mode 100644
index 0000000..8f34ae5
--- /dev/null
+++ b/contrib/ccan/compiler/test/compile_fail-printf.c
@@ -0,0 +1,22 @@
+#include <ccan/compiler/compiler.h>
+
+static void PRINTF_FMT(2,3) my_printf(int x, const char *fmt, ...)
+{
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int i = 0;
+
+ my_printf(1, "Not a pointer "
+#ifdef FAIL
+ "%p",
+#if !HAVE_ATTRIBUTE_PRINTF
+#error "Unfortunately we don't fail if !HAVE_ATTRIBUTE_PRINTF."
+#endif
+#else
+ "%i",
+#endif
+ i);
+ return 0;
+}
diff --git a/contrib/ccan/compiler/test/run-is_compile_constant.c b/contrib/ccan/compiler/test/run-is_compile_constant.c
new file mode 100644
index 0000000..a66f2e1
--- /dev/null
+++ b/contrib/ccan/compiler/test/run-is_compile_constant.c
@@ -0,0 +1,15 @@
+#include <ccan/compiler/compiler.h>
+#include <ccan/tap/tap.h>
+
+int main(int argc, char *argv[])
+{
+ plan_tests(2);
+
+ ok1(!IS_COMPILE_CONSTANT(argc));
+#if HAVE_BUILTIN_CONSTANT_P
+ ok1(IS_COMPILE_CONSTANT(7));
+#else
+ pass("If !HAVE_BUILTIN_CONSTANT_P, IS_COMPILE_CONSTANT always false");
+#endif
+ return exit_status();
+}
diff --git a/contrib/ccan/ilog/LICENSE b/contrib/ccan/ilog/LICENSE
new file mode 100644
index 0000000..feb9b11
--- /dev/null
+++ b/contrib/ccan/ilog/LICENSE
@@ -0,0 +1,28 @@
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
+
+ the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
+ moral rights retained by the original author(s) and/or performer(s);
+ publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
+ rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
+ rights protecting the extraction, dissemination, use and reuse of data in a Work;
+ database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
+ other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
+ Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
+ Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
+ Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
diff --git a/contrib/ccan/ilog/_info b/contrib/ccan/ilog/_info
new file mode 100644
index 0000000..f1f3f2d
--- /dev/null
+++ b/contrib/ccan/ilog/_info
@@ -0,0 +1,50 @@
+/**
+ * ilog - Integer logarithm.
+ *
+ * ilog_32() and ilog_64() compute the minimum number of bits required to store
+ * an unsigned 32-bit or 64-bit value without any leading zero bits.
+ *
+ * This can also be thought of as the location of the highest set bit, with
+ * counting starting from one (so that 0 returns 0, 1 returns 1, and 2**31
+ * returns 32).
+ *
+ * When the value is known to be non-zero ilog32_nz() and ilog64_nz() can
+ * compile into as few as two instructions, one of which may get optimized out
+ * later.
+ *
+ * STATIC_ILOG_32 and STATIC_ILOG_64 allow computation on compile-time
+ * constants, so other compile-time constants can be derived from them.
+ *
+ * Example:
+ * #include <stdio.h>
+ * #include <limits.h>
+ * #include <ccan/ilog/ilog.h>
+ *
+ * int main(void){
+ * int i;
+ * printf("ilog32(0x%08X)=%i\n",0,ilog32(0));
+ * for(i=1;i<=STATIC_ILOG_32(USHRT_MAX);i++){
+ * uint32_t v;
+ * v=(uint32_t)1U<<(i-1);
+ * //Here we know v is non-zero, so we can use ilog32_nz().
+ * printf("ilog32(0x%08X)=%i\n",v,ilog32_nz(v));
+ * }
+ * return 0;
+ * }
+ *
+ * License: CC0 (Public domain)
+ * Author: Timothy B. Terriberry <tterribe@xiph.org>
+ */
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+
+int main(int _argc,const char *_argv[]){
+ /*Expect exactly one argument.*/
+ if(_argc!=2)return 1;
+ if(strcmp(_argv[1],"depends")==0){
+ printf("ccan/compiler\n");
+ return 0;
+ }
+ return 1;
+}
diff --git a/contrib/ccan/ilog/ilog.c b/contrib/ccan/ilog/ilog.c
new file mode 100644
index 0000000..5f5122d
--- /dev/null
+++ b/contrib/ccan/ilog/ilog.c
@@ -0,0 +1,141 @@
+/*(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 CC0 (Public domain).
+ * See LICENSE file for details. */
+#include "ilog.h"
+#include <limits.h>
+
+/*The fastest fallback strategy for platforms with fast multiplication appears
+ to be based on de Bruijn sequences~\cite{LP98}.
+ Tests confirmed this to be true even on an ARM11, where it is actually faster
+ than using the native clz instruction.
+ Define ILOG_NODEBRUIJN to use a simpler fallback on platforms where
+ multiplication or table lookups are too expensive.
+
+ @UNPUBLISHED{LP98,
+ author="Charles E. Leiserson and Harald Prokop",
+ title="Using de {Bruijn} Sequences to Index a 1 in a Computer Word",
+ month=Jun,
+ year=1998,
+ note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}"
+ }*/
+static UNNEEDED const unsigned char DEBRUIJN_IDX32[32]={
+ 0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8,
+ 31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9
+};
+
+/* We always compile these in, in case someone takes address of function. */
+#undef ilog32_nz
+#undef ilog32
+#undef ilog64_nz
+#undef ilog64
+
+int ilog32(uint32_t _v){
+/*On a Pentium M, this branchless version tested as the fastest version without
+ multiplications on 1,000,000,000 random 32-bit integers, edging out a
+ similar version with branches, and a 256-entry LUT version.*/
+# if defined(ILOG_NODEBRUIJN)
+ int ret;
+ int m;
+ ret=_v>0;
+ m=(_v>0xFFFFU)<<4;
+ _v>>=m;
+ ret|=m;
+ m=(_v>0xFFU)<<3;
+ _v>>=m;
+ ret|=m;
+ m=(_v>0xFU)<<2;
+ _v>>=m;
+ ret|=m;
+ m=(_v>3)<<1;
+ _v>>=m;
+ ret|=m;
+ ret+=_v>1;
+ return ret;
+/*This de Bruijn sequence version is faster if you have a fast multiplier.*/
+# else
+ int ret;
+ ret=_v>0;
+ _v|=_v>>1;
+ _v|=_v>>2;
+ _v|=_v>>4;
+ _v|=_v>>8;
+ _v|=_v>>16;
+ _v=(_v>>1)+1;
+ ret+=DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F];
+ return ret;
+# endif
+}
+
+int ilog32_nz(uint32_t _v)
+{
+ return ilog32(_v);
+}
+
+int ilog64(uint64_t _v){
+# if defined(ILOG_NODEBRUIJN)
+ uint32_t v;
+ int ret;
+ int m;
+ ret=_v>0;
+ m=(_v>0xFFFFFFFFU)<<5;
+ v=(uint32_t)(_v>>m);
+ ret|=m;
+ m=(v>0xFFFFU)<<4;
+ v>>=m;
+ ret|=m;
+ m=(v>0xFFU)<<3;
+ v>>=m;
+ ret|=m;
+ m=(v>0xFU)<<2;
+ v>>=m;
+ ret|=m;
+ m=(v>3)<<1;
+ v>>=m;
+ ret|=m;
+ ret+=v>1;
+ return ret;
+# else
+/*If we don't have a 64-bit word, split it into two 32-bit halves.*/
+# if LONG_MAX<9223372036854775807LL
+ uint32_t v;
+ int ret;
+ int m;
+ ret=_v>0;
+ m=(_v>0xFFFFFFFFU)<<5;
+ v=(uint32_t)(_v>>m);
+ ret|=m;
+ v|=v>>1;
+ v|=v>>2;
+ v|=v>>4;
+ v|=v>>8;
+ v|=v>>16;
+ v=(v>>1)+1;
+ ret+=DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F];
+ return ret;
+/*Otherwise do it in one 64-bit operation.*/
+# else
+ static const unsigned char DEBRUIJN_IDX64[64]={
+ 0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
+ 5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
+ 63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56,
+ 62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
+ };
+ int ret;
+ ret=_v>0;
+ _v|=_v>>1;
+ _v|=_v>>2;
+ _v|=_v>>4;
+ _v|=_v>>8;
+ _v|=_v>>16;
+ _v|=_v>>32;
+ _v=(_v>>1)+1;
+ ret+=DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F];
+ return ret;
+# endif
+# endif
+}
+
+int ilog64_nz(uint64_t _v)
+{
+ return ilog64(_v);
+}
+
diff --git a/contrib/ccan/ilog/ilog.h b/contrib/ccan/ilog/ilog.h
new file mode 100644
index 0000000..9adbb82
--- /dev/null
+++ b/contrib/ccan/ilog/ilog.h
@@ -0,0 +1,151 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#if !defined(_ilog_H)
+# define _ilog_H (1)
+# include "config.h"
+# include <stdint.h>
+# include <limits.h>
+# include <ccan/compiler/compiler.h>
+
+/**
+ * ilog32 - Integer binary logarithm of a 32-bit value.
+ * @_v: A 32-bit value.
+ * Returns floor(log2(_v))+1, or 0 if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * Note that many uses will resolve to the fast macro version instead.
+ *
+ * See Also:
+ * ilog32_nz(), ilog64()
+ *
+ * Example:
+ * // Rounds up to next power of 2 (if not a power of 2).
+ * static uint32_t round_up32(uint32_t i)
+ * {
+ * assert(i != 0);
+ * return 1U << ilog32(i-1);
+ * }
+ */
+int ilog32(uint32_t _v) CONST_FUNCTION;
+
+/**
+ * ilog32_nz - Integer binary logarithm of a non-zero 32-bit value.
+ * @_v: A 32-bit value.
+ * Returns floor(log2(_v))+1, or undefined if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * Note that many uses will resolve to the fast macro version instead.
+ * See Also:
+ * ilog32(), ilog64_nz()
+ * Example:
+ * // Find Last Set (ie. highest bit set, 0 to 31).
+ * static uint32_t fls32(uint32_t i)
+ * {
+ * assert(i != 0);
+ * return ilog32_nz(i) - 1;
+ * }
+ */
+int ilog32_nz(uint32_t _v) CONST_FUNCTION;
+
+/**
+ * ilog64 - Integer binary logarithm of a 64-bit value.
+ * @_v: A 64-bit value.
+ * Returns floor(log2(_v))+1, or 0 if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * Note that many uses will resolve to the fast macro version instead.
+ * See Also:
+ * ilog64_nz(), ilog32()
+ */
+int ilog64(uint64_t _v) CONST_FUNCTION;
+
+/**
+ * ilog64_nz - Integer binary logarithm of a non-zero 64-bit value.
+ * @_v: A 64-bit value.
+ * Returns floor(log2(_v))+1, or undefined if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * Note that many uses will resolve to the fast macro version instead.
+ * See Also:
+ * ilog64(), ilog32_nz()
+ */
+int ilog64_nz(uint64_t _v) CONST_FUNCTION;
+
+/**
+ * STATIC_ILOG_32 - The integer logarithm of an (unsigned, 32-bit) constant.
+ * @_v: A non-negative 32-bit constant.
+ * Returns floor(log2(_v))+1, or 0 if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * This macro should only be used when you need a compile-time constant,
+ * otherwise ilog32 or ilog32_nz are just as fast and more flexible.
+ *
+ * Example:
+ * #define MY_PAGE_SIZE 4096
+ * #define MY_PAGE_BITS (STATIC_ILOG_32(PAGE_SIZE) - 1)
+ */
+#define STATIC_ILOG_32(_v) (STATIC_ILOG5((uint32_t)(_v)))
+
+/**
+ * STATIC_ILOG_64 - The integer logarithm of an (unsigned, 64-bit) constant.
+ * @_v: A non-negative 64-bit constant.
+ * Returns floor(log2(_v))+1, or 0 if _v==0.
+ * This is the number of bits that would be required to represent _v in two's
+ * complement notation with all of the leading zeros stripped.
+ * This macro should only be used when you need a compile-time constant,
+ * otherwise ilog64 or ilog64_nz are just as fast and more flexible.
+ */
+#define STATIC_ILOG_64(_v) (STATIC_ILOG6((uint64_t)(_v)))
+
+/* Private implementation details */
+
+/*Note the casts to (int) below: this prevents "upgrading"
+ the type of an entire expression to an (unsigned) size_t.*/
+#if INT_MAX>=2147483647 && HAVE_BUILTIN_CLZ
+#define builtin_ilog32_nz(v) \
+ (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v))
+#elif LONG_MAX>=2147483647L && HAVE_BUILTIN_CLZL
+#define builtin_ilog32_nz(v) \
+ (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clzl(v))
+#endif
+
+#if INT_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZ
+#define builtin_ilog64_nz(v) \
+ (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v))
+#elif LONG_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZL
+#define builtin_ilog64_nz(v) \
+ (((int)sizeof(unsigned long)*CHAR_BIT) - __builtin_clzl(v))
+#elif HAVE_BUILTIN_CLZLL
+#define builtin_ilog64_nz(v) \
+ (((int)sizeof(unsigned long long)*CHAR_BIT) - __builtin_clzll(v))
+#endif
+
+#ifdef builtin_ilog32_nz
+#define ilog32(_v) (builtin_ilog32_nz(_v)&-!!(_v))
+#define ilog32_nz(_v) builtin_ilog32_nz(_v)
+#else
+#define ilog32_nz(_v) ilog32(_v)
+#define ilog32(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_32(_v) : ilog32(_v))
+#endif /* builtin_ilog32_nz */
+
+#ifdef builtin_ilog64_nz
+#define ilog64(_v) (builtin_ilog64_nz(_v)&-!!(_v))
+#define ilog64_nz(_v) builtin_ilog64_nz(_v)
+#else
+#define ilog64_nz(_v) ilog64(_v)
+#define ilog64(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_64(_v) : ilog64(_v))
+#endif /* builtin_ilog64_nz */
+
+/* Macros for evaluating compile-time constant ilog. */
+# define STATIC_ILOG0(_v) (!!(_v))
+# define STATIC_ILOG1(_v) (((_v)&0x2)?2:STATIC_ILOG0(_v))
+# define STATIC_ILOG2(_v) (((_v)&0xC)?2+STATIC_ILOG1((_v)>>2):STATIC_ILOG1(_v))
+# define STATIC_ILOG3(_v) \
+ (((_v)&0xF0)?4+STATIC_ILOG2((_v)>>4):STATIC_ILOG2(_v))
+# define STATIC_ILOG4(_v) \
+ (((_v)&0xFF00)?8+STATIC_ILOG3((_v)>>8):STATIC_ILOG3(_v))
+# define STATIC_ILOG5(_v) \
+ (((_v)&0xFFFF0000)?16+STATIC_ILOG4((_v)>>16):STATIC_ILOG4(_v))
+# define STATIC_ILOG6(_v) \
+ (((_v)&0xFFFFFFFF00000000ULL)?32+STATIC_ILOG5((_v)>>32):STATIC_ILOG5(_v))
+
+#endif /* _ilog_H */
diff --git a/contrib/ccan/ilog/test/run-out-of-line.c b/contrib/ccan/ilog/test/run-out-of-line.c
new file mode 100644
index 0000000..48205d3
--- /dev/null
+++ b/contrib/ccan/ilog/test/run-out-of-line.c
@@ -0,0 +1,65 @@
+#include <ccan/ilog/ilog.h>
+#include <ccan/ilog/ilog.c>
+#include <stdio.h>
+#include <ccan/tap/tap.h>
+
+/*Dead simple (but slow) versions to compare against.*/
+
+static int test_ilog32(uint32_t _v){
+ int ret;
+ for(ret=0;_v;ret++)_v>>=1;
+ return ret;
+}
+
+static int test_ilog64(uint64_t _v){
+ int ret;
+ for(ret=0;_v;ret++)_v>>=1;
+ return ret;
+}
+
+#define NTRIALS (64)
+
+int main(int _argc,const char *_argv[]){
+ int i;
+ int j;
+ int (*il32)(uint32_t) = ilog32;
+ int (*il64)(uint64_t) = ilog64;
+ int (*il32_nz)(uint32_t) = ilog32_nz;
+ int (*il64_nz)(uint64_t) = ilog64_nz;
+
+ /*This is how many tests you plan to run.*/
+ plan_tests(33 * NTRIALS * 3 + 65 * NTRIALS * 3);
+ for(i=0;i<=32;i++){
+ uint32_t v;
+ /*Test each bit in turn (and 0).*/
+ v=i?(uint32_t)1U<<(i-1):0;
+ for(j=0;j<NTRIALS;j++){
+ int l;
+ l=test_ilog32(v);
+ ok1(STATIC_ILOG_32(v)==l);
+ ok1(il32(v)==l);
+ ok1(il32_nz(v) == l || v == 0);
+ /*Also try a few more pseudo-random values with at most the same number
+ of bits.*/
+ v=(1103515245U*v+12345U)&0xFFFFFFFFU>>((33-i)>>1)>>((32-i)>>1);
+ }
+ }
+
+ for(i=0;i<=64;i++){
+ uint64_t v;
+ /*Test each bit in turn (and 0).*/
+ v=i?(uint64_t)1U<<(i-1):0;
+ for(j=0;j<NTRIALS;j++){
+ int l;
+ l=test_ilog64(v);
+ ok1(STATIC_ILOG_64(v)==l);
+ ok1(il64(v)==l);
+ ok1(il64_nz(v) == l || v == 0);
+ /*Also try a few more pseudo-random values with at most the same number
+ of bits.*/
+ v=(uint64_t)((2862933555777941757ULL*v+3037000493ULL)
+ &0xFFFFFFFFFFFFFFFFULL>>((65-i)>>1)>>((64-i)>>1));
+ }
+ }
+ return exit_status();
+}
diff --git a/contrib/ccan/ilog/test/run.c b/contrib/ccan/ilog/test/run.c
new file mode 100644
index 0000000..bda59f9
--- /dev/null
+++ b/contrib/ccan/ilog/test/run.c
@@ -0,0 +1,60 @@
+#include <ccan/ilog/ilog.h>
+#include <ccan/ilog/ilog.c>
+#include <stdio.h>
+#include <ccan/tap/tap.h>
+
+/*Dead simple (but slow) versions to compare against.*/
+
+static int test_ilog32(uint32_t _v){
+ int ret;
+ for(ret=0;_v;ret++)_v>>=1;
+ return ret;
+}
+
+static int test_ilog64(uint64_t _v){
+ int ret;
+ for(ret=0;_v;ret++)_v>>=1;
+ return ret;
+}
+
+#define NTRIALS (64)
+
+int main(int _argc,const char *_argv[]){
+ int i;
+ int j;
+ /*This is how many tests you plan to run.*/
+ plan_tests(33 * NTRIALS * 3 + 65 * NTRIALS * 3);
+ for(i=0;i<=32;i++){
+ uint32_t v;
+ /*Test each bit in turn (and 0).*/
+ v=i?(uint32_t)1U<<(i-1):0;
+ for(j=0;j<NTRIALS;j++){
+ int l;
+ l=test_ilog32(v);
+ ok1(STATIC_ILOG_32(v)==l);
+ ok1(ilog32(v)==l);
+ ok1(ilog32_nz(v) == l || v == 0);
+ /*Also try a few more pseudo-random values with at most the same number
+ of bits.*/
+ v=(1103515245U*v+12345U)&0xFFFFFFFFU>>((33-i)>>1)>>((32-i)>>1);
+ }
+ }
+
+ for(i=0;i<=64;i++){
+ uint64_t v;
+ /*Test each bit in turn (and 0).*/
+ v=i?(uint64_t)1U<<(i-1):0;
+ for(j=0;j<NTRIALS;j++){
+ int l;
+ l=test_ilog64(v);
+ ok1(STATIC_ILOG_64(v)==l);
+ ok1(ilog64(v)==l);
+ ok1(ilog64_nz(v) == l || v == 0);
+ /*Also try a few more pseudo-random values with at most the same number
+ of bits.*/
+ v=(uint64_t)((2862933555777941757ULL*v+3037000493ULL)
+ &0xFFFFFFFFFFFFFFFFULL>>((65-i)>>1)>>((64-i)>>1));
+ }
+ }
+ return exit_status();
+}
diff --git a/contrib/ccan/json/LICENSE b/contrib/ccan/json/LICENSE
new file mode 100644
index 0000000..89de354
--- /dev/null
+++ b/contrib/ccan/json/LICENSE
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/contrib/ccan/json/_info b/contrib/ccan/json/_info
new file mode 100644
index 0000000..3113b63
--- /dev/null
+++ b/contrib/ccan/json/_info
@@ -0,0 +1,119 @@
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * json - Parse and generate JSON (JavaScript Object Notation)
+ *
+ * This is a library for encoding and decoding JSON that strives to be
+ * easy to learn, use, and incorporate into an application.
+ *
+ * JSON (JavaScript Object Notation) facilitates passing data among different
+ * programming languages, particularly JavaScript. It looks like this:
+ *
+ * [
+ * {
+ * "id": 1,
+ * "firstname": "John",
+ * "lastname": "Smith",
+ * "email": "john@example.com",
+ * "likes_pizza": false
+ * },
+ * {
+ * "id": 2,
+ * "firstname": "Linda",
+ * "lastname": "Jones",
+ * "email": null,
+ * "likes_pizza": true
+ * }
+ * ]
+ *
+ * Example:
+ * #include <ccan/json/json.h>
+ * #include <math.h>
+ * #include <stdio.h>
+ * #include <stdlib.h>
+ *
+ * static int find_number(JsonNode *object, const char *name, double *out)
+ * {
+ * JsonNode *node = json_find_member(object, name);
+ * if (node && node->tag == JSON_NUMBER) {
+ * *out = node->number_;
+ * return 1;
+ * }
+ * return 0;
+ * }
+ *
+ * static void solve_pythagorean(JsonNode *triple)
+ * {
+ * double a = 0, b = 0, c = 0;
+ * int a_given, b_given, c_given;
+ *
+ * if (triple->tag != JSON_OBJECT) {
+ * fprintf(stderr, "Error: Expected a JSON object.\n");
+ * exit(EXIT_FAILURE);
+ * }
+ *
+ * a_given = find_number(triple, "a", &a);
+ * b_given = find_number(triple, "b", &b);
+ * c_given = find_number(triple, "c", &c);
+ *
+ * if (a_given + b_given + c_given != 2) {
+ * fprintf(stderr, "Error: I need two sides to compute the length of the third.\n");
+ * exit(EXIT_FAILURE);
+ * }
+ *
+ * if (a_given && b_given) {
+ * c = sqrt(a*a + b*b);
+ * json_append_member(triple, "c", json_mknumber(c));
+ * } else if (a_given && c_given) {
+ * b = sqrt(c*c - a*a);
+ * json_append_member(triple, "b", json_mknumber(b));
+ * } else if (b_given && c_given) {
+ * a = sqrt(c*c - b*b);
+ * json_append_member(triple, "a", json_mknumber(a));
+ * }
+ * }
+ *
+ * int main(void)
+ * {
+ * JsonNode *triples = json_mkarray();
+ *
+ * json_append_element(triples, json_decode("{\"a\": 3, \"b\": 4}"));
+ * json_append_element(triples, json_decode("{\"a\": 5, \"c\": 13}"));
+ * json_append_element(triples, json_decode("{\"b\": 24, \"c\": 25}"));
+ *
+ * JsonNode *triple;
+ * json_foreach(triple, triples)
+ * solve_pythagorean(triple);
+ *
+ * char *tmp = json_stringify(triples, "\t");
+ * puts(tmp);
+ * free(tmp);
+ *
+ * json_delete(triples);
+ * return 0;
+ * }
+ *
+ * Author: Joey Adams
+ * Version: 0.1
+ * License: MIT
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ /* Nothing */
+ return 0;
+ }
+
+ if (strcmp(argv[1], "libs") == 0) {
+ printf("m\n"); /* Needed for sqrt() used in example code above. */
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/contrib/ccan/json/json.c b/contrib/ccan/json/json.c
new file mode 100644
index 0000000..3fd3d43
--- /dev/null
+++ b/contrib/ccan/json/json.c
@@ -0,0 +1,1381 @@
+/*
+ Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
+ All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include "json.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define out_of_memory() do { \
+ fprintf(stderr, "Out of memory.\n"); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+/* Sadly, strdup is not portable. */
+static char *json_strdup(const char *str)
+{
+ char *ret = (char*) malloc(strlen(str) + 1);
+ if (ret == NULL)
+ out_of_memory();
+ strcpy(ret, str);
+ return ret;
+}
+
+/* String buffer */
+
+typedef struct
+{
+ char *cur;
+ char *end;
+ char *start;
+} SB;
+
+static void sb_init(SB *sb)
+{
+ sb->start = (char*) malloc(17);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start;
+ sb->end = sb->start + 16;
+}
+
+/* sb and need may be evaluated multiple times. */
+#define sb_need(sb, need) do { \
+ if ((sb)->end - (sb)->cur < (need)) \
+ sb_grow(sb, need); \
+ } while (0)
+
+static void sb_grow(SB *sb, int need)
+{
+ size_t length = sb->cur - sb->start;
+ size_t alloc = sb->end - sb->start;
+
+ do {
+ alloc *= 2;
+ } while (alloc < length + need);
+
+ sb->start = (char*) realloc(sb->start, alloc + 1);
+ if (sb->start == NULL)
+ out_of_memory();
+ sb->cur = sb->start + length;
+ sb->end = sb->start + alloc;
+}
+
+static void sb_put(SB *sb, const char *bytes, int count)
+{
+ sb_need(sb, count);
+ memcpy(sb->cur, bytes, count);
+ sb->cur += count;
+}
+
+#define sb_putc(sb, c) do { \
+ if ((sb)->cur >= (sb)->end) \
+ sb_grow(sb, 1); \
+ *(sb)->cur++ = (c); \
+ } while (0)
+
+static void sb_puts(SB *sb, const char *str)
+{
+ sb_put(sb, str, strlen(str));
+}
+
+static char *sb_finish(SB *sb)
+{
+ *sb->cur = 0;
+ assert(sb->start <= sb->cur && strlen(sb->start) == (size_t)(sb->cur - sb->start));
+ return sb->start;
+}
+
+static void sb_free(SB *sb)
+{
+ free(sb->start);
+}
+
+/*
+ * Unicode helper functions
+ *
+ * These are taken from the ccan/charset module and customized a bit.
+ * Putting them here means the compiler can (choose to) inline them,
+ * and it keeps ccan/json from having a dependency.
+ */
+
+/*
+ * Type for Unicode codepoints.
+ * We need our own because wchar_t might be 16 bits.
+ */
+typedef uint32_t uchar_t;
+
+/*
+ * Validate a single UTF-8 character starting at @s.
+ * The string must be null-terminated.
+ *
+ * If it's valid, return its length (1 thru 4).
+ * If it's invalid or clipped, return 0.
+ *
+ * This function implements the syntax given in RFC3629, which is
+ * the same as that given in The Unicode Standard, Version 6.0.
+ *
+ * It has the following properties:
+ *
+ * * All codepoints U+0000..U+10FFFF may be encoded,
+ * except for U+D800..U+DFFF, which are reserved
+ * for UTF-16 surrogate pair encoding.
+ * * UTF-8 byte sequences longer than 4 bytes are not permitted,
+ * as they exceed the range of Unicode.
+ * * The sixty-six Unicode "non-characters" are permitted
+ * (namely, U+FDD0..U+FDEF, U+xxFFFE, and U+xxFFFF).
+ */
+static int utf8_validate_cz(const char *s)
+{
+ unsigned char c = *s++;
+
+ if (c <= 0x7F) { /* 00..7F */
+ return 1;
+ } else if (c <= 0xC1) { /* 80..C1 */
+ /* Disallow overlong 2-byte sequence. */
+ return 0;
+ } else if (c <= 0xDF) { /* C2..DF */
+ /* Make sure subsequent byte is in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 2;
+ } else if (c <= 0xEF) { /* E0..EF */
+ /* Disallow overlong 3-byte sequence. */
+ if (c == 0xE0 && (unsigned char)*s < 0xA0)
+ return 0;
+
+ /* Disallow U+D800..U+DFFF. */
+ if (c == 0xED && (unsigned char)*s > 0x9F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 3;
+ } else if (c <= 0xF4) { /* F0..F4 */
+ /* Disallow overlong 4-byte sequence. */
+ if (c == 0xF0 && (unsigned char)*s < 0x90)
+ return 0;
+
+ /* Disallow codepoints beyond U+10FFFF. */
+ if (c == 0xF4 && (unsigned char)*s > 0x8F)
+ return 0;
+
+ /* Make sure subsequent bytes are in the range 0x80..0xBF. */
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+ if (((unsigned char)*s++ & 0xC0) != 0x80)
+ return 0;
+
+ return 4;
+ } else { /* F5..FF */
+ return 0;
+ }
+}
+
+/* Validate a null-terminated UTF-8 string. */
+static bool utf8_validate(const char *s)
+{
+ int len;
+
+ for (; *s != 0; s += len) {
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Read a single UTF-8 character starting at @s,
+ * returning the length, in bytes, of the character read.
+ *
+ * This function assumes input is valid UTF-8,
+ * and that there are enough characters in front of @s.
+ */
+static int utf8_read_char(const char *s, uchar_t *out)
+{
+ const unsigned char *c = (const unsigned char*) s;
+
+ assert(utf8_validate_cz(s));
+
+ if (c[0] <= 0x7F) {
+ /* 00..7F */
+ *out = c[0];
+ return 1;
+ } else if (c[0] <= 0xDF) {
+ /* C2..DF (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x1F) << 6 |
+ ((uchar_t)c[1] & 0x3F);
+ return 2;
+ } else if (c[0] <= 0xEF) {
+ /* E0..EF */
+ *out = ((uchar_t)c[0] & 0xF) << 12 |
+ ((uchar_t)c[1] & 0x3F) << 6 |
+ ((uchar_t)c[2] & 0x3F);
+ return 3;
+ } else {
+ /* F0..F4 (unless input is invalid) */
+ *out = ((uchar_t)c[0] & 0x7) << 18 |
+ ((uchar_t)c[1] & 0x3F) << 12 |
+ ((uchar_t)c[2] & 0x3F) << 6 |
+ ((uchar_t)c[3] & 0x3F);
+ return 4;
+ }
+}
+
+/*
+ * Write a single UTF-8 character to @s,
+ * returning the length, in bytes, of the character written.
+ *
+ * @unicode must be U+0000..U+10FFFF, but not U+D800..U+DFFF.
+ *
+ * This function will write up to 4 bytes to @out.
+ */
+static int utf8_write_char(uchar_t unicode, char *out)
+{
+ unsigned char *o = (unsigned char*) out;
+
+ assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF));
+
+ if (unicode <= 0x7F) {
+ /* U+0000..U+007F */
+ *o++ = unicode;
+ return 1;
+ } else if (unicode <= 0x7FF) {
+ /* U+0080..U+07FF */
+ *o++ = 0xC0 | unicode >> 6;
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 2;
+ } else if (unicode <= 0xFFFF) {
+ /* U+0800..U+FFFF */
+ *o++ = 0xE0 | unicode >> 12;
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 3;
+ } else {
+ /* U+10000..U+10FFFF */
+ *o++ = 0xF0 | unicode >> 18;
+ *o++ = 0x80 | (unicode >> 12 & 0x3F);
+ *o++ = 0x80 | (unicode >> 6 & 0x3F);
+ *o++ = 0x80 | (unicode & 0x3F);
+ return 4;
+ }
+}
+
+/*
+ * Compute the Unicode codepoint of a UTF-16 surrogate pair.
+ *
+ * @uc should be 0xD800..0xDBFF, and @lc should be 0xDC00..0xDFFF.
+ * If they aren't, this function returns false.
+ */
+static bool from_surrogate_pair(uint16_t uc, uint16_t lc, uchar_t *unicode)
+{
+ if (uc >= 0xD800 && uc <= 0xDBFF && lc >= 0xDC00 && lc <= 0xDFFF) {
+ *unicode = 0x10000 + ((((uchar_t)uc & 0x3FF) << 10) | (lc & 0x3FF));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*
+ * Construct a UTF-16 surrogate pair given a Unicode codepoint.
+ *
+ * @unicode must be U+10000..U+10FFFF.
+ */
+static void to_surrogate_pair(uchar_t unicode, uint16_t *uc, uint16_t *lc)
+{
+ uchar_t n;
+
+ assert(unicode >= 0x10000 && unicode <= 0x10FFFF);
+
+ n = unicode - 0x10000;
+ *uc = ((n >> 10) & 0x3FF) | 0xD800;
+ *lc = (n & 0x3FF) | 0xDC00;
+}
+
+#define is_space(c) ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static bool parse_value (const char **sp, JsonNode **out);
+static bool parse_string (const char **sp, char **out);
+static bool parse_number (const char **sp, double *out);
+static bool parse_array (const char **sp, JsonNode **out);
+static bool parse_object (const char **sp, JsonNode **out);
+static bool parse_hex16 (const char **sp, uint16_t *out);
+
+static bool expect_literal (const char **sp, const char *str);
+static void skip_space (const char **sp);
+
+static void emit_value (SB *out, const JsonNode *node);
+static void emit_value_indented (SB *out, const JsonNode *node, const char *space, int indent_level);
+static void emit_string (SB *out, const char *str);
+static void emit_number (SB *out, double num);
+static void emit_array (SB *out, const JsonNode *array);
+static void emit_array_indented (SB *out, const JsonNode *array, const char *space, int indent_level);
+static void emit_object (SB *out, const JsonNode *object);
+static void emit_object_indented (SB *out, const JsonNode *object, const char *space, int indent_level);
+
+static int write_hex16(char *out, uint16_t val);
+
+static JsonNode *mknode(JsonTag tag);
+static void append_node(JsonNode *parent, JsonNode *child);
+static void prepend_node(JsonNode *parent, JsonNode *child);
+static void append_member(JsonNode *object, char *key, JsonNode *value);
+
+/* Assertion-friendly validity checks */
+static bool tag_is_valid(unsigned int tag);
+static bool number_is_valid(const char *num);
+
+JsonNode *json_decode(const char *json)
+{
+ const char *s = json;
+ JsonNode *ret;
+
+ skip_space(&s);
+ if (!parse_value(&s, &ret))
+ return NULL;
+
+ skip_space(&s);
+ if (*s != 0) {
+ json_delete(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+char *json_encode(const JsonNode *node)
+{
+ return json_stringify(node, NULL);
+}
+
+char *json_encode_string(const char *str)
+{
+ SB sb;
+ sb_init(&sb);
+
+ emit_string(&sb, str);
+
+ return sb_finish(&sb);
+}
+
+char *json_stringify(const JsonNode *node, const char *space)
+{
+ SB sb;
+ sb_init(&sb);
+
+ if (space != NULL)
+ emit_value_indented(&sb, node, space, 0);
+ else
+ emit_value(&sb, node);
+
+ return sb_finish(&sb);
+}
+
+void json_delete(JsonNode *node)
+{
+ if (node != NULL) {
+ json_remove_from_parent(node);
+
+ switch (node->tag) {
+ case JSON_STRING:
+ free(node->string_);
+ break;
+ case JSON_ARRAY:
+ case JSON_OBJECT:
+ {
+ JsonNode *child, *next;
+ for (child = node->children.head; child != NULL; child = next) {
+ next = child->next;
+ json_delete(child);
+ }
+ break;
+ }
+ default:;
+ }
+
+ free(node);
+ }
+}
+
+bool json_validate(const char *json)
+{
+ const char *s = json;
+
+ skip_space(&s);
+ if (!parse_value(&s, NULL))
+ return false;
+
+ skip_space(&s);
+ if (*s != 0)
+ return false;
+
+ return true;
+}
+
+JsonNode *json_find_element(JsonNode *array, int index)
+{
+ JsonNode *element;
+ int i = 0;
+
+ if (array == NULL || array->tag != JSON_ARRAY)
+ return NULL;
+
+ json_foreach(element, array) {
+ if (i == index)
+ return element;
+ i++;
+ }
+
+ return NULL;
+}
+
+JsonNode *json_find_member(JsonNode *object, const char *name)
+{
+ JsonNode *member;
+
+ if (object == NULL || object->tag != JSON_OBJECT)
+ return NULL;
+
+ json_foreach(member, object)
+ if (strcmp(member->key, name) == 0)
+ return member;
+
+ return NULL;
+}
+
+JsonNode *json_first_child(const JsonNode *node)
+{
+ if (node != NULL && (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT))
+ return node->children.head;
+ return NULL;
+}
+
+static JsonNode *mknode(JsonTag tag)
+{
+ JsonNode *ret = (JsonNode*) calloc(1, sizeof(JsonNode));
+ if (ret == NULL)
+ out_of_memory();
+ ret->tag = tag;
+ return ret;
+}
+
+JsonNode *json_mknull(void)
+{
+ return mknode(JSON_NULL);
+}
+
+JsonNode *json_mkbool(bool b)
+{
+ JsonNode *ret = mknode(JSON_BOOL);
+ ret->bool_ = b;
+ return ret;
+}
+
+static JsonNode *mkstring(char *s)
+{
+ JsonNode *ret = mknode(JSON_STRING);
+ ret->string_ = s;
+ return ret;
+}
+
+JsonNode *json_mkstring(const char *s)
+{
+ return mkstring(json_strdup(s));
+}
+
+JsonNode *json_mknumber(double n)
+{
+ JsonNode *node = mknode(JSON_NUMBER);
+ node->number_ = n;
+ return node;
+}
+
+JsonNode *json_mkarray(void)
+{
+ return mknode(JSON_ARRAY);
+}
+
+JsonNode *json_mkobject(void)
+{
+ return mknode(JSON_OBJECT);
+}
+
+static void append_node(JsonNode *parent, JsonNode *child)
+{
+ child->parent = parent;
+ child->prev = parent->children.tail;
+ child->next = NULL;
+
+ if (parent->children.tail != NULL)
+ parent->children.tail->next = child;
+ else
+ parent->children.head = child;
+ parent->children.tail = child;
+}
+
+static void prepend_node(JsonNode *parent, JsonNode *child)
+{
+ child->parent = parent;
+ child->prev = NULL;
+ child->next = parent->children.head;
+
+ if (parent->children.head != NULL)
+ parent->children.head->prev = child;
+ else
+ parent->children.tail = child;
+ parent->children.head = child;
+}
+
+static void append_member(JsonNode *object, char *key, JsonNode *value)
+{
+ value->key = key;
+ append_node(object, value);
+}
+
+void json_append_element(JsonNode *array, JsonNode *element)
+{
+ assert(array->tag == JSON_ARRAY);
+ assert(element->parent == NULL);
+
+ append_node(array, element);
+}
+
+void json_prepend_element(JsonNode *array, JsonNode *element)
+{
+ assert(array->tag == JSON_ARRAY);
+ assert(element->parent == NULL);
+
+ prepend_node(array, element);
+}
+
+void json_append_member(JsonNode *object, const char *key, JsonNode *value)
+{
+ assert(object->tag == JSON_OBJECT);
+ assert(value->parent == NULL);
+
+ append_member(object, json_strdup(key), value);
+}
+
+void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
+{
+ assert(object->tag == JSON_OBJECT);
+ assert(value->parent == NULL);
+
+ value->key = json_strdup(key);
+ prepend_node(object, value);
+}
+
+void json_remove_from_parent(JsonNode *node)
+{
+ JsonNode *parent = node->parent;
+
+ if (parent != NULL) {
+ if (node->prev != NULL)
+ node->prev->next = node->next;
+ else
+ parent->children.head = node->next;
+ if (node->next != NULL)
+ node->next->prev = node->prev;
+ else
+ parent->children.tail = node->prev;
+
+ free(node->key);
+
+ node->parent = NULL;
+ node->prev = node->next = NULL;
+ node->key = NULL;
+ }
+}
+
+static bool parse_value(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+
+ switch (*s) {
+ case 'n':
+ if (expect_literal(&s, "null")) {
+ if (out)
+ *out = json_mknull();
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case 'f':
+ if (expect_literal(&s, "false")) {
+ if (out)
+ *out = json_mkbool(false);
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case 't':
+ if (expect_literal(&s, "true")) {
+ if (out)
+ *out = json_mkbool(true);
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '"': {
+ char *str;
+ if (parse_string(&s, out ? &str : NULL)) {
+ if (out)
+ *out = mkstring(str);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+
+ case '[':
+ if (parse_array(&s, out)) {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ case '{':
+ if (parse_object(&s, out)) {
+ *sp = s;
+ return true;
+ }
+ return false;
+
+ default: {
+ double num;
+ if (parse_number(&s, out ? &num : NULL)) {
+ if (out)
+ *out = json_mknumber(num);
+ *sp = s;
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
+static bool parse_array(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkarray() : NULL;
+ JsonNode *element;
+
+ if (*s++ != '[')
+ goto failure;
+ skip_space(&s);
+
+ if (*s == ']') {
+ s++;
+ goto success;
+ }
+
+ for (;;) {
+ if (!parse_value(&s, out ? &element : NULL))
+ goto failure;
+ skip_space(&s);
+
+ if (out)
+ json_append_element(ret, element);
+
+ if (*s == ']') {
+ s++;
+ goto success;
+ }
+
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
+success:
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
+
+failure:
+ json_delete(ret);
+ return false;
+}
+
+static bool parse_object(const char **sp, JsonNode **out)
+{
+ const char *s = *sp;
+ JsonNode *ret = out ? json_mkobject() : NULL;
+ char *key;
+ JsonNode *value;
+
+ if (*s++ != '{')
+ goto failure;
+ skip_space(&s);
+
+ if (*s == '}') {
+ s++;
+ goto success;
+ }
+
+ for (;;) {
+ if (!parse_string(&s, out ? &key : NULL))
+ goto failure;
+ skip_space(&s);
+
+ if (*s++ != ':')
+ goto failure_free_key;
+ skip_space(&s);
+
+ if (!parse_value(&s, out ? &value : NULL))
+ goto failure_free_key;
+ skip_space(&s);
+
+ if (out)
+ append_member(ret, key, value);
+
+ if (*s == '}') {
+ s++;
+ goto success;
+ }
+
+ if (*s++ != ',')
+ goto failure;
+ skip_space(&s);
+ }
+
+success:
+ *sp = s;
+ if (out)
+ *out = ret;
+ return true;
+
+failure_free_key:
+ if (out)
+ free(key);
+failure:
+ json_delete(ret);
+ return false;
+}
+
+bool parse_string(const char **sp, char **out)
+{
+ const char *s = *sp;
+ SB sb = { NULL, NULL, NULL };
+ char throwaway_buffer[4];
+ /* enough space for a UTF-8 character */
+ char *b;
+
+ if (*s++ != '"')
+ return false;
+
+ if (out) {
+ sb_init(&sb);
+ sb_need(&sb, 4);
+ b = sb.cur;
+ } else {
+ b = throwaway_buffer;
+ }
+
+ while (*s != '"') {
+ unsigned char c = *s++;
+
+ /* Parse next character, and write it to b. */
+ if (c == '\\') {
+ c = *s++;
+ switch (c) {
+ case '"':
+ case '\\':
+ case '/':
+ *b++ = c;
+ break;
+ case 'b':
+ *b++ = '\b';
+ break;
+ case 'f':
+ *b++ = '\f';
+ break;
+ case 'n':
+ *b++ = '\n';
+ break;
+ case 'r':
+ *b++ = '\r';
+ break;
+ case 't':
+ *b++ = '\t';
+ break;
+ case 'u':
+ {
+ uint16_t uc, lc;
+ uchar_t unicode;
+
+ if (!parse_hex16(&s, &uc))
+ goto failed;
+
+ if (uc >= 0xD800 && uc <= 0xDFFF) {
+ /* Handle UTF-16 surrogate pair. */
+ if (*s++ != '\\' || *s++ != 'u' || !parse_hex16(&s, &lc))
+ goto failed; /* Incomplete surrogate pair. */
+ if (!from_surrogate_pair(uc, lc, &unicode))
+ goto failed; /* Invalid surrogate pair. */
+ } else if (uc == 0) {
+ /* Disallow "\u0000". */
+ goto failed;
+ } else {
+ unicode = uc;
+ }
+
+ b += utf8_write_char(unicode, b);
+ break;
+ }
+ default:
+ /* Invalid escape */
+ goto failed;
+ }
+ } else if (c <= 0x1F) {
+ /* Control characters are not allowed in string literals. */
+ goto failed;
+ } else {
+ /* Validate and echo a UTF-8 character. */
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+ if (len == 0)
+ goto failed; /* Invalid UTF-8 character. */
+
+ while (len--)
+ *b++ = *s++;
+ }
+
+ /*
+ * Update sb to know about the new bytes,
+ * and set up b to write another character.
+ */
+ if (out) {
+ sb.cur = b;
+ sb_need(&sb, 4);
+ b = sb.cur;
+ } else {
+ b = throwaway_buffer;
+ }
+ }
+ s++;
+
+ if (out)
+ *out = sb_finish(&sb);
+ *sp = s;
+ return true;
+
+failed:
+ if (out)
+ sb_free(&sb);
+ return false;
+}
+
+/*
+ * The JSON spec says that a number shall follow this precise pattern
+ * (spaces and quotes added for readability):
+ * '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
+ *
+ * However, some JSON parsers are more liberal. For instance, PHP accepts
+ * '.5' and '1.'. JSON.parse accepts '+3'.
+ *
+ * This function takes the strict approach.
+ */
+bool parse_number(const char **sp, double *out)
+{
+ const char *s = *sp;
+
+ /* '-'? */
+ if (*s == '-')
+ s++;
+
+ /* (0 | [1-9][0-9]*) */
+ if (*s == '0') {
+ s++;
+ } else {
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ /* ('.' [0-9]+)? */
+ if (*s == '.') {
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ /* ([Ee] [+-]? [0-9]+)? */
+ if (*s == 'E' || *s == 'e') {
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+ if (!is_digit(*s))
+ return false;
+ do {
+ s++;
+ } while (is_digit(*s));
+ }
+
+ if (out)
+ *out = strtod(*sp, NULL);
+
+ *sp = s;
+ return true;
+}
+
+static void skip_space(const char **sp)
+{
+ const char *s = *sp;
+ while (is_space(*s))
+ s++;
+ *sp = s;
+}
+
+static void emit_value(SB *out, const JsonNode *node)
+{
+ assert(tag_is_valid(node->tag));
+ switch (node->tag) {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array(out, node);
+ break;
+ case JSON_OBJECT:
+ emit_object(out, node);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void emit_value_indented(SB *out, const JsonNode *node, const char *space, int indent_level)
+{
+ assert(tag_is_valid(node->tag));
+ switch (node->tag) {
+ case JSON_NULL:
+ sb_puts(out, "null");
+ break;
+ case JSON_BOOL:
+ sb_puts(out, node->bool_ ? "true" : "false");
+ break;
+ case JSON_STRING:
+ emit_string(out, node->string_);
+ break;
+ case JSON_NUMBER:
+ emit_number(out, node->number_);
+ break;
+ case JSON_ARRAY:
+ emit_array_indented(out, node, space, indent_level);
+ break;
+ case JSON_OBJECT:
+ emit_object_indented(out, node, space, indent_level);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+static void emit_array(SB *out, const JsonNode *array)
+{
+ const JsonNode *element;
+
+ sb_putc(out, '[');
+ json_foreach(element, array) {
+ emit_value(out, element);
+ if (element->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, ']');
+}
+
+static void emit_array_indented(SB *out, const JsonNode *array, const char *space, int indent_level)
+{
+ const JsonNode *element = array->children.head;
+ int i;
+
+ if (element == NULL) {
+ sb_puts(out, "[]");
+ return;
+ }
+
+ sb_puts(out, "[\n");
+ while (element != NULL) {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_value_indented(out, element, space, indent_level + 1);
+
+ element = element->next;
+ sb_puts(out, element != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, ']');
+}
+
+static void emit_object(SB *out, const JsonNode *object)
+{
+ const JsonNode *member;
+
+ sb_putc(out, '{');
+ json_foreach(member, object) {
+ emit_string(out, member->key);
+ sb_putc(out, ':');
+ emit_value(out, member);
+ if (member->next != NULL)
+ sb_putc(out, ',');
+ }
+ sb_putc(out, '}');
+}
+
+static void emit_object_indented(SB *out, const JsonNode *object, const char *space, int indent_level)
+{
+ const JsonNode *member = object->children.head;
+ int i;
+
+ if (member == NULL) {
+ sb_puts(out, "{}");
+ return;
+ }
+
+ sb_puts(out, "{\n");
+ while (member != NULL) {
+ for (i = 0; i < indent_level + 1; i++)
+ sb_puts(out, space);
+ emit_string(out, member->key);
+ sb_puts(out, ": ");
+ emit_value_indented(out, member, space, indent_level + 1);
+
+ member = member->next;
+ sb_puts(out, member != NULL ? ",\n" : "\n");
+ }
+ for (i = 0; i < indent_level; i++)
+ sb_puts(out, space);
+ sb_putc(out, '}');
+}
+
+void emit_string(SB *out, const char *str)
+{
+ bool escape_unicode = false;
+ const char *s = str;
+ char *b;
+
+ assert(utf8_validate(str));
+
+ /*
+ * 14 bytes is enough space to write up to two
+ * \uXXXX escapes and two quotation marks.
+ */
+ sb_need(out, 14);
+ b = out->cur;
+
+ *b++ = '"';
+ while (*s != 0) {
+ unsigned char c = *s++;
+
+ /* Encode the next character, and write it to b. */
+ switch (c) {
+ case '"':
+ *b++ = '\\';
+ *b++ = '"';
+ break;
+ case '\\':
+ *b++ = '\\';
+ *b++ = '\\';
+ break;
+ case '\b':
+ *b++ = '\\';
+ *b++ = 'b';
+ break;
+ case '\f':
+ *b++ = '\\';
+ *b++ = 'f';
+ break;
+ case '\n':
+ *b++ = '\\';
+ *b++ = 'n';
+ break;
+ case '\r':
+ *b++ = '\\';
+ *b++ = 'r';
+ break;
+ case '\t':
+ *b++ = '\\';
+ *b++ = 't';
+ break;
+ default: {
+ int len;
+
+ s--;
+ len = utf8_validate_cz(s);
+
+ if (len == 0) {
+ /*
+ * Handle invalid UTF-8 character gracefully in production
+ * by writing a replacement character (U+FFFD)
+ * and skipping a single byte.
+ *
+ * This should never happen when assertions are enabled
+ * due to the assertion at the beginning of this function.
+ */
+ assert(false);
+ if (escape_unicode) {
+ strcpy(b, "\\uFFFD");
+ b += 6;
+ } else {
+ *b++ = (char)0xEF;
+ *b++ = (char)0xBF;
+ *b++ = (char)0xBD;
+ }
+ s++;
+ } else if (c < 0x1F || (c >= 0x80 && escape_unicode)) {
+ /* Encode using \u.... */
+ uint32_t unicode;
+
+ s += utf8_read_char(s, &unicode);
+
+ if (unicode <= 0xFFFF) {
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, unicode);
+ } else {
+ /* Produce a surrogate pair. */
+ uint16_t uc, lc;
+ assert(unicode <= 0x10FFFF);
+ to_surrogate_pair(unicode, &uc, &lc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, uc);
+ *b++ = '\\';
+ *b++ = 'u';
+ b += write_hex16(b, lc);
+ }
+ } else {
+ /* Write the character directly. */
+ while (len--)
+ *b++ = *s++;
+ }
+
+ break;
+ }
+ }
+
+ /*
+ * Update *out to know about the new bytes,
+ * and set up b to write another encoded character.
+ */
+ out->cur = b;
+ sb_need(out, 14);
+ b = out->cur;
+ }
+ *b++ = '"';
+
+ out->cur = b;
+}
+
+static void emit_number(SB *out, double num)
+{
+ /*
+ * This isn't exactly how JavaScript renders numbers,
+ * but it should produce valid JSON for reasonable numbers
+ * preserve precision well enough, and avoid some oddities
+ * like 0.3 -> 0.299999999999999988898 .
+ */
+ char buf[64];
+ sprintf(buf, "%.16g", num);
+
+ if (number_is_valid(buf))
+ sb_puts(out, buf);
+ else
+ sb_puts(out, "null");
+}
+
+static bool tag_is_valid(unsigned int tag)
+{
+ return (/* tag >= JSON_NULL && */ tag <= JSON_OBJECT);
+}
+
+static bool number_is_valid(const char *num)
+{
+ return (parse_number(&num, NULL) && *num == '\0');
+}
+
+static bool expect_literal(const char **sp, const char *str)
+{
+ const char *s = *sp;
+
+ while (*str != '\0')
+ if (*s++ != *str++)
+ return false;
+
+ *sp = s;
+ return true;
+}
+
+/*
+ * Parses exactly 4 hex characters (capital or lowercase).
+ * Fails if any input chars are not [0-9A-Fa-f].
+ */
+static bool parse_hex16(const char **sp, uint16_t *out)
+{
+ const char *s = *sp;
+ uint16_t ret = 0;
+ uint16_t i;
+ uint16_t tmp;
+ char c;
+
+ for (i = 0; i < 4; i++) {
+ c = *s++;
+ if (c >= '0' && c <= '9')
+ tmp = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ tmp = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ tmp = c - 'a' + 10;
+ else
+ return false;
+
+ ret <<= 4;
+ ret += tmp;
+ }
+
+ if (out)
+ *out = ret;
+ *sp = s;
+ return true;
+}
+
+/*
+ * Encodes a 16-bit number into hexadecimal,
+ * writing exactly 4 hex chars.
+ */
+static int write_hex16(char *out, uint16_t val)
+{
+ const char *hex = "0123456789ABCDEF";
+
+ *out++ = hex[(val >> 12) & 0xF];
+ *out++ = hex[(val >> 8) & 0xF];
+ *out++ = hex[(val >> 4) & 0xF];
+ *out++ = hex[ val & 0xF];
+
+ return 4;
+}
+
+bool json_check(const JsonNode *node, char errmsg[256])
+{
+ #define problem(...) do { \
+ if (errmsg != NULL) \
+ snprintf(errmsg, 256, __VA_ARGS__); \
+ return false; \
+ } while (0)
+
+ if (node->key != NULL && !utf8_validate(node->key))
+ problem("key contains invalid UTF-8");
+
+ if (!tag_is_valid(node->tag))
+ problem("tag is invalid (%u)", node->tag);
+
+ if (node->tag == JSON_BOOL) {
+ if (node->bool_ != false && node->bool_ != true)
+ problem("bool_ is neither false (%d) nor true (%d)", (int)false, (int)true);
+ } else if (node->tag == JSON_STRING) {
+ if (node->string_ == NULL)
+ problem("string_ is NULL");
+ if (!utf8_validate(node->string_))
+ problem("string_ contains invalid UTF-8");
+ } else if (node->tag == JSON_ARRAY || node->tag == JSON_OBJECT) {
+ JsonNode *head = node->children.head;
+ JsonNode *tail = node->children.tail;
+
+ if (head == NULL || tail == NULL) {
+ if (head != NULL)
+ problem("tail is NULL, but head is not");
+ if (tail != NULL)
+ problem("head is NULL, but tail is not");
+ } else {
+ JsonNode *child;
+ JsonNode *last = NULL;
+
+ if (head->prev != NULL)
+ problem("First child's prev pointer is not NULL");
+
+ for (child = head; child != NULL; last = child, child = child->next) {
+ if (child == node)
+ problem("node is its own child");
+ if (child->next == child)
+ problem("child->next == child (cycle)");
+ if (child->next == head)
+ problem("child->next == head (cycle)");
+
+ if (child->parent != node)
+ problem("child does not point back to parent");
+ if (child->next != NULL && child->next->prev != child)
+ problem("child->next does not point back to child");
+
+ if (node->tag == JSON_ARRAY && child->key != NULL)
+ problem("Array element's key is not NULL");
+ if (node->tag == JSON_OBJECT && child->key == NULL)
+ problem("Object member's key is NULL");
+
+ if (!json_check(child, errmsg))
+ return false;
+ }
+
+ if (last != tail)
+ problem("tail does not match pointer found by starting at head and following next links");
+ }
+ }
+
+ return true;
+
+ #undef problem
+}
diff --git a/contrib/ccan/json/json.h b/contrib/ccan/json/json.h
new file mode 100644
index 0000000..ed5255e
--- /dev/null
+++ b/contrib/ccan/json/json.h
@@ -0,0 +1,117 @@
+/*
+ Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
+ All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef CCAN_JSON_H
+#define CCAN_JSON_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef enum {
+ JSON_NULL,
+ JSON_BOOL,
+ JSON_STRING,
+ JSON_NUMBER,
+ JSON_ARRAY,
+ JSON_OBJECT,
+} JsonTag;
+
+typedef struct JsonNode JsonNode;
+
+struct JsonNode
+{
+ /* only if parent is an object or array (NULL otherwise) */
+ JsonNode *parent;
+ JsonNode *prev, *next;
+
+ /* only if parent is an object (NULL otherwise) */
+ char *key; /* Must be valid UTF-8. */
+
+ JsonTag tag;
+ union {
+ /* JSON_BOOL */
+ bool bool_;
+
+ /* JSON_STRING */
+ char *string_; /* Must be valid UTF-8. */
+
+ /* JSON_NUMBER */
+ double number_;
+
+ /* JSON_ARRAY */
+ /* JSON_OBJECT */
+ struct {
+ JsonNode *head, *tail;
+ } children;
+ };
+};
+
+/*** Encoding, decoding, and validation ***/
+
+JsonNode *json_decode (const char *json);
+char *json_encode (const JsonNode *node);
+char *json_encode_string (const char *str);
+char *json_stringify (const JsonNode *node, const char *space);
+void json_delete (JsonNode *node);
+
+bool json_validate (const char *json);
+
+/*** Lookup and traversal ***/
+
+JsonNode *json_find_element (JsonNode *array, int index);
+JsonNode *json_find_member (JsonNode *object, const char *key);
+
+JsonNode *json_first_child (const JsonNode *node);
+
+#define json_foreach(i, object_or_array) \
+ for ((i) = json_first_child(object_or_array); \
+ (i) != NULL; \
+ (i) = (i)->next)
+
+/*** Construction and manipulation ***/
+
+JsonNode *json_mknull(void);
+JsonNode *json_mkbool(bool b);
+JsonNode *json_mkstring(const char *s);
+JsonNode *json_mknumber(double n);
+JsonNode *json_mkarray(void);
+JsonNode *json_mkobject(void);
+
+void json_append_element(JsonNode *array, JsonNode *element);
+void json_prepend_element(JsonNode *array, JsonNode *element);
+void json_append_member(JsonNode *object, const char *key, JsonNode *value);
+void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
+
+void json_remove_from_parent(JsonNode *node);
+
+/*** Debugging ***/
+
+/*
+ * Look for structure and encoding problems in a JsonNode or its descendents.
+ *
+ * If a problem is detected, return false, writing a description of the problem
+ * to errmsg (unless errmsg is NULL).
+ */
+bool json_check(const JsonNode *node, char errmsg[256]);
+
+#endif
diff --git a/contrib/ccan/json/test/common.h b/contrib/ccan/json/test/common.h
new file mode 100644
index 0000000..328cb73
--- /dev/null
+++ b/contrib/ccan/json/test/common.h
@@ -0,0 +1,18 @@
+#include <ccan/json/json.c>
+#include <ccan/tap/tap.h>
+
+#include <errno.h>
+#include <string.h>
+
+static char *chomp(char *s)
+{
+ char *e;
+
+ if (s == NULL || *s == 0)
+ return s;
+
+ e = strchr(s, 0);
+ if (e[-1] == '\n')
+ *--e = 0;
+ return s;
+}
diff --git a/contrib/ccan/json/test/run-construction.c b/contrib/ccan/json/test/run-construction.c
new file mode 100644
index 0000000..cc9a395
--- /dev/null
+++ b/contrib/ccan/json/test/run-construction.c
@@ -0,0 +1,191 @@
+/* Build a list of numbers with various appends and prepends, verify them by testing against their encoded value, do pointer consistency checks each time, do element lookups, and remove items as well. */
+
+#include "common.h"
+
+#define should_be(var, expected) should_be_(var, #var, expected)
+
+static void should_be_(const JsonNode *node, const char *name, const char *expected)
+{
+ char errmsg[256];
+ char *encoded;
+
+ if (!json_check(node, errmsg)) {
+ fail("Invariants check failed: %s", errmsg);
+ return;
+ }
+
+ encoded = json_encode(node);
+
+ if (strcmp(encoded, expected) == 0)
+ pass("%s is %s", name, expected);
+ else
+ fail("%s should be %s, but is actually %s", name, expected, encoded);
+
+ free(encoded);
+}
+
+static void test_string(void)
+{
+ JsonNode *str;
+
+ str = json_mkstring("Hello\tworld!\n\001");
+ should_be(str, "\"Hello\\tworld!\\n\\u0001\"");
+ json_delete(str);
+
+ str = json_mkstring("\"\\\b\f\n\r\t");
+ should_be(str, "\"\\\"\\\\\\b\\f\\n\\r\\t\"");
+ json_delete(str);
+}
+
+static void test_number(void)
+{
+ JsonNode *num;
+
+ num = json_mknumber(5678901234.0);
+ should_be(num, "5678901234");
+ json_delete(num);
+
+ num = json_mknumber(-5678901234.0);
+ should_be(num, "-5678901234");
+ json_delete(num);
+
+ num = json_mknumber(0.0 / 0.0);
+ should_be(num, "null");
+ json_delete(num);
+}
+
+static void test_array(void)
+{
+ JsonNode *array;
+ JsonNode *children[5 + 1];
+
+ array = json_mkarray();
+ should_be(array, "[]");
+
+ children[1] = json_mknumber(1);
+ children[2] = json_mknumber(2);
+ children[3] = json_mknumber(3);
+ children[4] = json_mknumber(4);
+ children[5] = json_mknumber(5);
+
+ json_append_element(array, children[3]);
+ should_be(array, "[3]");
+
+ json_remove_from_parent(children[3]);
+ should_be(array, "[]");
+
+ json_prepend_element(array, children[3]);
+ should_be(array, "[3]");
+
+ json_prepend_element(array, children[2]);
+ should_be(array, "[2,3]");
+
+ json_append_element(array, children[4]);
+ should_be(array, "[2,3,4]");
+
+ json_delete(children[3]);
+ should_be(array, "[2,4]");
+
+ json_prepend_element(array, children[1]);
+ should_be(array, "[1,2,4]");
+
+ json_delete(children[1]);
+ should_be(array, "[2,4]");
+
+ json_delete(children[4]);
+ should_be(array, "[2]");
+
+ ok1(json_find_element(array, 0) == children[2]);
+ ok1(json_find_element(array, -1) == NULL);
+ ok1(json_find_element(array, 1) == NULL);
+
+ json_append_element(array, children[5]);
+ should_be(array, "[2,5]");
+
+ ok1(json_find_element(array, 0) == children[2]);
+ ok1(json_find_element(array, 1) == children[5]);
+ ok1(json_find_element(array, -1) == NULL);
+ ok1(json_find_element(array, 2) == NULL);
+
+ json_delete(children[2]);
+ json_delete(children[5]);
+ should_be(array, "[]");
+
+ ok1(json_find_element(array, -1) == NULL);
+ ok1(json_find_element(array, 0) == NULL);
+ ok1(json_find_element(array, 1) == NULL);
+
+ json_delete(array);
+}
+
+static void test_object(void)
+{
+ JsonNode *object;
+ JsonNode *children[5 + 1];
+
+ object = json_mkobject();
+ should_be(object, "{}");
+
+ children[1] = json_mknumber(1);
+ children[2] = json_mknumber(2);
+ children[3] = json_mknumber(3);
+
+ ok1(json_find_member(object, "one") == NULL);
+ ok1(json_find_member(object, "two") == NULL);
+ ok1(json_find_member(object, "three") == NULL);
+
+ json_append_member(object, "one", children[1]);
+ should_be(object, "{\"one\":1}");
+
+ ok1(json_find_member(object, "one") == children[1]);
+ ok1(json_find_member(object, "two") == NULL);
+ ok1(json_find_member(object, "three") == NULL);
+
+ json_prepend_member(object, "two", children[2]);
+ should_be(object, "{\"two\":2,\"one\":1}");
+
+ ok1(json_find_member(object, "one") == children[1]);
+ ok1(json_find_member(object, "two") == children[2]);
+ ok1(json_find_member(object, "three") == NULL);
+
+ json_append_member(object, "three", children[3]);
+ should_be(object, "{\"two\":2,\"one\":1,\"three\":3}");
+
+ ok1(json_find_member(object, "one") == children[1]);
+ ok1(json_find_member(object, "two") == children[2]);
+ ok1(json_find_member(object, "three") == children[3]);
+
+ json_delete(object);
+}
+
+int main(void)
+{
+ JsonNode *node;
+
+ (void) chomp;
+
+ plan_tests(49);
+
+ ok1(json_find_element(NULL, 0) == NULL);
+ ok1(json_find_member(NULL, "") == NULL);
+ ok1(json_first_child(NULL) == NULL);
+
+ node = json_mknull();
+ should_be(node, "null");
+ json_delete(node);
+
+ node = json_mkbool(false);
+ should_be(node, "false");
+ json_delete(node);
+
+ node = json_mkbool(true);
+ should_be(node, "true");
+ json_delete(node);
+
+ test_string();
+ test_number();
+ test_array();
+ test_object();
+
+ return exit_status();
+}
diff --git a/contrib/ccan/json/test/run-decode-encode.c b/contrib/ccan/json/test/run-decode-encode.c
new file mode 100644
index 0000000..6bdf7c3
--- /dev/null
+++ b/contrib/ccan/json/test/run-decode-encode.c
@@ -0,0 +1,77 @@
+#include "common.h"
+
+int main(void)
+{
+ const char *strings_file = "test/test-strings";
+ const char *strings_reencoded_file = "test/test-strings-reencoded";
+ FILE *f, *f2;
+ char buffer[1024], buffer2[1024];
+
+ plan_tests(90);
+
+ f = fopen(strings_file, "rb");
+ if (f == NULL) {
+ diag("Could not open %s: %s", strings_file, strerror(errno));
+ return 1;
+ }
+ f2 = fopen(strings_reencoded_file, "rb");
+ if (f2 == NULL) {
+ diag("Could not open %s: %s", strings_reencoded_file, strerror(errno));
+ return 1;
+ }
+
+ while (fgets(buffer, sizeof(buffer), f)) {
+ const char *s = chomp(buffer);
+ bool valid;
+ JsonNode *node;
+
+ if (expect_literal(&s, "valid ")) {
+ valid = true;
+ } else if (expect_literal(&s, "invalid ")) {
+ valid = false;
+ } else {
+ fail("Invalid line in test-strings: %s", buffer);
+ continue;
+ }
+
+ node = json_decode(s);
+
+ if (valid) {
+ char *reencoded;
+ char errmsg[256];
+
+ if (node == NULL) {
+ fail("%s is valid, but json_decode returned NULL", s);
+ continue;
+ }
+
+ if (!json_check(node, errmsg)) {
+ fail("Corrupt tree produced by json_decode: %s", errmsg);
+ continue;
+ }
+
+ reencoded = json_encode(node);
+
+ if (!fgets(buffer2, sizeof(buffer2), f2)) {
+ fail("test-strings-reencoded is missing this line: %s", reencoded);
+ continue;
+ }
+ chomp(buffer2);
+
+ ok(strcmp(reencoded, buffer2) == 0, "re-encode %s -> %s", s, reencoded);
+
+ free(reencoded);
+ json_delete(node);
+ } else if (node != NULL) {
+ fail("%s is invalid, but json_decode returned non-NULL", s);
+ continue;
+ }
+ }
+
+ if (ferror(f) || fclose(f) != 0 || ferror(f2) || fclose(f2) != 0) {
+ diag("I/O error reading test data.");
+ return 1;
+ }
+
+ return exit_status();
+}
diff --git a/contrib/ccan/json/test/run-stringify.c b/contrib/ccan/json/test/run-stringify.c
new file mode 100644
index 0000000..3a4cb73
--- /dev/null
+++ b/contrib/ccan/json/test/run-stringify.c
@@ -0,0 +1,108 @@
+#include "common.h"
+
+static char buf1[256], buf2[256];
+
+/* Used for pass and fail messages */
+static char *quote_string(const char *str, char buf[256])
+{
+ char *out = buf;
+
+ *out++ = '"';
+ for (; *str != 0; str++) {
+ if (out - buf > 256 - 5) {
+ /* String is too long. End it with `...' */
+ out = buf + 256 - 5;
+ *out++ = '.';
+ *out++ = '.';
+ *out++ = '.';
+ break;
+ }
+ switch (*str) {
+ case '\t':
+ *out++ = '\\';
+ *out++ = 't';
+ break;
+ case '\n':
+ *out++ = '\\';
+ *out++ = 'n';
+ break;
+ case '"':
+ *out++ = '\\';
+ *out++ = '"';
+ break;
+ case '\\':
+ *out++ = '\\';
+ *out++ = '\\';
+ break;
+ default:
+ *out++ = *str;
+ break;
+ }
+ }
+ *out++ = '"';
+
+ *out = 0;
+ return buf;
+}
+
+static void test_stringify(const char *input, const char *expected)
+{
+ JsonNode *node = NULL;
+ char *enc = NULL;
+ char *strn = NULL;
+ char *str = NULL;
+
+ node = json_decode(input);
+ if (node == NULL) {
+ fail("Failed to decode %s", input);
+ goto end;
+ }
+
+ enc = json_encode(node);
+ if (strcmp(enc, input) != 0) {
+ fail("%s re-encodes to %s. Either encode/decode is broken, or the input string needs to be normalized", input, enc);
+ goto end;
+ }
+
+ strn = json_stringify(node, NULL);
+ if (strcmp(strn, enc) != 0) {
+ fail("json_stringify with NULL space produced a different string than json_encode");
+ goto end;
+ }
+
+ str = json_stringify(node, "\t");
+ if (strcmp(str, expected) != 0) {
+ fail("Expected %s, but json_stringify produced %s",
+ quote_string(expected, buf1), quote_string(str, buf2));
+ goto end;
+ }
+
+ pass("stringify %s", input);
+
+end:
+ json_delete(node);
+ free(enc);
+ free(strn);
+ free(str);
+}
+
+int main(void)
+{
+ (void) chomp;
+
+ plan_tests(9);
+
+ test_stringify("[]", "[]");
+ test_stringify("[1]", "[\n\t1\n]");
+ test_stringify("[1,2,3]", "[\n\t1,\n\t2,\n\t3\n]");
+ test_stringify("[[]]", "[\n\t[]\n]");
+ test_stringify("[[1,2],[3,4]]", "[\n\t[\n\t\t1,\n\t\t2\n\t],\n\t[\n\t\t3,\n\t\t4\n\t]\n]");
+
+ test_stringify("{}", "{}");
+ test_stringify("{\"one\":1}", "{\n\t\"one\": 1\n}");
+ test_stringify("{\"one\":1,\"t*\":[2,3,10]}", "{\n\t\"one\": 1,\n\t\"t*\": [\n\t\t2,\n\t\t3,\n\t\t10\n\t]\n}");
+ test_stringify("{\"a\":{\"1\":1,\"2\":2},\"b\":{\"3\":[null,false,true,\"\\f\"]}}",
+ "{\n\t\"a\": {\n\t\t\"1\": 1,\n\t\t\"2\": 2\n\t},\n\t\"b\": {\n\t\t\"3\": [\n\t\t\tnull,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\t\"\\f\"\n\t\t]\n\t}\n}");
+
+ return exit_status();
+}
diff --git a/contrib/ccan/json/test/run-validate.c b/contrib/ccan/json/test/run-validate.c
new file mode 100644
index 0000000..f7bb3b0
--- /dev/null
+++ b/contrib/ccan/json/test/run-validate.c
@@ -0,0 +1,49 @@
+#include "common.h"
+
+int main(void)
+{
+ const char *strings_file = "test/test-strings";
+ FILE *f;
+ char buffer[1024];
+
+ plan_tests(224);
+
+ f = fopen(strings_file, "rb");
+ if (f == NULL) {
+ diag("Could not open %s: %s", strings_file, strerror(errno));
+ return 1;
+ }
+
+ while (fgets(buffer, sizeof(buffer), f)) {
+ const char *s = chomp(buffer);
+ bool valid;
+
+ if (expect_literal(&s, "valid ")) {
+ valid = true;
+ } else if (expect_literal(&s, "invalid ")) {
+ valid = false;
+ } else {
+ fail("Invalid line in test-strings: %s", buffer);
+ continue;
+ }
+
+ if (strcmp(s, "\"1\\u2\"") == 0)
+ puts("here");
+
+ if (json_validate(s) == valid) {
+ pass("%s %s", valid ? "valid" : "invalid", s);
+ } else {
+ fail("%s is %s, but json_validate returned %s",
+ s,
+ valid ? "valid" : "invalid",
+ valid ? "false" : "true");
+ }
+ }
+
+ if (ferror(f) || fclose(f) != 0) {
+ diag("I/O error reading test strings.");
+ return 1;
+ }
+
+ return exit_status();
+}
diff --git a/contrib/ccan/json/test/test-strings b/contrib/ccan/json/test/test-strings
new file mode 100644
index 0000000..439be7d
--- /dev/null
+++ b/contrib/ccan/json/test/test-strings
@@ -0,0 +1,224 @@
+invalid
+invalid
+invalid "
+invalid [,]
+invalid [)
+invalid []]
+invalid [}
+invalid {,}
+invalid {]
+invalid ["1":2]
+invalid [1,2,]
+invalid [1:2}
+invalid {"1":2,}
+invalid {1:2}
+invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7 ]}]}
+invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7]}]}
+invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]
+invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]]
+invalid {"1":2, "3":4
+invalid "1\u2"
+invalid [,2]
+invalid "3
+invalid "3" "4"
+invalid [3[4]
+invalid [3[4]]
+invalid [3, [4, [5], 6] 7, 8 9]
+invalid [3, [4, [5], 6] 7, 8, 9]
+invalid [3, [4, [5], 6], 7, 8 9]
+invalid {"hello":true, "bye":false, null}
+invalid {"hello":true, "bye":false, null:null}
+invalid "hi
+invalid "hi"""
+invalid {"hi": "bye"]
+invalid "\uD800\uD800"
+invalid "\uD800\uDBFF"
+invalid "\UD834\UDD1E"
+invalid "\uDB00"
+invalid "\uDB00\uDBFF"
+valid "\uFFFE"
+valid "\uFFFF"
+invalid .
+valid ""
+valid []
+valid {}
+invalid +.
+valid 0.5
+invalid 0.e1
+valid {"1":{}}
+valid {"1":2}
+valid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"]}]}
+valid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]}
+valid 1234
+valid -1234
+valid {"1":2, "3":4}
+invalid +1234
+invalid ++1234
+valid 123.456e142
+valid 123.456e-142
+valid 123.456e+142
+invalid 123.e-142
+valid "1\u2000"
+valid "1\u20001"
+valid 2
+invalid .246e-142
+invalid .2e-142
+valid 3
+invalid .3
+valid "3"
+valid [3]
+invalid +3.
+valid 3.2e+1
+valid [3, [4]]
+valid [3, [4, [5]]]
+valid [3, [4, [5], 6]]
+valid [3, [4, [5], 6], 7]
+valid [3, [4, [5], 6], 7, 8]
+valid [3, [4, [5], 6], 7, 8, 9]
+invalid +3.5
+invalid .3e
+invalid .3e1
+invalid .3e-1
+invalid .3e+1
+invalid 3.e1
+invalid 3.e+1
+valid 3e+1
+invalid .5
+invalid +.5
+invalid .5e+1
+valid [ 7]
+valid [7 ]
+valid [7]
+invalid .e-14234
+valid "hello"
+valid ["hello"]
+valid ["hello", "bye"]
+valid ["hello", "bye\n"]
+valid ["hello", "bye\n\r\t"]
+valid ["hello", "bye\n\r\t\b"]
+valid ["hello", "bye\n\r\t\b",true]
+valid ["hello", "bye\n\r\t\b",true , false]
+valid ["hello", "bye\n\r\t\b",true , false, null]
+invalid ["hello", "bye\n\r\t\v"]
+valid {"hello":true}
+valid {"hello":true, "bye":false}
+valid {"hello":true, "bye":false, "foo":["one","two","three"]}
+valid "hi"
+valid ["hi"]
+valid ["hi", "bye"]
+valid {"hi": "bye"}
+valid ["hi", "bye", 3]
+valid ["hi", "bye[", 3]
+valid "\u0007"
+valid "\u0008"
+valid "\u0009"
+valid "\u0010"
+valid "\u0020"
+valid "\u10000"
+valid "\u1234"
+valid "\u99999"
+valid "\ud800\udc00"
+valid "\uD800\uDC00"
+valid "\uD834\uDD1E"
+valid "\uDBFF\uDFFF"
+valid "\uFFFD"
+valid "\uFFFF"
+invalid hello
+valid [32, 1]
+invalid [32,
+valid "\uD800\uDC00"
+valid "\n"
+valid "hello"
+valid "hello\u0009world"
+valid "hello"
+valid "hello\n"
+valid "hello"
+valid 3
+invalid 3.
+invalid .3
+valid 0.3
+invalid 0.3e
+invalid 0.3e+
+valid 0.3e+5
+valid 0.3e-5
+valid 0.3e5
+valid "hello"
+invalid +3
+valid -3
+invalid -3.
+valid -3.1
+invalid .5
+invalid 5.
+invalid 5.e1
+valid 0.5
+invalid .3e1
+invalid .3e+1
+invalid .3e-1
+invalid .3e-1 .5
+invalid .3e-1.5
+invalid .3e+1.5
+invalid .3e+.
+invalid .3e+.5
+invalid .3e+1.5
+invalid 9.3e+1.5
+invalid 9.e+1.5
+invalid 9.e+
+invalid 9.e+1
+valid "\""
+valid "\"3.5"
+valid "\"."
+invalid "\".".
+valid "\"....."
+invalid "\"\"\"\"""
+invalid ["\"\"\"\"", .5]
+invalid [.5]
+valid ["\"\"\"\"", 0.5]
+invalid ["\"\"\"\"", .5]
+invalid ["\"\"\"\"",.5]
+invalid ["\"",.5]
+invalid ["\".5",.5]
+invalid ["\".5",".5\"".5]
+invalid ["\".5",".5\"", .5]
+invalid ["\".5",".5\"",.5]
+valid ["\".5",".5\"",0.5]
+invalid {"key":/*comment*/"value"}
+invalid {"key":/*comment"value"}
+invalid {"key":"value"}/*
+invalid {"key":"value"}/**/
+invalid {"key":"value"}/***/
+invalid {"key":"value"}/**//
+invalid {"key":"value"}/**///
+invalid {"key":"value"}/**///----
+invalid {"key":"value"}#
+invalid {"key":"value"}#{
+invalid {"key":"value"}#{}
+invalid {"key":"value"}#,
+invalid {"key":"value"/**/, "k2":"v2"}
+valid "\u0027"
+invalid "hello\'"
+invalid 'hello\''
+invalid 'hello'
+invalid 'hell\'o'
+invalid '\'hello'
+invalid '\'hello\''
+invalid \'hello\'
+invalid 'hello\'
+invalid ['hello\']
+invalid ['hello\'']
+invalid ['hello"']
+invalid ['hello\"']
+invalid ['hello"o']
+invalid ['"']
+invalid '"'
+invalid '"hello"'
+invalid '"hello'
+invalid '"hi"'
+valid [ 1 , 2 , 3 ]
+invalid nil
+invalid fals
+invalid falsify
+invalid falsetto
+invalid truism
+invalid {"key"
+invalid {"key","key2":value}
+invalid "\u0000"
diff --git a/contrib/ccan/json/test/test-strings-reencoded b/contrib/ccan/json/test/test-strings-reencoded
new file mode 100644
index 0000000..97890c1
--- /dev/null
+++ b/contrib/ccan/json/test/test-strings-reencoded
@@ -0,0 +1,90 @@
+"￾"
+"ï¿¿"
+""
+[]
+{}
+0.5
+{"1":{}}
+{"1":2}
+{"1":2,"2.5":[3,4,{},{"5":["6"]}]}
+{"1":2,"2.5":[3,4,{},{"5":["6"],"7":[8]}]}
+1234
+-1234
+{"1":2,"3":4}
+1.23456e+144
+1.23456e-140
+1.23456e+144
+"1 "
+"1 1"
+2
+3
+"3"
+[3]
+32
+[3,[4]]
+[3,[4,[5]]]
+[3,[4,[5],6]]
+[3,[4,[5],6],7]
+[3,[4,[5],6],7,8]
+[3,[4,[5],6],7,8,9]
+30
+[7]
+[7]
+[7]
+"hello"
+["hello"]
+["hello","bye"]
+["hello","bye\n"]
+["hello","bye\n\r\t"]
+["hello","bye\n\r\t\b"]
+["hello","bye\n\r\t\b",true]
+["hello","bye\n\r\t\b",true,false]
+["hello","bye\n\r\t\b",true,false,null]
+{"hello":true}
+{"hello":true,"bye":false}
+{"hello":true,"bye":false,"foo":["one","two","three"]}
+"hi"
+["hi"]
+["hi","bye"]
+{"hi":"bye"}
+["hi","bye",3]
+["hi","bye[",3]
+"\u0007"
+"\b"
+"\t"
+"\u0010"
+" "
+"က0"
+"ሴ"
+"香9"
+"ð€€"
+"ð€€"
+"ð„ž"
+"ô¿¿"
+"�"
+"ï¿¿"
+[32,1]
+"ð€€"
+"\n"
+"hello"
+"hello\tworld"
+"hello"
+"hello\n"
+"hello"
+3
+0.3
+30000
+3e-06
+30000
+"hello"
+-3
+-3.1
+0.5
+"\""
+"\"3.5"
+"\"."
+"\"....."
+["\"\"\"\"",0.5]
+["\".5",".5\"",0.5]
+"'"
+[1,2,3]
diff --git a/contrib/cleanup.h b/contrib/cleanup.h
new file mode 100644
index 0000000..55843f1
--- /dev/null
+++ b/contrib/cleanup.h
@@ -0,0 +1,37 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+/**
+ * Cleanup attributes.
+ * @cond internal
+ */
+#pragma once
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define auto_free __attribute__((cleanup(_cleanup_free)))
+static inline void _cleanup_free(char **p) {
+ free(*p);
+}
+#define auto_close __attribute__((cleanup(_cleanup_close)))
+static inline void _cleanup_close(int *p) {
+ if (*p > 0) close(*p);
+}
+#define auto_fclose __attribute__((cleanup(_cleanup_fclose)))
+static inline void _cleanup_fclose(FILE **p) {
+ if (*p) fclose(*p);
+}
+/* @endcond */
diff --git a/contrib/config.h b/contrib/config.h
new file mode 100644
index 0000000..c655374
--- /dev/null
+++ b/contrib/config.h
@@ -0,0 +1,6 @@
+/* Dummy file, no real configuration here */
+#define HAVE_ATTRIBUTE_COLD 1
+#define HAVE_ATTRIBUTE_NORETURN 1
+#define HAVE_ATTRIBUTE_PURE 1
+#define HAVE_ATTRIBUTE_UNUSED 1
+#define HAVE_ATTRIBUTE_NONNULL 1
diff --git a/contrib/contrib.mk b/contrib/contrib.mk
new file mode 100644
index 0000000..c8be024
--- /dev/null
+++ b/contrib/contrib.mk
@@ -0,0 +1,22 @@
+contrib_SOURCES := \
+ contrib/ccan/asprintf/asprintf.c \
+ contrib/ccan/ilog/ilog.c \
+ contrib/ccan/json/json.c \
+ contrib/ucw/mempool.c \
+ contrib/ucw/mempool-fmt.c \
+ contrib/murmurhash3/murmurhash3.c \
+ contrib/base32hex.c \
+ contrib/base64.c
+contrib_CFLAGS := -fPIC
+contrib_TARGET := $(abspath contrib)/contrib$(AREXT)
+
+# Use built-in LMDB if not found
+ifneq ($(HAS_lmdb), yes)
+contrib_SOURCES += contrib/lmdb/mdb.c \
+ contrib/lmdb/midl.c
+contrib_CFLAGS += -pthread
+contrib_LIBS += -pthread
+lmdb_CFLAGS += -I$(abspath contrib/lmdb)
+endif
+
+$(eval $(call make_static,contrib,contrib))
diff --git a/contrib/licenses/BSD-MIT b/contrib/licenses/BSD-MIT
new file mode 100644
index 0000000..89de354
--- /dev/null
+++ b/contrib/licenses/BSD-MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/contrib/licenses/CC0 b/contrib/licenses/CC0
new file mode 100644
index 0000000..feb9b11
--- /dev/null
+++ b/contrib/licenses/CC0
@@ -0,0 +1,28 @@
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
+
+ the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
+ moral rights retained by the original author(s) and/or performer(s);
+ publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
+ rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
+ rights protecting the extraction, dissemination, use and reuse of data in a Work;
+ database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
+ other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
+ Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
+ Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
+ Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
diff --git a/contrib/licenses/LGPL2 b/contrib/licenses/LGPL2
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/contrib/licenses/LGPL2
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/contrib/lmdb/LICENSE b/contrib/lmdb/LICENSE
new file mode 100644
index 0000000..05ad757
--- /dev/null
+++ b/contrib/lmdb/LICENSE
@@ -0,0 +1,47 @@
+The OpenLDAP Public License
+ Version 2.8, 17 August 2003
+
+Redistribution and use of this software and associated documentation
+("Software"), with or without modification, are permitted provided
+that the following conditions are met:
+
+1. Redistributions in source form must retain copyright statements
+ and notices,
+
+2. Redistributions in binary form must reproduce applicable copyright
+ statements and notices, this list of conditions, and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution, and
+
+3. Redistributions must contain a verbatim copy of this document.
+
+The OpenLDAP Foundation may revise this license from time to time.
+Each revision is distinguished by a version number. You may use
+this Software under terms of this license revision or under the
+terms of any subsequent revision of the license.
+
+THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+CONTRIBUTORS ``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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+OR OWNER(S) OF THE SOFTWARE 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.
+
+The names of the authors and copyright holders must not be used in
+advertising or otherwise to promote the sale, use or other dealing
+in this Software without specific, written prior permission. Title
+to copyright in this Software shall at all times remain with copyright
+holders.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
+California, USA. All Rights Reserved. Permission to copy and
+distribute verbatim copies of this document is granted.
diff --git a/contrib/lmdb/lmdb.h b/contrib/lmdb/lmdb.h
new file mode 100644
index 0000000..29135b7
--- /dev/null
+++ b/contrib/lmdb/lmdb.h
@@ -0,0 +1,1604 @@
+/** @file lmdb.h
+ * @brief Lightning memory-mapped database library
+ *
+ * @mainpage Lightning Memory-Mapped Database Manager (LMDB)
+ *
+ * @section intro_sec Introduction
+ * LMDB is a Btree-based database management library modeled loosely on the
+ * BerkeleyDB API, but much simplified. The entire database is exposed
+ * in a memory map, and all data fetches return data directly
+ * from the mapped memory, so no malloc's or memcpy's occur during
+ * data fetches. As such, the library is extremely simple because it
+ * requires no page caching layer of its own, and it is extremely high
+ * performance and memory-efficient. It is also fully transactional with
+ * full ACID semantics, and when the memory map is read-only, the
+ * database integrity cannot be corrupted by stray pointer writes from
+ * application code.
+ *
+ * The library is fully thread-aware and supports concurrent read/write
+ * access from multiple processes and threads. Data pages use a copy-on-
+ * write strategy so no active data pages are ever overwritten, which
+ * also provides resistance to corruption and eliminates the need of any
+ * special recovery procedures after a system crash. Writes are fully
+ * serialized; only one write transaction may be active at a time, which
+ * guarantees that writers can never deadlock. The database structure is
+ * multi-versioned so readers run with no locks; writers cannot block
+ * readers, and readers don't block writers.
+ *
+ * Unlike other well-known database mechanisms which use either write-ahead
+ * transaction logs or append-only data writes, LMDB requires no maintenance
+ * during operation. Both write-ahead loggers and append-only databases
+ * require periodic checkpointing and/or compaction of their log or database
+ * files otherwise they grow without bound. LMDB tracks free pages within
+ * the database and re-uses them for new write operations, so the database
+ * size does not grow without bound in normal use.
+ *
+ * The memory map can be used as a read-only or read-write map. It is
+ * read-only by default as this provides total immunity to corruption.
+ * Using read-write mode offers much higher write performance, but adds
+ * the possibility for stray application writes thru pointers to silently
+ * corrupt the database. Of course if your application code is known to
+ * be bug-free (...) then this is not an issue.
+ *
+ * If this is your first time using a transactional embedded key/value
+ * store, you may find the \ref starting page to be helpful.
+ *
+ * @section caveats_sec Caveats
+ * Troubleshooting the lock file, plus semaphores on BSD systems:
+ *
+ * - A broken lockfile can cause sync issues.
+ * Stale reader transactions left behind by an aborted program
+ * cause further writes to grow the database quickly, and
+ * stale locks can block further operation.
+ *
+ * Fix: Check for stale readers periodically, using the
+ * #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool.
+ * Stale writers will be cleared automatically on some systems:
+ * - Windows - automatic
+ * - Linux, systems using POSIX mutexes with Robust option - automatic
+ * - not on BSD, systems using POSIX semaphores.
+ * Otherwise just make all programs using the database close it;
+ * the lockfile is always reset on first open of the environment.
+ *
+ * - On BSD systems or others configured with MDB_USE_POSIX_SEM,
+ * startup can fail due to semaphores owned by another userid.
+ *
+ * Fix: Open and close the database as the user which owns the
+ * semaphores (likely last user) or as root, while no other
+ * process is using the database.
+ *
+ * Restrictions/caveats (in addition to those listed for some functions):
+ *
+ * - Only the database owner should normally use the database on
+ * BSD systems or when otherwise configured with MDB_USE_POSIX_SEM.
+ * Multiple users can cause startup to fail later, as noted above.
+ *
+ * - There is normally no pure read-only mode, since readers need write
+ * access to locks and lock file. Exceptions: On read-only filesystems
+ * or with the #MDB_NOLOCK flag described under #mdb_env_open().
+ *
+ * - An LMDB configuration will often reserve considerable \b unused
+ * memory address space and maybe file size for future growth.
+ * This does not use actual memory or disk space, but users may need
+ * to understand the difference so they won't be scared off.
+ *
+ * - By default, in versions before 0.9.10, unused portions of the data
+ * file might receive garbage data from memory freed by other code.
+ * (This does not happen when using the #MDB_WRITEMAP flag.) As of
+ * 0.9.10 the default behavior is to initialize such memory before
+ * writing to the data file. Since there may be a slight performance
+ * cost due to this initialization, applications may disable it using
+ * the #MDB_NOMEMINIT flag. Applications handling sensitive data
+ * which must not be written should not use this flag. This flag is
+ * irrelevant when using #MDB_WRITEMAP.
+ *
+ * - A thread can only use one transaction at a time, plus any child
+ * transactions. Each transaction belongs to one thread. See below.
+ * The #MDB_NOTLS flag changes this for read-only transactions.
+ *
+ * - Use an MDB_env* in the process which opened it, not after fork().
+ *
+ * - Do not have open an LMDB database twice in the same process at
+ * the same time. Not even from a plain open() call - close()ing it
+ * breaks fcntl() advisory locking. (It is OK to reopen it after
+ * fork() - exec*(), since the lockfile has FD_CLOEXEC set.)
+ *
+ * - Avoid long-lived transactions. Read transactions prevent
+ * reuse of pages freed by newer write transactions, thus the
+ * database can grow quickly. Write transactions prevent
+ * other write transactions, since writes are serialized.
+ *
+ * - Avoid suspending a process with active transactions. These
+ * would then be "long-lived" as above. Also read transactions
+ * suspended when writers commit could sometimes see wrong data.
+ *
+ * ...when several processes can use a database concurrently:
+ *
+ * - Avoid aborting a process with an active transaction.
+ * The transaction becomes "long-lived" as above until a check
+ * for stale readers is performed or the lockfile is reset,
+ * since the process may not remove it from the lockfile.
+ *
+ * This does not apply to write transactions if the system clears
+ * stale writers, see above.
+ *
+ * - If you do that anyway, do a periodic check for stale readers. Or
+ * close the environment once in a while, so the lockfile can get reset.
+ *
+ * - Do not use LMDB databases on remote filesystems, even between
+ * processes on the same host. This breaks flock() on some OSes,
+ * possibly memory map sync, and certainly sync between programs
+ * on different hosts.
+ *
+ * - Opening a database can fail if another process is opening or
+ * closing it at exactly the same time.
+ *
+ * @author Howard Chu, Symas Corporation.
+ *
+ * @copyright Copyright 2011-2017 Howard Chu, Symas Corp. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ *
+ * @par Derived From:
+ * This code is derived from btree.c written by Martin Hedenfalk.
+ *
+ * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _LMDB_H_
+#define _LMDB_H_
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Unix permissions for creating files, or dummy definition for Windows */
+#ifdef _MSC_VER
+typedef int mdb_mode_t;
+#else
+typedef mode_t mdb_mode_t;
+#endif
+
+/** An abstraction for a file handle.
+ * On POSIX systems file handles are small integers. On Windows
+ * they're opaque pointers.
+ */
+#ifdef _WIN32
+typedef void *mdb_filehandle_t;
+#else
+typedef int mdb_filehandle_t;
+#endif
+
+/** @defgroup mdb LMDB API
+ * @{
+ * @brief OpenLDAP Lightning Memory-Mapped Database Manager
+ */
+/** @defgroup Version Version Macros
+ * @{
+ */
+/** Library major version */
+#define MDB_VERSION_MAJOR 0
+/** Library minor version */
+#define MDB_VERSION_MINOR 9
+/** Library patch version */
+#define MDB_VERSION_PATCH 21
+
+/** Combine args a,b,c into a single integer for easy version comparisons */
+#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
+
+/** The full library version as a single integer */
+#define MDB_VERSION_FULL \
+ MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
+
+/** The release date of this library version */
+#define MDB_VERSION_DATE "June 1, 2017"
+
+/** A stringifier for the version info */
+#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
+
+/** A helper for the stringifier macro */
+#define MDB_VERFOO(a,b,c,d) MDB_VERSTR(a,b,c,d)
+
+/** The full library version as a C string */
+#define MDB_VERSION_STRING \
+ MDB_VERFOO(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH,MDB_VERSION_DATE)
+/** @} */
+
+/** @brief Opaque structure for a database environment.
+ *
+ * A DB environment supports multiple databases, all residing in the same
+ * shared-memory map.
+ */
+typedef struct MDB_env MDB_env;
+
+/** @brief Opaque structure for a transaction handle.
+ *
+ * All database operations require a transaction handle. Transactions may be
+ * read-only or read-write.
+ */
+typedef struct MDB_txn MDB_txn;
+
+/** @brief A handle for an individual database in the DB environment. */
+typedef unsigned int MDB_dbi;
+
+/** @brief Opaque structure for navigating through a database */
+typedef struct MDB_cursor MDB_cursor;
+
+/** @brief Generic structure used for passing keys and data in and out
+ * of the database.
+ *
+ * Values returned from the database are valid only until a subsequent
+ * update operation, or the end of the transaction. Do not modify or
+ * free them, they commonly point into the database itself.
+ *
+ * Key sizes must be between 1 and #mdb_env_get_maxkeysize() inclusive.
+ * The same applies to data sizes in databases with the #MDB_DUPSORT flag.
+ * Other data items can in theory be from 0 to 0xffffffff bytes long.
+ */
+typedef struct MDB_val {
+ size_t mv_size; /**< size of the data item */
+ void *mv_data; /**< address of the data item */
+} MDB_val;
+
+/** @brief A callback function used to compare two keys in a database */
+typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b);
+
+/** @brief A callback function used to relocate a position-dependent data item
+ * in a fixed-address database.
+ *
+ * The \b newptr gives the item's desired address in
+ * the memory map, and \b oldptr gives its previous address. The item's actual
+ * data resides at the address in \b item. This callback is expected to walk
+ * through the fields of the record in \b item and modify any
+ * values based at the \b oldptr address to be relative to the \b newptr address.
+ * @param[in,out] item The item that is to be relocated.
+ * @param[in] oldptr The previous address.
+ * @param[in] newptr The new address to relocate to.
+ * @param[in] relctx An application-provided context, set by #mdb_set_relctx().
+ * @todo This feature is currently unimplemented.
+ */
+typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx);
+
+/** @defgroup mdb_env Environment Flags
+ * @{
+ */
+ /** mmap at a fixed address (experimental) */
+#define MDB_FIXEDMAP 0x01
+ /** no environment directory */
+#define MDB_NOSUBDIR 0x4000
+ /** don't fsync after commit */
+#define MDB_NOSYNC 0x10000
+ /** read only */
+#define MDB_RDONLY 0x20000
+ /** don't fsync metapage after commit */
+#define MDB_NOMETASYNC 0x40000
+ /** use writable mmap */
+#define MDB_WRITEMAP 0x80000
+ /** use asynchronous msync when #MDB_WRITEMAP is used */
+#define MDB_MAPASYNC 0x100000
+ /** tie reader locktable slots to #MDB_txn objects instead of to threads */
+#define MDB_NOTLS 0x200000
+ /** don't do any locking, caller must manage their own locks */
+#define MDB_NOLOCK 0x400000
+ /** don't do readahead (no effect on Windows) */
+#define MDB_NORDAHEAD 0x800000
+ /** don't initialize malloc'd memory before writing to datafile */
+#define MDB_NOMEMINIT 0x1000000
+/** @} */
+
+/** @defgroup mdb_dbi_open Database Flags
+ * @{
+ */
+ /** use reverse string keys */
+#define MDB_REVERSEKEY 0x02
+ /** use sorted duplicates */
+#define MDB_DUPSORT 0x04
+ /** numeric keys in native byte order: either unsigned int or size_t.
+ * The keys must all be of the same size. */
+#define MDB_INTEGERKEY 0x08
+ /** with #MDB_DUPSORT, sorted dup items have fixed size */
+#define MDB_DUPFIXED 0x10
+ /** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */
+#define MDB_INTEGERDUP 0x20
+ /** with #MDB_DUPSORT, use reverse string dups */
+#define MDB_REVERSEDUP 0x40
+ /** create DB if not already existing */
+#define MDB_CREATE 0x40000
+/** @} */
+
+/** @defgroup mdb_put Write Flags
+ * @{
+ */
+/** For put: Don't write if the key already exists. */
+#define MDB_NOOVERWRITE 0x10
+/** Only for #MDB_DUPSORT<br>
+ * For put: don't write if the key and data pair already exist.<br>
+ * For mdb_cursor_del: remove all duplicate data items.
+ */
+#define MDB_NODUPDATA 0x20
+/** For mdb_cursor_put: overwrite the current key/data pair */
+#define MDB_CURRENT 0x40
+/** For put: Just reserve space for data, don't copy it. Return a
+ * pointer to the reserved space.
+ */
+#define MDB_RESERVE 0x10000
+/** Data is being appended, don't split full pages. */
+#define MDB_APPEND 0x20000
+/** Duplicate data is being appended, don't split full pages. */
+#define MDB_APPENDDUP 0x40000
+/** Store multiple data items in one call. Only for #MDB_DUPFIXED. */
+#define MDB_MULTIPLE 0x80000
+/* @} */
+
+/** @defgroup mdb_copy Copy Flags
+ * @{
+ */
+/** Compacting copy: Omit free space from copy, and renumber all
+ * pages sequentially.
+ */
+#define MDB_CP_COMPACT 0x01
+/* @} */
+
+/** @brief Cursor Get operations.
+ *
+ * This is the set of all operations for retrieving data
+ * using a cursor.
+ */
+typedef enum MDB_cursor_op {
+ MDB_FIRST, /**< Position at first key/data item */
+ MDB_FIRST_DUP, /**< Position at first data item of current key.
+ Only for #MDB_DUPSORT */
+ MDB_GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */
+ MDB_GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */
+ MDB_GET_CURRENT, /**< Return key/data at current cursor position */
+ MDB_GET_MULTIPLE, /**< Return key and up to a page of duplicate data items
+ from current cursor position. Move cursor to prepare
+ for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
+ MDB_LAST, /**< Position at last key/data item */
+ MDB_LAST_DUP, /**< Position at last data item of current key.
+ Only for #MDB_DUPSORT */
+ MDB_NEXT, /**< Position at next data item */
+ MDB_NEXT_DUP, /**< Position at next data item of current key.
+ Only for #MDB_DUPSORT */
+ MDB_NEXT_MULTIPLE, /**< Return key and up to a page of duplicate data items
+ from next cursor position. Move cursor to prepare
+ for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
+ MDB_NEXT_NODUP, /**< Position at first data item of next key */
+ MDB_PREV, /**< Position at previous data item */
+ MDB_PREV_DUP, /**< Position at previous data item of current key.
+ Only for #MDB_DUPSORT */
+ MDB_PREV_NODUP, /**< Position at last data item of previous key */
+ MDB_SET, /**< Position at specified key */
+ MDB_SET_KEY, /**< Position at specified key, return key + data */
+ MDB_SET_RANGE, /**< Position at first key greater than or equal to specified key. */
+ MDB_PREV_MULTIPLE /**< Position at previous page and return key and up to
+ a page of duplicate data items. Only for #MDB_DUPFIXED */
+} MDB_cursor_op;
+
+/** @defgroup errors Return Codes
+ *
+ * BerkeleyDB uses -30800 to -30999, we'll go under them
+ * @{
+ */
+ /** Successful result */
+#define MDB_SUCCESS 0
+ /** key/data pair already exists */
+#define MDB_KEYEXIST (-30799)
+ /** key/data pair not found (EOF) */
+#define MDB_NOTFOUND (-30798)
+ /** Requested page not found - this usually indicates corruption */
+#define MDB_PAGE_NOTFOUND (-30797)
+ /** Located page was wrong type */
+#define MDB_CORRUPTED (-30796)
+ /** Update of meta page failed or environment had fatal error */
+#define MDB_PANIC (-30795)
+ /** Environment version mismatch */
+#define MDB_VERSION_MISMATCH (-30794)
+ /** File is not a valid LMDB file */
+#define MDB_INVALID (-30793)
+ /** Environment mapsize reached */
+#define MDB_MAP_FULL (-30792)
+ /** Environment maxdbs reached */
+#define MDB_DBS_FULL (-30791)
+ /** Environment maxreaders reached */
+#define MDB_READERS_FULL (-30790)
+ /** Too many TLS keys in use - Windows only */
+#define MDB_TLS_FULL (-30789)
+ /** Txn has too many dirty pages */
+#define MDB_TXN_FULL (-30788)
+ /** Cursor stack too deep - internal error */
+#define MDB_CURSOR_FULL (-30787)
+ /** Page has not enough space - internal error */
+#define MDB_PAGE_FULL (-30786)
+ /** Database contents grew beyond environment mapsize */
+#define MDB_MAP_RESIZED (-30785)
+ /** Operation and DB incompatible, or DB type changed. This can mean:
+ * <ul>
+ * <li>The operation expects an #MDB_DUPSORT / #MDB_DUPFIXED database.
+ * <li>Opening a named DB when the unnamed DB has #MDB_DUPSORT / #MDB_INTEGERKEY.
+ * <li>Accessing a data record as a database, or vice versa.
+ * <li>The database was dropped and recreated with different flags.
+ * </ul>
+ */
+#define MDB_INCOMPATIBLE (-30784)
+ /** Invalid reuse of reader locktable slot */
+#define MDB_BAD_RSLOT (-30783)
+ /** Transaction must abort, has a child, or is invalid */
+#define MDB_BAD_TXN (-30782)
+ /** Unsupported size of key/DB name/data, or wrong DUPFIXED size */
+#define MDB_BAD_VALSIZE (-30781)
+ /** The specified DBI was changed unexpectedly */
+#define MDB_BAD_DBI (-30780)
+ /** The last defined error code */
+#define MDB_LAST_ERRCODE MDB_BAD_DBI
+/** @} */
+
+/** @brief Statistics for a database in the environment */
+typedef struct MDB_stat {
+ unsigned int ms_psize; /**< Size of a database page.
+ This is currently the same for all databases. */
+ unsigned int ms_depth; /**< Depth (height) of the B-tree */
+ size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
+ size_t ms_leaf_pages; /**< Number of leaf pages */
+ size_t ms_overflow_pages; /**< Number of overflow pages */
+ size_t ms_entries; /**< Number of data items */
+} MDB_stat;
+
+/** @brief Information about the environment */
+typedef struct MDB_envinfo {
+ void *me_mapaddr; /**< Address of map, if fixed */
+ size_t me_mapsize; /**< Size of the data memory map */
+ size_t me_last_pgno; /**< ID of the last used page */
+ size_t me_last_txnid; /**< ID of the last committed transaction */
+ unsigned int me_maxreaders; /**< max reader slots in the environment */
+ unsigned int me_numreaders; /**< max reader slots used in the environment */
+} MDB_envinfo;
+
+ /** @brief Return the LMDB library version information.
+ *
+ * @param[out] major if non-NULL, the library major version number is copied here
+ * @param[out] minor if non-NULL, the library minor version number is copied here
+ * @param[out] patch if non-NULL, the library patch version number is copied here
+ * @retval "version string" The library version as a string
+ */
+char *mdb_version(int *major, int *minor, int *patch);
+
+ /** @brief Return a string describing a given error code.
+ *
+ * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3)
+ * function. If the error code is greater than or equal to 0, then the string
+ * returned by the system function strerror(3) is returned. If the error code
+ * is less than 0, an error string corresponding to the LMDB library error is
+ * returned. See @ref errors for a list of LMDB-specific error codes.
+ * @param[in] err The error code
+ * @retval "error message" The description of the error
+ */
+char *mdb_strerror(int err);
+
+ /** @brief Create an LMDB environment handle.
+ *
+ * This function allocates memory for a #MDB_env structure. To release
+ * the allocated memory and discard the handle, call #mdb_env_close().
+ * Before the handle may be used, it must be opened using #mdb_env_open().
+ * Various other options may also need to be set before opening the handle,
+ * e.g. #mdb_env_set_mapsize(), #mdb_env_set_maxreaders(), #mdb_env_set_maxdbs(),
+ * depending on usage requirements.
+ * @param[out] env The address where the new handle will be stored
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_create(MDB_env **env);
+
+ /** @brief Open an environment handle.
+ *
+ * If this function fails, #mdb_env_close() must be called to discard the #MDB_env handle.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] path The directory in which the database files reside. This
+ * directory must already exist and be writable.
+ * @param[in] flags Special options for this environment. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ * Flags set by mdb_env_set_flags() are also used.
+ * <ul>
+ * <li>#MDB_FIXEDMAP
+ * use a fixed address for the mmap region. This flag must be specified
+ * when creating the environment, and is stored persistently in the environment.
+ * If successful, the memory map will always reside at the same virtual address
+ * and pointers used to reference data items in the database will be constant
+ * across multiple invocations. This option may not always work, depending on
+ * how the operating system has allocated memory to shared libraries and other uses.
+ * The feature is highly experimental.
+ * <li>#MDB_NOSUBDIR
+ * By default, LMDB creates its environment in a directory whose
+ * pathname is given in \b path, and creates its data and lock files
+ * under that directory. With this option, \b path is used as-is for
+ * the database main data file. The database lock file is the \b path
+ * with "-lock" appended.
+ * <li>#MDB_RDONLY
+ * Open the environment in read-only mode. No write operations will be
+ * allowed. LMDB will still modify the lock file - except on read-only
+ * filesystems, where LMDB does not use locks.
+ * <li>#MDB_WRITEMAP
+ * Use a writeable memory map unless MDB_RDONLY is set. This uses
+ * fewer mallocs but loses protection from application bugs
+ * like wild pointer writes and other bad updates into the database.
+ * This may be slightly faster for DBs that fit entirely in RAM, but
+ * is slower for DBs larger than RAM.
+ * Incompatible with nested transactions.
+ * Do not mix processes with and without MDB_WRITEMAP on the same
+ * environment. This can defeat durability (#mdb_env_sync etc).
+ * <li>#MDB_NOMETASYNC
+ * Flush system buffers to disk only once per transaction, omit the
+ * metadata flush. Defer that until the system flushes files to disk,
+ * or next non-MDB_RDONLY commit or #mdb_env_sync(). This optimization
+ * maintains database integrity, but a system crash may undo the last
+ * committed transaction. I.e. it preserves the ACI (atomicity,
+ * consistency, isolation) but not D (durability) database property.
+ * This flag may be changed at any time using #mdb_env_set_flags().
+ * <li>#MDB_NOSYNC
+ * Don't flush system buffers to disk when committing a transaction.
+ * This optimization means a system crash can corrupt the database or
+ * lose the last transactions if buffers are not yet flushed to disk.
+ * The risk is governed by how often the system flushes dirty buffers
+ * to disk and how often #mdb_env_sync() is called. However, if the
+ * filesystem preserves write order and the #MDB_WRITEMAP flag is not
+ * used, transactions exhibit ACI (atomicity, consistency, isolation)
+ * properties and only lose D (durability). I.e. database integrity
+ * is maintained, but a system crash may undo the final transactions.
+ * Note that (#MDB_NOSYNC | #MDB_WRITEMAP) leaves the system with no
+ * hint for when to write transactions to disk, unless #mdb_env_sync()
+ * is called. (#MDB_MAPASYNC | #MDB_WRITEMAP) may be preferable.
+ * This flag may be changed at any time using #mdb_env_set_flags().
+ * <li>#MDB_MAPASYNC
+ * When using #MDB_WRITEMAP, use asynchronous flushes to disk.
+ * As with #MDB_NOSYNC, a system crash can then corrupt the
+ * database or lose the last transactions. Calling #mdb_env_sync()
+ * ensures on-disk database integrity until next commit.
+ * This flag may be changed at any time using #mdb_env_set_flags().
+ * <li>#MDB_NOTLS
+ * Don't use Thread-Local Storage. Tie reader locktable slots to
+ * #MDB_txn objects instead of to threads. I.e. #mdb_txn_reset() keeps
+ * the slot reseved for the #MDB_txn object. A thread may use parallel
+ * read-only transactions. A read-only transaction may span threads if
+ * the user synchronizes its use. Applications that multiplex many
+ * user threads over individual OS threads need this option. Such an
+ * application must also serialize the write transactions in an OS
+ * thread, since LMDB's write locking is unaware of the user threads.
+ * <li>#MDB_NOLOCK
+ * Don't do any locking. If concurrent access is anticipated, the
+ * caller must manage all concurrency itself. For proper operation
+ * the caller must enforce single-writer semantics, and must ensure
+ * that no readers are using old transactions while a writer is
+ * active. The simplest approach is to use an exclusive lock so that
+ * no readers may be active at all when a writer begins.
+ * <li>#MDB_NORDAHEAD
+ * Turn off readahead. Most operating systems perform readahead on
+ * read requests by default. This option turns it off if the OS
+ * supports it. Turning it off may help random read performance
+ * when the DB is larger than RAM and system RAM is full.
+ * The option is not implemented on Windows.
+ * <li>#MDB_NOMEMINIT
+ * Don't initialize malloc'd memory before writing to unused spaces
+ * in the data file. By default, memory for pages written to the data
+ * file is obtained using malloc. While these pages may be reused in
+ * subsequent transactions, freshly malloc'd pages will be initialized
+ * to zeroes before use. This avoids persisting leftover data from other
+ * code (that used the heap and subsequently freed the memory) into the
+ * data file. Note that many other system libraries may allocate
+ * and free memory from the heap for arbitrary uses. E.g., stdio may
+ * use the heap for file I/O buffers. This initialization step has a
+ * modest performance cost so some applications may want to disable
+ * it using this flag. This option can be a problem for applications
+ * which handle sensitive data like passwords, and it makes memory
+ * checkers like Valgrind noisy. This flag is not needed with #MDB_WRITEMAP,
+ * which writes directly to the mmap instead of using malloc for pages. The
+ * initialization is also skipped if #MDB_RESERVE is used; the
+ * caller is expected to overwrite all of the memory that was
+ * reserved in that case.
+ * This flag may be changed at any time using #mdb_env_set_flags().
+ * </ul>
+ * @param[in] mode The UNIX permissions to set on created files and semaphores.
+ * This parameter is ignored on Windows.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_VERSION_MISMATCH - the version of the LMDB library doesn't match the
+ * version that created the database environment.
+ * <li>#MDB_INVALID - the environment file headers are corrupted.
+ * <li>ENOENT - the directory specified by the path parameter doesn't exist.
+ * <li>EACCES - the user didn't have permission to access the environment files.
+ * <li>EAGAIN - the environment was locked by another process.
+ * </ul>
+ */
+int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode);
+
+ /** @brief Copy an LMDB environment to the specified path.
+ *
+ * This function may be used to make a backup of an existing environment.
+ * No lockfile is created, since it gets recreated at need.
+ * @note This call can trigger significant file size growth if run in
+ * parallel with write transactions, because it employs a read-only
+ * transaction. See long-lived transactions under @ref caveats_sec.
+ * @param[in] env An environment handle returned by #mdb_env_create(). It
+ * must have already been opened successfully.
+ * @param[in] path The directory in which the copy will reside. This
+ * directory must already exist and be writable but must otherwise be
+ * empty.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_copy(MDB_env *env, const char *path);
+
+ /** @brief Copy an LMDB environment to the specified file descriptor.
+ *
+ * This function may be used to make a backup of an existing environment.
+ * No lockfile is created, since it gets recreated at need.
+ * @note This call can trigger significant file size growth if run in
+ * parallel with write transactions, because it employs a read-only
+ * transaction. See long-lived transactions under @ref caveats_sec.
+ * @param[in] env An environment handle returned by #mdb_env_create(). It
+ * must have already been opened successfully.
+ * @param[in] fd The filedescriptor to write the copy to. It must
+ * have already been opened for Write access.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
+
+ /** @brief Copy an LMDB environment to the specified path, with options.
+ *
+ * This function may be used to make a backup of an existing environment.
+ * No lockfile is created, since it gets recreated at need.
+ * @note This call can trigger significant file size growth if run in
+ * parallel with write transactions, because it employs a read-only
+ * transaction. See long-lived transactions under @ref caveats_sec.
+ * @param[in] env An environment handle returned by #mdb_env_create(). It
+ * must have already been opened successfully.
+ * @param[in] path The directory in which the copy will reside. This
+ * directory must already exist and be writable but must otherwise be
+ * empty.
+ * @param[in] flags Special options for this operation. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ * <ul>
+ * <li>#MDB_CP_COMPACT - Perform compaction while copying: omit free
+ * pages and sequentially renumber all pages in output. This option
+ * consumes more CPU and runs more slowly than the default.
+ * Currently it fails if the environment has suffered a page leak.
+ * </ul>
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags);
+
+ /** @brief Copy an LMDB environment to the specified file descriptor,
+ * with options.
+ *
+ * This function may be used to make a backup of an existing environment.
+ * No lockfile is created, since it gets recreated at need. See
+ * #mdb_env_copy2() for further details.
+ * @note This call can trigger significant file size growth if run in
+ * parallel with write transactions, because it employs a read-only
+ * transaction. See long-lived transactions under @ref caveats_sec.
+ * @param[in] env An environment handle returned by #mdb_env_create(). It
+ * must have already been opened successfully.
+ * @param[in] fd The filedescriptor to write the copy to. It must
+ * have already been opened for Write access.
+ * @param[in] flags Special options for this operation.
+ * See #mdb_env_copy2() for options.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_copyfd2(MDB_env *env, mdb_filehandle_t fd, unsigned int flags);
+
+ /** @brief Return statistics about the LMDB environment.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] stat The address of an #MDB_stat structure
+ * where the statistics will be copied
+ */
+int mdb_env_stat(MDB_env *env, MDB_stat *stat);
+
+ /** @brief Return information about the LMDB environment.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] stat The address of an #MDB_envinfo structure
+ * where the information will be copied
+ */
+int mdb_env_info(MDB_env *env, MDB_envinfo *stat);
+
+ /** @brief Flush the data buffers to disk.
+ *
+ * Data is always written to disk when #mdb_txn_commit() is called,
+ * but the operating system may keep it buffered. LMDB always flushes
+ * the OS buffers upon commit as well, unless the environment was
+ * opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC. This call is
+ * not valid if the environment was opened with #MDB_RDONLY.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] force If non-zero, force a synchronous flush. Otherwise
+ * if the environment has the #MDB_NOSYNC flag set the flushes
+ * will be omitted, and with #MDB_MAPASYNC they will be asynchronous.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EACCES - the environment is read-only.
+ * <li>EINVAL - an invalid parameter was specified.
+ * <li>EIO - an error occurred during synchronization.
+ * </ul>
+ */
+int mdb_env_sync(MDB_env *env, int force);
+
+ /** @brief Close the environment and release the memory map.
+ *
+ * Only a single thread may call this function. All transactions, databases,
+ * and cursors must already be closed before calling this function. Attempts to
+ * use any such handles after calling this function will cause a SIGSEGV.
+ * The environment handle will be freed and must not be used again after this call.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ */
+void mdb_env_close(MDB_env *env);
+
+ /** @brief Set environment flags.
+ *
+ * This may be used to set some flags in addition to those from
+ * #mdb_env_open(), or to unset these flags. If several threads
+ * change the flags at the same time, the result is undefined.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] flags The flags to change, bitwise OR'ed together
+ * @param[in] onoff A non-zero value sets the flags, zero clears them.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_env_set_flags(MDB_env *env, unsigned int flags, int onoff);
+
+ /** @brief Get environment flags.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] flags The address of an integer to store the flags
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_env_get_flags(MDB_env *env, unsigned int *flags);
+
+ /** @brief Return the path that was used in #mdb_env_open().
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] path Address of a string pointer to contain the path. This
+ * is the actual string in the environment, not a copy. It should not be
+ * altered in any way.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_env_get_path(MDB_env *env, const char **path);
+
+ /** @brief Return the filedescriptor for the given environment.
+ *
+ * This function may be called after fork(), so the descriptor can be
+ * closed before exec*(). Other LMDB file descriptors have FD_CLOEXEC.
+ * (Until LMDB 0.9.18, only the lockfile had that.)
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] fd Address of a mdb_filehandle_t to contain the descriptor.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd);
+
+ /** @brief Set the size of the memory map to use for this environment.
+ *
+ * The size should be a multiple of the OS page size. The default is
+ * 10485760 bytes. The size of the memory map is also the maximum size
+ * of the database. The value should be chosen as large as possible,
+ * to accommodate future growth of the database.
+ * This function should be called after #mdb_env_create() and before #mdb_env_open().
+ * It may be called at later times if no transactions are active in
+ * this process. Note that the library does not check for this condition,
+ * the caller must ensure it explicitly.
+ *
+ * The new size takes effect immediately for the current process but
+ * will not be persisted to any others until a write transaction has been
+ * committed by the current process. Also, only mapsize increases are
+ * persisted into the environment.
+ *
+ * If the mapsize is increased by another process, and data has grown
+ * beyond the range of the current mapsize, #mdb_txn_begin() will
+ * return #MDB_MAP_RESIZED. This function may be called with a size
+ * of zero to adopt the new size.
+ *
+ * Any attempt to set a size smaller than the space already consumed
+ * by the environment will be silently changed to the current size of the used space.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] size The size in bytes
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified, or the environment has
+ * an active write transaction.
+ * </ul>
+ */
+int mdb_env_set_mapsize(MDB_env *env, size_t size);
+
+ /** @brief Set the maximum number of threads/reader slots for the environment.
+ *
+ * This defines the number of slots in the lock table that is used to track readers in the
+ * the environment. The default is 126.
+ * Starting a read-only transaction normally ties a lock table slot to the
+ * current thread until the environment closes or the thread exits. If
+ * MDB_NOTLS is in use, #mdb_txn_begin() instead ties the slot to the
+ * MDB_txn object until it or the #MDB_env object is destroyed.
+ * This function may only be called after #mdb_env_create() and before #mdb_env_open().
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] readers The maximum number of reader lock table slots
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified, or the environment is already open.
+ * </ul>
+ */
+int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers);
+
+ /** @brief Get the maximum number of threads/reader slots for the environment.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] readers Address of an integer to store the number of readers
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers);
+
+ /** @brief Set the maximum number of named databases for the environment.
+ *
+ * This function is only needed if multiple databases will be used in the
+ * environment. Simpler applications that use the environment as a single
+ * unnamed database can ignore this option.
+ * This function may only be called after #mdb_env_create() and before #mdb_env_open().
+ *
+ * Currently a moderate number of slots are cheap but a huge number gets
+ * expensive: 7-120 words per transaction, and every #mdb_dbi_open()
+ * does a linear search of the opened slots.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] dbs The maximum number of databases
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified, or the environment is already open.
+ * </ul>
+ */
+int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs);
+
+ /** @brief Get the maximum size of keys and #MDB_DUPSORT data we can write.
+ *
+ * Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511.
+ * See @ref MDB_val.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @return The maximum size of a key we can write
+ */
+int mdb_env_get_maxkeysize(MDB_env *env);
+
+ /** @brief Set application information associated with the #MDB_env.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] ctx An arbitrary pointer for whatever the application needs.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_set_userctx(MDB_env *env, void *ctx);
+
+ /** @brief Get the application information associated with the #MDB_env.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @return The pointer set by #mdb_env_set_userctx().
+ */
+void *mdb_env_get_userctx(MDB_env *env);
+
+ /** @brief A callback function for most LMDB assert() failures,
+ * called before printing the message and aborting.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create().
+ * @param[in] msg The assertion message, not including newline.
+ */
+typedef void MDB_assert_func(MDB_env *env, const char *msg);
+
+ /** Set or reset the assert() callback of the environment.
+ * Disabled if liblmdb is buillt with NDEBUG.
+ * @note This hack should become obsolete as lmdb's error handling matures.
+ * @param[in] env An environment handle returned by #mdb_env_create().
+ * @param[in] func An #MDB_assert_func function, or 0.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
+
+ /** @brief Create a transaction for use with the environment.
+ *
+ * The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit().
+ * @note A transaction and its cursors must only be used by a single
+ * thread, and a thread may only have a single transaction at a time.
+ * If #MDB_NOTLS is in use, this does not apply to read-only transactions.
+ * @note Cursors may not span transactions.
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] parent If this parameter is non-NULL, the new transaction
+ * will be a nested transaction, with the transaction indicated by \b parent
+ * as its parent. Transactions may be nested to any level. A parent
+ * transaction and its cursors may not issue any other operations than
+ * mdb_txn_commit and mdb_txn_abort while it has active child transactions.
+ * @param[in] flags Special options for this transaction. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ * <ul>
+ * <li>#MDB_RDONLY
+ * This transaction will not perform any write operations.
+ * </ul>
+ * @param[out] txn Address where the new #MDB_txn handle will be stored
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_PANIC - a fatal error occurred earlier and the environment
+ * must be shut down.
+ * <li>#MDB_MAP_RESIZED - another process wrote data beyond this MDB_env's
+ * mapsize and this environment's map must be resized as well.
+ * See #mdb_env_set_mapsize().
+ * <li>#MDB_READERS_FULL - a read-only transaction was requested and
+ * the reader lock table is full. See #mdb_env_set_maxreaders().
+ * <li>ENOMEM - out of memory.
+ * </ul>
+ */
+int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn);
+
+ /** @brief Returns the transaction's #MDB_env
+ *
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ */
+MDB_env *mdb_txn_env(MDB_txn *txn);
+
+ /** @brief Return the transaction's ID.
+ *
+ * This returns the identifier associated with this transaction. For a
+ * read-only transaction, this corresponds to the snapshot being read;
+ * concurrent readers will frequently have the same transaction ID.
+ *
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @return A transaction ID, valid if input is an active transaction.
+ */
+size_t mdb_txn_id(MDB_txn *txn);
+
+ /** @brief Commit all the operations of a transaction into the database.
+ *
+ * The transaction handle is freed. It and its cursors must not be used
+ * again after this call, except with #mdb_cursor_renew().
+ * @note Earlier documentation incorrectly said all cursors would be freed.
+ * Only write-transactions free cursors.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * <li>ENOSPC - no more disk space.
+ * <li>EIO - a low-level I/O error occurred while writing.
+ * <li>ENOMEM - out of memory.
+ * </ul>
+ */
+int mdb_txn_commit(MDB_txn *txn);
+
+ /** @brief Abandon all the operations of the transaction instead of saving them.
+ *
+ * The transaction handle is freed. It and its cursors must not be used
+ * again after this call, except with #mdb_cursor_renew().
+ * @note Earlier documentation incorrectly said all cursors would be freed.
+ * Only write-transactions free cursors.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ */
+void mdb_txn_abort(MDB_txn *txn);
+
+ /** @brief Reset a read-only transaction.
+ *
+ * Abort the transaction like #mdb_txn_abort(), but keep the transaction
+ * handle. #mdb_txn_renew() may reuse the handle. This saves allocation
+ * overhead if the process will start a new read-only transaction soon,
+ * and also locking overhead if #MDB_NOTLS is in use. The reader table
+ * lock is released, but the table slot stays tied to its thread or
+ * #MDB_txn. Use mdb_txn_abort() to discard a reset handle, and to free
+ * its lock table slot if MDB_NOTLS is in use.
+ * Cursors opened within the transaction must not be used
+ * again after this call, except with #mdb_cursor_renew().
+ * Reader locks generally don't interfere with writers, but they keep old
+ * versions of database pages allocated. Thus they prevent the old pages
+ * from being reused when writers commit new data, and so under heavy load
+ * the database size may grow much more rapidly than otherwise.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ */
+void mdb_txn_reset(MDB_txn *txn);
+
+ /** @brief Renew a read-only transaction.
+ *
+ * This acquires a new reader lock for a transaction handle that had been
+ * released by #mdb_txn_reset(). It must be called before a reset transaction
+ * may be used again.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_PANIC - a fatal error occurred earlier and the environment
+ * must be shut down.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_txn_renew(MDB_txn *txn);
+
+/** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */
+#define mdb_open(txn,name,flags,dbi) mdb_dbi_open(txn,name,flags,dbi)
+/** Compat with version <= 0.9.4, avoid clash with libmdb from MDB Tools project */
+#define mdb_close(env,dbi) mdb_dbi_close(env,dbi)
+
+ /** @brief Open a database in the environment.
+ *
+ * A database handle denotes the name and parameters of a database,
+ * independently of whether such a database exists.
+ * The database handle may be discarded by calling #mdb_dbi_close().
+ * The old database handle is returned if the database was already open.
+ * The handle may only be closed once.
+ *
+ * The database handle will be private to the current transaction until
+ * the transaction is successfully committed. If the transaction is
+ * aborted the handle will be closed automatically.
+ * After a successful commit the handle will reside in the shared
+ * environment, and may be used by other transactions.
+ *
+ * This function must not be called from multiple concurrent
+ * transactions in the same process. A transaction that uses
+ * this function must finish (either commit or abort) before
+ * any other transaction in the process may use this function.
+ *
+ * To use named databases (with name != NULL), #mdb_env_set_maxdbs()
+ * must be called before opening the environment. Database names are
+ * keys in the unnamed database, and may be read but not written.
+ *
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] name The name of the database to open. If only a single
+ * database is needed in the environment, this value may be NULL.
+ * @param[in] flags Special options for this database. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ * <ul>
+ * <li>#MDB_REVERSEKEY
+ * Keys are strings to be compared in reverse order, from the end
+ * of the strings to the beginning. By default, Keys are treated as strings and
+ * compared from beginning to end.
+ * <li>#MDB_DUPSORT
+ * Duplicate keys may be used in the database. (Or, from another perspective,
+ * keys may have multiple data items, stored in sorted order.) By default
+ * keys must be unique and may have only a single data item.
+ * <li>#MDB_INTEGERKEY
+ * Keys are binary integers in native byte order, either unsigned int
+ * or size_t, and will be sorted as such.
+ * The keys must all be of the same size.
+ * <li>#MDB_DUPFIXED
+ * This flag may only be used in combination with #MDB_DUPSORT. This option
+ * tells the library that the data items for this database are all the same
+ * size, which allows further optimizations in storage and retrieval. When
+ * all data items are the same size, the #MDB_GET_MULTIPLE, #MDB_NEXT_MULTIPLE
+ * and #MDB_PREV_MULTIPLE cursor operations may be used to retrieve multiple
+ * items at once.
+ * <li>#MDB_INTEGERDUP
+ * This option specifies that duplicate data items are binary integers,
+ * similar to #MDB_INTEGERKEY keys.
+ * <li>#MDB_REVERSEDUP
+ * This option specifies that duplicate data items should be compared as
+ * strings in reverse order.
+ * <li>#MDB_CREATE
+ * Create the named database if it doesn't exist. This option is not
+ * allowed in a read-only transaction or a read-only environment.
+ * </ul>
+ * @param[out] dbi Address where the new #MDB_dbi handle will be stored
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_NOTFOUND - the specified database doesn't exist in the environment
+ * and #MDB_CREATE was not specified.
+ * <li>#MDB_DBS_FULL - too many databases have been opened. See #mdb_env_set_maxdbs().
+ * </ul>
+ */
+int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi);
+
+ /** @brief Retrieve statistics for a database.
+ *
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[out] stat The address of an #MDB_stat structure
+ * where the statistics will be copied
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat);
+
+ /** @brief Retrieve the DB flags for a database handle.
+ *
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[out] flags Address where the flags will be returned.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags);
+
+ /** @brief Close a database handle. Normally unnecessary. Use with care:
+ *
+ * This call is not mutex protected. Handles should only be closed by
+ * a single thread, and only if no other threads are going to reference
+ * the database handle or one of its cursors any further. Do not close
+ * a handle if an existing transaction has modified its database.
+ * Doing so can cause misbehavior from database corruption to errors
+ * like MDB_BAD_VALSIZE (since the DB name is gone).
+ *
+ * Closing a database handle is not necessary, but lets #mdb_dbi_open()
+ * reuse the handle value. Usually it's better to set a bigger
+ * #mdb_env_set_maxdbs(), unless that value would be large.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ */
+void mdb_dbi_close(MDB_env *env, MDB_dbi dbi);
+
+ /** @brief Empty or delete+close a database.
+ *
+ * See #mdb_dbi_close() for restrictions about closing the DB handle.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] del 0 to empty the DB, 1 to delete it from the
+ * environment and close the DB handle.
+ * @return A non-zero error value on failure and 0 on success.
+ */
+int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del);
+
+ /** @brief Set a custom key comparison function for a database.
+ *
+ * The comparison function is called whenever it is necessary to compare a
+ * key specified by the application with a key currently stored in the database.
+ * If no comparison function is specified, and no special key flags were specified
+ * with #mdb_dbi_open(), the keys are compared lexically, with shorter keys collating
+ * before longer keys.
+ * @warning This function must be called before any data access functions are used,
+ * otherwise data corruption may occur. The same comparison function must be used by every
+ * program accessing the database, every time the database is used.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] cmp A #MDB_cmp_func function
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp);
+
+ /** @brief Set a custom data comparison function for a #MDB_DUPSORT database.
+ *
+ * This comparison function is called whenever it is necessary to compare a data
+ * item specified by the application with a data item currently stored in the database.
+ * This function only takes effect if the database was opened with the #MDB_DUPSORT
+ * flag.
+ * If no comparison function is specified, and no special key flags were specified
+ * with #mdb_dbi_open(), the data items are compared lexically, with shorter items collating
+ * before longer items.
+ * @warning This function must be called before any data access functions are used,
+ * otherwise data corruption may occur. The same comparison function must be used by every
+ * program accessing the database, every time the database is used.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] cmp A #MDB_cmp_func function
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp);
+
+ /** @brief Set a relocation function for a #MDB_FIXEDMAP database.
+ *
+ * @todo The relocation function is called whenever it is necessary to move the data
+ * of an item to a different position in the database (e.g. through tree
+ * balancing operations, shifts as a result of adds or deletes, etc.). It is
+ * intended to allow address/position-dependent data items to be stored in
+ * a database in an environment opened with the #MDB_FIXEDMAP option.
+ * Currently the relocation feature is unimplemented and setting
+ * this function has no effect.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] rel A #MDB_rel_func function
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel);
+
+ /** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function.
+ *
+ * See #mdb_set_relfunc and #MDB_rel_func for more details.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] ctx An arbitrary pointer for whatever the application needs.
+ * It will be passed to the callback function set by #mdb_set_relfunc
+ * as its \b relctx parameter whenever the callback is invoked.
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx);
+
+ /** @brief Get items from a database.
+ *
+ * This function retrieves key/data pairs from the database. The address
+ * and length of the data associated with the specified \b key are returned
+ * in the structure to which \b data refers.
+ * If the database supports duplicate keys (#MDB_DUPSORT) then the
+ * first data item for the key will be returned. Retrieval of other
+ * items requires the use of #mdb_cursor_get().
+ *
+ * @note The memory pointed to by the returned values is owned by the
+ * database. The caller need not dispose of the memory, and may not
+ * modify it in any way. For values returned in a read-only transaction
+ * any modification attempts will cause a SIGSEGV.
+ * @note Values returned from the database are valid only until a
+ * subsequent update operation, or the end of the transaction.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] key The key to search for in the database
+ * @param[out] data The data corresponding to the key
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_NOTFOUND - the key was not in the database.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
+
+ /** @brief Store items into a database.
+ *
+ * This function stores key/data pairs in the database. The default behavior
+ * is to enter the new key/data pair, replacing any previously existing key
+ * if duplicates are disallowed, or adding a duplicate data item if
+ * duplicates are allowed (#MDB_DUPSORT).
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] key The key to store in the database
+ * @param[in,out] data The data to store
+ * @param[in] flags Special options for this operation. This parameter
+ * must be set to 0 or by bitwise OR'ing together one or more of the
+ * values described here.
+ * <ul>
+ * <li>#MDB_NODUPDATA - enter the new key/data pair only if it does not
+ * already appear in the database. This flag may only be specified
+ * if the database was opened with #MDB_DUPSORT. The function will
+ * return #MDB_KEYEXIST if the key/data pair already appears in the
+ * database.
+ * <li>#MDB_NOOVERWRITE - enter the new key/data pair only if the key
+ * does not already appear in the database. The function will return
+ * #MDB_KEYEXIST if the key already appears in the database, even if
+ * the database supports duplicates (#MDB_DUPSORT). The \b data
+ * parameter will be set to point to the existing item.
+ * <li>#MDB_RESERVE - reserve space for data of the given size, but
+ * don't copy the given data. Instead, return a pointer to the
+ * reserved space, which the caller can fill in later - before
+ * the next update operation or the transaction ends. This saves
+ * an extra memcpy if the data is being generated later.
+ * LMDB does nothing else with this memory, the caller is expected
+ * to modify all of the space requested. This flag must not be
+ * specified if the database was opened with #MDB_DUPSORT.
+ * <li>#MDB_APPEND - append the given key/data pair to the end of the
+ * database. This option allows fast bulk loading when keys are
+ * already known to be in the correct order. Loading unsorted keys
+ * with this flag will cause a #MDB_KEYEXIST error.
+ * <li>#MDB_APPENDDUP - as above, but for sorted dup data.
+ * </ul>
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize().
+ * <li>#MDB_TXN_FULL - the transaction has too many dirty pages.
+ * <li>EACCES - an attempt was made to write in a read-only transaction.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data,
+ unsigned int flags);
+
+ /** @brief Delete items from a database.
+ *
+ * This function removes key/data pairs from the database.
+ * If the database does not support sorted duplicate data items
+ * (#MDB_DUPSORT) the data parameter is ignored.
+ * If the database supports sorted duplicates and the data parameter
+ * is NULL, all of the duplicate data items for the key will be
+ * deleted. Otherwise, if the data parameter is non-NULL
+ * only the matching data item will be deleted.
+ * This function will return #MDB_NOTFOUND if the specified key/data
+ * pair is not in the database.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] key The key to delete from the database
+ * @param[in] data The data to delete
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EACCES - an attempt was made to write in a read-only transaction.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_del(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data);
+
+ /** @brief Create a cursor handle.
+ *
+ * A cursor is associated with a specific transaction and database.
+ * A cursor cannot be used when its database handle is closed. Nor
+ * when its transaction has ended, except with #mdb_cursor_renew().
+ * It can be discarded with #mdb_cursor_close().
+ * A cursor in a write-transaction can be closed before its transaction
+ * ends, and will otherwise be closed when its transaction ends.
+ * A cursor in a read-only transaction must be closed explicitly, before
+ * or after its transaction ends. It can be reused with
+ * #mdb_cursor_renew() before finally closing it.
+ * @note Earlier documentation said that cursors in every transaction
+ * were closed when the transaction committed or aborted.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[out] cursor Address where the new #MDB_cursor handle will be stored
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor);
+
+ /** @brief Close a cursor handle.
+ *
+ * The cursor handle will be freed and must not be used again after this call.
+ * Its transaction must still be live if it is a write-transaction.
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ */
+void mdb_cursor_close(MDB_cursor *cursor);
+
+ /** @brief Renew a cursor handle.
+ *
+ * A cursor is associated with a specific transaction and database.
+ * Cursors that are only used in read-only
+ * transactions may be re-used, to avoid unnecessary malloc/free overhead.
+ * The cursor may be associated with a new read-only transaction, and
+ * referencing the same database handle as it was created with.
+ * This may be done whether the previous transaction is live or dead.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_renew(MDB_txn *txn, MDB_cursor *cursor);
+
+ /** @brief Return the cursor's transaction handle.
+ *
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ */
+MDB_txn *mdb_cursor_txn(MDB_cursor *cursor);
+
+ /** @brief Return the cursor's database handle.
+ *
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ */
+MDB_dbi mdb_cursor_dbi(MDB_cursor *cursor);
+
+ /** @brief Retrieve by cursor.
+ *
+ * This function retrieves key/data pairs from the database. The address and length
+ * of the key are returned in the object to which \b key refers (except for the
+ * case of the #MDB_SET option, in which the \b key object is unchanged), and
+ * the address and length of the data are returned in the object to which \b data
+ * refers.
+ * See #mdb_get() for restrictions on using the output values.
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ * @param[in,out] key The key for a retrieved item
+ * @param[in,out] data The data of a retrieved item
+ * @param[in] op A cursor operation #MDB_cursor_op
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_NOTFOUND - no matching key found.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
+ MDB_cursor_op op);
+
+ /** @brief Store by cursor.
+ *
+ * This function stores key/data pairs into the database.
+ * The cursor is positioned at the new item, or on failure usually near it.
+ * @note Earlier documentation incorrectly said errors would leave the
+ * state of the cursor unchanged.
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ * @param[in] key The key operated on.
+ * @param[in] data The data operated on.
+ * @param[in] flags Options for this operation. This parameter
+ * must be set to 0 or one of the values described here.
+ * <ul>
+ * <li>#MDB_CURRENT - replace the item at the current cursor position.
+ * The \b key parameter must still be provided, and must match it.
+ * If using sorted duplicates (#MDB_DUPSORT) the data item must still
+ * sort into the same place. This is intended to be used when the
+ * new data is the same size as the old. Otherwise it will simply
+ * perform a delete of the old record followed by an insert.
+ * <li>#MDB_NODUPDATA - enter the new key/data pair only if it does not
+ * already appear in the database. This flag may only be specified
+ * if the database was opened with #MDB_DUPSORT. The function will
+ * return #MDB_KEYEXIST if the key/data pair already appears in the
+ * database.
+ * <li>#MDB_NOOVERWRITE - enter the new key/data pair only if the key
+ * does not already appear in the database. The function will return
+ * #MDB_KEYEXIST if the key already appears in the database, even if
+ * the database supports duplicates (#MDB_DUPSORT).
+ * <li>#MDB_RESERVE - reserve space for data of the given size, but
+ * don't copy the given data. Instead, return a pointer to the
+ * reserved space, which the caller can fill in later - before
+ * the next update operation or the transaction ends. This saves
+ * an extra memcpy if the data is being generated later. This flag
+ * must not be specified if the database was opened with #MDB_DUPSORT.
+ * <li>#MDB_APPEND - append the given key/data pair to the end of the
+ * database. No key comparisons are performed. This option allows
+ * fast bulk loading when keys are already known to be in the
+ * correct order. Loading unsorted keys with this flag will cause
+ * a #MDB_KEYEXIST error.
+ * <li>#MDB_APPENDDUP - as above, but for sorted dup data.
+ * <li>#MDB_MULTIPLE - store multiple contiguous data elements in a
+ * single request. This flag may only be specified if the database
+ * was opened with #MDB_DUPFIXED. The \b data argument must be an
+ * array of two MDB_vals. The mv_size of the first MDB_val must be
+ * the size of a single data element. The mv_data of the first MDB_val
+ * must point to the beginning of the array of contiguous data elements.
+ * The mv_size of the second MDB_val must be the count of the number
+ * of data elements to store. On return this field will be set to
+ * the count of the number of elements actually written. The mv_data
+ * of the second MDB_val is unused.
+ * </ul>
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize().
+ * <li>#MDB_TXN_FULL - the transaction has too many dirty pages.
+ * <li>EACCES - an attempt was made to write in a read-only transaction.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
+ unsigned int flags);
+
+ /** @brief Delete current key/data pair
+ *
+ * This function deletes the key/data pair to which the cursor refers.
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ * @param[in] flags Options for this operation. This parameter
+ * must be set to 0 or one of the values described here.
+ * <ul>
+ * <li>#MDB_NODUPDATA - delete all of the data items for the current key.
+ * This flag may only be specified if the database was opened with #MDB_DUPSORT.
+ * </ul>
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EACCES - an attempt was made to write in a read-only transaction.
+ * <li>EINVAL - an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags);
+
+ /** @brief Return count of duplicates for current key.
+ *
+ * This call is only valid on databases that support sorted duplicate
+ * data items #MDB_DUPSORT.
+ * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
+ * @param[out] countp Address where the count will be stored
+ * @return A non-zero error value on failure and 0 on success. Some possible
+ * errors are:
+ * <ul>
+ * <li>EINVAL - cursor is not initialized, or an invalid parameter was specified.
+ * </ul>
+ */
+int mdb_cursor_count(MDB_cursor *cursor, size_t *countp);
+
+ /** @brief Compare two data items according to a particular database.
+ *
+ * This returns a comparison as if the two data items were keys in the
+ * specified database.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] a The first item to compare
+ * @param[in] b The second item to compare
+ * @return < 0 if a < b, 0 if a == b, > 0 if a > b
+ */
+int mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b);
+
+ /** @brief Compare two data items according to a particular database.
+ *
+ * This returns a comparison as if the two items were data items of
+ * the specified database. The database must have the #MDB_DUPSORT flag.
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ * @param[in] a The first item to compare
+ * @param[in] b The second item to compare
+ * @return < 0 if a < b, 0 if a == b, > 0 if a > b
+ */
+int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b);
+
+ /** @brief A callback function used to print a message from the library.
+ *
+ * @param[in] msg The string to be printed.
+ * @param[in] ctx An arbitrary context pointer for the callback.
+ * @return < 0 on failure, >= 0 on success.
+ */
+typedef int (MDB_msg_func)(const char *msg, void *ctx);
+
+ /** @brief Dump the entries in the reader lock table.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[in] func A #MDB_msg_func function
+ * @param[in] ctx Anything the message function needs
+ * @return < 0 on failure, >= 0 on success.
+ */
+int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx);
+
+ /** @brief Check for stale entries in the reader lock table.
+ *
+ * @param[in] env An environment handle returned by #mdb_env_create()
+ * @param[out] dead Number of stale slots that were cleared
+ * @return 0 on success, non-zero on failure.
+ */
+int mdb_reader_check(MDB_env *env, int *dead);
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+/** @page tools LMDB Command Line Tools
+ The following describes the command line tools that are available for LMDB.
+ \li \ref mdb_copy_1
+ \li \ref mdb_dump_1
+ \li \ref mdb_load_1
+ \li \ref mdb_stat_1
+*/
+
+#endif /* _LMDB_H_ */
diff --git a/contrib/lmdb/mdb.c b/contrib/lmdb/mdb.c
new file mode 100644
index 0000000..f225a19
--- /dev/null
+++ b/contrib/lmdb/mdb.c
@@ -0,0 +1,10258 @@
+#pragma GCC diagnostic ignored "-Wshadow"
+/** @file mdb.c
+ * @brief Lightning memory-mapped database library
+ *
+ * A Btree-based database management library modeled loosely on the
+ * BerkeleyDB API, but much simplified.
+ */
+/*
+ * Copyright 2011-2017 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ *
+ * This code is derived from btree.c written by Martin Hedenfalk.
+ *
+ * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#if defined(__WIN64__)
+#define _FILE_OFFSET_BITS 64
+#endif
+#ifdef _WIN32
+#include <malloc.h>
+#include <windows.h>
+#include <wchar.h> /* get wcscpy() */
+
+/** getpid() returns int; MinGW defines pid_t but MinGW64 typedefs it
+ * as int64 which is wrong. MSVC doesn't define it at all, so just
+ * don't use it.
+ */
+#define MDB_PID_T int
+#define MDB_THR_T DWORD
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __GNUC__
+# include <sys/param.h>
+#else
+# define LITTLE_ENDIAN 1234
+# define BIG_ENDIAN 4321
+# define BYTE_ORDER LITTLE_ENDIAN
+# ifndef SSIZE_MAX
+# define SSIZE_MAX INT_MAX
+# endif
+#endif
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#define MDB_PID_T pid_t
+#define MDB_THR_T pthread_t
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#include <fcntl.h>
+#endif
+
+#if defined(__mips) && defined(__linux)
+/* MIPS has cache coherency issues, requires explicit cache control */
+#include <asm/cachectl.h>
+extern int cacheflush(char *addr, int nbytes, int cache);
+#define CACHEFLUSH(addr, bytes, cache) cacheflush(addr, bytes, cache)
+#else
+#define CACHEFLUSH(addr, bytes, cache)
+#endif
+
+#if defined(__linux) && !defined(MDB_FDATASYNC_WORKS)
+/** fdatasync is broken on ext3/ext4fs on older kernels, see
+ * description in #mdb_env_open2 comments. You can safely
+ * define MDB_FDATASYNC_WORKS if this code will only be run
+ * on kernels 3.6 and newer.
+ */
+#define BROKEN_FDATASYNC
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef _MSC_VER
+#include <io.h>
+typedef SSIZE_T ssize_t;
+#else
+#include <unistd.h>
+#endif
+
+#if defined(__sun) || defined(ANDROID)
+/* Most platforms have posix_memalign, older may only have memalign */
+#define HAVE_MEMALIGN 1
+#include <malloc.h>
+#endif
+
+#if !(defined(BYTE_ORDER) || defined(__BYTE_ORDER))
+#include <netinet/in.h>
+#include <resolv.h> /* defines BYTE_ORDER on HPUX and Solaris */
+#endif
+
+#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__)
+# define MDB_USE_POSIX_SEM 1
+# define MDB_FDATASYNC fsync
+#elif defined(ANDROID)
+# define MDB_FDATASYNC fsync
+#endif
+
+#ifndef _WIN32
+#include <pthread.h>
+#include <signal.h>
+#ifdef MDB_USE_POSIX_SEM
+# define MDB_USE_HASH 1
+#include <semaphore.h>
+#else
+#define MDB_USE_POSIX_MUTEX 1
+#endif
+#endif
+
+#if defined(_WIN32) + defined(MDB_USE_POSIX_SEM) \
+ + defined(MDB_USE_POSIX_MUTEX) != 1
+# error "Ambiguous shared-lock implementation"
+#endif
+
+#ifdef USE_VALGRIND
+#include <valgrind/memcheck.h>
+#define VGMEMP_CREATE(h,r,z) VALGRIND_CREATE_MEMPOOL(h,r,z)
+#define VGMEMP_ALLOC(h,a,s) VALGRIND_MEMPOOL_ALLOC(h,a,s)
+#define VGMEMP_FREE(h,a) VALGRIND_MEMPOOL_FREE(h,a)
+#define VGMEMP_DESTROY(h) VALGRIND_DESTROY_MEMPOOL(h)
+#define VGMEMP_DEFINED(a,s) VALGRIND_MAKE_MEM_DEFINED(a,s)
+#else
+#define VGMEMP_CREATE(h,r,z)
+#define VGMEMP_ALLOC(h,a,s)
+#define VGMEMP_FREE(h,a)
+#define VGMEMP_DESTROY(h)
+#define VGMEMP_DEFINED(a,s)
+#endif
+
+#ifndef BYTE_ORDER
+# if (defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN))
+/* Solaris just defines one or the other */
+# define LITTLE_ENDIAN 1234
+# define BIG_ENDIAN 4321
+# ifdef _LITTLE_ENDIAN
+# define BYTE_ORDER LITTLE_ENDIAN
+# else
+# define BYTE_ORDER BIG_ENDIAN
+# endif
+# else
+# define BYTE_ORDER __BYTE_ORDER
+# endif
+#endif
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+#endif
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN __BIG_ENDIAN
+#endif
+
+#if defined(__i386) || defined(__x86_64) || defined(_M_IX86)
+#define MISALIGNED_OK 1
+#endif
+
+#include "lmdb.h"
+#include "midl.h"
+
+#if (BYTE_ORDER == LITTLE_ENDIAN) == (BYTE_ORDER == BIG_ENDIAN)
+# error "Unknown or unsupported endianness (BYTE_ORDER)"
+#elif (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF
+# error "Two's complement, reasonably sized integer types, please"
+#endif
+
+#ifdef __GNUC__
+/** Put infrequently used env functions in separate section */
+# ifdef __APPLE__
+# define ESECT __attribute__ ((section("__TEXT,text_env")))
+# else
+# define ESECT __attribute__ ((section("text_env")))
+# endif
+#else
+#define ESECT
+#endif
+
+#ifdef _WIN32
+#define CALL_CONV WINAPI
+#else
+#define CALL_CONV
+#endif
+
+/** @defgroup internal LMDB Internals
+ * @{
+ */
+/** @defgroup compat Compatibility Macros
+ * A bunch of macros to minimize the amount of platform-specific ifdefs
+ * needed throughout the rest of the code. When the features this library
+ * needs are similar enough to POSIX to be hidden in a one-or-two line
+ * replacement, this macro approach is used.
+ * @{
+ */
+
+ /** Features under development */
+#ifndef MDB_DEVEL
+#define MDB_DEVEL 0
+#endif
+
+ /** Wrapper around __func__, which is a C99 feature */
+#if __STDC_VERSION__ >= 199901L
+# define mdb_func_ __func__
+#elif __GNUC__ >= 2 || _MSC_VER >= 1300
+# define mdb_func_ __FUNCTION__
+#else
+/* If a debug message says <mdb_unknown>(), update the #if statements above */
+# define mdb_func_ "<mdb_unknown>"
+#endif
+
+/* Internal error codes, not exposed outside liblmdb */
+#define MDB_NO_ROOT (MDB_LAST_ERRCODE + 10)
+#ifdef _WIN32
+#define MDB_OWNERDEAD ((int) WAIT_ABANDONED)
+#elif defined(MDB_USE_POSIX_MUTEX) && defined(EOWNERDEAD)
+#define MDB_OWNERDEAD EOWNERDEAD /**< #LOCK_MUTEX0() result if dead owner */
+#endif
+
+#ifdef __GLIBC__
+#define GLIBC_VER ((__GLIBC__ << 16 )| __GLIBC_MINOR__)
+#endif
+/** Some platforms define the EOWNERDEAD error code
+ * even though they don't support Robust Mutexes.
+ * Compile with -DMDB_USE_ROBUST=0, or use some other
+ * mechanism like -DMDB_USE_POSIX_SEM instead of
+ * -DMDB_USE_POSIX_MUTEX.
+ * (Posix semaphores are not robust.)
+ */
+#ifndef MDB_USE_ROBUST
+/* Android currently lacks Robust Mutex support. So does glibc < 2.4. */
+# if defined(MDB_USE_POSIX_MUTEX) && (defined(ANDROID) || \
+ (defined(__GLIBC__) && GLIBC_VER < 0x020004))
+# define MDB_USE_ROBUST 0
+# else
+# define MDB_USE_ROBUST 1
+# endif
+#endif /* !MDB_USE_ROBUST */
+
+#if defined(MDB_USE_POSIX_MUTEX) && (MDB_USE_ROBUST)
+/* glibc < 2.12 only provided _np API */
+# if (defined(__GLIBC__) && GLIBC_VER < 0x02000c) || \
+ (defined(PTHREAD_MUTEX_ROBUST_NP) && !defined(PTHREAD_MUTEX_ROBUST))
+# define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
+# define pthread_mutexattr_setrobust(attr, flag) pthread_mutexattr_setrobust_np(attr, flag)
+# define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex)
+# endif
+#endif /* MDB_USE_POSIX_MUTEX && MDB_USE_ROBUST */
+
+#if defined(MDB_OWNERDEAD) && (MDB_USE_ROBUST)
+#define MDB_ROBUST_SUPPORTED 1
+#endif
+
+#ifdef _WIN32
+#define MDB_USE_HASH 1
+#define MDB_PIDLOCK 0
+#define THREAD_RET DWORD
+#define pthread_t HANDLE
+#define pthread_mutex_t HANDLE
+#define pthread_cond_t HANDLE
+typedef HANDLE mdb_mutex_t, mdb_mutexref_t;
+#define pthread_key_t DWORD
+#define pthread_self() GetCurrentThreadId()
+#define pthread_key_create(x,y) \
+ ((*(x) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? ErrCode() : 0)
+#define pthread_key_delete(x) TlsFree(x)
+#define pthread_getspecific(x) TlsGetValue(x)
+#define pthread_setspecific(x,y) (TlsSetValue(x,y) ? 0 : ErrCode())
+#define pthread_mutex_unlock(x) ReleaseMutex(*x)
+#define pthread_mutex_lock(x) WaitForSingleObject(*x, INFINITE)
+#define pthread_cond_signal(x) SetEvent(*x)
+#define pthread_cond_wait(cond,mutex) do{SignalObjectAndWait(*mutex, *cond, INFINITE, FALSE); WaitForSingleObject(*mutex, INFINITE);}while(0)
+#define THREAD_CREATE(thr,start,arg) \
+ (((thr) = CreateThread(NULL, 0, start, arg, 0, NULL)) ? 0 : ErrCode())
+#define THREAD_FINISH(thr) \
+ (WaitForSingleObject(thr, INFINITE) ? ErrCode() : 0)
+#define LOCK_MUTEX0(mutex) WaitForSingleObject(mutex, INFINITE)
+#define UNLOCK_MUTEX(mutex) ReleaseMutex(mutex)
+#define mdb_mutex_consistent(mutex) 0
+#define getpid() GetCurrentProcessId()
+#define MDB_FDATASYNC(fd) (!FlushFileBuffers(fd))
+#define MDB_MSYNC(addr,len,flags) (!FlushViewOfFile(addr,len))
+#define ErrCode() GetLastError()
+#define GET_PAGESIZE(x) {SYSTEM_INFO si; GetSystemInfo(&si); (x) = si.dwPageSize;}
+#define close(fd) (CloseHandle(fd) ? 0 : -1)
+#define munmap(ptr,len) UnmapViewOfFile(ptr)
+#ifdef PROCESS_QUERY_LIMITED_INFORMATION
+#define MDB_PROCESS_QUERY_LIMITED_INFORMATION PROCESS_QUERY_LIMITED_INFORMATION
+#else
+#define MDB_PROCESS_QUERY_LIMITED_INFORMATION 0x1000
+#endif
+#define Z "I"
+#else
+#define THREAD_RET void *
+#define THREAD_CREATE(thr,start,arg) pthread_create(&thr,NULL,start,arg)
+#define THREAD_FINISH(thr) pthread_join(thr,NULL)
+#define Z "z" /**< printf format modifier for size_t */
+
+ /** For MDB_LOCK_FORMAT: True if readers take a pid lock in the lockfile */
+#define MDB_PIDLOCK 1
+
+#ifdef MDB_USE_POSIX_SEM
+
+typedef sem_t *mdb_mutex_t, *mdb_mutexref_t;
+#define LOCK_MUTEX0(mutex) mdb_sem_wait(mutex)
+#define UNLOCK_MUTEX(mutex) sem_post(mutex)
+
+static int
+mdb_sem_wait(sem_t *sem)
+{
+ int rc;
+ while ((rc = sem_wait(sem)) && (rc = errno) == EINTR) ;
+ return rc;
+}
+
+#else /* MDB_USE_POSIX_MUTEX: */
+ /** Shared mutex/semaphore as the original is stored.
+ *
+ * Not for copies. Instead it can be assigned to an #mdb_mutexref_t.
+ * When mdb_mutexref_t is a pointer and mdb_mutex_t is not, then it
+ * is array[size 1] so it can be assigned to the pointer.
+ */
+typedef pthread_mutex_t mdb_mutex_t[1];
+ /** Reference to an #mdb_mutex_t */
+typedef pthread_mutex_t *mdb_mutexref_t;
+ /** Lock the reader or writer mutex.
+ * Returns 0 or a code to give #mdb_mutex_failed(), as in #LOCK_MUTEX().
+ */
+#define LOCK_MUTEX0(mutex) pthread_mutex_lock(mutex)
+ /** Unlock the reader or writer mutex.
+ */
+#define UNLOCK_MUTEX(mutex) pthread_mutex_unlock(mutex)
+ /** Mark mutex-protected data as repaired, after death of previous owner.
+ */
+#define mdb_mutex_consistent(mutex) pthread_mutex_consistent(mutex)
+#endif /* MDB_USE_POSIX_SEM */
+
+ /** Get the error code for the last failed system function.
+ */
+#define ErrCode() errno
+
+ /** An abstraction for a file handle.
+ * On POSIX systems file handles are small integers. On Windows
+ * they're opaque pointers.
+ */
+#define HANDLE int
+
+ /** A value for an invalid file handle.
+ * Mainly used to initialize file variables and signify that they are
+ * unused.
+ */
+#define INVALID_HANDLE_VALUE (-1)
+
+ /** Get the size of a memory page for the system.
+ * This is the basic size that the platform's memory manager uses, and is
+ * fundamental to the use of memory-mapped files.
+ */
+#define GET_PAGESIZE(x) ((x) = sysconf(_SC_PAGE_SIZE))
+#endif
+
+#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM)
+#define MNAME_LEN 32
+#else
+#define MNAME_LEN (sizeof(pthread_mutex_t))
+#endif
+
+/** @} */
+
+#ifdef MDB_ROBUST_SUPPORTED
+ /** Lock mutex, handle any error, set rc = result.
+ * Return 0 on success, nonzero (not rc) on error.
+ */
+#define LOCK_MUTEX(rc, env, mutex) \
+ (((rc) = LOCK_MUTEX0(mutex)) && \
+ ((rc) = mdb_mutex_failed(env, mutex, rc)))
+static int mdb_mutex_failed(MDB_env *env, mdb_mutexref_t mutex, int rc);
+#else
+#define LOCK_MUTEX(rc, env, mutex) ((rc) = LOCK_MUTEX0(mutex))
+#define mdb_mutex_failed(env, mutex, rc) (rc)
+#endif
+
+#ifndef _WIN32
+/** A flag for opening a file and requesting synchronous data writes.
+ * This is only used when writing a meta page. It's not strictly needed;
+ * we could just do a normal write and then immediately perform a flush.
+ * But if this flag is available it saves us an extra system call.
+ *
+ * @note If O_DSYNC is undefined but exists in /usr/include,
+ * preferably set some compiler flag to get the definition.
+ */
+#ifndef MDB_DSYNC
+# ifdef O_DSYNC
+# define MDB_DSYNC O_DSYNC
+# else
+# define MDB_DSYNC O_SYNC
+# endif
+#endif
+#endif
+
+/** Function for flushing the data of a file. Define this to fsync
+ * if fdatasync() is not supported.
+ */
+#ifndef MDB_FDATASYNC
+# define MDB_FDATASYNC fdatasync
+#endif
+
+#ifndef MDB_MSYNC
+# define MDB_MSYNC(addr,len,flags) msync(addr,len,flags)
+#endif
+
+#ifndef MS_SYNC
+#define MS_SYNC 1
+#endif
+
+#ifndef MS_ASYNC
+#define MS_ASYNC 0
+#endif
+
+ /** A page number in the database.
+ * Note that 64 bit page numbers are overkill, since pages themselves
+ * already represent 12-13 bits of addressable memory, and the OS will
+ * always limit applications to a maximum of 63 bits of address space.
+ *
+ * @note In the #MDB_node structure, we only store 48 bits of this value,
+ * which thus limits us to only 60 bits of addressable data.
+ */
+typedef MDB_ID pgno_t;
+
+ /** A transaction ID.
+ * See struct MDB_txn.mt_txnid for details.
+ */
+typedef MDB_ID txnid_t;
+
+/** @defgroup debug Debug Macros
+ * @{
+ */
+#ifndef MDB_DEBUG
+ /** Enable debug output. Needs variable argument macros (a C99 feature).
+ * Set this to 1 for copious tracing. Set to 2 to add dumps of all IDLs
+ * read from and written to the database (used for free space management).
+ */
+#define MDB_DEBUG 0
+#endif
+
+#if MDB_DEBUG
+static int mdb_debug;
+static txnid_t mdb_debug_start;
+
+ /** Print a debug message with printf formatting.
+ * Requires double parenthesis around 2 or more args.
+ */
+# define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args))
+# define DPRINTF0(fmt, ...) \
+ fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__)
+#else
+# define DPRINTF(args) ((void) 0)
+#endif
+ /** Print a debug string.
+ * The string is printed literally, with no format processing.
+ */
+#define DPUTS(arg) DPRINTF(("%s", arg))
+ /** Debuging output value of a cursor DBI: Negative in a sub-cursor. */
+#define DDBI(mc) \
+ (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi)
+/** @} */
+
+ /** @brief The maximum size of a database page.
+ *
+ * It is 32k or 64k, since value-PAGEBASE must fit in
+ * #MDB_page.%mp_upper.
+ *
+ * LMDB will use database pages < OS pages if needed.
+ * That causes more I/O in write transactions: The OS must
+ * know (read) the whole page before writing a partial page.
+ *
+ * Note that we don't currently support Huge pages. On Linux,
+ * regular data files cannot use Huge pages, and in general
+ * Huge pages aren't actually pageable. We rely on the OS
+ * demand-pager to read our data and page it out when memory
+ * pressure from other processes is high. So until OSs have
+ * actual paging support for Huge pages, they're not viable.
+ */
+#define MAX_PAGESIZE (PAGEBASE ? 0x10000 : 0x8000)
+
+ /** The minimum number of keys required in a database page.
+ * Setting this to a larger value will place a smaller bound on the
+ * maximum size of a data item. Data items larger than this size will
+ * be pushed into overflow pages instead of being stored directly in
+ * the B-tree node. This value used to default to 4. With a page size
+ * of 4096 bytes that meant that any item larger than 1024 bytes would
+ * go into an overflow page. That also meant that on average 2-3KB of
+ * each overflow page was wasted space. The value cannot be lower than
+ * 2 because then there would no longer be a tree structure. With this
+ * value, items larger than 2KB will go into overflow pages, and on
+ * average only 1KB will be wasted.
+ */
+#define MDB_MINKEYS 2
+
+ /** A stamp that identifies a file as an LMDB file.
+ * There's nothing special about this value other than that it is easily
+ * recognizable, and it will reflect any byte order mismatches.
+ */
+#define MDB_MAGIC 0xBEEFC0DE
+
+ /** The version number for a database's datafile format. */
+#define MDB_DATA_VERSION ((MDB_DEVEL) ? 999 : 1)
+ /** The version number for a database's lockfile format. */
+#define MDB_LOCK_VERSION 1
+
+ /** @brief The max size of a key we can write, or 0 for computed max.
+ *
+ * This macro should normally be left alone or set to 0.
+ * Note that a database with big keys or dupsort data cannot be
+ * reliably modified by a liblmdb which uses a smaller max.
+ * The default is 511 for backwards compat, or 0 when #MDB_DEVEL.
+ *
+ * Other values are allowed, for backwards compat. However:
+ * A value bigger than the computed max can break if you do not
+ * know what you are doing, and liblmdb <= 0.9.10 can break when
+ * modifying a DB with keys/dupsort data bigger than its max.
+ *
+ * Data items in an #MDB_DUPSORT database are also limited to
+ * this size, since they're actually keys of a sub-DB. Keys and
+ * #MDB_DUPSORT data items must fit on a node in a regular page.
+ */
+#ifndef MDB_MAXKEYSIZE
+#define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511)
+#endif
+
+ /** The maximum size of a key we can write to the environment. */
+#if MDB_MAXKEYSIZE
+#define ENV_MAXKEY(env) (MDB_MAXKEYSIZE)
+#else
+#define ENV_MAXKEY(env) ((env)->me_maxkey)
+#endif
+
+ /** @brief The maximum size of a data item.
+ *
+ * We only store a 32 bit value for node sizes.
+ */
+#define MAXDATASIZE 0xffffffffUL
+
+#if MDB_DEBUG
+ /** Key size which fits in a #DKBUF.
+ * @ingroup debug
+ */
+#define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511)
+ /** A key buffer.
+ * @ingroup debug
+ * This is used for printing a hex dump of a key's contents.
+ */
+#define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1]
+ /** Display a key in hex.
+ * @ingroup debug
+ * Invoke a function to display a key in hex.
+ */
+#define DKEY(x) mdb_dkey(x, kbuf)
+#else
+#define DKBUF
+#define DKEY(x) 0
+#endif
+
+ /** An invalid page number.
+ * Mainly used to denote an empty tree.
+ */
+#define P_INVALID (~(pgno_t)0)
+
+ /** Test if the flags \b f are set in a flag word \b w. */
+#define F_ISSET(w, f) (((w) & (f)) == (f))
+
+ /** Round \b n up to an even number. */
+#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
+
+ /** Used for offsets within a single page.
+ * Since memory pages are typically 4 or 8KB in size, 12-13 bits,
+ * this is plenty.
+ */
+typedef uint16_t indx_t;
+
+ /** Default size of memory map.
+ * This is certainly too small for any actual applications. Apps should always set
+ * the size explicitly using #mdb_env_set_mapsize().
+ */
+#define DEFAULT_MAPSIZE 1048576
+
+/** @defgroup readers Reader Lock Table
+ * Readers don't acquire any locks for their data access. Instead, they
+ * simply record their transaction ID in the reader table. The reader
+ * mutex is needed just to find an empty slot in the reader table. The
+ * slot's address is saved in thread-specific data so that subsequent read
+ * transactions started by the same thread need no further locking to proceed.
+ *
+ * If #MDB_NOTLS is set, the slot address is not saved in thread-specific data.
+ *
+ * No reader table is used if the database is on a read-only filesystem, or
+ * if #MDB_NOLOCK is set.
+ *
+ * Since the database uses multi-version concurrency control, readers don't
+ * actually need any locking. This table is used to keep track of which
+ * readers are using data from which old transactions, so that we'll know
+ * when a particular old transaction is no longer in use. Old transactions
+ * that have discarded any data pages can then have those pages reclaimed
+ * for use by a later write transaction.
+ *
+ * The lock table is constructed such that reader slots are aligned with the
+ * processor's cache line size. Any slot is only ever used by one thread.
+ * This alignment guarantees that there will be no contention or cache
+ * thrashing as threads update their own slot info, and also eliminates
+ * any need for locking when accessing a slot.
+ *
+ * A writer thread will scan every slot in the table to determine the oldest
+ * outstanding reader transaction. Any freed pages older than this will be
+ * reclaimed by the writer. The writer doesn't use any locks when scanning
+ * this table. This means that there's no guarantee that the writer will
+ * see the most up-to-date reader info, but that's not required for correct
+ * operation - all we need is to know the upper bound on the oldest reader,
+ * we don't care at all about the newest reader. So the only consequence of
+ * reading stale information here is that old pages might hang around a
+ * while longer before being reclaimed. That's actually good anyway, because
+ * the longer we delay reclaiming old pages, the more likely it is that a
+ * string of contiguous pages can be found after coalescing old pages from
+ * many old transactions together.
+ * @{
+ */
+ /** Number of slots in the reader table.
+ * This value was chosen somewhat arbitrarily. 126 readers plus a
+ * couple mutexes fit exactly into 8KB on my development machine.
+ * Applications should set the table size using #mdb_env_set_maxreaders().
+ */
+#define DEFAULT_READERS 126
+
+ /** The size of a CPU cache line in bytes. We want our lock structures
+ * aligned to this size to avoid false cache line sharing in the
+ * lock table.
+ * This value works for most CPUs. For Itanium this should be 128.
+ */
+#ifndef CACHELINE
+#define CACHELINE 64
+#endif
+
+ /** The information we store in a single slot of the reader table.
+ * In addition to a transaction ID, we also record the process and
+ * thread ID that owns a slot, so that we can detect stale information,
+ * e.g. threads or processes that went away without cleaning up.
+ * @note We currently don't check for stale records. We simply re-init
+ * the table when we know that we're the only process opening the
+ * lock file.
+ */
+typedef struct MDB_rxbody {
+ /** Current Transaction ID when this transaction began, or (txnid_t)-1.
+ * Multiple readers that start at the same time will probably have the
+ * same ID here. Again, it's not important to exclude them from
+ * anything; all we need to know is which version of the DB they
+ * started from so we can avoid overwriting any data used in that
+ * particular version.
+ */
+ volatile txnid_t mrb_txnid;
+ /** The process ID of the process owning this reader txn. */
+ volatile MDB_PID_T mrb_pid;
+ /** The thread ID of the thread owning this txn. */
+ volatile MDB_THR_T mrb_tid;
+} MDB_rxbody;
+
+ /** The actual reader record, with cacheline padding. */
+typedef struct MDB_reader {
+ union {
+ MDB_rxbody mrx;
+ /** shorthand for mrb_txnid */
+#define mr_txnid mru.mrx.mrb_txnid
+#define mr_pid mru.mrx.mrb_pid
+#define mr_tid mru.mrx.mrb_tid
+ /** cache line alignment */
+ char pad[(sizeof(MDB_rxbody)+CACHELINE-1) & ~(CACHELINE-1)];
+ } mru;
+} MDB_reader;
+
+ /** The header for the reader table.
+ * The table resides in a memory-mapped file. (This is a different file
+ * than is used for the main database.)
+ *
+ * For POSIX the actual mutexes reside in the shared memory of this
+ * mapped file. On Windows, mutexes are named objects allocated by the
+ * kernel; we store the mutex names in this mapped file so that other
+ * processes can grab them. This same approach is also used on
+ * MacOSX/Darwin (using named semaphores) since MacOSX doesn't support
+ * process-shared POSIX mutexes. For these cases where a named object
+ * is used, the object name is derived from a 64 bit FNV hash of the
+ * environment pathname. As such, naming collisions are extremely
+ * unlikely. If a collision occurs, the results are unpredictable.
+ */
+typedef struct MDB_txbody {
+ /** Stamp identifying this as an LMDB file. It must be set
+ * to #MDB_MAGIC. */
+ uint32_t mtb_magic;
+ /** Format of this lock file. Must be set to #MDB_LOCK_FORMAT. */
+ uint32_t mtb_format;
+#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM)
+ char mtb_rmname[MNAME_LEN];
+#else
+ /** Mutex protecting access to this table.
+ * This is the reader table lock used with LOCK_MUTEX().
+ */
+ mdb_mutex_t mtb_rmutex;
+#endif
+ /** The ID of the last transaction committed to the database.
+ * This is recorded here only for convenience; the value can always
+ * be determined by reading the main database meta pages.
+ */
+ volatile txnid_t mtb_txnid;
+ /** The number of slots that have been used in the reader table.
+ * This always records the maximum count, it is not decremented
+ * when readers release their slots.
+ */
+ volatile unsigned mtb_numreaders;
+} MDB_txbody;
+
+ /** The actual reader table definition. */
+typedef struct MDB_txninfo {
+ union {
+ MDB_txbody mtb;
+#define mti_magic mt1.mtb.mtb_magic
+#define mti_format mt1.mtb.mtb_format
+#define mti_rmutex mt1.mtb.mtb_rmutex
+#define mti_rmname mt1.mtb.mtb_rmname
+#define mti_txnid mt1.mtb.mtb_txnid
+#define mti_numreaders mt1.mtb.mtb_numreaders
+ char pad[(sizeof(MDB_txbody)+CACHELINE-1) & ~(CACHELINE-1)];
+ } mt1;
+ union {
+#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM)
+ char mt2_wmname[MNAME_LEN];
+#define mti_wmname mt2.mt2_wmname
+#else
+ mdb_mutex_t mt2_wmutex;
+#define mti_wmutex mt2.mt2_wmutex
+#endif
+ char pad[(MNAME_LEN+CACHELINE-1) & ~(CACHELINE-1)];
+ } mt2;
+ MDB_reader mti_readers[1];
+} MDB_txninfo;
+
+ /** Lockfile format signature: version, features and field layout */
+#define MDB_LOCK_FORMAT \
+ ((uint32_t) \
+ ((MDB_LOCK_VERSION) \
+ /* Flags which describe functionality */ \
+ + (((MDB_PIDLOCK) != 0) << 16)))
+/** @} */
+
+/** Common header for all page types. The page type depends on #mp_flags.
+ *
+ * #P_BRANCH and #P_LEAF pages have unsorted '#MDB_node's at the end, with
+ * sorted #mp_ptrs[] entries referring to them. Exception: #P_LEAF2 pages
+ * omit mp_ptrs and pack sorted #MDB_DUPFIXED values after the page header.
+ *
+ * #P_OVERFLOW records occupy one or more contiguous pages where only the
+ * first has a page header. They hold the real data of #F_BIGDATA nodes.
+ *
+ * #P_SUBP sub-pages are small leaf "pages" with duplicate data.
+ * A node with flag #F_DUPDATA but not #F_SUBDATA contains a sub-page.
+ * (Duplicate data can also go in sub-databases, which use normal pages.)
+ *
+ * #P_META pages contain #MDB_meta, the start point of an LMDB snapshot.
+ *
+ * Each non-metapage up to #MDB_meta.%mm_last_pg is reachable exactly once
+ * in the snapshot: Either used by a database or listed in a freeDB record.
+ */
+typedef struct MDB_page {
+#define mp_pgno mp_p.p_pgno
+#define mp_next mp_p.p_next
+ union {
+ pgno_t p_pgno; /**< page number */
+ struct MDB_page *p_next; /**< for in-memory list of freed pages */
+ } mp_p;
+ uint16_t mp_pad; /**< key size if this is a LEAF2 page */
+/** @defgroup mdb_page Page Flags
+ * @ingroup internal
+ * Flags for the page headers.
+ * @{
+ */
+#define P_BRANCH 0x01 /**< branch page */
+#define P_LEAF 0x02 /**< leaf page */
+#define P_OVERFLOW 0x04 /**< overflow page */
+#define P_META 0x08 /**< meta page */
+#define P_DIRTY 0x10 /**< dirty page, also set for #P_SUBP pages */
+#define P_LEAF2 0x20 /**< for #MDB_DUPFIXED records */
+#define P_SUBP 0x40 /**< for #MDB_DUPSORT sub-pages */
+#define P_LOOSE 0x4000 /**< page was dirtied then freed, can be reused */
+#define P_KEEP 0x8000 /**< leave this page alone during spill */
+/** @} */
+ uint16_t mp_flags; /**< @ref mdb_page */
+#define mp_lower mp_pb.pb.pb_lower
+#define mp_upper mp_pb.pb.pb_upper
+#define mp_pages mp_pb.pb_pages
+ union {
+ struct {
+ indx_t pb_lower; /**< lower bound of free space */
+ indx_t pb_upper; /**< upper bound of free space */
+ } pb;
+ uint32_t pb_pages; /**< number of overflow pages */
+ } mp_pb;
+ indx_t mp_ptrs[1]; /**< dynamic size */
+} MDB_page;
+
+ /** Size of the page header, excluding dynamic data at the end */
+#define PAGEHDRSZ ((unsigned) offsetof(MDB_page, mp_ptrs))
+
+ /** Address of first usable data byte in a page, after the header */
+#define METADATA(p) ((void *)((char *)(p) + PAGEHDRSZ))
+
+ /** ITS#7713, change PAGEBASE to handle 65536 byte pages */
+#define PAGEBASE ((MDB_DEVEL) ? PAGEHDRSZ : 0)
+
+ /** Number of nodes on a page */
+#define NUMKEYS(p) (((p)->mp_lower - (PAGEHDRSZ-PAGEBASE)) >> 1)
+
+ /** The amount of space remaining in the page */
+#define SIZELEFT(p) (indx_t)((p)->mp_upper - (p)->mp_lower)
+
+ /** The percentage of space used in the page, in tenths of a percent. */
+#define PAGEFILL(env, p) (1000L * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \
+ ((env)->me_psize - PAGEHDRSZ))
+ /** The minimum page fill factor, in tenths of a percent.
+ * Pages emptier than this are candidates for merging.
+ */
+#define FILL_THRESHOLD 250
+
+ /** Test if a page is a leaf page */
+#define IS_LEAF(p) F_ISSET((p)->mp_flags, P_LEAF)
+ /** Test if a page is a LEAF2 page */
+#define IS_LEAF2(p) F_ISSET((p)->mp_flags, P_LEAF2)
+ /** Test if a page is a branch page */
+#define IS_BRANCH(p) F_ISSET((p)->mp_flags, P_BRANCH)
+ /** Test if a page is an overflow page */
+#define IS_OVERFLOW(p) F_ISSET((p)->mp_flags, P_OVERFLOW)
+ /** Test if a page is a sub page */
+#define IS_SUBP(p) F_ISSET((p)->mp_flags, P_SUBP)
+
+ /** The number of overflow pages needed to store the given size. */
+#define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1)
+
+ /** Link in #MDB_txn.%mt_loose_pgs list.
+ * Kept outside the page header, which is needed when reusing the page.
+ */
+#define NEXT_LOOSE_PAGE(p) (*(MDB_page **)((p) + 2))
+
+ /** Header for a single key/data pair within a page.
+ * Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2.
+ * We guarantee 2-byte alignment for 'MDB_node's.
+ *
+ * #mn_lo and #mn_hi are used for data size on leaf nodes, and for child
+ * pgno on branch nodes. On 64 bit platforms, #mn_flags is also used
+ * for pgno. (Branch nodes have no flags). Lo and hi are in host byte
+ * order in case some accesses can be optimized to 32-bit word access.
+ *
+ * Leaf node flags describe node contents. #F_BIGDATA says the node's
+ * data part is the page number of an overflow page with actual data.
+ * #F_DUPDATA and #F_SUBDATA can be combined giving duplicate data in
+ * a sub-page/sub-database, and named databases (just #F_SUBDATA).
+ */
+typedef struct MDB_node {
+ /** part of data size or pgno
+ * @{ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ unsigned short mn_lo, mn_hi;
+#else
+ unsigned short mn_hi, mn_lo;
+#endif
+ /** @} */
+/** @defgroup mdb_node Node Flags
+ * @ingroup internal
+ * Flags for node headers.
+ * @{
+ */
+#define F_BIGDATA 0x01 /**< data put on overflow page */
+#define F_SUBDATA 0x02 /**< data is a sub-database */
+#define F_DUPDATA 0x04 /**< data has duplicates */
+
+/** valid flags for #mdb_node_add() */
+#define NODE_ADD_FLAGS (F_DUPDATA|F_SUBDATA|MDB_RESERVE|MDB_APPEND)
+
+/** @} */
+ unsigned short mn_flags; /**< @ref mdb_node */
+ unsigned short mn_ksize; /**< key size */
+ char mn_data[1]; /**< key and data are appended here */
+} MDB_node;
+
+ /** Size of the node header, excluding dynamic data at the end */
+#define NODESIZE offsetof(MDB_node, mn_data)
+
+ /** Bit position of top word in page number, for shifting mn_flags */
+#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0)
+
+ /** Size of a node in a branch page with a given key.
+ * This is just the node header plus the key, there is no data.
+ */
+#define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->mv_size))
+
+ /** Size of a node in a leaf page with a given key and data.
+ * This is node header plus key plus data size.
+ */
+#define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size)
+
+ /** Address of node \b i in page \b p */
+#define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEBASE))
+
+ /** Address of the key for the node */
+#define NODEKEY(node) (void *)((node)->mn_data)
+
+ /** Address of the data for a node */
+#define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize)
+
+ /** Get the page number pointed to by a branch node */
+#define NODEPGNO(node) \
+ ((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | \
+ (PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0))
+ /** Set the page number in a branch node */
+#define SETPGNO(node,pgno) do { \
+ (node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; \
+ if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0)
+
+ /** Get the size of the data in a leaf node */
+#define NODEDSZ(node) ((node)->mn_lo | ((unsigned)(node)->mn_hi << 16))
+ /** Set the size of the data for a leaf node */
+#define SETDSZ(node,size) do { \
+ (node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0)
+ /** The size of a key in a node */
+#define NODEKSZ(node) ((node)->mn_ksize)
+
+ /** Copy a page number from src to dst */
+#ifdef MISALIGNED_OK
+#define COPY_PGNO(dst,src) dst = src
+#else
+#if SIZE_MAX > 4294967295UL
+#define COPY_PGNO(dst,src) do { \
+ unsigned short *s, *d; \
+ s = (unsigned short *)&(src); \
+ d = (unsigned short *)&(dst); \
+ *d++ = *s++; \
+ *d++ = *s++; \
+ *d++ = *s++; \
+ *d = *s; \
+} while (0)
+#else
+#define COPY_PGNO(dst,src) do { \
+ unsigned short *s, *d; \
+ s = (unsigned short *)&(src); \
+ d = (unsigned short *)&(dst); \
+ *d++ = *s++; \
+ *d = *s; \
+} while (0)
+#endif
+#endif
+ /** The address of a key in a LEAF2 page.
+ * LEAF2 pages are used for #MDB_DUPFIXED sorted-duplicate sub-DBs.
+ * There are no node headers, keys are stored contiguously.
+ */
+#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i)*(ks)))
+
+ /** Set the \b node's key into \b keyptr, if requested. */
+#define MDB_GET_KEY(node, keyptr) { if ((keyptr) != NULL) { \
+ (keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } }
+
+ /** Set the \b node's key into \b key. */
+#define MDB_GET_KEY2(node, key) { key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); }
+
+ /** Information about a single database in the environment. */
+typedef struct MDB_db {
+ uint32_t md_pad; /**< also ksize for LEAF2 pages */
+ uint16_t md_flags; /**< @ref mdb_dbi_open */
+ uint16_t md_depth; /**< depth of this tree */
+ pgno_t md_branch_pages; /**< number of internal pages */
+ pgno_t md_leaf_pages; /**< number of leaf pages */
+ pgno_t md_overflow_pages; /**< number of overflow pages */
+ size_t md_entries; /**< number of data items */
+ pgno_t md_root; /**< the root page of this tree */
+} MDB_db;
+
+#define MDB_VALID 0x8000 /**< DB handle is valid, for me_dbflags */
+#define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID))
+ /** #mdb_dbi_open() flags */
+#define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|\
+ MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE)
+
+ /** Handle for the DB used to track free pages. */
+#define FREE_DBI 0
+ /** Handle for the default DB. */
+#define MAIN_DBI 1
+ /** Number of DBs in metapage (free and main) - also hardcoded elsewhere */
+#define CORE_DBS 2
+
+ /** Number of meta pages - also hardcoded elsewhere */
+#define NUM_METAS 2
+
+ /** Meta page content.
+ * A meta page is the start point for accessing a database snapshot.
+ * Pages 0-1 are meta pages. Transaction N writes meta page #(N % 2).
+ */
+typedef struct MDB_meta {
+ /** Stamp identifying this as an LMDB file. It must be set
+ * to #MDB_MAGIC. */
+ uint32_t mm_magic;
+ /** Version number of this file. Must be set to #MDB_DATA_VERSION. */
+ uint32_t mm_version;
+ void *mm_address; /**< address for fixed mapping */
+ size_t mm_mapsize; /**< size of mmap region */
+ MDB_db mm_dbs[CORE_DBS]; /**< first is free space, 2nd is main db */
+ /** The size of pages used in this DB */
+#define mm_psize mm_dbs[FREE_DBI].md_pad
+ /** Any persistent environment flags. @ref mdb_env */
+#define mm_flags mm_dbs[FREE_DBI].md_flags
+ /** Last used page in the datafile.
+ * Actually the file may be shorter if the freeDB lists the final pages.
+ */
+ pgno_t mm_last_pg;
+ volatile txnid_t mm_txnid; /**< txnid that committed this page */
+} MDB_meta;
+
+ /** Buffer for a stack-allocated meta page.
+ * The members define size and alignment, and silence type
+ * aliasing warnings. They are not used directly; that could
+ * mean incorrectly using several union members in parallel.
+ */
+typedef union MDB_metabuf {
+ MDB_page mb_page;
+ struct {
+ char mm_pad[PAGEHDRSZ];
+ MDB_meta mm_meta;
+ } mb_metabuf;
+} MDB_metabuf;
+
+ /** Auxiliary DB info.
+ * The information here is mostly static/read-only. There is
+ * only a single copy of this record in the environment.
+ */
+typedef struct MDB_dbx {
+ MDB_val md_name; /**< name of the database */
+ MDB_cmp_func *md_cmp; /**< function for comparing keys */
+ MDB_cmp_func *md_dcmp; /**< function for comparing data items */
+ MDB_rel_func *md_rel; /**< user relocate function */
+ void *md_relctx; /**< user-provided context for md_rel */
+} MDB_dbx;
+
+ /** A database transaction.
+ * Every operation requires a transaction handle.
+ */
+struct MDB_txn {
+ MDB_txn *mt_parent; /**< parent of a nested txn */
+ /** Nested txn under this txn, set together with flag #MDB_TXN_HAS_CHILD */
+ MDB_txn *mt_child;
+ pgno_t mt_next_pgno; /**< next unallocated page */
+ /** The ID of this transaction. IDs are integers incrementing from 1.
+ * Only committed write transactions increment the ID. If a transaction
+ * aborts, the ID may be re-used by the next writer.
+ */
+ txnid_t mt_txnid;
+ MDB_env *mt_env; /**< the DB environment */
+ /** The list of pages that became unused during this transaction.
+ */
+ MDB_IDL mt_free_pgs;
+ /** The list of loose pages that became unused and may be reused
+ * in this transaction, linked through #NEXT_LOOSE_PAGE(page).
+ */
+ MDB_page *mt_loose_pgs;
+ /** Number of loose pages (#mt_loose_pgs) */
+ int mt_loose_count;
+ /** The sorted list of dirty pages we temporarily wrote to disk
+ * because the dirty list was full. page numbers in here are
+ * shifted left by 1, deleted slots have the LSB set.
+ */
+ MDB_IDL mt_spill_pgs;
+ union {
+ /** For write txns: Modified pages. Sorted when not MDB_WRITEMAP. */
+ MDB_ID2L dirty_list;
+ /** For read txns: This thread/txn's reader table slot, or NULL. */
+ MDB_reader *reader;
+ } mt_u;
+ /** Array of records for each DB known in the environment. */
+ MDB_dbx *mt_dbxs;
+ /** Array of MDB_db records for each known DB */
+ MDB_db *mt_dbs;
+ /** Array of sequence numbers for each DB handle */
+ unsigned int *mt_dbiseqs;
+/** @defgroup mt_dbflag Transaction DB Flags
+ * @ingroup internal
+ * @{
+ */
+#define DB_DIRTY 0x01 /**< DB was written in this txn */
+#define DB_STALE 0x02 /**< Named-DB record is older than txnID */
+#define DB_NEW 0x04 /**< Named-DB handle opened in this txn */
+#define DB_VALID 0x08 /**< DB handle is valid, see also #MDB_VALID */
+#define DB_USRVALID 0x10 /**< As #DB_VALID, but not set for #FREE_DBI */
+#define DB_DUPDATA 0x20 /**< DB is #MDB_DUPSORT data */
+/** @} */
+ /** In write txns, array of cursors for each DB */
+ MDB_cursor **mt_cursors;
+ /** Array of flags for each DB */
+ unsigned char *mt_dbflags;
+ /** Number of DB records in use, or 0 when the txn is finished.
+ * This number only ever increments until the txn finishes; we
+ * don't decrement it when individual DB handles are closed.
+ */
+ MDB_dbi mt_numdbs;
+
+/** @defgroup mdb_txn Transaction Flags
+ * @ingroup internal
+ * @{
+ */
+ /** #mdb_txn_begin() flags */
+#define MDB_TXN_BEGIN_FLAGS MDB_RDONLY
+#define MDB_TXN_RDONLY MDB_RDONLY /**< read-only transaction */
+ /* internal txn flags */
+#define MDB_TXN_WRITEMAP MDB_WRITEMAP /**< copy of #MDB_env flag in writers */
+#define MDB_TXN_FINISHED 0x01 /**< txn is finished or never began */
+#define MDB_TXN_ERROR 0x02 /**< txn is unusable after an error */
+#define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */
+#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
+#define MDB_TXN_HAS_CHILD 0x10 /**< txn has an #MDB_txn.%mt_child */
+ /** most operations on the txn are currently illegal */
+#define MDB_TXN_BLOCKED (MDB_TXN_FINISHED|MDB_TXN_ERROR|MDB_TXN_HAS_CHILD)
+/** @} */
+ unsigned int mt_flags; /**< @ref mdb_txn */
+ /** #dirty_list room: Array size - \#dirty pages visible to this txn.
+ * Includes ancestor txns' dirty pages not hidden by other txns'
+ * dirty/spilled pages. Thus commit(nested txn) has room to merge
+ * dirty_list into mt_parent after freeing hidden mt_parent pages.
+ */
+ unsigned int mt_dirty_room;
+};
+
+/** Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty.
+ * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to
+ * raise this on a 64 bit machine.
+ */
+#define CURSOR_STACK 32
+
+struct MDB_xcursor;
+
+ /** Cursors are used for all DB operations.
+ * A cursor holds a path of (page pointer, key index) from the DB
+ * root to a position in the DB, plus other state. #MDB_DUPSORT
+ * cursors include an xcursor to the current data item. Write txns
+ * track their cursors and keep them up to date when data moves.
+ * Exception: An xcursor's pointer to a #P_SUBP page can be stale.
+ * (A node with #F_DUPDATA but no #F_SUBDATA contains a subpage).
+ */
+struct MDB_cursor {
+ /** Next cursor on this DB in this txn */
+ MDB_cursor *mc_next;
+ /** Backup of the original cursor if this cursor is a shadow */
+ MDB_cursor *mc_backup;
+ /** Context used for databases with #MDB_DUPSORT, otherwise NULL */
+ struct MDB_xcursor *mc_xcursor;
+ /** The transaction that owns this cursor */
+ MDB_txn *mc_txn;
+ /** The database handle this cursor operates on */
+ MDB_dbi mc_dbi;
+ /** The database record for this cursor */
+ MDB_db *mc_db;
+ /** The database auxiliary record for this cursor */
+ MDB_dbx *mc_dbx;
+ /** The @ref mt_dbflag for this database */
+ unsigned char *mc_dbflag;
+ unsigned short mc_snum; /**< number of pushed pages */
+ unsigned short mc_top; /**< index of top page, normally mc_snum-1 */
+/** @defgroup mdb_cursor Cursor Flags
+ * @ingroup internal
+ * Cursor state flags.
+ * @{
+ */
+#define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */
+#define C_EOF 0x02 /**< No more data */
+#define C_SUB 0x04 /**< Cursor is a sub-cursor */
+#define C_DEL 0x08 /**< last op was a cursor_del */
+#define C_UNTRACK 0x40 /**< Un-track cursor when closing */
+/** @} */
+ unsigned int mc_flags; /**< @ref mdb_cursor */
+ MDB_page *mc_pg[CURSOR_STACK]; /**< stack of pushed pages */
+ indx_t mc_ki[CURSOR_STACK]; /**< stack of page indices */
+};
+
+ /** Context for sorted-dup records.
+ * We could have gone to a fully recursive design, with arbitrarily
+ * deep nesting of sub-databases. But for now we only handle these
+ * levels - main DB, optional sub-DB, sorted-duplicate DB.
+ */
+typedef struct MDB_xcursor {
+ /** A sub-cursor for traversing the Dup DB */
+ MDB_cursor mx_cursor;
+ /** The database record for this Dup DB */
+ MDB_db mx_db;
+ /** The auxiliary DB record for this Dup DB */
+ MDB_dbx mx_dbx;
+ /** The @ref mt_dbflag for this Dup DB */
+ unsigned char mx_dbflag;
+} MDB_xcursor;
+
+ /** Check if there is an inited xcursor, so #XCURSOR_REFRESH() is proper */
+#define XCURSOR_INITED(mc) \
+ ((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
+
+ /** Update sub-page pointer, if any, in \b mc->mc_xcursor. Needed
+ * when the node which contains the sub-page may have moved. Called
+ * with \b mp = mc->mc_pg[mc->mc_top], \b ki = mc->mc_ki[mc->mc_top].
+ */
+#define XCURSOR_REFRESH(mc, mp, ki) do { \
+ MDB_page *xr_pg = (mp); \
+ MDB_node *xr_node = NODEPTR(xr_pg, ki); \
+ if ((xr_node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) \
+ (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node); \
+} while (0)
+
+ /** State of FreeDB old pages, stored in the MDB_env */
+typedef struct MDB_pgstate {
+ pgno_t *mf_pghead; /**< Reclaimed freeDB pages, or NULL before use */
+ txnid_t mf_pglast; /**< ID of last used record, or 0 if !mf_pghead */
+} MDB_pgstate;
+
+ /** The database environment. */
+struct MDB_env {
+ HANDLE me_fd; /**< The main data file */
+ HANDLE me_lfd; /**< The lock file */
+ HANDLE me_mfd; /**< For writing and syncing the meta pages */
+ /** Failed to update the meta page. Probably an I/O error. */
+#define MDB_FATAL_ERROR 0x80000000U
+ /** Some fields are initialized. */
+#define MDB_ENV_ACTIVE 0x20000000U
+ /** me_txkey is set */
+#define MDB_ENV_TXKEY 0x10000000U
+ /** fdatasync is unreliable */
+#define MDB_FSYNCONLY 0x08000000U
+ uint32_t me_flags; /**< @ref mdb_env */
+ unsigned int me_psize; /**< DB page size, inited from me_os_psize */
+ unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */
+ unsigned int me_maxreaders; /**< size of the reader table */
+ /** Max #MDB_txninfo.%mti_numreaders of interest to #mdb_env_close() */
+ volatile int me_close_readers;
+ MDB_dbi me_numdbs; /**< number of DBs opened */
+ MDB_dbi me_maxdbs; /**< size of the DB table */
+ MDB_PID_T me_pid; /**< process ID of this env */
+ char *me_path; /**< path to the DB files */
+ char *me_map; /**< the memory map of the data file */
+ MDB_txninfo *me_txns; /**< the memory map of the lock file or NULL */
+ MDB_meta *me_metas[NUM_METAS]; /**< pointers to the two meta pages */
+ void *me_pbuf; /**< scratch area for DUPSORT put() */
+ MDB_txn *me_txn; /**< current write transaction */
+ MDB_txn *me_txn0; /**< prealloc'd write transaction */
+ size_t me_mapsize; /**< size of the data memory map */
+ off_t me_size; /**< current file size */
+ pgno_t me_maxpg; /**< me_mapsize / me_psize */
+ MDB_dbx *me_dbxs; /**< array of static DB info */
+ uint16_t *me_dbflags; /**< array of flags from MDB_db.md_flags */
+ unsigned int *me_dbiseqs; /**< array of dbi sequence numbers */
+ pthread_key_t me_txkey; /**< thread-key for readers */
+ txnid_t me_pgoldest; /**< ID of oldest reader last time we looked */
+ MDB_pgstate me_pgstate; /**< state of old pages from freeDB */
+# define me_pglast me_pgstate.mf_pglast
+# define me_pghead me_pgstate.mf_pghead
+ MDB_page *me_dpages; /**< list of malloc'd blocks for re-use */
+ /** IDL of pages that became unused in a write txn */
+ MDB_IDL me_free_pgs;
+ /** ID2L of pages written during a write txn. Length MDB_IDL_UM_SIZE. */
+ MDB_ID2L me_dirty_list;
+ /** Max number of freelist items that can fit in a single overflow page */
+ int me_maxfree_1pg;
+ /** Max size of a node on a page */
+ unsigned int me_nodemax;
+#if !(MDB_MAXKEYSIZE)
+ unsigned int me_maxkey; /**< max size of a key */
+#endif
+ int me_live_reader; /**< have liveness lock in reader table */
+#ifdef _WIN32
+ int me_pidquery; /**< Used in OpenProcess */
+#endif
+#ifdef MDB_USE_POSIX_MUTEX /* Posix mutexes reside in shared mem */
+# define me_rmutex me_txns->mti_rmutex /**< Shared reader lock */
+# define me_wmutex me_txns->mti_wmutex /**< Shared writer lock */
+#else
+ mdb_mutex_t me_rmutex;
+ mdb_mutex_t me_wmutex;
+#endif
+ void *me_userctx; /**< User-settable context */
+ MDB_assert_func *me_assert_func; /**< Callback for assertion failures */
+};
+
+ /** Nested transaction */
+typedef struct MDB_ntxn {
+ MDB_txn mnt_txn; /**< the transaction */
+ MDB_pgstate mnt_pgstate; /**< parent transaction's saved freestate */
+} MDB_ntxn;
+
+ /** max number of pages to commit in one writev() call */
+#define MDB_COMMIT_PAGES 64
+#if defined(IOV_MAX) && IOV_MAX < MDB_COMMIT_PAGES
+#undef MDB_COMMIT_PAGES
+#define MDB_COMMIT_PAGES IOV_MAX
+#endif
+
+ /** max bytes to write in one call */
+#define MAX_WRITE (0x40000000U >> (sizeof(ssize_t) == 4))
+
+ /** Check \b txn and \b dbi arguments to a function */
+#define TXN_DBI_EXIST(txn, dbi, validity) \
+ ((txn) && (dbi)<(txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & (validity)))
+
+ /** Check for misused \b dbi handles */
+#define TXN_DBI_CHANGED(txn, dbi) \
+ ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
+
+static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp);
+static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp);
+static int mdb_page_touch(MDB_cursor *mc);
+
+#define MDB_END_NAMES {"committed", "empty-commit", "abort", "reset", \
+ "reset-tmp", "fail-begin", "fail-beginchild"}
+enum {
+ /* mdb_txn_end operation number, for logging */
+ MDB_END_COMMITTED, MDB_END_EMPTY_COMMIT, MDB_END_ABORT, MDB_END_RESET,
+ MDB_END_RESET_TMP, MDB_END_FAIL_BEGIN, MDB_END_FAIL_BEGINCHILD
+};
+#define MDB_END_OPMASK 0x0F /**< mask for #mdb_txn_end() operation number */
+#define MDB_END_UPDATE 0x10 /**< update env state (DBIs) */
+#define MDB_END_FREE 0x20 /**< free txn unless it is #MDB_env.%me_txn0 */
+#define MDB_END_SLOT MDB_NOTLS /**< release any reader slot if #MDB_NOTLS */
+static void mdb_txn_end(MDB_txn *txn, unsigned mode);
+
+static int mdb_page_get(MDB_cursor *mc, pgno_t pgno, MDB_page **mp, int *lvl);
+static int mdb_page_search_root(MDB_cursor *mc,
+ MDB_val *key, int modify);
+#define MDB_PS_MODIFY 1
+#define MDB_PS_ROOTONLY 2
+#define MDB_PS_FIRST 4
+#define MDB_PS_LAST 8
+static int mdb_page_search(MDB_cursor *mc,
+ MDB_val *key, int flags);
+static int mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst);
+
+#define MDB_SPLIT_REPLACE MDB_APPENDDUP /**< newkey is not new */
+static int mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata,
+ pgno_t newpgno, unsigned int nflags);
+
+static int mdb_env_read_header(MDB_env *env, MDB_meta *meta);
+static MDB_meta *mdb_env_pick_meta(const MDB_env *env);
+static int mdb_env_write_meta(MDB_txn *txn);
+#ifdef MDB_USE_POSIX_MUTEX /* Drop unused excl arg */
+# define mdb_env_close0(env, excl) mdb_env_close1(env)
+#endif
+static void mdb_env_close0(MDB_env *env, int excl);
+
+static MDB_node *mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp);
+static int mdb_node_add(MDB_cursor *mc, indx_t indx,
+ MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags);
+static void mdb_node_del(MDB_cursor *mc, int ksize);
+static void mdb_node_shrink(MDB_page *mp, indx_t indx);
+static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft);
+static int mdb_node_read(MDB_cursor *mc, MDB_node *leaf, MDB_val *data);
+static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data);
+static size_t mdb_branch_size(MDB_env *env, MDB_val *key);
+
+static int mdb_rebalance(MDB_cursor *mc);
+static int mdb_update_key(MDB_cursor *mc, MDB_val *key);
+
+static void mdb_cursor_pop(MDB_cursor *mc);
+static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp);
+
+static int mdb_cursor_del0(MDB_cursor *mc);
+static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags);
+static int mdb_cursor_sibling(MDB_cursor *mc, int move_right);
+static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
+static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
+static int mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op,
+ int *exactp);
+static int mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data);
+static int mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data);
+
+static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx);
+static void mdb_xcursor_init0(MDB_cursor *mc);
+static void mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node);
+static void mdb_xcursor_init2(MDB_cursor *mc, MDB_xcursor *src_mx, int force);
+
+static int mdb_drop0(MDB_cursor *mc, int subs);
+static void mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi);
+static int mdb_reader_check0(MDB_env *env, int rlocked, int *dead);
+
+/** @cond */
+static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_cmp_long;
+/** @endcond */
+
+/** Compare two items pointing at size_t's of unknown alignment. */
+#ifdef MISALIGNED_OK
+# define mdb_cmp_clong mdb_cmp_long
+#else
+# define mdb_cmp_clong mdb_cmp_cint
+#endif
+
+#ifdef _WIN32
+static SECURITY_DESCRIPTOR mdb_null_sd;
+static SECURITY_ATTRIBUTES mdb_all_sa;
+static int mdb_sec_inited;
+
+struct MDB_name;
+static int utf8_to_utf16(const char *src, struct MDB_name *dst, int xtra);
+#endif
+
+/** Return the library version info. */
+char * ESECT
+mdb_version(int *major, int *minor, int *patch)
+{
+ if (major) *major = MDB_VERSION_MAJOR;
+ if (minor) *minor = MDB_VERSION_MINOR;
+ if (patch) *patch = MDB_VERSION_PATCH;
+ return MDB_VERSION_STRING;
+}
+
+/** Table of descriptions for LMDB @ref errors */
+static char *const mdb_errstr[] = {
+ "MDB_KEYEXIST: Key/data pair already exists",
+ "MDB_NOTFOUND: No matching key/data pair found",
+ "MDB_PAGE_NOTFOUND: Requested page not found",
+ "MDB_CORRUPTED: Located page was wrong type",
+ "MDB_PANIC: Update of meta page failed or environment had fatal error",
+ "MDB_VERSION_MISMATCH: Database environment version mismatch",
+ "MDB_INVALID: File is not an LMDB file",
+ "MDB_MAP_FULL: Environment mapsize limit reached",
+ "MDB_DBS_FULL: Environment maxdbs limit reached",
+ "MDB_READERS_FULL: Environment maxreaders limit reached",
+ "MDB_TLS_FULL: Thread-local storage keys full - too many environments open",
+ "MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big",
+ "MDB_CURSOR_FULL: Internal error - cursor stack limit reached",
+ "MDB_PAGE_FULL: Internal error - page has no more space",
+ "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize",
+ "MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
+ "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot",
+ "MDB_BAD_TXN: Transaction must abort, has a child, or is invalid",
+ "MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size",
+ "MDB_BAD_DBI: The specified DBI handle was closed/changed unexpectedly",
+};
+
+char *
+mdb_strerror(int err)
+{
+#ifdef _WIN32
+ /** HACK: pad 4KB on stack over the buf. Return system msgs in buf.
+ * This works as long as no function between the call to mdb_strerror
+ * and the actual use of the message uses more than 4K of stack.
+ */
+#define MSGSIZE 1024
+#define PADSIZE 4096
+ char buf[MSGSIZE+PADSIZE], *ptr = buf;
+#endif
+ int i;
+ if (!err)
+ return ("Successful return: 0");
+
+ if (err >= MDB_KEYEXIST && err <= MDB_LAST_ERRCODE) {
+ i = err - MDB_KEYEXIST;
+ return mdb_errstr[i];
+ }
+
+#ifdef _WIN32
+ /* These are the C-runtime error codes we use. The comment indicates
+ * their numeric value, and the Win32 error they would correspond to
+ * if the error actually came from a Win32 API. A major mess, we should
+ * have used LMDB-specific error codes for everything.
+ */
+ switch(err) {
+ case ENOENT: /* 2, FILE_NOT_FOUND */
+ case EIO: /* 5, ACCESS_DENIED */
+ case ENOMEM: /* 12, INVALID_ACCESS */
+ case EACCES: /* 13, INVALID_DATA */
+ case EBUSY: /* 16, CURRENT_DIRECTORY */
+ case EINVAL: /* 22, BAD_COMMAND */
+ case ENOSPC: /* 28, OUT_OF_PAPER */
+ return strerror(err);
+ default:
+ ;
+ }
+ buf[0] = 0;
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE);
+ return ptr;
+#else
+ return strerror(err);
+#endif
+}
+
+/** assert(3) variant in cursor context */
+#define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr)
+/** assert(3) variant in transaction context */
+#define mdb_tassert(txn, expr) mdb_assert0((txn)->mt_env, expr, #expr)
+/** assert(3) variant in environment context */
+#define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr)
+
+#ifndef NDEBUG
+# define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \
+ mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__))
+
+static void ESECT
+mdb_assert_fail(MDB_env *env, const char *expr_txt,
+ const char *func, const char *file, int line)
+{
+ char buf[400];
+ sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()",
+ file, line, expr_txt, func);
+ if (env->me_assert_func)
+ env->me_assert_func(env, buf);
+ fprintf(stderr, "%s\n", buf);
+ abort();
+}
+#else
+# define mdb_assert0(env, expr, expr_txt) ((void) 0)
+#endif /* NDEBUG */
+
+#if MDB_DEBUG
+/** Return the page number of \b mp which may be sub-page, for debug output */
+static pgno_t
+mdb_dbg_pgno(MDB_page *mp)
+{
+ pgno_t ret;
+ COPY_PGNO(ret, mp->mp_pgno);
+ return ret;
+}
+
+/** Display a key in hexadecimal and return the address of the result.
+ * @param[in] key the key to display
+ * @param[in] buf the buffer to write into. Should always be #DKBUF.
+ * @return The key in hexadecimal form.
+ */
+char *
+mdb_dkey(MDB_val *key, char *buf)
+{
+ char *ptr = buf;
+ unsigned char *c = key->mv_data;
+ unsigned int i;
+
+ if (!key)
+ return "";
+
+ if (key->mv_size > DKBUF_MAXKEYSIZE)
+ return "MDB_MAXKEYSIZE";
+ /* may want to make this a dynamic check: if the key is mostly
+ * printable characters, print it as-is instead of converting to hex.
+ */
+#if 1
+ buf[0] = '\0';
+ for (i=0; i<key->mv_size; i++)
+ ptr += sprintf(ptr, "%02x", *c++);
+#else
+ sprintf(buf, "%.*s", key->mv_size, key->mv_data);
+#endif
+ return buf;
+}
+
+static const char *
+mdb_leafnode_type(MDB_node *n)
+{
+ static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}};
+ return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" :
+ tp[F_ISSET(n->mn_flags, F_DUPDATA)][F_ISSET(n->mn_flags, F_SUBDATA)];
+}
+
+/** Display all the keys in the page. */
+void
+mdb_page_list(MDB_page *mp)
+{
+ pgno_t pgno = mdb_dbg_pgno(mp);
+ const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : "";
+ MDB_node *node;
+ unsigned int i, nkeys, nsize, total = 0;
+ MDB_val key;
+ DKBUF;
+
+ switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) {
+ case P_BRANCH: type = "Branch page"; break;
+ case P_LEAF: type = "Leaf page"; break;
+ case P_LEAF|P_SUBP: type = "Sub-page"; break;
+ case P_LEAF|P_LEAF2: type = "LEAF2 page"; break;
+ case P_LEAF|P_LEAF2|P_SUBP: type = "LEAF2 sub-page"; break;
+ case P_OVERFLOW:
+ fprintf(stderr, "Overflow page %"Z"u pages %u%s\n",
+ pgno, mp->mp_pages, state);
+ return;
+ case P_META:
+ fprintf(stderr, "Meta-page %"Z"u txnid %"Z"u\n",
+ pgno, ((MDB_meta *)METADATA(mp))->mm_txnid);
+ return;
+ default:
+ fprintf(stderr, "Bad page %"Z"u flags 0x%X\n", pgno, mp->mp_flags);
+ return;
+ }
+
+ nkeys = NUMKEYS(mp);
+ fprintf(stderr, "%s %"Z"u numkeys %d%s\n", type, pgno, nkeys, state);
+
+ for (i=0; i<nkeys; i++) {
+ if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */
+ key.mv_size = nsize = mp->mp_pad;
+ key.mv_data = LEAF2KEY(mp, i, nsize);
+ total += nsize;
+ fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key));
+ continue;
+ }
+ node = NODEPTR(mp, i);
+ key.mv_size = node->mn_ksize;
+ key.mv_data = node->mn_data;
+ nsize = NODESIZE + key.mv_size;
+ if (IS_BRANCH(mp)) {
+ fprintf(stderr, "key %d: page %"Z"u, %s\n", i, NODEPGNO(node),
+ DKEY(&key));
+ total += nsize;
+ } else {
+ if (F_ISSET(node->mn_flags, F_BIGDATA))
+ nsize += sizeof(pgno_t);
+ else
+ nsize += NODEDSZ(node);
+ total += nsize;
+ nsize += sizeof(indx_t);
+ fprintf(stderr, "key %d: nsize %d, %s%s\n",
+ i, nsize, DKEY(&key), mdb_leafnode_type(node));
+ }
+ total = EVEN(total);
+ }
+ fprintf(stderr, "Total: header %d + contents %d + unused %d\n",
+ IS_LEAF2(mp) ? PAGEHDRSZ : PAGEBASE + mp->mp_lower, total, SIZELEFT(mp));
+}
+
+void
+mdb_cursor_chk(MDB_cursor *mc)
+{
+ unsigned int i;
+ MDB_node *node;
+ MDB_page *mp;
+
+ if (!mc->mc_snum || !(mc->mc_flags & C_INITIALIZED)) return;
+ for (i=0; i<mc->mc_top; i++) {
+ mp = mc->mc_pg[i];
+ node = NODEPTR(mp, mc->mc_ki[i]);
+ if (NODEPGNO(node) != mc->mc_pg[i+1]->mp_pgno)
+ printf("oops!\n");
+ }
+ if (mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i]))
+ printf("ack!\n");
+ if (XCURSOR_INITED(mc)) {
+ node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if (((node->mn_flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA) &&
+ mc->mc_xcursor->mx_cursor.mc_pg[0] != NODEDATA(node)) {
+ printf("blah!\n");
+ }
+ }
+}
+#endif
+
+#if (MDB_DEBUG) > 2
+/** Count all the pages in each DB and in the freelist
+ * and make sure it matches the actual number of pages
+ * being used.
+ * All named DBs must be open for a correct count.
+ */
+static void mdb_audit(MDB_txn *txn)
+{
+ MDB_cursor mc;
+ MDB_val key, data;
+ MDB_ID freecount, count;
+ MDB_dbi i;
+ int rc;
+
+ freecount = 0;
+ mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
+ while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0)
+ freecount += *(MDB_ID *)data.mv_data;
+ mdb_tassert(txn, rc == MDB_NOTFOUND);
+
+ count = 0;
+ for (i = 0; i<txn->mt_numdbs; i++) {
+ MDB_xcursor mx;
+ if (!(txn->mt_dbflags[i] & DB_VALID))
+ continue;
+ mdb_cursor_init(&mc, txn, i, &mx);
+ if (txn->mt_dbs[i].md_root == P_INVALID)
+ continue;
+ count += txn->mt_dbs[i].md_branch_pages +
+ txn->mt_dbs[i].md_leaf_pages +
+ txn->mt_dbs[i].md_overflow_pages;
+ if (txn->mt_dbs[i].md_flags & MDB_DUPSORT) {
+ rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST);
+ for (; rc == MDB_SUCCESS; rc = mdb_cursor_sibling(&mc, 1)) {
+ unsigned j;
+ MDB_page *mp;
+ mp = mc.mc_pg[mc.mc_top];
+ for (j=0; j<NUMKEYS(mp); j++) {
+ MDB_node *leaf = NODEPTR(mp, j);
+ if (leaf->mn_flags & F_SUBDATA) {
+ MDB_db db;
+ memcpy(&db, NODEDATA(leaf), sizeof(db));
+ count += db.md_branch_pages + db.md_leaf_pages +
+ db.md_overflow_pages;
+ }
+ }
+ }
+ mdb_tassert(txn, rc == MDB_NOTFOUND);
+ }
+ }
+ if (freecount + count + NUM_METAS != txn->mt_next_pgno) {
+ fprintf(stderr, "audit: %"Z"u freecount: %"Z"u count: %"Z"u total: %"Z"u next_pgno: %"Z"u\n",
+ txn->mt_txnid, freecount, count+NUM_METAS,
+ freecount+count+NUM_METAS, txn->mt_next_pgno);
+ }
+}
+#endif
+
+int
+mdb_cmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
+{
+ return txn->mt_dbxs[dbi].md_cmp(a, b);
+}
+
+int
+mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b)
+{
+ MDB_cmp_func *dcmp = txn->mt_dbxs[dbi].md_dcmp;
+#if UINT_MAX < SIZE_MAX
+ if (dcmp == mdb_cmp_int && a->mv_size == sizeof(size_t))
+ dcmp = mdb_cmp_clong;
+#endif
+ return dcmp(a, b);
+}
+
+/** Allocate memory for a page.
+ * Re-use old malloc'd pages first for singletons, otherwise just malloc.
+ * Set #MDB_TXN_ERROR on failure.
+ */
+static MDB_page *
+mdb_page_malloc(MDB_txn *txn, unsigned num)
+{
+ MDB_env *env = txn->mt_env;
+ MDB_page *ret = env->me_dpages;
+ size_t psize = env->me_psize, sz = psize, off;
+ /* For ! #MDB_NOMEMINIT, psize counts how much to init.
+ * For a single page alloc, we init everything after the page header.
+ * For multi-page, we init the final page; if the caller needed that
+ * many pages they will be filling in at least up to the last page.
+ */
+ if (num == 1) {
+ if (ret) {
+ VGMEMP_ALLOC(env, ret, sz);
+ VGMEMP_DEFINED(ret, sizeof(ret->mp_next));
+ env->me_dpages = ret->mp_next;
+ return ret;
+ }
+ psize -= off = PAGEHDRSZ;
+ } else {
+ sz *= num;
+ off = sz - psize;
+ }
+ if ((ret = malloc(sz)) != NULL) {
+ VGMEMP_ALLOC(env, ret, sz);
+ if (!(env->me_flags & MDB_NOMEMINIT)) {
+ memset((char *)ret + off, 0, psize);
+ ret->mp_pad = 0;
+ }
+ } else {
+ txn->mt_flags |= MDB_TXN_ERROR;
+ }
+ return ret;
+}
+/** Free a single page.
+ * Saves single pages to a list, for future reuse.
+ * (This is not used for multi-page overflow pages.)
+ */
+static void
+mdb_page_free(MDB_env *env, MDB_page *mp)
+{
+ mp->mp_next = env->me_dpages;
+ VGMEMP_FREE(env, mp);
+ env->me_dpages = mp;
+}
+
+/** Free a dirty page */
+static void
+mdb_dpage_free(MDB_env *env, MDB_page *dp)
+{
+ if (!IS_OVERFLOW(dp) || dp->mp_pages == 1) {
+ mdb_page_free(env, dp);
+ } else {
+ /* large pages just get freed directly */
+ VGMEMP_FREE(env, dp);
+ free(dp);
+ }
+}
+
+/** Return all dirty pages to dpage list */
+static void
+mdb_dlist_free(MDB_txn *txn)
+{
+ MDB_env *env = txn->mt_env;
+ MDB_ID2L dl = txn->mt_u.dirty_list;
+ unsigned i, n = dl[0].mid;
+
+ for (i = 1; i <= n; i++) {
+ mdb_dpage_free(env, dl[i].mptr);
+ }
+ dl[0].mid = 0;
+}
+
+/** Loosen or free a single page.
+ * Saves single pages to a list for future reuse
+ * in this same txn. It has been pulled from the freeDB
+ * and already resides on the dirty list, but has been
+ * deleted. Use these pages first before pulling again
+ * from the freeDB.
+ *
+ * If the page wasn't dirtied in this txn, just add it
+ * to this txn's free list.
+ */
+static int
+mdb_page_loose(MDB_cursor *mc, MDB_page *mp)
+{
+ int loose = 0;
+ pgno_t pgno = mp->mp_pgno;
+ MDB_txn *txn = mc->mc_txn;
+
+ if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
+ if (txn->mt_parent) {
+ MDB_ID2 *dl = txn->mt_u.dirty_list;
+ /* If txn has a parent, make sure the page is in our
+ * dirty list.
+ */
+ if (dl[0].mid) {
+ unsigned x = mdb_mid2l_search(dl, pgno);
+ if (x <= dl[0].mid && dl[x].mid == pgno) {
+ if (mp != dl[x].mptr) { /* bad cursor? */
+ mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_CORRUPTED;
+ }
+ /* ok, it's ours */
+ loose = 1;
+ }
+ }
+ } else {
+ /* no parent txn, so it's just ours */
+ loose = 1;
+ }
+ }
+ if (loose) {
+ DPRINTF(("loosen db %d page %"Z"u", DDBI(mc),
+ mp->mp_pgno));
+ NEXT_LOOSE_PAGE(mp) = txn->mt_loose_pgs;
+ txn->mt_loose_pgs = mp;
+ txn->mt_loose_count++;
+ mp->mp_flags |= P_LOOSE;
+ } else {
+ int rc = mdb_midl_append(&txn->mt_free_pgs, pgno);
+ if (rc)
+ return rc;
+ }
+
+ return MDB_SUCCESS;
+}
+
+/** Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn.
+ * @param[in] mc A cursor handle for the current operation.
+ * @param[in] pflags Flags of the pages to update:
+ * P_DIRTY to set P_KEEP, P_DIRTY|P_KEEP to clear it.
+ * @param[in] all No shortcuts. Needed except after a full #mdb_page_flush().
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_pages_xkeep(MDB_cursor *mc, unsigned pflags, int all)
+{
+ enum { Mask = P_SUBP|P_DIRTY|P_LOOSE|P_KEEP };
+ MDB_txn *txn = mc->mc_txn;
+ MDB_cursor *m3, *m0 = mc;
+ MDB_xcursor *mx;
+ MDB_page *dp, *mp;
+ MDB_node *leaf;
+ unsigned i, j;
+ int rc = MDB_SUCCESS, level;
+
+ /* Mark pages seen by cursors */
+ if (mc->mc_flags & C_UNTRACK)
+ mc = NULL; /* will find mc in mt_cursors */
+ for (i = txn->mt_numdbs;; mc = txn->mt_cursors[--i]) {
+ for (; mc; mc=mc->mc_next) {
+ if (!(mc->mc_flags & C_INITIALIZED))
+ continue;
+ for (m3 = mc;; m3 = &mx->mx_cursor) {
+ mp = NULL;
+ for (j=0; j<m3->mc_snum; j++) {
+ mp = m3->mc_pg[j];
+ if ((mp->mp_flags & Mask) == pflags)
+ mp->mp_flags ^= P_KEEP;
+ }
+ mx = m3->mc_xcursor;
+ /* Proceed to mx if it is at a sub-database */
+ if (! (mx && (mx->mx_cursor.mc_flags & C_INITIALIZED)))
+ break;
+ if (! (mp && (mp->mp_flags & P_LEAF)))
+ break;
+ leaf = NODEPTR(mp, m3->mc_ki[j-1]);
+ if (!(leaf->mn_flags & F_SUBDATA))
+ break;
+ }
+ }
+ if (i == 0)
+ break;
+ }
+
+ if (all) {
+ /* Mark dirty root pages */
+ for (i=0; i<txn->mt_numdbs; i++) {
+ if (txn->mt_dbflags[i] & DB_DIRTY) {
+ pgno_t pgno = txn->mt_dbs[i].md_root;
+ if (pgno == P_INVALID)
+ continue;
+ if ((rc = mdb_page_get(m0, pgno, &dp, &level)) != MDB_SUCCESS)
+ break;
+ if ((dp->mp_flags & Mask) == pflags && level <= 1)
+ dp->mp_flags ^= P_KEEP;
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int mdb_page_flush(MDB_txn *txn, int keep);
+
+/** Spill pages from the dirty list back to disk.
+ * This is intended to prevent running into #MDB_TXN_FULL situations,
+ * but note that they may still occur in a few cases:
+ * 1) our estimate of the txn size could be too small. Currently this
+ * seems unlikely, except with a large number of #MDB_MULTIPLE items.
+ * 2) child txns may run out of space if their parents dirtied a
+ * lot of pages and never spilled them. TODO: we probably should do
+ * a preemptive spill during #mdb_txn_begin() of a child txn, if
+ * the parent's dirty_room is below a given threshold.
+ *
+ * Otherwise, if not using nested txns, it is expected that apps will
+ * not run into #MDB_TXN_FULL any more. The pages are flushed to disk
+ * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared.
+ * If the txn never references them again, they can be left alone.
+ * If the txn only reads them, they can be used without any fuss.
+ * If the txn writes them again, they can be dirtied immediately without
+ * going thru all of the work of #mdb_page_touch(). Such references are
+ * handled by #mdb_page_unspill().
+ *
+ * Also note, we never spill DB root pages, nor pages of active cursors,
+ * because we'll need these back again soon anyway. And in nested txns,
+ * we can't spill a page in a child txn if it was already spilled in a
+ * parent txn. That would alter the parent txns' data even though
+ * the child hasn't committed yet, and we'd have no way to undo it if
+ * the child aborted.
+ *
+ * @param[in] m0 cursor A cursor handle identifying the transaction and
+ * database for which we are checking space.
+ * @param[in] key For a put operation, the key being stored.
+ * @param[in] data For a put operation, the data being stored.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_spill(MDB_cursor *m0, MDB_val *key, MDB_val *data)
+{
+ MDB_txn *txn = m0->mc_txn;
+ MDB_page *dp;
+ MDB_ID2L dl = txn->mt_u.dirty_list;
+ unsigned int i, j, need;
+ int rc;
+
+ if (m0->mc_flags & C_SUB)
+ return MDB_SUCCESS;
+
+ /* Estimate how much space this op will take */
+ i = m0->mc_db->md_depth;
+ /* Named DBs also dirty the main DB */
+ if (m0->mc_dbi >= CORE_DBS)
+ i += txn->mt_dbs[MAIN_DBI].md_depth;
+ /* For puts, roughly factor in the key+data size */
+ if (key)
+ i += (LEAFSIZE(key, data) + txn->mt_env->me_psize) / txn->mt_env->me_psize;
+ i += i; /* double it for good measure */
+ need = i;
+
+ if (txn->mt_dirty_room > i)
+ return MDB_SUCCESS;
+
+ if (!txn->mt_spill_pgs) {
+ txn->mt_spill_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX);
+ if (!txn->mt_spill_pgs)
+ return ENOMEM;
+ } else {
+ /* purge deleted slots */
+ MDB_IDL sl = txn->mt_spill_pgs;
+ unsigned int num = sl[0];
+ j=0;
+ for (i=1; i<=num; i++) {
+ if (!(sl[i] & 1))
+ sl[++j] = sl[i];
+ }
+ sl[0] = j;
+ }
+
+ /* Preserve pages which may soon be dirtied again */
+ if ((rc = mdb_pages_xkeep(m0, P_DIRTY, 1)) != MDB_SUCCESS)
+ goto done;
+
+ /* Less aggressive spill - we originally spilled the entire dirty list,
+ * with a few exceptions for cursor pages and DB root pages. But this
+ * turns out to be a lot of wasted effort because in a large txn many
+ * of those pages will need to be used again. So now we spill only 1/8th
+ * of the dirty pages. Testing revealed this to be a good tradeoff,
+ * better than 1/2, 1/4, or 1/10.
+ */
+ if (need < MDB_IDL_UM_MAX / 8)
+ need = MDB_IDL_UM_MAX / 8;
+
+ /* Save the page IDs of all the pages we're flushing */
+ /* flush from the tail forward, this saves a lot of shifting later on. */
+ for (i=dl[0].mid; i && need; i--) {
+ MDB_ID pn = dl[i].mid << 1;
+ dp = dl[i].mptr;
+ if (dp->mp_flags & (P_LOOSE|P_KEEP))
+ continue;
+ /* Can't spill twice, make sure it's not already in a parent's
+ * spill list.
+ */
+ if (txn->mt_parent) {
+ MDB_txn *tx2;
+ for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) {
+ if (tx2->mt_spill_pgs) {
+ j = mdb_midl_search(tx2->mt_spill_pgs, pn);
+ if (j <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[j] == pn) {
+ dp->mp_flags |= P_KEEP;
+ break;
+ }
+ }
+ }
+ if (tx2)
+ continue;
+ }
+ if ((rc = mdb_midl_append(&txn->mt_spill_pgs, pn)))
+ goto done;
+ need--;
+ }
+ mdb_midl_sort(txn->mt_spill_pgs);
+
+ /* Flush the spilled part of dirty list */
+ if ((rc = mdb_page_flush(txn, i)) != MDB_SUCCESS)
+ goto done;
+
+ /* Reset any dirty pages we kept that page_flush didn't see */
+ rc = mdb_pages_xkeep(m0, P_DIRTY|P_KEEP, i);
+
+done:
+ txn->mt_flags |= rc ? MDB_TXN_ERROR : MDB_TXN_SPILLS;
+ return rc;
+}
+
+/** Find oldest txnid still referenced. Expects txn->mt_txnid > 0. */
+static txnid_t
+mdb_find_oldest(MDB_txn *txn)
+{
+ int i;
+ txnid_t mr, oldest = txn->mt_txnid - 1;
+ if (txn->mt_env->me_txns) {
+ MDB_reader *r = txn->mt_env->me_txns->mti_readers;
+ for (i = txn->mt_env->me_txns->mti_numreaders; --i >= 0; ) {
+ if (r[i].mr_pid) {
+ mr = r[i].mr_txnid;
+ if (oldest > mr)
+ oldest = mr;
+ }
+ }
+ }
+ return oldest;
+}
+
+/** Add a page to the txn's dirty list */
+static void
+mdb_page_dirty(MDB_txn *txn, MDB_page *mp)
+{
+ MDB_ID2 mid;
+ int rc, (*insert)(MDB_ID2L, MDB_ID2 *);
+
+ if (txn->mt_flags & MDB_TXN_WRITEMAP) {
+ insert = mdb_mid2l_append;
+ } else {
+ insert = mdb_mid2l_insert;
+ }
+ mid.mid = mp->mp_pgno;
+ mid.mptr = mp;
+ rc = insert(txn->mt_u.dirty_list, &mid);
+ mdb_tassert(txn, rc == 0);
+ txn->mt_dirty_room--;
+}
+
+/** Allocate page numbers and memory for writing. Maintain me_pglast,
+ * me_pghead and mt_next_pgno. Set #MDB_TXN_ERROR on failure.
+ *
+ * If there are free pages available from older transactions, they
+ * are re-used first. Otherwise allocate a new page at mt_next_pgno.
+ * Do not modify the freedB, just merge freeDB records into me_pghead[]
+ * and move me_pglast to say which records were consumed. Only this
+ * function can create me_pghead and move me_pglast/mt_next_pgno.
+ * @param[in] mc cursor A cursor handle identifying the transaction and
+ * database for which we are allocating.
+ * @param[in] num the number of pages to allocate.
+ * @param[out] mp Address of the allocated page(s). Requests for multiple pages
+ * will always be satisfied by a single contiguous chunk of memory.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
+{
+#ifdef MDB_PARANOID /* Seems like we can ignore this now */
+ /* Get at most <Max_retries> more freeDB records once me_pghead
+ * has enough pages. If not enough, use new pages from the map.
+ * If <Paranoid> and mc is updating the freeDB, only get new
+ * records if me_pghead is empty. Then the freelist cannot play
+ * catch-up with itself by growing while trying to save it.
+ */
+ enum { Paranoid = 1, Max_retries = 500 };
+#else
+ enum { Paranoid = 0, Max_retries = INT_MAX /*infinite*/ };
+#endif
+ int rc, retry = num * 60;
+ MDB_txn *txn = mc->mc_txn;
+ MDB_env *env = txn->mt_env;
+ pgno_t pgno, *mop = env->me_pghead;
+ unsigned i, j, mop_len = mop ? mop[0] : 0, n2 = num-1;
+ MDB_page *np;
+ txnid_t oldest = 0, last;
+ MDB_cursor_op op;
+ MDB_cursor m2;
+ int found_old = 0;
+
+ /* If there are any loose pages, just use them */
+ if (num == 1 && txn->mt_loose_pgs) {
+ np = txn->mt_loose_pgs;
+ txn->mt_loose_pgs = NEXT_LOOSE_PAGE(np);
+ txn->mt_loose_count--;
+ DPRINTF(("db %d use loose page %"Z"u", DDBI(mc),
+ np->mp_pgno));
+ *mp = np;
+ return MDB_SUCCESS;
+ }
+
+ *mp = NULL;
+
+ /* If our dirty list is already full, we can't do anything */
+ if (txn->mt_dirty_room == 0) {
+ rc = MDB_TXN_FULL;
+ goto fail;
+ }
+
+ for (op = MDB_FIRST;; op = MDB_NEXT) {
+ MDB_val key, data;
+ MDB_node *leaf;
+ pgno_t *idl;
+
+ /* Seek a big enough contiguous page range. Prefer
+ * pages at the tail, just truncating the list.
+ */
+ if (mop_len > n2) {
+ i = mop_len;
+ do {
+ pgno = mop[i];
+ if (mop[i-n2] == pgno+n2)
+ goto search_done;
+ } while (--i > n2);
+ if (--retry < 0)
+ break;
+ }
+
+ if (op == MDB_FIRST) { /* 1st iteration */
+ /* Prepare to fetch more and coalesce */
+ last = env->me_pglast;
+ oldest = env->me_pgoldest;
+ mdb_cursor_init(&m2, txn, FREE_DBI, NULL);
+ if (last) {
+ op = MDB_SET_RANGE;
+ key.mv_data = &last; /* will look up last+1 */
+ key.mv_size = sizeof(last);
+ }
+ if (Paranoid && mc->mc_dbi == FREE_DBI)
+ retry = -1;
+ }
+ if (Paranoid && retry < 0 && mop_len)
+ break;
+
+ last++;
+ /* Do not fetch more if the record will be too recent */
+ if (oldest <= last) {
+ if (!found_old) {
+ oldest = mdb_find_oldest(txn);
+ env->me_pgoldest = oldest;
+ found_old = 1;
+ }
+ if (oldest <= last)
+ break;
+ }
+ rc = mdb_cursor_get(&m2, &key, NULL, op);
+ if (rc) {
+ if (rc == MDB_NOTFOUND)
+ break;
+ goto fail;
+ }
+ last = *(txnid_t*)key.mv_data;
+ if (oldest <= last) {
+ if (!found_old) {
+ oldest = mdb_find_oldest(txn);
+ env->me_pgoldest = oldest;
+ found_old = 1;
+ }
+ if (oldest <= last)
+ break;
+ }
+ np = m2.mc_pg[m2.mc_top];
+ leaf = NODEPTR(np, m2.mc_ki[m2.mc_top]);
+ if ((rc = mdb_node_read(&m2, leaf, &data)) != MDB_SUCCESS)
+ goto fail;
+
+ idl = (MDB_ID *) data.mv_data;
+ i = idl[0];
+ if (!mop) {
+ if (!(env->me_pghead = mop = mdb_midl_alloc(i))) {
+ rc = ENOMEM;
+ goto fail;
+ }
+ } else {
+ if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
+ goto fail;
+ mop = env->me_pghead;
+ }
+ env->me_pglast = last;
+#if (MDB_DEBUG) > 1
+ DPRINTF(("IDL read txn %"Z"u root %"Z"u num %u",
+ last, txn->mt_dbs[FREE_DBI].md_root, i));
+ for (j = i; j; j--)
+ DPRINTF(("IDL %"Z"u", idl[j]));
+#endif
+ /* Merge in descending sorted order */
+ mdb_midl_xmerge(mop, idl);
+ mop_len = mop[0];
+ }
+
+ /* Use new pages from the map when nothing suitable in the freeDB */
+ i = 0;
+ pgno = txn->mt_next_pgno;
+ if (pgno + num >= env->me_maxpg) {
+ DPUTS("DB size maxed out");
+ rc = MDB_MAP_FULL;
+ goto fail;
+ }
+
+search_done:
+ if (env->me_flags & MDB_WRITEMAP) {
+ np = (MDB_page *)(env->me_map + env->me_psize * pgno);
+ } else {
+ if (!(np = mdb_page_malloc(txn, num))) {
+ rc = ENOMEM;
+ goto fail;
+ }
+ }
+ if (i) {
+ mop[0] = mop_len -= num;
+ /* Move any stragglers down */
+ for (j = i-num; j < mop_len; )
+ mop[++j] = mop[++i];
+ } else {
+ txn->mt_next_pgno = pgno + num;
+ }
+ np->mp_pgno = pgno;
+ mdb_page_dirty(txn, np);
+ *mp = np;
+
+ return MDB_SUCCESS;
+
+fail:
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+/** Copy the used portions of a non-overflow page.
+ * @param[in] dst page to copy into
+ * @param[in] src page to copy from
+ * @param[in] psize size of a page
+ */
+static void
+mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
+{
+ enum { Align = sizeof(pgno_t) };
+ indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper-lower;
+
+ /* If page isn't full, just copy the used portion. Adjust
+ * alignment so memcpy may copy words instead of bytes.
+ */
+ if ((unused &= -Align) && !IS_LEAF2(src)) {
+ upper = (upper + PAGEBASE) & -Align;
+ memcpy(dst, src, (lower + PAGEBASE + (Align-1)) & -Align);
+ memcpy((pgno_t *)((char *)dst+upper), (pgno_t *)((char *)src+upper),
+ psize - upper);
+ } else {
+ memcpy(dst, src, psize - unused);
+ }
+}
+
+/** Pull a page off the txn's spill list, if present.
+ * If a page being referenced was spilled to disk in this txn, bring
+ * it back and make it dirty/writable again.
+ * @param[in] txn the transaction handle.
+ * @param[in] mp the page being referenced. It must not be dirty.
+ * @param[out] ret the writable page, if any. ret is unchanged if
+ * mp wasn't spilled.
+ */
+static int
+mdb_page_unspill(MDB_txn *txn, MDB_page *mp, MDB_page **ret)
+{
+ MDB_env *env = txn->mt_env;
+ const MDB_txn *tx2;
+ unsigned x;
+ pgno_t pgno = mp->mp_pgno, pn = pgno << 1;
+
+ for (tx2 = txn; tx2; tx2=tx2->mt_parent) {
+ if (!tx2->mt_spill_pgs)
+ continue;
+ x = mdb_midl_search(tx2->mt_spill_pgs, pn);
+ if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) {
+ MDB_page *np;
+ int num;
+ if (txn->mt_dirty_room == 0)
+ return MDB_TXN_FULL;
+ if (IS_OVERFLOW(mp))
+ num = mp->mp_pages;
+ else
+ num = 1;
+ if (env->me_flags & MDB_WRITEMAP) {
+ np = mp;
+ } else {
+ np = mdb_page_malloc(txn, num);
+ if (!np)
+ return ENOMEM;
+ if (num > 1)
+ memcpy(np, mp, num * env->me_psize);
+ else
+ mdb_page_copy(np, mp, env->me_psize);
+ }
+ if (tx2 == txn) {
+ /* If in current txn, this page is no longer spilled.
+ * If it happens to be the last page, truncate the spill list.
+ * Otherwise mark it as deleted by setting the LSB.
+ */
+ if (x == txn->mt_spill_pgs[0])
+ txn->mt_spill_pgs[0]--;
+ else
+ txn->mt_spill_pgs[x] |= 1;
+ } /* otherwise, if belonging to a parent txn, the
+ * page remains spilled until child commits
+ */
+
+ mdb_page_dirty(txn, np);
+ np->mp_flags |= P_DIRTY;
+ *ret = np;
+ break;
+ }
+ }
+ return MDB_SUCCESS;
+}
+
+/** Touch a page: make it dirty and re-insert into tree with updated pgno.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in] mc cursor pointing to the page to be touched
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_touch(MDB_cursor *mc)
+{
+ MDB_page *mp = mc->mc_pg[mc->mc_top], *np;
+ MDB_txn *txn = mc->mc_txn;
+ MDB_cursor *m2, *m3;
+ pgno_t pgno;
+ int rc;
+
+ if (!F_ISSET(mp->mp_flags, P_DIRTY)) {
+ if (txn->mt_flags & MDB_TXN_SPILLS) {
+ np = NULL;
+ rc = mdb_page_unspill(txn, mp, &np);
+ if (rc)
+ goto fail;
+ if (np)
+ goto done;
+ }
+ if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) ||
+ (rc = mdb_page_alloc(mc, 1, &np)))
+ goto fail;
+ pgno = np->mp_pgno;
+ DPRINTF(("touched db %d page %"Z"u -> %"Z"u", DDBI(mc),
+ mp->mp_pgno, pgno));
+ mdb_cassert(mc, mp->mp_pgno != pgno);
+ mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
+ /* Update the parent page, if any, to point to the new page */
+ if (mc->mc_top) {
+ MDB_page *parent = mc->mc_pg[mc->mc_top-1];
+ MDB_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top-1]);
+ SETPGNO(node, pgno);
+ } else {
+ mc->mc_db->md_root = pgno;
+ }
+ } else if (txn->mt_parent && !IS_SUBP(mp)) {
+ MDB_ID2 mid, *dl = txn->mt_u.dirty_list;
+ pgno = mp->mp_pgno;
+ /* If txn has a parent, make sure the page is in our
+ * dirty list.
+ */
+ if (dl[0].mid) {
+ unsigned x = mdb_mid2l_search(dl, pgno);
+ if (x <= dl[0].mid && dl[x].mid == pgno) {
+ if (mp != dl[x].mptr) { /* bad cursor? */
+ mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_CORRUPTED;
+ }
+ return 0;
+ }
+ }
+ mdb_cassert(mc, dl[0].mid < MDB_IDL_UM_MAX);
+ /* No - copy it */
+ np = mdb_page_malloc(txn, 1);
+ if (!np)
+ return ENOMEM;
+ mid.mid = pgno;
+ mid.mptr = np;
+ rc = mdb_mid2l_insert(dl, &mid);
+ mdb_cassert(mc, rc == 0);
+ } else {
+ return 0;
+ }
+
+ mdb_page_copy(np, mp, txn->mt_env->me_psize);
+ np->mp_pgno = pgno;
+ np->mp_flags |= P_DIRTY;
+
+done:
+ /* Adjust cursors pointing to mp */
+ mc->mc_pg[mc->mc_top] = np;
+ m2 = txn->mt_cursors[mc->mc_dbi];
+ if (mc->mc_flags & C_SUB) {
+ for (; m2; m2=m2->mc_next) {
+ m3 = &m2->mc_xcursor->mx_cursor;
+ if (m3->mc_snum < mc->mc_snum) continue;
+ if (m3->mc_pg[mc->mc_top] == mp)
+ m3->mc_pg[mc->mc_top] = np;
+ }
+ } else {
+ for (; m2; m2=m2->mc_next) {
+ if (m2->mc_snum < mc->mc_snum) continue;
+ if (m2 == mc) continue;
+ if (m2->mc_pg[mc->mc_top] == mp) {
+ m2->mc_pg[mc->mc_top] = np;
+ if (XCURSOR_INITED(m2) && IS_LEAF(np))
+ XCURSOR_REFRESH(m2, np, m2->mc_ki[mc->mc_top]);
+ }
+ }
+ }
+ return 0;
+
+fail:
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+int
+mdb_env_sync(MDB_env *env, int force)
+{
+ int rc = 0;
+ if (env->me_flags & MDB_RDONLY)
+ return EACCES;
+ if (force || !F_ISSET(env->me_flags, MDB_NOSYNC)) {
+ if (env->me_flags & MDB_WRITEMAP) {
+ int flags = ((env->me_flags & MDB_MAPASYNC) && !force)
+ ? MS_ASYNC : MS_SYNC;
+ if (MDB_MSYNC(env->me_map, env->me_mapsize, flags))
+ rc = ErrCode();
+#ifdef _WIN32
+ else if (flags == MS_SYNC && MDB_FDATASYNC(env->me_fd))
+ rc = ErrCode();
+#endif
+ } else {
+#ifdef BROKEN_FDATASYNC
+ if (env->me_flags & MDB_FSYNCONLY) {
+ if (fsync(env->me_fd))
+ rc = ErrCode();
+ } else
+#endif
+ if (MDB_FDATASYNC(env->me_fd))
+ rc = ErrCode();
+ }
+ }
+ return rc;
+}
+
+/** Back up parent txn's cursors, then grab the originals for tracking */
+static int
+mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
+{
+ MDB_cursor *mc, *bk;
+ MDB_xcursor *mx;
+ size_t size;
+ int i;
+
+ for (i = src->mt_numdbs; --i >= 0; ) {
+ if ((mc = src->mt_cursors[i]) != NULL) {
+ size = sizeof(MDB_cursor);
+ if (mc->mc_xcursor)
+ size += sizeof(MDB_xcursor);
+ for (; mc; mc = bk->mc_next) {
+ bk = malloc(size);
+ if (!bk)
+ return ENOMEM;
+ *bk = *mc;
+ mc->mc_backup = bk;
+ mc->mc_db = &dst->mt_dbs[i];
+ /* Kill pointers into src to reduce abuse: The
+ * user may not use mc until dst ends. But we need a valid
+ * txn pointer here for cursor fixups to keep working.
+ */
+ mc->mc_txn = dst;
+ mc->mc_dbflag = &dst->mt_dbflags[i];
+ if ((mx = mc->mc_xcursor) != NULL) {
+ *(MDB_xcursor *)(bk+1) = *mx;
+ mx->mx_cursor.mc_txn = dst;
+ }
+ mc->mc_next = dst->mt_cursors[i];
+ dst->mt_cursors[i] = mc;
+ }
+ }
+ }
+ return MDB_SUCCESS;
+}
+
+/** Close this write txn's cursors, give parent txn's cursors back to parent.
+ * @param[in] txn the transaction handle.
+ * @param[in] merge true to keep changes to parent cursors, false to revert.
+ * @return 0 on success, non-zero on failure.
+ */
+static void
+mdb_cursors_close(MDB_txn *txn, unsigned merge)
+{
+ MDB_cursor **cursors = txn->mt_cursors, *mc, *next, *bk;
+ MDB_xcursor *mx;
+ int i;
+
+ for (i = txn->mt_numdbs; --i >= 0; ) {
+ for (mc = cursors[i]; mc; mc = next) {
+ next = mc->mc_next;
+ if ((bk = mc->mc_backup) != NULL) {
+ if (merge) {
+ /* Commit changes to parent txn */
+ mc->mc_next = bk->mc_next;
+ mc->mc_backup = bk->mc_backup;
+ mc->mc_txn = bk->mc_txn;
+ mc->mc_db = bk->mc_db;
+ mc->mc_dbflag = bk->mc_dbflag;
+ if ((mx = mc->mc_xcursor) != NULL)
+ mx->mx_cursor.mc_txn = bk->mc_txn;
+ } else {
+ /* Abort nested txn */
+ *mc = *bk;
+ if ((mx = mc->mc_xcursor) != NULL)
+ *mx = *(MDB_xcursor *)(bk+1);
+ }
+ mc = bk;
+ }
+ /* Only malloced cursors are permanently tracked. */
+ free(mc);
+ }
+ cursors[i] = NULL;
+ }
+}
+
+#if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */
+enum Pidlock_op {
+ Pidset, Pidcheck
+};
+#else
+enum Pidlock_op {
+ Pidset = F_SETLK, Pidcheck = F_GETLK
+};
+#endif
+
+/** Set or check a pid lock. Set returns 0 on success.
+ * Check returns 0 if the process is certainly dead, nonzero if it may
+ * be alive (the lock exists or an error happened so we do not know).
+ *
+ * On Windows Pidset is a no-op, we merely check for the existence
+ * of the process with the given pid. On POSIX we use a single byte
+ * lock on the lockfile, set at an offset equal to the pid.
+ */
+static int
+mdb_reader_pid(MDB_env *env, enum Pidlock_op op, MDB_PID_T pid)
+{
+#if !(MDB_PIDLOCK) /* Currently the same as defined(_WIN32) */
+ int ret = 0;
+ HANDLE h;
+ if (op == Pidcheck) {
+ h = OpenProcess(env->me_pidquery, FALSE, pid);
+ /* No documented "no such process" code, but other program use this: */
+ if (!h)
+ return ErrCode() != ERROR_INVALID_PARAMETER;
+ /* A process exists until all handles to it close. Has it exited? */
+ ret = WaitForSingleObject(h, 0) != 0;
+ CloseHandle(h);
+ }
+ return ret;
+#else
+ for (;;) {
+ int rc;
+ struct flock lock_info;
+ memset(&lock_info, 0, sizeof(lock_info));
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = pid;
+ lock_info.l_len = 1;
+ if ((rc = fcntl(env->me_lfd, op, &lock_info)) == 0) {
+ if (op == F_GETLK && lock_info.l_type != F_UNLCK)
+ rc = -1;
+ } else if ((rc = ErrCode()) == EINTR) {
+ continue;
+ }
+ return rc;
+ }
+#endif
+}
+
+/** Common code for #mdb_txn_begin() and #mdb_txn_renew().
+ * @param[in] txn the transaction handle to initialize
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_txn_renew0(MDB_txn *txn)
+{
+ MDB_env *env = txn->mt_env;
+ MDB_txninfo *ti = env->me_txns;
+ MDB_meta *meta;
+ unsigned int i, nr, flags = txn->mt_flags;
+ uint16_t x;
+ int rc, new_notls = 0;
+
+ if ((flags &= MDB_TXN_RDONLY) != 0) {
+ if (!ti) {
+ meta = mdb_env_pick_meta(env);
+ txn->mt_txnid = meta->mm_txnid;
+ txn->mt_u.reader = NULL;
+ } else {
+ MDB_reader *r = (env->me_flags & MDB_NOTLS) ? txn->mt_u.reader :
+ pthread_getspecific(env->me_txkey);
+ if (r) {
+ if (r->mr_pid != env->me_pid || r->mr_txnid != (txnid_t)-1)
+ return MDB_BAD_RSLOT;
+ } else {
+ MDB_PID_T pid = env->me_pid;
+ MDB_THR_T tid = pthread_self();
+ mdb_mutexref_t rmutex = env->me_rmutex;
+
+ if (!env->me_live_reader) {
+ rc = mdb_reader_pid(env, Pidset, pid);
+ if (rc)
+ return rc;
+ env->me_live_reader = 1;
+ }
+
+ if (LOCK_MUTEX(rc, env, rmutex))
+ return rc;
+ nr = ti->mti_numreaders;
+ for (i=0; i<nr; i++)
+ if (ti->mti_readers[i].mr_pid == 0)
+ break;
+ if (i == env->me_maxreaders) {
+ UNLOCK_MUTEX(rmutex);
+ return MDB_READERS_FULL;
+ }
+ r = &ti->mti_readers[i];
+ /* Claim the reader slot, carefully since other code
+ * uses the reader table un-mutexed: First reset the
+ * slot, next publish it in mti_numreaders. After
+ * that, it is safe for mdb_env_close() to touch it.
+ * When it will be closed, we can finally claim it.
+ */
+ r->mr_pid = 0;
+ r->mr_txnid = (txnid_t)-1;
+ r->mr_tid = tid;
+ if (i == nr)
+ ti->mti_numreaders = ++nr;
+ env->me_close_readers = nr;
+ r->mr_pid = pid;
+ UNLOCK_MUTEX(rmutex);
+
+ new_notls = (env->me_flags & MDB_NOTLS);
+ if (!new_notls && (rc=pthread_setspecific(env->me_txkey, r))) {
+ r->mr_pid = 0;
+ return rc;
+ }
+ }
+ do /* LY: Retry on a race, ITS#7970. */
+ r->mr_txnid = ti->mti_txnid;
+ while(r->mr_txnid != ti->mti_txnid);
+ txn->mt_txnid = r->mr_txnid;
+ txn->mt_u.reader = r;
+ meta = env->me_metas[txn->mt_txnid & 1];
+ }
+
+ } else {
+ /* Not yet touching txn == env->me_txn0, it may be active */
+ if (ti) {
+ if (LOCK_MUTEX(rc, env, env->me_wmutex))
+ return rc;
+ txn->mt_txnid = ti->mti_txnid;
+ meta = env->me_metas[txn->mt_txnid & 1];
+ } else {
+ meta = mdb_env_pick_meta(env);
+ txn->mt_txnid = meta->mm_txnid;
+ }
+ txn->mt_txnid++;
+#if MDB_DEBUG
+ if (txn->mt_txnid == mdb_debug_start)
+ mdb_debug = 1;
+#endif
+ txn->mt_child = NULL;
+ txn->mt_loose_pgs = NULL;
+ txn->mt_loose_count = 0;
+ txn->mt_dirty_room = MDB_IDL_UM_MAX;
+ txn->mt_u.dirty_list = env->me_dirty_list;
+ txn->mt_u.dirty_list[0].mid = 0;
+ txn->mt_free_pgs = env->me_free_pgs;
+ txn->mt_free_pgs[0] = 0;
+ txn->mt_spill_pgs = NULL;
+ env->me_txn = txn;
+ memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned int));
+ }
+
+ /* Copy the DB info and flags */
+ memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDB_db));
+
+ /* Moved to here to avoid a data race in read TXNs */
+ txn->mt_next_pgno = meta->mm_last_pg+1;
+
+ txn->mt_flags = flags;
+
+ /* Setup db info */
+ txn->mt_numdbs = env->me_numdbs;
+ for (i=CORE_DBS; i<txn->mt_numdbs; i++) {
+ x = env->me_dbflags[i];
+ txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS;
+ txn->mt_dbflags[i] = (x & MDB_VALID) ? DB_VALID|DB_USRVALID|DB_STALE : 0;
+ }
+ txn->mt_dbflags[MAIN_DBI] = DB_VALID|DB_USRVALID;
+ txn->mt_dbflags[FREE_DBI] = DB_VALID;
+
+ if (env->me_flags & MDB_FATAL_ERROR) {
+ DPUTS("environment had fatal error, must shutdown!");
+ rc = MDB_PANIC;
+ } else if (env->me_maxpg < txn->mt_next_pgno) {
+ rc = MDB_MAP_RESIZED;
+ } else {
+ return MDB_SUCCESS;
+ }
+ mdb_txn_end(txn, new_notls /*0 or MDB_END_SLOT*/ | MDB_END_FAIL_BEGIN);
+ return rc;
+}
+
+int
+mdb_txn_renew(MDB_txn *txn)
+{
+ int rc;
+
+ if (!txn || !F_ISSET(txn->mt_flags, MDB_TXN_RDONLY|MDB_TXN_FINISHED))
+ return EINVAL;
+
+ rc = mdb_txn_renew0(txn);
+ if (rc == MDB_SUCCESS) {
+ DPRINTF(("renew txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
+ txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w',
+ (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root));
+ }
+ return rc;
+}
+
+int
+mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
+{
+ MDB_txn *txn;
+ MDB_ntxn *ntxn;
+ int rc, size, tsize;
+
+ flags &= MDB_TXN_BEGIN_FLAGS;
+ flags |= env->me_flags & MDB_WRITEMAP;
+
+ if (env->me_flags & MDB_RDONLY & ~flags) /* write txn in RDONLY env */
+ return EACCES;
+
+ if (parent) {
+ /* Nested transactions: Max 1 child, write txns only, no writemap */
+ flags |= parent->mt_flags;
+ if (flags & (MDB_RDONLY|MDB_WRITEMAP|MDB_TXN_BLOCKED)) {
+ return (parent->mt_flags & MDB_TXN_RDONLY) ? EINVAL : MDB_BAD_TXN;
+ }
+ /* Child txns save MDB_pgstate and use own copy of cursors */
+ size = env->me_maxdbs * (sizeof(MDB_db)+sizeof(MDB_cursor *)+1);
+ size += tsize = sizeof(MDB_ntxn);
+ } else if (flags & MDB_RDONLY) {
+ size = env->me_maxdbs * (sizeof(MDB_db)+1);
+ size += tsize = sizeof(MDB_txn);
+ } else {
+ /* Reuse preallocated write txn. However, do not touch it until
+ * mdb_txn_renew0() succeeds, since it currently may be active.
+ */
+ txn = env->me_txn0;
+ goto renew;
+ }
+ if ((txn = calloc(1, size)) == NULL) {
+ DPRINTF(("calloc: %s", strerror(errno)));
+ return ENOMEM;
+ }
+ txn->mt_dbxs = env->me_dbxs; /* static */
+ txn->mt_dbs = (MDB_db *) ((char *)txn + tsize);
+ txn->mt_dbflags = (unsigned char *)txn + size - env->me_maxdbs;
+ txn->mt_flags = flags;
+ txn->mt_env = env;
+
+ if (parent) {
+ unsigned int i;
+ txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs);
+ txn->mt_dbiseqs = parent->mt_dbiseqs;
+ txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE);
+ if (!txn->mt_u.dirty_list ||
+ !(txn->mt_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)))
+ {
+ free(txn->mt_u.dirty_list);
+ free(txn);
+ return ENOMEM;
+ }
+ txn->mt_txnid = parent->mt_txnid;
+ txn->mt_dirty_room = parent->mt_dirty_room;
+ txn->mt_u.dirty_list[0].mid = 0;
+ txn->mt_spill_pgs = NULL;
+ txn->mt_next_pgno = parent->mt_next_pgno;
+ parent->mt_flags |= MDB_TXN_HAS_CHILD;
+ parent->mt_child = txn;
+ txn->mt_parent = parent;
+ txn->mt_numdbs = parent->mt_numdbs;
+ memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
+ /* Copy parent's mt_dbflags, but clear DB_NEW */
+ for (i=0; i<txn->mt_numdbs; i++)
+ txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~DB_NEW;
+ rc = 0;
+ ntxn = (MDB_ntxn *)txn;
+ ntxn->mnt_pgstate = env->me_pgstate; /* save parent me_pghead & co */
+ if (env->me_pghead) {
+ size = MDB_IDL_SIZEOF(env->me_pghead);
+ env->me_pghead = mdb_midl_alloc(env->me_pghead[0]);
+ if (env->me_pghead)
+ memcpy(env->me_pghead, ntxn->mnt_pgstate.mf_pghead, size);
+ else
+ rc = ENOMEM;
+ }
+ if (!rc)
+ rc = mdb_cursor_shadow(parent, txn);
+ if (rc)
+ mdb_txn_end(txn, MDB_END_FAIL_BEGINCHILD);
+ } else { /* MDB_RDONLY */
+ txn->mt_dbiseqs = env->me_dbiseqs;
+renew:
+ rc = mdb_txn_renew0(txn);
+ }
+ if (rc) {
+ if (txn != env->me_txn0)
+ free(txn);
+ } else {
+ txn->mt_flags |= flags; /* could not change txn=me_txn0 earlier */
+ *ret = txn;
+ DPRINTF(("begin txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
+ txn->mt_txnid, (flags & MDB_RDONLY) ? 'r' : 'w',
+ (void *) txn, (void *) env, txn->mt_dbs[MAIN_DBI].md_root));
+ }
+
+ return rc;
+}
+
+MDB_env *
+mdb_txn_env(MDB_txn *txn)
+{
+ if(!txn) return NULL;
+ return txn->mt_env;
+}
+
+size_t
+mdb_txn_id(MDB_txn *txn)
+{
+ if(!txn) return 0;
+ return txn->mt_txnid;
+}
+
+/** Export or close DBI handles opened in this txn. */
+static void
+mdb_dbis_update(MDB_txn *txn, int keep)
+{
+ int i;
+ MDB_dbi n = txn->mt_numdbs;
+ MDB_env *env = txn->mt_env;
+ unsigned char *tdbflags = txn->mt_dbflags;
+
+ for (i = n; --i >= CORE_DBS;) {
+ if (tdbflags[i] & DB_NEW) {
+ if (keep) {
+ env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID;
+ } else {
+ char *ptr = env->me_dbxs[i].md_name.mv_data;
+ if (ptr) {
+ env->me_dbxs[i].md_name.mv_data = NULL;
+ env->me_dbxs[i].md_name.mv_size = 0;
+ env->me_dbflags[i] = 0;
+ env->me_dbiseqs[i]++;
+ free(ptr);
+ }
+ }
+ }
+ }
+ if (keep && env->me_numdbs < n)
+ env->me_numdbs = n;
+}
+
+/** End a transaction, except successful commit of a nested transaction.
+ * May be called twice for readonly txns: First reset it, then abort.
+ * @param[in] txn the transaction handle to end
+ * @param[in] mode why and how to end the transaction
+ */
+static void
+mdb_txn_end(MDB_txn *txn, unsigned mode)
+{
+ MDB_env *env = txn->mt_env;
+#if MDB_DEBUG
+ static const char *const names[] = MDB_END_NAMES;
+#endif
+
+ /* Export or close DBI handles opened in this txn */
+ mdb_dbis_update(txn, mode & MDB_END_UPDATE);
+
+ DPRINTF(("%s txn %"Z"u%c %p on mdbenv %p, root page %"Z"u",
+ names[mode & MDB_END_OPMASK],
+ txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w',
+ (void *) txn, (void *)env, txn->mt_dbs[MAIN_DBI].md_root));
+
+ if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
+ if (txn->mt_u.reader) {
+ txn->mt_u.reader->mr_txnid = (txnid_t)-1;
+ if (!(env->me_flags & MDB_NOTLS)) {
+ txn->mt_u.reader = NULL; /* txn does not own reader */
+ } else if (mode & MDB_END_SLOT) {
+ txn->mt_u.reader->mr_pid = 0;
+ txn->mt_u.reader = NULL;
+ } /* else txn owns the slot until it does MDB_END_SLOT */
+ }
+ txn->mt_numdbs = 0; /* prevent further DBI activity */
+ txn->mt_flags |= MDB_TXN_FINISHED;
+
+ } else if (!F_ISSET(txn->mt_flags, MDB_TXN_FINISHED)) {
+ pgno_t *pghead = env->me_pghead;
+
+ if (!(mode & MDB_END_UPDATE)) /* !(already closed cursors) */
+ mdb_cursors_close(txn, 0);
+ if (!(env->me_flags & MDB_WRITEMAP)) {
+ mdb_dlist_free(txn);
+ }
+
+ txn->mt_numdbs = 0;
+ txn->mt_flags = MDB_TXN_FINISHED;
+
+ if (!txn->mt_parent) {
+ mdb_midl_shrink(&txn->mt_free_pgs);
+ env->me_free_pgs = txn->mt_free_pgs;
+ /* me_pgstate: */
+ env->me_pghead = NULL;
+ env->me_pglast = 0;
+
+ env->me_txn = NULL;
+ mode = 0; /* txn == env->me_txn0, do not free() it */
+
+ /* The writer mutex was locked in mdb_txn_begin. */
+ if (env->me_txns)
+ UNLOCK_MUTEX(env->me_wmutex);
+ } else {
+ txn->mt_parent->mt_child = NULL;
+ txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD;
+ env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate;
+ mdb_midl_free(txn->mt_free_pgs);
+ mdb_midl_free(txn->mt_spill_pgs);
+ free(txn->mt_u.dirty_list);
+ }
+
+ mdb_midl_free(pghead);
+ }
+
+ if (mode & MDB_END_FREE)
+ free(txn);
+}
+
+void
+mdb_txn_reset(MDB_txn *txn)
+{
+ if (txn == NULL)
+ return;
+
+ /* This call is only valid for read-only txns */
+ if (!(txn->mt_flags & MDB_TXN_RDONLY))
+ return;
+
+ mdb_txn_end(txn, MDB_END_RESET);
+}
+
+void
+mdb_txn_abort(MDB_txn *txn)
+{
+ if (txn == NULL)
+ return;
+
+ if (txn->mt_child)
+ mdb_txn_abort(txn->mt_child);
+
+ mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE);
+}
+
+/** Save the freelist as of this transaction to the freeDB.
+ * This changes the freelist. Keep trying until it stabilizes.
+ */
+static int
+mdb_freelist_save(MDB_txn *txn)
+{
+ /* env->me_pghead[] can grow and shrink during this call.
+ * env->me_pglast and txn->mt_free_pgs[] can only grow.
+ * Page numbers cannot disappear from txn->mt_free_pgs[].
+ */
+ MDB_cursor mc;
+ MDB_env *env = txn->mt_env;
+ int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1;
+ txnid_t pglast = 0, head_id = 0;
+ pgno_t freecnt = 0, *free_pgs, *mop;
+ ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
+
+ mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
+
+ if (env->me_pghead) {
+ /* Make sure first page of freeDB is touched and on freelist */
+ rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST|MDB_PS_MODIFY);
+ if (rc && rc != MDB_NOTFOUND)
+ return rc;
+ }
+
+ if (!env->me_pghead && txn->mt_loose_pgs) {
+ /* Put loose page numbers in mt_free_pgs, since
+ * we may be unable to return them to me_pghead.
+ */
+ MDB_page *mp = txn->mt_loose_pgs;
+ if ((rc = mdb_midl_need(&txn->mt_free_pgs, txn->mt_loose_count)) != 0)
+ return rc;
+ for (; mp; mp = NEXT_LOOSE_PAGE(mp))
+ mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
+ txn->mt_loose_pgs = NULL;
+ txn->mt_loose_count = 0;
+ }
+
+ /* MDB_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */
+ clean_limit = (env->me_flags & (MDB_NOMEMINIT|MDB_WRITEMAP))
+ ? SSIZE_MAX : maxfree_1pg;
+
+ for (;;) {
+ /* Come back here after each Put() in case freelist changed */
+ MDB_val key, data;
+ pgno_t *pgs;
+ ssize_t j;
+
+ /* If using records from freeDB which we have not yet
+ * deleted, delete them and any we reserved for me_pghead.
+ */
+ while (pglast < env->me_pglast) {
+ rc = mdb_cursor_first(&mc, &key, NULL);
+ if (rc)
+ return rc;
+ pglast = head_id = *(txnid_t *)key.mv_data;
+ total_room = head_room = 0;
+ mdb_tassert(txn, pglast <= env->me_pglast);
+ rc = mdb_cursor_del(&mc, 0);
+ if (rc)
+ return rc;
+ }
+
+ /* Save the IDL of pages freed by this txn, to a single record */
+ if (freecnt < txn->mt_free_pgs[0]) {
+ if (!freecnt) {
+ /* Make sure last page of freeDB is touched and on freelist */
+ rc = mdb_page_search(&mc, NULL, MDB_PS_LAST|MDB_PS_MODIFY);
+ if (rc && rc != MDB_NOTFOUND)
+ return rc;
+ }
+ free_pgs = txn->mt_free_pgs;
+ /* Write to last page of freeDB */
+ key.mv_size = sizeof(txn->mt_txnid);
+ key.mv_data = &txn->mt_txnid;
+ do {
+ freecnt = free_pgs[0];
+ data.mv_size = MDB_IDL_SIZEOF(free_pgs);
+ rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
+ if (rc)
+ return rc;
+ /* Retry if mt_free_pgs[] grew during the Put() */
+ free_pgs = txn->mt_free_pgs;
+ } while (freecnt < free_pgs[0]);
+ mdb_midl_sort(free_pgs);
+ memcpy(data.mv_data, free_pgs, data.mv_size);
+#if (MDB_DEBUG) > 1
+ {
+ unsigned int i = free_pgs[0];
+ DPRINTF(("IDL write txn %"Z"u root %"Z"u num %u",
+ txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i));
+ for (; i; i--)
+ DPRINTF(("IDL %"Z"u", free_pgs[i]));
+ }
+#endif
+ continue;
+ }
+
+ mop = env->me_pghead;
+ mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count;
+
+ /* Reserve records for me_pghead[]. Split it if multi-page,
+ * to avoid searching freeDB for a page range. Use keys in
+ * range [1,me_pglast]: Smaller than txnid of oldest reader.
+ */
+ if (total_room >= mop_len) {
+ if (total_room == mop_len || --more < 0)
+ break;
+ } else if (head_room >= maxfree_1pg && head_id > 1) {
+ /* Keep current record (overflow page), add a new one */
+ head_id--;
+ head_room = 0;
+ }
+ /* (Re)write {key = head_id, IDL length = head_room} */
+ total_room -= head_room;
+ head_room = mop_len - total_room;
+ if (head_room > maxfree_1pg && head_id > 1) {
+ /* Overflow multi-page for part of me_pghead */
+ head_room /= head_id; /* amortize page sizes */
+ head_room += maxfree_1pg - head_room % (maxfree_1pg + 1);
+ } else if (head_room < 0) {
+ /* Rare case, not bothering to delete this record */
+ head_room = 0;
+ }
+ key.mv_size = sizeof(head_id);
+ key.mv_data = &head_id;
+ data.mv_size = (head_room + 1) * sizeof(pgno_t);
+ rc = mdb_cursor_put(&mc, &key, &data, MDB_RESERVE);
+ if (rc)
+ return rc;
+ /* IDL is initially empty, zero out at least the length */
+ pgs = (pgno_t *)data.mv_data;
+ j = head_room > clean_limit ? head_room : 0;
+ do {
+ pgs[j] = 0;
+ } while (--j >= 0);
+ total_room += head_room;
+ }
+
+ /* Return loose page numbers to me_pghead, though usually none are
+ * left at this point. The pages themselves remain in dirty_list.
+ */
+ if (txn->mt_loose_pgs) {
+ MDB_page *mp = txn->mt_loose_pgs;
+ unsigned count = txn->mt_loose_count;
+ MDB_IDL loose;
+ /* Room for loose pages + temp IDL with same */
+ if ((rc = mdb_midl_need(&env->me_pghead, 2*count+1)) != 0)
+ return rc;
+ mop = env->me_pghead;
+ loose = mop + MDB_IDL_ALLOCLEN(mop) - count;
+ for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp))
+ loose[ ++count ] = mp->mp_pgno;
+ loose[0] = count;
+ mdb_midl_sort(loose);
+ mdb_midl_xmerge(mop, loose);
+ txn->mt_loose_pgs = NULL;
+ txn->mt_loose_count = 0;
+ mop_len = mop[0];
+ }
+
+ /* Fill in the reserved me_pghead records */
+ rc = MDB_SUCCESS;
+ if (mop_len) {
+ MDB_val key, data;
+
+ mop += mop_len;
+ rc = mdb_cursor_first(&mc, &key, &data);
+ for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) {
+ txnid_t id = *(txnid_t *)key.mv_data;
+ ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1;
+ MDB_ID save;
+
+ mdb_tassert(txn, len >= 0 && id <= env->me_pglast);
+ key.mv_data = &id;
+ if (len > mop_len) {
+ len = mop_len;
+ data.mv_size = (len + 1) * sizeof(MDB_ID);
+ }
+ data.mv_data = mop -= len;
+ save = mop[0];
+ mop[0] = len;
+ rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT);
+ mop[0] = save;
+ if (rc || !(mop_len -= len))
+ break;
+ }
+ }
+ return rc;
+}
+
+/** Flush (some) dirty pages to the map, after clearing their dirty flag.
+ * @param[in] txn the transaction that's being committed
+ * @param[in] keep number of initial pages in dirty_list to keep dirty.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_flush(MDB_txn *txn, int keep)
+{
+ MDB_env *env = txn->mt_env;
+ MDB_ID2L dl = txn->mt_u.dirty_list;
+ unsigned psize = env->me_psize, j;
+ int i, pagecount = dl[0].mid, rc;
+ size_t size = 0, pos = 0;
+ pgno_t pgno = 0;
+ MDB_page *dp = NULL;
+#ifdef _WIN32
+ OVERLAPPED ov;
+#else
+ struct iovec iov[MDB_COMMIT_PAGES];
+ ssize_t wpos = 0, wsize = 0, wres;
+ size_t next_pos = 1; /* impossible pos, so pos != next_pos */
+ int n = 0;
+#endif
+
+ j = i = keep;
+
+ if (env->me_flags & MDB_WRITEMAP) {
+ /* Clear dirty flags */
+ while (++i <= pagecount) {
+ dp = dl[i].mptr;
+ /* Don't flush this page yet */
+ if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
+ dp->mp_flags &= ~P_KEEP;
+ dl[++j] = dl[i];
+ continue;
+ }
+ dp->mp_flags &= ~P_DIRTY;
+ }
+ goto done;
+ }
+
+ /* Write the pages */
+ for (;;) {
+ if (++i <= pagecount) {
+ dp = dl[i].mptr;
+ /* Don't flush this page yet */
+ if (dp->mp_flags & (P_LOOSE|P_KEEP)) {
+ dp->mp_flags &= ~P_KEEP;
+ dl[i].mid = 0;
+ continue;
+ }
+ pgno = dl[i].mid;
+ /* clear dirty flag */
+ dp->mp_flags &= ~P_DIRTY;
+ pos = pgno * psize;
+ size = psize;
+ if (IS_OVERFLOW(dp)) size *= dp->mp_pages;
+ }
+#ifdef _WIN32
+ else break;
+
+ /* Windows actually supports scatter/gather I/O, but only on
+ * unbuffered file handles. Since we're relying on the OS page
+ * cache for all our data, that's self-defeating. So we just
+ * write pages one at a time. We use the ov structure to set
+ * the write offset, to at least save the overhead of a Seek
+ * system call.
+ */
+ DPRINTF(("committing page %"Z"u", pgno));
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset = pos & 0xffffffff;
+ ov.OffsetHigh = pos >> 16 >> 16;
+ if (!WriteFile(env->me_fd, dp, size, NULL, &ov)) {
+ rc = ErrCode();
+ DPRINTF(("WriteFile: %d", rc));
+ return rc;
+ }
+#else
+ /* Write up to MDB_COMMIT_PAGES dirty pages at a time. */
+ if (pos!=next_pos || n==MDB_COMMIT_PAGES || wsize+size>MAX_WRITE) {
+ if (n) {
+retry_write:
+ /* Write previous page(s) */
+#ifdef MDB_USE_PWRITEV
+ wres = pwritev(env->me_fd, iov, n, wpos);
+#else
+ if (n == 1) {
+ wres = pwrite(env->me_fd, iov[0].iov_base, wsize, wpos);
+ } else {
+retry_seek:
+ if (lseek(env->me_fd, wpos, SEEK_SET) == -1) {
+ rc = ErrCode();
+ if (rc == EINTR)
+ goto retry_seek;
+ DPRINTF(("lseek: %s", strerror(rc)));
+ return rc;
+ }
+ wres = writev(env->me_fd, iov, n);
+ }
+#endif
+ if (wres != wsize) {
+ if (wres < 0) {
+ rc = ErrCode();
+ if (rc == EINTR)
+ goto retry_write;
+ DPRINTF(("Write error: %s", strerror(rc)));
+ } else {
+ rc = EIO; /* TODO: Use which error code? */
+ DPUTS("short write, filesystem full?");
+ }
+ return rc;
+ }
+ n = 0;
+ }
+ if (i > pagecount)
+ break;
+ wpos = pos;
+ wsize = 0;
+ }
+ DPRINTF(("committing page %"Z"u", pgno));
+ next_pos = pos + size;
+ iov[n].iov_len = size;
+ iov[n].iov_base = (char *)dp;
+ wsize += size;
+ n++;
+#endif /* _WIN32 */
+ }
+
+ /* MIPS has cache coherency issues, this is a no-op everywhere else
+ * Note: for any size >= on-chip cache size, entire on-chip cache is
+ * flushed.
+ */
+ CACHEFLUSH(env->me_map, txn->mt_next_pgno * env->me_psize, DCACHE);
+
+ for (i = keep; ++i <= pagecount; ) {
+ dp = dl[i].mptr;
+ /* This is a page we skipped above */
+ if (!dl[i].mid) {
+ dl[++j] = dl[i];
+ dl[j].mid = dp->mp_pgno;
+ continue;
+ }
+ mdb_dpage_free(env, dp);
+ }
+
+done:
+ i--;
+ txn->mt_dirty_room += i - j;
+ dl[0].mid = j;
+ return MDB_SUCCESS;
+}
+
+int
+mdb_txn_commit(MDB_txn *txn)
+{
+ int rc;
+ unsigned int i, end_mode;
+ MDB_env *env;
+
+ if (txn == NULL)
+ return EINVAL;
+
+ /* mdb_txn_end() mode for a commit which writes nothing */
+ end_mode = MDB_END_EMPTY_COMMIT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE;
+
+ if (txn->mt_child) {
+ rc = mdb_txn_commit(txn->mt_child);
+ if (rc)
+ goto fail;
+ }
+
+ env = txn->mt_env;
+
+ if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) {
+ goto done;
+ }
+
+ if (txn->mt_flags & (MDB_TXN_FINISHED|MDB_TXN_ERROR)) {
+ DPUTS("txn has failed/finished, can't commit");
+ if (txn->mt_parent)
+ txn->mt_parent->mt_flags |= MDB_TXN_ERROR;
+ rc = MDB_BAD_TXN;
+ goto fail;
+ }
+
+ if (txn->mt_parent) {
+ MDB_txn *parent = txn->mt_parent;
+ MDB_page **lp;
+ MDB_ID2L dst, src;
+ MDB_IDL pspill;
+ unsigned x, y, len, ps_len;
+
+ /* Append our free list to parent's */
+ rc = mdb_midl_append_list(&parent->mt_free_pgs, txn->mt_free_pgs);
+ if (rc)
+ goto fail;
+ mdb_midl_free(txn->mt_free_pgs);
+ /* Failures after this must either undo the changes
+ * to the parent or set MDB_TXN_ERROR in the parent.
+ */
+
+ parent->mt_next_pgno = txn->mt_next_pgno;
+ parent->mt_flags = txn->mt_flags;
+
+ /* Merge our cursors into parent's and close them */
+ mdb_cursors_close(txn, 1);
+
+ /* Update parent's DB table. */
+ memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
+ parent->mt_numdbs = txn->mt_numdbs;
+ parent->mt_dbflags[FREE_DBI] = txn->mt_dbflags[FREE_DBI];
+ parent->mt_dbflags[MAIN_DBI] = txn->mt_dbflags[MAIN_DBI];
+ for (i=CORE_DBS; i<txn->mt_numdbs; i++) {
+ /* preserve parent's DB_NEW status */
+ x = parent->mt_dbflags[i] & DB_NEW;
+ parent->mt_dbflags[i] = txn->mt_dbflags[i] | x;
+ }
+
+ dst = parent->mt_u.dirty_list;
+ src = txn->mt_u.dirty_list;
+ /* Remove anything in our dirty list from parent's spill list */
+ if ((pspill = parent->mt_spill_pgs) && (ps_len = pspill[0])) {
+ x = y = ps_len;
+ pspill[0] = (pgno_t)-1;
+ /* Mark our dirty pages as deleted in parent spill list */
+ for (i=0, len=src[0].mid; ++i <= len; ) {
+ MDB_ID pn = src[i].mid << 1;
+ while (pn > pspill[x])
+ x--;
+ if (pn == pspill[x]) {
+ pspill[x] = 1;
+ y = --x;
+ }
+ }
+ /* Squash deleted pagenums if we deleted any */
+ for (x=y; ++x <= ps_len; )
+ if (!(pspill[x] & 1))
+ pspill[++y] = pspill[x];
+ pspill[0] = y;
+ }
+
+ /* Remove anything in our spill list from parent's dirty list */
+ if (txn->mt_spill_pgs && txn->mt_spill_pgs[0]) {
+ for (i=1; i<=txn->mt_spill_pgs[0]; i++) {
+ MDB_ID pn = txn->mt_spill_pgs[i];
+ if (pn & 1)
+ continue; /* deleted spillpg */
+ pn >>= 1;
+ y = mdb_mid2l_search(dst, pn);
+ if (y <= dst[0].mid && dst[y].mid == pn) {
+ free(dst[y].mptr);
+ while (y < dst[0].mid) {
+ dst[y] = dst[y+1];
+ y++;
+ }
+ dst[0].mid--;
+ }
+ }
+ }
+
+ /* Find len = length of merging our dirty list with parent's */
+ x = dst[0].mid;
+ dst[0].mid = 0; /* simplify loops */
+ if (parent->mt_parent) {
+ len = x + src[0].mid;
+ y = mdb_mid2l_search(src, dst[x].mid + 1) - 1;
+ for (i = x; y && i; y--) {
+ pgno_t yp = src[y].mid;
+ while (yp < dst[i].mid)
+ i--;
+ if (yp == dst[i].mid) {
+ i--;
+ len--;
+ }
+ }
+ } else { /* Simplify the above for single-ancestor case */
+ len = MDB_IDL_UM_MAX - txn->mt_dirty_room;
+ }
+ /* Merge our dirty list with parent's */
+ y = src[0].mid;
+ for (i = len; y; dst[i--] = src[y--]) {
+ pgno_t yp = src[y].mid;
+ while (yp < dst[x].mid)
+ dst[i--] = dst[x--];
+ if (yp == dst[x].mid)
+ free(dst[x--].mptr);
+ }
+ mdb_tassert(txn, i == x);
+ dst[0].mid = len;
+ free(txn->mt_u.dirty_list);
+ parent->mt_dirty_room = txn->mt_dirty_room;
+ if (txn->mt_spill_pgs) {
+ if (parent->mt_spill_pgs) {
+ /* TODO: Prevent failure here, so parent does not fail */
+ rc = mdb_midl_append_list(&parent->mt_spill_pgs, txn->mt_spill_pgs);
+ if (rc)
+ parent->mt_flags |= MDB_TXN_ERROR;
+ mdb_midl_free(txn->mt_spill_pgs);
+ mdb_midl_sort(parent->mt_spill_pgs);
+ } else {
+ parent->mt_spill_pgs = txn->mt_spill_pgs;
+ }
+ }
+
+ /* Append our loose page list to parent's */
+ for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(*lp))
+ ;
+ *lp = txn->mt_loose_pgs;
+ parent->mt_loose_count += txn->mt_loose_count;
+
+ parent->mt_child = NULL;
+ mdb_midl_free(((MDB_ntxn *)txn)->mnt_pgstate.mf_pghead);
+ free(txn);
+ return rc;
+ }
+
+ if (txn != env->me_txn) {
+ DPUTS("attempt to commit unknown transaction");
+ rc = EINVAL;
+ goto fail;
+ }
+
+ mdb_cursors_close(txn, 0);
+
+ if (!txn->mt_u.dirty_list[0].mid &&
+ !(txn->mt_flags & (MDB_TXN_DIRTY|MDB_TXN_SPILLS)))
+ goto done;
+
+ DPRINTF(("committing txn %"Z"u %p on mdbenv %p, root page %"Z"u",
+ txn->mt_txnid, (void*)txn, (void*)env, txn->mt_dbs[MAIN_DBI].md_root));
+
+ /* Update DB root pointers */
+ if (txn->mt_numdbs > CORE_DBS) {
+ MDB_cursor mc;
+ MDB_dbi i;
+ MDB_val data;
+ data.mv_size = sizeof(MDB_db);
+
+ mdb_cursor_init(&mc, txn, MAIN_DBI, NULL);
+ for (i = CORE_DBS; i < txn->mt_numdbs; i++) {
+ if (txn->mt_dbflags[i] & DB_DIRTY) {
+ if (TXN_DBI_CHANGED(txn, i)) {
+ rc = MDB_BAD_DBI;
+ goto fail;
+ }
+ data.mv_data = &txn->mt_dbs[i];
+ rc = mdb_cursor_put(&mc, &txn->mt_dbxs[i].md_name, &data,
+ F_SUBDATA);
+ if (rc)
+ goto fail;
+ }
+ }
+ }
+
+ rc = mdb_freelist_save(txn);
+ if (rc)
+ goto fail;
+
+ mdb_midl_free(env->me_pghead);
+ env->me_pghead = NULL;
+ mdb_midl_shrink(&txn->mt_free_pgs);
+
+#if (MDB_DEBUG) > 2
+ mdb_audit(txn);
+#endif
+
+ if ((rc = mdb_page_flush(txn, 0)) ||
+ (rc = mdb_env_sync(env, 0)) ||
+ (rc = mdb_env_write_meta(txn)))
+ goto fail;
+ end_mode = MDB_END_COMMITTED|MDB_END_UPDATE;
+
+done:
+ mdb_txn_end(txn, end_mode);
+ return MDB_SUCCESS;
+
+fail:
+ mdb_txn_abort(txn);
+ return rc;
+}
+
+/** Read the environment parameters of a DB environment before
+ * mapping it into memory.
+ * @param[in] env the environment handle
+ * @param[out] meta address of where to store the meta information
+ * @return 0 on success, non-zero on failure.
+ */
+static int ESECT
+mdb_env_read_header(MDB_env *env, MDB_meta *meta)
+{
+ MDB_metabuf pbuf;
+ MDB_page *p;
+ MDB_meta *m;
+ int i, rc, off;
+ enum { Size = sizeof(pbuf) };
+
+ /* We don't know the page size yet, so use a minimum value.
+ * Read both meta pages so we can use the latest one.
+ */
+
+ for (i=off=0; i<NUM_METAS; i++, off += meta->mm_psize) {
+#ifdef _WIN32
+ DWORD len;
+ OVERLAPPED ov;
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset = off;
+ rc = ReadFile(env->me_fd, &pbuf, Size, &len, &ov) ? (int)len : -1;
+ if (rc == -1 && ErrCode() == ERROR_HANDLE_EOF)
+ rc = 0;
+#else
+ rc = pread(env->me_fd, &pbuf, Size, off);
+#endif
+ if (rc != Size) {
+ if (rc == 0 && off == 0)
+ return ENOENT;
+ rc = rc < 0 ? (int) ErrCode() : MDB_INVALID;
+ DPRINTF(("read: %s", mdb_strerror(rc)));
+ return rc;
+ }
+
+ p = (MDB_page *)&pbuf;
+
+ if (!F_ISSET(p->mp_flags, P_META)) {
+ DPRINTF(("page %"Z"u not a meta page", p->mp_pgno));
+ return MDB_INVALID;
+ }
+
+ m = METADATA(p);
+ if (m->mm_magic != MDB_MAGIC) {
+ DPUTS("meta has invalid magic");
+ return MDB_INVALID;
+ }
+
+ if (m->mm_version != MDB_DATA_VERSION) {
+ DPRINTF(("database is version %u, expected version %u",
+ m->mm_version, MDB_DATA_VERSION));
+ return MDB_VERSION_MISMATCH;
+ }
+
+ if (off == 0 || m->mm_txnid > meta->mm_txnid)
+ *meta = *m;
+ }
+ return 0;
+}
+
+/** Fill in most of the zeroed #MDB_meta for an empty database environment */
+static void ESECT
+mdb_env_init_meta0(MDB_env *env, MDB_meta *meta)
+{
+ meta->mm_magic = MDB_MAGIC;
+ meta->mm_version = MDB_DATA_VERSION;
+ meta->mm_mapsize = env->me_mapsize;
+ meta->mm_psize = env->me_psize;
+ meta->mm_last_pg = NUM_METAS-1;
+ meta->mm_flags = env->me_flags & 0xffff;
+ meta->mm_flags |= MDB_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */
+ meta->mm_dbs[FREE_DBI].md_root = P_INVALID;
+ meta->mm_dbs[MAIN_DBI].md_root = P_INVALID;
+}
+
+/** Write the environment parameters of a freshly created DB environment.
+ * @param[in] env the environment handle
+ * @param[in] meta the #MDB_meta to write
+ * @return 0 on success, non-zero on failure.
+ */
+static int ESECT
+mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
+{
+ MDB_page *p, *q;
+ int rc;
+ unsigned int psize;
+#ifdef _WIN32
+ DWORD len;
+ OVERLAPPED ov;
+ memset(&ov, 0, sizeof(ov));
+#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \
+ ov.Offset = pos; \
+ rc = WriteFile(fd, ptr, size, &len, &ov); } while(0)
+#else
+ int len;
+#define DO_PWRITE(rc, fd, ptr, size, len, pos) do { \
+ len = pwrite(fd, ptr, size, pos); \
+ if (len == -1 && ErrCode() == EINTR) continue; \
+ rc = (len >= 0); break; } while(1)
+#endif
+
+ DPUTS("writing new meta page");
+
+ psize = env->me_psize;
+
+ p = calloc(NUM_METAS, psize);
+ if (!p)
+ return ENOMEM;
+
+ p->mp_pgno = 0;
+ p->mp_flags = P_META;
+ *(MDB_meta *)METADATA(p) = *meta;
+
+ q = (MDB_page *)((char *)p + psize);
+ q->mp_pgno = 1;
+ q->mp_flags = P_META;
+ *(MDB_meta *)METADATA(q) = *meta;
+
+ DO_PWRITE(rc, env->me_fd, p, psize * NUM_METAS, len, 0);
+ if (!rc)
+ rc = ErrCode();
+ else if ((unsigned) len == psize * NUM_METAS)
+ rc = MDB_SUCCESS;
+ else
+ rc = ENOSPC;
+ free(p);
+ return rc;
+}
+
+/** Update the environment info to commit a transaction.
+ * @param[in] txn the transaction that's being committed
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_env_write_meta(MDB_txn *txn)
+{
+ MDB_env *env;
+ MDB_meta meta, metab, *mp;
+ unsigned flags;
+ size_t mapsize;
+ off_t off;
+ int rc, len, toggle;
+ char *ptr;
+ HANDLE mfd;
+#ifdef _WIN32
+ OVERLAPPED ov;
+#else
+ int r2;
+#endif
+
+ toggle = txn->mt_txnid & 1;
+ DPRINTF(("writing meta page %d for root page %"Z"u",
+ toggle, txn->mt_dbs[MAIN_DBI].md_root));
+
+ env = txn->mt_env;
+ flags = env->me_flags;
+ mp = env->me_metas[toggle];
+ mapsize = env->me_metas[toggle ^ 1]->mm_mapsize;
+ /* Persist any increases of mapsize config */
+ if (mapsize < env->me_mapsize)
+ mapsize = env->me_mapsize;
+
+ if (flags & MDB_WRITEMAP) {
+ mp->mm_mapsize = mapsize;
+ mp->mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI];
+ mp->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
+ mp->mm_last_pg = txn->mt_next_pgno - 1;
+#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 404) && /* TODO: portability */ \
+ !(defined(__i386__) || defined(__x86_64__))
+ /* LY: issue a memory barrier, if not x86. ITS#7969 */
+ __sync_synchronize();
+#endif
+ mp->mm_txnid = txn->mt_txnid;
+ if (!(flags & (MDB_NOMETASYNC|MDB_NOSYNC))) {
+ unsigned meta_size = env->me_psize;
+ rc = (env->me_flags & MDB_MAPASYNC) ? MS_ASYNC : MS_SYNC;
+ ptr = (char *)mp - PAGEHDRSZ;
+#ifndef _WIN32 /* POSIX msync() requires ptr = start of OS page */
+ r2 = (ptr - env->me_map) & (env->me_os_psize - 1);
+ ptr -= r2;
+ meta_size += r2;
+#endif
+ if (MDB_MSYNC(ptr, meta_size, rc)) {
+ rc = ErrCode();
+ goto fail;
+ }
+ }
+ goto done;
+ }
+ metab.mm_txnid = mp->mm_txnid;
+ metab.mm_last_pg = mp->mm_last_pg;
+
+ meta.mm_mapsize = mapsize;
+ meta.mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI];
+ meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
+ meta.mm_last_pg = txn->mt_next_pgno - 1;
+ meta.mm_txnid = txn->mt_txnid;
+
+ off = offsetof(MDB_meta, mm_mapsize);
+ ptr = (char *)&meta + off;
+ len = sizeof(MDB_meta) - off;
+ off += (char *)mp - env->me_map;
+
+ /* Write to the SYNC fd unless MDB_NOSYNC/MDB_NOMETASYNC.
+ * (me_mfd goes to the same file as me_fd, but writing to it
+ * also syncs to disk. Avoids a separate fdatasync() call.)
+ */
+ mfd = (flags & (MDB_NOSYNC|MDB_NOMETASYNC)) ? env->me_fd : env->me_mfd;
+#ifdef _WIN32
+ {
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset = off;
+ if (!WriteFile(mfd, ptr, len, (DWORD *)&rc, &ov))
+ rc = -1;
+ }
+#else
+retry_write:
+ rc = pwrite(mfd, ptr, len, off);
+#endif
+ if (rc != len) {
+ rc = rc < 0 ? ErrCode() : EIO;
+#ifndef _WIN32
+ if (rc == EINTR)
+ goto retry_write;
+#endif
+ DPUTS("write failed, disk error?");
+ /* On a failure, the pagecache still contains the new data.
+ * Write some old data back, to prevent it from being used.
+ * Use the non-SYNC fd; we know it will fail anyway.
+ */
+ meta.mm_last_pg = metab.mm_last_pg;
+ meta.mm_txnid = metab.mm_txnid;
+#ifdef _WIN32
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset = off;
+ WriteFile(env->me_fd, ptr, len, NULL, &ov);
+#else
+ r2 = pwrite(env->me_fd, ptr, len, off);
+ (void)r2; /* Silence warnings. We don't care about pwrite's return value */
+#endif
+fail:
+ env->me_flags |= MDB_FATAL_ERROR;
+ return rc;
+ }
+ /* MIPS has cache coherency issues, this is a no-op everywhere else */
+ CACHEFLUSH(env->me_map + off, len, DCACHE);
+done:
+ /* Memory ordering issues are irrelevant; since the entire writer
+ * is wrapped by wmutex, all of these changes will become visible
+ * after the wmutex is unlocked. Since the DB is multi-version,
+ * readers will get consistent data regardless of how fresh or
+ * how stale their view of these values is.
+ */
+ if (env->me_txns)
+ env->me_txns->mti_txnid = txn->mt_txnid;
+
+ return MDB_SUCCESS;
+}
+
+/** Check both meta pages to see which one is newer.
+ * @param[in] env the environment handle
+ * @return newest #MDB_meta.
+ */
+static MDB_meta *
+mdb_env_pick_meta(const MDB_env *env)
+{
+ MDB_meta *const *metas = env->me_metas;
+ return metas[ metas[0]->mm_txnid < metas[1]->mm_txnid ];
+}
+
+int ESECT
+mdb_env_create(MDB_env **env)
+{
+ MDB_env *e;
+
+ e = calloc(1, sizeof(MDB_env));
+ if (!e)
+ return ENOMEM;
+
+ e->me_maxreaders = DEFAULT_READERS;
+ e->me_maxdbs = e->me_numdbs = CORE_DBS;
+ e->me_fd = INVALID_HANDLE_VALUE;
+ e->me_lfd = INVALID_HANDLE_VALUE;
+ e->me_mfd = INVALID_HANDLE_VALUE;
+#ifdef MDB_USE_POSIX_SEM
+ e->me_rmutex = SEM_FAILED;
+ e->me_wmutex = SEM_FAILED;
+#endif
+ e->me_pid = getpid();
+ GET_PAGESIZE(e->me_os_psize);
+ VGMEMP_CREATE(e,0,0);
+ *env = e;
+ return MDB_SUCCESS;
+}
+
+static int ESECT
+mdb_env_map(MDB_env *env, void *addr)
+{
+ MDB_page *p;
+ unsigned int flags = env->me_flags;
+#ifdef _WIN32
+ int rc;
+ HANDLE mh;
+ LONG sizelo, sizehi;
+ size_t msize;
+
+ if (flags & MDB_RDONLY) {
+ /* Don't set explicit map size, use whatever exists */
+ msize = 0;
+ sizelo = 0;
+ sizehi = 0;
+ } else {
+ msize = env->me_mapsize;
+ sizelo = msize & 0xffffffff;
+ sizehi = msize >> 16 >> 16; /* only needed on Win64 */
+
+ /* Windows won't create mappings for zero length files.
+ * and won't map more than the file size.
+ * Just set the maxsize right now.
+ */
+ if (SetFilePointer(env->me_fd, sizelo, &sizehi, 0) != (DWORD)sizelo
+ || !SetEndOfFile(env->me_fd)
+ || SetFilePointer(env->me_fd, 0, NULL, 0) != 0)
+ return ErrCode();
+ }
+
+ mh = CreateFileMapping(env->me_fd, NULL, flags & MDB_WRITEMAP ?
+ PAGE_READWRITE : PAGE_READONLY,
+ sizehi, sizelo, NULL);
+ if (!mh)
+ return ErrCode();
+ env->me_map = MapViewOfFileEx(mh, flags & MDB_WRITEMAP ?
+ FILE_MAP_WRITE : FILE_MAP_READ,
+ 0, 0, msize, addr);
+ rc = env->me_map ? 0 : ErrCode();
+ CloseHandle(mh);
+ if (rc)
+ return rc;
+#else
+ int prot = PROT_READ;
+ if (flags & MDB_WRITEMAP) {
+ prot |= PROT_WRITE;
+ if (ftruncate(env->me_fd, env->me_mapsize) < 0)
+ return ErrCode();
+ }
+ env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED,
+ env->me_fd, 0);
+ if (env->me_map == MAP_FAILED) {
+ env->me_map = NULL;
+ return ErrCode();
+ }
+
+ if (flags & MDB_NORDAHEAD) {
+ /* Turn off readahead. It's harmful when the DB is larger than RAM. */
+#ifdef MADV_RANDOM
+ madvise(env->me_map, env->me_mapsize, MADV_RANDOM);
+#else
+#ifdef POSIX_MADV_RANDOM
+ posix_madvise(env->me_map, env->me_mapsize, POSIX_MADV_RANDOM);
+#endif /* POSIX_MADV_RANDOM */
+#endif /* MADV_RANDOM */
+ }
+#endif /* _WIN32 */
+
+ /* Can happen because the address argument to mmap() is just a
+ * hint. mmap() can pick another, e.g. if the range is in use.
+ * The MAP_FIXED flag would prevent that, but then mmap could
+ * instead unmap existing pages to make room for the new map.
+ */
+ if (addr && env->me_map != addr)
+ return EBUSY; /* TODO: Make a new MDB_* error code? */
+
+ p = (MDB_page *)env->me_map;
+ env->me_metas[0] = METADATA(p);
+ env->me_metas[1] = (MDB_meta *)((char *)env->me_metas[0] + env->me_psize);
+
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_set_mapsize(MDB_env *env, size_t size)
+{
+ /* If env is already open, caller is responsible for making
+ * sure there are no active txns.
+ */
+ if (env->me_map) {
+ int rc;
+ MDB_meta *meta;
+ void *old;
+ if (env->me_txn)
+ return EINVAL;
+ meta = mdb_env_pick_meta(env);
+ if (!size)
+ size = meta->mm_mapsize;
+ {
+ /* Silently round up to minimum if the size is too small */
+ size_t minsize = (meta->mm_last_pg + 1) * env->me_psize;
+ if (size < minsize)
+ size = minsize;
+ }
+ munmap(env->me_map, env->me_mapsize);
+ env->me_mapsize = size;
+ old = (env->me_flags & MDB_FIXEDMAP) ? env->me_map : NULL;
+ rc = mdb_env_map(env, old);
+ if (rc)
+ return rc;
+ }
+ env->me_mapsize = size;
+ if (env->me_psize)
+ env->me_maxpg = env->me_mapsize / env->me_psize;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
+{
+ if (env->me_map)
+ return EINVAL;
+ env->me_maxdbs = dbs + CORE_DBS;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_set_maxreaders(MDB_env *env, unsigned int readers)
+{
+ if (env->me_map || readers < 1)
+ return EINVAL;
+ env->me_maxreaders = readers;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
+{
+ if (!env || !readers)
+ return EINVAL;
+ *readers = env->me_maxreaders;
+ return MDB_SUCCESS;
+}
+
+static int ESECT
+mdb_fsize(HANDLE fd, size_t *size)
+{
+#ifdef _WIN32
+ LARGE_INTEGER fsize;
+
+ if (!GetFileSizeEx(fd, &fsize))
+ return ErrCode();
+
+ *size = fsize.QuadPart;
+#else
+ struct stat st;
+
+ if (fstat(fd, &st))
+ return ErrCode();
+
+ *size = st.st_size;
+#endif
+ return MDB_SUCCESS;
+}
+
+
+#ifdef _WIN32
+typedef wchar_t mdb_nchar_t;
+# define MDB_NAME(str) L##str
+# define mdb_name_cpy wcscpy
+#else
+/** Character type for file names: char on Unix, wchar_t on Windows */
+typedef char mdb_nchar_t;
+# define MDB_NAME(str) str /**< #mdb_nchar_t[] string literal */
+# define mdb_name_cpy strcpy /**< Copy name (#mdb_nchar_t string) */
+#endif
+
+/** Filename - string of #mdb_nchar_t[] */
+typedef struct MDB_name {
+ int mn_len; /**< Length */
+ int mn_alloced; /**< True if #mn_val was malloced */
+ mdb_nchar_t *mn_val; /**< Contents */
+} MDB_name;
+
+/** Filename suffixes [datafile,lockfile][without,with MDB_NOSUBDIR] */
+static const mdb_nchar_t *const mdb_suffixes[2][2] = {
+ { MDB_NAME("/data.mdb"), MDB_NAME("") },
+ { MDB_NAME("/lock.mdb"), MDB_NAME("-lock") }
+};
+
+#define MDB_SUFFLEN 9 /**< Max string length in #mdb_suffixes[] */
+
+/** Set up filename + scratch area for filename suffix, for opening files.
+ * It should be freed with #mdb_fname_destroy().
+ * On Windows, paths are converted from char *UTF-8 to wchar_t *UTF-16.
+ *
+ * @param[in] path Pathname for #mdb_env_open().
+ * @param[in] envflags Whether a subdir and/or lockfile will be used.
+ * @param[out] fname Resulting filename, with room for a suffix if necessary.
+ */
+static int ESECT
+mdb_fname_init(const char *path, unsigned envflags, MDB_name *fname)
+{
+ int no_suffix = F_ISSET(envflags, MDB_NOSUBDIR|MDB_NOLOCK);
+ fname->mn_alloced = 0;
+#ifdef _WIN32
+ return utf8_to_utf16(path, fname, no_suffix ? 0 : MDB_SUFFLEN);
+#else
+ fname->mn_len = strlen(path);
+ if (no_suffix)
+ fname->mn_val = (char *) path;
+ else if ((fname->mn_val = malloc(fname->mn_len + MDB_SUFFLEN+1)) != NULL) {
+ fname->mn_alloced = 1;
+ strcpy(fname->mn_val, path);
+ }
+ else
+ return ENOMEM;
+ return MDB_SUCCESS;
+#endif
+}
+
+/** Destroy \b fname from #mdb_fname_init() */
+#define mdb_fname_destroy(fname) \
+ do { if ((fname).mn_alloced) free((fname).mn_val); } while (0)
+
+#ifdef O_CLOEXEC /* POSIX.1-2008: Set FD_CLOEXEC atomically at open() */
+# define MDB_CLOEXEC O_CLOEXEC
+#else
+# define MDB_CLOEXEC 0
+#endif
+
+/** File type, access mode etc. for #mdb_fopen() */
+enum mdb_fopen_type {
+#ifdef _WIN32
+ MDB_O_RDONLY, MDB_O_RDWR, MDB_O_META, MDB_O_COPY, MDB_O_LOCKS
+#else
+ /* A comment in mdb_fopen() explains some O_* flag choices. */
+ MDB_O_RDONLY= O_RDONLY, /**< for RDONLY me_fd */
+ MDB_O_RDWR = O_RDWR |O_CREAT, /**< for me_fd */
+ MDB_O_META = O_WRONLY|MDB_DSYNC |MDB_CLOEXEC, /**< for me_mfd */
+ MDB_O_COPY = O_WRONLY|O_CREAT|O_EXCL|MDB_CLOEXEC, /**< for #mdb_env_copy() */
+ /** Bitmask for open() flags in enum #mdb_fopen_type. The other bits
+ * distinguish otherwise-equal MDB_O_* constants from each other.
+ */
+ MDB_O_MASK = MDB_O_RDWR|MDB_CLOEXEC | MDB_O_RDONLY|MDB_O_META|MDB_O_COPY,
+ MDB_O_LOCKS = MDB_O_RDWR|MDB_CLOEXEC | ((MDB_O_MASK+1) & ~MDB_O_MASK) /**< for me_lfd */
+#endif
+};
+
+/** Open an LMDB file.
+ * @param[in] env The LMDB environment.
+ * @param[in,out] fname Path from from #mdb_fname_init(). A suffix is
+ * appended if necessary to create the filename, without changing mn_len.
+ * @param[in] which Determines file type, access mode, etc.
+ * @param[in] mode The Unix permissions for the file, if we create it.
+ * @param[out] res Resulting file handle.
+ * @return 0 on success, non-zero on failure.
+ */
+static int ESECT
+mdb_fopen(const MDB_env *env, MDB_name *fname,
+ enum mdb_fopen_type which, mdb_mode_t mode,
+ HANDLE *res)
+{
+ int rc = MDB_SUCCESS;
+ HANDLE fd;
+#ifdef _WIN32
+ DWORD acc, share, disp, attrs;
+#else
+ int flags;
+#endif
+
+ if (fname->mn_alloced) /* modifiable copy */
+ mdb_name_cpy(fname->mn_val + fname->mn_len,
+ mdb_suffixes[which==MDB_O_LOCKS][F_ISSET(env->me_flags, MDB_NOSUBDIR)]);
+
+ /* The directory must already exist. Usually the file need not.
+ * MDB_O_META requires the file because we already created it using
+ * MDB_O_RDWR. MDB_O_COPY must not overwrite an existing file.
+ *
+ * With MDB_O_COPY we do not want the OS to cache the writes, since
+ * the source data is already in the OS cache.
+ *
+ * The lockfile needs FD_CLOEXEC (close file descriptor on exec*())
+ * to avoid the flock() issues noted under Caveats in lmdb.h.
+ * Also set it for other filehandles which the user cannot get at
+ * and close himself, which he may need after fork(). I.e. all but
+ * me_fd, which programs do use via mdb_env_get_fd().
+ */
+
+#ifdef _WIN32
+ acc = GENERIC_READ|GENERIC_WRITE;
+ share = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ disp = OPEN_ALWAYS;
+ attrs = FILE_ATTRIBUTE_NORMAL;
+ switch (which) {
+ case MDB_O_RDONLY: /* read-only datafile */
+ acc = GENERIC_READ;
+ disp = OPEN_EXISTING;
+ break;
+ case MDB_O_META: /* for writing metapages */
+ acc = GENERIC_WRITE;
+ disp = OPEN_EXISTING;
+ attrs = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH;
+ break;
+ case MDB_O_COPY: /* mdb_env_copy() & co */
+ acc = GENERIC_WRITE;
+ share = 0;
+ disp = CREATE_NEW;
+ attrs = FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH;
+ break;
+ default: break; /* silence gcc -Wswitch (not all enum values handled) */
+ }
+ fd = CreateFileW(fname->mn_val, acc, share, NULL, disp, attrs, NULL);
+#else
+ fd = open(fname->mn_val, which & MDB_O_MASK, mode);
+#endif
+
+ if (fd == INVALID_HANDLE_VALUE)
+ rc = ErrCode();
+#ifndef _WIN32
+ else {
+ if (which != MDB_O_RDONLY && which != MDB_O_RDWR) {
+ /* Set CLOEXEC if we could not pass it to open() */
+ if (!MDB_CLOEXEC && (flags = fcntl(fd, F_GETFD)) != -1)
+ (void) fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ }
+ if (which == MDB_O_COPY && env->me_psize >= env->me_os_psize) {
+ /* This may require buffer alignment. There is no portable
+ * way to ask how much, so we require OS pagesize alignment.
+ */
+# ifdef F_NOCACHE /* __APPLE__ */
+ (void) fcntl(fd, F_NOCACHE, 1);
+# elif defined O_DIRECT
+ /* open(...O_DIRECT...) would break on filesystems without
+ * O_DIRECT support (ITS#7682). Try to set it here instead.
+ */
+ if ((flags = fcntl(fd, F_GETFL)) != -1)
+ (void) fcntl(fd, F_SETFL, flags | O_DIRECT);
+# endif
+ }
+ }
+#endif /* !_WIN32 */
+
+ *res = fd;
+ return rc;
+}
+
+
+#ifdef BROKEN_FDATASYNC
+#include <sys/utsname.h>
+#include <sys/vfs.h>
+#endif
+
+/** Further setup required for opening an LMDB environment
+ */
+static int ESECT
+mdb_env_open2(MDB_env *env)
+{
+ unsigned int flags = env->me_flags;
+ int i, newenv = 0, rc;
+ MDB_meta meta;
+
+#ifdef _WIN32
+ /* See if we should use QueryLimited */
+ rc = GetVersion();
+ if ((rc & 0xff) > 5)
+ env->me_pidquery = MDB_PROCESS_QUERY_LIMITED_INFORMATION;
+ else
+ env->me_pidquery = PROCESS_QUERY_INFORMATION;
+#endif /* _WIN32 */
+
+#ifdef BROKEN_FDATASYNC
+ /* ext3/ext4 fdatasync is broken on some older Linux kernels.
+ * https://lkml.org/lkml/2012/9/3/83
+ * Kernels after 3.6-rc6 are known good.
+ * https://lkml.org/lkml/2012/9/10/556
+ * See if the DB is on ext3/ext4, then check for new enough kernel
+ * Kernels 2.6.32.60, 2.6.34.15, 3.2.30, and 3.5.4 are also known
+ * to be patched.
+ */
+ {
+ struct statfs st;
+ fstatfs(env->me_fd, &st);
+ while (st.f_type == 0xEF53) {
+ struct utsname uts;
+ int i;
+ uname(&uts);
+ if (uts.release[0] < '3') {
+ if (!strncmp(uts.release, "2.6.32.", 7)) {
+ i = atoi(uts.release+7);
+ if (i >= 60)
+ break; /* 2.6.32.60 and newer is OK */
+ } else if (!strncmp(uts.release, "2.6.34.", 7)) {
+ i = atoi(uts.release+7);
+ if (i >= 15)
+ break; /* 2.6.34.15 and newer is OK */
+ }
+ } else if (uts.release[0] == '3') {
+ i = atoi(uts.release+2);
+ if (i > 5)
+ break; /* 3.6 and newer is OK */
+ if (i == 5) {
+ i = atoi(uts.release+4);
+ if (i >= 4)
+ break; /* 3.5.4 and newer is OK */
+ } else if (i == 2) {
+ i = atoi(uts.release+4);
+ if (i >= 30)
+ break; /* 3.2.30 and newer is OK */
+ }
+ } else { /* 4.x and newer is OK */
+ break;
+ }
+ env->me_flags |= MDB_FSYNCONLY;
+ break;
+ }
+ }
+#endif
+
+ if ((i = mdb_env_read_header(env, &meta)) != 0) {
+ if (i != ENOENT)
+ return i;
+ DPUTS("new mdbenv");
+ newenv = 1;
+ env->me_psize = env->me_os_psize;
+ if (env->me_psize > MAX_PAGESIZE)
+ env->me_psize = MAX_PAGESIZE;
+ memset(&meta, 0, sizeof(meta));
+ mdb_env_init_meta0(env, &meta);
+ meta.mm_mapsize = DEFAULT_MAPSIZE;
+ } else {
+ env->me_psize = meta.mm_psize;
+ }
+
+ /* Was a mapsize configured? */
+ if (!env->me_mapsize) {
+ env->me_mapsize = meta.mm_mapsize;
+ }
+ {
+ /* Make sure mapsize >= committed data size. Even when using
+ * mm_mapsize, which could be broken in old files (ITS#7789).
+ */
+ size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize;
+ if (env->me_mapsize < minsize)
+ env->me_mapsize = minsize;
+ }
+ meta.mm_mapsize = env->me_mapsize;
+
+ if (newenv && !(flags & MDB_FIXEDMAP)) {
+ /* mdb_env_map() may grow the datafile. Write the metapages
+ * first, so the file will be valid if initialization fails.
+ * Except with FIXEDMAP, since we do not yet know mm_address.
+ * We could fill in mm_address later, but then a different
+ * program might end up doing that - one with a memory layout
+ * and map address which does not suit the main program.
+ */
+ rc = mdb_env_init_meta(env, &meta);
+ if (rc)
+ return rc;
+ newenv = 0;
+ }
+
+ rc = mdb_env_map(env, (flags & MDB_FIXEDMAP) ? meta.mm_address : NULL);
+ if (rc)
+ return rc;
+
+ if (newenv) {
+ if (flags & MDB_FIXEDMAP)
+ meta.mm_address = env->me_map;
+ i = mdb_env_init_meta(env, &meta);
+ if (i != MDB_SUCCESS) {
+ return i;
+ }
+ }
+
+ env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1;
+ env->me_nodemax = (((env->me_psize - PAGEHDRSZ) / MDB_MINKEYS) & -2)
+ - sizeof(indx_t);
+#if !(MDB_MAXKEYSIZE)
+ env->me_maxkey = env->me_nodemax - (NODESIZE + sizeof(MDB_db));
+#endif
+ env->me_maxpg = env->me_mapsize / env->me_psize;
+
+#if MDB_DEBUG
+ {
+ MDB_meta *meta = mdb_env_pick_meta(env);
+ MDB_db *db = &meta->mm_dbs[MAIN_DBI];
+
+ DPRINTF(("opened database version %u, pagesize %u",
+ meta->mm_version, env->me_psize));
+ DPRINTF(("using meta page %d", (int) (meta->mm_txnid & 1)));
+ DPRINTF(("depth: %u", db->md_depth));
+ DPRINTF(("entries: %"Z"u", db->md_entries));
+ DPRINTF(("branch pages: %"Z"u", db->md_branch_pages));
+ DPRINTF(("leaf pages: %"Z"u", db->md_leaf_pages));
+ DPRINTF(("overflow pages: %"Z"u", db->md_overflow_pages));
+ DPRINTF(("root: %"Z"u", db->md_root));
+ }
+#endif
+
+ return MDB_SUCCESS;
+}
+
+
+/** Release a reader thread's slot in the reader lock table.
+ * This function is called automatically when a thread exits.
+ * @param[in] ptr This points to the slot in the reader lock table.
+ */
+static void
+mdb_env_reader_dest(void *ptr)
+{
+ MDB_reader *reader = ptr;
+
+#ifndef _WIN32
+ if (reader->mr_pid == getpid()) /* catch pthread_exit() in child process */
+#endif
+ /* We omit the mutex, so do this atomically (i.e. skip mr_txnid) */
+ reader->mr_pid = 0;
+}
+
+#ifdef _WIN32
+/** Junk for arranging thread-specific callbacks on Windows. This is
+ * necessarily platform and compiler-specific. Windows supports up
+ * to 1088 keys. Let's assume nobody opens more than 64 environments
+ * in a single process, for now. They can override this if needed.
+ */
+#ifndef MAX_TLS_KEYS
+#define MAX_TLS_KEYS 64
+#endif
+static pthread_key_t mdb_tls_keys[MAX_TLS_KEYS];
+static int mdb_tls_nkeys;
+
+static void NTAPI mdb_tls_callback(PVOID module, DWORD reason, PVOID ptr)
+{
+ int i;
+ switch(reason) {
+ case DLL_PROCESS_ATTACH: break;
+ case DLL_THREAD_ATTACH: break;
+ case DLL_THREAD_DETACH:
+ for (i=0; i<mdb_tls_nkeys; i++) {
+ MDB_reader *r = pthread_getspecific(mdb_tls_keys[i]);
+ if (r) {
+ mdb_env_reader_dest(r);
+ }
+ }
+ break;
+ case DLL_PROCESS_DETACH: break;
+ }
+}
+#ifdef __GNUC__
+#ifdef _WIN64
+const PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (".CRT$XLB"))) = mdb_tls_callback;
+#else
+PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (".CRT$XLB"))) = mdb_tls_callback;
+#endif
+#else
+#ifdef _WIN64
+/* Force some symbol references.
+ * _tls_used forces the linker to create the TLS directory if not already done
+ * mdb_tls_cbp prevents whole-program-optimizer from dropping the symbol.
+ */
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:mdb_tls_cbp")
+#pragma const_seg(".CRT$XLB")
+extern const PIMAGE_TLS_CALLBACK mdb_tls_cbp;
+const PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
+#pragma const_seg()
+#else /* _WIN32 */
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_mdb_tls_cbp")
+#pragma data_seg(".CRT$XLB")
+PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
+#pragma data_seg()
+#endif /* WIN 32/64 */
+#endif /* !__GNUC__ */
+#endif
+
+/** Downgrade the exclusive lock on the region back to shared */
+static int ESECT
+mdb_env_share_locks(MDB_env *env, int *excl)
+{
+ int rc = 0;
+ MDB_meta *meta = mdb_env_pick_meta(env);
+
+ env->me_txns->mti_txnid = meta->mm_txnid;
+
+#ifdef _WIN32
+ {
+ OVERLAPPED ov;
+ /* First acquire a shared lock. The Unlock will
+ * then release the existing exclusive lock.
+ */
+ memset(&ov, 0, sizeof(ov));
+ if (!LockFileEx(env->me_lfd, 0, 0, 1, 0, &ov)) {
+ rc = ErrCode();
+ } else {
+ UnlockFile(env->me_lfd, 0, 0, 1, 0);
+ *excl = 0;
+ }
+ }
+#else
+ {
+ struct flock lock_info;
+ /* The shared lock replaces the existing lock */
+ memset((void *)&lock_info, 0, sizeof(lock_info));
+ lock_info.l_type = F_RDLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = 0;
+ lock_info.l_len = 1;
+ while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) &&
+ (rc = ErrCode()) == EINTR) ;
+ *excl = rc ? -1 : 0; /* error may mean we lost the lock */
+ }
+#endif
+
+ return rc;
+}
+
+/** Try to get exclusive lock, otherwise shared.
+ * Maintain *excl = -1: no/unknown lock, 0: shared, 1: exclusive.
+ */
+static int ESECT
+mdb_env_excl_lock(MDB_env *env, int *excl)
+{
+ int rc = 0;
+#ifdef _WIN32
+ if (LockFile(env->me_lfd, 0, 0, 1, 0)) {
+ *excl = 1;
+ } else {
+ OVERLAPPED ov;
+ memset(&ov, 0, sizeof(ov));
+ if (LockFileEx(env->me_lfd, 0, 0, 1, 0, &ov)) {
+ *excl = 0;
+ } else {
+ rc = ErrCode();
+ }
+ }
+#else
+ struct flock lock_info;
+ memset((void *)&lock_info, 0, sizeof(lock_info));
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = 0;
+ lock_info.l_len = 1;
+ while ((rc = fcntl(env->me_lfd, F_SETLK, &lock_info)) &&
+ (rc = ErrCode()) == EINTR) ;
+ if (!rc) {
+ *excl = 1;
+ } else
+# ifndef MDB_USE_POSIX_MUTEX
+ if (*excl < 0) /* always true when MDB_USE_POSIX_MUTEX */
+# endif
+ {
+ lock_info.l_type = F_RDLCK;
+ while ((rc = fcntl(env->me_lfd, F_SETLKW, &lock_info)) &&
+ (rc = ErrCode()) == EINTR) ;
+ if (rc == 0)
+ *excl = 0;
+ }
+#endif
+ return rc;
+}
+
+#ifdef MDB_USE_HASH
+/*
+ * hash_64 - 64 bit Fowler/Noll/Vo-0 FNV-1a hash code
+ *
+ * @(#) $Revision: 5.1 $
+ * @(#) $Id: hash_64a.c,v 5.1 2009/06/30 09:01:38 chongo Exp $
+ * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_64a.c,v $
+ *
+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ ***
+ *
+ * Please do not copyright this code. This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, 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.
+ *
+ * By:
+ * chongo <Landon Curt Noll> /\oo/\
+ * http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy! :-)
+ */
+
+typedef unsigned long long mdb_hash_t;
+#define MDB_HASH_INIT ((mdb_hash_t)0xcbf29ce484222325ULL)
+
+/** perform a 64 bit Fowler/Noll/Vo FNV-1a hash on a buffer
+ * @param[in] val value to hash
+ * @param[in] hval initial value for hash
+ * @return 64 bit hash
+ *
+ * NOTE: To use the recommended 64 bit FNV-1a hash, use MDB_HASH_INIT as the
+ * hval arg on the first call.
+ */
+static mdb_hash_t
+mdb_hash_val(MDB_val *val, mdb_hash_t hval)
+{
+ unsigned char *s = (unsigned char *)val->mv_data; /* unsigned string */
+ unsigned char *end = s + val->mv_size;
+ /*
+ * FNV-1a hash each octet of the string
+ */
+ while (s < end) {
+ /* xor the bottom with the current octet */
+ hval ^= (mdb_hash_t)*s++;
+
+ /* multiply by the 64 bit FNV magic prime mod 2^64 */
+ hval += (hval << 1) + (hval << 4) + (hval << 5) +
+ (hval << 7) + (hval << 8) + (hval << 40);
+ }
+ /* return our new hash value */
+ return hval;
+}
+
+/** Hash the string and output the encoded hash.
+ * This uses modified RFC1924 Ascii85 encoding to accommodate systems with
+ * very short name limits. We don't care about the encoding being reversible,
+ * we just want to preserve as many bits of the input as possible in a
+ * small printable string.
+ * @param[in] str string to hash
+ * @param[out] encbuf an array of 11 chars to hold the hash
+ */
+static const char mdb_a85[]= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
+
+static void ESECT
+mdb_pack85(unsigned long l, char *out)
+{
+ int i;
+
+ for (i=0; i<5; i++) {
+ *out++ = mdb_a85[l % 85];
+ l /= 85;
+ }
+}
+
+static void ESECT
+mdb_hash_enc(MDB_val *val, char *encbuf)
+{
+ mdb_hash_t h = mdb_hash_val(val, MDB_HASH_INIT);
+
+ mdb_pack85(h, encbuf);
+ mdb_pack85(h>>32, encbuf+5);
+ encbuf[10] = '\0';
+}
+#endif
+
+/** Open and/or initialize the lock region for the environment.
+ * @param[in] env The LMDB environment.
+ * @param[in] fname Filename + scratch area, from #mdb_fname_init().
+ * @param[in] mode The Unix permissions for the file, if we create it.
+ * @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive
+ * @return 0 on success, non-zero on failure.
+ */
+static int ESECT
+mdb_env_setup_locks(MDB_env *env, MDB_name *fname, int mode, int *excl)
+{
+#ifdef _WIN32
+# define MDB_ERRCODE_ROFS ERROR_WRITE_PROTECT
+#else
+# define MDB_ERRCODE_ROFS EROFS
+#endif
+ int rc;
+ off_t size, rsize;
+
+ rc = mdb_fopen(env, fname, MDB_O_LOCKS, mode, &env->me_lfd);
+ if (rc) {
+ /* Omit lockfile if read-only env on read-only filesystem */
+ if (rc == MDB_ERRCODE_ROFS && (env->me_flags & MDB_RDONLY)) {
+ return MDB_SUCCESS;
+ }
+ goto fail;
+ }
+
+ if (!(env->me_flags & MDB_NOTLS)) {
+ rc = pthread_key_create(&env->me_txkey, mdb_env_reader_dest);
+ if (rc)
+ goto fail;
+ env->me_flags |= MDB_ENV_TXKEY;
+#ifdef _WIN32
+ /* Windows TLS callbacks need help finding their TLS info. */
+ if (mdb_tls_nkeys >= MAX_TLS_KEYS) {
+ rc = MDB_TLS_FULL;
+ goto fail;
+ }
+ mdb_tls_keys[mdb_tls_nkeys++] = env->me_txkey;
+#endif
+ }
+
+ /* Try to get exclusive lock. If we succeed, then
+ * nobody is using the lock region and we should initialize it.
+ */
+ if ((rc = mdb_env_excl_lock(env, excl))) goto fail;
+
+#ifdef _WIN32
+ size = GetFileSize(env->me_lfd, NULL);
+#else
+ size = lseek(env->me_lfd, 0, SEEK_END);
+ if (size == -1) goto fail_errno;
+#endif
+ rsize = (env->me_maxreaders-1) * sizeof(MDB_reader) + sizeof(MDB_txninfo);
+ if (size < rsize && *excl > 0) {
+#ifdef _WIN32
+ if (SetFilePointer(env->me_lfd, rsize, NULL, FILE_BEGIN) != (DWORD)rsize
+ || !SetEndOfFile(env->me_lfd))
+ goto fail_errno;
+#else
+ if (ftruncate(env->me_lfd, rsize) != 0) goto fail_errno;
+#endif
+ } else {
+ rsize = size;
+ size = rsize - sizeof(MDB_txninfo);
+ env->me_maxreaders = size/sizeof(MDB_reader) + 1;
+ }
+ {
+#ifdef _WIN32
+ HANDLE mh;
+ mh = CreateFileMapping(env->me_lfd, NULL, PAGE_READWRITE,
+ 0, 0, NULL);
+ if (!mh) goto fail_errno;
+ env->me_txns = MapViewOfFileEx(mh, FILE_MAP_WRITE, 0, 0, rsize, NULL);
+ CloseHandle(mh);
+ if (!env->me_txns) goto fail_errno;
+#else
+ void *m = mmap(NULL, rsize, PROT_READ|PROT_WRITE, MAP_SHARED,
+ env->me_lfd, 0);
+ if (m == MAP_FAILED) goto fail_errno;
+ env->me_txns = m;
+#endif
+ }
+ if (*excl > 0) {
+#ifdef _WIN32
+ BY_HANDLE_FILE_INFORMATION stbuf;
+ struct {
+ DWORD volume;
+ DWORD nhigh;
+ DWORD nlow;
+ } idbuf;
+ MDB_val val;
+ char encbuf[11];
+
+ if (!mdb_sec_inited) {
+ InitializeSecurityDescriptor(&mdb_null_sd,
+ SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&mdb_null_sd, TRUE, 0, FALSE);
+ mdb_all_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ mdb_all_sa.bInheritHandle = FALSE;
+ mdb_all_sa.lpSecurityDescriptor = &mdb_null_sd;
+ mdb_sec_inited = 1;
+ }
+ if (!GetFileInformationByHandle(env->me_lfd, &stbuf)) goto fail_errno;
+ idbuf.volume = stbuf.dwVolumeSerialNumber;
+ idbuf.nhigh = stbuf.nFileIndexHigh;
+ idbuf.nlow = stbuf.nFileIndexLow;
+ val.mv_data = &idbuf;
+ val.mv_size = sizeof(idbuf);
+ mdb_hash_enc(&val, encbuf);
+ sprintf(env->me_txns->mti_rmname, "Global\\MDBr%s", encbuf);
+ sprintf(env->me_txns->mti_wmname, "Global\\MDBw%s", encbuf);
+ env->me_rmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_rmname);
+ if (!env->me_rmutex) goto fail_errno;
+ env->me_wmutex = CreateMutexA(&mdb_all_sa, FALSE, env->me_txns->mti_wmname);
+ if (!env->me_wmutex) goto fail_errno;
+#elif defined(MDB_USE_POSIX_SEM)
+ struct stat stbuf;
+ struct {
+ dev_t dev;
+ ino_t ino;
+ } idbuf;
+ MDB_val val;
+ char encbuf[11];
+
+#if defined(__NetBSD__)
+#define MDB_SHORT_SEMNAMES 1 /* limited to 14 chars */
+#endif
+ if (fstat(env->me_lfd, &stbuf)) goto fail_errno;
+ idbuf.dev = stbuf.st_dev;
+ idbuf.ino = stbuf.st_ino;
+ val.mv_data = &idbuf;
+ val.mv_size = sizeof(idbuf);
+ mdb_hash_enc(&val, encbuf);
+#ifdef MDB_SHORT_SEMNAMES
+ encbuf[9] = '\0'; /* drop name from 15 chars to 14 chars */
+#endif
+ sprintf(env->me_txns->mti_rmname, "/MDBr%s", encbuf);
+ sprintf(env->me_txns->mti_wmname, "/MDBw%s", encbuf);
+ /* Clean up after a previous run, if needed: Try to
+ * remove both semaphores before doing anything else.
+ */
+ sem_unlink(env->me_txns->mti_rmname);
+ sem_unlink(env->me_txns->mti_wmname);
+ env->me_rmutex = sem_open(env->me_txns->mti_rmname,
+ O_CREAT|O_EXCL, mode, 1);
+ if (env->me_rmutex == SEM_FAILED) goto fail_errno;
+ env->me_wmutex = sem_open(env->me_txns->mti_wmname,
+ O_CREAT|O_EXCL, mode, 1);
+ if (env->me_wmutex == SEM_FAILED) goto fail_errno;
+#else /* MDB_USE_POSIX_MUTEX: */
+ pthread_mutexattr_t mattr;
+
+ /* Solaris needs this before initing a robust mutex. Otherwise
+ * it may skip the init and return EBUSY "seems someone already
+ * inited" or EINVAL "it was inited differently".
+ */
+ memset(env->me_txns->mti_rmutex, 0, sizeof(*env->me_txns->mti_rmutex));
+ memset(env->me_txns->mti_wmutex, 0, sizeof(*env->me_txns->mti_wmutex));
+
+ if ((rc = pthread_mutexattr_init(&mattr)))
+ goto fail;
+
+ rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
+#ifdef MDB_ROBUST_SUPPORTED
+ if (!rc) rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
+#endif
+ if (!rc) rc = pthread_mutex_init(env->me_txns->mti_rmutex, &mattr);
+ if (!rc) rc = pthread_mutex_init(env->me_txns->mti_wmutex, &mattr);
+ pthread_mutexattr_destroy(&mattr);
+ if (rc)
+ goto fail;
+#endif /* _WIN32 || MDB_USE_POSIX_SEM */
+
+ env->me_txns->mti_magic = MDB_MAGIC;
+ env->me_txns->mti_format = MDB_LOCK_FORMAT;
+ env->me_txns->mti_txnid = 0;
+ env->me_txns->mti_numreaders = 0;
+
+ } else {
+ if (env->me_txns->mti_magic != MDB_MAGIC) {
+ DPUTS("lock region has invalid magic");
+ rc = MDB_INVALID;
+ goto fail;
+ }
+ if (env->me_txns->mti_format != MDB_LOCK_FORMAT) {
+ DPRINTF(("lock region has format+version 0x%x, expected 0x%x",
+ env->me_txns->mti_format, MDB_LOCK_FORMAT));
+ rc = MDB_VERSION_MISMATCH;
+ goto fail;
+ }
+ rc = ErrCode();
+ if (rc && rc != EACCES && rc != EAGAIN) {
+ goto fail;
+ }
+#ifdef _WIN32
+ env->me_rmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_rmname);
+ if (!env->me_rmutex) goto fail_errno;
+ env->me_wmutex = OpenMutexA(SYNCHRONIZE, FALSE, env->me_txns->mti_wmname);
+ if (!env->me_wmutex) goto fail_errno;
+#elif defined(MDB_USE_POSIX_SEM)
+ env->me_rmutex = sem_open(env->me_txns->mti_rmname, 0);
+ if (env->me_rmutex == SEM_FAILED) goto fail_errno;
+ env->me_wmutex = sem_open(env->me_txns->mti_wmname, 0);
+ if (env->me_wmutex == SEM_FAILED) goto fail_errno;
+#endif
+ }
+ return MDB_SUCCESS;
+
+fail_errno:
+ rc = ErrCode();
+fail:
+ return rc;
+}
+
+ /** Only a subset of the @ref mdb_env flags can be changed
+ * at runtime. Changing other flags requires closing the
+ * environment and re-opening it with the new flags.
+ */
+#define CHANGEABLE (MDB_NOSYNC|MDB_NOMETASYNC|MDB_MAPASYNC|MDB_NOMEMINIT)
+#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY| \
+ MDB_WRITEMAP|MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD)
+
+#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
+# error "Persistent DB flags & env flags overlap, but both go in mm_flags"
+#endif
+
+int ESECT
+mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
+{
+ int rc, excl = -1;
+ MDB_name fname;
+
+ if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS)))
+ return EINVAL;
+
+ flags |= env->me_flags;
+
+ rc = mdb_fname_init(path, flags, &fname);
+ if (rc)
+ return rc;
+
+ if (flags & MDB_RDONLY) {
+ /* silently ignore WRITEMAP when we're only getting read access */
+ flags &= ~MDB_WRITEMAP;
+ } else {
+ if (!((env->me_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)) &&
+ (env->me_dirty_list = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2)))))
+ rc = ENOMEM;
+ }
+ env->me_flags = flags |= MDB_ENV_ACTIVE;
+ if (rc)
+ goto leave;
+
+ env->me_path = strdup(path);
+ env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDB_dbx));
+ env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t));
+ env->me_dbiseqs = calloc(env->me_maxdbs, sizeof(unsigned int));
+ if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) {
+ rc = ENOMEM;
+ goto leave;
+ }
+ env->me_dbxs[FREE_DBI].md_cmp = mdb_cmp_long; /* aligned MDB_INTEGERKEY */
+
+ /* For RDONLY, get lockfile after we know datafile exists */
+ if (!(flags & (MDB_RDONLY|MDB_NOLOCK))) {
+ rc = mdb_env_setup_locks(env, &fname, mode, &excl);
+ if (rc)
+ goto leave;
+ }
+
+ rc = mdb_fopen(env, &fname,
+ (flags & MDB_RDONLY) ? MDB_O_RDONLY : MDB_O_RDWR,
+ mode, &env->me_fd);
+ if (rc)
+ goto leave;
+
+ if ((flags & (MDB_RDONLY|MDB_NOLOCK)) == MDB_RDONLY) {
+ rc = mdb_env_setup_locks(env, &fname, mode, &excl);
+ if (rc)
+ goto leave;
+ }
+
+ if ((rc = mdb_env_open2(env)) == MDB_SUCCESS) {
+ if (!(flags & (MDB_RDONLY|MDB_WRITEMAP))) {
+ /* Synchronous fd for meta writes. Needed even with
+ * MDB_NOSYNC/MDB_NOMETASYNC, in case these get reset.
+ */
+ rc = mdb_fopen(env, &fname, MDB_O_META, mode, &env->me_mfd);
+ if (rc)
+ goto leave;
+ }
+ DPRINTF(("opened dbenv %p", (void *) env));
+ if (excl > 0) {
+ rc = mdb_env_share_locks(env, &excl);
+ if (rc)
+ goto leave;
+ }
+ if (!(flags & MDB_RDONLY)) {
+ MDB_txn *txn;
+ int tsize = sizeof(MDB_txn), size = tsize + env->me_maxdbs *
+ (sizeof(MDB_db)+sizeof(MDB_cursor *)+sizeof(unsigned int)+1);
+ if ((env->me_pbuf = calloc(1, env->me_psize)) &&
+ (txn = calloc(1, size)))
+ {
+ txn->mt_dbs = (MDB_db *)((char *)txn + tsize);
+ txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + env->me_maxdbs);
+ txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs);
+ txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs);
+ txn->mt_env = env;
+ txn->mt_dbxs = env->me_dbxs;
+ txn->mt_flags = MDB_TXN_FINISHED;
+ env->me_txn0 = txn;
+ } else {
+ rc = ENOMEM;
+ }
+ }
+ }
+
+leave:
+ if (rc) {
+ mdb_env_close0(env, excl);
+ }
+ mdb_fname_destroy(fname);
+ return rc;
+}
+
+/** Destroy resources from mdb_env_open(), clear our readers & DBIs */
+static void ESECT
+mdb_env_close0(MDB_env *env, int excl)
+{
+ int i;
+
+ if (!(env->me_flags & MDB_ENV_ACTIVE))
+ return;
+
+ /* Doing this here since me_dbxs may not exist during mdb_env_close */
+ if (env->me_dbxs) {
+ for (i = env->me_maxdbs; --i >= CORE_DBS; )
+ free(env->me_dbxs[i].md_name.mv_data);
+ free(env->me_dbxs);
+ }
+
+ free(env->me_pbuf);
+ free(env->me_dbiseqs);
+ free(env->me_dbflags);
+ free(env->me_path);
+ free(env->me_dirty_list);
+ free(env->me_txn0);
+ mdb_midl_free(env->me_free_pgs);
+
+ if (env->me_flags & MDB_ENV_TXKEY) {
+ pthread_key_delete(env->me_txkey);
+#ifdef _WIN32
+ /* Delete our key from the global list */
+ for (i=0; i<mdb_tls_nkeys; i++)
+ if (mdb_tls_keys[i] == env->me_txkey) {
+ mdb_tls_keys[i] = mdb_tls_keys[mdb_tls_nkeys-1];
+ mdb_tls_nkeys--;
+ break;
+ }
+#endif
+ }
+
+ if (env->me_map) {
+ munmap(env->me_map, env->me_mapsize);
+ }
+ if (env->me_mfd != INVALID_HANDLE_VALUE)
+ (void) close(env->me_mfd);
+ if (env->me_fd != INVALID_HANDLE_VALUE)
+ (void) close(env->me_fd);
+ if (env->me_txns) {
+ MDB_PID_T pid = env->me_pid;
+ /* Clearing readers is done in this function because
+ * me_txkey with its destructor must be disabled first.
+ *
+ * We skip the the reader mutex, so we touch only
+ * data owned by this process (me_close_readers and
+ * our readers), and clear each reader atomically.
+ */
+ for (i = env->me_close_readers; --i >= 0; )
+ if (env->me_txns->mti_readers[i].mr_pid == pid)
+ env->me_txns->mti_readers[i].mr_pid = 0;
+#ifdef _WIN32
+ if (env->me_rmutex) {
+ CloseHandle(env->me_rmutex);
+ if (env->me_wmutex) CloseHandle(env->me_wmutex);
+ }
+ /* Windows automatically destroys the mutexes when
+ * the last handle closes.
+ */
+#elif defined(MDB_USE_POSIX_SEM)
+ if (env->me_rmutex != SEM_FAILED) {
+ sem_close(env->me_rmutex);
+ if (env->me_wmutex != SEM_FAILED)
+ sem_close(env->me_wmutex);
+ /* If we have the filelock: If we are the
+ * only remaining user, clean up semaphores.
+ */
+ if (excl == 0)
+ mdb_env_excl_lock(env, &excl);
+ if (excl > 0) {
+ sem_unlink(env->me_txns->mti_rmname);
+ sem_unlink(env->me_txns->mti_wmname);
+ }
+ }
+#endif
+ munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo));
+ }
+ if (env->me_lfd != INVALID_HANDLE_VALUE) {
+#ifdef _WIN32
+ if (excl >= 0) {
+ /* Unlock the lockfile. Windows would have unlocked it
+ * after closing anyway, but not necessarily at once.
+ */
+ UnlockFile(env->me_lfd, 0, 0, 1, 0);
+ }
+#endif
+ (void) close(env->me_lfd);
+ }
+
+ env->me_flags &= ~(MDB_ENV_ACTIVE|MDB_ENV_TXKEY);
+}
+
+void ESECT
+mdb_env_close(MDB_env *env)
+{
+ MDB_page *dp;
+
+ if (env == NULL)
+ return;
+
+ VGMEMP_DESTROY(env);
+ while ((dp = env->me_dpages) != NULL) {
+ VGMEMP_DEFINED(&dp->mp_next, sizeof(dp->mp_next));
+ env->me_dpages = dp->mp_next;
+ free(dp);
+ }
+
+ mdb_env_close0(env, 0);
+ free(env);
+}
+
+/** Compare two items pointing at aligned size_t's */
+static int
+mdb_cmp_long(const MDB_val *a, const MDB_val *b)
+{
+ return (*(size_t *)a->mv_data < *(size_t *)b->mv_data) ? -1 :
+ *(size_t *)a->mv_data > *(size_t *)b->mv_data;
+}
+
+/** Compare two items pointing at aligned unsigned int's.
+ *
+ * This is also set as #MDB_INTEGERDUP|#MDB_DUPFIXED's #MDB_dbx.%md_dcmp,
+ * but #mdb_cmp_clong() is called instead if the data type is size_t.
+ */
+static int
+mdb_cmp_int(const MDB_val *a, const MDB_val *b)
+{
+ return (*(unsigned int *)a->mv_data < *(unsigned int *)b->mv_data) ? -1 :
+ *(unsigned int *)a->mv_data > *(unsigned int *)b->mv_data;
+}
+
+/** Compare two items pointing at unsigned ints of unknown alignment.
+ * Nodes and keys are guaranteed to be 2-byte aligned.
+ */
+static int
+mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ unsigned short *u, *c;
+ int x;
+
+ u = (unsigned short *) ((char *) a->mv_data + a->mv_size);
+ c = (unsigned short *) ((char *) b->mv_data + a->mv_size);
+ do {
+ x = *--u - *--c;
+ } while(!x && u > (unsigned short *)a->mv_data);
+ return x;
+#else
+ unsigned short *u, *c, *end;
+ int x;
+
+ end = (unsigned short *) ((char *) a->mv_data + a->mv_size);
+ u = (unsigned short *)a->mv_data;
+ c = (unsigned short *)b->mv_data;
+ do {
+ x = *u++ - *c++;
+ } while(!x && u < end);
+ return x;
+#endif
+}
+
+/** Compare two items lexically */
+static int
+mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
+{
+ int diff;
+ ssize_t len_diff;
+ unsigned int len;
+
+ len = a->mv_size;
+ len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+ if (len_diff > 0) {
+ len = b->mv_size;
+ len_diff = 1;
+ }
+
+ diff = memcmp(a->mv_data, b->mv_data, len);
+ return diff ? diff : len_diff<0 ? -1 : len_diff;
+}
+
+/** Compare two items in reverse byte order */
+static int
+mdb_cmp_memnr(const MDB_val *a, const MDB_val *b)
+{
+ const unsigned char *p1, *p2, *p1_lim;
+ ssize_t len_diff;
+ int diff;
+
+ p1_lim = (const unsigned char *)a->mv_data;
+ p1 = (const unsigned char *)a->mv_data + a->mv_size;
+ p2 = (const unsigned char *)b->mv_data + b->mv_size;
+
+ len_diff = (ssize_t) a->mv_size - (ssize_t) b->mv_size;
+ if (len_diff > 0) {
+ p1_lim += len_diff;
+ len_diff = 1;
+ }
+
+ while (p1 > p1_lim) {
+ diff = *--p1 - *--p2;
+ if (diff)
+ return diff;
+ }
+ return len_diff<0 ? -1 : len_diff;
+}
+
+/** Search for key within a page, using binary search.
+ * Returns the smallest entry larger or equal to the key.
+ * If exactp is non-null, stores whether the found entry was an exact match
+ * in *exactp (1 or 0).
+ * Updates the cursor index with the index of the found entry.
+ * If no entry larger or equal to the key is found, returns NULL.
+ */
+static MDB_node *
+mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp)
+{
+ unsigned int i = 0, nkeys;
+ int low, high;
+ int rc = 0;
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ MDB_node *node = NULL;
+ MDB_val nodekey;
+ MDB_cmp_func *cmp;
+ DKBUF;
+
+ nkeys = NUMKEYS(mp);
+
+ DPRINTF(("searching %u keys in %s %spage %"Z"u",
+ nkeys, IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
+ mdb_dbg_pgno(mp)));
+
+ low = IS_LEAF(mp) ? 0 : 1;
+ high = nkeys - 1;
+ cmp = mc->mc_dbx->md_cmp;
+
+ /* Branch pages have no data, so if using integer keys,
+ * alignment is guaranteed. Use faster mdb_cmp_int.
+ */
+ if (cmp == mdb_cmp_cint && IS_BRANCH(mp)) {
+ if (NODEPTR(mp, 1)->mn_ksize == sizeof(size_t))
+ cmp = mdb_cmp_long;
+ else
+ cmp = mdb_cmp_int;
+ }
+
+ if (IS_LEAF2(mp)) {
+ nodekey.mv_size = mc->mc_db->md_pad;
+ node = NODEPTR(mp, 0); /* fake */
+ while (low <= high) {
+ i = (low + high) >> 1;
+ nodekey.mv_data = LEAF2KEY(mp, i, nodekey.mv_size);
+ rc = cmp(key, &nodekey);
+ DPRINTF(("found leaf index %u [%s], rc = %i",
+ i, DKEY(&nodekey), rc));
+ if (rc == 0)
+ break;
+ if (rc > 0)
+ low = i + 1;
+ else
+ high = i - 1;
+ }
+ } else {
+ while (low <= high) {
+ i = (low + high) >> 1;
+
+ node = NODEPTR(mp, i);
+ nodekey.mv_size = NODEKSZ(node);
+ nodekey.mv_data = NODEKEY(node);
+
+ rc = cmp(key, &nodekey);
+#if MDB_DEBUG
+ if (IS_LEAF(mp))
+ DPRINTF(("found leaf index %u [%s], rc = %i",
+ i, DKEY(&nodekey), rc));
+ else
+ DPRINTF(("found branch index %u [%s -> %"Z"u], rc = %i",
+ i, DKEY(&nodekey), NODEPGNO(node), rc));
+#endif
+ if (rc == 0)
+ break;
+ if (rc > 0)
+ low = i + 1;
+ else
+ high = i - 1;
+ }
+ }
+
+ if (rc > 0) { /* Found entry is less than the key. */
+ i++; /* Skip to get the smallest entry larger than key. */
+ if (!IS_LEAF2(mp))
+ node = NODEPTR(mp, i);
+ }
+ if (exactp)
+ *exactp = (rc == 0 && nkeys > 0);
+ /* store the key index */
+ mc->mc_ki[mc->mc_top] = i;
+ if (i >= nkeys)
+ /* There is no entry larger or equal to the key. */
+ return NULL;
+
+ /* nodeptr is fake for LEAF2 */
+ return node;
+}
+
+#if 0
+static void
+mdb_cursor_adjust(MDB_cursor *mc, func)
+{
+ MDB_cursor *m2;
+
+ for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
+ if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) {
+ func(mc, m2);
+ }
+ }
+}
+#endif
+
+/** Pop a page off the top of the cursor's stack. */
+static void
+mdb_cursor_pop(MDB_cursor *mc)
+{
+ if (mc->mc_snum) {
+ DPRINTF(("popping page %"Z"u off db %d cursor %p",
+ mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *) mc));
+
+ mc->mc_snum--;
+ if (mc->mc_snum) {
+ mc->mc_top--;
+ } else {
+ mc->mc_flags &= ~C_INITIALIZED;
+ }
+ }
+}
+
+/** Push a page onto the top of the cursor's stack.
+ * Set #MDB_TXN_ERROR on failure.
+ */
+static int
+mdb_cursor_push(MDB_cursor *mc, MDB_page *mp)
+{
+ DPRINTF(("pushing page %"Z"u on db %d cursor %p", mp->mp_pgno,
+ DDBI(mc), (void *) mc));
+
+ if (mc->mc_snum >= CURSOR_STACK) {
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_CURSOR_FULL;
+ }
+
+ mc->mc_top = mc->mc_snum++;
+ mc->mc_pg[mc->mc_top] = mp;
+ mc->mc_ki[mc->mc_top] = 0;
+
+ return MDB_SUCCESS;
+}
+
+/** Find the address of the page corresponding to a given page number.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in] mc the cursor accessing the page.
+ * @param[in] pgno the page number for the page to retrieve.
+ * @param[out] ret address of a pointer where the page's address will be stored.
+ * @param[out] lvl dirty_list inheritance level of found page. 1=current txn, 0=mapped page.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_get(MDB_cursor *mc, pgno_t pgno, MDB_page **ret, int *lvl)
+{
+ MDB_txn *txn = mc->mc_txn;
+ MDB_env *env = txn->mt_env;
+ MDB_page *p = NULL;
+ int level;
+
+ if (! (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_WRITEMAP))) {
+ MDB_txn *tx2 = txn;
+ level = 1;
+ do {
+ MDB_ID2L dl = tx2->mt_u.dirty_list;
+ unsigned x;
+ /* Spilled pages were dirtied in this txn and flushed
+ * because the dirty list got full. Bring this page
+ * back in from the map (but don't unspill it here,
+ * leave that unless page_touch happens again).
+ */
+ if (tx2->mt_spill_pgs) {
+ MDB_ID pn = pgno << 1;
+ x = mdb_midl_search(tx2->mt_spill_pgs, pn);
+ if (x <= tx2->mt_spill_pgs[0] && tx2->mt_spill_pgs[x] == pn) {
+ p = (MDB_page *)(env->me_map + env->me_psize * pgno);
+ goto done;
+ }
+ }
+ if (dl[0].mid) {
+ unsigned x = mdb_mid2l_search(dl, pgno);
+ if (x <= dl[0].mid && dl[x].mid == pgno) {
+ p = dl[x].mptr;
+ goto done;
+ }
+ }
+ level++;
+ } while ((tx2 = tx2->mt_parent) != NULL);
+ }
+
+ if (pgno < txn->mt_next_pgno) {
+ level = 0;
+ p = (MDB_page *)(env->me_map + env->me_psize * pgno);
+ } else {
+ DPRINTF(("page %"Z"u not found", pgno));
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_PAGE_NOTFOUND;
+ }
+
+done:
+ *ret = p;
+ if (lvl)
+ *lvl = level;
+ return MDB_SUCCESS;
+}
+
+/** Finish #mdb_page_search() / #mdb_page_search_lowest().
+ * The cursor is at the root page, set up the rest of it.
+ */
+static int
+mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags)
+{
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ int rc;
+ DKBUF;
+
+ while (IS_BRANCH(mp)) {
+ MDB_node *node;
+ indx_t i;
+
+ DPRINTF(("branch page %"Z"u has %u keys", mp->mp_pgno, NUMKEYS(mp)));
+ /* Don't assert on branch pages in the FreeDB. We can get here
+ * while in the process of rebalancing a FreeDB branch page; we must
+ * let that proceed. ITS#8336
+ */
+ mdb_cassert(mc, !mc->mc_dbi || NUMKEYS(mp) > 1);
+ DPRINTF(("found index 0 to page %"Z"u", NODEPGNO(NODEPTR(mp, 0))));
+
+ if (flags & (MDB_PS_FIRST|MDB_PS_LAST)) {
+ i = 0;
+ if (flags & MDB_PS_LAST) {
+ i = NUMKEYS(mp) - 1;
+ /* if already init'd, see if we're already in right place */
+ if (mc->mc_flags & C_INITIALIZED) {
+ if (mc->mc_ki[mc->mc_top] == i) {
+ mc->mc_top = mc->mc_snum++;
+ mp = mc->mc_pg[mc->mc_top];
+ goto ready;
+ }
+ }
+ }
+ } else {
+ int exact;
+ node = mdb_node_search(mc, key, &exact);
+ if (node == NULL)
+ i = NUMKEYS(mp) - 1;
+ else {
+ i = mc->mc_ki[mc->mc_top];
+ if (!exact) {
+ mdb_cassert(mc, i > 0);
+ i--;
+ }
+ }
+ DPRINTF(("following index %u for key [%s]", i, DKEY(key)));
+ }
+
+ mdb_cassert(mc, i < NUMKEYS(mp));
+ node = NODEPTR(mp, i);
+
+ if ((rc = mdb_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0)
+ return rc;
+
+ mc->mc_ki[mc->mc_top] = i;
+ if ((rc = mdb_cursor_push(mc, mp)))
+ return rc;
+
+ready:
+ if (flags & MDB_PS_MODIFY) {
+ if ((rc = mdb_page_touch(mc)) != 0)
+ return rc;
+ mp = mc->mc_pg[mc->mc_top];
+ }
+ }
+
+ if (!IS_LEAF(mp)) {
+ DPRINTF(("internal error, index points to a %02X page!?",
+ mp->mp_flags));
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_CORRUPTED;
+ }
+
+ DPRINTF(("found leaf page %"Z"u for key [%s]", mp->mp_pgno,
+ key ? DKEY(key) : "null"));
+ mc->mc_flags |= C_INITIALIZED;
+ mc->mc_flags &= ~C_EOF;
+
+ return MDB_SUCCESS;
+}
+
+/** Search for the lowest key under the current branch page.
+ * This just bypasses a NUMKEYS check in the current page
+ * before calling mdb_page_search_root(), because the callers
+ * are all in situations where the current page is known to
+ * be underfilled.
+ */
+static int
+mdb_page_search_lowest(MDB_cursor *mc)
+{
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ MDB_node *node = NODEPTR(mp, 0);
+ int rc;
+
+ if ((rc = mdb_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0)
+ return rc;
+
+ mc->mc_ki[mc->mc_top] = 0;
+ if ((rc = mdb_cursor_push(mc, mp)))
+ return rc;
+ return mdb_page_search_root(mc, NULL, MDB_PS_FIRST);
+}
+
+/** Search for the page a given key should be in.
+ * Push it and its parent pages on the cursor stack.
+ * @param[in,out] mc the cursor for this operation.
+ * @param[in] key the key to search for, or NULL for first/last page.
+ * @param[in] flags If MDB_PS_MODIFY is set, visited pages in the DB
+ * are touched (updated with new page numbers).
+ * If MDB_PS_FIRST or MDB_PS_LAST is set, find first or last leaf.
+ * This is used by #mdb_cursor_first() and #mdb_cursor_last().
+ * If MDB_PS_ROOTONLY set, just fetch root node, no further lookups.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
+{
+ int rc;
+ pgno_t root;
+
+ /* Make sure the txn is still viable, then find the root from
+ * the txn's db table and set it as the root of the cursor's stack.
+ */
+ if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED) {
+ DPUTS("transaction may not be used now");
+ return MDB_BAD_TXN;
+ } else {
+ /* Make sure we're using an up-to-date root */
+ if (*mc->mc_dbflag & DB_STALE) {
+ MDB_cursor mc2;
+ if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))
+ return MDB_BAD_DBI;
+ mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL);
+ rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, 0);
+ if (rc)
+ return rc;
+ {
+ MDB_val data;
+ int exact = 0;
+ uint16_t flags;
+ MDB_node *leaf = mdb_node_search(&mc2,
+ &mc->mc_dbx->md_name, &exact);
+ if (!exact)
+ return MDB_NOTFOUND;
+ if ((leaf->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA)
+ return MDB_INCOMPATIBLE; /* not a named DB */
+ rc = mdb_node_read(&mc2, leaf, &data);
+ if (rc)
+ return rc;
+ memcpy(&flags, ((char *) data.mv_data + offsetof(MDB_db, md_flags)),
+ sizeof(uint16_t));
+ /* The txn may not know this DBI, or another process may
+ * have dropped and recreated the DB with other flags.
+ */
+ if ((mc->mc_db->md_flags & PERSISTENT_FLAGS) != flags)
+ return MDB_INCOMPATIBLE;
+ memcpy(mc->mc_db, data.mv_data, sizeof(MDB_db));
+ }
+ *mc->mc_dbflag &= ~DB_STALE;
+ }
+ root = mc->mc_db->md_root;
+
+ if (root == P_INVALID) { /* Tree is empty. */
+ DPUTS("tree is empty");
+ return MDB_NOTFOUND;
+ }
+ }
+
+ mdb_cassert(mc, root > 1);
+ if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root)
+ if ((rc = mdb_page_get(mc, root, &mc->mc_pg[0], NULL)) != 0)
+ return rc;
+
+ mc->mc_snum = 1;
+ mc->mc_top = 0;
+
+ DPRINTF(("db %d root page %"Z"u has flags 0x%X",
+ DDBI(mc), root, mc->mc_pg[0]->mp_flags));
+
+ if (flags & MDB_PS_MODIFY) {
+ if ((rc = mdb_page_touch(mc)))
+ return rc;
+ }
+
+ if (flags & MDB_PS_ROOTONLY)
+ return MDB_SUCCESS;
+
+ return mdb_page_search_root(mc, key, flags);
+}
+
+static int
+mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
+{
+ MDB_txn *txn = mc->mc_txn;
+ pgno_t pg = mp->mp_pgno;
+ unsigned x = 0, ovpages = mp->mp_pages;
+ MDB_env *env = txn->mt_env;
+ MDB_IDL sl = txn->mt_spill_pgs;
+ MDB_ID pn = pg << 1;
+ int rc;
+
+ DPRINTF(("free ov page %"Z"u (%d)", pg, ovpages));
+ /* If the page is dirty or on the spill list we just acquired it,
+ * so we should give it back to our current free list, if any.
+ * Otherwise put it onto the list of pages we freed in this txn.
+ *
+ * Won't create me_pghead: me_pglast must be inited along with it.
+ * Unsupported in nested txns: They would need to hide the page
+ * range in ancestor txns' dirty and spilled lists.
+ */
+ if (env->me_pghead &&
+ !txn->mt_parent &&
+ ((mp->mp_flags & P_DIRTY) ||
+ (sl && (x = mdb_midl_search(sl, pn)) <= sl[0] && sl[x] == pn)))
+ {
+ unsigned i, j;
+ pgno_t *mop;
+ MDB_ID2 *dl, ix, iy;
+ rc = mdb_midl_need(&env->me_pghead, ovpages);
+ if (rc)
+ return rc;
+ if (!(mp->mp_flags & P_DIRTY)) {
+ /* This page is no longer spilled */
+ if (x == sl[0])
+ sl[0]--;
+ else
+ sl[x] |= 1;
+ goto release;
+ }
+ /* Remove from dirty list */
+ dl = txn->mt_u.dirty_list;
+ x = dl[0].mid--;
+ for (ix = dl[x]; ix.mptr != mp; ix = iy) {
+ if (x > 1) {
+ x--;
+ iy = dl[x];
+ dl[x] = ix;
+ } else {
+ mdb_cassert(mc, x > 1);
+ j = ++(dl[0].mid);
+ dl[j] = ix; /* Unsorted. OK when MDB_TXN_ERROR. */
+ txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_CORRUPTED;
+ }
+ }
+ txn->mt_dirty_room++;
+ if (!(env->me_flags & MDB_WRITEMAP))
+ mdb_dpage_free(env, mp);
+release:
+ /* Insert in me_pghead */
+ mop = env->me_pghead;
+ j = mop[0] + ovpages;
+ for (i = mop[0]; i && mop[i] < pg; i--)
+ mop[j--] = mop[i];
+ while (j>i)
+ mop[j--] = pg++;
+ mop[0] += ovpages;
+ } else {
+ rc = mdb_midl_append_range(&txn->mt_free_pgs, pg, ovpages);
+ if (rc)
+ return rc;
+ }
+ mc->mc_db->md_overflow_pages -= ovpages;
+ return 0;
+}
+
+/** Return the data associated with a given node.
+ * @param[in] mc The cursor for this operation.
+ * @param[in] leaf The node being read.
+ * @param[out] data Updated to point to the node's data.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_node_read(MDB_cursor *mc, MDB_node *leaf, MDB_val *data)
+{
+ MDB_page *omp; /* overflow page */
+ pgno_t pgno;
+ int rc;
+
+ if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) {
+ data->mv_size = NODEDSZ(leaf);
+ data->mv_data = NODEDATA(leaf);
+ return MDB_SUCCESS;
+ }
+
+ /* Read overflow data.
+ */
+ data->mv_size = NODEDSZ(leaf);
+ memcpy(&pgno, NODEDATA(leaf), sizeof(pgno));
+ if ((rc = mdb_page_get(mc, pgno, &omp, NULL)) != 0) {
+ DPRINTF(("read overflow page %"Z"u failed", pgno));
+ return rc;
+ }
+ data->mv_data = METADATA(omp);
+
+ return MDB_SUCCESS;
+}
+
+int
+mdb_get(MDB_txn *txn, MDB_dbi dbi,
+ MDB_val *key, MDB_val *data)
+{
+ MDB_cursor mc;
+ MDB_xcursor mx;
+ int exact = 0;
+ DKBUF;
+
+ DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key)));
+
+ if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ if (txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ mdb_cursor_init(&mc, txn, dbi, &mx);
+ return mdb_cursor_set(&mc, key, data, MDB_SET, &exact);
+}
+
+/** Find a sibling for a page.
+ * Replaces the page at the top of the cursor's stack with the
+ * specified sibling, if one exists.
+ * @param[in] mc The cursor for this operation.
+ * @param[in] move_right Non-zero if the right sibling is requested,
+ * otherwise the left sibling.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_cursor_sibling(MDB_cursor *mc, int move_right)
+{
+ int rc;
+ MDB_node *indx;
+ MDB_page *mp;
+
+ if (mc->mc_snum < 2) {
+ return MDB_NOTFOUND; /* root has no siblings */
+ }
+
+ mdb_cursor_pop(mc);
+ DPRINTF(("parent page is page %"Z"u, index %u",
+ mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top]));
+
+ if (move_right ? (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mc->mc_pg[mc->mc_top]))
+ : (mc->mc_ki[mc->mc_top] == 0)) {
+ DPRINTF(("no more keys left, moving to %s sibling",
+ move_right ? "right" : "left"));
+ if ((rc = mdb_cursor_sibling(mc, move_right)) != MDB_SUCCESS) {
+ /* undo cursor_pop before returning */
+ mc->mc_top++;
+ mc->mc_snum++;
+ return rc;
+ }
+ } else {
+ if (move_right)
+ mc->mc_ki[mc->mc_top]++;
+ else
+ mc->mc_ki[mc->mc_top]--;
+ DPRINTF(("just moving to %s index key %u",
+ move_right ? "right" : "left", mc->mc_ki[mc->mc_top]));
+ }
+ mdb_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top]));
+
+ indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if ((rc = mdb_page_get(mc, NODEPGNO(indx), &mp, NULL)) != 0) {
+ /* mc will be inconsistent if caller does mc_snum++ as above */
+ mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
+ return rc;
+ }
+
+ mdb_cursor_push(mc, mp);
+ if (!move_right)
+ mc->mc_ki[mc->mc_top] = NUMKEYS(mp)-1;
+
+ return MDB_SUCCESS;
+}
+
+/** Move the cursor to the next data item. */
+static int
+mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
+{
+ MDB_page *mp;
+ MDB_node *leaf;
+ int rc;
+
+ if ((mc->mc_flags & C_DEL && op == MDB_NEXT_DUP))
+ return MDB_NOTFOUND;
+
+ if (!(mc->mc_flags & C_INITIALIZED))
+ return mdb_cursor_first(mc, key, data);
+
+ mp = mc->mc_pg[mc->mc_top];
+
+ if (mc->mc_flags & C_EOF) {
+ if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mp)-1)
+ return MDB_NOTFOUND;
+ mc->mc_flags ^= C_EOF;
+ }
+
+ if (mc->mc_db->md_flags & MDB_DUPSORT) {
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ if (op == MDB_NEXT || op == MDB_NEXT_DUP) {
+ rc = mdb_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_NEXT);
+ if (op != MDB_NEXT || rc != MDB_NOTFOUND) {
+ if (rc == MDB_SUCCESS)
+ MDB_GET_KEY(leaf, key);
+ return rc;
+ }
+ }
+ } else {
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+ if (op == MDB_NEXT_DUP)
+ return MDB_NOTFOUND;
+ }
+ }
+
+ DPRINTF(("cursor_next: top page is %"Z"u in cursor %p",
+ mdb_dbg_pgno(mp), (void *) mc));
+ if (mc->mc_flags & C_DEL) {
+ mc->mc_flags ^= C_DEL;
+ goto skip;
+ }
+
+ if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) {
+ DPUTS("=====> move to next sibling page");
+ if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) {
+ mc->mc_flags |= C_EOF;
+ return rc;
+ }
+ mp = mc->mc_pg[mc->mc_top];
+ DPRINTF(("next page is %"Z"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top]));
+ } else
+ mc->mc_ki[mc->mc_top]++;
+
+skip:
+ DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
+ mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
+
+ if (IS_LEAF2(mp)) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size);
+ return MDB_SUCCESS;
+ }
+
+ mdb_cassert(mc, IS_LEAF(mp));
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ mdb_xcursor_init1(mc, leaf);
+ }
+ if (data) {
+ if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS)
+ return rc;
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ }
+
+ MDB_GET_KEY(leaf, key);
+ return MDB_SUCCESS;
+}
+
+/** Move the cursor to the previous data item. */
+static int
+mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
+{
+ MDB_page *mp;
+ MDB_node *leaf;
+ int rc;
+
+ if (!(mc->mc_flags & C_INITIALIZED)) {
+ rc = mdb_cursor_last(mc, key, data);
+ if (rc)
+ return rc;
+ mc->mc_ki[mc->mc_top]++;
+ }
+
+ mp = mc->mc_pg[mc->mc_top];
+
+ if (mc->mc_db->md_flags & MDB_DUPSORT) {
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ if (op == MDB_PREV || op == MDB_PREV_DUP) {
+ rc = mdb_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_PREV);
+ if (op != MDB_PREV || rc != MDB_NOTFOUND) {
+ if (rc == MDB_SUCCESS) {
+ MDB_GET_KEY(leaf, key);
+ mc->mc_flags &= ~C_EOF;
+ }
+ return rc;
+ }
+ }
+ } else {
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+ if (op == MDB_PREV_DUP)
+ return MDB_NOTFOUND;
+ }
+ }
+
+ DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p",
+ mdb_dbg_pgno(mp), (void *) mc));
+
+ mc->mc_flags &= ~(C_EOF|C_DEL);
+
+ if (mc->mc_ki[mc->mc_top] == 0) {
+ DPUTS("=====> move to prev sibling page");
+ if ((rc = mdb_cursor_sibling(mc, 0)) != MDB_SUCCESS) {
+ return rc;
+ }
+ mp = mc->mc_pg[mc->mc_top];
+ mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1;
+ DPRINTF(("prev page is %"Z"u, key index %u", mp->mp_pgno, mc->mc_ki[mc->mc_top]));
+ } else
+ mc->mc_ki[mc->mc_top]--;
+
+ DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
+ mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
+
+ if (IS_LEAF2(mp)) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size);
+ return MDB_SUCCESS;
+ }
+
+ mdb_cassert(mc, IS_LEAF(mp));
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ mdb_xcursor_init1(mc, leaf);
+ }
+ if (data) {
+ if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS)
+ return rc;
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ }
+
+ MDB_GET_KEY(leaf, key);
+ return MDB_SUCCESS;
+}
+
+/** Set the cursor on a specific data item. */
+static int
+mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
+ MDB_cursor_op op, int *exactp)
+{
+ int rc;
+ MDB_page *mp;
+ MDB_node *leaf = NULL;
+ DKBUF;
+
+ if (key->mv_size == 0)
+ return MDB_BAD_VALSIZE;
+
+ if (mc->mc_xcursor)
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+
+ /* See if we're already on the right page */
+ if (mc->mc_flags & C_INITIALIZED) {
+ MDB_val nodekey;
+
+ mp = mc->mc_pg[mc->mc_top];
+ if (!NUMKEYS(mp)) {
+ mc->mc_ki[mc->mc_top] = 0;
+ return MDB_NOTFOUND;
+ }
+ if (mp->mp_flags & P_LEAF2) {
+ nodekey.mv_size = mc->mc_db->md_pad;
+ nodekey.mv_data = LEAF2KEY(mp, 0, nodekey.mv_size);
+ } else {
+ leaf = NODEPTR(mp, 0);
+ MDB_GET_KEY2(leaf, nodekey);
+ }
+ rc = mc->mc_dbx->md_cmp(key, &nodekey);
+ if (rc == 0) {
+ /* Probably happens rarely, but first node on the page
+ * was the one we wanted.
+ */
+ mc->mc_ki[mc->mc_top] = 0;
+ if (exactp)
+ *exactp = 1;
+ goto set1;
+ }
+ if (rc > 0) {
+ unsigned int i;
+ unsigned int nkeys = NUMKEYS(mp);
+ if (nkeys > 1) {
+ if (mp->mp_flags & P_LEAF2) {
+ nodekey.mv_data = LEAF2KEY(mp,
+ nkeys-1, nodekey.mv_size);
+ } else {
+ leaf = NODEPTR(mp, nkeys-1);
+ MDB_GET_KEY2(leaf, nodekey);
+ }
+ rc = mc->mc_dbx->md_cmp(key, &nodekey);
+ if (rc == 0) {
+ /* last node was the one we wanted */
+ mc->mc_ki[mc->mc_top] = nkeys-1;
+ if (exactp)
+ *exactp = 1;
+ goto set1;
+ }
+ if (rc < 0) {
+ if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) {
+ /* This is definitely the right page, skip search_page */
+ if (mp->mp_flags & P_LEAF2) {
+ nodekey.mv_data = LEAF2KEY(mp,
+ mc->mc_ki[mc->mc_top], nodekey.mv_size);
+ } else {
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+ MDB_GET_KEY2(leaf, nodekey);
+ }
+ rc = mc->mc_dbx->md_cmp(key, &nodekey);
+ if (rc == 0) {
+ /* current node was the one we wanted */
+ if (exactp)
+ *exactp = 1;
+ goto set1;
+ }
+ }
+ rc = 0;
+ mc->mc_flags &= ~C_EOF;
+ goto set2;
+ }
+ }
+ /* If any parents have right-sibs, search.
+ * Otherwise, there's nothing further.
+ */
+ for (i=0; i<mc->mc_top; i++)
+ if (mc->mc_ki[i] <
+ NUMKEYS(mc->mc_pg[i])-1)
+ break;
+ if (i == mc->mc_top) {
+ /* There are no other pages */
+ mc->mc_ki[mc->mc_top] = nkeys;
+ return MDB_NOTFOUND;
+ }
+ }
+ if (!mc->mc_top) {
+ /* There are no other pages */
+ mc->mc_ki[mc->mc_top] = 0;
+ if (op == MDB_SET_RANGE && !exactp) {
+ rc = 0;
+ goto set1;
+ } else
+ return MDB_NOTFOUND;
+ }
+ } else {
+ mc->mc_pg[0] = 0;
+ }
+
+ rc = mdb_page_search(mc, key, 0);
+ if (rc != MDB_SUCCESS)
+ return rc;
+
+ mp = mc->mc_pg[mc->mc_top];
+ mdb_cassert(mc, IS_LEAF(mp));
+
+set2:
+ leaf = mdb_node_search(mc, key, exactp);
+ if (exactp != NULL && !*exactp) {
+ /* MDB_SET specified and not an exact match. */
+ return MDB_NOTFOUND;
+ }
+
+ if (leaf == NULL) {
+ DPUTS("===> inexact leaf not found, goto sibling");
+ if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS) {
+ mc->mc_flags |= C_EOF;
+ return rc; /* no entries matched */
+ }
+ mp = mc->mc_pg[mc->mc_top];
+ mdb_cassert(mc, IS_LEAF(mp));
+ leaf = NODEPTR(mp, 0);
+ }
+
+set1:
+ mc->mc_flags |= C_INITIALIZED;
+ mc->mc_flags &= ~C_EOF;
+
+ if (IS_LEAF2(mp)) {
+ if (op == MDB_SET_RANGE || op == MDB_SET_KEY) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size);
+ }
+ return MDB_SUCCESS;
+ }
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ mdb_xcursor_init1(mc, leaf);
+ }
+ if (data) {
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ if (op == MDB_SET || op == MDB_SET_KEY || op == MDB_SET_RANGE) {
+ rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
+ } else {
+ int ex2, *ex2p;
+ if (op == MDB_GET_BOTH) {
+ ex2p = &ex2;
+ ex2 = 0;
+ } else {
+ ex2p = NULL;
+ }
+ rc = mdb_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_SET_RANGE, ex2p);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ } else if (op == MDB_GET_BOTH || op == MDB_GET_BOTH_RANGE) {
+ MDB_val olddata;
+ MDB_cmp_func *dcmp;
+ if ((rc = mdb_node_read(mc, leaf, &olddata)) != MDB_SUCCESS)
+ return rc;
+ dcmp = mc->mc_dbx->md_dcmp;
+#if UINT_MAX < SIZE_MAX
+ if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
+ dcmp = mdb_cmp_clong;
+#endif
+ rc = dcmp(data, &olddata);
+ if (rc) {
+ if (op == MDB_GET_BOTH || rc > 0)
+ return MDB_NOTFOUND;
+ rc = 0;
+ }
+ *data = olddata;
+
+ } else {
+ if (mc->mc_xcursor)
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+ if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS)
+ return rc;
+ }
+ }
+
+ /* The key already matches in all other cases */
+ if (op == MDB_SET_RANGE || op == MDB_SET_KEY)
+ MDB_GET_KEY(leaf, key);
+ DPRINTF(("==> cursor placed on key [%s]", DKEY(key)));
+
+ return rc;
+}
+
+/** Move the cursor to the first item in the database. */
+static int
+mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data)
+{
+ int rc;
+ MDB_node *leaf;
+
+ if (mc->mc_xcursor)
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+
+ if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
+ rc = mdb_page_search(mc, NULL, MDB_PS_FIRST);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
+
+ leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0);
+ mc->mc_flags |= C_INITIALIZED;
+ mc->mc_flags &= ~C_EOF;
+
+ mc->mc_ki[mc->mc_top] = 0;
+
+ if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->mv_size);
+ return MDB_SUCCESS;
+ }
+
+ if (data) {
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ mdb_xcursor_init1(mc, leaf);
+ rc = mdb_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
+ if (rc)
+ return rc;
+ } else {
+ if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS)
+ return rc;
+ }
+ }
+ MDB_GET_KEY(leaf, key);
+ return MDB_SUCCESS;
+}
+
+/** Move the cursor to the last item in the database. */
+static int
+mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data)
+{
+ int rc;
+ MDB_node *leaf;
+
+ if (mc->mc_xcursor)
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+
+ if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
+ rc = mdb_page_search(mc, NULL, MDB_PS_LAST);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
+
+ mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1;
+ mc->mc_flags |= C_INITIALIZED|C_EOF;
+ leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+
+ if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->mv_size);
+ return MDB_SUCCESS;
+ }
+
+ if (data) {
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ mdb_xcursor_init1(mc, leaf);
+ rc = mdb_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL);
+ if (rc)
+ return rc;
+ } else {
+ if ((rc = mdb_node_read(mc, leaf, data)) != MDB_SUCCESS)
+ return rc;
+ }
+ }
+
+ MDB_GET_KEY(leaf, key);
+ return MDB_SUCCESS;
+}
+
+int
+mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
+ MDB_cursor_op op)
+{
+ int rc;
+ int exact = 0;
+ int (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data);
+
+ if (mc == NULL)
+ return EINVAL;
+
+ if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ switch (op) {
+ case MDB_GET_CURRENT:
+ if (!(mc->mc_flags & C_INITIALIZED)) {
+ rc = EINVAL;
+ } else {
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ int nkeys = NUMKEYS(mp);
+ if (!nkeys || mc->mc_ki[mc->mc_top] >= nkeys) {
+ mc->mc_ki[mc->mc_top] = nkeys;
+ rc = MDB_NOTFOUND;
+ break;
+ }
+ rc = MDB_SUCCESS;
+ if (IS_LEAF2(mp)) {
+ key->mv_size = mc->mc_db->md_pad;
+ key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size);
+ } else {
+ MDB_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+ MDB_GET_KEY(leaf, key);
+ if (data) {
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT);
+ } else {
+ rc = mdb_node_read(mc, leaf, data);
+ }
+ }
+ }
+ }
+ break;
+ case MDB_GET_BOTH:
+ case MDB_GET_BOTH_RANGE:
+ if (data == NULL) {
+ rc = EINVAL;
+ break;
+ }
+ if (mc->mc_xcursor == NULL) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ /* FALLTHRU */
+ case MDB_SET:
+ case MDB_SET_KEY:
+ case MDB_SET_RANGE:
+ if (key == NULL) {
+ rc = EINVAL;
+ } else {
+ rc = mdb_cursor_set(mc, key, data, op,
+ op == MDB_SET_RANGE ? NULL : &exact);
+ }
+ break;
+ case MDB_GET_MULTIPLE:
+ if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
+ rc = EINVAL;
+ break;
+ }
+ if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ rc = MDB_SUCCESS;
+ if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) ||
+ (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF))
+ break;
+ goto fetchm;
+ case MDB_NEXT_MULTIPLE:
+ if (data == NULL) {
+ rc = EINVAL;
+ break;
+ }
+ if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
+ if (rc == MDB_SUCCESS) {
+ if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
+ MDB_cursor *mx;
+fetchm:
+ mx = &mc->mc_xcursor->mx_cursor;
+ data->mv_size = NUMKEYS(mx->mc_pg[mx->mc_top]) *
+ mx->mc_db->md_pad;
+ data->mv_data = METADATA(mx->mc_pg[mx->mc_top]);
+ mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top])-1;
+ } else {
+ rc = MDB_NOTFOUND;
+ }
+ }
+ break;
+ case MDB_PREV_MULTIPLE:
+ if (data == NULL) {
+ rc = EINVAL;
+ break;
+ }
+ if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ if (!(mc->mc_flags & C_INITIALIZED))
+ rc = mdb_cursor_last(mc, key, data);
+ else
+ rc = MDB_SUCCESS;
+ if (rc == MDB_SUCCESS) {
+ MDB_cursor *mx = &mc->mc_xcursor->mx_cursor;
+ if (mx->mc_flags & C_INITIALIZED) {
+ rc = mdb_cursor_sibling(mx, 0);
+ if (rc == MDB_SUCCESS)
+ goto fetchm;
+ } else {
+ rc = MDB_NOTFOUND;
+ }
+ }
+ break;
+ case MDB_NEXT:
+ case MDB_NEXT_DUP:
+ case MDB_NEXT_NODUP:
+ rc = mdb_cursor_next(mc, key, data, op);
+ break;
+ case MDB_PREV:
+ case MDB_PREV_DUP:
+ case MDB_PREV_NODUP:
+ rc = mdb_cursor_prev(mc, key, data, op);
+ break;
+ case MDB_FIRST:
+ rc = mdb_cursor_first(mc, key, data);
+ break;
+ case MDB_FIRST_DUP:
+ mfunc = mdb_cursor_first;
+ mmove:
+ if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
+ rc = EINVAL;
+ break;
+ }
+ if (mc->mc_xcursor == NULL) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ {
+ MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ MDB_GET_KEY(leaf, key);
+ rc = mdb_node_read(mc, leaf, data);
+ break;
+ }
+ }
+ if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) {
+ rc = EINVAL;
+ break;
+ }
+ rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL);
+ break;
+ case MDB_LAST:
+ rc = mdb_cursor_last(mc, key, data);
+ break;
+ case MDB_LAST_DUP:
+ mfunc = mdb_cursor_last;
+ goto mmove;
+ default:
+ DPRINTF(("unhandled/unimplemented cursor operation %u", op));
+ rc = EINVAL;
+ break;
+ }
+
+ if (mc->mc_flags & C_DEL)
+ mc->mc_flags ^= C_DEL;
+
+ return rc;
+}
+
+/** Touch all the pages in the cursor stack. Set mc_top.
+ * Makes sure all the pages are writable, before attempting a write operation.
+ * @param[in] mc The cursor to operate on.
+ */
+static int
+mdb_cursor_touch(MDB_cursor *mc)
+{
+ int rc = MDB_SUCCESS;
+
+ if (mc->mc_dbi >= CORE_DBS && !(*mc->mc_dbflag & (DB_DIRTY|DB_DUPDATA))) {
+ /* Touch DB record of named DB */
+ MDB_cursor mc2;
+ MDB_xcursor mcx;
+ if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))
+ return MDB_BAD_DBI;
+ mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, &mcx);
+ rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY);
+ if (rc)
+ return rc;
+ *mc->mc_dbflag |= DB_DIRTY;
+ }
+ mc->mc_top = 0;
+ if (mc->mc_snum) {
+ do {
+ rc = mdb_page_touch(mc);
+ } while (!rc && ++(mc->mc_top) < mc->mc_snum);
+ mc->mc_top = mc->mc_snum-1;
+ }
+ return rc;
+}
+
+/** Do not spill pages to disk if txn is getting full, may fail instead */
+#define MDB_NOSPILL 0x8000
+
+int
+mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
+ unsigned int flags)
+{
+ MDB_env *env;
+ MDB_node *leaf = NULL;
+ MDB_page *fp, *mp, *sub_root = NULL;
+ uint16_t fp_flags;
+ MDB_val xdata, *rdata, dkey, olddata;
+ MDB_db dummy;
+ int do_sub = 0, insert_key, insert_data;
+ unsigned int mcount = 0, dcount = 0, nospill;
+ size_t nsize;
+ int rc, rc2;
+ unsigned int nflags;
+ DKBUF;
+
+ if (mc == NULL || key == NULL)
+ return EINVAL;
+
+ env = mc->mc_txn->mt_env;
+
+ /* Check this first so counter will always be zero on any
+ * early failures.
+ */
+ if (flags & MDB_MULTIPLE) {
+ dcount = data[1].mv_size;
+ data[1].mv_size = 0;
+ if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFIXED))
+ return MDB_INCOMPATIBLE;
+ }
+
+ nospill = flags & MDB_NOSPILL;
+ flags &= ~MDB_NOSPILL;
+
+ if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
+ return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+
+ if (key->mv_size-1 >= ENV_MAXKEY(env))
+ return MDB_BAD_VALSIZE;
+
+#if SIZE_MAX > MAXDATASIZE
+ if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))
+ return MDB_BAD_VALSIZE;
+#else
+ if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env))
+ return MDB_BAD_VALSIZE;
+#endif
+
+ DPRINTF(("==> put db %d key [%s], size %"Z"u, data size %"Z"u",
+ DDBI(mc), DKEY(key), key ? key->mv_size : 0, data->mv_size));
+
+ dkey.mv_size = 0;
+
+ if (flags == MDB_CURRENT) {
+ if (!(mc->mc_flags & C_INITIALIZED))
+ return EINVAL;
+ rc = MDB_SUCCESS;
+ } else if (mc->mc_db->md_root == P_INVALID) {
+ /* new database, cursor has nothing to point to */
+ mc->mc_snum = 0;
+ mc->mc_top = 0;
+ mc->mc_flags &= ~C_INITIALIZED;
+ rc = MDB_NO_ROOT;
+ } else {
+ int exact = 0;
+ MDB_val d2;
+ if (flags & MDB_APPEND) {
+ MDB_val k2;
+ rc = mdb_cursor_last(mc, &k2, &d2);
+ if (rc == 0) {
+ rc = mc->mc_dbx->md_cmp(key, &k2);
+ if (rc > 0) {
+ rc = MDB_NOTFOUND;
+ mc->mc_ki[mc->mc_top]++;
+ } else {
+ /* new key is <= last key */
+ rc = MDB_KEYEXIST;
+ }
+ }
+ } else {
+ rc = mdb_cursor_set(mc, key, &d2, MDB_SET, &exact);
+ }
+ if ((flags & MDB_NOOVERWRITE) && rc == 0) {
+ DPRINTF(("duplicate key [%s]", DKEY(key)));
+ *data = d2;
+ return MDB_KEYEXIST;
+ }
+ if (rc && rc != MDB_NOTFOUND)
+ return rc;
+ }
+
+ if (mc->mc_flags & C_DEL)
+ mc->mc_flags ^= C_DEL;
+
+ /* Cursor is positioned, check for room in the dirty list */
+ if (!nospill) {
+ if (flags & MDB_MULTIPLE) {
+ rdata = &xdata;
+ xdata.mv_size = data->mv_size * dcount;
+ } else {
+ rdata = data;
+ }
+ if ((rc2 = mdb_page_spill(mc, key, rdata)))
+ return rc2;
+ }
+
+ if (rc == MDB_NO_ROOT) {
+ MDB_page *np;
+ /* new database, write a root leaf page */
+ DPUTS("allocating new root leaf page");
+ if ((rc2 = mdb_page_new(mc, P_LEAF, 1, &np))) {
+ return rc2;
+ }
+ mdb_cursor_push(mc, np);
+ mc->mc_db->md_root = np->mp_pgno;
+ mc->mc_db->md_depth++;
+ *mc->mc_dbflag |= DB_DIRTY;
+ if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED))
+ == MDB_DUPFIXED)
+ np->mp_flags |= P_LEAF2;
+ mc->mc_flags |= C_INITIALIZED;
+ } else {
+ /* make sure all cursor pages are writable */
+ rc2 = mdb_cursor_touch(mc);
+ if (rc2)
+ return rc2;
+ }
+
+ insert_key = insert_data = rc;
+ if (insert_key) {
+ /* The key does not exist */
+ DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top]));
+ if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
+ LEAFSIZE(key, data) > env->me_nodemax)
+ {
+ /* Too big for a node, insert in sub-DB. Set up an empty
+ * "old sub-page" for prep_subDB to expand to a full page.
+ */
+ fp_flags = P_LEAF|P_DIRTY;
+ fp = env->me_pbuf;
+ fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */
+ fp->mp_lower = fp->mp_upper = (PAGEHDRSZ-PAGEBASE);
+ olddata.mv_size = PAGEHDRSZ;
+ goto prep_subDB;
+ }
+ } else {
+ /* there's only a key anyway, so this is a no-op */
+ if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
+ char *ptr;
+ unsigned int ksize = mc->mc_db->md_pad;
+ if (key->mv_size != ksize)
+ return MDB_BAD_VALSIZE;
+ ptr = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize);
+ memcpy(ptr, key->mv_data, ksize);
+fix_parent:
+ /* if overwriting slot 0 of leaf, need to
+ * update branch key if there is a parent page
+ */
+ if (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
+ unsigned short dtop = 1;
+ mc->mc_top--;
+ /* slot 0 is always an empty key, find real slot */
+ while (mc->mc_top && !mc->mc_ki[mc->mc_top]) {
+ mc->mc_top--;
+ dtop++;
+ }
+ if (mc->mc_ki[mc->mc_top])
+ rc2 = mdb_update_key(mc, key);
+ else
+ rc2 = MDB_SUCCESS;
+ mc->mc_top += dtop;
+ if (rc2)
+ return rc2;
+ }
+ return MDB_SUCCESS;
+ }
+
+more:
+ leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ olddata.mv_size = NODEDSZ(leaf);
+ olddata.mv_data = NODEDATA(leaf);
+
+ /* DB has dups? */
+ if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) {
+ /* Prepare (sub-)page/sub-DB to accept the new item,
+ * if needed. fp: old sub-page or a header faking
+ * it. mp: new (sub-)page. offset: growth in page
+ * size. xdata: node data with new page or DB.
+ */
+ unsigned i, offset = 0;
+ mp = fp = xdata.mv_data = env->me_pbuf;
+ mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
+
+ /* Was a single item before, must convert now */
+ if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ MDB_cmp_func *dcmp;
+ /* Just overwrite the current item */
+ if (flags == MDB_CURRENT)
+ goto current;
+ dcmp = mc->mc_dbx->md_dcmp;
+#if UINT_MAX < SIZE_MAX
+ if (dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
+ dcmp = mdb_cmp_clong;
+#endif
+ /* does data match? */
+ if (!dcmp(data, &olddata)) {
+ if (flags & (MDB_NODUPDATA|MDB_APPENDDUP))
+ return MDB_KEYEXIST;
+ /* overwrite it */
+ goto current;
+ }
+
+ /* Back up original data item */
+ dkey.mv_size = olddata.mv_size;
+ dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size);
+
+ /* Make sub-page header for the dup items, with dummy body */
+ fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP;
+ fp->mp_lower = (PAGEHDRSZ-PAGEBASE);
+ xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size;
+ if (mc->mc_db->md_flags & MDB_DUPFIXED) {
+ fp->mp_flags |= P_LEAF2;
+ fp->mp_pad = data->mv_size;
+ xdata.mv_size += 2 * data->mv_size; /* leave space for 2 more */
+ } else {
+ xdata.mv_size += 2 * (sizeof(indx_t) + NODESIZE) +
+ (dkey.mv_size & 1) + (data->mv_size & 1);
+ }
+ fp->mp_upper = xdata.mv_size - PAGEBASE;
+ olddata.mv_size = xdata.mv_size; /* pretend olddata is fp */
+ } else if (leaf->mn_flags & F_SUBDATA) {
+ /* Data is on sub-DB, just store it */
+ flags |= F_DUPDATA|F_SUBDATA;
+ goto put_sub;
+ } else {
+ /* Data is on sub-page */
+ fp = olddata.mv_data;
+ switch (flags) {
+ default:
+ if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
+ offset = EVEN(NODESIZE + sizeof(indx_t) +
+ data->mv_size);
+ break;
+ }
+ offset = fp->mp_pad;
+ if (SIZELEFT(fp) < offset) {
+ offset *= 4; /* space for 4 more */
+ break;
+ }
+ /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
+ case MDB_CURRENT:
+ fp->mp_flags |= P_DIRTY;
+ COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
+ mc->mc_xcursor->mx_cursor.mc_pg[0] = fp;
+ flags |= F_DUPDATA;
+ goto put_sub;
+ }
+ xdata.mv_size = olddata.mv_size + offset;
+ }
+
+ fp_flags = fp->mp_flags;
+ if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) {
+ /* Too big for a sub-page, convert to sub-DB */
+ fp_flags &= ~P_SUBP;
+prep_subDB:
+ if (mc->mc_db->md_flags & MDB_DUPFIXED) {
+ fp_flags |= P_LEAF2;
+ dummy.md_pad = fp->mp_pad;
+ dummy.md_flags = MDB_DUPFIXED;
+ if (mc->mc_db->md_flags & MDB_INTEGERDUP)
+ dummy.md_flags |= MDB_INTEGERKEY;
+ } else {
+ dummy.md_pad = 0;
+ dummy.md_flags = 0;
+ }
+ dummy.md_depth = 1;
+ dummy.md_branch_pages = 0;
+ dummy.md_leaf_pages = 1;
+ dummy.md_overflow_pages = 0;
+ dummy.md_entries = NUMKEYS(fp);
+ xdata.mv_size = sizeof(MDB_db);
+ xdata.mv_data = &dummy;
+ if ((rc = mdb_page_alloc(mc, 1, &mp)))
+ return rc;
+ offset = env->me_psize - olddata.mv_size;
+ flags |= F_DUPDATA|F_SUBDATA;
+ dummy.md_root = mp->mp_pgno;
+ sub_root = mp;
+ }
+ if (mp != fp) {
+ mp->mp_flags = fp_flags | P_DIRTY;
+ mp->mp_pad = fp->mp_pad;
+ mp->mp_lower = fp->mp_lower;
+ mp->mp_upper = fp->mp_upper + offset;
+ if (fp_flags & P_LEAF2) {
+ memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
+ } else {
+ memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGEBASE,
+ olddata.mv_size - fp->mp_upper - PAGEBASE);
+ for (i=0; i<NUMKEYS(fp); i++)
+ mp->mp_ptrs[i] = fp->mp_ptrs[i] + offset;
+ }
+ }
+
+ rdata = &xdata;
+ flags |= F_DUPDATA;
+ do_sub = 1;
+ if (!insert_key)
+ mdb_node_del(mc, 0);
+ goto new_sub;
+ }
+current:
+ /* LMDB passes F_SUBDATA in 'flags' to write a DB record */
+ if ((leaf->mn_flags ^ flags) & F_SUBDATA)
+ return MDB_INCOMPATIBLE;
+ /* overflow page overwrites need special handling */
+ if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
+ MDB_page *omp;
+ pgno_t pg;
+ int level, ovpages, dpages = OVPAGES(data->mv_size, env->me_psize);
+
+ memcpy(&pg, olddata.mv_data, sizeof(pg));
+ if ((rc2 = mdb_page_get(mc, pg, &omp, &level)) != 0)
+ return rc2;
+ ovpages = omp->mp_pages;
+
+ /* Is the ov page large enough? */
+ if (ovpages >= dpages) {
+ if (!(omp->mp_flags & P_DIRTY) &&
+ (level || (env->me_flags & MDB_WRITEMAP)))
+ {
+ rc = mdb_page_unspill(mc->mc_txn, omp, &omp);
+ if (rc)
+ return rc;
+ level = 0; /* dirty in this txn or clean */
+ }
+ /* Is it dirty? */
+ if (omp->mp_flags & P_DIRTY) {
+ /* yes, overwrite it. Note in this case we don't
+ * bother to try shrinking the page if the new data
+ * is smaller than the overflow threshold.
+ */
+ if (level > 1) {
+ /* It is writable only in a parent txn */
+ size_t sz = (size_t) env->me_psize * ovpages, off;
+ MDB_page *np = mdb_page_malloc(mc->mc_txn, ovpages);
+ MDB_ID2 id2;
+ if (!np)
+ return ENOMEM;
+ id2.mid = pg;
+ id2.mptr = np;
+ /* Note - this page is already counted in parent's dirty_room */
+ rc2 = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
+ mdb_cassert(mc, rc2 == 0);
+ /* Currently we make the page look as with put() in the
+ * parent txn, in case the user peeks at MDB_RESERVEd
+ * or unused parts. Some users treat ovpages specially.
+ */
+ if (!(flags & MDB_RESERVE)) {
+ /* Skip the part where LMDB will put *data.
+ * Copy end of page, adjusting alignment so
+ * compiler may copy words instead of bytes.
+ */
+ off = (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);
+ memcpy((size_t *)((char *)np + off),
+ (size_t *)((char *)omp + off), sz - off);
+ sz = PAGEHDRSZ;
+ }
+ memcpy(np, omp, sz); /* Copy beginning of page */
+ omp = np;
+ }
+ SETDSZ(leaf, data->mv_size);
+ if (F_ISSET(flags, MDB_RESERVE))
+ data->mv_data = METADATA(omp);
+ else
+ memcpy(METADATA(omp), data->mv_data, data->mv_size);
+ return MDB_SUCCESS;
+ }
+ }
+ if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS)
+ return rc2;
+ } else if (data->mv_size == olddata.mv_size) {
+ /* same size, just replace it. Note that we could
+ * also reuse this node if the new data is smaller,
+ * but instead we opt to shrink the node in that case.
+ */
+ if (F_ISSET(flags, MDB_RESERVE))
+ data->mv_data = olddata.mv_data;
+ else if (!(mc->mc_flags & C_SUB))
+ memcpy(olddata.mv_data, data->mv_data, data->mv_size);
+ else {
+ memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
+ goto fix_parent;
+ }
+ return MDB_SUCCESS;
+ }
+ mdb_node_del(mc, 0);
+ }
+
+ rdata = data;
+
+new_sub:
+ nflags = flags & NODE_ADD_FLAGS;
+ nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata);
+ if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) {
+ if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA )
+ nflags &= ~MDB_APPEND; /* sub-page may need room to grow */
+ if (!insert_key)
+ nflags |= MDB_SPLIT_REPLACE;
+ rc = mdb_page_split(mc, key, rdata, P_INVALID, nflags);
+ } else {
+ /* There is room already in this leaf page. */
+ rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags);
+ if (rc == 0) {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = mc->mc_dbi;
+ unsigned i = mc->mc_top;
+ MDB_page *mp = mc->mc_pg[i];
+
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (mc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp) continue;
+ if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) {
+ m3->mc_ki[i]++;
+ }
+ if (XCURSOR_INITED(m3))
+ XCURSOR_REFRESH(m3, mp, m3->mc_ki[i]);
+ }
+ }
+ }
+
+ if (rc == MDB_SUCCESS) {
+ /* Now store the actual data in the child DB. Note that we're
+ * storing the user data in the keys field, so there are strict
+ * size limits on dupdata. The actual data fields of the child
+ * DB are all zero size.
+ */
+ if (do_sub) {
+ int xflags, new_dupdata;
+ size_t ecount;
+put_sub:
+ xdata.mv_size = 0;
+ xdata.mv_data = "";
+ leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if (flags & MDB_CURRENT) {
+ xflags = MDB_CURRENT|MDB_NOSPILL;
+ } else {
+ mdb_xcursor_init1(mc, leaf);
+ xflags = (flags & MDB_NODUPDATA) ?
+ MDB_NOOVERWRITE|MDB_NOSPILL : MDB_NOSPILL;
+ }
+ if (sub_root)
+ mc->mc_xcursor->mx_cursor.mc_pg[0] = sub_root;
+ new_dupdata = (int)dkey.mv_size;
+ /* converted, write the original data first */
+ if (dkey.mv_size) {
+ rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
+ if (rc)
+ goto bad_sub;
+ /* we've done our job */
+ dkey.mv_size = 0;
+ }
+ if (!(leaf->mn_flags & F_SUBDATA) || sub_root) {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2;
+ MDB_xcursor *mx = mc->mc_xcursor;
+ unsigned i = mc->mc_top;
+ MDB_page *mp = mc->mc_pg[i];
+ int nkeys = NUMKEYS(mp);
+
+ for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
+ if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
+ if (!(m2->mc_flags & C_INITIALIZED)) continue;
+ if (m2->mc_pg[i] == mp) {
+ if (m2->mc_ki[i] == mc->mc_ki[i]) {
+ mdb_xcursor_init2(m2, mx, new_dupdata);
+ } else if (!insert_key && m2->mc_ki[i] < nkeys) {
+ XCURSOR_REFRESH(m2, mp, m2->mc_ki[i]);
+ }
+ }
+ }
+ }
+ ecount = mc->mc_xcursor->mx_db.md_entries;
+ if (flags & MDB_APPENDDUP)
+ xflags |= MDB_APPEND;
+ rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags);
+ if (flags & F_SUBDATA) {
+ void *db = NODEDATA(leaf);
+ memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db));
+ }
+ insert_data = mc->mc_xcursor->mx_db.md_entries - ecount;
+ }
+ /* Increment count unless we just replaced an existing item. */
+ if (insert_data)
+ mc->mc_db->md_entries++;
+ if (insert_key) {
+ /* Invalidate txn if we created an empty sub-DB */
+ if (rc)
+ goto bad_sub;
+ /* If we succeeded and the key didn't exist before,
+ * make sure the cursor is marked valid.
+ */
+ mc->mc_flags |= C_INITIALIZED;
+ }
+ if (flags & MDB_MULTIPLE) {
+ if (!rc) {
+ mcount++;
+ /* let caller know how many succeeded, if any */
+ data[1].mv_size = mcount;
+ if (mcount < dcount) {
+ data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size;
+ insert_key = insert_data = 0;
+ goto more;
+ }
+ }
+ }
+ return rc;
+bad_sub:
+ if (rc == MDB_KEYEXIST) /* should not happen, we deleted that item */
+ rc = MDB_CORRUPTED;
+ }
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+int
+mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
+{
+ MDB_node *leaf;
+ MDB_page *mp;
+ int rc;
+
+ if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
+ return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+
+ if (!(mc->mc_flags & C_INITIALIZED))
+ return EINVAL;
+
+ if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top]))
+ return MDB_NOTFOUND;
+
+ if (!(flags & MDB_NOSPILL) && (rc = mdb_page_spill(mc, NULL, NULL)))
+ return rc;
+
+ rc = mdb_cursor_touch(mc);
+ if (rc)
+ return rc;
+
+ mp = mc->mc_pg[mc->mc_top];
+ if (IS_LEAF2(mp))
+ goto del_key;
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+
+ if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ if (flags & MDB_NODUPDATA) {
+ /* mdb_cursor_del0() will subtract the final entry */
+ mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1;
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
+ } else {
+ if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
+ mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
+ }
+ rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL);
+ if (rc)
+ return rc;
+ /* If sub-DB still has entries, we're done */
+ if (mc->mc_xcursor->mx_db.md_entries) {
+ if (leaf->mn_flags & F_SUBDATA) {
+ /* update subDB info */
+ void *db = NODEDATA(leaf);
+ memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db));
+ } else {
+ MDB_cursor *m2;
+ /* shrink fake page */
+ mdb_node_shrink(mp, mc->mc_ki[mc->mc_top]);
+ leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
+ mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
+ /* fix other sub-DB cursors pointed at fake pages on this page */
+ for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
+ if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
+ if (!(m2->mc_flags & C_INITIALIZED)) continue;
+ if (m2->mc_pg[mc->mc_top] == mp) {
+ MDB_node *n2 = leaf;
+ if (m2->mc_ki[mc->mc_top] != mc->mc_ki[mc->mc_top]) {
+ n2 = NODEPTR(mp, m2->mc_ki[mc->mc_top]);
+ if (n2->mn_flags & F_SUBDATA) continue;
+ }
+ m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2);
+ }
+ }
+ }
+ mc->mc_db->md_entries--;
+ return rc;
+ } else {
+ mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
+ }
+ /* otherwise fall thru and delete the sub-DB */
+ }
+
+ if (leaf->mn_flags & F_SUBDATA) {
+ /* add all the child DB's pages to the free list */
+ rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
+ if (rc)
+ goto fail;
+ }
+ }
+ /* LMDB passes F_SUBDATA in 'flags' to delete a DB record */
+ else if ((leaf->mn_flags ^ flags) & F_SUBDATA) {
+ rc = MDB_INCOMPATIBLE;
+ goto fail;
+ }
+
+ /* add overflow pages to free list */
+ if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
+ MDB_page *omp;
+ pgno_t pg;
+
+ memcpy(&pg, NODEDATA(leaf), sizeof(pg));
+ if ((rc = mdb_page_get(mc, pg, &omp, NULL)) ||
+ (rc = mdb_ovpage_free(mc, omp)))
+ goto fail;
+ }
+
+del_key:
+ return mdb_cursor_del0(mc);
+
+fail:
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+/** Allocate and initialize new pages for a database.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in] mc a cursor on the database being added to.
+ * @param[in] flags flags defining what type of page is being allocated.
+ * @param[in] num the number of pages to allocate. This is usually 1,
+ * unless allocating overflow pages for a large record.
+ * @param[out] mp Address of a page, or NULL on failure.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp)
+{
+ MDB_page *np;
+ int rc;
+
+ if ((rc = mdb_page_alloc(mc, num, &np)))
+ return rc;
+ DPRINTF(("allocated new mpage %"Z"u, page size %u",
+ np->mp_pgno, mc->mc_txn->mt_env->me_psize));
+ np->mp_flags = flags | P_DIRTY;
+ np->mp_lower = (PAGEHDRSZ-PAGEBASE);
+ np->mp_upper = mc->mc_txn->mt_env->me_psize - PAGEBASE;
+
+ if (IS_BRANCH(np))
+ mc->mc_db->md_branch_pages++;
+ else if (IS_LEAF(np))
+ mc->mc_db->md_leaf_pages++;
+ else if (IS_OVERFLOW(np)) {
+ mc->mc_db->md_overflow_pages += num;
+ np->mp_pages = num;
+ }
+ *mp = np;
+
+ return 0;
+}
+
+/** Calculate the size of a leaf node.
+ * The size depends on the environment's page size; if a data item
+ * is too large it will be put onto an overflow page and the node
+ * size will only include the key and not the data. Sizes are always
+ * rounded up to an even number of bytes, to guarantee 2-byte alignment
+ * of the #MDB_node headers.
+ * @param[in] env The environment handle.
+ * @param[in] key The key for the node.
+ * @param[in] data The data for the node.
+ * @return The number of bytes needed to store the node.
+ */
+static size_t
+mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data)
+{
+ size_t sz;
+
+ sz = LEAFSIZE(key, data);
+ if (sz > env->me_nodemax) {
+ /* put on overflow page */
+ sz -= data->mv_size - sizeof(pgno_t);
+ }
+
+ return EVEN(sz + sizeof(indx_t));
+}
+
+/** Calculate the size of a branch node.
+ * The size should depend on the environment's page size but since
+ * we currently don't support spilling large keys onto overflow
+ * pages, it's simply the size of the #MDB_node header plus the
+ * size of the key. Sizes are always rounded up to an even number
+ * of bytes, to guarantee 2-byte alignment of the #MDB_node headers.
+ * @param[in] env The environment handle.
+ * @param[in] key The key for the node.
+ * @return The number of bytes needed to store the node.
+ */
+static size_t
+mdb_branch_size(MDB_env *env, MDB_val *key)
+{
+ size_t sz;
+
+ sz = INDXSIZE(key);
+ if (sz > env->me_nodemax) {
+ /* put on overflow page */
+ /* not implemented */
+ /* sz -= key->size - sizeof(pgno_t); */
+ }
+
+ return sz + sizeof(indx_t);
+}
+
+/** Add a node to the page pointed to by the cursor.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in] mc The cursor for this operation.
+ * @param[in] indx The index on the page where the new node should be added.
+ * @param[in] key The key for the new node.
+ * @param[in] data The data for the new node, if any.
+ * @param[in] pgno The page number, if adding a branch node.
+ * @param[in] flags Flags for the node.
+ * @return 0 on success, non-zero on failure. Possible errors are:
+ * <ul>
+ * <li>ENOMEM - failed to allocate overflow pages for the node.
+ * <li>MDB_PAGE_FULL - there is insufficient room in the page. This error
+ * should never happen since all callers already calculate the
+ * page's free space before calling this function.
+ * </ul>
+ */
+static int
+mdb_node_add(MDB_cursor *mc, indx_t indx,
+ MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags)
+{
+ unsigned int i;
+ size_t node_size = NODESIZE;
+ ssize_t room;
+ indx_t ofs;
+ MDB_node *node;
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ MDB_page *ofp = NULL; /* overflow page */
+ void *ndata;
+ DKBUF;
+
+ mdb_cassert(mc, mp->mp_upper >= mp->mp_lower);
+
+ DPRINTF(("add to %s %spage %"Z"u index %i, data size %"Z"u key size %"Z"u [%s]",
+ IS_LEAF(mp) ? "leaf" : "branch",
+ IS_SUBP(mp) ? "sub-" : "",
+ mdb_dbg_pgno(mp), indx, data ? data->mv_size : 0,
+ key ? key->mv_size : 0, key ? DKEY(key) : "null"));
+
+ if (IS_LEAF2(mp)) {
+ /* Move higher keys up one slot. */
+ int ksize = mc->mc_db->md_pad, dif;
+ char *ptr = LEAF2KEY(mp, indx, ksize);
+ dif = NUMKEYS(mp) - indx;
+ if (dif > 0)
+ memmove(ptr+ksize, ptr, dif*ksize);
+ /* insert new key */
+ memcpy(ptr, key->mv_data, ksize);
+
+ /* Just using these for counting */
+ mp->mp_lower += sizeof(indx_t);
+ mp->mp_upper -= ksize - sizeof(indx_t);
+ return MDB_SUCCESS;
+ }
+
+ room = (ssize_t)SIZELEFT(mp) - (ssize_t)sizeof(indx_t);
+ if (key != NULL)
+ node_size += key->mv_size;
+ if (IS_LEAF(mp)) {
+ mdb_cassert(mc, key && data);
+ if (F_ISSET(flags, F_BIGDATA)) {
+ /* Data already on overflow page. */
+ node_size += sizeof(pgno_t);
+ } else if (node_size + data->mv_size > mc->mc_txn->mt_env->me_nodemax) {
+ int ovpages = OVPAGES(data->mv_size, mc->mc_txn->mt_env->me_psize);
+ int rc;
+ /* Put data on overflow page. */
+ DPRINTF(("data size is %"Z"u, node would be %"Z"u, put data on overflow page",
+ data->mv_size, node_size+data->mv_size));
+ node_size = EVEN(node_size + sizeof(pgno_t));
+ if ((ssize_t)node_size > room)
+ goto full;
+ if ((rc = mdb_page_new(mc, P_OVERFLOW, ovpages, &ofp)))
+ return rc;
+ DPRINTF(("allocated overflow page %"Z"u", ofp->mp_pgno));
+ flags |= F_BIGDATA;
+ goto update;
+ } else {
+ node_size += data->mv_size;
+ }
+ }
+ node_size = EVEN(node_size);
+ if ((ssize_t)node_size > room)
+ goto full;
+
+update:
+ /* Move higher pointers up one slot. */
+ for (i = NUMKEYS(mp); i > indx; i--)
+ mp->mp_ptrs[i] = mp->mp_ptrs[i - 1];
+
+ /* Adjust free space offsets. */
+ ofs = mp->mp_upper - node_size;
+ mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t));
+ mp->mp_ptrs[indx] = ofs;
+ mp->mp_upper = ofs;
+ mp->mp_lower += sizeof(indx_t);
+
+ /* Write the node data. */
+ node = NODEPTR(mp, indx);
+ node->mn_ksize = (key == NULL) ? 0 : key->mv_size;
+ node->mn_flags = flags;
+ if (IS_LEAF(mp))
+ SETDSZ(node,data->mv_size);
+ else
+ SETPGNO(node,pgno);
+
+ if (key)
+ memcpy(NODEKEY(node), key->mv_data, key->mv_size);
+
+ if (IS_LEAF(mp)) {
+ ndata = NODEDATA(node);
+ if (ofp == NULL) {
+ if (F_ISSET(flags, F_BIGDATA))
+ memcpy(ndata, data->mv_data, sizeof(pgno_t));
+ else if (F_ISSET(flags, MDB_RESERVE))
+ data->mv_data = ndata;
+ else
+ memcpy(ndata, data->mv_data, data->mv_size);
+ } else {
+ memcpy(ndata, &ofp->mp_pgno, sizeof(pgno_t));
+ ndata = METADATA(ofp);
+ if (F_ISSET(flags, MDB_RESERVE))
+ data->mv_data = ndata;
+ else
+ memcpy(ndata, data->mv_data, data->mv_size);
+ }
+ }
+
+ return MDB_SUCCESS;
+
+full:
+ DPRINTF(("not enough room in page %"Z"u, got %u ptrs",
+ mdb_dbg_pgno(mp), NUMKEYS(mp)));
+ DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room));
+ DPRINTF(("node size = %"Z"u", node_size));
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return MDB_PAGE_FULL;
+}
+
+/** Delete the specified node from a page.
+ * @param[in] mc Cursor pointing to the node to delete.
+ * @param[in] ksize The size of a node. Only used if the page is
+ * part of a #MDB_DUPFIXED database.
+ */
+static void
+mdb_node_del(MDB_cursor *mc, int ksize)
+{
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ indx_t indx = mc->mc_ki[mc->mc_top];
+ unsigned int sz;
+ indx_t i, j, numkeys, ptr;
+ MDB_node *node;
+ char *base;
+
+ DPRINTF(("delete node %u on %s page %"Z"u", indx,
+ IS_LEAF(mp) ? "leaf" : "branch", mdb_dbg_pgno(mp)));
+ numkeys = NUMKEYS(mp);
+ mdb_cassert(mc, indx < numkeys);
+
+ if (IS_LEAF2(mp)) {
+ int x = numkeys - 1 - indx;
+ base = LEAF2KEY(mp, indx, ksize);
+ if (x)
+ memmove(base, base + ksize, x * ksize);
+ mp->mp_lower -= sizeof(indx_t);
+ mp->mp_upper += ksize - sizeof(indx_t);
+ return;
+ }
+
+ node = NODEPTR(mp, indx);
+ sz = NODESIZE + node->mn_ksize;
+ if (IS_LEAF(mp)) {
+ if (F_ISSET(node->mn_flags, F_BIGDATA))
+ sz += sizeof(pgno_t);
+ else
+ sz += NODEDSZ(node);
+ }
+ sz = EVEN(sz);
+
+ ptr = mp->mp_ptrs[indx];
+ for (i = j = 0; i < numkeys; i++) {
+ if (i != indx) {
+ mp->mp_ptrs[j] = mp->mp_ptrs[i];
+ if (mp->mp_ptrs[i] < ptr)
+ mp->mp_ptrs[j] += sz;
+ j++;
+ }
+ }
+
+ base = (char *)mp + mp->mp_upper + PAGEBASE;
+ memmove(base + sz, base, ptr - mp->mp_upper);
+
+ mp->mp_lower -= sizeof(indx_t);
+ mp->mp_upper += sz;
+}
+
+/** Compact the main page after deleting a node on a subpage.
+ * @param[in] mp The main page to operate on.
+ * @param[in] indx The index of the subpage on the main page.
+ */
+static void
+mdb_node_shrink(MDB_page *mp, indx_t indx)
+{
+ MDB_node *node;
+ MDB_page *sp, *xp;
+ char *base;
+ indx_t delta, nsize, len, ptr;
+ int i;
+
+ node = NODEPTR(mp, indx);
+ sp = (MDB_page *)NODEDATA(node);
+ delta = SIZELEFT(sp);
+ nsize = NODEDSZ(node) - delta;
+
+ /* Prepare to shift upward, set len = length(subpage part to shift) */
+ if (IS_LEAF2(sp)) {
+ len = nsize;
+ if (nsize & 1)
+ return; /* do not make the node uneven-sized */
+ } else {
+ xp = (MDB_page *)((char *)sp + delta); /* destination subpage */
+ for (i = NUMKEYS(sp); --i >= 0; )
+ xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta;
+ len = PAGEHDRSZ;
+ }
+ sp->mp_upper = sp->mp_lower;
+ COPY_PGNO(sp->mp_pgno, mp->mp_pgno);
+ SETDSZ(node, nsize);
+
+ /* Shift <lower nodes...initial part of subpage> upward */
+ base = (char *)mp + mp->mp_upper + PAGEBASE;
+ memmove(base + delta, base, (char *)sp + len - base);
+
+ ptr = mp->mp_ptrs[indx];
+ for (i = NUMKEYS(mp); --i >= 0; ) {
+ if (mp->mp_ptrs[i] <= ptr)
+ mp->mp_ptrs[i] += delta;
+ }
+ mp->mp_upper += delta;
+}
+
+/** Initial setup of a sorted-dups cursor.
+ * Sorted duplicates are implemented as a sub-database for the given key.
+ * The duplicate data items are actually keys of the sub-database.
+ * Operations on the duplicate data items are performed using a sub-cursor
+ * initialized when the sub-database is first accessed. This function does
+ * the preliminary setup of the sub-cursor, filling in the fields that
+ * depend only on the parent DB.
+ * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized.
+ */
+static void
+mdb_xcursor_init0(MDB_cursor *mc)
+{
+ MDB_xcursor *mx = mc->mc_xcursor;
+
+ mx->mx_cursor.mc_xcursor = NULL;
+ mx->mx_cursor.mc_txn = mc->mc_txn;
+ mx->mx_cursor.mc_db = &mx->mx_db;
+ mx->mx_cursor.mc_dbx = &mx->mx_dbx;
+ mx->mx_cursor.mc_dbi = mc->mc_dbi;
+ mx->mx_cursor.mc_dbflag = &mx->mx_dbflag;
+ mx->mx_cursor.mc_snum = 0;
+ mx->mx_cursor.mc_top = 0;
+ mx->mx_cursor.mc_flags = C_SUB;
+ mx->mx_dbx.md_name.mv_size = 0;
+ mx->mx_dbx.md_name.mv_data = NULL;
+ mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp;
+ mx->mx_dbx.md_dcmp = NULL;
+ mx->mx_dbx.md_rel = mc->mc_dbx->md_rel;
+}
+
+/** Final setup of a sorted-dups cursor.
+ * Sets up the fields that depend on the data from the main cursor.
+ * @param[in] mc The main cursor whose sorted-dups cursor is to be initialized.
+ * @param[in] node The data containing the #MDB_db record for the
+ * sorted-dup database.
+ */
+static void
+mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
+{
+ MDB_xcursor *mx = mc->mc_xcursor;
+
+ if (node->mn_flags & F_SUBDATA) {
+ memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDB_db));
+ mx->mx_cursor.mc_pg[0] = 0;
+ mx->mx_cursor.mc_snum = 0;
+ mx->mx_cursor.mc_top = 0;
+ mx->mx_cursor.mc_flags = C_SUB;
+ } else {
+ MDB_page *fp = NODEDATA(node);
+ mx->mx_db.md_pad = 0;
+ mx->mx_db.md_flags = 0;
+ mx->mx_db.md_depth = 1;
+ mx->mx_db.md_branch_pages = 0;
+ mx->mx_db.md_leaf_pages = 1;
+ mx->mx_db.md_overflow_pages = 0;
+ mx->mx_db.md_entries = NUMKEYS(fp);
+ COPY_PGNO(mx->mx_db.md_root, fp->mp_pgno);
+ mx->mx_cursor.mc_snum = 1;
+ mx->mx_cursor.mc_top = 0;
+ mx->mx_cursor.mc_flags = C_INITIALIZED|C_SUB;
+ mx->mx_cursor.mc_pg[0] = fp;
+ mx->mx_cursor.mc_ki[0] = 0;
+ if (mc->mc_db->md_flags & MDB_DUPFIXED) {
+ mx->mx_db.md_flags = MDB_DUPFIXED;
+ mx->mx_db.md_pad = fp->mp_pad;
+ if (mc->mc_db->md_flags & MDB_INTEGERDUP)
+ mx->mx_db.md_flags |= MDB_INTEGERKEY;
+ }
+ }
+ DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
+ mx->mx_db.md_root));
+ mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DUPDATA;
+#if UINT_MAX < SIZE_MAX
+ if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_pad == sizeof(size_t))
+ mx->mx_dbx.md_cmp = mdb_cmp_clong;
+#endif
+}
+
+
+/** Fixup a sorted-dups cursor due to underlying update.
+ * Sets up some fields that depend on the data from the main cursor.
+ * Almost the same as init1, but skips initialization steps if the
+ * xcursor had already been used.
+ * @param[in] mc The main cursor whose sorted-dups cursor is to be fixed up.
+ * @param[in] src_mx The xcursor of an up-to-date cursor.
+ * @param[in] new_dupdata True if converting from a non-#F_DUPDATA item.
+ */
+static void
+mdb_xcursor_init2(MDB_cursor *mc, MDB_xcursor *src_mx, int new_dupdata)
+{
+ MDB_xcursor *mx = mc->mc_xcursor;
+
+ if (new_dupdata) {
+ mx->mx_cursor.mc_snum = 1;
+ mx->mx_cursor.mc_top = 0;
+ mx->mx_cursor.mc_flags |= C_INITIALIZED;
+ mx->mx_cursor.mc_ki[0] = 0;
+ mx->mx_dbflag = DB_VALID|DB_USRVALID|DB_DUPDATA;
+#if UINT_MAX < SIZE_MAX
+ mx->mx_dbx.md_cmp = src_mx->mx_dbx.md_cmp;
+#endif
+ } else if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) {
+ return;
+ }
+ mx->mx_db = src_mx->mx_db;
+ mx->mx_cursor.mc_pg[0] = src_mx->mx_cursor.mc_pg[0];
+ DPRINTF(("Sub-db -%u root page %"Z"u", mx->mx_cursor.mc_dbi,
+ mx->mx_db.md_root));
+}
+
+/** Initialize a cursor for a given transaction and database. */
+static void
+mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
+{
+ mc->mc_next = NULL;
+ mc->mc_backup = NULL;
+ mc->mc_dbi = dbi;
+ mc->mc_txn = txn;
+ mc->mc_db = &txn->mt_dbs[dbi];
+ mc->mc_dbx = &txn->mt_dbxs[dbi];
+ mc->mc_dbflag = &txn->mt_dbflags[dbi];
+ mc->mc_snum = 0;
+ mc->mc_top = 0;
+ mc->mc_pg[0] = 0;
+ mc->mc_ki[0] = 0;
+ mc->mc_flags = 0;
+ if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
+ mdb_tassert(txn, mx != NULL);
+ mc->mc_xcursor = mx;
+ mdb_xcursor_init0(mc);
+ } else {
+ mc->mc_xcursor = NULL;
+ }
+ if (*mc->mc_dbflag & DB_STALE) {
+ mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
+ }
+}
+
+int
+mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
+{
+ MDB_cursor *mc;
+ size_t size = sizeof(MDB_cursor);
+
+ if (!ret || !TXN_DBI_EXIST(txn, dbi, DB_VALID))
+ return EINVAL;
+
+ if (txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ if (dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
+ return EINVAL;
+
+ if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT)
+ size += sizeof(MDB_xcursor);
+
+ if ((mc = malloc(size)) != NULL) {
+ mdb_cursor_init(mc, txn, dbi, (MDB_xcursor *)(mc + 1));
+ if (txn->mt_cursors) {
+ mc->mc_next = txn->mt_cursors[dbi];
+ txn->mt_cursors[dbi] = mc;
+ mc->mc_flags |= C_UNTRACK;
+ }
+ } else {
+ return ENOMEM;
+ }
+
+ *ret = mc;
+
+ return MDB_SUCCESS;
+}
+
+int
+mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
+{
+ if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID))
+ return EINVAL;
+
+ if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)
+ return EINVAL;
+
+ if (txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ mdb_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor);
+ return MDB_SUCCESS;
+}
+
+/* Return the count of duplicate data items for the current key */
+int
+mdb_cursor_count(MDB_cursor *mc, size_t *countp)
+{
+ MDB_node *leaf;
+
+ if (mc == NULL || countp == NULL)
+ return EINVAL;
+
+ if (mc->mc_xcursor == NULL)
+ return MDB_INCOMPATIBLE;
+
+ if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ if (!(mc->mc_flags & C_INITIALIZED))
+ return EINVAL;
+
+ if (!mc->mc_snum)
+ return MDB_NOTFOUND;
+
+ if (mc->mc_flags & C_EOF) {
+ if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top]))
+ return MDB_NOTFOUND;
+ mc->mc_flags ^= C_EOF;
+ }
+
+ leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
+ *countp = 1;
+ } else {
+ if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
+ return EINVAL;
+
+ *countp = mc->mc_xcursor->mx_db.md_entries;
+ }
+ return MDB_SUCCESS;
+}
+
+void
+mdb_cursor_close(MDB_cursor *mc)
+{
+ if (mc && !mc->mc_backup) {
+ /* remove from txn, if tracked */
+ if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) {
+ MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi];
+ while (*prev && *prev != mc) prev = &(*prev)->mc_next;
+ if (*prev == mc)
+ *prev = mc->mc_next;
+ }
+ free(mc);
+ }
+}
+
+MDB_txn *
+mdb_cursor_txn(MDB_cursor *mc)
+{
+ if (!mc) return NULL;
+ return mc->mc_txn;
+}
+
+MDB_dbi
+mdb_cursor_dbi(MDB_cursor *mc)
+{
+ return mc->mc_dbi;
+}
+
+/** Replace the key for a branch node with a new key.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in] mc Cursor pointing to the node to operate on.
+ * @param[in] key The new key to use.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_update_key(MDB_cursor *mc, MDB_val *key)
+{
+ MDB_page *mp;
+ MDB_node *node;
+ char *base;
+ size_t len;
+ int delta, ksize, oksize;
+ indx_t ptr, i, numkeys, indx;
+ DKBUF;
+
+ indx = mc->mc_ki[mc->mc_top];
+ mp = mc->mc_pg[mc->mc_top];
+ node = NODEPTR(mp, indx);
+ ptr = mp->mp_ptrs[indx];
+#if MDB_DEBUG
+ {
+ MDB_val k2;
+ char kbuf2[DKBUF_MAXKEYSIZE*2+1];
+ k2.mv_data = NODEKEY(node);
+ k2.mv_size = node->mn_ksize;
+ DPRINTF(("update key %u (ofs %u) [%s] to [%s] on page %"Z"u",
+ indx, ptr,
+ mdb_dkey(&k2, kbuf2),
+ DKEY(key),
+ mp->mp_pgno));
+ }
+#endif
+
+ /* Sizes must be 2-byte aligned. */
+ ksize = EVEN(key->mv_size);
+ oksize = EVEN(node->mn_ksize);
+ delta = ksize - oksize;
+
+ /* Shift node contents if EVEN(key length) changed. */
+ if (delta) {
+ if (delta > 0 && SIZELEFT(mp) < delta) {
+ pgno_t pgno;
+ /* not enough space left, do a delete and split */
+ DPRINTF(("Not enough room, delta = %d, splitting...", delta));
+ pgno = NODEPGNO(node);
+ mdb_node_del(mc, 0);
+ return mdb_page_split(mc, key, NULL, pgno, MDB_SPLIT_REPLACE);
+ }
+
+ numkeys = NUMKEYS(mp);
+ for (i = 0; i < numkeys; i++) {
+ if (mp->mp_ptrs[i] <= ptr)
+ mp->mp_ptrs[i] -= delta;
+ }
+
+ base = (char *)mp + mp->mp_upper + PAGEBASE;
+ len = ptr - mp->mp_upper + NODESIZE;
+ memmove(base - delta, base, len);
+ mp->mp_upper -= delta;
+
+ node = NODEPTR(mp, indx);
+ }
+
+ /* But even if no shift was needed, update ksize */
+ if (node->mn_ksize != key->mv_size)
+ node->mn_ksize = key->mv_size;
+
+ if (key->mv_size)
+ memcpy(NODEKEY(node), key->mv_data, key->mv_size);
+
+ return MDB_SUCCESS;
+}
+
+static void
+mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst);
+
+/** Perform \b act while tracking temporary cursor \b mn */
+#define WITH_CURSOR_TRACKING(mn, act) do { \
+ MDB_cursor dummy, *tracked, **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \
+ if ((mn).mc_flags & C_SUB) { \
+ dummy.mc_flags = C_INITIALIZED; \
+ dummy.mc_xcursor = (MDB_xcursor *)&(mn); \
+ tracked = &dummy; \
+ } else { \
+ tracked = &(mn); \
+ } \
+ tracked->mc_next = *tp; \
+ *tp = tracked; \
+ { act; } \
+ *tp = tracked->mc_next; \
+} while (0)
+
+/** Move a node from csrc to cdst.
+ */
+static int
+mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
+{
+ MDB_node *srcnode;
+ MDB_val key, data;
+ pgno_t srcpg;
+ MDB_cursor mn;
+ int rc;
+ unsigned short flags;
+
+ DKBUF;
+
+ /* Mark src and dst as dirty. */
+ if ((rc = mdb_page_touch(csrc)) ||
+ (rc = mdb_page_touch(cdst)))
+ return rc;
+
+ if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
+ key.mv_size = csrc->mc_db->md_pad;
+ key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size);
+ data.mv_size = 0;
+ data.mv_data = NULL;
+ srcpg = 0;
+ flags = 0;
+ } else {
+ srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]);
+ mdb_cassert(csrc, !((size_t)srcnode & 1));
+ srcpg = NODEPGNO(srcnode);
+ flags = srcnode->mn_flags;
+ if (csrc->mc_ki[csrc->mc_top] == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
+ unsigned int snum = csrc->mc_snum;
+ MDB_node *s2;
+ /* must find the lowest key below src */
+ rc = mdb_page_search_lowest(csrc);
+ if (rc)
+ return rc;
+ if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
+ key.mv_size = csrc->mc_db->md_pad;
+ key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
+ } else {
+ s2 = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
+ key.mv_size = NODEKSZ(s2);
+ key.mv_data = NODEKEY(s2);
+ }
+ csrc->mc_snum = snum--;
+ csrc->mc_top = snum;
+ } else {
+ key.mv_size = NODEKSZ(srcnode);
+ key.mv_data = NODEKEY(srcnode);
+ }
+ data.mv_size = NODEDSZ(srcnode);
+ data.mv_data = NODEDATA(srcnode);
+ }
+ mn.mc_xcursor = NULL;
+ if (IS_BRANCH(cdst->mc_pg[cdst->mc_top]) && cdst->mc_ki[cdst->mc_top] == 0) {
+ unsigned int snum = cdst->mc_snum;
+ MDB_node *s2;
+ MDB_val bkey;
+ /* must find the lowest key below dst */
+ mdb_cursor_copy(cdst, &mn);
+ rc = mdb_page_search_lowest(&mn);
+ if (rc)
+ return rc;
+ if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
+ bkey.mv_size = mn.mc_db->md_pad;
+ bkey.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, bkey.mv_size);
+ } else {
+ s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
+ bkey.mv_size = NODEKSZ(s2);
+ bkey.mv_data = NODEKEY(s2);
+ }
+ mn.mc_snum = snum--;
+ mn.mc_top = snum;
+ mn.mc_ki[snum] = 0;
+ rc = mdb_update_key(&mn, &bkey);
+ if (rc)
+ return rc;
+ }
+
+ DPRINTF(("moving %s node %u [%s] on page %"Z"u to node %u on page %"Z"u",
+ IS_LEAF(csrc->mc_pg[csrc->mc_top]) ? "leaf" : "branch",
+ csrc->mc_ki[csrc->mc_top],
+ DKEY(&key),
+ csrc->mc_pg[csrc->mc_top]->mp_pgno,
+ cdst->mc_ki[cdst->mc_top], cdst->mc_pg[cdst->mc_top]->mp_pgno));
+
+ /* Add the node to the destination page.
+ */
+ rc = mdb_node_add(cdst, cdst->mc_ki[cdst->mc_top], &key, &data, srcpg, flags);
+ if (rc != MDB_SUCCESS)
+ return rc;
+
+ /* Delete the node from the source page.
+ */
+ mdb_node_del(csrc, key.mv_size);
+
+ {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = csrc->mc_dbi;
+ MDB_page *mpd, *mps;
+
+ mps = csrc->mc_pg[csrc->mc_top];
+ /* If we're adding on the left, bump others up */
+ if (fromleft) {
+ mpd = cdst->mc_pg[csrc->mc_top];
+ for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (csrc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
+ continue;
+ if (m3 != cdst &&
+ m3->mc_pg[csrc->mc_top] == mpd &&
+ m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) {
+ m3->mc_ki[csrc->mc_top]++;
+ }
+ if (m3 !=csrc &&
+ m3->mc_pg[csrc->mc_top] == mps &&
+ m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) {
+ m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top];
+ m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top];
+ m3->mc_ki[csrc->mc_top-1]++;
+ }
+ if (XCURSOR_INITED(m3) && IS_LEAF(mps))
+ XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]);
+ }
+ } else
+ /* Adding on the right, bump others down */
+ {
+ for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (csrc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (m3 == csrc) continue;
+ if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
+ continue;
+ if (m3->mc_pg[csrc->mc_top] == mps) {
+ if (!m3->mc_ki[csrc->mc_top]) {
+ m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top];
+ m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top];
+ m3->mc_ki[csrc->mc_top-1]--;
+ } else {
+ m3->mc_ki[csrc->mc_top]--;
+ }
+ if (XCURSOR_INITED(m3) && IS_LEAF(mps))
+ XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]);
+ }
+ }
+ }
+ }
+
+ /* Update the parent separators.
+ */
+ if (csrc->mc_ki[csrc->mc_top] == 0) {
+ if (csrc->mc_ki[csrc->mc_top-1] != 0) {
+ if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
+ key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
+ } else {
+ srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0);
+ key.mv_size = NODEKSZ(srcnode);
+ key.mv_data = NODEKEY(srcnode);
+ }
+ DPRINTF(("update separator for source page %"Z"u to [%s]",
+ csrc->mc_pg[csrc->mc_top]->mp_pgno, DKEY(&key)));
+ mdb_cursor_copy(csrc, &mn);
+ mn.mc_snum--;
+ mn.mc_top--;
+ /* We want mdb_rebalance to find mn when doing fixups */
+ WITH_CURSOR_TRACKING(mn,
+ rc = mdb_update_key(&mn, &key));
+ if (rc)
+ return rc;
+ }
+ if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
+ MDB_val nullkey;
+ indx_t ix = csrc->mc_ki[csrc->mc_top];
+ nullkey.mv_size = 0;
+ csrc->mc_ki[csrc->mc_top] = 0;
+ rc = mdb_update_key(csrc, &nullkey);
+ csrc->mc_ki[csrc->mc_top] = ix;
+ mdb_cassert(csrc, rc == MDB_SUCCESS);
+ }
+ }
+
+ if (cdst->mc_ki[cdst->mc_top] == 0) {
+ if (cdst->mc_ki[cdst->mc_top-1] != 0) {
+ if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
+ key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size);
+ } else {
+ srcnode = NODEPTR(cdst->mc_pg[cdst->mc_top], 0);
+ key.mv_size = NODEKSZ(srcnode);
+ key.mv_data = NODEKEY(srcnode);
+ }
+ DPRINTF(("update separator for destination page %"Z"u to [%s]",
+ cdst->mc_pg[cdst->mc_top]->mp_pgno, DKEY(&key)));
+ mdb_cursor_copy(cdst, &mn);
+ mn.mc_snum--;
+ mn.mc_top--;
+ /* We want mdb_rebalance to find mn when doing fixups */
+ WITH_CURSOR_TRACKING(mn,
+ rc = mdb_update_key(&mn, &key));
+ if (rc)
+ return rc;
+ }
+ if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) {
+ MDB_val nullkey;
+ indx_t ix = cdst->mc_ki[cdst->mc_top];
+ nullkey.mv_size = 0;
+ cdst->mc_ki[cdst->mc_top] = 0;
+ rc = mdb_update_key(cdst, &nullkey);
+ cdst->mc_ki[cdst->mc_top] = ix;
+ mdb_cassert(cdst, rc == MDB_SUCCESS);
+ }
+ }
+
+ return MDB_SUCCESS;
+}
+
+/** Merge one page into another.
+ * The nodes from the page pointed to by \b csrc will
+ * be copied to the page pointed to by \b cdst and then
+ * the \b csrc page will be freed.
+ * @param[in] csrc Cursor pointing to the source page.
+ * @param[in] cdst Cursor pointing to the destination page.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
+{
+ MDB_page *psrc, *pdst;
+ MDB_node *srcnode;
+ MDB_val key, data;
+ unsigned nkeys;
+ int rc;
+ indx_t i, j;
+
+ psrc = csrc->mc_pg[csrc->mc_top];
+ pdst = cdst->mc_pg[cdst->mc_top];
+
+ DPRINTF(("merging page %"Z"u into %"Z"u", psrc->mp_pgno, pdst->mp_pgno));
+
+ mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */
+ mdb_cassert(csrc, cdst->mc_snum > 1);
+
+ /* Mark dst as dirty. */
+ if ((rc = mdb_page_touch(cdst)))
+ return rc;
+
+ /* get dst page again now that we've touched it. */
+ pdst = cdst->mc_pg[cdst->mc_top];
+
+ /* Move all nodes from src to dst.
+ */
+ j = nkeys = NUMKEYS(pdst);
+ if (IS_LEAF2(psrc)) {
+ key.mv_size = csrc->mc_db->md_pad;
+ key.mv_data = METADATA(psrc);
+ for (i = 0; i < NUMKEYS(psrc); i++, j++) {
+ rc = mdb_node_add(cdst, j, &key, NULL, 0, 0);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ key.mv_data = (char *)key.mv_data + key.mv_size;
+ }
+ } else {
+ for (i = 0; i < NUMKEYS(psrc); i++, j++) {
+ srcnode = NODEPTR(psrc, i);
+ if (i == 0 && IS_BRANCH(psrc)) {
+ MDB_cursor mn;
+ MDB_node *s2;
+ mdb_cursor_copy(csrc, &mn);
+ mn.mc_xcursor = NULL;
+ /* must find the lowest key below src */
+ rc = mdb_page_search_lowest(&mn);
+ if (rc)
+ return rc;
+ if (IS_LEAF2(mn.mc_pg[mn.mc_top])) {
+ key.mv_size = mn.mc_db->md_pad;
+ key.mv_data = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.mv_size);
+ } else {
+ s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0);
+ key.mv_size = NODEKSZ(s2);
+ key.mv_data = NODEKEY(s2);
+ }
+ } else {
+ key.mv_size = srcnode->mn_ksize;
+ key.mv_data = NODEKEY(srcnode);
+ }
+
+ data.mv_size = NODEDSZ(srcnode);
+ data.mv_data = NODEDATA(srcnode);
+ rc = mdb_node_add(cdst, j, &key, &data, NODEPGNO(srcnode), srcnode->mn_flags);
+ if (rc != MDB_SUCCESS)
+ return rc;
+ }
+ }
+
+ DPRINTF(("dst page %"Z"u now has %u keys (%.1f%% filled)",
+ pdst->mp_pgno, NUMKEYS(pdst),
+ (float)PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10));
+
+ /* Unlink the src page from parent and add to free list.
+ */
+ csrc->mc_top--;
+ mdb_node_del(csrc, 0);
+ if (csrc->mc_ki[csrc->mc_top] == 0) {
+ key.mv_size = 0;
+ rc = mdb_update_key(csrc, &key);
+ if (rc) {
+ csrc->mc_top++;
+ return rc;
+ }
+ }
+ csrc->mc_top++;
+
+ psrc = csrc->mc_pg[csrc->mc_top];
+ /* If not operating on FreeDB, allow this page to be reused
+ * in this txn. Otherwise just add to free list.
+ */
+ rc = mdb_page_loose(csrc, psrc);
+ if (rc)
+ return rc;
+ if (IS_LEAF(psrc))
+ csrc->mc_db->md_leaf_pages--;
+ else
+ csrc->mc_db->md_branch_pages--;
+ {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = csrc->mc_dbi;
+ unsigned int top = csrc->mc_top;
+
+ for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (csrc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (m3 == csrc) continue;
+ if (m3->mc_snum < csrc->mc_snum) continue;
+ if (m3->mc_pg[top] == psrc) {
+ m3->mc_pg[top] = pdst;
+ m3->mc_ki[top] += nkeys;
+ m3->mc_ki[top-1] = cdst->mc_ki[top-1];
+ } else if (m3->mc_pg[top-1] == csrc->mc_pg[top-1] &&
+ m3->mc_ki[top-1] > csrc->mc_ki[top-1]) {
+ m3->mc_ki[top-1]--;
+ }
+ if (XCURSOR_INITED(m3) && IS_LEAF(psrc))
+ XCURSOR_REFRESH(m3, m3->mc_pg[top], m3->mc_ki[top]);
+ }
+ }
+ {
+ unsigned int snum = cdst->mc_snum;
+ uint16_t depth = cdst->mc_db->md_depth;
+ mdb_cursor_pop(cdst);
+ rc = mdb_rebalance(cdst);
+ /* Did the tree height change? */
+ if (depth != cdst->mc_db->md_depth)
+ snum += cdst->mc_db->md_depth - depth;
+ cdst->mc_snum = snum;
+ cdst->mc_top = snum-1;
+ }
+ return rc;
+}
+
+/** Copy the contents of a cursor.
+ * @param[in] csrc The cursor to copy from.
+ * @param[out] cdst The cursor to copy to.
+ */
+static void
+mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst)
+{
+ unsigned int i;
+
+ cdst->mc_txn = csrc->mc_txn;
+ cdst->mc_dbi = csrc->mc_dbi;
+ cdst->mc_db = csrc->mc_db;
+ cdst->mc_dbx = csrc->mc_dbx;
+ cdst->mc_snum = csrc->mc_snum;
+ cdst->mc_top = csrc->mc_top;
+ cdst->mc_flags = csrc->mc_flags;
+
+ for (i=0; i<csrc->mc_snum; i++) {
+ cdst->mc_pg[i] = csrc->mc_pg[i];
+ cdst->mc_ki[i] = csrc->mc_ki[i];
+ }
+}
+
+/** Rebalance the tree after a delete operation.
+ * @param[in] mc Cursor pointing to the page where rebalancing
+ * should begin.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_rebalance(MDB_cursor *mc)
+{
+ MDB_node *node;
+ int rc, fromleft;
+ unsigned int ptop, minkeys, thresh;
+ MDB_cursor mn;
+ indx_t oldki;
+
+ if (IS_BRANCH(mc->mc_pg[mc->mc_top])) {
+ minkeys = 2;
+ thresh = 1;
+ } else {
+ minkeys = 1;
+ thresh = FILL_THRESHOLD;
+ }
+ DPRINTF(("rebalancing %s page %"Z"u (has %u keys, %.1f%% full)",
+ IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch",
+ mdb_dbg_pgno(mc->mc_pg[mc->mc_top]), NUMKEYS(mc->mc_pg[mc->mc_top]),
+ (float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10));
+
+ if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= thresh &&
+ NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
+ DPRINTF(("no need to rebalance page %"Z"u, above fill threshold",
+ mdb_dbg_pgno(mc->mc_pg[mc->mc_top])));
+ return MDB_SUCCESS;
+ }
+
+ if (mc->mc_snum < 2) {
+ MDB_page *mp = mc->mc_pg[0];
+ if (IS_SUBP(mp)) {
+ DPUTS("Can't rebalance a subpage, ignoring");
+ return MDB_SUCCESS;
+ }
+ if (NUMKEYS(mp) == 0) {
+ DPUTS("tree is completely empty");
+ mc->mc_db->md_root = P_INVALID;
+ mc->mc_db->md_depth = 0;
+ mc->mc_db->md_leaf_pages = 0;
+ rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
+ if (rc)
+ return rc;
+ /* Adjust cursors pointing to mp */
+ mc->mc_snum = 0;
+ mc->mc_top = 0;
+ mc->mc_flags &= ~C_INITIALIZED;
+ {
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = mc->mc_dbi;
+
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (mc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum))
+ continue;
+ if (m3->mc_pg[0] == mp) {
+ m3->mc_snum = 0;
+ m3->mc_top = 0;
+ m3->mc_flags &= ~C_INITIALIZED;
+ }
+ }
+ }
+ } else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
+ int i;
+ DPUTS("collapsing root page!");
+ rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
+ if (rc)
+ return rc;
+ mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
+ rc = mdb_page_get(mc, mc->mc_db->md_root, &mc->mc_pg[0], NULL);
+ if (rc)
+ return rc;
+ mc->mc_db->md_depth--;
+ mc->mc_db->md_branch_pages--;
+ mc->mc_ki[0] = mc->mc_ki[1];
+ for (i = 1; i<mc->mc_db->md_depth; i++) {
+ mc->mc_pg[i] = mc->mc_pg[i+1];
+ mc->mc_ki[i] = mc->mc_ki[i+1];
+ }
+ {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = mc->mc_dbi;
+
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (mc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (m3 == mc) continue;
+ if (!(m3->mc_flags & C_INITIALIZED))
+ continue;
+ if (m3->mc_pg[0] == mp) {
+ for (i=0; i<mc->mc_db->md_depth; i++) {
+ m3->mc_pg[i] = m3->mc_pg[i+1];
+ m3->mc_ki[i] = m3->mc_ki[i+1];
+ }
+ m3->mc_snum--;
+ m3->mc_top--;
+ }
+ }
+ }
+ } else
+ DPUTS("root page doesn't need rebalancing");
+ return MDB_SUCCESS;
+ }
+
+ /* The parent (branch page) must have at least 2 pointers,
+ * otherwise the tree is invalid.
+ */
+ ptop = mc->mc_top-1;
+ mdb_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1);
+
+ /* Leaf page fill factor is below the threshold.
+ * Try to move keys from left or right neighbor, or
+ * merge with a neighbor page.
+ */
+
+ /* Find neighbors.
+ */
+ mdb_cursor_copy(mc, &mn);
+ mn.mc_xcursor = NULL;
+
+ oldki = mc->mc_ki[mc->mc_top];
+ if (mc->mc_ki[ptop] == 0) {
+ /* We're the leftmost leaf in our parent.
+ */
+ DPUTS("reading right neighbor");
+ mn.mc_ki[ptop]++;
+ node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]);
+ rc = mdb_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL);
+ if (rc)
+ return rc;
+ mn.mc_ki[mn.mc_top] = 0;
+ mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]);
+ fromleft = 0;
+ } else {
+ /* There is at least one neighbor to the left.
+ */
+ DPUTS("reading left neighbor");
+ mn.mc_ki[ptop]--;
+ node = NODEPTR(mc->mc_pg[ptop], mn.mc_ki[ptop]);
+ rc = mdb_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL);
+ if (rc)
+ return rc;
+ mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1;
+ mc->mc_ki[mc->mc_top] = 0;
+ fromleft = 1;
+ }
+
+ DPRINTF(("found neighbor page %"Z"u (%u keys, %.1f%% full)",
+ mn.mc_pg[mn.mc_top]->mp_pgno, NUMKEYS(mn.mc_pg[mn.mc_top]),
+ (float)PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) / 10));
+
+ /* If the neighbor page is above threshold and has enough keys,
+ * move one key from it. Otherwise we should try to merge them.
+ * (A branch page must never have less than 2 keys.)
+ */
+ if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= thresh && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) {
+ rc = mdb_node_move(&mn, mc, fromleft);
+ if (fromleft) {
+ /* if we inserted on left, bump position up */
+ oldki++;
+ }
+ } else {
+ if (!fromleft) {
+ rc = mdb_page_merge(&mn, mc);
+ } else {
+ oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
+ mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
+ /* We want mdb_rebalance to find mn when doing fixups */
+ WITH_CURSOR_TRACKING(mn,
+ rc = mdb_page_merge(mc, &mn));
+ mdb_cursor_copy(&mn, mc);
+ }
+ mc->mc_flags &= ~C_EOF;
+ }
+ mc->mc_ki[mc->mc_top] = oldki;
+ return rc;
+}
+
+/** Complete a delete operation started by #mdb_cursor_del(). */
+static int
+mdb_cursor_del0(MDB_cursor *mc)
+{
+ int rc;
+ MDB_page *mp;
+ indx_t ki;
+ unsigned int nkeys;
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = mc->mc_dbi;
+
+ ki = mc->mc_ki[mc->mc_top];
+ mp = mc->mc_pg[mc->mc_top];
+ mdb_node_del(mc, mc->mc_db->md_pad);
+ mc->mc_db->md_entries--;
+ {
+ /* Adjust other cursors pointing to mp */
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
+ if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED))
+ continue;
+ if (m3 == mc || m3->mc_snum < mc->mc_snum)
+ continue;
+ if (m3->mc_pg[mc->mc_top] == mp) {
+ if (m3->mc_ki[mc->mc_top] == ki) {
+ m3->mc_flags |= C_DEL;
+ if (mc->mc_db->md_flags & MDB_DUPSORT) {
+ /* Sub-cursor referred into dataset which is gone */
+ m3->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED|C_EOF);
+ }
+ continue;
+ } else if (m3->mc_ki[mc->mc_top] > ki) {
+ m3->mc_ki[mc->mc_top]--;
+ }
+ if (XCURSOR_INITED(m3))
+ XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
+ }
+ }
+ }
+ rc = mdb_rebalance(mc);
+
+ if (rc == MDB_SUCCESS) {
+ /* DB is totally empty now, just bail out.
+ * Other cursors adjustments were already done
+ * by mdb_rebalance and aren't needed here.
+ */
+ if (!mc->mc_snum)
+ return rc;
+
+ mp = mc->mc_pg[mc->mc_top];
+ nkeys = NUMKEYS(mp);
+
+ /* Adjust other cursors pointing to mp */
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) {
+ m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
+ if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED))
+ continue;
+ if (m3->mc_snum < mc->mc_snum)
+ continue;
+ if (m3->mc_pg[mc->mc_top] == mp) {
+ /* if m3 points past last node in page, find next sibling */
+ if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) {
+ if (m3->mc_ki[mc->mc_top] >= nkeys) {
+ rc = mdb_cursor_sibling(m3, 1);
+ if (rc == MDB_NOTFOUND) {
+ m3->mc_flags |= C_EOF;
+ rc = MDB_SUCCESS;
+ continue;
+ }
+ }
+ if (mc->mc_db->md_flags & MDB_DUPSORT) {
+ MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]);
+ /* If this node has dupdata, it may need to be reinited
+ * because its data has moved.
+ * If the xcursor was not initd it must be reinited.
+ * Else if node points to a subDB, nothing is needed.
+ * Else (xcursor was initd, not a subDB) needs mc_pg[0] reset.
+ */
+ if (node->mn_flags & F_DUPDATA) {
+ if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
+ if (!(node->mn_flags & F_SUBDATA))
+ m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node);
+ } else
+ mdb_xcursor_init1(m3, node);
+ }
+ }
+ }
+ }
+ }
+ mc->mc_flags |= C_DEL;
+ }
+
+ if (rc)
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+int
+mdb_del(MDB_txn *txn, MDB_dbi dbi,
+ MDB_val *key, MDB_val *data)
+{
+ if (!key || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
+ return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+
+ if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
+ /* must ignore any data */
+ data = NULL;
+ }
+
+ return mdb_del0(txn, dbi, key, data, 0);
+}
+
+static int
+mdb_del0(MDB_txn *txn, MDB_dbi dbi,
+ MDB_val *key, MDB_val *data, unsigned flags)
+{
+ MDB_cursor mc;
+ MDB_xcursor mx;
+ MDB_cursor_op op;
+ MDB_val rdata, *xdata;
+ int rc, exact = 0;
+ DKBUF;
+
+ DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
+
+ mdb_cursor_init(&mc, txn, dbi, &mx);
+
+ if (data) {
+ op = MDB_GET_BOTH;
+ rdata = *data;
+ xdata = &rdata;
+ } else {
+ op = MDB_SET;
+ xdata = NULL;
+ flags |= MDB_NODUPDATA;
+ }
+ rc = mdb_cursor_set(&mc, key, xdata, op, &exact);
+ if (rc == 0) {
+ /* let mdb_page_split know about this cursor if needed:
+ * delete will trigger a rebalance; if it needs to move
+ * a node from one page to another, it will have to
+ * update the parent's separator key(s). If the new sepkey
+ * is larger than the current one, the parent page may
+ * run out of space, triggering a split. We need this
+ * cursor to be consistent until the end of the rebalance.
+ */
+ mc.mc_flags |= C_UNTRACK;
+ mc.mc_next = txn->mt_cursors[dbi];
+ txn->mt_cursors[dbi] = &mc;
+ rc = mdb_cursor_del(&mc, flags);
+ txn->mt_cursors[dbi] = mc.mc_next;
+ }
+ return rc;
+}
+
+/** Split a page and insert a new node.
+ * Set #MDB_TXN_ERROR on failure.
+ * @param[in,out] mc Cursor pointing to the page and desired insertion index.
+ * The cursor will be updated to point to the actual page and index where
+ * the node got inserted after the split.
+ * @param[in] newkey The key for the newly inserted node.
+ * @param[in] newdata The data for the newly inserted node.
+ * @param[in] newpgno The page number, if the new node is a branch node.
+ * @param[in] nflags The #NODE_ADD_FLAGS for the new node.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno,
+ unsigned int nflags)
+{
+ unsigned int flags;
+ int rc = MDB_SUCCESS, new_root = 0, did_split = 0;
+ indx_t newindx;
+ pgno_t pgno = 0;
+ int i, j, split_indx, nkeys, pmax;
+ MDB_env *env = mc->mc_txn->mt_env;
+ MDB_node *node;
+ MDB_val sepkey, rkey, xdata, *rdata = &xdata;
+ MDB_page *copy = NULL;
+ MDB_page *mp, *rp, *pp;
+ int ptop;
+ MDB_cursor mn;
+ DKBUF;
+
+ mp = mc->mc_pg[mc->mc_top];
+ newindx = mc->mc_ki[mc->mc_top];
+ nkeys = NUMKEYS(mp);
+
+ DPRINTF(("-----> splitting %s page %"Z"u and adding [%s] at index %i/%i",
+ IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno,
+ DKEY(newkey), mc->mc_ki[mc->mc_top], nkeys));
+
+ /* Create a right sibling. */
+ if ((rc = mdb_page_new(mc, mp->mp_flags, 1, &rp)))
+ return rc;
+ rp->mp_pad = mp->mp_pad;
+ DPRINTF(("new right sibling: page %"Z"u", rp->mp_pgno));
+
+ /* Usually when splitting the root page, the cursor
+ * height is 1. But when called from mdb_update_key,
+ * the cursor height may be greater because it walks
+ * up the stack while finding the branch slot to update.
+ */
+ if (mc->mc_top < 1) {
+ if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp)))
+ goto done;
+ /* shift current top to make room for new parent */
+ for (i=mc->mc_snum; i>0; i--) {
+ mc->mc_pg[i] = mc->mc_pg[i-1];
+ mc->mc_ki[i] = mc->mc_ki[i-1];
+ }
+ mc->mc_pg[0] = pp;
+ mc->mc_ki[0] = 0;
+ mc->mc_db->md_root = pp->mp_pgno;
+ DPRINTF(("root split! new root = %"Z"u", pp->mp_pgno));
+ new_root = mc->mc_db->md_depth++;
+
+ /* Add left (implicit) pointer. */
+ if ((rc = mdb_node_add(mc, 0, NULL, NULL, mp->mp_pgno, 0)) != MDB_SUCCESS) {
+ /* undo the pre-push */
+ mc->mc_pg[0] = mc->mc_pg[1];
+ mc->mc_ki[0] = mc->mc_ki[1];
+ mc->mc_db->md_root = mp->mp_pgno;
+ mc->mc_db->md_depth--;
+ goto done;
+ }
+ mc->mc_snum++;
+ mc->mc_top++;
+ ptop = 0;
+ } else {
+ ptop = mc->mc_top-1;
+ DPRINTF(("parent branch page is %"Z"u", mc->mc_pg[ptop]->mp_pgno));
+ }
+
+ mdb_cursor_copy(mc, &mn);
+ mn.mc_xcursor = NULL;
+ mn.mc_pg[mn.mc_top] = rp;
+ mn.mc_ki[ptop] = mc->mc_ki[ptop]+1;
+
+ if (nflags & MDB_APPEND) {
+ mn.mc_ki[mn.mc_top] = 0;
+ sepkey = *newkey;
+ split_indx = newindx;
+ nkeys = 0;
+ } else {
+
+ split_indx = (nkeys+1) / 2;
+
+ if (IS_LEAF2(rp)) {
+ char *split, *ins;
+ int x;
+ unsigned int lsize, rsize, ksize;
+ /* Move half of the keys to the right sibling */
+ x = mc->mc_ki[mc->mc_top] - split_indx;
+ ksize = mc->mc_db->md_pad;
+ split = LEAF2KEY(mp, split_indx, ksize);
+ rsize = (nkeys - split_indx) * ksize;
+ lsize = (nkeys - split_indx) * sizeof(indx_t);
+ mp->mp_lower -= lsize;
+ rp->mp_lower += lsize;
+ mp->mp_upper += rsize - lsize;
+ rp->mp_upper -= rsize - lsize;
+ sepkey.mv_size = ksize;
+ if (newindx == split_indx) {
+ sepkey.mv_data = newkey->mv_data;
+ } else {
+ sepkey.mv_data = split;
+ }
+ if (x<0) {
+ ins = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], ksize);
+ memcpy(rp->mp_ptrs, split, rsize);
+ sepkey.mv_data = rp->mp_ptrs;
+ memmove(ins+ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize);
+ memcpy(ins, newkey->mv_data, ksize);
+ mp->mp_lower += sizeof(indx_t);
+ mp->mp_upper -= ksize - sizeof(indx_t);
+ } else {
+ if (x)
+ memcpy(rp->mp_ptrs, split, x * ksize);
+ ins = LEAF2KEY(rp, x, ksize);
+ memcpy(ins, newkey->mv_data, ksize);
+ memcpy(ins+ksize, split + x * ksize, rsize - x * ksize);
+ rp->mp_lower += sizeof(indx_t);
+ rp->mp_upper -= ksize - sizeof(indx_t);
+ mc->mc_ki[mc->mc_top] = x;
+ }
+ } else {
+ int psize, nsize, k;
+ /* Maximum free space in an empty page */
+ pmax = env->me_psize - PAGEHDRSZ;
+ if (IS_LEAF(mp))
+ nsize = mdb_leaf_size(env, newkey, newdata);
+ else
+ nsize = mdb_branch_size(env, newkey);
+ nsize = EVEN(nsize);
+
+ /* grab a page to hold a temporary copy */
+ copy = mdb_page_malloc(mc->mc_txn, 1);
+ if (copy == NULL) {
+ rc = ENOMEM;
+ goto done;
+ }
+ copy->mp_pgno = mp->mp_pgno;
+ copy->mp_flags = mp->mp_flags;
+ copy->mp_lower = (PAGEHDRSZ-PAGEBASE);
+ copy->mp_upper = env->me_psize - PAGEBASE;
+
+ /* prepare to insert */
+ for (i=0, j=0; i<nkeys; i++) {
+ if (i == newindx) {
+ copy->mp_ptrs[j++] = 0;
+ }
+ copy->mp_ptrs[j++] = mp->mp_ptrs[i];
+ }
+
+ /* When items are relatively large the split point needs
+ * to be checked, because being off-by-one will make the
+ * difference between success or failure in mdb_node_add.
+ *
+ * It's also relevant if a page happens to be laid out
+ * such that one half of its nodes are all "small" and
+ * the other half of its nodes are "large." If the new
+ * item is also "large" and falls on the half with
+ * "large" nodes, it also may not fit.
+ *
+ * As a final tweak, if the new item goes on the last
+ * spot on the page (and thus, onto the new page), bias
+ * the split so the new page is emptier than the old page.
+ * This yields better packing during sequential inserts.
+ */
+ if (nkeys < 20 || nsize > pmax/16 || newindx >= nkeys) {
+ /* Find split point */
+ psize = 0;
+ if (newindx <= split_indx || newindx >= nkeys) {
+ i = 0; j = 1;
+ k = newindx >= nkeys ? nkeys : split_indx+1+IS_LEAF(mp);
+ } else {
+ i = nkeys; j = -1;
+ k = split_indx-1;
+ }
+ for (; i!=k; i+=j) {
+ if (i == newindx) {
+ psize += nsize;
+ node = NULL;
+ } else {
+ node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE);
+ psize += NODESIZE + NODEKSZ(node) + sizeof(indx_t);
+ if (IS_LEAF(mp)) {
+ if (F_ISSET(node->mn_flags, F_BIGDATA))
+ psize += sizeof(pgno_t);
+ else
+ psize += NODEDSZ(node);
+ }
+ psize = EVEN(psize);
+ }
+ if (psize > pmax || i == k-j) {
+ split_indx = i + (j<0);
+ break;
+ }
+ }
+ }
+ if (split_indx == newindx) {
+ sepkey.mv_size = newkey->mv_size;
+ sepkey.mv_data = newkey->mv_data;
+ } else {
+ node = (MDB_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEBASE);
+ sepkey.mv_size = node->mn_ksize;
+ sepkey.mv_data = NODEKEY(node);
+ }
+ }
+ }
+
+ DPRINTF(("separator is %d [%s]", split_indx, DKEY(&sepkey)));
+
+ /* Copy separator key to the parent.
+ */
+ if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) {
+ int snum = mc->mc_snum;
+ mn.mc_snum--;
+ mn.mc_top--;
+ did_split = 1;
+ /* We want other splits to find mn when doing fixups */
+ WITH_CURSOR_TRACKING(mn,
+ rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0));
+ if (rc)
+ goto done;
+
+ /* root split? */
+ if (mc->mc_snum > snum) {
+ ptop++;
+ }
+ /* Right page might now have changed parent.
+ * Check if left page also changed parent.
+ */
+ if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
+ mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
+ for (i=0; i<ptop; i++) {
+ mc->mc_pg[i] = mn.mc_pg[i];
+ mc->mc_ki[i] = mn.mc_ki[i];
+ }
+ mc->mc_pg[ptop] = mn.mc_pg[ptop];
+ if (mn.mc_ki[ptop]) {
+ mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
+ } else {
+ /* find right page's left sibling */
+ mc->mc_ki[ptop] = mn.mc_ki[ptop];
+ mdb_cursor_sibling(mc, 0);
+ }
+ }
+ } else {
+ mn.mc_top--;
+ rc = mdb_node_add(&mn, mn.mc_ki[ptop], &sepkey, NULL, rp->mp_pgno, 0);
+ mn.mc_top++;
+ }
+ if (rc != MDB_SUCCESS) {
+ goto done;
+ }
+ if (nflags & MDB_APPEND) {
+ mc->mc_pg[mc->mc_top] = rp;
+ mc->mc_ki[mc->mc_top] = 0;
+ rc = mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags);
+ if (rc)
+ goto done;
+ for (i=0; i<mc->mc_top; i++)
+ mc->mc_ki[i] = mn.mc_ki[i];
+ } else if (!IS_LEAF2(mp)) {
+ /* Move nodes */
+ mc->mc_pg[mc->mc_top] = rp;
+ i = split_indx;
+ j = 0;
+ do {
+ if (i == newindx) {
+ rkey.mv_data = newkey->mv_data;
+ rkey.mv_size = newkey->mv_size;
+ if (IS_LEAF(mp)) {
+ rdata = newdata;
+ } else
+ pgno = newpgno;
+ flags = nflags;
+ /* Update index for the new key. */
+ mc->mc_ki[mc->mc_top] = j;
+ } else {
+ node = (MDB_node *)((char *)mp + copy->mp_ptrs[i] + PAGEBASE);
+ rkey.mv_data = NODEKEY(node);
+ rkey.mv_size = node->mn_ksize;
+ if (IS_LEAF(mp)) {
+ xdata.mv_data = NODEDATA(node);
+ xdata.mv_size = NODEDSZ(node);
+ rdata = &xdata;
+ } else
+ pgno = NODEPGNO(node);
+ flags = node->mn_flags;
+ }
+
+ if (!IS_LEAF(mp) && j == 0) {
+ /* First branch index doesn't need key data. */
+ rkey.mv_size = 0;
+ }
+
+ rc = mdb_node_add(mc, j, &rkey, rdata, pgno, flags);
+ if (rc)
+ goto done;
+ if (i == nkeys) {
+ i = 0;
+ j = 0;
+ mc->mc_pg[mc->mc_top] = copy;
+ } else {
+ i++;
+ j++;
+ }
+ } while (i != split_indx);
+
+ nkeys = NUMKEYS(copy);
+ for (i=0; i<nkeys; i++)
+ mp->mp_ptrs[i] = copy->mp_ptrs[i];
+ mp->mp_lower = copy->mp_lower;
+ mp->mp_upper = copy->mp_upper;
+ memcpy(NODEPTR(mp, nkeys-1), NODEPTR(copy, nkeys-1),
+ env->me_psize - copy->mp_upper - PAGEBASE);
+
+ /* reset back to original page */
+ if (newindx < split_indx) {
+ mc->mc_pg[mc->mc_top] = mp;
+ } else {
+ mc->mc_pg[mc->mc_top] = rp;
+ mc->mc_ki[ptop]++;
+ /* Make sure mc_ki is still valid.
+ */
+ if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
+ mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
+ for (i=0; i<=ptop; i++) {
+ mc->mc_pg[i] = mn.mc_pg[i];
+ mc->mc_ki[i] = mn.mc_ki[i];
+ }
+ }
+ }
+ if (nflags & MDB_RESERVE) {
+ node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
+ if (!(node->mn_flags & F_BIGDATA))
+ newdata->mv_data = NODEDATA(node);
+ }
+ } else {
+ if (newindx >= split_indx) {
+ mc->mc_pg[mc->mc_top] = rp;
+ mc->mc_ki[ptop]++;
+ /* Make sure mc_ki is still valid.
+ */
+ if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
+ mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
+ for (i=0; i<=ptop; i++) {
+ mc->mc_pg[i] = mn.mc_pg[i];
+ mc->mc_ki[i] = mn.mc_ki[i];
+ }
+ }
+ }
+ }
+
+ {
+ /* Adjust other cursors pointing to mp */
+ MDB_cursor *m2, *m3;
+ MDB_dbi dbi = mc->mc_dbi;
+ nkeys = NUMKEYS(mp);
+
+ for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
+ if (mc->mc_flags & C_SUB)
+ m3 = &m2->mc_xcursor->mx_cursor;
+ else
+ m3 = m2;
+ if (m3 == mc)
+ continue;
+ if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED))
+ continue;
+ if (new_root) {
+ int k;
+ /* sub cursors may be on different DB */
+ if (m3->mc_pg[0] != mp)
+ continue;
+ /* root split */
+ for (k=new_root; k>=0; k--) {
+ m3->mc_ki[k+1] = m3->mc_ki[k];
+ m3->mc_pg[k+1] = m3->mc_pg[k];
+ }
+ if (m3->mc_ki[0] >= nkeys) {
+ m3->mc_ki[0] = 1;
+ } else {
+ m3->mc_ki[0] = 0;
+ }
+ m3->mc_pg[0] = mc->mc_pg[0];
+ m3->mc_snum++;
+ m3->mc_top++;
+ }
+ if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) {
+ if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDB_SPLIT_REPLACE))
+ m3->mc_ki[mc->mc_top]++;
+ if (m3->mc_ki[mc->mc_top] >= nkeys) {
+ m3->mc_pg[mc->mc_top] = rp;
+ m3->mc_ki[mc->mc_top] -= nkeys;
+ for (i=0; i<mc->mc_top; i++) {
+ m3->mc_ki[i] = mn.mc_ki[i];
+ m3->mc_pg[i] = mn.mc_pg[i];
+ }
+ }
+ } else if (!did_split && m3->mc_top >= ptop && m3->mc_pg[ptop] == mc->mc_pg[ptop] &&
+ m3->mc_ki[ptop] >= mc->mc_ki[ptop]) {
+ m3->mc_ki[ptop]++;
+ }
+ if (XCURSOR_INITED(m3) && IS_LEAF(mp))
+ XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]);
+ }
+ }
+ DPRINTF(("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp)));
+
+done:
+ if (copy) /* tmp page */
+ mdb_page_free(env, copy);
+ if (rc)
+ mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
+ return rc;
+}
+
+int
+mdb_put(MDB_txn *txn, MDB_dbi dbi,
+ MDB_val *key, MDB_val *data, unsigned int flags)
+{
+ MDB_cursor mc;
+ MDB_xcursor mx;
+ int rc;
+
+ if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP))
+ return EINVAL;
+
+ if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
+ return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
+
+ mdb_cursor_init(&mc, txn, dbi, &mx);
+ mc.mc_next = txn->mt_cursors[dbi];
+ txn->mt_cursors[dbi] = &mc;
+ rc = mdb_cursor_put(&mc, key, data, flags);
+ txn->mt_cursors[dbi] = mc.mc_next;
+ return rc;
+}
+
+#ifndef MDB_WBUF
+#define MDB_WBUF (1024*1024)
+#endif
+#define MDB_EOF 0x10 /**< #mdb_env_copyfd1() is done reading */
+
+ /** State needed for a double-buffering compacting copy. */
+typedef struct mdb_copy {
+ MDB_env *mc_env;
+ MDB_txn *mc_txn;
+ pthread_mutex_t mc_mutex;
+ pthread_cond_t mc_cond; /**< Condition variable for #mc_new */
+ char *mc_wbuf[2];
+ char *mc_over[2];
+ int mc_wlen[2];
+ int mc_olen[2];
+ pgno_t mc_next_pgno;
+ HANDLE mc_fd;
+ int mc_toggle; /**< Buffer number in provider */
+ int mc_new; /**< (0-2 buffers to write) | (#MDB_EOF at end) */
+ /** Error code. Never cleared if set. Both threads can set nonzero
+ * to fail the copy. Not mutex-protected, LMDB expects atomic int.
+ */
+ volatile int mc_error;
+} mdb_copy;
+
+ /** Dedicated writer thread for compacting copy. */
+static THREAD_RET ESECT CALL_CONV
+mdb_env_copythr(void *arg)
+{
+ mdb_copy *my = arg;
+ char *ptr;
+ int toggle = 0, wsize, rc;
+#ifdef _WIN32
+ DWORD len;
+#define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL)
+#else
+ int len;
+#define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0)
+#ifdef SIGPIPE
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ if ((rc = pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
+ my->mc_error = rc;
+#endif
+#endif
+
+ pthread_mutex_lock(&my->mc_mutex);
+ for(;;) {
+ while (!my->mc_new)
+ pthread_cond_wait(&my->mc_cond, &my->mc_mutex);
+ if (my->mc_new == 0 + MDB_EOF) /* 0 buffers, just EOF */
+ break;
+ wsize = my->mc_wlen[toggle];
+ ptr = my->mc_wbuf[toggle];
+again:
+ rc = MDB_SUCCESS;
+ while (wsize > 0 && !my->mc_error) {
+ DO_WRITE(rc, my->mc_fd, ptr, wsize, len);
+ if (!rc) {
+ rc = ErrCode();
+#if defined(SIGPIPE) && !defined(_WIN32)
+ if (rc == EPIPE) {
+ /* Collect the pending SIGPIPE, otherwise at least OS X
+ * gives it to the process on thread-exit (ITS#8504).
+ */
+ int tmp;
+ sigwait(&set, &tmp);
+ }
+#endif
+ break;
+ } else if (len > 0) {
+ rc = MDB_SUCCESS;
+ ptr += len;
+ wsize -= len;
+ continue;
+ } else {
+ rc = EIO;
+ break;
+ }
+ }
+ if (rc) {
+ my->mc_error = rc;
+ }
+ /* If there's an overflow page tail, write it too */
+ if (my->mc_olen[toggle]) {
+ wsize = my->mc_olen[toggle];
+ ptr = my->mc_over[toggle];
+ my->mc_olen[toggle] = 0;
+ goto again;
+ }
+ my->mc_wlen[toggle] = 0;
+ toggle ^= 1;
+ /* Return the empty buffer to provider */
+ my->mc_new--;
+ pthread_cond_signal(&my->mc_cond);
+ }
+ pthread_mutex_unlock(&my->mc_mutex);
+ return (THREAD_RET)0;
+#undef DO_WRITE
+}
+
+ /** Give buffer and/or #MDB_EOF to writer thread, await unused buffer.
+ *
+ * @param[in] my control structure.
+ * @param[in] adjust (1 to hand off 1 buffer) | (MDB_EOF when ending).
+ */
+static int ESECT
+mdb_env_cthr_toggle(mdb_copy *my, int adjust)
+{
+ pthread_mutex_lock(&my->mc_mutex);
+ my->mc_new += adjust;
+ pthread_cond_signal(&my->mc_cond);
+ while (my->mc_new & 2) /* both buffers in use */
+ pthread_cond_wait(&my->mc_cond, &my->mc_mutex);
+ pthread_mutex_unlock(&my->mc_mutex);
+
+ my->mc_toggle ^= (adjust & 1);
+ /* Both threads reset mc_wlen, to be safe from threading errors */
+ my->mc_wlen[my->mc_toggle] = 0;
+ return my->mc_error;
+}
+
+ /** Depth-first tree traversal for compacting copy.
+ * @param[in] my control structure.
+ * @param[in,out] pg database root.
+ * @param[in] flags includes #F_DUPDATA if it is a sorted-duplicate sub-DB.
+ */
+static int ESECT
+mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
+{
+ MDB_cursor mc = {0};
+ MDB_node *ni;
+ MDB_page *mo, *mp, *leaf;
+ char *buf, *ptr;
+ int rc, toggle;
+ unsigned int i;
+
+ /* Empty DB, nothing to do */
+ if (*pg == P_INVALID)
+ return MDB_SUCCESS;
+
+ mc.mc_snum = 1;
+ mc.mc_txn = my->mc_txn;
+
+ rc = mdb_page_get(&mc, *pg, &mc.mc_pg[0], NULL);
+ if (rc)
+ return rc;
+ rc = mdb_page_search_root(&mc, NULL, MDB_PS_FIRST);
+ if (rc)
+ return rc;
+
+ /* Make cursor pages writable */
+ buf = ptr = malloc(my->mc_env->me_psize * mc.mc_snum);
+ if (buf == NULL)
+ return ENOMEM;
+
+ for (i=0; i<mc.mc_top; i++) {
+ mdb_page_copy((MDB_page *)ptr, mc.mc_pg[i], my->mc_env->me_psize);
+ mc.mc_pg[i] = (MDB_page *)ptr;
+ ptr += my->mc_env->me_psize;
+ }
+
+ /* This is writable space for a leaf page. Usually not needed. */
+ leaf = (MDB_page *)ptr;
+
+ toggle = my->mc_toggle;
+ while (mc.mc_snum > 0) {
+ unsigned n;
+ mp = mc.mc_pg[mc.mc_top];
+ n = NUMKEYS(mp);
+
+ if (IS_LEAF(mp)) {
+ if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) {
+ for (i=0; i<n; i++) {
+ ni = NODEPTR(mp, i);
+ if (ni->mn_flags & F_BIGDATA) {
+ MDB_page *omp;
+ pgno_t pg;
+
+ /* Need writable leaf */
+ if (mp != leaf) {
+ mc.mc_pg[mc.mc_top] = leaf;
+ mdb_page_copy(leaf, mp, my->mc_env->me_psize);
+ mp = leaf;
+ ni = NODEPTR(mp, i);
+ }
+
+ memcpy(&pg, NODEDATA(ni), sizeof(pg));
+ memcpy(NODEDATA(ni), &my->mc_next_pgno, sizeof(pgno_t));
+ rc = mdb_page_get(&mc, pg, &omp, NULL);
+ if (rc)
+ goto done;
+ if (my->mc_wlen[toggle] >= MDB_WBUF) {
+ rc = mdb_env_cthr_toggle(my, 1);
+ if (rc)
+ goto done;
+ toggle = my->mc_toggle;
+ }
+ mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]);
+ memcpy(mo, omp, my->mc_env->me_psize);
+ mo->mp_pgno = my->mc_next_pgno;
+ my->mc_next_pgno += omp->mp_pages;
+ my->mc_wlen[toggle] += my->mc_env->me_psize;
+ if (omp->mp_pages > 1) {
+ my->mc_olen[toggle] = my->mc_env->me_psize * (omp->mp_pages - 1);
+ my->mc_over[toggle] = (char *)omp + my->mc_env->me_psize;
+ rc = mdb_env_cthr_toggle(my, 1);
+ if (rc)
+ goto done;
+ toggle = my->mc_toggle;
+ }
+ } else if (ni->mn_flags & F_SUBDATA) {
+ MDB_db db;
+
+ /* Need writable leaf */
+ if (mp != leaf) {
+ mc.mc_pg[mc.mc_top] = leaf;
+ mdb_page_copy(leaf, mp, my->mc_env->me_psize);
+ mp = leaf;
+ ni = NODEPTR(mp, i);
+ }
+
+ memcpy(&db, NODEDATA(ni), sizeof(db));
+ my->mc_toggle = toggle;
+ rc = mdb_env_cwalk(my, &db.md_root, ni->mn_flags & F_DUPDATA);
+ if (rc)
+ goto done;
+ toggle = my->mc_toggle;
+ memcpy(NODEDATA(ni), &db, sizeof(db));
+ }
+ }
+ }
+ } else {
+ mc.mc_ki[mc.mc_top]++;
+ if (mc.mc_ki[mc.mc_top] < n) {
+ pgno_t pg;
+again:
+ ni = NODEPTR(mp, mc.mc_ki[mc.mc_top]);
+ pg = NODEPGNO(ni);
+ rc = mdb_page_get(&mc, pg, &mp, NULL);
+ if (rc)
+ goto done;
+ mc.mc_top++;
+ mc.mc_snum++;
+ mc.mc_ki[mc.mc_top] = 0;
+ if (IS_BRANCH(mp)) {
+ /* Whenever we advance to a sibling branch page,
+ * we must proceed all the way down to its first leaf.
+ */
+ mdb_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize);
+ goto again;
+ } else
+ mc.mc_pg[mc.mc_top] = mp;
+ continue;
+ }
+ }
+ if (my->mc_wlen[toggle] >= MDB_WBUF) {
+ rc = mdb_env_cthr_toggle(my, 1);
+ if (rc)
+ goto done;
+ toggle = my->mc_toggle;
+ }
+ mo = (MDB_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]);
+ mdb_page_copy(mo, mp, my->mc_env->me_psize);
+ mo->mp_pgno = my->mc_next_pgno++;
+ my->mc_wlen[toggle] += my->mc_env->me_psize;
+ if (mc.mc_top) {
+ /* Update parent if there is one */
+ ni = NODEPTR(mc.mc_pg[mc.mc_top-1], mc.mc_ki[mc.mc_top-1]);
+ SETPGNO(ni, mo->mp_pgno);
+ mdb_cursor_pop(&mc);
+ } else {
+ /* Otherwise we're done */
+ *pg = mo->mp_pgno;
+ break;
+ }
+ }
+done:
+ free(buf);
+ return rc;
+}
+
+ /** Copy environment with compaction. */
+static int ESECT
+mdb_env_copyfd1(MDB_env *env, HANDLE fd)
+{
+ MDB_meta *mm;
+ MDB_page *mp;
+ mdb_copy my = {0};
+ MDB_txn *txn = NULL;
+ pthread_t thr;
+ pgno_t root, new_root;
+ int rc = MDB_SUCCESS;
+
+#ifdef _WIN32
+ if (!(my.mc_mutex = CreateMutex(NULL, FALSE, NULL)) ||
+ !(my.mc_cond = CreateEvent(NULL, FALSE, FALSE, NULL))) {
+ rc = ErrCode();
+ goto done;
+ }
+ my.mc_wbuf[0] = _aligned_malloc(MDB_WBUF*2, env->me_os_psize);
+ if (my.mc_wbuf[0] == NULL) {
+ /* _aligned_malloc() sets errno, but we use Windows error codes */
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto done;
+ }
+#else
+ if ((rc = pthread_mutex_init(&my.mc_mutex, NULL)) != 0)
+ return rc;
+ if ((rc = pthread_cond_init(&my.mc_cond, NULL)) != 0)
+ goto done2;
+#ifdef HAVE_MEMALIGN
+ my.mc_wbuf[0] = memalign(env->me_os_psize, MDB_WBUF*2);
+ if (my.mc_wbuf[0] == NULL) {
+ rc = errno;
+ goto done;
+ }
+#else
+ {
+ void *p;
+ if ((rc = posix_memalign(&p, env->me_os_psize, MDB_WBUF*2)) != 0)
+ goto done;
+ my.mc_wbuf[0] = p;
+ }
+#endif
+#endif
+ memset(my.mc_wbuf[0], 0, MDB_WBUF*2);
+ my.mc_wbuf[1] = my.mc_wbuf[0] + MDB_WBUF;
+ my.mc_next_pgno = NUM_METAS;
+ my.mc_env = env;
+ my.mc_fd = fd;
+ rc = THREAD_CREATE(thr, mdb_env_copythr, &my);
+ if (rc)
+ goto done;
+
+ rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
+ if (rc)
+ goto finish;
+
+ mp = (MDB_page *)my.mc_wbuf[0];
+ memset(mp, 0, NUM_METAS * env->me_psize);
+ mp->mp_pgno = 0;
+ mp->mp_flags = P_META;
+ mm = (MDB_meta *)METADATA(mp);
+ mdb_env_init_meta0(env, mm);
+ mm->mm_address = env->me_metas[0]->mm_address;
+
+ mp = (MDB_page *)(my.mc_wbuf[0] + env->me_psize);
+ mp->mp_pgno = 1;
+ mp->mp_flags = P_META;
+ *(MDB_meta *)METADATA(mp) = *mm;
+ mm = (MDB_meta *)METADATA(mp);
+
+ /* Set metapage 1 with current main DB */
+ root = new_root = txn->mt_dbs[MAIN_DBI].md_root;
+ if (root != P_INVALID) {
+ /* Count free pages + freeDB pages. Subtract from last_pg
+ * to find the new last_pg, which also becomes the new root.
+ */
+ MDB_ID freecount = 0;
+ MDB_cursor mc;
+ MDB_val key, data;
+ mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
+ while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0)
+ freecount += *(MDB_ID *)data.mv_data;
+ if (rc != MDB_NOTFOUND)
+ goto finish;
+ freecount += txn->mt_dbs[FREE_DBI].md_branch_pages +
+ txn->mt_dbs[FREE_DBI].md_leaf_pages +
+ txn->mt_dbs[FREE_DBI].md_overflow_pages;
+
+ new_root = txn->mt_next_pgno - 1 - freecount;
+ mm->mm_last_pg = new_root;
+ mm->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
+ mm->mm_dbs[MAIN_DBI].md_root = new_root;
+ } else {
+ /* When the DB is empty, handle it specially to
+ * fix any breakage like page leaks from ITS#8174.
+ */
+ mm->mm_dbs[MAIN_DBI].md_flags = txn->mt_dbs[MAIN_DBI].md_flags;
+ }
+ if (root != P_INVALID || mm->mm_dbs[MAIN_DBI].md_flags) {
+ mm->mm_txnid = 1; /* use metapage 1 */
+ }
+
+ my.mc_wlen[0] = env->me_psize * NUM_METAS;
+ my.mc_txn = txn;
+ rc = mdb_env_cwalk(&my, &root, 0);
+ if (rc == MDB_SUCCESS && root != new_root) {
+ rc = MDB_INCOMPATIBLE; /* page leak or corrupt DB */
+ }
+
+finish:
+ if (rc)
+ my.mc_error = rc;
+ mdb_env_cthr_toggle(&my, 1 | MDB_EOF);
+ rc = THREAD_FINISH(thr);
+ mdb_txn_abort(txn);
+
+done:
+#ifdef _WIN32
+ if (my.mc_wbuf[0]) _aligned_free(my.mc_wbuf[0]);
+ if (my.mc_cond) CloseHandle(my.mc_cond);
+ if (my.mc_mutex) CloseHandle(my.mc_mutex);
+#else
+ free(my.mc_wbuf[0]);
+ pthread_cond_destroy(&my.mc_cond);
+done2:
+ pthread_mutex_destroy(&my.mc_mutex);
+#endif
+ return rc ? rc : my.mc_error;
+}
+
+ /** Copy environment as-is. */
+static int ESECT
+mdb_env_copyfd0(MDB_env *env, HANDLE fd)
+{
+ MDB_txn *txn = NULL;
+ mdb_mutexref_t wmutex = NULL;
+ int rc;
+ size_t wsize, w3;
+ char *ptr;
+#ifdef _WIN32
+ DWORD len, w2;
+#define DO_WRITE(rc, fd, ptr, w2, len) rc = WriteFile(fd, ptr, w2, &len, NULL)
+#else
+ ssize_t len;
+ size_t w2;
+#define DO_WRITE(rc, fd, ptr, w2, len) len = write(fd, ptr, w2); rc = (len >= 0)
+#endif
+
+ /* Do the lock/unlock of the reader mutex before starting the
+ * write txn. Otherwise other read txns could block writers.
+ */
+ rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
+ if (rc)
+ return rc;
+
+ if (env->me_txns) {
+ /* We must start the actual read txn after blocking writers */
+ mdb_txn_end(txn, MDB_END_RESET_TMP);
+
+ /* Temporarily block writers until we snapshot the meta pages */
+ wmutex = env->me_wmutex;
+ if (LOCK_MUTEX(rc, env, wmutex))
+ goto leave;
+
+ rc = mdb_txn_renew0(txn);
+ if (rc) {
+ UNLOCK_MUTEX(wmutex);
+ goto leave;
+ }
+ }
+
+ wsize = env->me_psize * NUM_METAS;
+ ptr = env->me_map;
+ w2 = wsize;
+ while (w2 > 0) {
+ DO_WRITE(rc, fd, ptr, w2, len);
+ if (!rc) {
+ rc = ErrCode();
+ break;
+ } else if (len > 0) {
+ rc = MDB_SUCCESS;
+ ptr += len;
+ w2 -= len;
+ continue;
+ } else {
+ /* Non-blocking or async handles are not supported */
+ rc = EIO;
+ break;
+ }
+ }
+ if (wmutex)
+ UNLOCK_MUTEX(wmutex);
+
+ if (rc)
+ goto leave;
+
+ w3 = txn->mt_next_pgno * env->me_psize;
+ {
+ size_t fsize = 0;
+ if ((rc = mdb_fsize(env->me_fd, &fsize)))
+ goto leave;
+ if (w3 > fsize)
+ w3 = fsize;
+ }
+ wsize = w3 - wsize;
+ while (wsize > 0) {
+ if (wsize > MAX_WRITE)
+ w2 = MAX_WRITE;
+ else
+ w2 = wsize;
+ DO_WRITE(rc, fd, ptr, w2, len);
+ if (!rc) {
+ rc = ErrCode();
+ break;
+ } else if (len > 0) {
+ rc = MDB_SUCCESS;
+ ptr += len;
+ wsize -= len;
+ continue;
+ } else {
+ rc = EIO;
+ break;
+ }
+ }
+
+leave:
+ mdb_txn_abort(txn);
+ return rc;
+}
+
+int ESECT
+mdb_env_copyfd2(MDB_env *env, HANDLE fd, unsigned int flags)
+{
+ if (flags & MDB_CP_COMPACT)
+ return mdb_env_copyfd1(env, fd);
+ else
+ return mdb_env_copyfd0(env, fd);
+}
+
+int ESECT
+mdb_env_copyfd(MDB_env *env, HANDLE fd)
+{
+ return mdb_env_copyfd2(env, fd, 0);
+}
+
+int ESECT
+mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
+{
+ int rc;
+ MDB_name fname;
+ HANDLE newfd = INVALID_HANDLE_VALUE;
+
+ rc = mdb_fname_init(path, env->me_flags | MDB_NOLOCK, &fname);
+ if (rc == MDB_SUCCESS) {
+ rc = mdb_fopen(env, &fname, MDB_O_COPY, 0666, &newfd);
+ mdb_fname_destroy(fname);
+ }
+ if (rc == MDB_SUCCESS) {
+ rc = mdb_env_copyfd2(env, newfd, flags);
+ if (close(newfd) < 0 && rc == MDB_SUCCESS)
+ rc = ErrCode();
+ }
+ return rc;
+}
+
+int ESECT
+mdb_env_copy(MDB_env *env, const char *path)
+{
+ return mdb_env_copy2(env, path, 0);
+}
+
+int ESECT
+mdb_env_set_flags(MDB_env *env, unsigned int flag, int onoff)
+{
+ if (flag & ~CHANGEABLE)
+ return EINVAL;
+ if (onoff)
+ env->me_flags |= flag;
+ else
+ env->me_flags &= ~flag;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_get_flags(MDB_env *env, unsigned int *arg)
+{
+ if (!env || !arg)
+ return EINVAL;
+
+ *arg = env->me_flags & (CHANGEABLE|CHANGELESS);
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_set_userctx(MDB_env *env, void *ctx)
+{
+ if (!env)
+ return EINVAL;
+ env->me_userctx = ctx;
+ return MDB_SUCCESS;
+}
+
+void * ESECT
+mdb_env_get_userctx(MDB_env *env)
+{
+ return env ? env->me_userctx : NULL;
+}
+
+int ESECT
+mdb_env_set_assert(MDB_env *env, MDB_assert_func *func)
+{
+ if (!env)
+ return EINVAL;
+#ifndef NDEBUG
+ env->me_assert_func = func;
+#endif
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_get_path(MDB_env *env, const char **arg)
+{
+ if (!env || !arg)
+ return EINVAL;
+
+ *arg = env->me_path;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *arg)
+{
+ if (!env || !arg)
+ return EINVAL;
+
+ *arg = env->me_fd;
+ return MDB_SUCCESS;
+}
+
+/** Common code for #mdb_stat() and #mdb_env_stat().
+ * @param[in] env the environment to operate in.
+ * @param[in] db the #MDB_db record containing the stats to return.
+ * @param[out] arg the address of an #MDB_stat structure to receive the stats.
+ * @return 0, this function always succeeds.
+ */
+static int ESECT
+mdb_stat0(MDB_env *env, MDB_db *db, MDB_stat *arg)
+{
+ arg->ms_psize = env->me_psize;
+ arg->ms_depth = db->md_depth;
+ arg->ms_branch_pages = db->md_branch_pages;
+ arg->ms_leaf_pages = db->md_leaf_pages;
+ arg->ms_overflow_pages = db->md_overflow_pages;
+ arg->ms_entries = db->md_entries;
+
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_stat(MDB_env *env, MDB_stat *arg)
+{
+ MDB_meta *meta;
+
+ if (env == NULL || arg == NULL)
+ return EINVAL;
+
+ meta = mdb_env_pick_meta(env);
+
+ return mdb_stat0(env, &meta->mm_dbs[MAIN_DBI], arg);
+}
+
+int ESECT
+mdb_env_info(MDB_env *env, MDB_envinfo *arg)
+{
+ MDB_meta *meta;
+
+ if (env == NULL || arg == NULL)
+ return EINVAL;
+
+ meta = mdb_env_pick_meta(env);
+ arg->me_mapaddr = meta->mm_address;
+ arg->me_last_pgno = meta->mm_last_pg;
+ arg->me_last_txnid = meta->mm_txnid;
+
+ arg->me_mapsize = env->me_mapsize;
+ arg->me_maxreaders = env->me_maxreaders;
+ arg->me_numreaders = env->me_txns ? env->me_txns->mti_numreaders : 0;
+ return MDB_SUCCESS;
+}
+
+/** Set the default comparison functions for a database.
+ * Called immediately after a database is opened to set the defaults.
+ * The user can then override them with #mdb_set_compare() or
+ * #mdb_set_dupsort().
+ * @param[in] txn A transaction handle returned by #mdb_txn_begin()
+ * @param[in] dbi A database handle returned by #mdb_dbi_open()
+ */
+static void
+mdb_default_cmp(MDB_txn *txn, MDB_dbi dbi)
+{
+ uint16_t f = txn->mt_dbs[dbi].md_flags;
+
+ txn->mt_dbxs[dbi].md_cmp =
+ (f & MDB_REVERSEKEY) ? mdb_cmp_memnr :
+ (f & MDB_INTEGERKEY) ? mdb_cmp_cint : mdb_cmp_memn;
+
+ txn->mt_dbxs[dbi].md_dcmp =
+ !(f & MDB_DUPSORT) ? 0 :
+ ((f & MDB_INTEGERDUP)
+ ? ((f & MDB_DUPFIXED) ? mdb_cmp_int : mdb_cmp_cint)
+ : ((f & MDB_REVERSEDUP) ? mdb_cmp_memnr : mdb_cmp_memn));
+}
+
+int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
+{
+ MDB_val key, data;
+ MDB_dbi i;
+ MDB_cursor mc;
+ MDB_db dummy;
+ int rc, dbflag, exact;
+ unsigned int unused = 0, seq;
+ char *namedup;
+ size_t len;
+
+ if (flags & ~VALID_FLAGS)
+ return EINVAL;
+ if (txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ /* main DB? */
+ if (!name) {
+ *dbi = MAIN_DBI;
+ if (flags & PERSISTENT_FLAGS) {
+ uint16_t f2 = flags & PERSISTENT_FLAGS;
+ /* make sure flag changes get committed */
+ if ((txn->mt_dbs[MAIN_DBI].md_flags | f2) != txn->mt_dbs[MAIN_DBI].md_flags) {
+ txn->mt_dbs[MAIN_DBI].md_flags |= f2;
+ txn->mt_flags |= MDB_TXN_DIRTY;
+ }
+ }
+ mdb_default_cmp(txn, MAIN_DBI);
+ return MDB_SUCCESS;
+ }
+
+ if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) {
+ mdb_default_cmp(txn, MAIN_DBI);
+ }
+
+ /* Is the DB already open? */
+ len = strlen(name);
+ for (i=CORE_DBS; i<txn->mt_numdbs; i++) {
+ if (!txn->mt_dbxs[i].md_name.mv_size) {
+ /* Remember this free slot */
+ if (!unused) unused = i;
+ continue;
+ }
+ if (len == txn->mt_dbxs[i].md_name.mv_size &&
+ !strncmp(name, txn->mt_dbxs[i].md_name.mv_data, len)) {
+ *dbi = i;
+ return MDB_SUCCESS;
+ }
+ }
+
+ /* If no free slot and max hit, fail */
+ if (!unused && txn->mt_numdbs >= txn->mt_env->me_maxdbs)
+ return MDB_DBS_FULL;
+
+ /* Cannot mix named databases with some mainDB flags */
+ if (txn->mt_dbs[MAIN_DBI].md_flags & (MDB_DUPSORT|MDB_INTEGERKEY))
+ return (flags & MDB_CREATE) ? MDB_INCOMPATIBLE : MDB_NOTFOUND;
+
+ /* Find the DB info */
+ dbflag = DB_NEW|DB_VALID|DB_USRVALID;
+ exact = 0;
+ key.mv_size = len;
+ key.mv_data = (void *)name;
+ mdb_cursor_init(&mc, txn, MAIN_DBI, NULL);
+ rc = mdb_cursor_set(&mc, &key, &data, MDB_SET, &exact);
+ if (rc == MDB_SUCCESS) {
+ /* make sure this is actually a DB */
+ MDB_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]);
+ if ((node->mn_flags & (F_DUPDATA|F_SUBDATA)) != F_SUBDATA)
+ return MDB_INCOMPATIBLE;
+ } else if (! (rc == MDB_NOTFOUND && (flags & MDB_CREATE))) {
+ return rc;
+ }
+
+ /* Done here so we cannot fail after creating a new DB */
+ if ((namedup = strdup(name)) == NULL)
+ return ENOMEM;
+
+ if (rc) {
+ /* MDB_NOTFOUND and MDB_CREATE: Create new DB */
+ data.mv_size = sizeof(MDB_db);
+ data.mv_data = &dummy;
+ memset(&dummy, 0, sizeof(dummy));
+ dummy.md_root = P_INVALID;
+ dummy.md_flags = flags & PERSISTENT_FLAGS;
+ WITH_CURSOR_TRACKING(mc,
+ rc = mdb_cursor_put(&mc, &key, &data, F_SUBDATA));
+ dbflag |= DB_DIRTY;
+ }
+
+ if (rc) {
+ free(namedup);
+ } else {
+ /* Got info, register DBI in this txn */
+ unsigned int slot = unused ? unused : txn->mt_numdbs;
+ txn->mt_dbxs[slot].md_name.mv_data = namedup;
+ txn->mt_dbxs[slot].md_name.mv_size = len;
+ txn->mt_dbxs[slot].md_rel = NULL;
+ txn->mt_dbflags[slot] = dbflag;
+ /* txn-> and env-> are the same in read txns, use
+ * tmp variable to avoid undefined assignment
+ */
+ seq = ++txn->mt_env->me_dbiseqs[slot];
+ txn->mt_dbiseqs[slot] = seq;
+
+ memcpy(&txn->mt_dbs[slot], data.mv_data, sizeof(MDB_db));
+ *dbi = slot;
+ mdb_default_cmp(txn, slot);
+ if (!unused) {
+ txn->mt_numdbs++;
+ }
+ }
+
+ return rc;
+}
+
+int ESECT
+mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)
+{
+ if (!arg || !TXN_DBI_EXIST(txn, dbi, DB_VALID))
+ return EINVAL;
+
+ if (txn->mt_flags & MDB_TXN_BLOCKED)
+ return MDB_BAD_TXN;
+
+ if (txn->mt_dbflags[dbi] & DB_STALE) {
+ MDB_cursor mc;
+ MDB_xcursor mx;
+ /* Stale, must read the DB's root. cursor_init does it for us. */
+ mdb_cursor_init(&mc, txn, dbi, &mx);
+ }
+ return mdb_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg);
+}
+
+void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
+{
+ char *ptr;
+ if (dbi < CORE_DBS || dbi >= env->me_maxdbs)
+ return;
+ ptr = env->me_dbxs[dbi].md_name.mv_data;
+ /* If there was no name, this was already closed */
+ if (ptr) {
+ env->me_dbxs[dbi].md_name.mv_data = NULL;
+ env->me_dbxs[dbi].md_name.mv_size = 0;
+ env->me_dbflags[dbi] = 0;
+ env->me_dbiseqs[dbi]++;
+ free(ptr);
+ }
+}
+
+int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
+{
+ /* We could return the flags for the FREE_DBI too but what's the point? */
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+ *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
+ return MDB_SUCCESS;
+}
+
+/** Add all the DB's pages to the free list.
+ * @param[in] mc Cursor on the DB to free.
+ * @param[in] subs non-Zero to check for sub-DBs in this DB.
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+mdb_drop0(MDB_cursor *mc, int subs)
+{
+ int rc;
+
+ rc = mdb_page_search(mc, NULL, MDB_PS_FIRST);
+ if (rc == MDB_SUCCESS) {
+ MDB_txn *txn = mc->mc_txn;
+ MDB_node *ni;
+ MDB_cursor mx;
+ unsigned int i;
+
+ /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves.
+ * This also avoids any P_LEAF2 pages, which have no nodes.
+ * Also if the DB doesn't have sub-DBs and has no overflow
+ * pages, omit scanning leaves.
+ */
+ if ((mc->mc_flags & C_SUB) ||
+ (!subs && !mc->mc_db->md_overflow_pages))
+ mdb_cursor_pop(mc);
+
+ mdb_cursor_copy(mc, &mx);
+ while (mc->mc_snum > 0) {
+ MDB_page *mp = mc->mc_pg[mc->mc_top];
+ unsigned n = NUMKEYS(mp);
+ if (IS_LEAF(mp)) {
+ for (i=0; i<n; i++) {
+ ni = NODEPTR(mp, i);
+ if (ni->mn_flags & F_BIGDATA) {
+ MDB_page *omp;
+ pgno_t pg;
+ memcpy(&pg, NODEDATA(ni), sizeof(pg));
+ rc = mdb_page_get(mc, pg, &omp, NULL);
+ if (rc != 0)
+ goto done;
+ mdb_cassert(mc, IS_OVERFLOW(omp));
+ rc = mdb_midl_append_range(&txn->mt_free_pgs,
+ pg, omp->mp_pages);
+ if (rc)
+ goto done;
+ mc->mc_db->md_overflow_pages -= omp->mp_pages;
+ if (!mc->mc_db->md_overflow_pages && !subs)
+ break;
+ } else if (subs && (ni->mn_flags & F_SUBDATA)) {
+ mdb_xcursor_init1(mc, ni);
+ rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
+ if (rc)
+ goto done;
+ }
+ }
+ if (!subs && !mc->mc_db->md_overflow_pages)
+ goto pop;
+ } else {
+ if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
+ goto done;
+ for (i=0; i<n; i++) {
+ pgno_t pg;
+ ni = NODEPTR(mp, i);
+ pg = NODEPGNO(ni);
+ /* free it */
+ mdb_midl_xappend(txn->mt_free_pgs, pg);
+ }
+ }
+ if (!mc->mc_top)
+ break;
+ mc->mc_ki[mc->mc_top] = i;
+ rc = mdb_cursor_sibling(mc, 1);
+ if (rc) {
+ if (rc != MDB_NOTFOUND)
+ goto done;
+ /* no more siblings, go back to beginning
+ * of previous level.
+ */
+pop:
+ mdb_cursor_pop(mc);
+ mc->mc_ki[0] = 0;
+ for (i=1; i<mc->mc_snum; i++) {
+ mc->mc_ki[i] = 0;
+ mc->mc_pg[i] = mx.mc_pg[i];
+ }
+ }
+ }
+ /* free it */
+ rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root);
+done:
+ if (rc)
+ txn->mt_flags |= MDB_TXN_ERROR;
+ } else if (rc == MDB_NOTFOUND) {
+ rc = MDB_SUCCESS;
+ }
+ mc->mc_flags &= ~C_INITIALIZED;
+ return rc;
+}
+
+int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
+{
+ MDB_cursor *mc, *m2;
+ int rc;
+
+ if ((unsigned)del > 1 || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
+ return EACCES;
+
+ if (TXN_DBI_CHANGED(txn, dbi))
+ return MDB_BAD_DBI;
+
+ rc = mdb_cursor_open(txn, dbi, &mc);
+ if (rc)
+ return rc;
+
+ rc = mdb_drop0(mc, mc->mc_db->md_flags & MDB_DUPSORT);
+ /* Invalidate the dropped DB's cursors */
+ for (m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next)
+ m2->mc_flags &= ~(C_INITIALIZED|C_EOF);
+ if (rc)
+ goto leave;
+
+ /* Can't delete the main DB */
+ if (del && dbi >= CORE_DBS) {
+ rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA);
+ if (!rc) {
+ txn->mt_dbflags[dbi] = DB_STALE;
+ mdb_dbi_close(txn->mt_env, dbi);
+ } else {
+ txn->mt_flags |= MDB_TXN_ERROR;
+ }
+ } else {
+ /* reset the DB record, mark it dirty */
+ txn->mt_dbflags[dbi] |= DB_DIRTY;
+ txn->mt_dbs[dbi].md_depth = 0;
+ txn->mt_dbs[dbi].md_branch_pages = 0;
+ txn->mt_dbs[dbi].md_leaf_pages = 0;
+ txn->mt_dbs[dbi].md_overflow_pages = 0;
+ txn->mt_dbs[dbi].md_entries = 0;
+ txn->mt_dbs[dbi].md_root = P_INVALID;
+
+ txn->mt_flags |= MDB_TXN_DIRTY;
+ }
+leave:
+ mdb_cursor_close(mc);
+ return rc;
+}
+
+int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
+{
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ txn->mt_dbxs[dbi].md_cmp = cmp;
+ return MDB_SUCCESS;
+}
+
+int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
+{
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ txn->mt_dbxs[dbi].md_dcmp = cmp;
+ return MDB_SUCCESS;
+}
+
+int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
+{
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ txn->mt_dbxs[dbi].md_rel = rel;
+ return MDB_SUCCESS;
+}
+
+int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
+{
+ if (!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
+ return EINVAL;
+
+ txn->mt_dbxs[dbi].md_relctx = ctx;
+ return MDB_SUCCESS;
+}
+
+int ESECT
+mdb_env_get_maxkeysize(MDB_env *env)
+{
+ return ENV_MAXKEY(env);
+}
+
+int ESECT
+mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
+{
+ unsigned int i, rdrs;
+ MDB_reader *mr;
+ char buf[64];
+ int rc = 0, first = 1;
+
+ if (!env || !func)
+ return -1;
+ if (!env->me_txns) {
+ return func("(no reader locks)\n", ctx);
+ }
+ rdrs = env->me_txns->mti_numreaders;
+ mr = env->me_txns->mti_readers;
+ for (i=0; i<rdrs; i++) {
+ if (mr[i].mr_pid) {
+ txnid_t txnid = mr[i].mr_txnid;
+ sprintf(buf, txnid == (txnid_t)-1 ?
+ "%10d %"Z"x -\n" : "%10d %"Z"x %"Z"u\n",
+ (int)mr[i].mr_pid, (size_t)mr[i].mr_tid, txnid);
+ if (first) {
+ first = 0;
+ rc = func(" pid thread txnid\n", ctx);
+ if (rc < 0)
+ break;
+ }
+ rc = func(buf, ctx);
+ if (rc < 0)
+ break;
+ }
+ }
+ if (first) {
+ rc = func("(no active readers)\n", ctx);
+ }
+ return rc;
+}
+
+/** Insert pid into list if not already present.
+ * return -1 if already present.
+ */
+static int ESECT
+mdb_pid_insert(MDB_PID_T *ids, MDB_PID_T pid)
+{
+ /* binary search of pid in list */
+ unsigned base = 0;
+ unsigned cursor = 1;
+ int val = 0;
+ unsigned n = ids[0];
+
+ while( 0 < n ) {
+ unsigned pivot = n >> 1;
+ cursor = base + pivot + 1;
+ val = pid - ids[cursor];
+
+ if( val < 0 ) {
+ n = pivot;
+
+ } else if ( val > 0 ) {
+ base = cursor;
+ n -= pivot + 1;
+
+ } else {
+ /* found, so it's a duplicate */
+ return -1;
+ }
+ }
+
+ if( val > 0 ) {
+ ++cursor;
+ }
+ ids[0]++;
+ for (n = ids[0]; n > cursor; n--)
+ ids[n] = ids[n-1];
+ ids[n] = pid;
+ return 0;
+}
+
+int ESECT
+mdb_reader_check(MDB_env *env, int *dead)
+{
+ if (!env)
+ return EINVAL;
+ if (dead)
+ *dead = 0;
+ return env->me_txns ? mdb_reader_check0(env, 0, dead) : MDB_SUCCESS;
+}
+
+/** As #mdb_reader_check(). \b rlocked is set if caller locked #me_rmutex. */
+static int ESECT
+mdb_reader_check0(MDB_env *env, int rlocked, int *dead)
+{
+ mdb_mutexref_t rmutex = rlocked ? NULL : env->me_rmutex;
+ unsigned int i, j, rdrs;
+ MDB_reader *mr;
+ MDB_PID_T *pids, pid;
+ int rc = MDB_SUCCESS, count = 0;
+
+ rdrs = env->me_txns->mti_numreaders;
+ pids = malloc((rdrs+1) * sizeof(MDB_PID_T));
+ if (!pids)
+ return ENOMEM;
+ pids[0] = 0;
+ mr = env->me_txns->mti_readers;
+ for (i=0; i<rdrs; i++) {
+ pid = mr[i].mr_pid;
+ if (pid && pid != env->me_pid) {
+ if (mdb_pid_insert(pids, pid) == 0) {
+ if (!mdb_reader_pid(env, Pidcheck, pid)) {
+ /* Stale reader found */
+ j = i;
+ if (rmutex) {
+ if ((rc = LOCK_MUTEX0(rmutex)) != 0) {
+ if ((rc = mdb_mutex_failed(env, rmutex, rc)))
+ break;
+ rdrs = 0; /* the above checked all readers */
+ } else {
+ /* Recheck, a new process may have reused pid */
+ if (mdb_reader_pid(env, Pidcheck, pid))
+ j = rdrs;
+ }
+ }
+ for (; j<rdrs; j++)
+ if (mr[j].mr_pid == pid) {
+ DPRINTF(("clear stale reader pid %u txn %"Z"d",
+ (unsigned) pid, mr[j].mr_txnid));
+ mr[j].mr_pid = 0;
+ count++;
+ }
+ if (rmutex)
+ UNLOCK_MUTEX(rmutex);
+ }
+ }
+ }
+ }
+ free(pids);
+ if (dead)
+ *dead = count;
+ return rc;
+}
+
+#ifdef MDB_ROBUST_SUPPORTED
+/** Handle #LOCK_MUTEX0() failure.
+ * Try to repair the lock file if the mutex owner died.
+ * @param[in] env the environment handle
+ * @param[in] mutex LOCK_MUTEX0() mutex
+ * @param[in] rc LOCK_MUTEX0() error (nonzero)
+ * @return 0 on success with the mutex locked, or an error code on failure.
+ */
+static int ESECT
+mdb_mutex_failed(MDB_env *env, mdb_mutexref_t mutex, int rc)
+{
+ int rlocked, rc2;
+ MDB_meta *meta;
+
+ if (rc == MDB_OWNERDEAD) {
+ /* We own the mutex. Clean up after dead previous owner. */
+ rc = MDB_SUCCESS;
+ rlocked = (mutex == env->me_rmutex);
+ if (!rlocked) {
+ /* Keep mti_txnid updated, otherwise next writer can
+ * overwrite data which latest meta page refers to.
+ */
+ meta = mdb_env_pick_meta(env);
+ env->me_txns->mti_txnid = meta->mm_txnid;
+ /* env is hosed if the dead thread was ours */
+ if (env->me_txn) {
+ env->me_flags |= MDB_FATAL_ERROR;
+ env->me_txn = NULL;
+ rc = MDB_PANIC;
+ }
+ }
+ DPRINTF(("%cmutex owner died, %s", (rlocked ? 'r' : 'w'),
+ (rc ? "this process' env is hosed" : "recovering")));
+ rc2 = mdb_reader_check0(env, rlocked, NULL);
+ if (rc2 == 0)
+ rc2 = mdb_mutex_consistent(mutex);
+ if (rc || (rc = rc2)) {
+ DPRINTF(("LOCK_MUTEX recovery failed, %s", mdb_strerror(rc)));
+ UNLOCK_MUTEX(mutex);
+ }
+ } else {
+#ifdef _WIN32
+ rc = ErrCode();
+#endif
+ DPRINTF(("LOCK_MUTEX failed, %s", mdb_strerror(rc)));
+ }
+
+ return rc;
+}
+#endif /* MDB_ROBUST_SUPPORTED */
+
+#if defined(_WIN32)
+/** Convert \b src to new wchar_t[] string with room for \b xtra extra chars */
+static int ESECT
+utf8_to_utf16(const char *src, MDB_name *dst, int xtra)
+{
+ int rc, need = 0;
+ wchar_t *result = NULL;
+ for (;;) { /* malloc result, then fill it in */
+ need = MultiByteToWideChar(CP_UTF8, 0, src, -1, result, need);
+ if (!need) {
+ rc = ErrCode();
+ free(result);
+ return rc;
+ }
+ if (!result) {
+ result = malloc(sizeof(wchar_t) * (need + xtra));
+ if (!result)
+ return ENOMEM;
+ continue;
+ }
+ dst->mn_alloced = 1;
+ dst->mn_len = need - 1;
+ dst->mn_val = result;
+ return MDB_SUCCESS;
+ }
+}
+#endif /* defined(_WIN32) */
+/** @} */
diff --git a/contrib/lmdb/midl.c b/contrib/lmdb/midl.c
new file mode 100644
index 0000000..1689c3a
--- /dev/null
+++ b/contrib/lmdb/midl.c
@@ -0,0 +1,359 @@
+/** @file midl.c
+ * @brief ldap bdb back-end ID List functions */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2000-2016 The OpenLDAP Foundation.
+ * Portions Copyright 2001-2017 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "midl.h"
+
+/** @defgroup internal LMDB Internals
+ * @{
+ */
+/** @defgroup idls ID List Management
+ * @{
+ */
+#define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
+
+unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id )
+{
+ /*
+ * binary search of id in ids
+ * if found, returns position of id
+ * if not found, returns first position greater than id
+ */
+ unsigned base = 0;
+ unsigned cursor = 1;
+ int val = 0;
+ unsigned n = ids[0];
+
+ while( 0 < n ) {
+ unsigned pivot = n >> 1;
+ cursor = base + pivot + 1;
+ val = CMP( ids[cursor], id );
+
+ if( val < 0 ) {
+ n = pivot;
+
+ } else if ( val > 0 ) {
+ base = cursor;
+ n -= pivot + 1;
+
+ } else {
+ return cursor;
+ }
+ }
+
+ if( val > 0 ) {
+ ++cursor;
+ }
+ return cursor;
+}
+
+#if 0 /* superseded by append/sort */
+int mdb_midl_insert( MDB_IDL ids, MDB_ID id )
+{
+ unsigned x, i;
+
+ x = mdb_midl_search( ids, id );
+ assert( x > 0 );
+
+ if( x < 1 ) {
+ /* internal error */
+ return -2;
+ }
+
+ if ( x <= ids[0] && ids[x] == id ) {
+ /* duplicate */
+ assert(0);
+ return -1;
+ }
+
+ if ( ++ids[0] >= MDB_IDL_DB_MAX ) {
+ /* no room */
+ --ids[0];
+ return -2;
+
+ } else {
+ /* insert id */
+ for (i=ids[0]; i>x; i--)
+ ids[i] = ids[i-1];
+ ids[x] = id;
+ }
+
+ return 0;
+}
+#endif
+
+MDB_IDL mdb_midl_alloc(int num)
+{
+ MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID));
+ if (ids) {
+ *ids++ = num;
+ *ids = 0;
+ }
+ return ids;
+}
+
+void mdb_midl_free(MDB_IDL ids)
+{
+ if (ids)
+ free(ids-1);
+}
+
+void mdb_midl_shrink( MDB_IDL *idp )
+{
+ MDB_IDL ids = *idp;
+ if (*(--ids) > MDB_IDL_UM_MAX &&
+ (ids = realloc(ids, (MDB_IDL_UM_MAX+2) * sizeof(MDB_ID))))
+ {
+ *ids++ = MDB_IDL_UM_MAX;
+ *idp = ids;
+ }
+}
+
+static int mdb_midl_grow( MDB_IDL *idp, int num )
+{
+ MDB_IDL idn = *idp-1;
+ /* grow it */
+ idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID));
+ if (!idn)
+ return ENOMEM;
+ *idn++ += num;
+ *idp = idn;
+ return 0;
+}
+
+int mdb_midl_need( MDB_IDL *idp, unsigned num )
+{
+ MDB_IDL ids = *idp;
+ num += ids[0];
+ if (num > ids[-1]) {
+ num = (num + num/4 + (256 + 2)) & -256;
+ if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
+ return ENOMEM;
+ *ids++ = num - 2;
+ *idp = ids;
+ }
+ return 0;
+}
+
+int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
+{
+ MDB_IDL ids = *idp;
+ /* Too big? */
+ if (ids[0] >= ids[-1]) {
+ if (mdb_midl_grow(idp, MDB_IDL_UM_MAX))
+ return ENOMEM;
+ ids = *idp;
+ }
+ ids[0]++;
+ ids[ids[0]] = id;
+ return 0;
+}
+
+int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
+{
+ MDB_IDL ids = *idp;
+ /* Too big? */
+ if (ids[0] + app[0] >= ids[-1]) {
+ if (mdb_midl_grow(idp, app[0]))
+ return ENOMEM;
+ ids = *idp;
+ }
+ memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID));
+ ids[0] += app[0];
+ return 0;
+}
+
+int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
+{
+ MDB_ID *ids = *idp, len = ids[0];
+ /* Too big? */
+ if (len + n > ids[-1]) {
+ if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX))
+ return ENOMEM;
+ ids = *idp;
+ }
+ ids[0] = len + n;
+ ids += len;
+ while (n)
+ ids[n--] = id++;
+ return 0;
+}
+
+void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge )
+{
+ MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k;
+ idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */
+ old_id = idl[j];
+ while (i) {
+ merge_id = merge[i--];
+ for (; old_id < merge_id; old_id = idl[--j])
+ idl[k--] = old_id;
+ idl[k--] = merge_id;
+ }
+ idl[0] = total;
+}
+
+/* Quicksort + Insertion sort for small arrays */
+
+#define SMALL 8
+#define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
+
+void
+mdb_midl_sort( MDB_IDL ids )
+{
+ /* Max possible depth of int-indexed tree * 2 items/level */
+ int istack[sizeof(int)*CHAR_BIT * 2];
+ int i,j,k,l,ir,jstack;
+ MDB_ID a, itmp;
+
+ ir = (int)ids[0];
+ l = 1;
+ jstack = 0;
+ for(;;) {
+ if (ir - l < SMALL) { /* Insertion sort */
+ for (j=l+1;j<=ir;j++) {
+ a = ids[j];
+ for (i=j-1;i>=1;i--) {
+ if (ids[i] >= a) break;
+ ids[i+1] = ids[i];
+ }
+ ids[i+1] = a;
+ }
+ if (jstack == 0) break;
+ ir = istack[jstack--];
+ l = istack[jstack--];
+ } else {
+ k = (l + ir) >> 1; /* Choose median of left, center, right */
+ MIDL_SWAP(ids[k], ids[l+1]);
+ if (ids[l] < ids[ir]) {
+ MIDL_SWAP(ids[l], ids[ir]);
+ }
+ if (ids[l+1] < ids[ir]) {
+ MIDL_SWAP(ids[l+1], ids[ir]);
+ }
+ if (ids[l] < ids[l+1]) {
+ MIDL_SWAP(ids[l], ids[l+1]);
+ }
+ i = l+1;
+ j = ir;
+ a = ids[l+1];
+ for(;;) {
+ do i++; while(ids[i] > a);
+ do j--; while(ids[j] < a);
+ if (j < i) break;
+ MIDL_SWAP(ids[i],ids[j]);
+ }
+ ids[l+1] = ids[j];
+ ids[j] = a;
+ jstack += 2;
+ if (ir-i+1 >= j-l) {
+ istack[jstack] = ir;
+ istack[jstack-1] = i;
+ ir = j-1;
+ } else {
+ istack[jstack] = j-1;
+ istack[jstack-1] = l;
+ l = i;
+ }
+ }
+ }
+}
+
+unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id )
+{
+ /*
+ * binary search of id in ids
+ * if found, returns position of id
+ * if not found, returns first position greater than id
+ */
+ unsigned base = 0;
+ unsigned cursor = 1;
+ int val = 0;
+ unsigned n = (unsigned)ids[0].mid;
+
+ while( 0 < n ) {
+ unsigned pivot = n >> 1;
+ cursor = base + pivot + 1;
+ val = CMP( id, ids[cursor].mid );
+
+ if( val < 0 ) {
+ n = pivot;
+
+ } else if ( val > 0 ) {
+ base = cursor;
+ n -= pivot + 1;
+
+ } else {
+ return cursor;
+ }
+ }
+
+ if( val > 0 ) {
+ ++cursor;
+ }
+ return cursor;
+}
+
+int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id )
+{
+ unsigned x, i;
+
+ x = mdb_mid2l_search( ids, id->mid );
+
+ if( x < 1 ) {
+ /* internal error */
+ return -2;
+ }
+
+ if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
+ /* duplicate */
+ return -1;
+ }
+
+ if ( ids[0].mid >= MDB_IDL_UM_MAX ) {
+ /* too big */
+ return -2;
+
+ } else {
+ /* insert id */
+ ids[0].mid++;
+ for (i=(unsigned)ids[0].mid; i>x; i--)
+ ids[i] = ids[i-1];
+ ids[x] = *id;
+ }
+
+ return 0;
+}
+
+int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
+{
+ /* Too big? */
+ if (ids[0].mid >= MDB_IDL_UM_MAX) {
+ return -2;
+ }
+ ids[0].mid++;
+ ids[ids[0].mid] = *id;
+ return 0;
+}
+
+/** @} */
+/** @} */
diff --git a/contrib/lmdb/midl.h b/contrib/lmdb/midl.h
new file mode 100644
index 0000000..df9414d
--- /dev/null
+++ b/contrib/lmdb/midl.h
@@ -0,0 +1,186 @@
+/** @file midl.h
+ * @brief LMDB ID List header file.
+ *
+ * This file was originally part of back-bdb but has been
+ * modified for use in libmdb. Most of the macros defined
+ * in this file are unused, just left over from the original.
+ *
+ * This file is only used internally in libmdb and its definitions
+ * are not exposed publicly.
+ */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2000-2016 The OpenLDAP Foundation.
+ * Portions Copyright 2001-2017 Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+
+#ifndef _MDB_MIDL_H_
+#define _MDB_MIDL_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup internal LMDB Internals
+ * @{
+ */
+
+/** @defgroup idls ID List Management
+ * @{
+ */
+ /** A generic unsigned ID number. These were entryIDs in back-bdb.
+ * Preferably it should have the same size as a pointer.
+ */
+typedef size_t MDB_ID;
+
+ /** An IDL is an ID List, a sorted array of IDs. The first
+ * element of the array is a counter for how many actual
+ * IDs are in the list. In the original back-bdb code, IDLs are
+ * sorted in ascending order. For libmdb IDLs are sorted in
+ * descending order.
+ */
+typedef MDB_ID *MDB_IDL;
+
+/* IDL sizes - likely should be even bigger
+ * limiting factors: sizeof(ID), thread stack size
+ */
+#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
+#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
+#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
+
+#define MDB_IDL_DB_MAX (MDB_IDL_DB_SIZE-1)
+#define MDB_IDL_UM_MAX (MDB_IDL_UM_SIZE-1)
+
+#define MDB_IDL_SIZEOF(ids) (((ids)[0]+1) * sizeof(MDB_ID))
+#define MDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
+#define MDB_IDL_CPY( dst, src ) (memcpy( dst, src, MDB_IDL_SIZEOF( src ) ))
+#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
+#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
+
+ /** Current max length of an #mdb_midl_alloc()ed IDL */
+#define MDB_IDL_ALLOCLEN( ids ) ( (ids)[-1] )
+
+ /** Append ID to IDL. The IDL must be big enough. */
+#define mdb_midl_xappend(idl, id) do { \
+ MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \
+ xidl[xlen] = (id); \
+ } while (0)
+
+ /** Search for an ID in an IDL.
+ * @param[in] ids The IDL to search.
+ * @param[in] id The ID to search for.
+ * @return The index of the first ID greater than or equal to \b id.
+ */
+unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id );
+
+ /** Allocate an IDL.
+ * Allocates memory for an IDL of the given size.
+ * @return IDL on success, NULL on failure.
+ */
+MDB_IDL mdb_midl_alloc(int num);
+
+ /** Free an IDL.
+ * @param[in] ids The IDL to free.
+ */
+void mdb_midl_free(MDB_IDL ids);
+
+ /** Shrink an IDL.
+ * Return the IDL to the default size if it has grown larger.
+ * @param[in,out] idp Address of the IDL to shrink.
+ */
+void mdb_midl_shrink(MDB_IDL *idp);
+
+ /** Make room for num additional elements in an IDL.
+ * @param[in,out] idp Address of the IDL.
+ * @param[in] num Number of elements to make room for.
+ * @return 0 on success, ENOMEM on failure.
+ */
+int mdb_midl_need(MDB_IDL *idp, unsigned num);
+
+ /** Append an ID onto an IDL.
+ * @param[in,out] idp Address of the IDL to append to.
+ * @param[in] id The ID to append.
+ * @return 0 on success, ENOMEM if the IDL is too large.
+ */
+int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
+
+ /** Append an IDL onto an IDL.
+ * @param[in,out] idp Address of the IDL to append to.
+ * @param[in] app The IDL to append.
+ * @return 0 on success, ENOMEM if the IDL is too large.
+ */
+int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
+
+ /** Append an ID range onto an IDL.
+ * @param[in,out] idp Address of the IDL to append to.
+ * @param[in] id The lowest ID to append.
+ * @param[in] n Number of IDs to append.
+ * @return 0 on success, ENOMEM if the IDL is too large.
+ */
+int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n );
+
+ /** Merge an IDL onto an IDL. The destination IDL must be big enough.
+ * @param[in] idl The IDL to merge into.
+ * @param[in] merge The IDL to merge.
+ */
+void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge );
+
+ /** Sort an IDL.
+ * @param[in,out] ids The IDL to sort.
+ */
+void mdb_midl_sort( MDB_IDL ids );
+
+ /** An ID2 is an ID/pointer pair.
+ */
+typedef struct MDB_ID2 {
+ MDB_ID mid; /**< The ID */
+ void *mptr; /**< The pointer */
+} MDB_ID2;
+
+ /** An ID2L is an ID2 List, a sorted array of ID2s.
+ * The first element's \b mid member is a count of how many actual
+ * elements are in the array. The \b mptr member of the first element is unused.
+ * The array is sorted in ascending order by \b mid.
+ */
+typedef MDB_ID2 *MDB_ID2L;
+
+ /** Search for an ID in an ID2L.
+ * @param[in] ids The ID2L to search.
+ * @param[in] id The ID to search for.
+ * @return The index of the first ID2 whose \b mid member is greater than or equal to \b id.
+ */
+unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id );
+
+
+ /** Insert an ID2 into a ID2L.
+ * @param[in,out] ids The ID2L to insert into.
+ * @param[in] id The ID2 to insert.
+ * @return 0 on success, -1 if the ID was already present in the ID2L.
+ */
+int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
+
+ /** Append an ID2 into a ID2L.
+ * @param[in,out] ids The ID2L to append into.
+ * @param[in] id The ID2 to append.
+ * @return 0 on success, -2 if the ID2L is too big.
+ */
+int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
+
+/** @} */
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MDB_MIDL_H_ */
diff --git a/contrib/murmurhash3/LICENSE b/contrib/murmurhash3/LICENSE
new file mode 100644
index 0000000..feb9b11
--- /dev/null
+++ b/contrib/murmurhash3/LICENSE
@@ -0,0 +1,28 @@
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
+
+ the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
+ moral rights retained by the original author(s) and/or performer(s);
+ publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
+ rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
+ rights protecting the extraction, dissemination, use and reuse of data in a Work;
+ database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
+ other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
+ Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
+ Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
+ Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
diff --git a/contrib/murmurhash3/murmurhash3.c b/contrib/murmurhash3/murmurhash3.c
new file mode 100644
index 0000000..06ed7d8
--- /dev/null
+++ b/contrib/murmurhash3/murmurhash3.c
@@ -0,0 +1,74 @@
+/* This is MurmurHash3. The original C++ code was placed in the public domain
+ * by its author, Austin Appleby. */
+
+#include "murmurhash3.h"
+
+static inline uint32_t fmix(uint32_t h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+static inline uint32_t rotl32(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+uint32_t hash(const char* data, size_t len_)
+{
+ const int len = (int) len_;
+ const int nblocks = len / 4;
+
+ uint32_t h1 = 0xc062fb4a;
+
+ uint32_t c1 = 0xcc9e2d51;
+ uint32_t c2 = 0x1b873593;
+
+ //----------
+ // body
+
+ const uint32_t * blocks = (const uint32_t*) (data + nblocks * 4);
+
+ int i;
+ for(i = -nblocks; i; i++)
+ {
+ uint32_t k1 = blocks[i];
+
+ k1 *= c1;
+ k1 = rotl32(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = rotl32(h1, 13);
+ h1 = h1*5+0xe6546b64;
+ }
+
+ //----------
+ // tail
+
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
+
+ uint32_t k1 = 0;
+
+ switch(len & 3)
+ {
+ case 3: k1 ^= tail[2] << 16;
+ case 2: k1 ^= tail[1] << 8;
+ case 1: k1 ^= tail[0];
+ k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
+ }
+
+ //----------
+ // finalization
+
+ h1 ^= len;
+
+ h1 = fmix(h1);
+
+ return h1;
+}
diff --git a/contrib/murmurhash3/murmurhash3.h b/contrib/murmurhash3/murmurhash3.h
new file mode 100644
index 0000000..b4507b3
--- /dev/null
+++ b/contrib/murmurhash3/murmurhash3.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <stdlib.h>
+#include <stdint.h>
+
+uint32_t hash(const char* data, size_t len);
diff --git a/contrib/ucw/LICENSE b/contrib/ucw/LICENSE
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/contrib/ucw/LICENSE
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/contrib/ucw/alloc.h b/contrib/ucw/alloc.h
new file mode 100644
index 0000000..668c707
--- /dev/null
+++ b/contrib/ucw/alloc.h
@@ -0,0 +1,36 @@
+/*
+ * UCW Library -- Generic allocators
+ *
+ * (c) 2014 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _UCW_ALLOC_H
+#define _UCW_ALLOC_H
+
+/**
+ * This structure describes a generic allocator. It provides pointers
+ * to three functions, which handle the actual (re)allocations.
+ **/
+struct ucw_allocator {
+ void * (*alloc)(struct ucw_allocator *alloc, size_t size);
+ void * (*realloc)(struct ucw_allocator *alloc, void *ptr, size_t old_size, size_t new_size);
+ void (*free)(struct ucw_allocator *alloc, void *ptr);
+};
+
+/* alloc-std.c */
+
+/**
+ * [[std]]
+ * This allocator uses <<basics:xmalloc()>>, <<basics:xrealloc()>> and <<basics:xfree()>>. The memory
+ * it allocates is left unitialized.
+ **/
+extern struct ucw_allocator ucw_allocator_std;
+
+/**
+ * [[zeroing]]
+ * This allocator uses <<basics:xmalloc()>>, <<basics:xrealloc()>> and <<basics:xfree()>>. All memory
+ * is zeroed upon allocation.
+ **/
+extern struct ucw_allocator ucw_allocator_zeroed;
+
+#endif
diff --git a/contrib/ucw/config.h b/contrib/ucw/config.h
new file mode 100644
index 0000000..5d3cb4f
--- /dev/null
+++ b/contrib/ucw/config.h
@@ -0,0 +1,58 @@
+/*
+ * UCW Library -- Configuration-Dependent Definitions
+ *
+ * (c) 1997--2012 Martin Mares <mj@ucw.cz>
+ * (c) 2006 Robert Spalek <robert@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#ifndef _UCW_CONFIG_H
+#define _UCW_CONFIG_H
+
+/* Default page size and pointer alignment */
+#ifndef CPU_PAGE_SIZE
+#define CPU_PAGE_SIZE 4096
+#endif
+#define CPU_STRUCT_ALIGN sizeof(void *)
+
+/* Tell libc we're going to use all extensions available */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/* Types (based on standard C99 integers) */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef uint8_t byte; /** Exactly 8 bits, unsigned **/
+typedef uint8_t u8; /** Exactly 8 bits, unsigned **/
+typedef int8_t s8; /** Exactly 8 bits, signed **/
+typedef uint16_t u16; /** Exactly 16 bits, unsigned **/
+typedef int16_t s16; /** Exactly 16 bits, signed **/
+typedef uint32_t u32; /** Exactly 32 bits, unsigned **/
+typedef int32_t s32; /** Exactly 32 bits, signed **/
+typedef uint64_t u64; /** Exactly 64 bits, unsigned **/
+typedef int64_t s64; /** Exactly 64 bits, signed **/
+
+
+#ifndef uint /* Redefining typedef is a C11 feature. */
+typedef unsigned int uint; /** A better pronounceable alias for `unsigned int` **/
+#define uint uint
+#endif
+
+typedef s64 timestamp_t; /** Milliseconds since an unknown epoch **/
+
+// FIXME: This should be removed soon
+typedef uint uns; /** Backwards compatible alias for `uint' ***/
+
+#ifdef CONFIG_UCW_LARGE_FILES
+typedef s64 ucw_off_t; /** File position (either 32- or 64-bit, depending on `CONFIG_UCW_LARGE_FILES`). **/
+#else
+typedef s32 ucw_off_t;
+#endif
+
+#endif
diff --git a/contrib/ucw/lib.h b/contrib/ucw/lib.h
new file mode 100644
index 0000000..506f09b
--- /dev/null
+++ b/contrib/ucw/lib.h
@@ -0,0 +1,125 @@
+/*
+ * The UCW Library -- Miscellaneous Functions
+ *
+ * (c) 1997--2014 Martin Mares <mj@ucw.cz>
+ * (c) 2005--2014 Tomas Valla <tom@ucw.cz>
+ * (c) 2006 Robert Spalek <robert@ucw.cz>
+ * (c) 2007 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#ifndef _UCW_LIB_H
+#define _UCW_LIB_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef CONFIG_UCW_CLEAN_ABI
+#define assert_failed ucw_assert_failed
+#define assert_failed_msg ucw_assert_failed_msg
+#define assert_failed_noinfo ucw_assert_failed_noinfo
+#define big_alloc ucw_big_alloc
+#define big_alloc_zero ucw_big_alloc_zero
+#define big_free ucw_big_free
+#define die ucw_die
+#define log_die_hook ucw_log_die_hook
+#define log_file ucw_log_file
+#define log_fork ucw_log_fork
+#define log_init ucw_log_init
+#define log_pid ucw_log_pid
+#define log_title ucw_log_title
+#define msg ucw_msg
+#define page_alloc ucw_page_alloc
+#define page_alloc_zero ucw_page_alloc_zero
+#define page_free ucw_page_free
+#define page_realloc ucw_page_realloc
+#define random_max ucw_random_max
+#define random_max_u64 ucw_random_max_u64
+#define random_u32 ucw_random_u32
+#define random_u64 ucw_random_u64
+#define vdie ucw_vdie
+#define vmsg ucw_vmsg
+#define xfree ucw_xfree
+#define xmalloc ucw_xmalloc
+#define xmalloc_zero ucw_xmalloc_zero
+#define xrealloc ucw_xrealloc
+#define xstrdup ucw_xstrdup
+#endif
+
+/*** === Macros for handling structures, offsets and alignment ***/
+
+#define CHECK_PTR_TYPE(x, type) ((x)-(type)(x) + (type)(x)) /** Check that a pointer @x is of type @type. Fail compilation if not. **/
+#define PTR_TO(s, i) &((s*)0)->i /** Return OFFSETOF() in form of a pointer. **/
+#define OFFSETOF(s, i) ((uint)offsetof(s, i)) /** Offset of item @i from the start of structure @s **/
+#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i))) /** Given a pointer @p to item @i of structure @s, return a pointer to the start of the struct. **/
+
+/** Align an integer @s to the nearest higher multiple of @a (which should be a power of two) **/
+#define ALIGN_TO(s, a) (((s)+a-1)&~(a-1))
+
+/** Align a pointer @p to the nearest higher multiple of @s. **/
+#define ALIGN_PTR(p, s) ((uintptr_t)(p) % (s) ? (typeof(p))((uintptr_t)(p) + (s) - (uintptr_t)(p) % (s)) : (p))
+
+#define UNALIGNED_PART(ptr, type) (((uintptr_t) (ptr)) % sizeof(type))
+
+/*** === Other utility macros ***/
+
+#define MIN(a,b) (((a)<(b))?(a):(b)) /** Minimum of two numbers **/
+#define MAX(a,b) (((a)>(b))?(a):(b)) /** Maximum of two numbers **/
+#define CLAMP(x,min,max) ({ typeof(x) _t=x; (_t < min) ? min : (_t > max) ? max : _t; }) /** Clip a number @x to interval [@min,@max] **/
+#define ABS(x) ((x) < 0 ? -(x) : (x)) /** Absolute value **/
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) /** The number of elements of an array **/
+#define STRINGIFY(x) #x /** Convert macro parameter to a string **/
+#define STRINGIFY_EXPANDED(x) STRINGIFY(x) /** Convert an expanded macro parameter to a string **/
+#define GLUE(x,y) x##y /** Glue two tokens together **/
+#define GLUE_(x,y) x##_##y /** Glue two tokens together, separating them by an underscore **/
+
+#define COMPARE(x,y) do { if ((x)<(y)) return -1; if ((x)>(y)) return 1; } while(0) /** Numeric comparison function for qsort() **/
+#define REV_COMPARE(x,y) COMPARE(y,x) /** Reverse numeric comparison **/
+#define COMPARE_LT(x,y) do { if ((x)<(y)) return 1; if ((x)>(y)) return 0; } while(0)
+#define COMPARE_GT(x,y) COMPARE_LT(y,x)
+
+#define ROL(x, bits) (((x) << (bits)) | ((uint)(x) >> (sizeof(uint)*8 - (bits)))) /** Bitwise rotation of an unsigned int to the left **/
+#define ROR(x, bits) (((uint)(x) >> (bits)) | ((x) << (sizeof(uint)*8 - (bits)))) /** Bitwise rotation of an unsigned int to the right **/
+
+/*** === Shortcuts for GCC Extensions ***/
+
+#ifdef __GNUC__
+
+#include "ccan/compiler/compiler.h"
+#define FORMAT_CHECK(x,y,z) __attribute__((format(x,y,z))) /** Checking of printf-like format strings **/
+#define likely(x) __builtin_expect((x),1) /** Use `if (likely(@x))` if @x is almost always true **/
+#define unlikely(x) __builtin_expect((x),0) /** Use `if (unlikely(@x))` to hint that @x is almost always false **/
+
+#if __GNUC__ >= 4 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3
+#define ALWAYS_INLINE inline __attribute__((always_inline)) /** Forcibly inline **/
+#define NO_INLINE __attribute__((noinline)) /** Forcibly uninline **/
+#else
+#define ALWAYS_INLINE inline
+#endif
+
+#if __GNUC__ >= 4
+#define LIKE_MALLOC __attribute__((malloc)) /** Function returns a "new" pointer **/
+#define SENTINEL_CHECK __attribute__((sentinel)) /** The last argument must be NULL **/
+#else
+#define LIKE_MALLOC
+#define SENTINEL_CHECK
+#endif
+
+#else
+#error This program requires the GNU C compiler.
+#endif
+
+/***
+ * [[logging]]
+ *
+ * === Basic logging functions (see <<log:,Logging>> and <ucw/log.h> for more)
+ ***/
+
+#define DBG(x, ...) do { } while(0)
+#define DBG_SPOT do { } while(0)
+#define ASSERT(x)
+
+#endif
diff --git a/contrib/ucw/mempool-fmt.c b/contrib/ucw/mempool-fmt.c
new file mode 100644
index 0000000..6c93e1e
--- /dev/null
+++ b/contrib/ucw/mempool-fmt.c
@@ -0,0 +1,100 @@
+/*
+ * UCW Library -- Memory Pools (Formatting)
+ *
+ * (c) 2005 Martin Mares <mj@ucw.cz>
+ * (c) 2007 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/mempool.h>
+
+#include <stdio.h>
+#include <string.h>
+
+/* FIXME: migrate to Knot DNS version of mempools. */
+#pragma GCC diagnostic ignored "-Wpointer-arith"
+
+static char *
+mp_vprintf_at(struct mempool *mp, size_t ofs, const char *fmt, va_list args)
+{
+ char *ret = mp_grow(mp, ofs + 1) + ofs;
+ va_list args2;
+ va_copy(args2, args);
+ int cnt = vsnprintf(ret, mp_avail(mp) - ofs, fmt, args2);
+ va_end(args2);
+ if (cnt < 0)
+ {
+ /* Our C library doesn't support C99 return value of vsnprintf, so we need to iterate */
+ do
+ {
+ ret = mp_expand(mp) + ofs;
+ va_copy(args2, args);
+ cnt = vsnprintf(ret, mp_avail(mp) - ofs, fmt, args2);
+ va_end(args2);
+ }
+ while (cnt < 0);
+ }
+ else if ((uint)cnt >= mp_avail(mp) - ofs)
+ {
+ ret = mp_grow(mp, ofs + cnt + 1) + ofs;
+ va_copy(args2, args);
+ vsnprintf(ret, cnt + 1, fmt, args2);
+ va_end(args2);
+ }
+ mp_end(mp, ret + cnt + 1);
+ return ret - ofs;
+}
+
+char *
+mp_vprintf(struct mempool *mp, const char *fmt, va_list args)
+{
+ mp_start(mp, 1);
+ return mp_vprintf_at(mp, 0, fmt, args);
+}
+
+char *
+mp_printf(struct mempool *p, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char *res = mp_vprintf(p, fmt, args);
+ va_end(args);
+ return res;
+}
+
+char *
+mp_vprintf_append(struct mempool *mp, char *ptr, const char *fmt, va_list args)
+{
+ size_t ofs = mp_open(mp, ptr);
+ ASSERT(ofs && !ptr[ofs - 1]);
+ return mp_vprintf_at(mp, ofs - 1, fmt, args);
+}
+
+char *
+mp_printf_append(struct mempool *mp, char *ptr, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char *res = mp_vprintf_append(mp, ptr, fmt, args);
+ va_end(args);
+ return res;
+}
+
+#ifdef TEST
+
+int main(void)
+{
+ struct mempool *mp = mp_new(64);
+ char *x = mp_printf(mp, "<Hello, %s!>", "World");
+ fputs(x, stdout);
+ x = mp_printf_append(mp, x, "<Appended>");
+ fputs(x, stdout);
+ x = mp_printf(mp, "<Hello, %50s!>\n", "World");
+ fputs(x, stdout);
+ return 0;
+}
+
+#endif
diff --git a/contrib/ucw/mempool.c b/contrib/ucw/mempool.c
new file mode 100644
index 0000000..129b733
--- /dev/null
+++ b/contrib/ucw/mempool.c
@@ -0,0 +1,601 @@
+/*
+ * UCW Library -- Memory Pools (One-Time Allocation)
+ *
+ * (c) 1997--2014 Martin Mares <mj@ucw.cz>
+ * (c) 2007--2015 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#undef LOCAL_DEBUG
+
+#include <ucw/config.h>
+#include <ucw/lib.h>
+#include <ucw/alloc.h>
+#include <ucw/mempool.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+/* FIXME: migrate to Knot DNS version of mempools. */
+#pragma GCC diagnostic ignored "-Wpointer-arith"
+
+#define MP_CHUNK_TAIL ALIGN_TO(sizeof(struct mempool_chunk), CPU_STRUCT_ALIGN)
+#define MP_SIZE_MAX (SIZE_MAX - MP_CHUNK_TAIL - CPU_PAGE_SIZE)
+
+struct mempool_chunk {
+#ifdef CONFIG_DEBUG
+ struct mempool *pool; // Can be useful when analysing coredump for memory leaks
+#endif
+ struct mempool_chunk *next;
+ size_t size;
+};
+
+static size_t
+mp_align_size(size_t size)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ size = MAX(size, 64 + MP_CHUNK_TAIL);
+ return ALIGN_TO(size, CPU_PAGE_SIZE) - MP_CHUNK_TAIL;
+#else
+ return ALIGN_TO(size, CPU_STRUCT_ALIGN);
+#endif
+}
+
+static void *mp_allocator_alloc(struct ucw_allocator *a, size_t size)
+{
+ struct mempool *mp = (struct mempool *) a;
+ return mp_alloc_fast(mp, size);
+}
+
+static void *mp_allocator_realloc(struct ucw_allocator *a, void *ptr, size_t old_size, size_t new_size)
+{
+ if (new_size <= old_size)
+ return ptr;
+
+ /*
+ * In the future, we might want to do something like mp_realloc(),
+ * but we have to check that it is indeed the last block in the pool.
+ */
+ struct mempool *mp = (struct mempool *) a;
+ void *new = mp_alloc_fast(mp, new_size);
+ memcpy(new, ptr, old_size);
+ return new;
+}
+
+static void mp_allocator_free(struct ucw_allocator *a UNUSED, void *ptr UNUSED)
+{
+ // Does nothing
+}
+
+void
+mp_init(struct mempool *pool, size_t chunk_size)
+{
+ chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+ *pool = (struct mempool) {
+ .allocator = {
+ .alloc = mp_allocator_alloc,
+ .realloc = mp_allocator_realloc,
+ .free = mp_allocator_free,
+ },
+ .chunk_size = chunk_size,
+ .threshold = chunk_size >> 1,
+ .last_big = &pool->last_big
+ };
+}
+
+static void *
+mp_new_big_chunk(struct mempool *pool, size_t size)
+{
+ struct mempool_chunk *chunk;
+ chunk = malloc(size + MP_CHUNK_TAIL);
+ if (!chunk)
+ return NULL;
+ chunk = (struct mempool_chunk *)((char *)chunk + size);
+ chunk->size = size;
+ if (pool)
+ pool->total_size += size + MP_CHUNK_TAIL;
+ return chunk;
+}
+
+static void
+mp_free_big_chunk(struct mempool *pool, struct mempool_chunk *chunk)
+{
+ pool->total_size -= chunk->size + MP_CHUNK_TAIL;
+ free((void *)chunk - chunk->size);
+}
+
+static void *
+mp_new_chunk(struct mempool *pool, size_t size)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ struct mempool_chunk *chunk;
+ chunk = page_alloc(size + MP_CHUNK_TAIL) + size;
+ chunk->size = size;
+ if (pool)
+ pool->total_size += size + MP_CHUNK_TAIL;
+ return chunk;
+#else
+ return mp_new_big_chunk(pool, size);
+#endif
+}
+
+static void
+mp_free_chunk(struct mempool *pool, struct mempool_chunk *chunk)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ pool->total_size -= chunk->size + MP_CHUNK_TAIL;
+ page_free((void *)chunk - chunk->size, chunk->size + MP_CHUNK_TAIL);
+#else
+ mp_free_big_chunk(pool, chunk);
+#endif
+}
+
+struct mempool *
+mp_new(size_t chunk_size)
+{
+ chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+ struct mempool_chunk *chunk = mp_new_chunk(NULL, chunk_size);
+ struct mempool *pool = (void *)chunk - chunk_size;
+ DBG("Creating mempool %p with %u bytes long chunks", pool, chunk_size);
+ chunk->next = NULL;
+#ifdef CONFIG_DEBUG
+ chunk->pool = pool;
+#endif
+ *pool = (struct mempool) {
+ .allocator = {
+ .alloc = mp_allocator_alloc,
+ .realloc = mp_allocator_realloc,
+ .free = mp_allocator_free,
+ },
+ .state = { .free = { chunk_size - sizeof(*pool) }, .last = { chunk } },
+ .chunk_size = chunk_size,
+ .threshold = chunk_size >> 1,
+ .last_big = &pool->last_big,
+ .total_size = chunk->size + MP_CHUNK_TAIL,
+ };
+ return pool;
+}
+
+static void
+mp_free_chain(struct mempool *pool, struct mempool_chunk *chunk)
+{
+ while (chunk)
+ {
+ struct mempool_chunk *next = chunk->next;
+ mp_free_chunk(pool, chunk);
+ chunk = next;
+ }
+}
+
+static void
+mp_free_big_chain(struct mempool *pool, struct mempool_chunk *chunk)
+{
+ while (chunk)
+ {
+ struct mempool_chunk *next = chunk->next;
+ mp_free_big_chunk(pool, chunk);
+ chunk = next;
+ }
+}
+
+void
+mp_delete(struct mempool *pool)
+{
+ DBG("Deleting mempool %p", pool);
+ mp_free_big_chain(pool, pool->state.last[1]);
+ mp_free_chain(pool, pool->unused);
+ mp_free_chain(pool, pool->state.last[0]); // can contain the mempool structure
+}
+
+void
+mp_flush(struct mempool *pool)
+{
+ mp_free_big_chain(pool, pool->state.last[1]);
+ struct mempool_chunk *chunk, *next;
+ for (chunk = pool->state.last[0]; chunk && (void *)chunk - chunk->size != pool; chunk = next)
+ {
+ next = chunk->next;
+ chunk->next = pool->unused;
+ pool->unused = chunk;
+ }
+ pool->state.last[0] = chunk;
+ pool->state.free[0] = chunk ? chunk->size - sizeof(*pool) : 0;
+ pool->state.last[1] = NULL;
+ pool->state.free[1] = 0;
+ pool->state.next = NULL;
+ pool->last_big = &pool->last_big;
+}
+
+static void
+mp_stats_chain(struct mempool *pool, struct mempool_chunk *chunk, struct mempool_stats *stats, uint idx)
+{
+ while (chunk)
+ {
+ stats->chain_size[idx] += chunk->size + MP_CHUNK_TAIL;
+ stats->chain_count[idx]++;
+ if (idx < 2)
+ {
+ stats->used_size += chunk->size;
+ if ((byte *)pool == (byte *)chunk - chunk->size)
+ stats->used_size -= sizeof(*pool);
+ }
+ chunk = chunk->next;
+ }
+ stats->total_size += stats->chain_size[idx];
+}
+
+void
+mp_stats(struct mempool *pool, struct mempool_stats *stats)
+{
+ bzero(stats, sizeof(*stats));
+ mp_stats_chain(pool, pool->state.last[0], stats, 0);
+ mp_stats_chain(pool, pool->state.last[1], stats, 1);
+ mp_stats_chain(pool, pool->unused, stats, 2);
+ stats->used_size -= pool->state.free[0] + pool->state.free[1];
+ ASSERT(stats->total_size == pool->total_size);
+ ASSERT(stats->used_size <= stats->total_size);
+}
+
+u64
+mp_total_size(struct mempool *pool)
+{
+ return pool->total_size;
+}
+
+void
+mp_shrink(struct mempool *pool, u64 min_total_size)
+{
+ while (1)
+ {
+ struct mempool_chunk *chunk = pool->unused;
+ if (!chunk || pool->total_size - (chunk->size + MP_CHUNK_TAIL) < min_total_size)
+ break;
+ pool->unused = chunk->next;
+ mp_free_chunk(pool, chunk);
+ }
+}
+
+void *
+mp_alloc_internal(struct mempool *pool, size_t size)
+{
+ struct mempool_chunk *chunk;
+ if (size <= pool->threshold)
+ {
+ pool->idx = 0;
+ if (pool->unused)
+ {
+ chunk = pool->unused;
+ pool->unused = chunk->next;
+ }
+ else
+ {
+ chunk = mp_new_chunk(pool, pool->chunk_size);
+#ifdef CONFIG_DEBUG
+ chunk->pool = pool;
+#endif
+ }
+ chunk->next = pool->state.last[0];
+ pool->state.last[0] = chunk;
+ pool->state.free[0] = pool->chunk_size - size;
+ return (void *)chunk - pool->chunk_size;
+ }
+ else if (likely(size <= MP_SIZE_MAX))
+ {
+ pool->idx = 1;
+ size_t aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN);
+ chunk = mp_new_big_chunk(pool, aligned);
+ chunk->next = pool->state.last[1];
+#ifdef CONFIG_DEBUG
+ chunk->pool = pool;
+#endif
+ pool->state.last[1] = chunk;
+ pool->state.free[1] = aligned - size;
+ return pool->last_big = (void *)chunk - aligned;
+ }
+ else
+ return NULL;
+}
+
+void *
+mp_alloc(struct mempool *pool, size_t size)
+{
+ return mp_alloc_fast(pool, size);
+}
+
+void *
+mp_alloc_noalign(struct mempool *pool, size_t size)
+{
+ return mp_alloc_fast_noalign(pool, size);
+}
+
+void *
+mp_alloc_zero(struct mempool *pool, size_t size)
+{
+ void *ptr = mp_alloc_fast(pool, size);
+ bzero(ptr, size);
+ return ptr;
+}
+
+void *
+mp_start_internal(struct mempool *pool, size_t size)
+{
+ void *ptr = mp_alloc_internal(pool, size);
+ if (!ptr)
+ return NULL;
+ pool->state.free[pool->idx] += size;
+ return ptr;
+}
+
+void *
+mp_start(struct mempool *pool, size_t size)
+{
+ return mp_start_fast(pool, size);
+}
+
+void *
+mp_start_noalign(struct mempool *pool, size_t size)
+{
+ return mp_start_fast_noalign(pool, size);
+}
+
+void *
+mp_grow_internal(struct mempool *pool, size_t size)
+{
+ if (unlikely(size > MP_SIZE_MAX))
+ return NULL;
+ size_t avail = mp_avail(pool);
+ void *ptr = mp_ptr(pool);
+ if (pool->idx)
+ {
+ size_t amortized = likely(avail <= MP_SIZE_MAX / 2) ? avail * 2 : MP_SIZE_MAX;
+ amortized = MAX(amortized, size);
+ amortized = ALIGN_TO(amortized, CPU_STRUCT_ALIGN);
+ struct mempool_chunk *chunk = pool->state.last[1], *next = chunk->next;
+ pool->total_size = pool->total_size - chunk->size + amortized;
+ void *nptr = realloc(ptr, amortized + MP_CHUNK_TAIL);
+ if (!nptr)
+ return NULL;
+ ptr = nptr;
+ chunk = ptr + amortized;
+ chunk->next = next;
+ chunk->size = amortized;
+ pool->state.last[1] = chunk;
+ pool->state.free[1] = amortized;
+ pool->last_big = ptr;
+ return ptr;
+ }
+ else
+ {
+ void *p = mp_start_internal(pool, size);
+ memcpy(p, ptr, avail);
+ return p;
+ }
+}
+
+size_t
+mp_open(struct mempool *pool, void *ptr)
+{
+ return mp_open_fast(pool, ptr);
+}
+
+void *
+mp_realloc(struct mempool *pool, void *ptr, size_t size)
+{
+ return mp_realloc_fast(pool, ptr, size);
+}
+
+void *
+mp_realloc_zero(struct mempool *pool, void *ptr, size_t size)
+{
+ size_t old_size = mp_open_fast(pool, ptr);
+ ptr = mp_grow(pool, size);
+ if (size > old_size)
+ bzero(ptr + old_size, size - old_size);
+ mp_end(pool, ptr + size);
+ return ptr;
+}
+
+void *
+mp_spread_internal(struct mempool *pool, void *p, size_t size)
+{
+ void *old = mp_ptr(pool);
+ void *new = mp_grow_internal(pool, p-old+size);
+ if (!new) {
+ return NULL;
+ }
+ return p-old+new;
+}
+
+void
+mp_restore(struct mempool *pool, struct mempool_state *state)
+{
+ struct mempool_chunk *chunk, *next;
+ struct mempool_state s = *state;
+ for (chunk = pool->state.last[0]; chunk != s.last[0]; chunk = next)
+ {
+ next = chunk->next;
+ chunk->next = pool->unused;
+ pool->unused = chunk;
+ }
+ for (chunk = pool->state.last[1]; chunk != s.last[1]; chunk = next)
+ {
+ next = chunk->next;
+ mp_free_big_chunk(pool, chunk);
+ }
+ pool->state = s;
+ pool->last_big = &pool->last_big;
+}
+
+struct mempool_state *
+mp_push(struct mempool *pool)
+{
+ struct mempool_state state = pool->state;
+ struct mempool_state *p = mp_alloc_fast(pool, sizeof(*p));
+ *p = state;
+ pool->state.next = p;
+ return p;
+}
+
+void
+mp_pop(struct mempool *pool)
+{
+ ASSERT(pool->state.next);
+ mp_restore(pool, pool->state.next);
+}
+
+#ifdef TEST
+
+#include <ucw/getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+static void
+fill(byte *ptr, uint len, uint magic)
+{
+ while (len--)
+ *ptr++ = (magic++ & 255);
+}
+
+static void
+check(byte *ptr, uint len, uint magic, uint align)
+{
+ ASSERT(!((uintptr_t)ptr & (align - 1)));
+ while (len--)
+ if (*ptr++ != (magic++ & 255))
+ ASSERT(0);
+}
+
+int main(int argc, char **argv)
+{
+ srand(time(NULL));
+ log_init(argv[0]);
+ cf_def_file = NULL;
+ if (cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) >= 0 || argc != optind)
+ die("Invalid usage");
+
+ uint max = 1000, n = 0, m = 0, can_realloc = 0;
+ void *ptr[max];
+ struct mempool_state *state[max];
+ uint len[max], num[max], align[max];
+ struct mempool *mp = mp_new(128), mp_static;
+
+ for (uint i = 0; i < 5000; i++)
+ {
+ for (uint j = 0; j < n; j++)
+ check(ptr[j], len[j], j, align[j]);
+#if 0
+ DBG("free_small=%u free_big=%u idx=%u chunk_size=%u last_big=%p", mp->state.free[0], mp->state.free[1], mp->idx, mp->chunk_size, mp->last_big);
+ for (struct mempool_chunk *ch = mp->state.last[0]; ch; ch = ch->next)
+ DBG("small %p %p %p %d", (byte *)ch - ch->size, ch, ch + 1, ch->size);
+ for (struct mempool_chunk *ch = mp->state.last[1]; ch; ch = ch->next)
+ DBG("big %p %p %p %d", (byte *)ch - ch->size, ch, ch + 1, ch->size);
+#endif
+ int r = random_max(100);
+ if ((r -= 1) < 0)
+ {
+ DBG("flush");
+ mp_flush(mp);
+ n = m = 0;
+ }
+ else if ((r -= 1) < 0)
+ {
+ DBG("delete & new");
+ mp_delete(mp);
+ if (random_max(2))
+ mp = mp_new(random_max(0x1000) + 1);
+ else
+ mp = &mp_static, mp_init(mp, random_max(512) + 1);
+ n = m = 0;
+ }
+ else if (n < max && (r -= 30) < 0)
+ {
+ len[n] = random_max(0x2000);
+ DBG("alloc(%u)", len[n]);
+ align[n] = random_max(2) ? CPU_STRUCT_ALIGN : 1;
+ ptr[n] = (align[n] == 1) ? mp_alloc_fast_noalign(mp, len[n]) : mp_alloc_fast(mp, len[n]);
+ DBG(" -> (%p)", ptr[n]);
+ fill(ptr[n], len[n], n);
+ n++;
+ can_realloc = 1;
+ }
+ else if (n < max && (r -= 20) < 0)
+ {
+ len[n] = random_max(0x2000);
+ DBG("start(%u)", len[n]);
+ align[n] = random_max(2) ? CPU_STRUCT_ALIGN : 1;
+ ptr[n] = (align[n] == 1) ? mp_start_fast_noalign(mp, len[n]) : mp_start_fast(mp, len[n]);
+ DBG(" -> (%p)", ptr[n]);
+ fill(ptr[n], len[n], n);
+ n++;
+ can_realloc = 1;
+ goto grow;
+ }
+ else if (can_realloc && n && (r -= 10) < 0)
+ {
+ if (mp_open(mp, ptr[n - 1]) != len[n - 1])
+ ASSERT(0);
+grow:
+ {
+ uint k = n - 1;
+ for (uint i = random_max(4); i--; )
+ {
+ uint l = len[k];
+ len[k] = random_max(0x2000);
+ DBG("grow(%u)", len[k]);
+ ptr[k] = mp_grow(mp, len[k]);
+ DBG(" -> (%p)", ptr[k]);
+ check(ptr[k], MIN(l, len[k]), k, align[k]);
+ fill(ptr[k], len[k], k);
+ }
+ mp_end(mp, ptr[k] + len[k]);
+ }
+ }
+ else if (can_realloc && n && (r -= 20) < 0)
+ {
+ uint i = n - 1, l = len[i];
+ DBG("realloc(%p, %u)", ptr[i], len[i]);
+ ptr[i] = mp_realloc(mp, ptr[i], len[i] = random_max(0x2000));
+ DBG(" -> (%p, %u)", ptr[i], len[i]);
+ check(ptr[i], MIN(len[i], l), i, align[i]);
+ fill(ptr[i], len[i], i);
+ }
+ else if (m < max && (r -= 5) < 0)
+ {
+ DBG("push(%u)", m);
+ num[m] = n;
+ state[m++] = mp_push(mp);
+ can_realloc = 0;
+ }
+ else if (m && (r -= 2) < 0)
+ {
+ m--;
+ DBG("pop(%u)", m);
+ mp_pop(mp);
+ n = num[m];
+ can_realloc = 0;
+ }
+ else if (m && (r -= 1) < 0)
+ {
+ uint i = random_max(m);
+ DBG("restore(%u)", i);
+ mp_restore(mp, state[i]);
+ n = num[m = i];
+ can_realloc = 0;
+ }
+ else if (can_realloc && n && (r -= 5) < 0)
+ ASSERT(mp_size(mp, ptr[n - 1]) == len[n - 1]);
+ else
+ {
+ struct mempool_stats stats;
+ mp_stats(mp, &stats);
+ }
+ }
+
+ mp_delete(mp);
+ return 0;
+}
+
+#endif
diff --git a/contrib/ucw/mempool.h b/contrib/ucw/mempool.h
new file mode 100644
index 0000000..8cb1d57
--- /dev/null
+++ b/contrib/ucw/mempool.h
@@ -0,0 +1,565 @@
+/*
+ * UCW Library -- Memory Pools
+ *
+ * (c) 1997--2015 Martin Mares <mj@ucw.cz>
+ * (c) 2007 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#ifndef _UCW_POOLS_H
+#define _UCW_POOLS_H
+
+#include <ucw/alloc.h>
+#include <ucw/config.h>
+#include <ucw/lib.h>
+#include <string.h>
+
+#ifdef CONFIG_UCW_CLEAN_ABI
+#define mp_alloc ucw_mp_alloc
+#define mp_alloc_internal ucw_mp_alloc_internal
+#define mp_alloc_noalign ucw_mp_alloc_noalign
+#define mp_alloc_zero ucw_mp_alloc_zero
+#define mp_delete ucw_mp_delete
+#define mp_flush ucw_mp_flush
+#define mp_grow_internal ucw_mp_grow_internal
+#define mp_init ucw_mp_init
+#define mp_memdup ucw_mp_memdup
+#define mp_multicat ucw_mp_multicat
+#define mp_new ucw_mp_new
+#define mp_open ucw_mp_open
+#define mp_pop ucw_mp_pop
+#define mp_printf ucw_mp_printf
+#define mp_printf_append ucw_mp_printf_append
+#define mp_push ucw_mp_push
+#define mp_realloc ucw_mp_realloc
+#define mp_realloc_zero ucw_mp_realloc_zero
+#define mp_restore ucw_mp_restore
+#define mp_shrink ucw_mp_shrink
+#define mp_spread_internal ucw_mp_spread_internal
+#define mp_start ucw_mp_start
+#define mp_start_internal ucw_mp_start_internal
+#define mp_start_noalign ucw_mp_start_noalign
+#define mp_stats ucw_mp_stats
+#define mp_str_from_mem ucw_mp_str_from_mem
+#define mp_strdup ucw_mp_strdup
+#define mp_strjoin ucw_mp_strjoin
+#define mp_total_size ucw_mp_total_size
+#define mp_vprintf ucw_mp_vprintf
+#define mp_vprintf_append ucw_mp_vprintf_append
+#endif
+
+/***
+ * [[defs]]
+ * Definitions
+ * -----------
+ ***/
+
+/**
+ * Memory pool state (see @mp_push(), ...).
+ * You should use this one as an opaque handle only, the insides are internal.
+ **/
+struct mempool_state {
+ size_t free[2];
+ void *last[2];
+ struct mempool_state *next;
+};
+
+/**
+ * Memory pool.
+ * You should use this one as an opaque handle only, the insides are internal.
+ **/
+struct mempool {
+ struct ucw_allocator allocator; // This must be the first element
+ struct mempool_state state;
+ void *unused, *last_big;
+ size_t chunk_size, threshold;
+ uint idx;
+ u64 total_size;
+};
+
+struct mempool_stats { /** Mempool statistics. See @mp_stats(). **/
+ u64 total_size; /* Real allocated size in bytes */
+ u64 used_size; /* Estimated size allocated from mempool to application */
+ uint chain_count[3]; /* Number of allocated chunks in small/big/unused chains */
+ u64 chain_size[3]; /* Size of allocated chunks in small/big/unused chains */
+};
+
+/***
+ * [[basic]]
+ * Basic manipulation
+ * ------------------
+ ***/
+
+/**
+ * Initialize a given mempool structure.
+ * @chunk_size must be in the interval `[1, SIZE_MAX / 2]`.
+ * It will allocate memory by this large chunks and take
+ * memory to satisfy requests from them.
+ *
+ * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
+ **/
+void mp_init(struct mempool *pool, size_t chunk_size);
+
+/**
+ * Allocate and initialize a new memory pool.
+ * See @mp_init() for @chunk_size limitations.
+ *
+ * The new mempool structure is allocated on the new mempool.
+ *
+ * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
+ **/
+struct mempool *mp_new(size_t chunk_size);
+
+/**
+ * Cleanup mempool initialized by mp_init or mp_new.
+ * Frees all the memory allocated by this mempool and,
+ * if created by @mp_new(), the @pool itself.
+ **/
+void mp_delete(struct mempool *pool);
+
+/**
+ * Frees all data on a memory pool, but leaves it working.
+ * It can keep some of the chunks allocated to serve
+ * further allocation requests. Leaves the @pool alive,
+ * even if it was created with @mp_new().
+ **/
+void mp_flush(struct mempool *pool);
+
+/**
+ * Compute some statistics for debug purposes.
+ * See the definition of the <<struct_mempool_stats,mempool_stats structure>>.
+ * This function scans the chunk list, so it can be slow. If you are interested
+ * in total memory consumption only, mp_total_size() is faster.
+ **/
+void mp_stats(struct mempool *pool, struct mempool_stats *stats);
+
+/**
+ * Return how many bytes were allocated by the pool, including unused parts
+ * of chunks. This function runs in constant time.
+ **/
+u64 mp_total_size(struct mempool *pool);
+
+/**
+ * Release unused chunks of memory reserved for further allocation
+ * requests, but stop if mp_total_size() would drop below @min_total_size.
+ **/
+void mp_shrink(struct mempool *pool, u64 min_total_size);
+
+/***
+ * [[alloc]]
+ * Allocation routines
+ * -------------------
+ ***/
+
+/* For internal use only, do not call directly */
+void *mp_alloc_internal(struct mempool *pool, size_t size) LIKE_MALLOC;
+
+/**
+ * The function allocates new @size bytes on a given memory pool.
+ * If the @size is zero, the resulting pointer is undefined,
+ * but it may be safely reallocated or used as the parameter
+ * to other functions below.
+ *
+ * The resulting pointer is always aligned to a multiple of
+ * `CPU_STRUCT_ALIGN` bytes and this condition remains true also
+ * after future reallocations.
+ **/
+void *mp_alloc(struct mempool *pool, size_t size);
+
+/**
+ * The same as @mp_alloc(), but the result may be unaligned.
+ **/
+void *mp_alloc_noalign(struct mempool *pool, size_t size);
+
+/**
+ * The same as @mp_alloc(), but fills the newly allocated memory with zeroes.
+ **/
+void *mp_alloc_zero(struct mempool *pool, size_t size);
+
+/**
+ * Inlined version of @mp_alloc().
+ **/
+static inline void *mp_alloc_fast(struct mempool *pool, size_t size)
+{
+ size_t avail = pool->state.free[0] & ~(size_t)(CPU_STRUCT_ALIGN - 1);
+ if (size <= avail)
+ {
+ pool->state.free[0] = avail - size;
+ return (byte *)pool->state.last[0] - avail;
+ }
+ else
+ return mp_alloc_internal(pool, size);
+}
+
+/**
+ * Inlined version of @mp_alloc_noalign().
+ **/
+static inline void *mp_alloc_fast_noalign(struct mempool *pool, size_t size)
+{
+ if (size <= pool->state.free[0])
+ {
+ void *ptr = (byte *)pool->state.last[0] - pool->state.free[0];
+ pool->state.free[0] -= size;
+ return ptr;
+ }
+ else
+ return mp_alloc_internal(pool, size);
+}
+
+/**
+ * Return a generic allocator representing the given mempool.
+ **/
+static inline struct ucw_allocator *mp_get_allocator(struct mempool *mp)
+{
+ return &mp->allocator;
+}
+
+/***
+ * [[gbuf]]
+ * Growing buffers
+ * ---------------
+ *
+ * You do not need to know, how a buffer will need to be large,
+ * you can grow it incrementally to needed size. You can grow only
+ * one buffer at a time on a given mempool.
+ *
+ * Similar functionality is provided by <<growbuf:,growing buffes>> module.
+ ***/
+
+/* For internal use only, do not call directly */
+void *mp_start_internal(struct mempool *pool, size_t size) LIKE_MALLOC;
+void *mp_grow_internal(struct mempool *pool, size_t size);
+void *mp_spread_internal(struct mempool *pool, void *p, size_t size);
+
+static inline uint mp_idx(struct mempool *pool, void *ptr)
+{
+ return ptr == pool->last_big;
+}
+
+/**
+ * Open a new growing buffer (at least @size bytes long).
+ * If the @size is zero, the resulting pointer is undefined,
+ * but it may be safely reallocated or used as the parameter
+ * to other functions below.
+ *
+ * The resulting pointer is always aligned to a multiple of
+ * `CPU_STRUCT_ALIGN` bytes and this condition remains true also
+ * after future reallocations. There is an unaligned version as well.
+ *
+ * Keep in mind that you can't make any other pool allocations
+ * before you "close" the growing buffer with @mp_end().
+ */
+void *mp_start(struct mempool *pool, size_t size);
+void *mp_start_noalign(struct mempool *pool, size_t size);
+
+/**
+ * Inlined version of @mp_start().
+ **/
+static inline void *mp_start_fast(struct mempool *pool, size_t size)
+{
+ size_t avail = pool->state.free[0] & ~(size_t)(CPU_STRUCT_ALIGN - 1);
+ if (size <= avail)
+ {
+ pool->idx = 0;
+ pool->state.free[0] = avail;
+ return (byte *)pool->state.last[0] - avail;
+ }
+ else
+ return mp_start_internal(pool, size);
+}
+
+/**
+ * Inlined version of @mp_start_noalign().
+ **/
+static inline void *mp_start_fast_noalign(struct mempool *pool, size_t size)
+{
+ if (size <= pool->state.free[0])
+ {
+ pool->idx = 0;
+ return (byte *)pool->state.last[0] - pool->state.free[0];
+ }
+ else
+ return mp_start_internal(pool, size);
+}
+
+/**
+ * Return start pointer of the growing buffer allocated by latest @mp_start() or a similar function.
+ **/
+static inline void *mp_ptr(struct mempool *pool)
+{
+ return (byte *)pool->state.last[pool->idx] - pool->state.free[pool->idx];
+}
+
+/**
+ * Return the number of bytes available for extending the growing buffer.
+ * (Before a reallocation will be needed).
+ **/
+static inline size_t mp_avail(struct mempool *pool)
+{
+ return pool->state.free[pool->idx];
+}
+
+/**
+ * Grow the buffer allocated by @mp_start() to be at least @size bytes long
+ * (@size may be less than @mp_avail(), even zero). Reallocated buffer may
+ * change its starting position. The content will be unchanged to the minimum
+ * of the old and new sizes; newly allocated memory will be uninitialized.
+ * Multiple calls to mp_grow() have amortized linear cost wrt. the maximum value of @size. */
+static inline void *mp_grow(struct mempool *pool, size_t size)
+{
+ return (size <= mp_avail(pool)) ? mp_ptr(pool) : mp_grow_internal(pool, size);
+}
+
+/**
+ * Grow the buffer by at least one byte -- equivalent to <<mp_grow(),`mp_grow`>>`(@pool, @mp_avail(pool) + 1)`.
+ **/
+static inline void *mp_expand(struct mempool *pool)
+{
+ return mp_grow_internal(pool, mp_avail(pool) + 1);
+}
+
+/**
+ * Ensure that there is at least @size bytes free after @p,
+ * if not, reallocate and adjust @p.
+ **/
+static inline void *mp_spread(struct mempool *pool, void *p, size_t size)
+{
+ return (((size_t)((byte *)pool->state.last[pool->idx] - (byte *)p) >= size) ? p : mp_spread_internal(pool, p, size));
+}
+
+/**
+ * Append a character to the growing buffer. Called with @p pointing after
+ * the last byte in the buffer, returns a pointer after the last byte
+ * of the new (possibly reallocated) buffer.
+ **/
+static inline char *mp_append_char(struct mempool *pool, char *p, uint c)
+{
+ p = mp_spread(pool, p, 1);
+ *p++ = c;
+ return p;
+}
+
+/**
+ * Append a memory block to the growing buffer. Called with @p pointing after
+ * the last byte in the buffer, returns a pointer after the last byte
+ * of the new (possibly reallocated) buffer.
+ **/
+static inline void *mp_append_block(struct mempool *pool, void *p, const void *block, size_t size)
+{
+ char *q = mp_spread(pool, p, size);
+ memcpy(q, block, size);
+ return q + size;
+}
+
+/**
+ * Append a string to the growing buffer. Called with @p pointing after
+ * the last byte in the buffer, returns a pointer after the last byte
+ * of the new (possibly reallocated) buffer.
+ **/
+static inline void *mp_append_string(struct mempool *pool, void *p, const char *str)
+{
+ return mp_append_block(pool, p, str, strlen(str));
+}
+
+/**
+ * Close the growing buffer. The @end must point just behind the data, you want to keep
+ * allocated (so it can be in the interval `[@mp_ptr(@pool), @mp_ptr(@pool) + @mp_avail(@pool)]`).
+ * Returns a pointer to the beginning of the just closed block.
+ **/
+static inline void *mp_end(struct mempool *pool, void *end)
+{
+ void *p = mp_ptr(pool);
+ pool->state.free[pool->idx] = (byte *)pool->state.last[pool->idx] - (byte *)end;
+ return p;
+}
+
+/**
+ * Close the growing buffer as a string. That is, append a zero byte and call mp_end().
+ **/
+static inline char *mp_end_string(struct mempool *pool, void *end)
+{
+ end = mp_append_char(pool, end, 0);
+ return mp_end(pool, end);
+}
+
+/**
+ * Return size in bytes of the last allocated memory block (with @mp_alloc() or @mp_end()).
+ **/
+static inline size_t mp_size(struct mempool *pool, void *ptr)
+{
+ uint idx = mp_idx(pool, ptr);
+ return ((byte *)pool->state.last[idx] - (byte *)ptr) - pool->state.free[idx];
+}
+
+/**
+ * Open the last memory block (allocated with @mp_alloc() or @mp_end())
+ * for growing and return its size in bytes. The contents and the start pointer
+ * remain unchanged. Do not forget to call @mp_end() to close it.
+ **/
+size_t mp_open(struct mempool *pool, void *ptr);
+
+/**
+ * Inlined version of @mp_open().
+ **/
+static inline size_t mp_open_fast(struct mempool *pool, void *ptr)
+{
+ pool->idx = mp_idx(pool, ptr);
+ size_t size = ((byte *)pool->state.last[pool->idx] - (byte *)ptr) - pool->state.free[pool->idx];
+ pool->state.free[pool->idx] += size;
+ return size;
+}
+
+/**
+ * Reallocate the last memory block (allocated with @mp_alloc() or @mp_end())
+ * to the new @size. Behavior is similar to @mp_grow(), but the resulting
+ * block is closed.
+ **/
+void *mp_realloc(struct mempool *pool, void *ptr, size_t size);
+
+/**
+ * The same as @mp_realloc(), but fills the additional bytes (if any) with zeroes.
+ **/
+void *mp_realloc_zero(struct mempool *pool, void *ptr, size_t size);
+
+/**
+ * Inlined version of @mp_realloc().
+ **/
+static inline void *mp_realloc_fast(struct mempool *pool, void *ptr, size_t size)
+{
+ mp_open_fast(pool, ptr);
+ ptr = mp_grow(pool, size);
+ mp_end(pool, (byte *)ptr + size);
+ return ptr;
+}
+
+/***
+ * [[store]]
+ * Storing and restoring state
+ * ---------------------------
+ *
+ * Mempools can remember history of what was allocated and return back
+ * in time.
+ ***/
+
+/**
+ * Save the current state of a memory pool.
+ * Do not call this function with an opened growing buffer.
+ **/
+static inline void mp_save(struct mempool *pool, struct mempool_state *state)
+{
+ *state = pool->state;
+ pool->state.next = state;
+}
+
+/**
+ * Save the current state to a newly allocated mempool_state structure.
+ * Do not call this function with an opened growing buffer.
+ **/
+struct mempool_state *mp_push(struct mempool *pool);
+
+/**
+ * Restore the state saved by @mp_save() or @mp_push() and free all
+ * data allocated after that point (including the state structure itself).
+ * You can't reallocate the last memory block from the saved state.
+ **/
+void mp_restore(struct mempool *pool, struct mempool_state *state);
+
+/**
+ * Inlined version of @mp_restore().
+ **/
+static inline void mp_restore_fast(struct mempool *pool, struct mempool_state *state)
+{
+ if (pool->state.last[0] != state->last[0] || pool->state.last[1] != state->last[1])
+ mp_restore(pool, state);
+ else
+ {
+ pool->state = *state;
+ pool->last_big = &pool->last_big;
+ }
+}
+
+/**
+ * Restore the state saved by the last call to @mp_push().
+ * @mp_pop() and @mp_push() works as a stack so you can push more states safely.
+ **/
+void mp_pop(struct mempool *pool);
+
+
+/***
+ * [[string]]
+ * String operations
+ * -----------------
+ ***/
+
+char *mp_strdup(struct mempool *, const char *) LIKE_MALLOC; /** Makes a copy of a string on a mempool. Returns NULL for NULL string. **/
+void *mp_memdup(struct mempool *, const void *, size_t) LIKE_MALLOC; /** Makes a copy of a memory block on a mempool. **/
+/**
+ * Concatenates all passed strings. The last parameter must be NULL.
+ * This will concatenate two strings:
+ *
+ * char *message = mp_multicat(pool, "hello ", "world", NULL);
+ **/
+char *mp_multicat(struct mempool *, ...) LIKE_MALLOC SENTINEL_CHECK;
+/**
+ * Concatenates two strings and stores result on @mp.
+ */
+static inline char *LIKE_MALLOC mp_strcat(struct mempool *mp, const char *x, const char *y)
+{
+ return mp_multicat(mp, x, y, NULL);
+}
+/**
+ * Join strings and place @sep between each two neighboring.
+ * @p is the mempool to provide memory, @a is array of strings and @n
+ * tells how many there is of them.
+ **/
+char *mp_strjoin(struct mempool *p, char **a, uint n, uint sep) LIKE_MALLOC;
+/**
+ * Convert memory block to a string. Makes a copy of the given memory block
+ * in the mempool @p, adding an extra terminating zero byte at the end.
+ **/
+char *mp_str_from_mem(struct mempool *p, const void *mem, size_t len) LIKE_MALLOC;
+
+
+/***
+ * [[format]]
+ * Formatted output
+ * ---------------
+ ***/
+
+/**
+ * printf() into a in-memory string, allocated on the memory pool.
+ **/
+char *mp_printf(struct mempool *mp, const char *fmt, ...) FORMAT_CHECK(printf,2,3) LIKE_MALLOC;
+/**
+ * Like @mp_printf(), but uses `va_list` for parameters.
+ **/
+char *mp_vprintf(struct mempool *mp, const char *fmt, va_list args) LIKE_MALLOC;
+/**
+ * Like @mp_printf(), but it appends the data at the end of string
+ * pointed to by @ptr. The string is @mp_open()ed, so you have to
+ * provide something that can be.
+ *
+ * Returns pointer to the beginning of the string (the pointer may have
+ * changed due to reallocation).
+ *
+ * In some versions of LibUCW, this function was called mp_append_printf(). However,
+ * this name turned out to be confusing -- unlike other appending functions, this one is
+ * not called on an opened growing buffer. The old name will be preserved for backward
+ * compatibility for the time being.
+ **/
+char *mp_printf_append(struct mempool *mp, char *ptr, const char *fmt, ...) FORMAT_CHECK(printf,3,4);
+#define mp_append_printf mp_printf_append
+/**
+ * Like @mp_printf_append(), but uses `va_list` for parameters.
+ *
+ * In some versions of LibUCW, this function was called mp_append_vprintf(). However,
+ * this name turned out to be confusing -- unlike other appending functions, this one is
+ * not called on an opened growing buffer. The old name will be preserved for backward
+ * compatibility for the time being.
+ **/
+char *mp_vprintf_append(struct mempool *mp, char *ptr, const char *fmt, va_list args);
+#define mp_append_vprintf mp_vprintf_append
+
+#endif
diff --git a/contrib/wire.h b/contrib/wire.h
new file mode 100644
index 0000000..b02296e
--- /dev/null
+++ b/contrib/wire.h
@@ -0,0 +1,175 @@
+/* Copyright (C) 2011-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+/*!
+ * \file
+ *
+ * \brief Wire integer operations.
+ *
+ * \addtogroup contrib
+ * @{
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(__linux__) || defined(__gnu_hurd__) || \
+ (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
+# include <endian.h>
+# ifndef be64toh
+# include <arpa/inet.h>
+# include <byteswap.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define be16toh(x) ntohs(x)
+# define be32toh(x) ntohl(x)
+# define be64toh(x) bswap_64 (x)
+# define le16toh(x) (x)
+# define le32toh(x) (x)
+# define le64toh(x) (x)
+# else
+# define be16toh(x) (x)
+# define be32toh(x) (x)
+# define be64toh(x) (x)
+# define le16toh(x) ntohs(x)
+# define le32toh(x) ntohl(x)
+# define le64toh(x) bswap_64 (x)
+# endif
+# endif
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+# include <sys/endian.h>
+#elif defined(__OpenBSD__)
+# include <endian.h>
+#elif defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+# define be16toh(x) OSSwapBigToHostInt16(x)
+# define be32toh(x) OSSwapBigToHostInt32(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+# define htobe16(x) OSSwapHostToBigInt16(x)
+# define htobe32(x) OSSwapHostToBigInt32(x)
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define le16toh(x) OSSwapLittleToHostInt16(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+# define le64toh(x) OSSwapLittleToHostInt64(x)
+# define htole16(x) OSSwapHostToLittleInt16(x)
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define htole64(x) OSSwapHostToLittleInt64(x)
+#endif
+
+/*!
+ * \brief Reads 2 bytes from the wireformat data.
+ *
+ * \param pos Data to read the 2 bytes from.
+ *
+ * \return The 2 bytes read, in host byte order.
+ */
+inline static uint16_t wire_read_u16(const uint8_t *pos)
+{
+ return be16toh(*(uint16_t *)pos);
+}
+
+/*!
+ * \brief Reads 4 bytes from the wireformat data.
+ *
+ * \param pos Data to read the 4 bytes from.
+ *
+ * \return The 4 bytes read, in host byte order.
+ */
+inline static uint32_t wire_read_u32(const uint8_t *pos)
+{
+ return be32toh(*(uint32_t *)pos);
+}
+
+/*!
+ * \brief Reads 6 bytes from the wireformat data.
+ *
+ * \param pos Data to read the 6 bytes from.
+ *
+ * \return The 6 bytes read, in host byte order.
+ */
+inline static uint64_t wire_read_u48(const uint8_t *pos)
+{
+ uint64_t input = 0;
+ memcpy((uint8_t *)&input + 1, pos, 6);
+ return be64toh(input) >> 8;
+}
+
+/*!
+ * \brief Read 8 bytes from the wireformat data.
+ *
+ * \param pos Data to read the 8 bytes from.
+ *
+ * \return The 8 bytes read, in host byte order.
+ */
+inline static uint64_t wire_read_u64(const uint8_t *pos)
+{
+ return be64toh(*(uint64_t *)pos);
+}
+
+/*!
+ * \brief Writes 2 bytes in wireformat.
+ *
+ * The data are stored in network byte order (big endian).
+ *
+ * \param pos Position where to put the 2 bytes.
+ * \param data Data to put.
+ */
+inline static void wire_write_u16(uint8_t *pos, uint16_t data)
+{
+ *(uint16_t *)pos = htobe16(data);
+}
+
+/*!
+ * \brief Writes 4 bytes in wireformat.
+ *
+ * The data are stored in network byte order (big endian).
+ *
+ * \param pos Position where to put the 4 bytes.
+ * \param data Data to put.
+ */
+inline static void wire_write_u32(uint8_t *pos, uint32_t data)
+{
+ *(uint32_t *)pos = htobe32(data);
+}
+
+/*!
+ * \brief Writes 6 bytes in wireformat.
+ *
+ * The data are stored in network byte order (big endian).
+ *
+ * \param pos Position where to put the 4 bytes.
+ * \param data Data to put.
+ */
+inline static void wire_write_u48(uint8_t *pos, uint64_t data)
+{
+ uint64_t swapped = htobe64(data << 8);
+ memcpy(pos, (uint8_t *)&swapped + 1, 6);
+}
+
+/*!
+ * \brief Writes 8 bytes in wireformat.
+ *
+ * The data are stored in network byte order (big endian).
+ *
+ * \param pos Position where to put the 8 bytes.
+ * \param data Data to put.
+ */
+inline static void wire_write_u64(uint8_t *pos, uint64_t data)
+{
+ *(uint64_t *)pos = htobe64(data);
+}
+
+/*! @} */
diff --git a/coverage.mk b/coverage.mk
new file mode 100644
index 0000000..aed4864
--- /dev/null
+++ b/coverage.mk
@@ -0,0 +1,55 @@
+# Measure code coverage using luacov and gcov
+# C and Lua code is measured separately and resutls are combined together
+# Define COVERAGE=1 during build *and* test runs to enable measurement.
+#
+# Beware: Tests are typically run in parallel and neither luacov not gcov
+# support that, so we have to store results from each run separatelly
+# and combine them.
+
+coverage-c-combine-gcda:
+ @# combine trees of gcda files into one info file per tree
+ @mkdir -p '$(COVERAGE_STATSDIR)/tmp.c'
+ @LCOV=$(LCOV) ./scripts/coverage_c_combine.sh '$(TOPSRCDIR)' '$(COVERAGE_STATSDIR)' '$(COVERAGE_STATSDIR)/tmp.c'
+
+coverage-c: coverage-c-combine-gcda
+ @# combine info files for each tree into resulting c.info file
+ @$(LCOV) -q $(addprefix --add-tracefile ,$(wildcard $(COVERAGE_STATSDIR)/tmp.c/*.info)) --output-file '$(COVERAGE_STAGE).c.info'
+ @$(RM) -r '$(COVERAGE_STATSDIR)/tmp.c'
+
+LUA_STATS_OUT := $(shell find '$(COVERAGE_STATSDIR)' -type f -name 'luacov.stats.out' 2> /dev/null)
+LUA_INFOS_OUT := $(patsubst %.stats.out,%.lua.info,$(LUA_STATS_OUT))
+
+coverage-lua-fix-paths: $(LUA_STATS_OUT)
+ @# map Lua install paths to source paths
+ @$(MAKE) PREFIX=$(PREFIX) install --dry-run --always-make | scripts/map_install_src.lua --sed > .luacov_path_map
+ @sed -i -f .luacov_path_map $^
+ @$(RM) .luacov_path_map
+
+luacov.empty_stats.out:
+ @# generate list of all Lua files to fill holes in luacov stats
+ @$(MAKE) PREFIX=$(PREFIX) install --dry-run --always-make | scripts/map_install_src.lua | cut -f 2 | grep '\.lua$$' | scripts/luacov_gen_empty.sh > luacov.empty_stats.out
+
+%.lua.info: %.stats.out coverage-lua-fix-paths
+ @scripts/luacov_to_info.lua $*.stats.out > $@
+
+coverage-lua: $(LUA_INFOS_OUT) luacov.empty_stats.out
+ @echo '# Lua coverage in $(COVERAGE_STAGE).lua.info'
+ @# add missing files to luacov stats
+ @scripts/luacov_to_info.lua luacov.empty_stats.out > luacov.empty_stats.lua.info
+ @# combine info files for each tree into resulting lua.info file
+ @$(LCOV) -q $(addprefix --add-tracefile ,$(LUA_INFOS_OUT)) --add-tracefile luacov.empty_stats.lua.info --output-file '$(COVERAGE_STAGE).lua.info'
+ @$(RM) luacov.empty_stats.out luacov.empty_stats.lua.info
+
+coverage:
+ @$(LCOV) $(addprefix --add-tracefile ,$(wildcard $(COVERAGE_STAGE)*.info)) --output-file coverage.info
+ @$(GENHTML) --no-function-coverage --no-branch-coverage -q -o coverage -p '$(realpath $(CURDIR))' -t 'Knot Resolver $(VERSION)-$(PLATFORM) coverage report' --legend coverage.info
+
+coverage-clean:
+ @$(RM) -rf '$(COVERAGE_STATSDIR)'
+
+.PHONY: coverage-c-combine-gcda coverage-c coverage-lua-fix-paths coverage-lua coverage coverage-clean
+
+# Options
+ifdef COVERAGE
+BUILD_CFLAGS += --coverage
+endif
diff --git a/daemon/README.rst b/daemon/README.rst
new file mode 100644
index 0000000..51f95fe
--- /dev/null
+++ b/daemon/README.rst
@@ -0,0 +1,1394 @@
+************************
+Knot Resolver daemon
+************************
+
+The server is in the `daemon` directory, it works out of the box without any configuration.
+
+.. code-block:: bash
+
+ $ kresd -h # Get help
+ $ kresd -a ::1
+
+If you're using our packages, they also provide systemd integration. To start the resolver under systemd, you can use the ``kresd@1.service`` service. By default, the resolver only binds to local interfaces.
+
+.. code-block:: bash
+
+ $ man kresd.systemd # Help for systemd integration configuration
+ $ systemctl start kresd@1.service
+
+
+Configuration
+=============
+
+.. contents::
+ :depth: 2
+ :local:
+
+In its simplest form the server requires just a working directory in which it can set up persistent files like
+cache and the process state. If you don't provide the working directory by parameter, it is going to make itself
+comfortable in the current working directory.
+
+.. code-block:: sh
+
+ $ kresd /var/cache/knot-resolver
+
+And you're good to go for most use cases! If you want to use modules or configure daemon behavior, read on.
+
+There are several choices on how you can configure the daemon, a RPC interface, a CLI, and a configuration file.
+Fortunately all share common syntax and are transparent to each other.
+
+Configuration example
+---------------------
+.. code-block:: lua
+
+ -- interfaces
+ net = { '127.0.0.1', '::1' }
+ -- load some modules
+ modules = { 'policy' }
+ -- 10MB cache
+ cache.size = 10*MB
+
+.. tip:: There are more configuration examples in `etc/` directory for personal, ISP, company internal and resolver cluster use cases.
+
+Configuration syntax
+--------------------
+
+The configuration is kept in the ``config`` file in the daemon working directory, and it's going to get loaded automatically.
+If there isn't one, the daemon is going to start with sane defaults, listening on `localhost`.
+The syntax for options is like follows: ``group.option = value`` or ``group.action(parameters)``.
+You can also comment using a ``--`` prefix.
+
+A simple example would be to load static hints.
+
+.. code-block:: lua
+
+ modules = {
+ 'hints' -- no configuration
+ }
+
+If the module accepts configuration, you can call the ``module.config({...})`` or provide options table.
+The syntax for table is ``{ key1 = value, key2 = value }``, and it represents the unpacked `JSON-encoded`_ string, that
+the modules use as the :ref:`input configuration <mod-properties>`.
+
+.. code-block:: lua
+
+ modules = {
+ hints = '/etc/hosts'
+ }
+
+.. warning:: Modules specified including their configuration may not load exactly in the same order as specified.
+
+Modules are inherently ordered by their declaration. Some modules are built-in, so it would be normally impossible to place for example *hints* before *cache*. You can enforce specific order by precedence operators **>** and **<**.
+
+.. code-block:: lua
+
+ modules = {
+ 'hints > iterate', -- Hints AFTER iterate
+ 'policy > hints', -- Policy AFTER hints
+ 'view < cache' -- View BEFORE cache
+ }
+ modules.list() -- Check module call order
+
+This is useful if you're writing a module with a layer, that evaluates an answer before writing it into cache for example.
+
+.. tip:: The configuration and CLI syntax is Lua language, with which you may already be familiar with.
+ If not, you can read the `Learn Lua in 15 minutes`_ for a syntax overview. Spending just a few minutes
+ will allow you to break from static configuration, write more efficient configuration with iteration, and
+ leverage events and hooks. Lua is heavily used for scripting in applications ranging from embedded to game engines,
+ but in DNS world notably in `PowerDNS Recursor`_. Knot Resolver does not simply use Lua modules, but it is
+ the heart of the daemon for everything from configuration, internal events and user interaction.
+
+Dynamic configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+Knowing that the the configuration is a Lua in disguise enables you to write dynamic rules. It also helps you to avoid repetitive templating that is unavoidable with static configuration.
+
+.. code-block:: lua
+
+ if hostname() == 'hidden' then
+ net.listen(net.eth0, 5353)
+ else
+ net = { '127.0.0.1', net.eth1.addr[1] }
+ end
+
+Another example would show how it is possible to bind to all interfaces, using iteration.
+
+.. code-block:: lua
+
+ for name, addr_list in pairs(net.interfaces()) do
+ net.listen(addr_list)
+ end
+
+.. tip:: Some users observed a considerable, close to 100%, performance gain in Docker containers when they bound the daemon to a single interface:ip address pair. One may expand the aforementioned example with browsing available addresses as:
+
+ .. code-block:: lua
+
+ addrpref = env.EXPECTED_ADDR_PREFIX
+ for k, v in pairs(addr_list["addr"]) do
+ if string.sub(v,1,string.len(addrpref)) == addrpref then
+ net.listen(v)
+ ...
+
+You can also use third-party packages (available for example through LuaRocks_) as on this example
+to download cache from parent, to avoid cold-cache start.
+
+.. code-block:: lua
+
+ local http = require('socket.http')
+ local ltn12 = require('ltn12')
+
+ local cache_size = 100*MB
+ local cache_path = '/var/cache/knot-resolver'
+ cache.open(cache_size, 'lmdb://' .. cache_path)
+ if cache.count() == 0 then
+ cache.close()
+ -- download cache from parent
+ http.request {
+ url = 'http://parent/data.mdb',
+ sink = ltn12.sink.file(io.open(cache_path .. '/data.mdb', 'w'))
+ }
+ -- reopen cache with 100M limit
+ cache.open(cache_size, 'lmdb://' .. cache_path)
+ end
+
+Asynchronous events
+^^^^^^^^^^^^^^^^^^^
+
+Lua supports a concept called closures_, this is extremely useful for scripting actions upon various events,
+say for example - publish statistics each minute and so on.
+Here's an example of an anonymous function with :func:`event.recurrent()`.
+
+Note that each scheduled event is identified by a number valid for the duration of the event,
+you may use it to cancel the event at any time.
+
+.. code-block:: lua
+
+ modules.load('stats')
+
+ -- log statistics every second
+ local stat_id = event.recurrent(1 * second, function(evid)
+ log(table_print(stats.list()))
+ end)
+
+ -- stop printing statistics after first minute
+ event.after(1 * minute, function(evid)
+ event.cancel(stat_id)
+ end)
+
+If you need to persist state between events, encapsulate even handle in closure function which will provide persistent variable (called ``previous``):
+
+.. code-block:: lua
+
+ modules.load('stats')
+
+ -- make a closure, encapsulating counter
+ function speed_monitor()
+ local previous = stats.list()
+ -- monitoring function
+ return function(evid)
+ local now = stats.list()
+ local total_increment = now['answer.total'] - previous['answer.total']
+ local slow_increment = now['answer.slow'] - previous['answer.slow']
+ if slow_increment / total_increment > 0.05 then
+ log('WARNING! More than 5 %% of queries was slow!')
+ end
+ previous = now -- store current value in closure
+ end
+ end
+
+ -- monitor every minute
+ local monitor_id = event.recurrent(1 * minute, speed_monitor())
+
+Another type of actionable event is activity on a file descriptor. This allows you to embed other
+event loops or monitor open files and then fire a callback when an activity is detected.
+This allows you to build persistent services like HTTP servers or monitoring probes that cooperate
+well with the daemon internal operations. See :func:`event.socket()`
+
+
+File watchers are possible with :func:`worker.coroutine()` and cqueues_, see the cqueues documentation for more information.
+
+.. code-block:: lua
+
+ local notify = require('cqueues.notify')
+ local watcher = notify.opendir('/etc')
+ watcher:add('hosts')
+
+ -- Watch changes to /etc/hosts
+ worker.coroutine(function ()
+ for flags, name in watcher:changes() do
+ for flag in notify.flags(flags) do
+ print(name, notify[flag])
+ end
+ end
+ end)
+
+.. _closures: https://www.lua.org/pil/6.1.html
+
+Configuration reference
+-----------------------
+
+This is a reference for variables and functions available to both configuration file and CLI.
+
+.. contents::
+ :depth: 1
+ :local:
+
+Environment
+^^^^^^^^^^^
+
+.. envvar:: env (table)
+
+ Return environment variable.
+
+ .. code-block:: lua
+
+ env.USER -- equivalent to $USER in shell
+
+.. function:: hostname([fqdn])
+
+ :return: Machine hostname.
+
+ If called with a parameter, it will set kresd's internal
+ hostname. If called without a parameter, it will return kresd's
+ internal hostname, or the system's POSIX hostname (see
+ gethostname(2)) if kresd's internal hostname is unset.
+
+ This affects ephemeral certificates for kresd serving DNS over TLS.
+
+.. function:: moduledir([dir])
+
+ :return: Modules directory.
+
+ If called with a parameter, it will change kresd's directory for
+ looking up the dynamic modules. If called without a parameter, it
+ will return kresd's modules directory.
+
+.. function:: verbose(true | false)
+
+ :return: Toggle verbose logging.
+
+.. function:: mode('strict' | 'normal' | 'permissive')
+
+ :return: Change resolver strictness checking level.
+
+ By default, resolver runs in *normal* mode. There are possibly many small adjustments
+ hidden behind the mode settings, but the main idea is that in *permissive* mode, the resolver
+ tries to resolve a name with as few lookups as possible, while in *strict* mode it spends much
+ more effort resolving and checking referral path. However, if majority of the traffic is covered
+ by DNSSEC, some of the strict checking actions are counter-productive.
+
+ .. csv-table::
+ :header: "Glue type", "Modes when it is accepted", "Example glue [#example_glue]_"
+
+ "mandatory glue", "strict, normal, permissive", "ns1.example.org"
+ "in-bailiwick glue", "normal, permissive", "ns1.example2.org"
+ "any glue records", "permissive", "ns1.example3.net"
+
+ .. [#example_glue] The examples show glue records acceptable from servers
+ authoritative for `org` zone when delegating to `example.org` zone.
+ Unacceptable or missing glue records trigger resolution of names listed
+ in NS records before following respective delegation.
+
+.. function:: reorder_RR([true | false])
+
+ :param boolean value: New value for the option *(optional)*
+ :return: The (new) value of the option
+
+ If set, resolver will vary the order of resource records within RR-sets.
+ It is disabled by default.
+
+.. function:: user(name, [group])
+
+ :param string name: user name
+ :param string group: group name (optional)
+ :return: boolean
+
+ Drop privileges and run as given user (and group, if provided).
+
+ .. tip:: Note that you should bind to required network addresses before changing user. At the same time, you should open the cache **AFTER** you change the user (so it remains accessible). A good practice is to divide configuration in two parts:
+
+ .. code-block:: lua
+
+ -- privileged
+ net = { '127.0.0.1', '::1' }
+ -- unprivileged
+ cache.size = 100*MB
+ trust_anchors.file = 'root.key'
+
+ Example output:
+
+ .. code-block:: lua
+
+ > user('baduser')
+ invalid user name
+ > user('knot-resolver', 'netgrp')
+ true
+ > user('root')
+ Operation not permitted
+
+.. function:: resolve(name, type[, class = kres.class.IN, options = {}, finish = nil, init = nil])
+
+ :param string name: Query name (e.g. 'com.')
+ :param number type: Query type (e.g. ``kres.type.NS``)
+ :param number class: Query class *(optional)* (e.g. ``kres.class.IN``)
+ :param strings options: Resolution options (see :c:type:`kr_qflags`)
+ :param function finish: Callback to be executed when resolution completes (e.g. `function cb (pkt, req) end`). The callback gets a packet containing the final answer and doesn't have to return anything.
+ :param function init: Callback to be executed with the :c:type:`kr_request` before resolution starts.
+ :return: boolean
+
+ The function can also be executed with a table of arguments instead. This is useful if you'd like to skip some arguments, for example:
+
+ .. code-block:: lua
+
+ resolve {
+ name = 'example.com',
+ type = kres.type.AAAA,
+ init = function (req)
+ end,
+ }
+
+ Example:
+
+ .. code-block:: lua
+
+ -- Send query for root DNSKEY, ignore cache
+ resolve('.', kres.type.DNSKEY, kres.class.IN, 'NO_CACHE')
+
+ -- Query for AAAA record
+ resolve('example.com', kres.type.AAAA, kres.class.IN, 0,
+ function (answer, req)
+ -- Check answer RCODE
+ local pkt = kres.pkt_t(answer)
+ if pkt:rcode() == kres.rcode.NOERROR then
+ -- Print matching records
+ local records = pkt:section(kres.section.ANSWER)
+ for i = 1, #records do
+ local rr = records[i]
+ if rr.type == kres.type.AAAA then
+ print ('record:', kres.rr2str(rr))
+ end
+ end
+ else
+ print ('rcode: ', pkt:rcode())
+ end
+ end)
+
+.. function:: package_version()
+
+ :return: Current package version.
+
+ This returns current package version (the version of the binary) as a string.
+
+ .. code-block:: lua
+
+ > package_version()
+ 2.1.1
+
+
+.. _network-configuration:
+
+Network configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+For when listening on ``localhost`` just doesn't cut it.
+
+**Systemd socket configuration**
+
+If you're using our packages with systemd with sockets support (not supported
+on CentOS 7), network interfaces are configured using systemd drop-in files for
+``kresd.socket`` and ``kresd-tls.socket``.
+
+To configure kresd to listen on public interface, create a drop-in file:
+
+.. code-block:: bash
+
+ $ systemctl edit kresd.socket
+
+.. code-block:: none
+
+ # /etc/systemd/system/kresd.socket.d/override.conf
+ [Socket]
+ ListenDatagram=192.0.2.115:53
+ ListenStream=192.0.2.115:53
+
+.. _kresd-socket-override-port:
+
+The default port can also be overriden by using an empty ``ListenDatagram=`` or ``ListenStream=`` directive. This can be useful if you want to use the Knot DNS with the `dnsproxy module`_ to have both resolver and authoritative server running on the same machine.
+
+.. code-block:: none
+
+ # /etc/systemd/system/kresd.socket.d/override.conf
+ [Socket]
+ ListenDatagram=
+ ListenStream=
+ ListenDatagram=127.0.0.1:53000
+ ListenStream=127.0.0.1:53000
+ ListenDatagram=[::1]:53000
+ ListenStream=[::1]:53000
+
+The ``kresd-tls.socket`` can also be configured to listen for TLS connections.
+
+.. code-block:: bash
+
+ $ systemctl edit kresd-tls.socket
+
+.. code-block:: none
+
+ # /etc/systemd/system/kresd-tls.socket.d/override.conf
+ [Socket]
+ ListenStream=192.0.2.115:853
+
+**Daemon network configuration**
+
+If you don't use systemd with sockets to run kresd, network interfaces are
+configured in the config file.
+
+.. tip:: Use declarative interface for network.
+
+ .. code-block:: lua
+
+ net = { '127.0.0.1', net.eth0, net.eth1.addr[1] }
+ net.ipv4 = false
+
+.. warning:: On machines with multiple IP addresses avoid binding to wildcard ``0.0.0.0`` or ``::`` (see example below). Knot Resolver could answer from different IP in case the ranges overlap and client will probably refuse such a response.
+
+ .. code-block:: lua
+
+ net = { '0.0.0.0' }
+
+
+.. envvar:: net.ipv6 = true|false
+
+ :return: boolean (default: true)
+
+ Enable/disable using IPv6 for contacting upstream nameservers.
+
+.. envvar:: net.ipv4 = true|false
+
+ :return: boolean (default: true)
+
+ Enable/disable using IPv4 for contacting upstream nameservers.
+
+.. function:: net.listen(addresses, [port = 53, flags = {tls = (port == 853)}])
+
+ :return: boolean
+
+ Listen on addresses; port and flags are optional.
+ The addresses can be specified as a string or device,
+ or a list of addresses (recursively).
+ The command can be given multiple times, but note that it silently skips
+ any addresses that have already been bound.
+
+ Examples:
+
+ .. code-block:: lua
+
+ net.listen('::1')
+ net.listen(net.lo, 5353)
+ net.listen({net.eth0, '127.0.0.1'}, 53853, {tls = true})
+
+.. function:: net.close(address, [port = 53])
+
+ :return: boolean
+
+ Close opened address/port pair, noop if not listening.
+
+.. function:: net.list()
+
+ :return: Table of bound interfaces.
+
+ Example output:
+
+ .. code-block:: none
+
+ [127.0.0.1] => {
+ [port] => 53
+ [tcp] => true
+ [udp] => true
+ }
+
+.. function:: net.interfaces()
+
+ :return: Table of available interfaces and their addresses.
+
+ Example output:
+
+ .. code-block:: none
+
+ [lo0] => {
+ [addr] => {
+ [1] => ::1
+ [2] => 127.0.0.1
+ }
+ [mac] => 00:00:00:00:00:00
+ }
+ [eth0] => {
+ [addr] => {
+ [1] => 192.168.0.1
+ }
+ [mac] => de:ad:be:ef:aa:bb
+ }
+
+ .. tip:: You can use ``net.<iface>`` as a shortcut for specific interface, e.g. ``net.eth0``
+
+.. function:: net.bufsize([udp_bufsize])
+
+ Get/set maximum EDNS payload available. Default is 4096.
+ You cannot set less than 512 (512 is DNS packet size without EDNS, 1220 is minimum size for DNSSEC) or more than 65535 octets.
+
+ Example output:
+
+ .. code-block:: lua
+
+ > net.bufsize 4096
+ > net.bufsize()
+ 4096
+
+.. function:: net.tcp_pipeline([len])
+
+ Get/set per-client TCP pipeline limit, i.e. the number of outstanding queries that a single client connection can make in parallel. Default is 100.
+
+ .. code-block:: lua
+
+ > net.tcp_pipeline()
+ 100
+ > net.tcp_pipeline(50)
+ 50
+
+ .. warning:: Please note that too large limit may have negative impact on performance and can lead to increased number of SERVFAIL answers.
+
+.. function:: net.outgoing_v4([string address])
+
+ Get/set the IPv4 address used to perform queries. There is also ``net.outgoing_v6`` for IPv6.
+ The default is ``nil``, which lets the OS choose any address.
+
+
+.. _tls-server-config:
+
+TLS server configuration
+^^^^^^^^^^^^^^^^^^^^^^^^
+.. note:: Installations using systemd should be configured using systemd-specific procedures
+ described in manual page ``kresd.systemd(7)``.
+
+DNS-over-TLS server (:rfc:`7858`) can be enabled using ``{tls = true}`` parameter
+in :c:func:`net.listen()` function call. For example:
+
+.. code-block:: lua
+
+ > net.listen("::", 53) -- plain UDP+TCP on port 53 (standard DNS)
+ > net.listen("::", 853, {tls = true}) -- DNS-over-TLS on port 853 (standard DoT)
+ > net.listen("::", 443, {tls = true}) -- DNS-over-TLS on port 443 (non-standard)
+
+By default an self-signed certificate will be generated. For serious deployments
+it is strongly recommended to provide TLS certificates signed by a trusted CA
+using :c:func:`net.tls()`.
+
+.. function:: net.tls([cert_path], [key_path])
+
+ Get/set path to a server TLS certificate and private key for DNS/TLS.
+
+ Example output:
+
+ .. code-block:: lua
+
+ > net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
+ > net.tls() -- print configured paths
+ ("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
+
+.. function:: net.tls_padding([true | false])
+
+ Get/set EDNS(0) padding of answers to queries that arrive over TLS
+ transport. If set to `true` (the default), it will use a sensible
+ default padding scheme, as implemented by libknot if available at
+ compile time. If set to a numeric value >= 2 it will pad the
+ answers to nearest *padding* boundary, e.g. if set to `64`, the
+ answer will have size of a multiple of 64 (64, 128, 192, ...). If
+ set to `false` (or a number < 2), it will disable padding entirely.
+
+.. function:: net.tls_sticket_secret([string with pre-shared secret])
+
+ Set secret for TLS session resumption via tickets, by :rfc:`5077`.
+
+ The server-side key is rotated roughly once per hour.
+ By default or if called without secret, the key is random.
+ That is good for long-term forward secrecy, but multiple kresd instances
+ won't be able to resume each other's sessions.
+
+ If you provide the same secret to multiple instances, they will be able to resume
+ each other's sessions *without* any further communication between them.
+ This synchronization works only among instances having the same endianess
+ and time_t structure and size (`sizeof(time_t)`).
+
+ **For good security** the secret must have enough entropy to be hard to guess,
+ and it should still be occasionally rotated manually and securely forgotten,
+ to reduce the scope of privacy leak in case the
+ `secret leaks eventually <https://en.wikipedia.org/wiki/Forward_secrecy>`_.
+
+ .. warning:: **Setting the secret is probably too risky with TLS <= 1.2**.
+ GnuTLS stable release supports TLS 1.3 since 3.6.3 (summer 2018).
+ Therefore setting the secrets should be considered experimental for now
+ and might not be available on your system.
+
+.. function:: net.tls_sticket_secret_file([string with path to a file containing pre-shared secret])
+
+ The same as :func:`net.tls_sticket_secret`,
+ except the secret is read from a (binary) file.
+
+.. _dnssec-config:
+
+Trust anchors and DNSSEC
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: trust_anchors.config(keyfile, readonly)
+
+ Alias for `add_file`. It is also equivalent to CLI parameter ``-k <keyfile>``
+ and ``trust_anchors.file = keyfile``.
+
+.. function:: trust_anchors.add_file(keyfile, readonly)
+
+ :param string keyfile: path to the file.
+ :param readonly: if true, do not attempt to update the file.
+
+ The format is standard zone file, though additional information may be persisted in comments.
+ Either DS or DNSKEY records can be used for TAs.
+ If the file does not exist, bootstrapping of *root* TA will be attempted.
+
+ Each file can only contain records for a single domain.
+ The TAs will be updated according to :rfc:`5011` and persisted in the file (if allowed).
+
+ Example output:
+
+ .. code-block:: lua
+
+ > trust_anchors.add_file('root.key')
+ [ ta ] new state of trust anchors for a domain:
+ . 165488 DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
+ nil
+
+ [ ta ] key: 19036 state: Valid
+
+.. envvar:: trust_anchors.keyfile_default = KEYFILE_DEFAULT
+
+ Set by ``KEYFILE_DEFAULT`` during compilation (by default ``nil``). This can be explicitly
+ set to ``nil`` to override the value set during compilation in order to disable DNSSEC.
+
+.. envvar:: trust_anchors.hold_down_time = 30 * day
+
+ :return: int (default: 30 * day)
+
+ Modify RFC5011 hold-down timer to given value. Example: ``30 * sec``
+
+.. envvar:: trust_anchors.refresh_time = nil
+
+ :return: int (default: nil)
+
+ Modify RFC5011 refresh timer to given value (not set by default), this will force trust anchors
+ to be updated every N seconds periodically instead of relying on RFC5011 logic and TTLs.
+ Example: ``10 * sec``
+
+.. envvar:: trust_anchors.keep_removed = 0
+
+ :return: int (default: 0)
+
+ How many ``Removed`` keys should be held in history (and key file) before being purged.
+ Note: all ``Removed`` keys will be purged from key file after restarting the process.
+
+
+.. function:: trust_anchors.set_insecure(nta_set)
+
+ :param table nta_list: List of domain names (text format) representing NTAs.
+
+ When you use a domain name as an NTA, DNSSEC validation will be turned off at/below these names.
+ Each function call replaces the previous NTA set. You can find the current active set in ``trust_anchors.insecure`` variable.
+
+ .. tip:: Use the `trust_anchors.negative = {}` alias for easier configuration.
+
+ Example output:
+
+ .. code-block:: lua
+
+ > trust_anchors.negative = { 'bad.boy', 'example.com' }
+ > trust_anchors.insecure
+ [1] => bad.boy
+ [2] => example.com
+
+ .. warning:: If you set NTA on a name that is not a zone cut,
+ it may not always affect names not separated from the NTA by a zone cut.
+
+.. function:: trust_anchors.add(rr_string)
+
+ :param string rr_string: DS/DNSKEY records in presentation format (e.g. ``. 3600 IN DS 19036 8 2 49AAC11...``)
+
+ Inserts DS/DNSKEY record(s) into current keyset. These will not be managed or updated, use it only for testing
+ or if you have a specific use case for not using a keyfile.
+
+ Example output:
+
+ .. code-block:: lua
+
+ > trust_anchors.add('. 3600 IN DS 19036 8 2 49AAC11...')
+
+.. function:: trust_anchors.summary()
+
+ Return string with summary of configured DNSSEC trust anchors, including negative TAs.
+
+Modules configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+The daemon provides an interface for dynamic loading of :ref:`daemon modules <modules-implemented>`.
+
+.. tip:: Use declarative interface for module loading.
+
+ .. code-block:: lua
+
+ modules = {
+ hints = {file = '/etc/hosts'}
+ }
+
+ Equals to:
+
+ .. code-block:: lua
+
+ modules.load('hints')
+ hints.config({file = '/etc/hosts'})
+
+
+.. function:: modules.list()
+
+ :return: List of loaded modules.
+
+.. function:: modules.load(name)
+
+ :param string name: Module name, e.g. "hints"
+ :return: boolean
+
+ Load a module by name.
+
+.. function:: modules.unload(name)
+
+ :param string name: Module name
+ :return: boolean
+
+ Unload a module by name.
+
+Cache configuration
+^^^^^^^^^^^^^^^^^^^
+
+The default cache in Knot Resolver is persistent with LMDB backend, this means that the daemon doesn't lose
+the cached data on restart or crash to avoid cold-starts. The cache may be reused between cache
+daemons or manipulated from other processes, making for example synchronized load-balanced recursors possible.
+
+.. function:: cache.open(max_size[, config_uri])
+
+ :param number max_size: Maximum cache size in bytes.
+ :return: ``true`` if cache was opened
+
+ Open cache with a size limit. The cache will be reopened if already open.
+ Note that the max_size cannot be lowered, only increased due to how cache is implemented.
+
+ .. tip:: Use ``kB, MB, GB`` constants as a multiplier, e.g. ``100*MB``.
+
+ As of now, the built-in backend with URI ``lmdb://`` allows you to change the cache directory.
+
+ Example:
+
+ .. code-block:: lua
+
+ cache.open(100 * MB, 'lmdb:///var/cache/knot-resolver')
+
+.. envvar:: cache.size
+
+ Set the cache maximum size in bytes. Note that this is only a hint to the backend,
+ which may or may not respect it. See :func:`cache.open()`.
+
+ .. code-block:: lua
+
+ cache.size = 100 * MB -- equivalent to `cache.open(100 * MB)`
+
+.. envvar:: cache.current_size
+
+ Get the maximum size in bytes.
+
+ .. code-block:: lua
+
+ print(cache.current_size)
+
+.. envvar:: cache.storage
+
+ Set the cache storage backend configuration, see :func:`cache.backends()` for
+ more information. If the new storage configuration is invalid, it is not set.
+
+ .. code-block:: lua
+
+ cache.storage = 'lmdb://.'
+
+.. envvar:: cache.current_storage
+
+ Get the storage backend configuration.
+
+ .. code-block:: lua
+
+ print(cache.storage)
+
+.. function:: cache.backends()
+
+ :return: map of backends
+
+ The cache supports runtime-changeable backends, using the optional :rfc:`3986` URI, where the scheme
+ represents backend protocol and the rest of the URI backend-specific configuration. By default, it
+ is a ``lmdb`` backend in working directory, i.e. ``lmdb://``.
+
+ Example output:
+
+ .. code-block:: lua
+
+ [lmdb://] => true
+
+.. function:: cache.count()
+
+ :return: Number of entries in the cache. Meaning of the number is an implementation detail and is subject of change.
+
+.. function:: cache.close()
+
+ :return: ``true`` if cache was closed
+
+ Close the cache.
+
+ .. note:: This may or may not clear the cache, depending on the cache backend.
+
+.. function:: cache.stats()
+
+ .. warning:: Cache statistics are being reworked. Do not rely on current behavior.
+
+ Return table of statistics, note that this tracks all operations over cache, not just which
+ queries were answered from cache or not.
+
+ Example:
+
+ .. code-block:: lua
+
+ print('Insertions:', cache.stats().insert)
+
+.. function:: cache.max_ttl([ttl])
+
+ :param number ttl: maximum cache TTL in seconds (default: 6 days)
+
+ .. KR_CACHE_DEFAULT_TTL_MAX ^^
+
+ :return: current maximum TTL
+
+ Get or set maximum cache TTL.
+
+ .. note:: The `ttl` value must be in range `(min_ttl, 4294967295)`.
+
+ .. warning:: This settings applies only to currently open cache, it will not persist if the cache is closed or reopened.
+
+ .. code-block:: lua
+
+ -- Get maximum TTL
+ cache.max_ttl()
+ 518400
+ -- Set maximum TTL
+ cache.max_ttl(172800)
+ 172800
+
+.. function:: cache.min_ttl([ttl])
+
+ :param number ttl: minimum cache TTL in seconds (default: 5 seconds)
+
+ .. KR_CACHE_DEFAULT_TTL_MIN ^^
+
+ :return: current maximum TTL
+
+ Get or set minimum cache TTL. Any entry inserted into cache with TTL lower than minimal will be overridden to minimum TTL. Forcing TTL higher than specified violates DNS standards, use with care.
+
+ .. note:: The `ttl` value must be in range `<0, max_ttl)`.
+
+ .. warning:: This settings applies only to currently open cache, it will not persist if the cache is closed or reopened.
+
+ .. code-block:: lua
+
+ -- Get minimum TTL
+ cache.min_ttl()
+ 0
+ -- Set minimum TTL
+ cache.min_ttl(5)
+ 5
+
+.. function:: cache.ns_tout([timeout])
+
+ :param number timeout: NS retry interval in milliseconds (default: :c:macro:`KR_NS_TIMEOUT_RETRY_INTERVAL`)
+ :return: current timeout
+
+ Get or set time interval for which a nameserver address will be ignored after determining that it doesn't return (useful) answers.
+ The intention is to avoid waiting if there's little hope; instead, kresd can immediately SERVFAIL or immediately use stale records (with :ref:`serve_stale <mod-serve_stale>` module).
+
+ .. warning:: This settings applies only to the current kresd process.
+
+.. function:: cache.get([domain])
+
+ This function is not implemented at this moment.
+ We plan to re-introduce it soon, probably with a slightly different API.
+
+.. function:: cache.clear([name], [exact_name], [rr_type], [chunk_size], [callback], [prev_state])
+
+ Purge cache records matching specified criteria. There are two specifics:
+
+ * To reliably remove **negative** cache entries you need to clear subtree with the whole zone. E.g. to clear negative cache entries for (formerly non-existing) record `www.example.com. A` you need to flush whole subtree starting at zone apex, e.g. `example.com.` [#]_.
+ * This operation is asynchronous and might not be yet finished when call to ``cache.clear()`` function returns. Return value indicates if clearing continues asynchronously or not.
+
+ :param string name: subtree to purge; if the name isn't provided, whole cache is purged
+ (and any other parameters are disregarded).
+ :param bool exact_name: if set to ``true``, only records with *the same* name are removed;
+ default: false.
+ :param kres.type rr_type: you may additionally specify the type to remove,
+ but that is only supported with ``exact_name == true``; default: nil.
+ :param integer chunk_size: the number of records to remove in one round; default: 100.
+ The purpose is not to block the resolver for long.
+ The default ``callback`` repeats the command after one millisecond
+ until all matching data are cleared.
+ :param function callback: a custom code to handle result of the underlying C call.
+ Its parameters are copies of those passed to `cache.clear()` with one additional
+ parameter ``rettable`` containing table with return value from current call.
+ ``count`` field contains a return code from :func:`kr_cache_remove_subtree()`.
+ :param table prev_state: return value from previous run (can be used by callback)
+
+ :rtype: table
+ :return: ``count`` key is always present. Other keys are optional and their presence indicate special conditions.
+
+ * **count** *(integer)* - number of items removed from cache by this call (can be 0 if no entry matched criteria)
+ * **not_apex** - cleared subtree is not cached as zone apex; proofs of non-existence were probably not removed
+ * **subtree** *(string)* - hint where zone apex lies (this is estimation from cache content and might not be accurate)
+ * **chunk_limit** - more than ``chunk_size`` items needs to be cleared, clearing will continue asynchronously
+
+
+ Examples:
+
+ .. code-block:: lua
+
+ -- Clear whole cache
+ > cache.clear()
+ [count] => 76
+
+ -- Clear records at and below 'com.'
+ > cache.clear('com.')
+ [chunk_limit] => chunk size limit reached; the default callback will continue asynchronously
+ [not_apex] => to clear proofs of non-existence call cache.clear('com.')
+ [count] => 100
+ [round] => 1
+ [subtree] => com.
+ > worker.sleep(0.1)
+ [cache] asynchonous cache.clear('com', false) finished
+
+ -- Clear only 'www.example.com.'
+ > cache.clear('www.example.com.', true)
+ [round] => 1
+ [count] => 1
+ [not_apex] => to clear proofs of non-existence call cache.clear('example.com.')
+ [subtree] => example.com.
+
+.. [#] This is a consequence of DNSSEC negative cache which relies on proofs of non-existence on various owner nodes. It is impossible to efficiently flush part of DNS zones signed with NSEC3.
+
+Timers and events
+^^^^^^^^^^^^^^^^^
+
+The timer represents exactly the thing described in the examples - it allows you to execute closures
+after specified time, or event recurrent events. Time is always described in milliseconds,
+but there are convenient variables that you can use - ``sec, minute, hour``.
+For example, ``5 * hour`` represents five hours, or 5*60*60*100 milliseconds.
+
+.. function:: event.after(time, function)
+
+ :return: event id
+
+ Execute function after the specified time has passed.
+ The first parameter of the callback is the event itself.
+
+ Example:
+
+ .. code-block:: lua
+
+ event.after(1 * minute, function() print('Hi!') end)
+
+.. function:: event.recurrent(interval, function)
+
+ :return: event id
+
+ Similar to :func:`event.after()`, periodically execute function after ``interval`` passes.
+
+ Example:
+
+ .. code-block:: lua
+
+ msg_count = 0
+ event.recurrent(5 * sec, function(e)
+ msg_count = msg_count + 1
+ print('Hi #'..msg_count)
+ end)
+
+.. function:: event.reschedule(event_id, timeout)
+
+ Reschedule a running event, it has no effect on canceled events.
+ New events may reuse the event_id, so the behaviour is undefined if the function
+ is called after another event is started.
+
+ Example:
+
+ .. code-block:: lua
+
+ local interval = 1 * minute
+ event.after(1 * minute, function (ev)
+ print('Good morning!')
+ -- Halven the interval for each iteration
+ interval = interval / 2
+ event.reschedule(ev, interval)
+ end)
+
+.. function:: event.cancel(event_id)
+
+ Cancel running event, it has no effect on already canceled events.
+ New events may reuse the event_id, so the behaviour is undefined if the function
+ is called after another event is started.
+
+ Example:
+
+ .. code-block:: lua
+
+ e = event.after(1 * minute, function() print('Hi!') end)
+ event.cancel(e)
+
+Watch for file descriptor activity. This allows embedding other event loops or simply
+firing events when a pipe endpoint becomes active. In another words, asynchronous
+notifications for daemon.
+
+.. function:: event.socket(fd, cb)
+
+ :param number fd: file descriptor to watch
+ :param cb: closure or callback to execute when fd becomes active
+ :return: event id
+
+ Execute function when there is activity on the file descriptor and calls a closure
+ with event id as the first parameter, status as second and number of events as third.
+
+ Example:
+
+ .. code-block:: lua
+
+ e = event.socket(0, function(e, status, nevents)
+ print('activity detected')
+ end)
+ e.cancel(e)
+
+Asynchronous function execution
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The `event` package provides a very basic mean for non-blocking execution - it allows running code when activity on a file descriptor is detected, and when a certain amount of time passes. It doesn't however provide an easy to use abstraction for non-blocking I/O. This is instead exposed through the `worker` package (if `cqueues` Lua package is installed in the system).
+
+.. function:: worker.coroutine(function)
+
+ Start a new coroutine with given function (closure). The function can do I/O or run timers without blocking the main thread. See cqueues_ for documentation of possible operations and synchronization primitives. The main limitation is that you can't wait for a finish of a coroutine from processing layers, because it's not currently possible to suspend and resume execution of processing layers.
+
+ Example:
+
+ .. code-block:: lua
+
+ worker.coroutine(function ()
+ for i = 0, 10 do
+ print('executing', i)
+ worker.sleep(1)
+ end
+ end)
+
+.. function:: worker.sleep(seconds)
+
+ Pause execution of current function (asynchronously if running inside a worker coroutine).
+
+When daemon is running in forked mode, each process acts independently. This is good because it reduces software complexity and allows for runtime scaling, but not ideal because of additional operational burden.
+For example, when you want to add a new policy, you'd need to add it to either put it in the configuration, or execute command on each process independently. The daemon simplifies this by promoting process group leader which is able to execute commands synchronously over forks.
+
+ Example:
+
+ .. code-block:: lua
+
+ worker.sleep(1)
+
+.. function:: map(expr)
+
+ Run expression synchronously over all forks, results are returned as a table ordered as forks. Expression can be any valid expression in Lua.
+
+
+ Example:
+
+ .. code-block:: lua
+
+ -- Current instance only
+ hostname()
+ localhost
+ -- Mapped to forks
+ map 'hostname()'
+ [1] => localhost
+ [2] => localhost
+ -- Get worker ID from each fork
+ map 'worker.id'
+ [1] => 0
+ [2] => 1
+ -- Get cache stats from each fork
+ map 'cache.stats()'
+ [1] => {
+ [hit] => 0
+ [delete] => 0
+ [miss] => 0
+ [insert] => 0
+ }
+ [2] => {
+ [hit] => 0
+ [delete] => 0
+ [miss] => 0
+ [insert] => 0
+ }
+
+Scripting worker
+^^^^^^^^^^^^^^^^
+
+Worker is a service over event loop that tracks and schedules outstanding queries,
+you can see the statistics or schedule new queries. It also contains information about
+specified worker count and process rank.
+
+.. envvar:: worker.count
+
+ Return current total worker count (e.g. `1` for single-process)
+
+.. envvar:: worker.id
+
+ Return current worker ID (starting from `0` up to `worker.count - 1`)
+
+
+.. envvar:: worker.pid
+
+ Current worker process PID (number).
+
+
+.. function:: worker.stats()
+
+ Return table of statistics.
+
+ * ``udp`` - number of outbound queries over UDP
+ * ``tcp`` - number of outbound queries over TCP
+ * ``ipv6`` - number of outbound queries over IPv6
+ * ``ipv4`` - number of outbound queries over IPv4
+ * ``timeout`` - number of timeouted outbound queries
+ * ``concurrent`` - number of concurrent queries at the moment
+ * ``queries`` - number of inbound queries
+ * ``dropped`` - number of dropped inbound queries
+
+ Example:
+
+ .. code-block:: lua
+
+ print(worker.stats().concurrent)
+
+.. _enabling-dnssec:
+
+Enabling DNSSEC
+===============
+
+The resolver supports DNSSEC including :rfc:`5011` automated DNSSEC TA updates and :rfc:`7646` negative trust anchors.
+To enable it, you need to provide trusted root keys. Bootstrapping of the keys is automated, and kresd fetches root trust anchors set `over a secure channel <http://jpmens.net/2015/01/21/opendnssec-rfc-5011-bind-and-unbound/>`_ from IANA. From there, it can perform :rfc:`5011` automatic updates for you.
+
+.. note:: Automatic bootstrap requires luasocket_ and luasec_ installed.
+
+.. code-block:: none
+
+ $ kresd -k root-new.keys # File for root keys
+ [ ta ] keyfile 'root-new.keys': doesn't exist, bootstrapping
+ [ ta ] Root trust anchors bootstrapped over https with pinned certificate.
+ You SHOULD verify them manually against original source:
+ https://www.iana.org/dnssec/files
+ [ ta ] Current root trust anchors are:
+ . 0 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
+ . 0 IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
+ [ ta ] next refresh for . in 24 hours
+
+Alternatively, you can set it in configuration file with ``trust_anchors.file = 'root.keys'``. If the file doesn't exist, it will be automatically populated with root keys validated using root anchors retrieved over HTTPS.
+
+This is equivalent to `using unbound-anchor <https://www.unbound.net/documentation/howto_anchor.html>`_:
+
+.. code-block:: bash
+
+ $ unbound-anchor -a "root.keys" || echo "warning: check the key at this point"
+ $ echo "auto-trust-anchor-file: \"root.keys\"" >> unbound.conf
+ $ unbound -c unbound.conf
+
+.. warning:: Bootstrapping of the root trust anchors is automatic, you are however **encouraged to check** the key over **secure channel**, as specified in `DNSSEC Trust Anchor Publication for the Root Zone <https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.html#sigs>`_. This is a critical step where the whole infrastructure may be compromised, you will be warned in the server log.
+
+Configuration is described in :ref:`dnssec-config`.
+
+Manually providing root anchors
+-------------------------------
+
+The root anchors bootstrap may fail for various reasons, in this case you need to provide IANA or alternative root anchors. The format of the keyfile is the same as for Unbound or BIND and contains DS/DNSKEY records.
+
+1. Check the current TA published on `IANA website <https://data.iana.org/root-anchors/root-anchors.xml>`_
+2. Fetch current keys (DNSKEY), verify digests
+3. Deploy them
+
+.. code-block:: bash
+
+ $ kdig DNSKEY . @k.root-servers.net +noall +answer | grep "DNSKEY[[:space:]]257" > root.keys
+ $ ldns-key2ds -n root.keys # Only print to stdout
+ ... verify that digest matches TA published by IANA ...
+ $ kresd -k root.keys
+
+You've just enabled DNSSEC!
+
+.. note:: Bootstrapping and automatic update need write access to keyfile directory. If you want to manage root anchors manually you should use ``trust_anchors.add_file('root.keys', true)``.
+
+CLI interface
+=============
+
+The daemon features a CLI interface, type ``help()`` to see the list of available commands.
+
+.. code-block:: bash
+
+ $ kresd /var/cache/knot-resolver
+ [system] started in interactive mode, type 'help()'
+ > cache.count()
+ 53
+
+.. role:: lua(code)
+ :language: lua
+
+Verbose output
+--------------
+
+If the verbose logging is compiled in, i.e. not turned off by ``-DNOVERBOSELOG``, you can turn on verbose tracing of server operation with the ``-v`` option.
+You can also toggle it on runtime with ``verbose(true|false)`` command.
+
+.. code-block:: bash
+
+ $ kresd -v
+
+To run the daemon by hand, such as under ``nohup``, use ``-f 1`` to start a single fork. For example:
+
+.. code-block:: bash
+
+ $ nohup ./daemon/kresd -a 127.0.0.1 -f 1 -v &
+
+
+Control sockets
+===============
+
+Unless ran manually, knot-resolver is typically started in non-interactive mode.
+The mode gets triggered by using the ``-f`` command-line parameter or by passing sockets from systemd.
+You can attach to the the consoles for each process; by default they are in ``rundir/tty/$PID``.
+
+.. note:: When running kresd with systemd, you can find the location of the socket(s) using ``systemctl status kresd-control@*.socket``. Typically, these are in ``/run/knot-resolver/control@*``.
+
+.. code-block:: bash
+
+ $ nc -U rundir/tty/3008 # or socat - UNIX-CONNECT:rundir/tty/3008
+ > cache.count()
+ 53
+
+The *direct output* of the CLI command is captured and sent over the socket, while also printed to the daemon standard outputs (for accountability). This gives you an immediate response on the outcome of your command.
+Error or debug logs aren't captured, but you can find them in the daemon standard outputs.
+
+This is also a way to enumerate and test running instances, the list of files in ``tty`` corresponds to the list
+of running processes, and you can test the process for liveliness by connecting to the UNIX socket.
+
+
+Utilizing multiple CPUs
+=======================
+
+The server can run in multiple independent processes, all sharing the same socket and cache. These processes can be started or stopped during runtime based on the load.
+
+**Using systemd**
+
+To run multiple daemons using systemd, use a different numeric identifier for
+the instance, for example:
+
+.. code-block:: bash
+
+ $ systemctl start kresd@1.service
+ $ systemctl start kresd@2.service
+ $ systemctl start kresd@3.service
+ $ systemctl start kresd@4.service
+
+With the use of brace expansion, the equivalent command looks like:
+
+.. code-block:: bash
+
+ $ systemctl start kresd@{1..4}.service
+
+For more details, see ``kresd.systemd(7)``.
+
+**Daemon only**
+
+.. code-block:: bash
+
+ $ kresd -f 4 rundir > kresd.log &
+ $ kresd -f 2 rundir > kresd_2.log & # Extra instances
+ $ pstree $$ -g
+ bash(3533)─┬─kresd(19212)─┬─kresd(19212)
+ │ ├─kresd(19212)
+ │ └─kresd(19212)
+ ├─kresd(19399)───kresd(19399)
+ └─pstree(19411)
+ $ kill 19399 # Kill group 2, former will continue to run
+ bash(3533)─┬─kresd(19212)─┬─kresd(19212)
+ │ ├─kresd(19212)
+ │ └─kresd(19212)
+ └─pstree(19460)
+
+.. _daemon-reuseport:
+
+.. note:: On recent Linux supporting ``SO_REUSEPORT`` (since 3.9, backported to RHEL 2.6.32) it is also able to bind to the same endpoint and distribute the load between the forked processes. If your OS doesn't support it, use only one daemon process.
+
+
+Using CLI tools
+===============
+
+* ``kresd-host.lua`` - a drop-in replacement for *host(1)* utility
+
+Queries the DNS for information.
+The hostname is looked up for IP4, IP6 and mail.
+
+Example:
+
+.. code-block:: bash
+
+ $ kresd-host.lua -f root.key -v nic.cz
+ nic.cz. has address 217.31.205.50 (secure)
+ nic.cz. has IPv6 address 2001:1488:0:3::2 (secure)
+ nic.cz. mail is handled by 10 mail.nic.cz. (secure)
+ nic.cz. mail is handled by 20 mx.nic.cz. (secure)
+ nic.cz. mail is handled by 30 bh.nic.cz. (secure)
+
+* ``kresd-query.lua`` - run the daemon in zero-configuration mode, perform a query and execute given callback.
+
+This is useful for executing one-shot queries and hooking into the processing of the result,
+for example to check if a domain is managed by a certain registrar or if it's signed.
+
+Example:
+
+.. code-block:: bash
+
+ $ kresd-query.lua www.sub.nic.cz 'assert(kres.dname2str(req:resolved().zone_cut.name) == "nic.cz.")' && echo "yes"
+ yes
+ $ kresd-query.lua -C 'trust_anchors.config("root.keys")' nic.cz 'assert(req:resolved().flags.DNSSEC_WANT)'
+ $ echo $?
+ 0
+
+.. _`JSON-encoded`: http://json.org/example
+.. _`Learn Lua in 15 minutes`: http://tylerneylon.com/a/learn-lua/
+.. _`PowerDNS Recursor`: https://doc.powerdns.com/md/recursor/scripting/
+.. _LuaRocks: https://rocks.moonscript.org/
+.. _libuv: https://github.com/libuv/libuv
+.. _Lua: https://www.lua.org/about.html
+.. _LuaJIT: http://luajit.org/luajit.html
+.. _luasec: https://luarocks.org/modules/brunoos/luasec
+.. _luasocket: https://luarocks.org/modules/luarocks/luasocket
+.. _cqueues: https://25thandclement.com/~william/projects/cqueues.html
+.. _`real process managers`: http://blog.crocodoc.com/post/48703468992/process-managers-the-good-the-bad-and-the-ugly
+.. _`socket activation`: http://0pointer.de/blog/projects/socket-activation.html
+.. _`dnsproxy module`: https://www.knot-dns.cz/docs/2.7/html/modules.html#dnsproxy-tiny-dns-proxy
diff --git a/daemon/bindings.c b/daemon/bindings.c
new file mode 100644
index 0000000..3a7dae1
--- /dev/null
+++ b/daemon/bindings.c
@@ -0,0 +1,1849 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <uv.h>
+#include <contrib/cleanup.h>
+#include <libknot/descriptor.h>
+
+#include "lib/cache/api.h"
+#include "lib/cache/cdb_api.h"
+#include "lib/utils.h"
+#include "daemon/bindings.h"
+#include "daemon/worker.h"
+#include "daemon/tls.h"
+#include "daemon/zimport.h"
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+/** @internal Annotate for static checkers. */
+KR_NORETURN int lua_error (lua_State *L);
+
+/** @internal Prefix error with file:line */
+static int format_error(lua_State* L, const char *err)
+{
+ lua_Debug d;
+ lua_getstack(L, 1, &d);
+ /* error message prefix */
+ lua_getinfo(L, "Sln", &d);
+ if (strncmp(d.short_src, "[", 1) != 0) {
+ lua_pushstring(L, d.short_src);
+ lua_pushstring(L, ":");
+ lua_pushnumber(L, d.currentline);
+ lua_pushstring(L, ": error: ");
+ lua_concat(L, 4);
+ } else {
+ lua_pushstring(L, "error: ");
+ }
+ /* error message */
+ lua_pushstring(L, err);
+ lua_concat(L, 2);
+ return 1;
+}
+
+static inline struct worker_ctx *wrk_luaget(lua_State *L) {
+ lua_getglobal(L, "__worker");
+ struct worker_ctx *worker = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ return worker;
+}
+
+/** List loaded modules */
+static int mod_list(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ lua_newtable(L);
+ for (unsigned i = 0; i < engine->modules.len; ++i) {
+ struct kr_module *module = engine->modules.at[i];
+ lua_pushstring(L, module->name);
+ lua_rawseti(L, -2, i + 1);
+ }
+ return 1;
+}
+
+/** Load module. */
+static int mod_load(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n != 1 || !lua_isstring(L, 1)) {
+ format_error(L, "expected 'load(string name)'");
+ lua_error(L);
+ }
+ /* Parse precedence declaration */
+ char *declaration = strdup(lua_tostring(L, 1));
+ if (!declaration) {
+ return kr_error(ENOMEM);
+ }
+ const char *name = strtok(declaration, " ");
+ const char *precedence = strtok(NULL, " ");
+ const char *ref = strtok(NULL, " ");
+ /* Load engine module */
+ struct engine *engine = engine_luaget(L);
+ int ret = engine_register(engine, name, precedence, ref);
+ free(declaration);
+ if (ret != 0) {
+ if (ret == kr_error(EIDRM)) {
+ format_error(L, "referenced module not found");
+ } else {
+ format_error(L, kr_strerror(ret));
+ }
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+/** Unload module. */
+static int mod_unload(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n != 1 || !lua_isstring(L, 1)) {
+ format_error(L, "expected 'unload(string name)'");
+ lua_error(L);
+ }
+ /* Unload engine module */
+ struct engine *engine = engine_luaget(L);
+ int ret = engine_unregister(engine, lua_tostring(L, 1));
+ if (ret != 0) {
+ format_error(L, kr_strerror(ret));
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+int lib_modules(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "list", mod_list },
+ { "load", mod_load },
+ { "unload", mod_unload },
+ { NULL, NULL }
+ };
+
+ register_lib(L, "modules", lib);
+ return 1;
+}
+
+/** Append 'addr = {port = int, udp = bool, tcp = bool}' */
+static int net_list_add(const char *key, void *val, void *ext)
+{
+ lua_State *L = (lua_State *)ext;
+ endpoint_array_t *ep_array = val;
+ lua_newtable(L);
+ for (size_t i = ep_array->len; i--;) {
+ struct endpoint *ep = ep_array->at[i];
+ lua_pushinteger(L, ep->port);
+ lua_setfield(L, -2, "port");
+ lua_pushboolean(L, ep->flags & NET_UDP);
+ lua_setfield(L, -2, "udp");
+ lua_pushboolean(L, ep->flags & NET_TCP);
+ lua_setfield(L, -2, "tcp");
+ lua_pushboolean(L, ep->flags & NET_TLS);
+ lua_setfield(L, -2, "tls");
+ }
+ lua_setfield(L, -2, key);
+ return kr_ok();
+}
+
+/** List active endpoints. */
+static int net_list(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ lua_newtable(L);
+ map_walk(&engine->net.endpoints, net_list_add, L);
+ return 1;
+}
+
+/** Listen on an address list represented by the top of lua stack. */
+static int net_listen_addrs(lua_State *L, int port, int flags)
+{
+ /* Case: table with 'addr' field; only follow that field directly. */
+ lua_getfield(L, -1, "addr");
+ if (!lua_isnil(L, -1)) {
+ lua_replace(L, -2);
+ } else {
+ lua_pop(L, 1);
+ }
+
+ /* Case: string, representing a single address. */
+ const char *str = lua_tostring(L, -1);
+ if (str != NULL) {
+ struct engine *engine = engine_luaget(L);
+ int ret = network_listen(&engine->net, str, port, flags);
+ if (ret != 0) {
+ kr_log_info("[system] bind to '%s@%d' %s\n",
+ str, port, kr_strerror(ret));
+ }
+ return ret == 0;
+ }
+
+ /* Last case: table where all entries are added recursively. */
+ if (!lua_istable(L, -1)) {
+ format_error(L, "bad type for address");
+ lua_error(L);
+ return 0;
+ }
+ lua_pushnil(L);
+ while (lua_next(L, -2)) {
+ if (net_listen_addrs(L, port, flags) == 0)
+ return 0;
+ lua_pop(L, 1);
+ }
+ return 1;
+}
+
+static bool table_get_flag(lua_State *L, int index, const char *key, bool def)
+{
+ bool result = def;
+ lua_getfield(L, index, key);
+ if (lua_isboolean(L, -1)) {
+ result = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+ return result;
+}
+
+/** Listen on endpoint. */
+static int net_listen(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 1 || n > 3) {
+ format_error(L, "expected one to three arguments; usage:\n"
+ "net.listen(addressses, [port = " xstr(KR_DNS_PORT) ", flags = {tls = (port == " xstr(KR_DNS_TLS_PORT) ")}])\n");
+ lua_error(L);
+ }
+
+ int port = KR_DNS_PORT;
+ if (n > 1 && lua_isnumber(L, 2)) {
+ port = lua_tointeger(L, 2);
+ }
+
+ bool tls = (port == KR_DNS_TLS_PORT);
+ if (n > 2 && lua_istable(L, 3)) {
+ tls = table_get_flag(L, 3, "tls", tls);
+ }
+ int flags = tls ? (NET_TCP|NET_TLS) : (NET_TCP|NET_UDP);
+
+ /* Now focus on the first argument. */
+ lua_pop(L, n - 1);
+ int res = net_listen_addrs(L, port, flags);
+ lua_pushboolean(L, res);
+ return res;
+}
+
+/** Close endpoint. */
+static int net_close(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 2) {
+ format_error(L, "expected 'close(string addr, number port)'");
+ lua_error(L);
+ }
+
+ /* Open resolution context cache */
+ struct engine *engine = engine_luaget(L);
+ int ret = network_close(&engine->net, lua_tostring(L, 1), lua_tointeger(L, 2));
+ lua_pushboolean(L, ret == 0);
+ return 1;
+}
+
+/** List available interfaces. */
+static int net_interfaces(lua_State *L)
+{
+ /* Retrieve interface list */
+ int count = 0;
+ char buf[INET6_ADDRSTRLEN]; /* https://tools.ietf.org/html/rfc4291 */
+ uv_interface_address_t *info = NULL;
+ uv_interface_addresses(&info, &count);
+ lua_newtable(L);
+ for (int i = 0; i < count; ++i) {
+ uv_interface_address_t iface = info[i];
+ lua_getfield(L, -1, iface.name);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ }
+
+ /* Address */
+ lua_getfield(L, -1, "addr");
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ }
+ if (iface.address.address4.sin_family == AF_INET) {
+ uv_ip4_name(&iface.address.address4, buf, sizeof(buf));
+ } else if (iface.address.address4.sin_family == AF_INET6) {
+ uv_ip6_name(&iface.address.address6, buf, sizeof(buf));
+ } else {
+ buf[0] = '\0';
+ }
+ lua_pushstring(L, buf);
+ lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
+ lua_setfield(L, -2, "addr");
+
+ /* Hardware address. */
+ char *p = buf;
+ memset(buf, 0, sizeof(buf));
+ for (unsigned k = 0; k < sizeof(iface.phys_addr); ++k) {
+ sprintf(p, "%s%.2x", k > 0 ? ":" : "", iface.phys_addr[k] & 0xff);
+ p += 3;
+ }
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "mac");
+
+ /* Push table */
+ lua_setfield(L, -2, iface.name);
+ }
+ uv_free_interface_addresses(info, count);
+
+ return 1;
+}
+
+/** Set UDP maximum payload size. */
+static int net_bufsize(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ knot_rrset_t *opt_rr = engine->resolver.opt_rr;
+ if (!lua_isnumber(L, 1)) {
+ lua_pushnumber(L, knot_edns_get_payload(opt_rr));
+ return 1;
+ }
+ int bufsize = lua_tointeger(L, 1);
+ if (bufsize < 512 || bufsize > UINT16_MAX) {
+ format_error(L, "bufsize must be within <512, " xstr(UINT16_MAX) ">");
+ lua_error(L);
+ }
+ knot_edns_set_payload(opt_rr, (uint16_t) bufsize);
+ return 0;
+}
+
+/** Set TCP pipelining size. */
+static int net_pipeline(lua_State *L)
+{
+ struct worker_ctx *worker = wrk_luaget(L);
+ if (!worker) {
+ return 0;
+ }
+ if (!lua_isnumber(L, 1)) {
+ lua_pushnumber(L, worker->tcp_pipeline_max);
+ return 1;
+ }
+ int len = lua_tointeger(L, 1);
+ if (len < 0 || len > UINT16_MAX) {
+ format_error(L, "tcp_pipeline must be within <0, " xstr(UINT16_MAX) ">");
+ lua_error(L);
+ }
+ worker->tcp_pipeline_max = len;
+ lua_pushnumber(L, len);
+ return 1;
+}
+
+static int net_tls(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (!engine) {
+ return 0;
+ }
+ struct network *net = &engine->net;
+ if (!net) {
+ return 0;
+ }
+
+ /* Only return current credentials. */
+ if (lua_gettop(L) == 0) {
+ /* No credentials configured yet. */
+ if (!net->tls_credentials) {
+ return 0;
+ }
+ lua_newtable(L);
+ lua_pushstring(L, net->tls_credentials->tls_cert);
+ lua_setfield(L, -2, "cert_file");
+ lua_pushstring(L, net->tls_credentials->tls_key);
+ lua_setfield(L, -2, "key_file");
+ return 1;
+ }
+
+ if ((lua_gettop(L) != 2) || !lua_isstring(L, 1) || !lua_isstring(L, 2)) {
+ lua_pushstring(L, "net.tls takes two parameters: (\"cert_file\", \"key_file\")");
+ lua_error(L);
+ }
+
+ int r = tls_certificate_set(net, lua_tostring(L, 1), lua_tostring(L, 2));
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int print_tls_param(const char *key, void *val, void *data)
+{
+ if (!val) {
+ return 0;
+ }
+
+ struct tls_client_paramlist_entry *entry = (struct tls_client_paramlist_entry *)val;
+
+ lua_State *L = (lua_State *)data;
+
+ lua_createtable(L, 0, 3);
+
+ lua_createtable(L, entry->pins.len, 0);
+ for (size_t i = 0; i < entry->pins.len; ++i) {
+ lua_pushnumber(L, i + 1);
+ lua_pushstring(L, entry->pins.at[i]);
+ lua_settable(L, -3);
+ }
+ lua_setfield(L, -2, "pins");
+
+ lua_createtable(L, entry->ca_files.len, 0);
+ for (size_t i = 0; i < entry->ca_files.len; ++i) {
+ lua_pushnumber(L, i + 1);
+ lua_pushstring(L, entry->ca_files.at[i]);
+ lua_settable(L, -3);
+ }
+ lua_setfield(L, -2, "ca_files");
+
+ lua_createtable(L, entry->hostnames.len, 0);
+ for (size_t i = 0; i < entry->hostnames.len; ++i) {
+ lua_pushnumber(L, i + 1);
+ lua_pushstring(L, entry->hostnames.at[i]);
+ lua_settable(L, -3);
+ }
+ lua_setfield(L, -2, "hostnames");
+
+ lua_setfield(L, -2, key);
+
+ return 0;
+}
+
+static int print_tls_client_params(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (!engine) {
+ return 0;
+ }
+ struct network *net = &engine->net;
+ if (!net) {
+ return 0;
+ }
+ if (net->tls_client_params.root == 0 ) {
+ return 0;
+ }
+ lua_newtable(L);
+ map_walk(&net->tls_client_params, print_tls_param, (void *)L);
+ return 1;
+}
+
+
+static int net_tls_client(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (!engine) {
+ return 0;
+ }
+ struct network *net = &engine->net;
+ if (!net) {
+ return 0;
+ }
+
+ /* Only return current credentials. */
+ if (lua_gettop(L) == 0) {
+ return print_tls_client_params(L);
+ }
+
+ const char *full_addr = NULL;
+ bool pin_exists = false;
+ bool hostname_exists = false;
+ if ((lua_gettop(L) == 1) && lua_isstring(L, 1)) {
+ full_addr = lua_tostring(L, 1);
+ } else if ((lua_gettop(L) == 2) && lua_isstring(L, 1) && lua_istable(L, 2)) {
+ full_addr = lua_tostring(L, 1);
+ pin_exists = true;
+ } else if ((lua_gettop(L) == 3) && lua_isstring(L, 1) && lua_istable(L, 2)) {
+ full_addr = lua_tostring(L, 1);
+ hostname_exists = true;
+ } else if ((lua_gettop(L) == 4) && lua_isstring(L, 1) &&
+ lua_istable(L, 2) && lua_istable(L, 3)) {
+ full_addr = lua_tostring(L, 1);
+ pin_exists = true;
+ hostname_exists = true;
+ } else {
+ format_error(L, "net.tls_client takes one parameter (\"address\"), two parameters (\"address\",\"pin\"), three parameters (\"address\", \"ca_file\", \"hostname\") or four ones: (\"address\", \"pin\", \"ca_file\", \"hostname\")");
+ lua_error(L);
+ }
+
+ char addr[INET6_ADDRSTRLEN];
+ uint16_t port = 0;
+ if (kr_straddr_split(full_addr, addr, sizeof(addr), &port) != kr_ok()) {
+ format_error(L, "invalid IP address");
+ lua_error(L);
+ }
+
+ if (port == 0) {
+ port = 853;
+ }
+
+ if (!pin_exists && !hostname_exists) {
+ int r = tls_client_params_set(&net->tls_client_params,
+ addr, port, NULL,
+ TLS_CLIENT_PARAM_NONE);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+ }
+
+ if (pin_exists) {
+ /* iterate over table with pins
+ * http://www.lua.org/manual/5.1/manual.html#lua_next */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, 2)) { /* pin table is in stack at index 2 */
+ /* pin now at index -1, key at index -2*/
+ const char *pin = lua_tostring(L, -1);
+ int r = tls_client_params_set(&net->tls_client_params,
+ addr, port, pin,
+ TLS_CLIENT_PARAM_PIN);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+ lua_pop(L, 1);
+ }
+ }
+
+ int ca_table_index = 2;
+ int hostname_table_index = 3;
+ if (hostname_exists) {
+ if (pin_exists) {
+ ca_table_index = 3;
+ hostname_table_index = 4;
+ }
+ } else {
+ lua_pushboolean(L, true);
+ return 1;
+ }
+
+ /* iterate over hostnames,
+ * it must be done before iterating over ca filenames */
+ lua_pushnil(L);
+ while (lua_next(L, hostname_table_index)) {
+ const char *hostname = lua_tostring(L, -1);
+ int r = tls_client_params_set(&net->tls_client_params,
+ addr, port, hostname,
+ TLS_CLIENT_PARAM_HOSTNAME);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+ /* removes 'value'; keeps 'key' for next iteration */
+ lua_pop(L, 1);
+ }
+
+ /* iterate over ca filenames */
+ lua_pushnil(L);
+ size_t num_of_ca_files = 0;
+ while (lua_next(L, ca_table_index)) {
+ const char *ca_file = lua_tostring(L, -1);
+ int r = tls_client_params_set(&net->tls_client_params,
+ addr, port, ca_file,
+ TLS_CLIENT_PARAM_CA);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+ num_of_ca_files += 1;
+ /* removes 'value'; keeps 'key' for next iteration */
+ lua_pop(L, 1);
+ }
+
+ if (num_of_ca_files == 0) {
+ /* No ca files were explicitly configured, so use system CA */
+ int r = tls_client_params_set(&net->tls_client_params,
+ addr, port, NULL,
+ TLS_CLIENT_PARAM_CA);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_tls_client_clear(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (!engine) {
+ return 0;
+ }
+
+ struct network *net = &engine->net;
+ if (!net) {
+ return 0;
+ }
+
+ if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
+ format_error(L, "net.tls_client_clear() requires one parameter (\"address\")");
+ lua_error(L);
+ }
+
+ const char *full_addr = lua_tostring(L, 1);
+
+ char addr[INET6_ADDRSTRLEN];
+ uint16_t port = 0;
+ if (kr_straddr_split(full_addr, addr, sizeof(addr), &port) != kr_ok()) {
+ format_error(L, "invalid IP address");
+ lua_error(L);
+ }
+
+ if (port == 0) {
+ port = 853;
+ }
+
+ int r = tls_client_params_clear(&net->tls_client_params, addr, port);
+ if (r != 0) {
+ lua_pushstring(L, kr_strerror(r));
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_tls_padding(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+
+ /* Only return current padding. */
+ if (lua_gettop(L) == 0) {
+ if (engine->resolver.tls_padding < 0) {
+ lua_pushboolean(L, true);
+ return 1;
+ } else if (engine->resolver.tls_padding == 0) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+ lua_pushinteger(L, engine->resolver.tls_padding);
+ return 1;
+ }
+
+ if ((lua_gettop(L) != 1)) {
+ lua_pushstring(L, "net.tls_padding takes one parameter: (\"padding\")");
+ lua_error(L);
+ }
+ if (lua_isboolean(L, 1)) {
+ bool x = lua_toboolean(L, 1);
+ if (x) {
+ engine->resolver.tls_padding = -1;
+ } else {
+ engine->resolver.tls_padding = 0;
+ }
+ } else if (lua_isnumber(L, 1)) {
+ int padding = lua_tointeger(L, 1);
+ if ((padding < 0) || (padding > MAX_TLS_PADDING)) {
+ lua_pushstring(L, "net.tls_padding parameter has to be true, false, or a number between <0, " xstr(MAX_TLS_PADDING) ">");
+ lua_error(L);
+ }
+ engine->resolver.tls_padding = padding;
+ } else {
+ lua_pushstring(L, "net.tls_padding parameter has to be true, false, or a number between <0, " xstr(MAX_TLS_PADDING) ">");
+ lua_error(L);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+/** Shorter salt can't contain much entropy. */
+#define net_tls_sticket_MIN_SECRET_LEN 32
+
+static int net_tls_sticket_secret_string(lua_State *L)
+{
+ struct network *net = &engine_luaget(L)->net;
+
+ size_t secret_len;
+ const char *secret;
+
+ if (lua_gettop(L) == 0) {
+ /* Zero-length secret, implying random key. */
+ secret_len = 0;
+ secret = NULL;
+ } else {
+ if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
+ lua_pushstring(L,
+ "net.tls_sticket_secret takes one parameter: (\"secret string\")");
+ lua_error(L);
+ }
+ secret = lua_tolstring(L, 1, &secret_len);
+ if (secret_len < net_tls_sticket_MIN_SECRET_LEN || !secret) {
+ lua_pushstring(L, "net.tls_sticket_secret - the secret is shorter than "
+ xstr(net_tls_sticket_MIN_SECRET_LEN) " bytes");
+ lua_error(L);
+ }
+ }
+
+ tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
+ net->tls_session_ticket_ctx =
+ tls_session_ticket_ctx_create(net->loop, secret, secret_len);
+ if (net->tls_session_ticket_ctx == NULL) {
+ lua_pushstring(L,
+ "net.tls_sticket_secret_string - can't create session ticket context");
+ lua_error(L);
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_tls_sticket_secret_file(lua_State *L)
+{
+ if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
+ lua_pushstring(L,
+ "net.tls_sticket_secret_file takes one parameter: (\"file name\")");
+ lua_error(L);
+ }
+
+ const char *file_name = lua_tostring(L, 1);
+ if (strlen(file_name) == 0) {
+ lua_pushstring(L, "net.tls_sticket_secret_file - empty file name");
+ lua_error(L);
+ }
+
+ FILE *fp = fopen(file_name, "r");
+ if (fp == NULL) {
+ lua_pushfstring(L, "net.tls_sticket_secret_file - can't open file '%s': %s",
+ file_name, strerror(errno));
+ lua_error(L);
+ }
+
+ char secret_buf[TLS_SESSION_TICKET_SECRET_MAX_LEN];
+ const size_t secret_len = fread(secret_buf, 1, sizeof(secret_buf), fp);
+ int err = ferror(fp);
+ if (err) {
+ lua_pushfstring(L,
+ "net.tls_sticket_secret_file - error reading from file '%s': %s",
+ file_name, strerror(err));
+ lua_error(L);
+ }
+ if (secret_len < net_tls_sticket_MIN_SECRET_LEN) {
+ lua_pushfstring(L,
+ "net.tls_sticket_secret_file - file '%s' is shorter than "
+ xstr(net_tls_sticket_MIN_SECRET_LEN) " bytes",
+ file_name);
+ lua_error(L);
+ }
+ fclose(fp);
+
+ struct network *net = &engine_luaget(L)->net;
+
+ tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
+ net->tls_session_ticket_ctx =
+ tls_session_ticket_ctx_create(net->loop, secret_buf, secret_len);
+ if (net->tls_session_ticket_ctx == NULL) {
+ lua_pushstring(L,
+ "net.tls_sticket_secret_file - can't create session ticket context");
+ lua_error(L);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_outgoing(lua_State *L, int family)
+{
+ struct worker_ctx *worker = wrk_luaget(L);
+ union inaddr *addr;
+ if (family == AF_INET)
+ addr = (union inaddr*)&worker->out_addr4;
+ else
+ addr = (union inaddr*)&worker->out_addr6;
+
+ if (lua_gettop(L) == 0) { /* Return the current value. */
+ if (addr->ip.sa_family == AF_UNSPEC) {
+ lua_pushnil(L);
+ return 1;
+ }
+ if (addr->ip.sa_family != family) {
+ assert(false);
+ lua_error(L);
+ }
+ char addr_buf[INET6_ADDRSTRLEN];
+ int err;
+ if (family == AF_INET)
+ err = uv_ip4_name(&addr->ip4, addr_buf, sizeof(addr_buf));
+ else
+ err = uv_ip6_name(&addr->ip6, addr_buf, sizeof(addr_buf));
+ if (err)
+ lua_error(L);
+ lua_pushstring(L, addr_buf);
+ return 1;
+ }
+
+ if ((lua_gettop(L) != 1) || (!lua_isstring(L, 1) && !lua_isnil(L, 1))) {
+ format_error(L, "net.outgoing_vX takes one address string parameter or nil");
+ lua_error(L);
+ }
+
+ if (lua_isnil(L, 1)) {
+ addr->ip.sa_family = AF_UNSPEC;
+ return 1;
+ }
+
+ const char *addr_str = lua_tostring(L, 1);
+ int err;
+ if (family == AF_INET)
+ err = uv_ip4_addr(addr_str, 0, &addr->ip4);
+ else
+ err = uv_ip6_addr(addr_str, 0, &addr->ip6);
+ if (err) {
+ format_error(L, "net.outgoing_vX: failed to parse the address");
+ lua_error(L);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_outgoing_v4(lua_State *L) { return net_outgoing(L, AF_INET); }
+static int net_outgoing_v6(lua_State *L) { return net_outgoing(L, AF_INET6); }
+
+static int net_update_timeout(lua_State *L, uint64_t *timeout, const char *name)
+{
+ /* Only return current idle timeout. */
+ if (lua_gettop(L) == 0) {
+ lua_pushnumber(L, *timeout);
+ return 1;
+ }
+
+ if ((lua_gettop(L) != 1)) {
+ lua_pushstring(L, name);
+ lua_pushstring(L, " takes one parameter: (\"idle timeout\")");
+ lua_error(L);
+ }
+
+ if (lua_isnumber(L, 1)) {
+ int idle_timeout = lua_tointeger(L, 1);
+ if (idle_timeout <= 0) {
+ lua_pushstring(L, name);
+ lua_pushstring(L, " parameter has to be positive number");
+ lua_error(L);
+ }
+ *timeout = idle_timeout;
+ } else {
+ lua_pushstring(L, name);
+ lua_pushstring(L, " parameter has to be positive number");
+ lua_error(L);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int net_tcp_in_idle(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct network *net = &engine->net;
+
+ return net_update_timeout(L, &net->tcp.in_idle_timeout, "net.tcp_in_idle");
+}
+
+static int net_tls_handshake_timeout(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct network *net = &engine->net;
+
+ return net_update_timeout(L, &net->tcp.tls_handshake_timeout, "net.tls_handshake_timeout");
+}
+
+static int net_bpf_set(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct network *net = &engine->net;
+
+ if (lua_gettop(L) != 1 || !lua_isnumber(L, 1)) {
+ format_error(L, "net.bpf_set(fd) takes one parameter: the open file descriptor of a loaded BPF program");
+ lua_error(L);
+ return 0;
+ }
+
+#if __linux__
+
+ int progfd = lua_tointeger(L, 1);
+ if (progfd == 0) {
+ /* conversion error despite that fact
+ * that lua_isnumber(L, 1) has returned true.
+ * Real or stdin? */
+ lua_error(L);
+ return 0;
+ }
+ lua_pop(L, 1);
+
+ if (network_set_bpf(net, progfd) == 0) {
+ char errmsg[256] = { 0 };
+ snprintf(errmsg, sizeof(errmsg), "failed to attach BPF program to some networks: %s", strerror(errno));
+ format_error(L, errmsg);
+ lua_error(L);
+ return 0;
+ }
+
+ lua_pushboolean(L, 1);
+ return 1;
+
+#endif
+
+ format_error(L, "BPF is not supported on this operating system");
+ lua_error(L);
+ return 0;
+}
+
+static int net_bpf_clear(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct network *net = &engine->net;
+
+ if (lua_gettop(L) != 0) {
+ format_error(L, "net.bpf_clear() does not take any parameters");
+ lua_error(L);
+ return 0;
+ }
+
+#if __linux__
+
+ network_clear_bpf(net);
+
+ lua_pushboolean(L, 1);
+ return 1;
+
+#endif
+
+ format_error(L, "BPF is not supported on this operating system");
+ lua_error(L);
+ return 0;
+}
+
+int lib_net(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "list", net_list },
+ { "listen", net_listen },
+ { "close", net_close },
+ { "interfaces", net_interfaces },
+ { "bufsize", net_bufsize },
+ { "tcp_pipeline", net_pipeline },
+ { "tls", net_tls },
+ { "tls_server", net_tls },
+ { "tls_client", net_tls_client },
+ { "tls_client_clear", net_tls_client_clear },
+ { "tls_padding", net_tls_padding },
+ { "tls_sticket_secret", net_tls_sticket_secret_string },
+ { "tls_sticket_secret_file", net_tls_sticket_secret_file },
+ { "outgoing_v4", net_outgoing_v4 },
+ { "outgoing_v6", net_outgoing_v6 },
+ { "tcp_in_idle", net_tcp_in_idle },
+ { "tls_handshake_timeout", net_tls_handshake_timeout },
+ { "bpf_set", net_bpf_set },
+ { "bpf_clear", net_bpf_clear },
+ { NULL, NULL }
+ };
+ register_lib(L, "net", lib);
+ return 1;
+}
+
+
+
+/** @internal return cache, or throw lua error if not open */
+struct kr_cache * cache_assert_open(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct kr_cache *cache = &engine->resolver.cache;
+ assert(cache);
+ if (!cache || !kr_cache_is_open(cache)) {
+ format_error(L, "no cache is open yet, use cache.open() or cache.size, etc.");
+ lua_error(L);
+ }
+ return cache;
+}
+
+/** Return available cached backends. */
+static int cache_backends(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+
+ lua_newtable(L);
+ for (unsigned i = 0; i < engine->backends.len; ++i) {
+ const struct kr_cdb_api *api = engine->backends.at[i];
+ lua_pushboolean(L, api == engine->resolver.cache.api);
+ lua_setfield(L, -2, api->name);
+ }
+ return 1;
+}
+
+/** Return number of cached records. */
+static int cache_count(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+
+ int count = cache->api->count(cache->db);
+ if (count >= 0) {
+ /* First key is a version counter, omit it if nonempty. */
+ lua_pushinteger(L, count ? count - 1 : 0);
+ return 1;
+ }
+ return 0;
+}
+
+/** Return time of last checkpoint, or re-set it if passed `true`. */
+static int cache_checkpoint(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+
+ if (lua_gettop(L) == 0) { /* Return the current value. */
+ lua_newtable(L);
+ lua_pushnumber(L, cache->checkpoint_monotime);
+ lua_setfield(L, -2, "monotime");
+ lua_newtable(L);
+ lua_pushnumber(L, cache->checkpoint_walltime.tv_sec);
+ lua_setfield(L, -2, "sec");
+ lua_pushnumber(L, cache->checkpoint_walltime.tv_usec);
+ lua_setfield(L, -2, "usec");
+ lua_setfield(L, -2, "walltime");
+ return 1;
+ }
+
+ if (lua_gettop(L) != 1 || !lua_isboolean(L, 1) || !lua_toboolean(L, 1)) {
+ format_error(L, "cache.checkpoint() takes no parameters or a true value");
+ lua_error(L);
+ }
+ kr_cache_make_checkpoint(cache);
+ return 1;
+}
+
+/** Return cache statistics. */
+static int cache_stats(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+ lua_newtable(L);
+ lua_pushnumber(L, cache->stats.hit);
+ lua_setfield(L, -2, "hit");
+ lua_pushnumber(L, cache->stats.miss);
+ lua_setfield(L, -2, "miss");
+ lua_pushnumber(L, cache->stats.insert);
+ lua_setfield(L, -2, "insert");
+ lua_pushnumber(L, cache->stats.delete);
+ lua_setfield(L, -2, "delete");
+ return 1;
+}
+
+static const struct kr_cdb_api *cache_select(struct engine *engine, const char **conf)
+{
+ /* Return default backend */
+ if (*conf == NULL || !strstr(*conf, "://")) {
+ return engine->backends.at[0];
+ }
+
+ /* Find storage backend from config prefix */
+ for (unsigned i = 0; i < engine->backends.len; ++i) {
+ const struct kr_cdb_api *api = engine->backends.at[i];
+ if (strncmp(*conf, api->name, strlen(api->name)) == 0) {
+ *conf += strlen(api->name) + strlen("://");
+ return api;
+ }
+ }
+
+ return NULL;
+}
+
+static int cache_max_ttl(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+
+ int n = lua_gettop(L);
+ if (n > 0) {
+ if (!lua_isnumber(L, 1)) {
+ format_error(L, "expected 'max_ttl(number ttl)'");
+ lua_error(L);
+ }
+ uint32_t min = cache->ttl_min;
+ int64_t ttl = lua_tonumber(L, 1);
+ if (ttl < 0 || ttl < min || ttl > UINT32_MAX) {
+ format_error(L, "max_ttl must be larger than minimum TTL, and in range <1, " xstr(UINT32_MAX) ">'");
+ lua_error(L);
+ }
+ cache->ttl_max = ttl;
+ }
+ lua_pushinteger(L, cache->ttl_max);
+ return 1;
+}
+
+
+static int cache_min_ttl(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+
+ int n = lua_gettop(L);
+ if (n > 0) {
+ if (!lua_isnumber(L, 1)) {
+ format_error(L, "expected 'min_ttl(number ttl)'");
+ lua_error(L);
+ }
+ uint32_t max = cache->ttl_max;
+ int64_t ttl = lua_tonumber(L, 1);
+ if (ttl < 0 || ttl > max || ttl > UINT32_MAX) {
+ format_error(L, "min_ttl must be smaller than maximum TTL, and in range <0, " xstr(UINT32_MAX) ">'");
+ lua_error(L);
+ }
+ cache->ttl_min = ttl;
+ }
+ lua_pushinteger(L, cache->ttl_min);
+ return 1;
+}
+
+/** Open cache */
+static int cache_open(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 1 || !lua_isnumber(L, 1)) {
+ format_error(L, "expected 'open(number max_size, string config = \"\")'");
+ lua_error(L);
+ }
+
+ /* Select cache storage backend */
+ struct engine *engine = engine_luaget(L);
+
+ lua_Number csize_lua = lua_tonumber(L, 1);
+ if (!(csize_lua >= 8192 && csize_lua < SIZE_MAX)) { /* min. is basically arbitrary */
+ format_error(L, "invalid cache size specified, it must be in range <8192, " xstr(SIZE_MAX) ">");
+ lua_error(L);
+ }
+ size_t cache_size = csize_lua;
+
+ const char *conf = n > 1 ? lua_tostring(L, 2) : NULL;
+ const char *uri = conf;
+ const struct kr_cdb_api *api = cache_select(engine, &conf);
+ if (!api) {
+ format_error(L, "unsupported cache backend");
+ lua_error(L);
+ }
+
+ /* Close if already open */
+ kr_cache_close(&engine->resolver.cache);
+
+ /* Reopen cache */
+ struct kr_cdb_opts opts = {
+ (conf && strlen(conf)) ? conf : ".",
+ cache_size
+ };
+ int ret = kr_cache_open(&engine->resolver.cache, api, &opts, engine->pool);
+ if (ret != 0) {
+ char cwd[PATH_MAX];
+ if(getcwd(cwd, sizeof(cwd)) == NULL) {
+ const char errprefix[] = "<invalid working directory>";
+ strncpy(cwd, errprefix, sizeof(cwd));
+ }
+ return luaL_error(L, "can't open cache path '%s'; working directory '%s'", opts.path, cwd);
+ }
+
+ /* Store current configuration */
+ lua_getglobal(L, "cache");
+ lua_pushstring(L, "current_size");
+ lua_pushnumber(L, cache_size);
+ lua_rawset(L, -3);
+ lua_pushstring(L, "current_storage");
+ lua_pushstring(L, uri);
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+static int cache_close(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct kr_cache *cache = &engine->resolver.cache;
+ if (!kr_cache_is_open(cache)) {
+ return 0;
+ }
+
+ kr_cache_close(cache);
+ lua_getglobal(L, "cache");
+ lua_pushstring(L, "current_size");
+ lua_pushnumber(L, 0);
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+ lua_pushboolean(L, 1);
+ return 1;
+}
+
+#if 0
+/** @internal Prefix walk. */
+static int cache_prefixed(struct kr_cache *cache, const char *prefix, bool exact_name,
+ knot_db_val_t keyval[][2], int maxcount)
+{
+ /* Convert to domain name */
+ uint8_t buf[KNOT_DNAME_MAXLEN];
+ if (!knot_dname_from_str(buf, prefix, sizeof(buf))) {
+ return kr_error(EINVAL);
+ }
+ /* Start prefix search */
+ return kr_cache_match(cache, buf, exact_name, keyval, maxcount);
+}
+#endif
+
+/** Prune expired/invalid records. */
+static int cache_prune(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+ /* Check parameters */
+ int prune_max = UINT16_MAX;
+ int n = lua_gettop(L);
+ if (n >= 1 && lua_isnumber(L, 1)) {
+ prune_max = lua_tointeger(L, 1);
+ }
+
+ /* Check if API supports pruning. */
+ int ret = kr_error(ENOSYS);
+ if (cache->api->prune) {
+ ret = cache->api->prune(cache->db, prune_max);
+ }
+ /* Commit and format result. */
+ if (ret < 0) {
+ format_error(L, kr_strerror(ret));
+ lua_error(L);
+ }
+ lua_pushinteger(L, ret);
+ return 1;
+}
+
+/** Clear everything. */
+static int cache_clear_everything(lua_State *L)
+{
+ struct kr_cache *cache = cache_assert_open(L);
+
+ /* Clear records and packets. */
+ int ret = kr_cache_clear(cache);
+ if (ret < 0) {
+ format_error(L, kr_strerror(ret));
+ lua_error(L);
+ }
+
+ /* Clear reputation tables */
+ struct engine *engine = engine_luaget(L);
+ lru_reset(engine->resolver.cache_rtt);
+ lru_reset(engine->resolver.cache_rep);
+ lru_reset(engine->resolver.cache_cookie);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+#if 0
+/** @internal Dump cache key into table on Lua stack. */
+static void cache_dump(lua_State *L, knot_db_val_t keyval[])
+{
+ knot_dname_t dname[KNOT_DNAME_MAXLEN];
+ char name[KNOT_DNAME_TXT_MAXLEN];
+ uint16_t type;
+
+ int ret = kr_unpack_cache_key(keyval[0], dname, &type);
+ if (ret < 0) {
+ return;
+ }
+
+ ret = !knot_dname_to_str(name, dname, sizeof(name));
+ assert(!ret);
+ if (ret) return;
+
+ /* If name typemap doesn't exist yet, create it */
+ lua_getfield(L, -1, name);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ }
+ /* Append to typemap */
+ char type_buf[KR_RRTYPE_STR_MAXLEN] = { '\0' };
+ knot_rrtype_to_string(type, type_buf, sizeof(type_buf));
+ lua_pushboolean(L, true);
+ lua_setfield(L, -2, type_buf);
+ /* Set name typemap */
+ lua_setfield(L, -2, name);
+}
+
+/** Query cached records. TODO: fix caveats in ./README.rst documentation? */
+static int cache_get(lua_State *L)
+{
+ //struct kr_cache *cache = cache_assert_open(L); // to be fixed soon
+
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 1 || !lua_isstring(L, 1)) {
+ format_error(L, "expected 'cache.get(string key)'");
+ lua_error(L);
+ }
+
+ /* Retrieve set of keys */
+ const char *prefix = lua_tostring(L, 1);
+ knot_db_val_t keyval[100][2];
+ int ret = cache_prefixed(cache, prefix, false/*FIXME*/, keyval, 100);
+ if (ret < 0) {
+ format_error(L, kr_strerror(ret));
+ lua_error(L);
+ }
+ /* Format output */
+ lua_newtable(L);
+ for (int i = 0; i < ret; ++i) {
+ cache_dump(L, keyval[i]);
+ }
+ return 1;
+}
+#endif
+static int cache_get(lua_State *L)
+{
+ int ret = kr_error(ENOSYS);
+ format_error(L, kr_strerror(ret));
+ lua_error(L);
+ return ret;
+}
+
+/** Set time interval for cleaning rtt cache.
+ * Servers with score >= KR_NS_TIMEOUT will be cleaned after
+ * this interval ended up, so that they will be able to participate
+ * in NS elections again. */
+static int cache_ns_tout(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct kr_context *ctx = &engine->resolver;
+
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 1) {
+ lua_pushinteger(L, ctx->cache_rtt_tout_retry_interval);
+ return 1;
+ }
+
+ if (!lua_isnumber(L, 1)) {
+ format_error(L, "expected 'cache.ns_tout(interval in ms)'");
+ lua_error(L);
+ }
+
+ lua_Integer interval_lua = lua_tointeger(L, 1);
+ if (!(interval_lua > 0 && interval_lua < UINT_MAX)) {
+ format_error(L, "invalid interval specified, it must be in range > 0, < " xstr(UINT_MAX));
+ lua_error(L);
+ }
+
+ ctx->cache_rtt_tout_retry_interval = interval_lua;
+ lua_pushinteger(L, ctx->cache_rtt_tout_retry_interval);
+ return 1;
+}
+
+/** Zone import completion callback.
+ * Deallocates zone import context. */
+static void cache_zone_import_cb(int state, void *param)
+{
+ assert (param);
+ (void)state;
+ struct worker_ctx *worker = (struct worker_ctx *)param;
+ assert (worker->z_import);
+ zi_free(worker->z_import);
+ worker->z_import = NULL;
+}
+
+/** Import zone from file. */
+static int cache_zone_import(lua_State *L)
+{
+ int ret = -1;
+ char msg[128];
+
+ struct worker_ctx *worker = wrk_luaget(L);
+ if (!worker) {
+ strncpy(msg, "internal error, empty worker pointer", sizeof(msg));
+ goto finish;
+ }
+
+ if (worker->z_import && zi_import_started(worker->z_import)) {
+ strncpy(msg, "import already started", sizeof(msg));
+ goto finish;
+ }
+
+ (void)cache_assert_open(L); /* just check it in advance */
+
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 1 || !lua_isstring(L, 1)) {
+ strncpy(msg, "expected 'cache.zone_import(path to zone file)'", sizeof(msg));
+ goto finish;
+ }
+
+ /* Parse zone file */
+ const char *zone_file = lua_tostring(L, 1);
+
+ const char *default_origin = NULL; /* TODO */
+ uint16_t default_rclass = 1;
+ uint32_t default_ttl = 0;
+
+ if (worker->z_import == NULL) {
+ worker->z_import = zi_allocate(worker, cache_zone_import_cb, worker);
+ if (worker->z_import == NULL) {
+ strncpy(msg, "can't allocate zone import context", sizeof(msg));
+ goto finish;
+ }
+ }
+
+ ret = zi_zone_import(worker->z_import, zone_file, default_origin,
+ default_rclass, default_ttl);
+
+ lua_newtable(L);
+ if (ret == 0) {
+ strncpy(msg, "zone file successfully parsed, import started", sizeof(msg));
+ } else if (ret == 1) {
+ strncpy(msg, "TA not found", sizeof(msg));
+ } else {
+ strncpy(msg, "error parsing zone file", sizeof(msg));
+ }
+
+finish:
+ msg[sizeof(msg) - 1] = 0;
+ lua_newtable(L);
+ lua_pushstring(L, msg);
+ lua_setfield(L, -2, "msg");
+ lua_pushnumber(L, ret);
+ lua_setfield(L, -2, "code");
+
+ return 1;
+}
+
+int lib_cache(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "backends", cache_backends },
+ { "count", cache_count },
+ { "stats", cache_stats },
+ { "checkpoint", cache_checkpoint },
+ { "open", cache_open },
+ { "close", cache_close },
+ { "prune", cache_prune },
+ { "clear_everything", cache_clear_everything },
+ { "get", cache_get },
+ { "max_ttl", cache_max_ttl },
+ { "min_ttl", cache_min_ttl },
+ { "ns_tout", cache_ns_tout },
+ { "zone_import", cache_zone_import },
+ { NULL, NULL }
+ };
+
+ register_lib(L, "cache", lib);
+ return 1;
+}
+
+static void event_free(uv_timer_t *timer)
+{
+ struct worker_ctx *worker = timer->loop->data;
+ lua_State *L = worker->engine->L;
+ int ref = (intptr_t) timer->data;
+ luaL_unref(L, LUA_REGISTRYINDEX, ref);
+ free(timer);
+}
+
+static int execute_callback(lua_State *L, int argc)
+{
+ int ret = engine_pcall(L, argc);
+ if (ret != 0) {
+ fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
+ }
+ /* Clear the stack, there may be event a/o enything returned */
+ lua_settop(L, 0);
+ return ret;
+}
+
+static void event_callback(uv_timer_t *timer)
+{
+ struct worker_ctx *worker = timer->loop->data;
+ lua_State *L = worker->engine->L;
+
+ /* Retrieve callback and execute */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t) timer->data);
+ lua_rawgeti(L, -1, 1);
+ lua_pushinteger(L, (intptr_t) timer->data);
+ int ret = execute_callback(L, 1);
+ /* Free callback if not recurrent or an error */
+ if (ret != 0 || (uv_timer_get_repeat(timer) == 0 && uv_is_active((uv_handle_t *)timer) == 0)) {
+ if (!uv_is_closing((uv_handle_t *)timer)) {
+ uv_close((uv_handle_t *)timer, (uv_close_cb) event_free);
+ }
+ }
+}
+
+static void event_fdcallback(uv_poll_t* handle, int status, int events)
+{
+ struct worker_ctx *worker = handle->loop->data;
+ lua_State *L = worker->engine->L;
+
+ /* Retrieve callback and execute */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t) handle->data);
+ lua_rawgeti(L, -1, 1);
+ lua_pushinteger(L, (intptr_t) handle->data);
+ lua_pushinteger(L, status);
+ lua_pushinteger(L, events);
+ int ret = execute_callback(L, 3);
+ /* Free callback if not recurrent or an error */
+ if (ret != 0) {
+ if (!uv_is_closing((uv_handle_t *)handle)) {
+ uv_close((uv_handle_t *)handle, (uv_close_cb) event_free);
+ }
+ }
+}
+
+static int event_sched(lua_State *L, unsigned timeout, unsigned repeat)
+{
+ uv_timer_t *timer = malloc(sizeof(*timer));
+ if (!timer) {
+ format_error(L, "out of memory");
+ lua_error(L);
+ }
+
+ /* Start timer with the reference */
+ uv_loop_t *loop = uv_default_loop();
+ uv_timer_init(loop, timer);
+ int ret = uv_timer_start(timer, event_callback, timeout, repeat);
+ if (ret != 0) {
+ free(timer);
+ format_error(L, "couldn't start the event");
+ lua_error(L);
+ }
+
+ /* Save callback and timer in registry */
+ lua_newtable(L);
+ lua_pushvalue(L, 2);
+ lua_rawseti(L, -2, 1);
+ lua_pushlightuserdata(L, timer);
+ lua_rawseti(L, -2, 2);
+ int ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* Save reference to the timer */
+ timer->data = (void *) (intptr_t)ref;
+ lua_pushinteger(L, ref);
+ return 1;
+}
+
+static int event_after(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 2 || !lua_isnumber(L, 1) || !lua_isfunction(L, 2)) {
+ format_error(L, "expected 'after(number timeout, function)'");
+ lua_error(L);
+ }
+
+ return event_sched(L, lua_tonumber(L, 1), 0);
+}
+
+static int event_recurrent(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 2 || !lua_isnumber(L, 1) || !lua_isfunction(L, 2)) {
+ format_error(L, "expected 'recurrent(number interval, function)'");
+ lua_error(L);
+ }
+ return event_sched(L, 0, lua_tonumber(L, 1));
+}
+
+static int event_cancel(lua_State *L)
+{
+ int n = lua_gettop(L);
+ if (n < 1 || !lua_isnumber(L, 1)) {
+ format_error(L, "expected 'cancel(number event)'");
+ lua_error(L);
+ }
+
+ /* Fetch event if it exists */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_tointeger(L, 1));
+ if (!lua_istable(L, -1)) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ /* Close the timer */
+ lua_rawgeti(L, -1, 2);
+ uv_handle_t *timer = lua_touserdata(L, -1);
+ if (!uv_is_closing(timer)) {
+ uv_close(timer, (uv_close_cb) event_free);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int event_reschedule(lua_State *L)
+{
+ int n = lua_gettop(L);
+ if (n < 2 || !lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
+ format_error(L, "expected 'reschedule(number event, number timeout)'");
+ lua_error(L);
+ }
+
+ /* Fetch event if it exists */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_tointeger(L, 1));
+ if (!lua_istable(L, -1)) {
+ lua_pushboolean(L, false);
+ return 1;
+ }
+
+ /* Reschedule the timer */
+ lua_rawgeti(L, -1, 2);
+ uv_handle_t *timer = lua_touserdata(L, -1);
+ if (!uv_is_closing(timer)) {
+ if (uv_is_active(timer)) {
+ uv_timer_stop((uv_timer_t *)timer);
+ }
+ int ret = uv_timer_start((uv_timer_t *)timer, event_callback, lua_tointeger(L, 2), 0);
+ if (ret != 0) {
+ event_cancel(L);
+ lua_pushboolean(L, false);
+ return 1;
+ }
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+static int event_fdwatch(lua_State *L)
+{
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n < 2 || !lua_isnumber(L, 1) || !lua_isfunction(L, 2)) {
+ format_error(L, "expected 'socket(number fd, function)'");
+ lua_error(L);
+ }
+
+ uv_poll_t *handle = malloc(sizeof(*handle));
+ if (!handle) {
+ format_error(L, "out of memory");
+ lua_error(L);
+ }
+
+ /* Start timer with the reference */
+ int sock = lua_tonumber(L, 1);
+ uv_loop_t *loop = uv_default_loop();
+#if defined(__APPLE__) || defined(__FreeBSD__)
+ /* libuv is buggy and fails to create poller for
+ * kqueue sockets as it can't be fcntl'd to non-blocking mode,
+ * so we pass it a copy of standard input and then
+ * switch it with real socket before starting the poller
+ */
+ int decoy_fd = dup(STDIN_FILENO);
+ int ret = uv_poll_init(loop, handle, decoy_fd);
+ if (ret == 0) {
+ handle->io_watcher.fd = sock;
+ }
+ close(decoy_fd);
+#else
+ int ret = uv_poll_init(loop, handle, sock);
+#endif
+ if (ret == 0) {
+ ret = uv_poll_start(handle, UV_READABLE, event_fdcallback);
+ }
+ if (ret != 0) {
+ free(handle);
+ format_error(L, "couldn't start event poller");
+ lua_error(L);
+ }
+
+ /* Save callback and timer in registry */
+ lua_newtable(L);
+ lua_pushvalue(L, 2);
+ lua_rawseti(L, -2, 1);
+ lua_pushlightuserdata(L, handle);
+ lua_rawseti(L, -2, 2);
+ int ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ /* Save reference to the timer */
+ handle->data = (void *) (intptr_t)ref;
+ lua_pushinteger(L, ref);
+ return 1;
+}
+
+int lib_event(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "after", event_after },
+ { "recurrent", event_recurrent },
+ { "cancel", event_cancel },
+ { "socket", event_fdwatch },
+ { "reschedule", event_reschedule },
+ { NULL, NULL }
+ };
+
+ register_lib(L, "event", lib);
+ return 1;
+}
+
+static int wrk_resolve(lua_State *L)
+{
+ struct worker_ctx *worker = wrk_luaget(L);
+ if (!worker) {
+ return 0;
+ }
+
+ uint8_t dname[KNOT_DNAME_MAXLEN];
+ if (!knot_dname_from_str(dname, lua_tostring(L, 1), sizeof(dname))) {
+ lua_pushstring(L, "invalid qname");
+ lua_error(L);
+ };
+
+ /* Check class and type */
+ uint16_t rrtype = lua_tointeger(L, 2);
+ if (!lua_isnumber(L, 2)) {
+ lua_pushstring(L, "invalid RR type");
+ lua_error(L);
+ }
+
+ uint16_t rrclass = lua_tointeger(L, 3);
+ if (!lua_isnumber(L, 3)) { /* Default class is IN */
+ rrclass = KNOT_CLASS_IN;
+ }
+
+ /* Add query options */
+ const struct kr_qflags *options = lua_topointer(L, 4);
+ if (!options) { /* but we rely on the lua wrapper when dereferencing non-NULL */
+ lua_pushstring(L, "invalid options");
+ lua_error(L);
+ }
+
+ /* Create query packet */
+ knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_EDNS_MAX_UDP_PAYLOAD, NULL);
+ if (!pkt) {
+ lua_pushstring(L, kr_strerror(ENOMEM));
+ lua_error(L);
+ }
+ knot_pkt_put_question(pkt, dname, rrclass, rrtype);
+ knot_wire_set_rd(pkt->wire);
+ knot_wire_set_ad(pkt->wire);
+
+ /* Add OPT RR */
+ pkt->opt_rr = knot_rrset_copy(worker->engine->resolver.opt_rr, NULL);
+ if (!pkt->opt_rr) {
+ knot_pkt_free(pkt);
+ return kr_error(ENOMEM);
+ }
+ if (options->DNSSEC_WANT) {
+ knot_edns_set_do(pkt->opt_rr);
+ }
+
+ if (options->DNSSEC_CD) {
+ knot_wire_set_cd(pkt->wire);
+ }
+
+ /* Create task and start with a first question */
+ struct qr_task *task = worker_resolve_start(worker, pkt, *options);
+ if (!task) {
+ knot_rrset_free(pkt->opt_rr, NULL);
+ knot_pkt_free(pkt);
+ lua_pushstring(L, "couldn't create a resolution request");
+ lua_error(L);
+ }
+
+ /* Add initialisation callback */
+ if (lua_isfunction(L, 5)) {
+ lua_pushvalue(L, 5);
+ lua_pushlightuserdata(L, worker_task_request(task));
+ (void) execute_callback(L, 1);
+ }
+
+ /* Start execution */
+ int ret = worker_resolve_exec(task, pkt);
+ lua_pushboolean(L, ret == 0);
+ knot_rrset_free(pkt->opt_rr, NULL);
+ knot_pkt_free(pkt);
+ return 1;
+}
+
+static inline double getseconds(uv_timeval_t *tv)
+{
+ return (double)tv->tv_sec + 0.000001*((double)tv->tv_usec);
+}
+
+/** Return worker statistics. */
+static int wrk_stats(lua_State *L)
+{
+ struct worker_ctx *worker = wrk_luaget(L);
+ if (!worker) {
+ return 0;
+ }
+ lua_newtable(L);
+ lua_pushnumber(L, worker->stats.concurrent);
+ lua_setfield(L, -2, "concurrent");
+ lua_pushnumber(L, worker->stats.udp);
+ lua_setfield(L, -2, "udp");
+ lua_pushnumber(L, worker->stats.tcp);
+ lua_setfield(L, -2, "tcp");
+ lua_pushnumber(L, worker->stats.tls);
+ lua_setfield(L, -2, "tls");
+ lua_pushnumber(L, worker->stats.ipv6);
+ lua_setfield(L, -2, "ipv6");
+ lua_pushnumber(L, worker->stats.ipv4);
+ lua_setfield(L, -2, "ipv4");
+ lua_pushnumber(L, worker->stats.queries);
+ lua_setfield(L, -2, "queries");
+ lua_pushnumber(L, worker->stats.dropped);
+ lua_setfield(L, -2, "dropped");
+ lua_pushnumber(L, worker->stats.timeout);
+ lua_setfield(L, -2, "timeout");
+ /* Add subset of rusage that represents counters. */
+ uv_rusage_t rusage;
+ if (uv_getrusage(&rusage) == 0) {
+ lua_pushnumber(L, getseconds(&rusage.ru_utime));
+ lua_setfield(L, -2, "usertime");
+ lua_pushnumber(L, getseconds(&rusage.ru_stime));
+ lua_setfield(L, -2, "systime");
+ lua_pushnumber(L, rusage.ru_majflt);
+ lua_setfield(L, -2, "pagefaults");
+ lua_pushnumber(L, rusage.ru_nswap);
+ lua_setfield(L, -2, "swaps");
+ lua_pushnumber(L, rusage.ru_nvcsw + rusage.ru_nivcsw);
+ lua_setfield(L, -2, "csw");
+ }
+ /* Get RSS */
+ size_t rss = 0;
+ if (uv_resident_set_memory(&rss) == 0) {
+ lua_pushnumber(L, rss);
+ lua_setfield(L, -2, "rss");
+ }
+ return 1;
+}
+
+int lib_worker(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "resolve_unwrapped", wrk_resolve },
+ { "stats", wrk_stats },
+ { NULL, NULL }
+ };
+ register_lib(L, "worker", lib);
+ return 1;
+}
diff --git a/daemon/bindings.h b/daemon/bindings.h
new file mode 100644
index 0000000..5540778
--- /dev/null
+++ b/daemon/bindings.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Bindings to engine services, see \a https://www.lua.org/manual/5.2/manual.html#luaL_newlib for the reference.
+ */
+#pragma once
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "daemon/engine.h"
+
+/** @internal Compatibility wrapper for Lua 5.0 - 5.2 */
+#if LUA_VERSION_NUM >= 502
+#define register_lib(L, name, lib) \
+ luaL_newlib((L), (lib))
+#else
+#define lua_rawlen(L, obj) \
+ lua_objlen((L), (obj))
+#define register_lib(L, name, lib) \
+ luaL_openlib((L), (name), (lib), 0)
+#endif
+
+#if !LUA_HAS_SETFUNCS
+/* Adapted from Lua 5.2.0 */
+static inline void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ luaL_checkstack(L, nup+1, "too many upvalues");
+ for (; l->name != NULL; l++) { /* fill the table with given functions */
+ int i;
+ lua_pushstring(L, l->name);
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -(nup+1));
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_settable(L, -(nup + 3));
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+#endif
+
+/**
+ * Load 'modules' package.
+ * @param L scriptable
+ * @return number of packages to load
+ */
+int lib_modules(lua_State *L);
+
+/**
+ * Load 'net' package.
+ * @param L scriptable
+ * @return number of packages to load
+ */
+int lib_net(lua_State *L);
+
+/**
+ * Load 'cache' package.
+ * @param L scriptable
+ * @return number of packages to load
+ */
+int lib_cache(lua_State *L);
+
+/**
+ * Load 'event' package.
+ * @param L scriptable
+ * @return number of packages to load
+ */
+int lib_event(lua_State *L);
+
+/**
+ * Load worker API.
+ * @param L scriptable
+ * @return number of packages to load
+ */
+int lib_worker(lua_State *L);
diff --git a/daemon/cache.test/clear.test.lua b/daemon/cache.test/clear.test.lua
new file mode 100644
index 0000000..473103b
--- /dev/null
+++ b/daemon/cache.test/clear.test.lua
@@ -0,0 +1,211 @@
+-- unload modules which are not related to this test
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+if priming then
+ modules.unload('priming')
+end
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+-- test. domain is used by some tests, allow it
+policy.add(policy.suffix(policy.PASS, {todname('test.')}))
+
+cache.size = 2*MB
+-- verbose(true)
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function () return 1 end)
+event.cancel(ev)
+ev = event.after(0, function () return 1 end)
+
+
+-- Import fake root zone; avoid interference with configured KEYFILE_DEFAULT.
+trust_anchors.keyfile_default = nil
+trust_anchors.add('. IN DS 48409 8 2 3D63A0C25BCE86621DE63636F11B35B908EFE8E9381E0E3E9DEFD89EA952C27D')
+
+local function check_answer(desc, qname, qtype, expected_rcode)
+ qtype_str = kres.tostring.type[qtype]
+ callback = function(pkt)
+ same(pkt:rcode(), expected_rcode,
+ desc .. ': expecting answer for query ' .. qname .. ' ' .. qtype_str
+ .. ' with rcode ' .. kres.tostring.rcode[expected_rcode])
+
+ ok((pkt:ancount() > 0) == (pkt:rcode() == kres.rcode.NOERROR),
+ desc ..': checking number of answers for ' .. qname .. ' ' .. qtype_str)
+ end
+ resolve(qname, qtype, kres.class.IN, {}, callback)
+end
+
+-- do not attempt to contact outside world, operate only on cache
+net.ipv4 = false
+net.ipv6 = false
+-- do not listen, test is driven by config code
+env.KRESD_NO_LISTEN = true
+
+
+local function import_zone()
+ local import_res = cache.zone_import('testroot.zone')
+ assert(import_res.code == 0)
+ -- beware that import takes at least 100 ms
+ worker.sleep(0.2) -- zimport is delayed by 100 ms from function call
+ -- sanity checks - cache must be filled in
+ ok(cache.count() > 0, 'cache is not empty after import')
+ check_answer('root apex is in cache',
+ '.', kres.type.NS, kres.rcode.NOERROR)
+ check_answer('deep subdomain is in cache',
+ 'a.b.subtree1.', kres.type.AAAA, kres.rcode.NOERROR)
+
+end
+
+local function test_exact_match_qtype()
+ nok(cache.clear('a.b.subtree1.', true, kres.type.A)['chunk_limit'],
+ 'single qname+qtype can be cleared at once')
+ check_answer('exact match on qname+qtype must flush RR from cache',
+ 'a.b.subtree1.', kres.type.A, kres.rcode.SERVFAIL)
+ check_answer('exact match on qname+qtype must not affect other RRs on the same node',
+ 'a.b.subtree1.', kres.type.AAAA, kres.rcode.NOERROR)
+ check_answer('exact match on qname must not affect parent',
+ 'b.subtree1.', kres.type.A, kres.rcode.NOERROR)
+end
+
+local function test_exact_match_qname()
+ res = cache.clear('a.b.SubTree1.')
+ is(res.count, 2, 'single qname can be cleared at once')
+ check_answer('exact match on qname must flush all RRs with the same owner from cache',
+ 'a.b.subtree1.', kres.type.AAAA, kres.rcode.SERVFAIL)
+ check_answer('exact match on qname must flush all RRs with the same owner from cache',
+ 'a.b.subtree1.', kres.type.A, kres.rcode.SERVFAIL)
+ check_answer('exact match on qname must flush all RRs with the same owner from cache',
+ 'a.b.subtree1.', kres.type.TXT, kres.rcode.SERVFAIL)
+ -- exact match for negative proofs is not implemented yet
+ --check_answer('exact match on qname must flush negative proofs for owner from cache',
+ -- 'a.b.subtree1.', kres.type.NULL, kres.rcode.SERVFAIL)
+ --check_answer('exact match on qname must not affect parent',
+ -- 'b.subtree1.', kres.type.A, kres.rcode.NOERROR)
+ -- same(cache.clear(), 0, 'full cache clear can be performed')
+ --check_answer('.', kres.type.NS, false)
+
+end
+
+local function test_subtree()
+ res = cache.clear('subtree1.')
+ nok(res.chunk_limit,
+ 'whole positive subtree must be flushed (does not include neg. proofs)')
+ ok(res.not_apex,
+ 'subtree clear below apex must be detected')
+ same(res.subtree, '.', 'detected apex must be returned')
+ check_answer('subtree variant must flush all RRs in subdomains from cache',
+ 'b.subtree1.', kres.type.A, kres.rcode.SERVFAIL)
+ check_answer('subtree variant must flush all RRs in subdomains from cache',
+ 'b.subtree1.', kres.type.TXT, kres.rcode.SERVFAIL)
+ check_answer('subtree variant must flush all RRs in subdomains from cache',
+ 'subtree1.', kres.type.TXT, kres.rcode.SERVFAIL)
+ check_answer('subtree variant must not affect parent',
+ '.', kres.type.NS, kres.rcode.NOERROR)
+ -- same(cache.clear(), 0, 'full cache clear can be performed')
+ --check_answer('.', kres.type.NS, false)
+
+end
+
+local function test_callback()
+ local test_name = '20r.subtree2.'
+ local test_exactname = true
+ local test_rrtype = nil
+ local test_chunksize = 1
+ local test_prev_state = { works = true }
+ local function check_callback(name, exact_name, rr_type, chunk_size, callback, prev_state, errors)
+ is(errors.count, 1, 'callback received correct # of removed records')
+ is(test_name, name, 'callback received subtree name')
+ is(test_exactname, exact_name, 'callback received exact_name')
+ is(test_rrtype, rr_type, 'callback received rr_type')
+ is(test_chunksize, chunk_size, 'callback received chunk_size')
+ is(check_callback, callback, 'callback received reference to itself')
+ is(type(errors), 'table', 'callback received table of errors')
+ same(test_prev_state, prev_state, 'callback received previous state')
+ return 666
+ end
+ same(cache.clear(test_name, test_exactname, test_rrtype, test_chunksize, check_callback, test_prev_state),
+ 666, 'first callback return value is passed to cache.clear() caller')
+ local cnt_before_wait = cache.count()
+ worker.sleep(0.2)
+ is(cnt_before_wait, cache.count(), 'custom callback can stop clearing')
+end
+
+local function test_subtree_limit() -- default limit = 100
+ res = cache.clear('subtree2.', false, nil)
+ ok(res.chunk_limit,
+ 'chunk_size limit must be respected')
+ is(res.count, 100,
+ 'chunk_size limit must match returned count')
+
+ -- callbacks are running in background so we can now wait
+ -- and later verify that everything was removed
+ -- 200 RRs, 100 was removed in first call
+ -- so the rest should be removed in single invocation of callback
+ -- hopefully the machine is not too slow ...
+ worker.sleep(0.1)
+ res = cache.clear('subtree2.', false, nil)
+ is(res.count, 0,
+ 'previous calls + callbacks must have removed everything')
+end
+
+local function test_apex()
+ check_answer('a negative proof is still present in cache',
+ 'aaaaa.b.subtree1.', kres.type.TXT, kres.rcode.NXDOMAIN)
+
+ local prev_count = cache.count()
+ ok(prev_count > 0, 'previous subtree clearing did not remove everything')
+ res = cache.clear('.', false, nil, 10000)
+ is(res.count, prev_count, 'clear on root removed everyting including proofs')
+ check_answer('exact match on qname must flush negative proofs for owner from cache',
+ 'a.b.subtree1.', kres.type.NULL, kres.rcode.SERVFAIL)
+end
+
+local function test_root()
+ check_answer('root apex is still in cache',
+ '.', kres.type.NS, kres.rcode.NOERROR)
+ res = cache.clear('.', true)
+ check_answer('root apex is in no longer cache',
+ '.', kres.type.NS, kres.rcode.SERVFAIL)
+ check_answer('some other item is still in cache',
+ '16r.subtree2.', kres.type.A, kres.rcode.NOERROR)
+
+ local prev_count = cache.count()
+ res = cache.clear('.')
+ is(res.count, prev_count, 'full clear reports correct number of entries')
+ is(cache.count(), 0, 'clearing root clears everything')
+end
+
+local function test_complete_flush()
+ local prev_count = cache.count()
+ res = cache.clear()
+ is(res.count, prev_count, 'full clear reports correct number of entries')
+ is(cache.count(), 0, 'cache is empty after full clear')
+end
+
+return {
+ import_zone,
+ test_exact_match_qtype,
+ test_exact_match_qname,
+ test_callback,
+ import_zone,
+ test_subtree,
+ test_subtree_limit,
+ test_apex,
+ import_zone,
+ test_root,
+ import_zone,
+ test_complete_flush,
+}
diff --git a/daemon/cache.test/testroot.zone b/daemon/cache.test/testroot.zone
new file mode 100644
index 0000000..51814d5
--- /dev/null
+++ b/daemon/cache.test/testroot.zone
@@ -0,0 +1,1256 @@
+; File written on Wed Aug 15 09:23:14 2018
+; dnssec_signzone version 9.13.0-dev
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20460416024207 20180815062314 48409 . r3pIfvAMPJ8eHGU/OLKUCCRU2+u+1ah7fably80gtRVEgLeb207jQEAW MbNlTFJhUIomov3+ERdPAOZ9Kw0+k4d856sfMUUtgdX7BL9Zo0fIcpTu 7/ek7EELfKXb/vYfFlIP1lEOUvo7MB/YDo1zljPJ1Qh1BDsp5zyNaTgq O0PQg/nN1UmFXwjEVGmsn6uid6cJfxdO7UaluZ5c/alvOIx3tBAoDJ2j a4He6Rjlc63pEsKBYmAHz2Rdxq5d/+kqVFJUTyVVvMJ35apczpZ4S4gl BPJQZz15hB3OcpPt7GY1TwI83FjGXFaGiuTUqhvSIRoFimRPVOIGSkJX edKPBQ==
+; resign=20460416024207
+. 86400 IN NS rootns.
+. 86400 IN RRSIG NS 8 0 86400 20460416024207 20180815062314 48409 . lAwwTOgQuFowdXma1vVrHKz7qi4vaighh104/2vl6DlEpAFEEOz8y5Y3 9bjWfaNp+UDq0AyqnZ3ow7VN9/Hm8uUbicu2BrNSDhGQ/F66rvw8wZff eE5+w3Ihgm4/vK8zmxUnxRz5mwcbbuCyyTP13WQJ8N89wFgsgezkM2E8 s0qKw5ZyriPopd9X2uLFS1vapezFSSo6AN0khBdrUYWzgCRbE1zLHmKV AW1nWMcgV5zJNX1/9dxgC+yEM1nYhcN1Nhl7neO23pRk/vZ26SruzPdY s5j+fn7WyV0cQqAb7BJ7aTFYuD3kG1s3QUxjQolcCUjK7fCCJeYPINdK m2dLtw==
+; resign=20460416024207
+. 86400 IN NSEC rootns. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20460416024207 20180815062314 48409 . aLdes4mtohdcKA7/kyOdDrCUA72c7DRuK86yxOl3p+5mDarjzBw2Q02b nXEgWoY2RdMJ+KlkxcU87Ojl/p3sIF9RwHlzvW09iXznPyLVTPwD/mnq /5onoMPW4dLbwVIIrFgjhuF/YfN+XCyKoKIJQgB2Qdoo4ppWqeUZXOgU byoPWpzuBupMmrwjownmJLO3bUFUHDaNkIXFi3KwdvhdYj28bP4Z9P4A 1RAKdmU4C24f0auTJDIVDFj4v0ENXzpvDKJyX/VOyLR5+EXwp4YtO1vl TjWueCrTREYDZzXYJgtYHvMDVNQ1uZ+6YCLE7wrgCTQYne9uNp6eAZH3 oFIPTw==
+; resign=20460416024207
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
+. 1814400 IN RRSIG DNSKEY 8 0 1814400 20460416024207 20180815062314 48409 . MiiRlBAgMnadkm6Y/IDLGiE9Y9xvGU0u9IYD1cAddUMpYAwGe5584lfj 1L/Pdg+OeJiGDfFSD7m3ppX18wIeo5eWHmdCO1/nEAdPl0u/XDB/avtj o3Q34szjOV/sA3s5a3Kc+DFrBiZiTA5BwMIHZX4vvITf2cEq2K4K39Iv Cg1blSathklWkpgYIPttpZIcIt5vxoe9e0aqar6FLOCWJ68noreCIenR XmzhMW+l7kOBoKOvkyv1lcDM0zWXI9r5lqAqJB0mWsCiR+VloxSbFii7 kjUDju8BqXu2G8YzM7y0vMytMafjfLsj7bHvQ1HefOht6Xzi1jRHblEh GGQ8UA==
+; resign=20460416024207
+100r.subtree2. 86400 IN A 192.0.2.1
+100r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . QMB4uw2u+kJ4Iic6G6fJ1B+LL5Jp0y/tPHwb9iW8mfAfZoaHuNxUFMdW nncNjZcjIXpeWiWcD3fzKr6DwJ20oWMpt9fxGthYyXp5DWhmeb6Pq6sS cWy5xhGEP6Cv1gBx4oZs0xmdmLsi/eK8x0E6DScwGeLu9v/lUGxnD7ug b4gl/9ABXhFVXW0qALF48dTpc5mMDsAIkPJevarbLDrg3CyOTrCcZtc1 v9DYSN2KGG7l3H7jAY9WNpwhTGXVNthSGHLvSUmzJ418ya8bU9L0Baoj +WBmdERcmFyx4KS+mwDcJxORwLPtEpRN1Kdg/X/z41cw/ViakoZ62ikq r2j8YA==
+; resign=20460416024207
+100r.subtree2. 86400 IN NSEC 101r.subtree2. A RRSIG NSEC
+100r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . EK+71G5XMyRg37UmfcnMxVl6RbkzUL5YLi+kL8LXYXrq5AEXCof2K26i EPVZlQqjaSSyCHDV1PGpUAbxmGu5JFJ17wksgJ5q+vkPMTJhU9gVQUGf 1Ymj8hOa+eYs1Of0/3O2mf5V5KOpQ/R/cONQelziCLQeJJvJ70AHJUx/ 3+guSkXehkZszxuVozy7AmguyRjAWtNOLmVR74HFaP5+PyosZhie7LZS rsGq0p+VzHc1Xl9BXLBg/WrBXEpcuEtvg1wc/gVkNAlC4NLr1zbWcmIw Hdf3/NFgfFkJ0gFRX7P3+zXCipUHjdpb/kxtFCopYlZpP5km0cOmrbq5 rPwwcw==
+; resign=20460416024207
+rootns. 86400 IN A 198.41.0.4
+rootns. 86400 IN RRSIG A 8 1 86400 20460416024207 20180815062314 48409 . wvg4r9R9qeCwgxxb+Hrit/Ag63lSAzB8SPyKAz61GHojJbES8sz1dvnN fpaFX6bd+8oYfLKK2m+xyNITXm7mzZU2lEg6eHih4E/PCQzEfi12VaQq Esyg46LKIYCMcazou0I3ot/BbXHokSlAnfyAA+2+7EKSFK6SZDVQwK5Q Y0w3ps+gevcrnSHSQuymyjkOUgAxGtGTEA/QvmfzS7f7Dc0vrTRHRmOU 0lJ6Epi8kajwMjtEkRWN0TUnwD2z1eNyaCaa+C9TTwIKGoQkZlMFoc/m 4hBCPDEA1/Z5qDVFnFdWNOE3CLon/P14ONTznSJr8lfqdPmRb4iXqIn3 yNRLaQ==
+; resign=20460416024207
+rootns. 86400 IN NSEC subtree1. A RRSIG NSEC
+rootns. 86400 IN RRSIG NSEC 8 1 86400 20460416024207 20180815062314 48409 . Kv4r9Utt5+TrzUuzXedmlJlJsjai7Ebs8Ldj2TfV7uktkOx1GTCTMIFs jmWBJDi/tm2CRP8VvNL6tSmxOQ2sNRXbyNmbgY+WujCuIA1hTiYC8cR5 p17K0MuR6LDu7UfcHVUAIiiucqQ+FHgnDN6DPyeGPMEqiRUG6KFtmQdz VcVHN9EeVwvru6l7M0NSg4onNGDUAd3Lzb4OVSdjcfCC5/TRxN/A04pm xIbag7nBTmx5T7/RRhywKycnbaPCmljmGtwd0+ikdNtIkQZa2/S82rOb 579vgx2cliVQszNmqei3PVRSHDoqTv26lHM27fTAkwdCGX2rBMDRLjQ3 Dk/etQ==
+; resign=20460416024207
+102r.subtree2. 86400 IN A 192.0.2.1
+102r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . AJoiUtB4aQsllEPMM4jYB8B5ZSJA3nAZnICi0lxmpJzhYUVnOKdj6B50 1U2TADwJ1SHs9tciZAuJvILJMwu1LapISmZ9692u7CR2gcTfifnY8iny +cZwEsFFbwdv/pHMIZhox+h2+H18ltSpa8Sad8vvnqtaePtUgnJdR3kp 2b5q77VrSxEwizLq6OkjCYiCPh7YrbfNfTesZwIbuKH80TSaJF9kTVar hh5yW23vEwq0tGyrYn4bYJR2OzZqukLHz+aSMIQ7BpQPHY0hMWPndb5p HLvaDHbmp7Mc/1bnhCVmqqECKouV/Y8omUUHOljyjZ8WlCol0pYWQm6L O/U4SQ==
+; resign=20460416024207
+102r.subtree2. 86400 IN NSEC 103r.subtree2. A RRSIG NSEC
+102r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . PE/1zyqvetDmu+d7yFhICfmNWl1AmSZ1K5tKtb04wz+I1aihwWkozCuC hLskRAIrhogNSFDjVqhM2F1HFYm3ACkr3vvWxsTAk4hnvIIw1TVj+iqU ZTpXNKnS7UarPxM8a5fctME2mgPSQnsAzJRlkInpT450Ls7qhTpqEREx wMAY7fQx+Y5zdg90rEINJBdKJgw7K8ES3bm1JwEIpkjw4I5NZhyAS026 2fW6x5UaTGWhV1Qa7YVwdXrEDxcsyb/FR/N0AofcP0JrQ8/UfPJNoO3U rtUigRA8tDapiQuSTFaYb1thtqMgGtrJqxjDRU82I75HBZnhhFilOGUD fcVq9g==
+; resign=20460416024207
+104r.subtree2. 86400 IN A 192.0.2.1
+104r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . lNhsi5Dvb6lFrzp8+A3j5DDY+sK8p+CbB9jRtxRoCh9TJsWs3V8tWfcJ qLN7PKgCchmLTfQryKsIERDBNgEvaFbygk9UO/YX4z0J5xVtXQ6lRz12 rcgR0EJ098ZoOtmHa25+YILXwwO9WqoBzx5VItYduOaRXqDJA6QcUUyx cnd14DkfJcD/MXKMkWS95SIIOg5KuOga0N6H7ATIxkrTCbqRfLwoj0Ne 52Mp4LSyVY9BN51s/jHmYOYiubLMtGYKVVffkmH1LtqUnY/kNK0YixT8 4zs1REuk6e3PAiyBOANvMqVm76FiBapaZgFnGJu/2S7foTC0yHfmLh5J NFTq8Q==
+; resign=20460416024207
+104r.subtree2. 86400 IN NSEC 105r.subtree2. A RRSIG NSEC
+104r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . BrGAn5NmHS74Ru+CcjBzjUamO6en8GaTg+fOuSaECpFNCx/rnFQziS/a gZs44Mlc3IdXLEeo3GI21Uqf/mNeGqfl+TCnUfnevy+1Gl2093dtma4/ LNHMd9BxDmXe94WQVp4xJOLbICv4aaKIhGD7w4ck9cMk1r8p4ngvsvoV kn9uLl1lx14yddufdS8B/NGvzeqRlJNdyfZJg47pQfghgg+qLbmmzqHr Rt+ke0Vge4Nur3PsNs/daYb02OWqWA5YLbljRaKqatEn95ohkrfl/CMe rZ3b3gcR6dowj9+dIkGODCQhrzqtk3v1QAEkYq5LJDPPnhXYduNWqsz/ 5F/m/g==
+; resign=20460416024207
+a.b.subtree1. 86400 IN A 192.0.2.3
+a.b.subtree1. 86400 IN RRSIG A 8 3 86400 20460416024207 20180815062314 48409 . BTJSG6mn5eRo2GDyw8lT3S7POU6BBrB2w3ULx8+BY8aoEHzak8Ul/abD fqneEji+subHFGpMwQXFtzKfnwTTRHyHS2P7FZQO3l7b+T2oDRZn9B0d mrmGQRmv5XrTDlO0WRYlRsWSMalkbUEul6L9q3koCCtXd4GCxDh20tk7 o27pKtuO0ALptDLIMXoVdhRhTBd+qARVJrg2u/XyUzlwqfgZTsY6SkyN mEYvK4UCM1RkhqCqo3NBNmR7islmWVPM3Ax8uTssCf5T+MUN+gNT6Co+ zRXX71qGw6hpQFxWe1dA9PCna4ZoWPIfx6A666blMrciwbYTQL8xUEPS 5RmRtw==
+; resign=20460416024207
+a.b.subtree1. 86400 IN TXT "txt exists"
+a.b.subtree1. 86400 IN RRSIG TXT 8 3 86400 20460416024207 20180815062314 48409 . gN77jXi+ntj3SeXk2WprymZGcwPEXY/0w1svtsP2RXijvXwOlWlpmsSK +SnZFtkSRKwJXEY1nSDW3UORaDzzZrraMxCtjtt2Vi77Uqi97PdaRmk+ +IRcJBNQ3PywGRdqw1MZuPlyKbmGe8B4PE96d6ya4fXtvL8tuMU4L7uP h2Wn4sB1eSFpH5rGrytPMyv6W4T7JubL6+R1YdmQBAARJXnIqN8WlOYM JiZtQl7kdnPOxxhHZCzlFOP1Ci934u9jh93ynJPbF9dJG75f74+sWw2k RHZUu7SkphoPsVR7nhulAHcPB805yxWPtmMC2Rsq+RGbLpfgFENPsnxv VZa5Wg==
+; resign=20460416024207
+a.b.subtree1. 86400 IN AAAA 2001:db8::
+a.b.subtree1. 86400 IN RRSIG AAAA 8 3 86400 20460416024207 20180815062314 48409 . cLipbUelm96/75NoXOJR3atJKr9fjYaz4lu4CQBREmQ7eUwkGfDGW7jj ar60VA2OSVT1Q3SxsvKjZ9OjSDLtPbhVeIabBKhDQWULy3c0rBgblMfc xIa++QItLiuxyfj3EiwGfwkIlwuM0jg4sByisvWBeUwsIv9+nHJYZERf p96DhsZXC4OTba5Tai2sJ8CmYINWQBu8GRb9wrtrEBGg2LyZifXRirTB RoTuXPOSScURU4VmzyJrVLuNipsd9V6Dnq6J4Yuc21ws9ZrB7nF1TYqr zmW1x86umJHM1Evw6NWrHX4rMgiTiwJR0ju4uc7FDZ8irdtmcPGr0C9F 3hycmg==
+; resign=20460416024207
+a.b.subtree1. 86400 IN NSEC 100r.subtree2. A TXT AAAA RRSIG NSEC
+a.b.subtree1. 86400 IN RRSIG NSEC 8 3 86400 20460416024207 20180815062314 48409 . ipRQluXZcAsYQqTMnV6VDykJym1bh4VujIFvWnM+oQxZEpsreqwl3hFM INUapADed66F8p7goYlC9oKdbOfqLAJSBvPyL2MJIPEifnTeFI5SiQe7 u2NxsNn1glotVBHGL37EOf55xvbO9N/y8fnIjtOD4g8kJBthaeyOCsc+ KbcOcBce9y9f/meoibQc9plyQSeGhXYtc/9jliNmnJehG+y4WUZpmeOc sy0NB3VDHMwNigxUJl4+ezSGlR7TLReeGXX7BGBSdtDigz8uDpi5vmXk Ebmxjr1gSVh++5cZV2l6IhA6l6/ZNWh8EnYWnydHZR/FdMZ/xnJP9fdK bN5Kcg==
+; resign=20460416024207
+105r.subtree2. 86400 IN A 192.0.2.1
+105r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FBlsr7zNihecaykcv61PL0Huh8SECrXoZ/unuWxmT+ZqDKjmfFGxoG/v MgmmJ9r/sfZ29e9mMnfBtXj/xJLW1dbHYwFZSt4ZeGZ+W/ohgCKVW0Fb XJTZacoWJtXhgObs6gjoab5IPqle3dgqUsP6xNvzonReL1IW7+45QRh2 nWU+4j5OTL/eO1mNXU841PtvmmotwDamR6aSoNr3X99Hwd3/3yJtRIIW JYVAr5G49m+YickDVH2gvJ+JZkswzGfbQgXqThUiSMBfHw23LQk7A1ZH aStSqsRcJt/w1pTl5cEDpnq2yFelQdmCE1DqnUIOkSTRdemk4ObnXFOW FArXZw==
+; resign=20460416024207
+105r.subtree2. 86400 IN NSEC 106r.subtree2. A RRSIG NSEC
+105r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . uSMqXmIDnP/m7EW1gMGI7N8Wp6x142d8xTtJTFJ4mOPbyrKBRDDdzEEQ iiistwQThYUZkM6gWpiE0yfTvUI1pP4Aa6zASUExJoO0P+CEmHTmRJ9c 2sCqottCOirXivxfC2PoxXlIZ1nQketizjzMXErjKogU4/HaaaxiDLXh P56bAeFkIqGKujbdRhVMArugKvbbkjVjE1iXznG/bzKqOXldi7JNQbxx cc6+fZTs4Ahg2H+FtQLH+WFbD+JBLQzvc2WnjqvNq5MGTSKxcuGDA80O CLEFs/7zhEBSZYhBGoVXqywvDR4j4Lox02g5wUpWlXK10pnU0ppr6Asx bM4wLA==
+; resign=20460416024207
+106r.subtree2. 86400 IN A 192.0.2.1
+106r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . kIpw+6J1f7ByzuP9ynrP4bmQTZaXCF5CjRgDLWoIcU+mnqidsWwjZRHb 1q8OtXcUUEfwTNc6mqvUnWHXQHARTIjZ/xtQeAwfpq8ZGjmplXykmlDX Fl3p4cleG3QM+uhHnZRncbVSEXnOA8H9PFHpDSi9bBVLmqEHOot0evxA 4wfUkGQLGpa2MxzAXymWO6A1RdntuL+gBbRYgGlR0RnZycMMLtRNv+ou QhFEuPw/apF+fqmV82dX+XL8kEWPflDhOBbZqMO53sKFj5MG+gXBiPid G5VFgyFqsc4atV/PMk5RvQ+jRE8PgC2lWmdmnOL9D/RT0O4FjrXbq+4/ LEuBWg==
+; resign=20460416024207
+106r.subtree2. 86400 IN NSEC 107r.subtree2. A RRSIG NSEC
+106r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . OnRo2W1aBYVqzLQsgUF2zisHiaGnlbp1DIC3bcReDq3hKe1EqPtqffho 3UcvnzVOIp31qTjr1ntoWhNt8mOJMDzn2/UUSPQkAj8Laj1lOtSnLzm/ b8c1eFb45LTsZHic4DZoEwlhtwV3EmwKJWXMkDQZdV5x+g2RGGZ2W30t tCZllImuJbHLyCB7Mwy0ipGrVQ9iO2uCITURICTiDGKwyIox0Dr/0la6 7ZtknDiqG27PC4me5AASkGj3DaLo8ZmlBudYDG4sh/B+tryvdrhizgcK XoIrLqNjB18d9+CgKKVmRLZr6yY9aw7XSlP8euPJmQZv20CyCxhG5S+e dpCdAw==
+; resign=20460416024207
+107r.subtree2. 86400 IN A 192.0.2.1
+107r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . UyerZwNc/ZaXNSvYbxxB4CpWkGVntXXrSwtyqIeBY7LUSW1738rmg1Bj V66avt0M2HrlhDJioLvHCjI0xwKxaoLEzDcC3g6sqvvDW/42KKzMVAwy 3ARu0Fm4HNlbjuaqsC1h0WqvIjJBMHc+pK5etjSRJ1WqAq4YK7fh+DE+ Bb5NMXyqWTFe0aW2nia8v2oZQ5QlRICXBQ8pvvyiOUmiv+CuNHYOTJ5N kcvekf05R6QVjTAR7cIUn3/87V8psWcHuuV+qgTJ3eaQ1EWvuO+B6rOH eYLsvHfCi0EoE2+uNtloBTL1H8URJ8E5+XMMSoGEXFdq9A4M0JvhMfcZ EuCshw==
+; resign=20460416024207
+107r.subtree2. 86400 IN NSEC 108r.subtree2. A RRSIG NSEC
+107r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . B0lyCGkGFKCwmYXdbTUyanhQP1qlQltuiF8fcMyPVtlUcGdML69XWZ5s PqBiuEZ13avpCL8HTQckuTcR274hxGBsP0vcMGIwHJ8O5BqhN1Rp+0SQ aC+MFTsH4Q3DenHv5hkaS3FmdbEN0hQU3PSTvjTc6X1HSz311Qcc0EVc +dcnxa0F6nCwpuNU/cuVQ1Vo7iA/4iXiGDFnek4udqGAbxK3MuAYNqe4 YtQlnA2hOTrJ7nDe+n2Id1jPcRf0SRT08YM2hUrkMjiFi+eW3kD3jSIR 6O/Rmz8QpruQBsf3xPfv5zFeam6el6rca12lcSoFFWXq0WakDF3Lkqgr LF9WSg==
+; resign=20460416024207
+108r.subtree2. 86400 IN A 192.0.2.1
+108r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Odwq4YxK4F2S2jUo8vMOFVoHOCsC2CdHRhdR2Z6WiGpk3CY4qD4uIAzy JW6vpL6fKgHavZHfg/YA1vyxvJ96lMx4RiHkoQhoeugyQ4nllh8Hrp4S IJEyjNq0OqtO9QjLBSMHvrEIwVVfN/sQHainyoLquY7bMQdJvm99fN5l W+pmxMlLVG0n6M2UA/o006q7AXorgUsVMot5lyZ6TCq/YFZyAkIYZdJC zaVS+WYcUOMRQqfOmWhameS4VjOSfBjPjdO7tIgZ/0N3YsSm2mwaDFYD rua6BIoriiXUurzPZIfaI2eo7JGPB+NM3cOZDDf9NIFY8xt5SDBUz5Mz ye/veg==
+; resign=20460416024207
+108r.subtree2. 86400 IN NSEC 109r.subtree2. A RRSIG NSEC
+108r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . mHx6mvjFhd/o6RvTuRmobVp6p8PC21Byq/Bah8RJnZ89E3uzgnw75PK1 Kv3UfGw33xK53ujjq2A3R5ik6ozJQTIF7CRQ3g8va3yKrCttyff+dckT qBtXpaDkZlm1JkgH/H1AQ6z+4l9GlLOIcrbfwv6ypAgxRME3lcOpHM/o xyIuIdHh1GntYzeyNWhsB7SOzpqAePNh0RVLyPslPGhm7BFGTv2MJbBp BayfaWNCgn6VISbj/9K33GCZMbbh0Usj7K3HIKHoVtyoNP/izDnNCXDJ 8cNXN1SrRl/9jIOw2Z7mIt0dzxvC4Ts3SNQBdgHd4JuZV+aasHt49+MS 0JdlTw==
+; resign=20460416024207
+109r.subtree2. 86400 IN A 192.0.2.1
+109r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . eI2rg6VV++ck7Ei4g/K4XH7CEKliDx4+a9xyYPDHpGZJ1FhKjI5wcJNf li4IQXP84I15EKHSyiA4CVn0oZ6GTGuJtEZWkOXndPzVTmRW0vyk1tm0 oVaYcBNfVvYd45qLYMJLTwWD0cooq/qHoFTofqKsqgW8Jxe+ziZnhqDH otRi/B6OZMmqG9ZPkAKWmC6eHyBSzHzBRZ4U5fSExkdzeqcMA9+sNkNO c1koeZKUFpbzIFNyFu0erZWaZuxgBlpkyCX5TvCNu5gxKHOMy9GsKymJ OCpg73ltfjAh057odKJd+5cZBt2sqgHTipPdK8OySn4l4H4ZiWt69SmG uoVlZw==
+; resign=20460416024207
+109r.subtree2. 86400 IN NSEC 10r.subtree2. A RRSIG NSEC
+109r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Y3Dz809IO18mcCEk73sQJdCJteOpR+bH77aRQfSD9pXz6xwCmlcdnqe3 zvLJeBdRrN+wbn8TKleUIoPLQZcX+/K8eVrcrHtn+Myit3ojby3WBkqK GwMEy95fxFA+yB8EWqsVPyEFgcYLiawf5Y+d4CRp1YBF5C1iA2SYDEfT lzDQ24IeI2hKsUJSxBGzhzn334ghrwySQ/8XMqVBa0Az4VCcJL9Or/ZN a7+lw9v4afZtbMlaYNQ8V65u2oLaRXPfiY4gC8j0MiUxgdpmbFmB6x9P URY/jLmhclShe2VzRiHyir2Whcf2lRjs/o8Sp2HOqCC2K3XeG4B/6+X9 oTAYYQ==
+; resign=20460416024207
+10r.subtree2. 86400 IN A 192.0.2.1
+10r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . iAfz6tNv3K8iEbFfVH2M+Oj+tWLA0JK/yBWB4mERkTZaJW4Z5I5vBCYo 1TW5wj9b7QcDvMYGtgHwQ4UVZ2QZB4liQnazhqyV7OYr48yif5q6INFy NP6l9ZVh1axfw8dUmorOA9cEZQgI7PJkRckspp4uLg6NmQaaY9Z5NvvQ cRW+2zFITLKrZbtwHGYqHIpB+kdakBvPXemZfWBrMQ3VcOO//cXX/O3Z B4w1AsX3odnHQbLMGjs3tJc/cs5ClFoZxtOS9rNPJHvMs5YFyZz8O2cF jfIQwZcmIA+iuEkNP3N4zLJkzqRBnHXSWmSAIagvCrdfK7c0MBZa4jpr kVZ+9g==
+; resign=20460416024207
+10r.subtree2. 86400 IN NSEC 110r.subtree2. A RRSIG NSEC
+10r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . QEFhA6SbI156Bv/lxec5Og9S7gwCeTKzlToFV7UThfHykz3FA6GjemA6 3tsgTi0OzEWtEzK03a0ATPiwuleqcO4iY1m5jwh0gReKT0iDiCdVEMHL WQzL5eKXOu69G7qPxust4p51PlDqH51HhqTHWSiBIoIn5Keus7xdFxMQ IwGiyBIrAyIUZtO48FvZJLI3hNn3ChZJjVRZUmiK28Z1vkn3vYPbPalg VmMWgb+vGiHJPj/RuAfeMZ00keids2ICoV5YgYokzyO3hhr9kfF/sYQj Osnp9b3B4EC3Qm9bzTzt9CBcIAuvqQUb1+vrGssNDuAtVX68WBH/iL6C dPUpMg==
+; resign=20460416024207
+110r.subtree2. 86400 IN A 192.0.2.1
+110r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Ou9f5KbvjA77eB+iAQ3OPRHwcUQrNfmR+H0RF6zInwO6fQbSP9q2jWMU 0l8Zt7GZN3rgoUpchhZBBbgGckw5qpLa+IiRBGphxeXmfeLOFMeUOTy+ Ge2yRz6Z+LhTWKUVk/vgEBxklx/OEmsM7/y+Bkiyt74+s17KLM70uKb7 AA/URH5lYCS638z7AZgAbxqblAlWqqz0WH4IB2yINUZxG3C9tZS+xByN Rc0+jL1owXuJkrNMjONcMRrPAfjTKYlZFIFoGs0BwahwTRNWlPSw/HsN X8FCtpkvL1w+3geku7eMUwokfHvJvvKBFE7c4WkL8dCxaBCbHXYDquNy AWrVSA==
+; resign=20460416024207
+110r.subtree2. 86400 IN NSEC 111r.subtree2. A RRSIG NSEC
+110r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . wtaj215QzpzCt3LTtSZaXxUo8wJmWo8tcjhsB5/f6VkZnxGJDZnqCAbt r4xsIMT/RUfwMX28v5qNonI2QHNoBmgOpsdiV6ZWuwpgLYrBpRkOpLDM XO3XH/5kdbQJXaRHKBRdHoHo7J1suISafFwxBgm6I+cTEIeJA5aZ6JOq r06Jb8GcqzW0MgqxRVuHcgv1n4/ZqCmJlJW9ZzCoC96lbXCmWpAs0zFz UM0IYUdyl0w/VqRIHetQlB/hf7tof4deq/rPyatxcYWPkiYEK6qmDEzA hHRWB4oFYegcQOYYuhj/gWGN1bF9UEVsPSQhHrFJpsMSQkhxd6lV/t5J oXBFNQ==
+; resign=20460416024207
+111r.subtree2. 86400 IN A 192.0.2.1
+111r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Kvj8eksZMrSLThU8yas0K/Ep+k0LEZygkg9Nw/cvTpK3gKlDV0wXGtMM xEa6y+VnVmELbZg5205/haxo+diQ1+NDpNYD6GY/zgBQkIUT3MeHGdMG L4WHwZhqg6vHVz6XtQvNOkwq5IIvwZkOTnMmUwx1H3kZOO7HyazxmkY4 0ak9ggXRDBTvydarg27CX1UvAh3AI67/Jsy3LchaD0TUPtKIEK66MkkK ja8HXxAY2qiI4pc97ZvZOOjAh2Kj29AS58ben+pdY6B7d2Ea+04jeyCQ SbFP1YQGGzpI2/m39y+pcBJQIDa9aTtcL9/W7sn+pa8NTettHcpGfGzT Hww0Fw==
+; resign=20460416024207
+111r.subtree2. 86400 IN NSEC 112r.subtree2. A RRSIG NSEC
+111r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . w9XbWXOIjG9K+uiCTpq04S5a0ZXPK5eAQ9wZ9HWhBlNwLD9k0P+4Uami R3NoHd/ns/SqCdhQpbrR1SYnzhT/hezRzC/ahtipvsc20OCoqn5Cpmcx Kmh30VW6mxUVtV9KNumoM80FQq3jIu/q3r9I8oDG23TAXOPDc9K97Qxf 0Kt2RQgh0wYYCXfL/rlv9zUn/H73Ldj4N0gioOFwvU0SXbJVUfPG8UiO HV+BtY382maAOGMR9gRLHVX0TIKD07QIKcnkUugLRhLlgyJ1Knzetrbk O119Ti2FBOqVhvjEcm8v28bvo9XKuBTR2Guk9AzsXJQGC0juE6JJqiH2 XtXlLg==
+; resign=20460416024207
+112r.subtree2. 86400 IN A 192.0.2.1
+112r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FvJNCOO1H1K0KHlXwdwyaFSQNPdUG0D76yZkyQMhOm7wxjC84dq6X5yi g1vNXp/vvovpRgLeJPuQqg+7O2MekQUTwNQSbzehtOnY2JoPXbGmllio +hqqk2gpqcj7bnIZpN9PkjcqM/EOL+TpmizPi1LRcVl9EHfsfQdIRUBj cMdfveDjOuyV8iWtNLwPUG0bP/gqoOPwkEJIoas7yMbQTiSjAZtV701Y 0gAoM6Kc9tINYlmydqvallSow3K9DE0otRVwaR0IFF0o7uSjWo76sYsf L6UyqK1/WDMkh6gS//IT4ZvwfcXbKi/WrFS4/AurH3XyTY2D1rvxZi/B K2UbGw==
+; resign=20460416024207
+112r.subtree2. 86400 IN NSEC 113r.subtree2. A RRSIG NSEC
+112r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . UDQGBNS8u+0VJLat16g21VS795ucpkMD/GucIPErSyF5zTiSke8jThPA TllPS+Ynx6hcljlUnye1ARb5pqcp1gV9DN2L6AFgQfSJ/gCtUe8Aanwd ajuQtENFgMPy94nkjEYteLvUJNP0x9mmnt0Y+Keyaehwz7ppI+1eJUfs qZvZMD+i/o2lKEb4KRo52ju8MGcMXOWmgcgDqwPf5EOH3tG89fVOE90J gMS+CQbB0f97fDGWea7lAou+V9HmIqxtQkUHguxwcxYot2rx3GKw+ACr dNY4hm04vseoULJm8MVoy4cEh19DGWmxOgCMW59B8EQd1+h81FDfszbx k2NdqQ==
+; resign=20460416024207
+113r.subtree2. 86400 IN A 192.0.2.1
+113r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . lMLx5WcSLY887gnXvV7zwS5GzmPas9qF7q6GI+9KOdJFcQnbRsmMZlXP 24p6Fz3qcXpH6aMKg7y5HuGxwcWfIMY5WBbdl7rJ8r4nu7UzqOXVQDIC z9Q0EVL7ZYUynzUCGlg1Twb+IUbNcCktySwbIXyt60yX87D0JX0xa0UG P4vlUz602aymQi2J2OCt9jDMjGoopvdy6D2dpr2rygeajpgPrn2XKbqO sdG4GLEnjwSFRWVgnajRM6D7ARaVp8HNElOwdQz4x97AoqtlmrE9XB1b CV8m45n17X4xXAlS8ibPPrs63Q8WLBAXPGiq4xjAubqCkWRJOaKsud7O Ovl6fg==
+; resign=20460416024207
+113r.subtree2. 86400 IN NSEC 114r.subtree2. A RRSIG NSEC
+113r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . XSQUXBwDasTlUvwGR7qmtItAd8IN2t5PEkp5WwyoakU2UerAOAlvWew5 jajLTb4P5g6hyqqeub+undk84ZgG5hrGK8qK8rf8EhjkPaQl/svow3eh x1tM5sL+CpKnG2CgEKmHdVEjSS5sJVOTE7qUJ1HG2+HYxaMkuNdANNuQ cAuLz/y0YPZ41c1ii10cH80+K/zP8NipEz8EJvDzU+r0NNghiFJI1leX wUeUNQ90svZjZ5XujNk2Q9lvoTI0xV0gIIdpTooTC3pDmAp7JbxXLAnV /IRHHgfX5/6SDpqtQUcRcIIAsDgEut4lktzYHmarfHVHZqeuNIardgt+ f9N09w==
+; resign=20460416024207
+114r.subtree2. 86400 IN A 192.0.2.1
+114r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . kmW55IQ6ZIl8D0E+Jh/ANLu3YzE0MgZPy51DVXHSjQBbNRZc9pGAUjA7 5yAZyPlySl3WOZaMDmVSquqBt6TG3mNo3nyweUKGupcNU/AaAZlKfR4T aloJ5oB60sDPPoMZtyet9dnrncNmfUJSiWackRcNPbgzySDmxbc55XWu 3du14PY6EaG6cgxmebFmOneffmKH26HyyA22Bum1qogLQVUGzidYgxQB 3M2GgGty/mHWp+dZpRoqh9gijN7w2dKbdW2fJgaxzrBTyL7bBYOaUFL8 pAs5bQtNE9kP3Ks3yQrVbn89hV+AC6RUNOcG7qp/YsiAFPHRi/RH0rwv cuWInw==
+; resign=20460416024207
+114r.subtree2. 86400 IN NSEC 115r.subtree2. A RRSIG NSEC
+114r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . qYqJCfeflaJz7SH9/hax1OVxNmdD4IlPeqyj6RcZDbZcoLea1YwCILCJ yKJiQhWJA2KbF/wgVrJPSZeNNFNgtsh24Rm/errWQVaGZs/eJOQATbxG FZhVHxlx2BguyWZkLfbrFdjkI4vONi5/LDF8ooYF1hC4go0EH3+MUWmr wfKJUFHZZ4iahun+RiYvLFtg2zlQEzAInLgMzngDOaVZ46XrFitcIo6O Wy4W6Hks96RdGAdOlmbsMmCmwhf5JFPDEu3xKgVC40IuU2Qd6oQSOtks hoGmOu0tW5by7tQXRhBB9g5t6DhMUplvwXxYF7noSCotVBAm0Gt7q8S7 YZpKeg==
+; resign=20460416024207
+115r.subtree2. 86400 IN A 192.0.2.1
+115r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ozrkRqfwxLgosoEbVRsyZuuxUU4XmxY2CKPQMeqwEJmOfNxVyDmJgG4y wGTO+hRQTrwRFSem5918Up1MO4Vt3vLr+i/n5aXbl4rq2jvyQidKpQCV nXxF7BWOhyHO/v8ns/5hr57ciDbz5kPjfM/JI1W03XnhdHd7opEEiu6J zlb9i653+dod9pd3gvuy9gzlhVh05uSOgpVJxjIyvRrOW/DqYg1iOsHR Ew+1q7bZlFGDaUL/3bmFxP6G2C7WxSuB4a8Wmu/KC44yb1LwFe/bhARS J9NnKpTX3SBP5A0pK4e957YqtjXRCMA5gXjmQuadgzIx5wFF7WRm+Ga/ HtojnQ==
+; resign=20460416024207
+115r.subtree2. 86400 IN NSEC 116r.subtree2. A RRSIG NSEC
+115r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . MvMYm8VkU6wGeUYsGTXft4vmyuz7KK/0cQcw8il3uobixnhEwtwdr+6y 5BGDV6MLNaBKWptnfUn7s5gN1t75H+tlxOrQSn34i6LacDaWZQEdHHxb A7089FsPBL3SgWeKf1Dn80YllFlpdH4xWDI9dHQgO3CuUi2lEvZ61NjT 9J7pBZvqQbb8yTzxUwXgSKRfmgjYEIRsdk8Pg8AwVmeNxmbH1oQSo2RL gpTpNKigdnA569l+2D1THUSZsMxnIk2G5IBFFDoPzpnp8UOfPl6O4j/g nExRVrGcSsZRLTwHavYrmsbMGPKFYlub0VbM/jfPjXe36fW4sMbeoyvQ eUu7uA==
+; resign=20460416024207
+117r.subtree2. 86400 IN A 192.0.2.1
+117r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FrC5ZQG8KQIopup7Ndzgh1LJCVYIUutqsK6+EeQDTBPZWEJYksRfjUMy iuaI3AzGKQEE+gBMwqXbPSYFDqj01ac6IXq3juiQXGpi5iGTgYTiict0 ggAt7UbKswuguW9w5WxL/+tHoqxtoVzojwT5L+NjgPtHKxdWjYcIoZDy Nm2YsJW+KNcEA2smFetqwdWc1bvlioE+FXAZInPrJ7dI8/5aKWiCCVqu jpOGiaTlAHGyl1Kn6psrsrptyaZbr4CseqDh3opLuTrLClA624lfbcr1 gnKvMDFFpkEIRtHDRt9h4/wJlcS8skVEUzrZna6K61U/H3ItL8rFPtnL 18L2aw==
+; resign=20460416024207
+117r.subtree2. 86400 IN NSEC 118r.subtree2. A RRSIG NSEC
+117r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . X4NPBF0M2VXoAw7t5OeWCIKig/KITQdBW6BxgFsidlrNacGLRYSXOlmT uFfslTO6h192MVUCjP7Nw5qXHII8vQ/joZUSO8diArhNI4rWZh5gO7De l9qpuy+Su2GzcCJ6/GltrpZDFSJo0PlCEcIiBQqZ9Tys6nHwwc7GYaGj l/biIrFJJDCv5UzYTob5Rb2zbHw3mHq0qh2FvmiYMZHo+vfCT48GRGjk Am5j8tQERyBGJ3HPOuXTif4wnQVYSHNrkMlCAfcsHQ/7FwPSyJMNQxMu EOlM+kjhmDYpiajVpcvZZ05oqw6iTwJM69N+zzuqvgcA2gQkhhg+VyP8 az9bfw==
+; resign=20460416024207
+118r.subtree2. 86400 IN A 192.0.2.1
+118r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . hIP4D5QN9rCph/6IgxToHbNJAssjLJuMq1zUZswcxRxUTHvShbPxNRon vCJwZscL0FbvYErydUK93+qrD7yU8Gohk7h0CDbDmRzgLbiZBWm/vkHu 1rYV+4ICCwAhlMlK/KyR1yZ5gvy0NKnd3pwapJD0EGVQ9V7AxAG1IHk6 N/8lQXbRkf/WGLCA5d3+nkBhoKZV6P6WTtI4OJt+XJjzJD9V9pFp3GUf VxHV17wKueFszQRblAn8vjYJwDihQGlyTcrJerZ62zm3yHRSW0m98T6N yHvNKNKvVHOoQQYtvm27/GC17GcQKjG8eQMJ3qGfzht1OEGtTSeaFLa2 lj2h6Q==
+; resign=20460416024207
+118r.subtree2. 86400 IN NSEC 119r.subtree2. A RRSIG NSEC
+118r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ZubXMLN67Fh758fSx4K3nSLMgGsxOl6kBkJG+7aZImIXyw0W4GGSI63s VIG1DT1VvSShWiO04M7FES4J/1/OhCSANMnivntKq2nZtbEEkiBp9kXf WJ9L1cvEsD8C0ca/rYN6rjP2XUxMj1iO/8QfJSyF1iGoAofuVdlLeHoE DTFCd+MxHdslbGawtAdycxjTFF3aWDwnTbP7ID2v7wiJqySwsBYcqefd iTQh+XdrHI1bObZNIOiQB+C+wKCOLmwzhhqGuvOzGbmCq+ELaQMs1wse VEGqV7DTVDu++rMo/QZhTVsiBWy67YPP4UMtOm191i9aU7MWMIqgIt+i 2e96Mg==
+; resign=20460416024207
+119r.subtree2. 86400 IN A 192.0.2.1
+119r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . IU9wuoC0CDxaBfN1HGIAZh3pC6ld8UPeHGkVrUhe+PJbPw2ELLvYue+1 kw5ObQ1/sijjWZoD/N0xOt621jCSZfRYNDXutYY1QxffTAYwR2K4/8gl m2qFiq+GHyLTFhFej7m2ZW2wXSjmLtcDi/AEOg0ED3llb/IOzgXjn5ja eMhb3HA9likWIv6aK1lOq+7dwDApJNRmo+7haRLeBecV5HOP/0Y2EGrn POHfogNJyVPTGazoinlEmeOSRQ70u6GD1foOk7j3P21RjT2MM4G6NCYu JKwI3YjWhtnJt1W07bATknoYoBGgT7Q281waUZ30nDuM4nLaOCG/Ry7a BUbrqA==
+; resign=20460416024207
+119r.subtree2. 86400 IN NSEC 11r.subtree2. A RRSIG NSEC
+119r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . rcdQ1ziRoRpysd8OMNH0Fn4nmDBUcPHSpe5gltLYYZblPRFU7oQrsvmi OWhl4OrIiyXvzkIWmUwt4V+THLI1UJfoAQQB7L3MK6m+81jTgLQYXK/E tgLaZynLBZN12M+24PV4PKrNqNH5qfEXolxQBcbNsYrOwdapEUalg1Nu Ge0MECjpNbtVYAwZNAtuzR+MIVmDASohxKX0aL2IYERvf3oi/m+bUv8Z VImvX6QdTw2ROFiuh5Q/r13ZbrdYG6gclt/xv+OzErbvnZH9m4dpFjXk H6/3A24Z04GBMaS32y1u7TO6Vdr3OsMiMweEXXKG1WFq7a4re663DhE4 Z/VGlw==
+; resign=20460416024207
+11r.subtree2. 86400 IN A 192.0.2.1
+11r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . eFgY0mGVLLbLvDn9QvJ6Nnxp+zL1sggZhbFlIisWv75nY/5YI3TZGq4O gRwD/1TpUr1/VI99rUuKYTb30C/pFmOo79tUxuvREp5NlWzuv7sE6tWe rxmtIpSH1vQMbZkP28it4C1JW3vC4MrqhoIQnHeIDkutet9rCh/1xoa8 22c7Uhj2MsuAesVhQRJxRj/fi8moNVOS8f0d5dgqnJ2MikshkyoziJgo udYxlnQMurbqFYi4isFGujwZnOdgQNJ/ccf81JRCRKLoCGj3uTgCNI8Z MxcweQsWD/mwk83VmiyQpT2PCSwKHfSoppNi9cuRC868OfKOTOc3DllE uHHShw==
+; resign=20460416024207
+11r.subtree2. 86400 IN NSEC 120r.subtree2. A RRSIG NSEC
+11r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . OaQS/m+fnOUyNf7JUfUFaGBQJ30+qX+g/jZc5mN/Zm5RSmyobvpZepbw dWttsrQnaEA4glDvgde+au1hf5I4zXOeav+sFZa3JE6JqEUNpkrhTjEo bvYoS2myywt6987D3IZpmDysdCWs/kQZyS4hR+TG5zVagFa7ojXUuRtz 2y1Z925/7EPLWi3W5gKwlyQLRoA3M/OaGOFBDOEY/qlGT15HaVo/gB8X K4dvzpsIWZfgS517U2eHQWEoPs7+xnU1ifii2HsEc5XuAjdodWT5gCuR 4l2iS9JzKt9snfrps0oSI3feDLDrXpJywFZQWMwu6cHh5YrcmnuNc2KN dkvtKQ==
+; resign=20460416024207
+120r.subtree2. 86400 IN A 192.0.2.1
+120r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . sh22Z4R/Ui5KsGXDxWZmwaxBarP5topizqVI68KtI0WqWu/jerkmPiI/ SQ9AKpoERv/sALeoS7uO4eJBWAW7zgPh9XiuD2NtDG3rKW2zWcw2XKvu GHWduKuy/aB6G6eUUFwXsY62sXQTV5rLHhEQ9U39x9+M4FY10RLjMGkm qIKJXyc3IV4T4GsO9BDtnK5nfd0llyOYrHyV2prGrJy2e20u00XK7jMD KxAt4ET1vlcdgvCmNXLkuRVJgA3oIAHj2l0R+H4Z46NZFsAEtNS6eejy i4SAAEXHeX9p4ZQYVwAADMOrJI9xl/iYy+Arsn/ZGsfPa9Y5g2hgQ6Ic z4DyGw==
+; resign=20460416024207
+120r.subtree2. 86400 IN NSEC 121r.subtree2. A RRSIG NSEC
+120r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . HfhZ5uCo72oXqj4Gr6jsTLPR9ZnXoYvLwmDPCBb5+ILw1jWzhaJdSPvg 2Q+3C9DGvQhj1UykKzjYuoLU0Oglfn22RB9zcJ3SkuBRORO/PDzociwu TbSFzdMYQW/F7bBaImHQ/hBrZ+g515pYUF048KgO1SySr0Gcu/d3JXnU A7wTdOi8b7LqSHjHBBLxjKfR9QCE/Bqk5XHO89AiS2AsALGSBB4JPNfc nZxtDzX7KAqNf5ttPdrp4j7Mo752nj56wf/q4LWmOZOE4MMDHdLaOFiT jo/Syo192MH3jiTp7gd1w//MXwd6UQ5I/4pQ8X0Lmt9fxyqyN8Vrue5d jBIhFg==
+; resign=20460416024207
+116r.subtree2. 86400 IN A 192.0.2.1
+116r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . O0oUTgppI/Cs1Yy28L0iThbZ+kKNbD3k5m8Y+VFb76tJLMAGe8zxMgCE Qta2kIAGWfTX3GW9/POApn7R2N1JYl19TGWGHw8YU1HJnn25VwRs9kNf B6rujBxFY8erychMRuxX55I3KR6JGyKlYdXNKbECaPS2nG+ctIa1oGfD HxYbivqoTsJIUnB0LapVJYfdR30/UOABIq+S2VSncdnXCUzMdf6zBwOM ohXLwZtuBtQg+ZResG0ELYu5VLFlCzJ/z7D8KlV0S1wRkyvR8t5+lEs2 LD2OKlC+ap6n1aK3AhIAmNeVXTooCR+9rG7XqJ05kuo3j3S/Z7G32oi4 tLNJOA==
+; resign=20460416024207
+116r.subtree2. 86400 IN NSEC 117r.subtree2. A RRSIG NSEC
+116r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . CbWdqSUtXErQ00EU6Xr13vgGvgD5iZBsj2cwNYuPfMmsCkNMJJAgVMDg cjtHMD0qbDy+ETew1BRFjHc7SOFSuaHT8oq0rGkHxfXu9vRhZUfD//Ea qKCUDjoUPpPWeLoo1z6Dr/iJs5ZZxs2vfo5Bog8nxsPUdzAFfvU5jS9S PylFAYVpjpBhNfXvMVcPLnIhFSskuvc2O29HuI9QPCkrGiTx0S5h7jP/ O9noYtKNT7NOY6jf0FRSjIsqyraoMa+H4/kbPZR/bDpDG3/XdIBEgagp a8ezUQ9PYsS/HoB5+lZBZz+UROezw9eZ+OmMjBAUb1kWjEkvPcHXnVRF 8TzpfA==
+; resign=20460416024207
+122r.subtree2. 86400 IN A 192.0.2.1
+122r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . NB5NXBp0OPis8JwfJq6jZL8A5c4OrObjj5UhXHmfu3QnRNG77B8FWwe8 v8pm9bRUgpbEGeQNLf6CFx5LbRNSQBoLl32Sp4ydaNtVNikU8Ob/B7ek rvX4NTl5kh/rEbbX1BINXmKW7WKAE4Qjbl9ydjrJ1FmsVZHnnnpSG+Tq 40ABYF9hKp4uH2ngc9wAuAFMXCpwODcm3ZvDgMGxGRESEbZp0ydJnoY+ SpRNnlY25oKkBDP4KNOU8Z5mRlEtjch0l9tDgUXsuB/OTRGf2wGwGbSJ iC22Mafk1BPRih8Dtybp1wwHdLEf3Uh6G9maHspDGHL0SoCoC20pDH0p 4VPfXw==
+; resign=20460416024207
+122r.subtree2. 86400 IN NSEC 123r.subtree2. A RRSIG NSEC
+122r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Q+RYhLVqKtiZG2gfNA5JJWs6UQHRD67thOVMP8kfXptrzCJ3zLDo4Ffw IFlkPM6BtBUI51fqnEL2Qjb5nXA1bX2p6IWOrINpPkSrhLXB4p66rNyw HyZXum6tKt6/4NMpyRPx4V0sU/2Z098s28bHo8AA7V4goC0m3NUr+JUn P47LYmK/cQ8xO0QFSTlfWOE2TC4kCY5vQju+OdfgRXPGFp2IMNUZs4jG 3snRf+xDjEGz4D2LyEHBu6YfEaaNvZGIR19uwGe8ATcINKD6hhHDZj4Q pIYzkvi3OocsZcu+dKhRE0Uq48S4mwq//YAfIBRRoiEXeYhqG6/KSIba DFR7+w==
+; resign=20460416024207
+123r.subtree2. 86400 IN A 192.0.2.1
+123r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . GndMmZXvK5RaihISXg8hCnuN+mkkP+YBlvZYTkB1L75ThSdhOzry+DcW Q2YiB5y2vfQceJ/7SiCCpYyOdhtlmm4kBBzEZNHkq5SHzFydYJ+RxU84 rbG6Zoa+QHNiL3W2EqsvtRdZSYmO6I3xTtpmfn0zGiWsXRpgRv+u+6Dr yhQ16FUHTKAYrh2/PReH/Mf13QnIPPMaguJ4HGM3YfOikrDPIEwx5Lmm JgAsHpSNGvgLgLrc8rew9C1DymzsXY7aa8rAMXXBOtvp5bqPOblxSQ9d 3JUXDRZPQYr0DXXNg9j5+FLX/JcPoCiFLr7OKVO/XxgIRZMYPI9pbZbX ZXdPog==
+; resign=20460416024207
+123r.subtree2. 86400 IN NSEC 124r.subtree2. A RRSIG NSEC
+123r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ixCP9RE3d7Ha9aOp5SYR4JZGtUe5cm9w1NWDZWhjXuvMLFnbKzICYgbK +eEAK3HFzpcNraSUUQnZ9zrUa5tZJedqRE53JCht05gDWqOwV33qbg5q Owp9xfXhJRG7bQxxwHV8AwMBDsPe6+Ann8jDUzXKlGZUEMTRdnemd9bI JavE4R22mmUZalElWTUtOki9VdLlg+8WM+38/rE4IG+q4LP/rv8+8lrR AdUTPwHH09e4sRe24zowxIQUmdOkSMP+pXH6H6huIXwnQHjMInO557JQ sxu1jLgJa9sngEpV66d8LJ4R4HVI8WpXNoCr+YX6vf6Uru570idlTnNS QkUzkQ==
+; resign=20460416024207
+124r.subtree2. 86400 IN A 192.0.2.1
+124r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . XolYJ3fJxqmokb/kRF8S8moO3lo7bV8qA24kqaB/B2jXGlvuPYAhIYNJ sifNdJIW1Vet9LmRnb4H3LmojrtiWT4NkFfSoiZVISpCQw0yUXt/Etm7 7zS7HyFp1Hn8Oedhr1wQOeqHl0sRKGoTiZXXHcR3+b9LaDyivVt1T+On JCP7OV3uctr/FXqB8LFNsCNLyNTk99fz26qQTgGGXu2EiYrApUfoG2pu ERE/sMDZO6pd4Y8I58mu7wVihEFiSqQGa3uS+VJwnCgQWArvcAF6vcbv 7T4EIhFZ7b/8JQhRw/R6UlDP5JxQhhZezTw/ERMUMJv8KhL02VlsCFGr bvTDFQ==
+; resign=20460416024207
+124r.subtree2. 86400 IN NSEC 125r.subtree2. A RRSIG NSEC
+124r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . tO74Eo4FdyD/rOtjVjrfVxEe85sHbjlA0sKbvD8iLBs4J5lN61JtnZcy LR8K+/QXx8mTlVdIPT+AYzDUhzhdCtZp+4gNH7sM6WhfglOK1IHr4Hqn Bij6d4HoDvzqpgcczekMiPHl1CCztvzzdt/GujwtHOVmyTTQJTAL0lta vxEbQ5tsVkHjM8zVioEm8tH6H2CSZJSGtBCyHVhp40Bzi+D2hwAtwNGk Iql31PYVaeJj7KXM2oKYuSQHFmkvshwUk3EYstIVEc0ykBKHc922T9Qu I7a6//m3u+Y4k3VyoKlYNSVfNiih1V6pBT4VqUHpa0EYfmsJVR29iByd KuwJ8g==
+; resign=20460416024207
+subtree1. 86400 IN A 192.0.2.1
+subtree1. 86400 IN RRSIG A 8 1 86400 20460416024207 20180815062314 48409 . SPHvBQOqg5nWHvEkJvt5jcV3/glfVA/b6wI2gkPNgcXkoMAzBfzCa95a fG3PCJS/9sAQAgr6W7k5FiQq/PaCt1jMZBS3z+2zWsNdGOAGdKz//Sdy y8YHxI20Uroqntvm0+Cu1p4HMRZd7QyBOxJJKA82mCLkwmRrSmwP/tVf qFE8HU+kkloSbidPwmp8nmYXYjByANHQCRBY6xkV6sMK71X+/eYzBlFT uxPS4aLHVoOTS5cwdxI7LXHxlW22J7Oe98vom2Bf6kWHd1MGLYvdp1fP D3bRMU5HCdktc+4Tl+nRo/RivUhYdcQQXOZWEx1CY4fCWssR683IlcOM nLwV+g==
+; resign=20460416024207
+subtree1. 86400 IN TXT "txt exists"
+subtree1. 86400 IN RRSIG TXT 8 1 86400 20460416024207 20180815062314 48409 . Eq+g8WC5BonimGjapGkBlLxjpXeRI20dDx6l3e3iyL5WEzZF2jP5ERps IFD9q4h4SPizF8iu/5Rwkfvm4IxJ5aT+8Mrarsk0c1HdtNJOo0AHT2k2 KllWe8T7e4QD+nZ0nx6Qwml+AaPj7PdcAKtEKLXCJxnubQrPjLfn/cYf +lTep5kgOUfEcHK/8kxor5Z6OfOCnE3jBrfsiDXPHnoO6JBbonNTnRft VWRTnyV+kSnq3UmwU6diuhiPJpezZJhYcn3ycwTgr+1WY5na/hOYOBTD gDrf/slbSnGyzkEoedln14DROa+EsNUyNKMfkXzBgx52w4rop2hR9UOm 3Nfuiw==
+; resign=20460416024207
+subtree1. 86400 IN NSEC b.subtree1. A TXT RRSIG NSEC
+subtree1. 86400 IN RRSIG NSEC 8 1 86400 20460416024207 20180815062314 48409 . KONcjoRpLJQHvahE4t0Q5UlkxkQv3DT62MbAbR8xIDigv9x7K8LqrpxT 3vC6aoHLn2ERJAQAG6sWj2vizmHdo0ND5flI1GbFAJQAzELlxHnbl7aS siQRIdwxpAnkCV48jjhcPkNpOWDHmUl8U+OVChTOWaRgChTMsDxWZvOC zbO4xzvHECjfw6iZGESSCLnQz7/FVQEG9B78nigXkx3QutFlvHKjAr7G tbse6i6CfQQWD3HUxlXOpYR5ZyUNXNwEQQXvKvv8o3B9b1dXhVgNpP3s Qulk3xxuKcbeZlvfOr2vawfY97VQ43mJZ8DVs/IXYDj1xQIDvUaZ1eFm mAi9Pg==
+; resign=20460416024207
+b.subtree1. 86400 IN A 192.0.2.2
+b.subtree1. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . iZZnfKUQIy6LbOBnjzbnKgpbAuolfWnhyiVKRDC+u6iNMsX/g/YQ6eDp sfaORTwV9yvVwYAXfHk1T+cFcguF/uM+jsVeXKWJTiMb8UDpNGzM0h4L 3ZAZv7v5FyMf/JNpg87JwyWwO3HU0BHfiCS5S5X6yCdEdbKyXrUcUgi3 X2DA6jm2GhPFsycNQndc6uwEgTZOKE7cxfVd/rlYhC1gYMafyu6g+NZY WmFQ5IHGFSwGJiweVQoIsQfB410WH4OpqtQUhwTbnh4qCnHqwnUZDaYA bjL3jJbOlieakQ6XW6h8ehr2+on7fozcdAuUee8OKutiDn4eBhZiRC5o aIdkFw==
+; resign=20460416024207
+b.subtree1. 86400 IN TXT "txt exists"
+b.subtree1. 86400 IN RRSIG TXT 8 2 86400 20460416024207 20180815062314 48409 . XdoE/QvnjQ8FEwSKG9CuqQ2TdxGdcMjWLGOfIgOoHOEPoGZD+TAfITw6 NYICtiujV4/9XRTQ8h63nVwhUjVdsGO5D8JLPqca/7fOdLyQ42hNnAmf t2KawvzqC1Y9Z7yMrcW+QC4rT1GEEkQMu59F35tJAsWODMZAZXDL28z/ HVXcxTDU+bcP95OYEGhnknFqYjzdk11zWT3PaA2RPt0GlDh2WATCtEc7 nr2ZhsbYyyzlY1glQhXPpjnpBcZXFP01wMhKcNH/vcXZF0AIi6N6nIXJ TO6u/fsG2RflsdpiBym98ASuZXA1nGZzMQ6nO4IuWafaLRUQ1feBAJLH lst32w==
+; resign=20460416024207
+b.subtree1. 86400 IN NSEC a.b.subtree1. A TXT RRSIG NSEC
+b.subtree1. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . axjtB8r8jja6iKQfdd4Qt6aaobdM8kpXLYAeJg+R8BXv7D+2Q5ZeCikc gaYaomzhSTqA7cdyv3ov0W6T8yZZ3rkPLkN6rwVNHf7Lu/cbF7q8UuaP O7pyXJDxp953/T+i+hJ6Lq7HV+Be6K0Vgq0+w0xe5BoTNVcBRQFu3QN1 Nu2m8ZsVhouM0aD9QDs/PqrCPktLL57xLVMoU3SaVhbQdV8VYZy+t646 zkDMQU7ZgvnFxFA+qyvVM2n8TRYImr4xzrIcOncz/td+HCni/EbCS2by KpE/xHQWthuSbiiUMXC6Go0yN5WKvOO3Ef4c6Jejw04XCg7XxlMmIDTa /KcznQ==
+; resign=20460416024207
+126r.subtree2. 86400 IN A 192.0.2.1
+126r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Y+oDiMv6emPFsvhyVOFd5w5OdHxWAcR7b8P6fHZEKWrgLspEBlkJJbCT Jg/0D0JgM2tSVw2G8qS8MdMEOrgrWukfy2H4gQn2GXd9oX+Q/SaYCxVZ AnnbX5duHLYKRUJ7aQ5S0BLUdqsQNzfjluNmAJAmrmqB/4qq3LqiOt4w rPe2NgsCDVx83d7lHEeLc9WY2iRHN6XEBVo0JuCH+n0qMItmnXAW2yRF 53tw9E3xzV7Ql8mZ8HfYkRxvs7LUnIBnWm4WTPxNFgW6sAuaovEHrCj+ S9edUSrKtFexYoj5NdYccEz2mVEnUgVkHbBGXBdplx3eiOAuH06S3+pn LAk2WQ==
+; resign=20460416024207
+126r.subtree2. 86400 IN NSEC 127r.subtree2. A RRSIG NSEC
+126r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . B4/GyQfnLIrgknDrWgMrRO++hKv8z1pFd5SovWqOXgfu3/pQ9F06vfL/ oo/w7OyQes22whJqZ5YHt7vj/ZcRQdzFyVUcIpAxCXV5vgFHhQtX4ctw XhW/HZFNeVEeJGjzVhOaSI92mACBdzMuywuqmFtRW6Flf7YyUZMchZOv KtR+SlKtXXjxtc4bIABPO7pf0jFBup42X6pv8KORhDSEq1gptuX7MrCE ZAT/6n2yk+2ilK+Gz5dKgxkwqKLg297jB1G3br/ja0dM5KPxXQxH6joH GmfgRn0YKOzKV97PklDjO36+eRSOXw+voQmSnAS0eOXCb3zvqevYdAg6 bXv+ug==
+; resign=20460416024207
+127r.subtree2. 86400 IN A 192.0.2.1
+127r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bZQ3ozEF0PcebMQWveJURSLH/8S8Abntn84pBAuG1kCzElCGrNPXQg+m l5Oh0dM0cMoZUYOgpECLR3mKE0MOvZfgGEgRFHHJEb4M0PipuLn1GfWD jGaAKQ3pMAOptg85aRleMgcHKWaAmTxV2C9TftEpul5o1T37Pumybe8t F+LS+5KlSBxOmNpQzXDz6Ladd8FIzqeUpA/ARQK/adt/+L3fIbuQ40M/ RGIRBrjQ4kz2YJuVqcvhNcdQitJNhXdRILNYjGKvuj4ZHFp6KXWoRTzL x6S+PYH7shrIkTqVeCziDy3LVtAaKgto59Kbw8cq0m5Yldyl+z4WQIq0 t1guyQ==
+; resign=20460416024207
+127r.subtree2. 86400 IN NSEC 128r.subtree2. A RRSIG NSEC
+127r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . uKm1r0A0BuyTRsYGjGoDDGcNld1VXSck076HxHJ7mQNusuKQZ5lfNtRE b2/FjlXukHQyXEkfsQc5BJvUjL5WnnPUSDBTnPercSCf6lkB9PPWOeJT EuOHGjCZC+wCYSsuz3JIaEhHwsA8JE3Ufj4Ld1S5FLyt+Y/smxpKg+Ca Nj2Um+sX5H6OkgXJPHnQ1s7rF+fTuYbkz/iiRU0CnDc6sfyJJjoDF2/9 ahCnNTqdxUjSK00Mg1flt3+sJCJ6tHjYdYgyANUKc65ZusPUKdGPJM17 +oxSrzE5+biVZllfYRnDYopeayciU5CuyUNl7Swr6x0EI9TA5t/KVD4m F/wEtg==
+; resign=20460416024207
+128r.subtree2. 86400 IN A 192.0.2.1
+128r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . b7G4uESmTYUIboJyhjzJUIGJyzfwOMgtQRdhk3+hGC6p0lE9QIAHoTta bUk5VGHvhg1FTE/RaNelXK3z2WmsaHtZEtEM6IE3j/9w2d1OCX/K6esG N0dLxynR7w8ZWTTC+5HZTgNURHD25Z0gMWBkiFv28Qwr1zGPhURUG5JA s8dZhsSpA21I3bkNaz5AJDMFxTyUTtdXG5jc9SRFX3jgPUCzsyNjf5W4 H2c+4opkhGcydcUPcsc6tbocUGzXhQU83Im/8Updz0f7GY7uzdaDZoeW Fz6AveZ4EbTmzWRXSKm/EEJqEOyy0xxKAY+CHocz5J3QZfbNjbEN27aC xhzsIg==
+; resign=20460416024207
+128r.subtree2. 86400 IN NSEC 129r.subtree2. A RRSIG NSEC
+128r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . eJikYm6Eb+bJpCxqIgiOA66w+mJNtd0MeA+oXNgl5JZVHuBLx88g6UhL 6nxC1RFY86sujHTdWnXR8KeHUFASsyYVzY/KQbEeOik7oTLcXZp75s6X /22WIxq2ahvRAXm/PCB7UEiZb6HJNhdU0vTafcUznYahO7FbE0Nw9fDD 0MPgOdRl1wtApItW1ZG6hUq/UYUKCTQHS8jJY5cidOg359mQB+Ik/L2M HKpk3j8bTxbHE2NVBIoScDQT5xqd8rsQAbBrtAVBBvIVcqgrd1fabr0s HKWT3+21ucs+DLdsFiidV48rRuGAJIrYPsteDLOgtZRchZxoUGOpHWPJ YVGs9w==
+; resign=20460416024207
+129r.subtree2. 86400 IN A 192.0.2.1
+129r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . xvPIWkuZ/zQGallRWH2I0V4qyV2cN0a/A9j/IGhnrflC58PKTsjkDu8x 6qemDbBM9Xo2nkdI3G7YZZjB+fZ9SSr5SuSMtCvmoUQOWjx36x8ZBa3S Z97oOOptOJPQLWYK957QuwgEtS1/SiRMZPrXFoMWpPIBINTcHPrXTYNg 1jgoIxPsXjinZTuO7VXPyRjlhhK0Cf27yomKku3zBkrwDqBH8FpKajD7 zq0uFztSY1MkpVgvfmT+6mxuVPiuIB39h/A7k6/sV+5G6Yw0qaL/hzER 6TYIs9cFw2C9qgLHeLcPGEnFhCwgEuk3wCYtXJtzCBqq4nXRm6OKTypP E9kBVw==
+; resign=20460416024207
+129r.subtree2. 86400 IN NSEC 12r.subtree2. A RRSIG NSEC
+129r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . g8Ym8RVSbxNVY8D4c4iNmHRgm58PPUE0JBaapvJTrAtt9Zj4ho/QYgnH iJGvNzIdEySGYD86aGvWlWgXKdsubnRCihSd88CuRDK2CXuYE2Jw3sGN SFRBkY9hOH4BZ0Bms95ZZCmjCxzI+6jMfkwuKGhI7K23vIg3oVpE/yHV 5HKVs5WJr6K1gMQOF8XrwlsJbawHYNsOOMuG5Y3NZWUUW+3L0zwxMMK2 d03f1AJpS1K6lqfw08FvhYgAhFoVVx8unB18UqEW+L8x0a716o27kACG 4fqdWR8TKhSG+/i/HVMFulBaWqGKwi1g4UnM825aEQtVtoOUnMYHOvmQ u86UcA==
+; resign=20460416024207
+12r.subtree2. 86400 IN A 192.0.2.1
+12r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . RQTtb1xIPxf3rvjpYYw0q9RcPiRPlx+uXg/1O0SNrgL8sxb+QZuBjEjz mLgOioX+g1zheFDbftKswUTb3F1vyKukW/Y62jiClb85lezH8EjTcHAQ n47ZSUnNGA7jFRMkrOc9i2hRo3H8DkMTFa/d5RFA4ZvFe3/jj4zWJ3YI aXWW7qUgDutPnrJtcPixOAD//KK4uGRxKwgeo1j1E6wkjyht3A09klN/ hZtT7qN3xruTu0mF3WmX/9HEOQhU4wswVHKHTGOMwh9h11qQsEu6UBgZ PDbAIZytU4m5ZStKg2QqjruNlS0lU3g6VBpOQ0RlZpzssPkxyRdQTCCq c3FEBw==
+; resign=20460416024207
+12r.subtree2. 86400 IN NSEC 130r.subtree2. A RRSIG NSEC
+12r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . KZEpHmob+s8a7FK1vLvmKWB3SWcmUP+tWmMP2QxeeLjHY+hZKU01F4tV FlXAUqLpmjuM2hQPfhPFqhw+Dpgvh4VUHmwO867t2OE82TNGTb63PDAm Ri0zsb+IObCIG5n+pd0mhV1gn77KSA72Qf++5SD1TqQ4b3zu554nzsig 3uqkpXbzYGe65GY6yVOW5nRsdo6qOMfcZIRFyPCSb5xUg7u/OaoOTV0C BaYx1o0dpbz5/pfriBPHPHkL6SXnOdzI70nj5m0ZfRQpKMgLOP+UW9bf +pPD9NHjD+UEs5LBQgWjXwymgLy+GvoCWURlWaHfDvgHT9fmeh2PlTUP 2ExVyA==
+; resign=20460416024207
+130r.subtree2. 86400 IN A 192.0.2.1
+130r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ZYhlWkQY1P62dVBDxos+9jRishojmYY/0wNvx4Zj2bHJIpuxAe6xvIrt YWlj58GQYlfB85sLp8K4/zwd+fahEjy1aZrmmfJJKVPLnQrUcYQBt9i1 RbTjR1smcSVoiIXu4FdDanbJc7sIuUpQOp3C27PImyfZa5qUMCnAxcLL SGhdvFLbii/ALAC5OKVxEqjAYtlJ7NuYZlxa/ZhruHnDRYBhh2QXSatx M19Mi9QboBMEd79U5ym2nK6HX6AcaFdimpK5Q6F4BWskUY+Qls5Y0PQH 5TPG2LiY998Pi5Pol+nnsfKMLJ+yX6bELy6AHeRHm92m19iu5Cbzg9SY wfRUTg==
+; resign=20460416024207
+130r.subtree2. 86400 IN NSEC 131r.subtree2. A RRSIG NSEC
+130r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . J+/kpBOiixw9TPfTRZXv8lkVS75TRukn57NKGPmp85uA6uGTsmAr+uMG gtAAqkxmkz4IeF++sjjaKxfK3afX+DrA+9ROUXqLeRBaut/abMocM5IK hJlMSweF6JLDSVkqFZ2lu/1yvTRTnIkL0XACrNfvbYfCDFAD8Rn3vXBB MkpsbfQ4mJVruag+OgP3lOyKDZPjMbjPR3l+rD5ywerfqfda744sWtRW A6xGpluhgUcJJzPvHGxrdpaDxKyJjWCN+JcP4yjfNrXX1YYJ8XZjErHr 5UHUMRZqEOxxNt8N7JdzHMieCRVrcQlB/oFMWZIoeiVVDe206seaV5cX 6hur1A==
+; resign=20460416024207
+131r.subtree2. 86400 IN A 192.0.2.1
+131r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . yDl5kzqQVeOBQANC2Hsb6WmN2W+Qul8r1L8LzquzWwYsjzYQOMeEKl7S ftHZSmLeVmEmARugRJxABJdwjzqfbOwHs0wAzKMrjp6W5naY3PH2Hehl vsi9nx7SHb2Q1bBMH4+OLfHfhG+E3tN5pJ/djdN2ksng+O0gSTAkYa1+ ym31BmIrtEBLUwLUUUvq6JWeU3Tw04JKeI0YXDL+Ve4Qjjwgrl/WhiId VGXRKgpGHy+GcB4pI/lJBpkQUWhjmd5IFkGbEImb1LDmAxsEmpLxTSEr dOlY57azlHqOfSVdSZVSiaYV/iCEvHW2a0+6hia3cFkcXBPzi16GiMEh CdbeNA==
+; resign=20460416024207
+131r.subtree2. 86400 IN NSEC 132r.subtree2. A RRSIG NSEC
+131r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . h9PV1OZUSaDHg6esVRA1903+gvl1LjuL9uqnmwfBwno/AeyGlG3H/UvD mGP0ktjftNcNdxLXOsKQ/bgoFT6771AtwpTqdBwcO0BPZwabh2tgUhLY UoMY/LufRyLs/3niI0rhBLURVvkG34aUJ9SIYa2vvxPZuaZevR8LrSrY etbkXWKiiCMeFb8y26xFjo/nYsbOoVs4RZr+24q8zSfEXEzeCPqe2uj4 NZtKOuSD14zP1qiWczlK3xOOFA9lU3MhOpyxXBv5mgVq72Q5CluugN48 9Jkp1bwZj3FPBRDdBJWkvJQhc3X1cdE1YQ1uLcvHyizdH0Cn3YqsRKh3 RlkIMw==
+; resign=20460416024207
+132r.subtree2. 86400 IN A 192.0.2.1
+132r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bSSIZRLnCDmGki3LVPFKkSG7FMHn7NUEbIObjHsKYRoBDMu6Enjrd+1z Qrt3mGkQg9vFVsFrcVTKPn+7Sq8Bjuur9knI9XX33tOszxWUFBk+pdAl tVtFLGQ9arB+JB8sISnEZZzD3/LID3XnUwURuemjLjYdzKZ8YZYvUoq9 DQJMZdScCBs3NghCJRcJ+Z+faYaQDepnsznmXfFklVE2ZMFjkejJpJPb qCO2bsPppOI9scQ894SefP72sehSVER/Fq1C6eUZ59sTB68Dd65yS1aJ Ft6WTTqp3pwysKpTpNXpxHCLdarQP28T9aBp8tHUyQu59S0Ir32tosXi iafxpA==
+; resign=20460416024207
+132r.subtree2. 86400 IN NSEC 133r.subtree2. A RRSIG NSEC
+132r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . qY8oCvoTEvFhDw/i0KCNZJvrlj2d39i637X69WOZ9pAHcsgs/BWSoxcR Fg+wjMZ5T/rqVuBmlOZywtwt8W1RZGpqmBzZq6PgkE+QJ3HuI3L8nxgS gkmeNMLqDDOH/Yq64u6F/hsV4GMlqrLdPTSVApkCjAQCeYtbv/vX+LIS X8hKaUjzbjRjKRfV18VwXgHdN8k7CE1TG6c4MN61rDuG50/Bzj4FquSG XhKsznV0qd2MuE/O/Rk0Iezo6QFrqukb9remAz78HfseDp7UxZ3gvCOr 5ZgN4LnXqEW9NbMznyEFqZQi9C2UzcVOHX2WXVWuvphhhcMPor0QfEuy NC6/JQ==
+; resign=20460416024207
+133r.subtree2. 86400 IN A 192.0.2.1
+133r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . k8zlvNtimuoghUWTrivzYIHg2y5nj3zErrgjIza67br+wy6k3SfHCLUm eDBFoMptjFyasoN9lYYDaKFziT/xOK4YaQKlfZrj3RP1AyKHcVBlIeea ZgF5LFHZiX1RtaMs0mnIkRk2B4DbxuljX8fADLsJsmSozR++Fr+nv2wt xXHbtodiyT2lQUJ4A/rx/TMJjHxBmNPGeXOA42KoAV+fbQx5fcYtySsz WBy9KMNylpWl85zqrXAi93shwDVJc7AsOozXNPNQAtw9ivRiVKzJp/Ya AQanbB+t0GbuwJUsL+Iz1wdze1BdLzo9yi5DUqAb2FEhyRfcgHywpdXA 4NNT0g==
+; resign=20460416024207
+133r.subtree2. 86400 IN NSEC 134r.subtree2. A RRSIG NSEC
+133r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . r8Eu/Q4l9RjfZ7R9vBJ9h048xdZS+P7Bs5hrY/++5bmE6+nCBkGXiK6f M+iBCzMOAIjgCkNReix7a78+MpRoQkUJ+UiMB3KIuOfsRWUqAEQwm6Ss 3XuGvDLPG01iBPL3nY38XfORJT3e9TRXml0WsmoFOWLcJGmgaOYC9m+z 8RERNtyA4S6YhUGyVdTGZWcIDF9uQXzHaEV3rnYLJ4keayYr1Wz/8y+g TKHPqO4vpaj/ta6umfaFlsBh+ij+73mdnwPLORbNfjoelqTvac9ysSIE MittrRdOtebOa1bSnuMixp/M9JKDcVon7ng9YQ96koKyQAulMOZVukoH So9Eag==
+; resign=20460416024207
+134r.subtree2. 86400 IN A 192.0.2.1
+134r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . s7kYOZs5grqw/3bmKBJn53eCs5IfIwXHS2LAjRcZEt2NpfrFZstYLOR5 dGJaRAFBHgh0n+7d/Tk/iEhvHo7eA6AJflqhGAYaoe8jcGA+bheI/lXH nFA/2Ct7pE4LPF4kgxrg8GdOnAq/lA7mG4BU7PDxNHFCbBjJRrZAtbZt rPszgHcRty0i2FOmL3LsUlRJYJZaNLxw297zXEouQ4S9URMsqiFL4QBD ALDOUtEA5t30+0DfSIxbxgIv5ELZ1y8FN0DW7o0AXOlmVj7vcWQ+65/F w1UsIbAYmoMxd3GovKTjAl2VT4uZ8pSWn21YZSm+mxwEhj/KlXi3vyZP 5F4kJw==
+; resign=20460416024207
+134r.subtree2. 86400 IN NSEC 135r.subtree2. A RRSIG NSEC
+134r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . nn23Ag8vjOKtaGMdeng/lUWZgtPNjQh52KoiIKOHNjcwRPcg/ABw4766 x/DYK5A1VzCAHRiXHxjAQDCdESbrZDURPiVWJUsAVKYHegkuET8ehmSp v7o+l7YhJzLqnwvbKHNMnXq78j98FGt7PTroughRV3FY0OJswKuxM0eW QnUAWn/126Z4m38hw8Ec2PtTCxS5Q4g4RefL7QEN+7wrZBMaYKMYL+wW 78RLqWMhGomI94QUNG4bhLSZhl5M3amVnljugdNOT4WA5Lvy15fQ5yfM Y1Dhj1l6vR0WN1S97mCPb0vEJYnNkW2XQZ+edR46FzV5dlIzhZLBKx06 18aLmg==
+; resign=20460416024207
+135r.subtree2. 86400 IN A 192.0.2.1
+135r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . mEUP8TKOZC+6X3NmaRFiczENU9+KKIalrmRD3fgkAIvogcDUiNkwo/Ii +PiHdJ5fJubznQyo/dbMep44pPWe7ONAv3+dW50ibI63UNRzcJ8T8d5W FsZQ7FeNNS5QPQe4TMacttc5sj+09IMgCADDa+TP1hgEMfFOVcICacbS /ZcZ1zol82sbJIf6qVW7oKSGP9WGs38gaNH/DP+i9qKGycMFUK5L4oa/ lKXO2xgiOaBsC6s1VpyNbAkkk3xFEfqR4XOYMdyKSUApqGFubuLdocn+ KiMg3FonJt2oH2rZPEeubyanbKK3+gHvPjHAzH+FpTl4SJoBNKg7oqon DTwgUw==
+; resign=20460416024207
+135r.subtree2. 86400 IN NSEC 136r.subtree2. A RRSIG NSEC
+135r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . FEoC0LiOaR55lIqMML0Hb+Q5vkqLdpJTAFK2zKbOntA0uSNPDyF1+iO6 8c+Si9E1QeteSUa15I6tnxE06g3uUEkGp0+uxHlruYKaK/6UdI6cJBBC UPxBqMqJydDcPKPJdWsmiOp3rRjPdwbEcLPtUqclLWr7FgDxpvor+3lV b8Cmogud5PmTN7IAMdo0hXljS/+GU9K2VERd/6z55Yk1jcQI5ZDSooa1 oY0HtssSg95QKn0VFw6PfZisDAgMsXTd1qGaomI48q4M1Nozp3XIHhaD YYGu49N26jkG+WfQXzC9ND0r0YpR8/FKhDo5VHryUJoDxG5F3CyN6f32 S7PSlQ==
+; resign=20460416024207
+136r.subtree2. 86400 IN A 192.0.2.1
+136r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . UVkngBEk4LZEtH7qI6nNxKJUoiWD7maltLy8h78nxEndS6mWqW7xq4GP E2w1I0PEaZV8Lzss2y2Hnl36uJKLgx3iqL/r1ycRBZgniEbfMxe3K56b i2qsViHKDBqKxmaOWsAEd0YoYJyiXYQhGZGbJFrDav6kCMrz7TMgCx5r t7Ng5XCsW4XfEqT2AbPTQdaccc/mYoJoNQypAnm0KYLvMtI3K1GJQlJ6 b9pL4ctktvW5+l1qdKUEdQDYgzx6kIb7YrQcB+/Hq6EA+oQMCWclwKos byloRSKgAIJcZNiHiIFHvilqgi+LfCGtvd/VU+M5if/57Ad5IdzIqcBL BmytXA==
+; resign=20460416024207
+136r.subtree2. 86400 IN NSEC 137r.subtree2. A RRSIG NSEC
+136r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . N/CSs1q/X5rVNErYAvM+nB4xBEeS6D/muzFOfp8wT0iooCVL5B4AlasB eu95iD+Yqvj/2UPpTODjDqCwq0GNJMkin0/PakrLPvGVjqaGUTibwa3/ 0uffENpVohWee1G/AmN90qfYMrHdd1LMFmbV1zAlr7/i6TpgGeYgLnyJ kFQN9PvWpHJzgRf6w5Kfy9rAkb+VolLOtaGysjota+FhL+vZdbZExTKf YeoajRvALe+7mdTSJl+fq0CvJmHIMHLZQ53OBrLaSH4ArT5L43Qb0td1 9GFIcRbnMPQxRDGacqTayUtDl707LhoN3Zycn6PCFvgbuBfJZgpnEdfT kwzu8w==
+; resign=20460416024207
+138r.subtree2. 86400 IN A 192.0.2.1
+138r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dd5AaIiOxGjLALDsWlu35xdOGnzmaqfT7dfUfV7swQEJJCI72xUttN3O bU66tRDNlGyPO9NF5FhGpqtlYde+cmkDsq9VicpbcRFGPzd7/iax9xkG NmRcss1SSqoShfTAobS9bmQNY769p9a29RxogqyW0ENHCuMyNrmnfDCq 2Ps28Mi7h8HhZkaweBq2E+K5jfvvdMpV5S0wGnXRItgsSulMltW0rAys 27cHbxeZruRKWwiF6TvXIRnFKmcDdJaB0wyHmGcbCp8yPP3cs1ucyL8T Jog8I9OODr9bkiNqR8hYe6Yb0Gjos9Jz+8sdg2j4GPTC799E7DQhDmTu P/IwbA==
+; resign=20460416024207
+138r.subtree2. 86400 IN NSEC 139r.subtree2. A RRSIG NSEC
+138r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . sYHaUjamI6bt1N7W4vexUPdzHO5kDj2xuG0E/3ASwpqwkMFdkPNLTKh5 368WZ9Jc7inXp96GY5UroJz+BvRuJQGW48R0XL3IZ6mxX7KIeS9srvxM +tjyc+ub6wrTXtmQLcv61+m0T5CNMmQ7LvwMmxOgtMgGOmBtTZ2sw5S5 3mvkZmtXihMDBnEH1/lJDgu67LtD72ULQLqMofHSjazdNWkxIjRkUQDi UWqQ1RHMf37UK/PA9U/y6x/VXR0IPHNDcEme2gsc8gS3nwbZee+eDyij cIl4l6+4E7ypn5s+PSUaaulzJ5r4SlQvsljyeoHd56X4fDld2X4NSYdJ Vqmt2w==
+; resign=20460416024207
+139r.subtree2. 86400 IN A 192.0.2.1
+139r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . daQs19zKjNtGzUILqvBev3gNBsGYSGPix4XW3KjPjJZRChxJ35FtZJD3 3J7zFUyGmvSMdqeu3SGUZPJQsjPfudn90nBQoixB7P1miaCP29VxUmw5 jhM4AeefB1N16Lu+e+XPWqjCjPmfwiUHvWLq4LSPG8h3vQwMwJqnAMCZ 5503rUtno791CZGGXAxAdJoJrYFoEgaDcdqk++0ls+xJLWgJkK49NW8b si/7eerweQHe6ugYU7jcpy+ZDOabHlmHD4/pg0oL9Iw5H8Ar+CYUhUgN uLjDgQlaw7lWco9vFLr2Aea26J+jOhKSRqLovm8hOl9yFv+M42QbUaHC TmHzGg==
+; resign=20460416024207
+139r.subtree2. 86400 IN NSEC 13r.subtree2. A RRSIG NSEC
+139r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Dcf7I9Uh4Tbiwhz5s+8VlC1O32GhHbSxDqeiwDrrnxghi3luXUerBWg1 hdb0zNRWDxnKWSryWVf5z2ixnO1DVQqqkI9u822xc0Cg7MhdEKtIHO5o xNDSg538jIbcrpI3yOyyfPoS74n5Rxv4bpbltWTuZIzYm/lbN78t9PKM twTHlVykbw0teKLEIkkRMHrVziwqZ3OO5OYeWsxkaR5gaNgUnCAgg+gS tFAb6I4X6cB+yh1opulG+hEZga81CmgwS0iDBor+vD8kTFqeAnQsHU6C 7mmaqP/gNS+l9plTYs76yR2yCdsDhKulK4BWFTjrCfPVtacJs6mooSg8 hIwgVw==
+; resign=20460416024207
+101r.subtree2. 86400 IN A 192.0.2.1
+101r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . naTWHH2lrB8zSUEbz6CGNZty1Ugf9dIFewyFcZzC305e6XtCPW0JlUPZ 0jInSEJg8dVeVZmWB2/9IaKlCtTCdUw9PL2b6lBNKenQFbb5dtTgZHvL nscMdS5VhTiu82hUNnGOAgvvrPbL6sq48r4kYqon2aE4w6C1S7hiOjGZ Ba4j3lhwLIBVYm2dmn1h3rrr2n9ZJWMDQIjyApx6CrcawFLA9qfyCosC spm2qXEMa6ErnCNjwl/GXsGxW4Q74Kk/xxYEq/xQaudGsHdJfXZ5+7N0 CXcuzfVpXYDkRd+M53g/T/K0ZWhIm3r/wSBj8zkpsJ4k8wUDz0sMG97u iFZ6gg==
+; resign=20460416024207
+101r.subtree2. 86400 IN NSEC 102r.subtree2. A RRSIG NSEC
+101r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . V5zFg8xsuFrlbt67SRtfgtw0twyy+kSd9oLuyRikZ1gIzNwI6Arg9MmN pE29waWsmKEx/JLve2iV906CGdansOw/of71SZilPXH9L+q4w2zCJRkl 8fh3YjAv3B7fulp5UYc075f2vcxqHtqP11b+a7MS1ZaCGA7hfeMqzJez B8zPcxQ5qU35DUYHEfx6ixe91a5sf8t0kOZmliZ0LrXu7JF75x9mfI1Y y1+WWRh4MPBER/4y/CVvQF0Yf75xKdDVRu7nM7OqLzwiZZdFiGIEr6g6 2JCEYhZMdLJ+QIuaEpKF+gz8zfOqgZ4ziXen5o/Ob8OjmxAOI9/A/vGE Dm7sXg==
+; resign=20460416024207
+103r.subtree2. 86400 IN A 192.0.2.1
+103r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . pR8d/NmAtcsBFWTXaqsR5LMSiYHHYlFg7YrMef27Sms3rDDf4xVrFUpp jhBMaz7f7ZRmQ9s9QxMY+Kcgz3/cB6Ic3ku8avkYS1eRhWY0ouY6d+Wr AfK5dplkPq2rZG0q+2TwutSEYC8YbXsEBw0PUgrkJb+TX9PALgN88dXi fOvF4dLw+fP3rdltnWU8ha8EMcz95OtiuiMXD5LKJEs/55e/wdBh3L4U En1F+iBTlewF1a+/1SJ8Bf67HWH2vZUd0YHDNKoLaCfVDa0dFAXZjR/o suYLrC30Asnqvnn30tzoT6HRql9FX4y9a8npbAVGgHcFsnGbm7QGRlfr yPXE9g==
+; resign=20460416024207
+103r.subtree2. 86400 IN NSEC 104r.subtree2. A RRSIG NSEC
+103r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . li/pzRyR5qYV92PvcXGMraDHPpfS0aSwzjZb4b8TykvnDLj1ho0Sc3GP MQi6M7NZ1aqyxwDXlJFGBYOEOybSC/yH8tIqpOZG7cXQm6OOJ8rWVCHX sU0+h1Hxs0oban3jnbflJnqW7OCtOFBxLApqS1AI/Wbu9qStqCUGCyZ1 18j4sewPatQ4fQUcw+nXaiPNV45lKgR35fOfoq6CSKWjecboY9BvAn+w 7PXywU9g6mEfgDw4tIlB9LGtl7MSYagHJnQX8+NWidZyzLHCdhePDYYl 4PfspQ7TCZvsLcerU95ETtp1iLyOYgQNgbobY3i4Ner3yuf7gtrMxHcf 7GbW7g==
+; resign=20460416024207
+125r.subtree2. 86400 IN A 192.0.2.1
+125r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . h5fOzVZEq+smgW8etkQddwgA6/TmQ3CTPHkLng1xY9V0hJai/n58ORk7 nDgpuy1A09tvtRuMolQmQIDUmazniagyWYxvTg+VF/lQXmMASjLWchQH tlKAhmuu1JN1b+exsJn/vn6dZ5E1c13yd6c6GB/emtRyF5fbeHOedInT EbPJxBkhGDo3CQXHDN7Hx/4I2giTQz4jXduj3vt8LcN/JOX2uG2acPgE RRgP2UBb2sjVeOKcHkRQyh8YsUMIMgvfZZOYTJycEm9YlLZpafg/ICJX U6aiAYqp7IYKjU52bGs/vGG1kOMgG73YDDZOkjCV1TVQYOVBz70dYl5y CzXfTQ==
+; resign=20460416024207
+125r.subtree2. 86400 IN NSEC 126r.subtree2. A RRSIG NSEC
+125r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . xk3GwzP9UACMuUs/0waDDlPfeJ7dZyoRHCfVl9EH3FP2ff8H9ttXjZhK HA9uqRPKf9nQZ5SsSIH093JsdKOHTax1E1U0HaN8aUsZ6wffWXED1Sk3 nZ2jKrfFhOvsz0e8BbemHl+Sn4B60O+ie0IEvNX4qKypc4zbZjUXKq4C WDU7+LJilB4OoFOtic81ZRVA6rWVSLIxbehJ7mbaEA0risRAbF5mT6HW 4OPmOZ/NxDG+5JKPuYpos9lnSjNmeUFuBE4i8nfm79Eq9KTak+clNJSZ iXlCY3/OkGSx7Je+fMa+rXxIiULKEopAFVTPCb7TKw2UqVclAAAOwf8L v0Z72g==
+; resign=20460416024207
+140r.subtree2. 86400 IN A 192.0.2.1
+140r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . vPLnzmORrcydMv7m5Qs+8ppHJZSPRHjLMOYISRo7UAsEfCszaaVv4AVo H4hTLrq2H7YbklEI/WsCSCZI+cm1bD83siNoTRgTXorWj7srLKIZ1UAw 32ArfkG9RpWVAt7wmEYirWgIRFejrZSpHdIa9t7sFa75buxueNEhnGi2 gPDBeFJDlfLI+YqZsUmjJWGgM7C/JLhGVzcQCEHppjtLRmjwRVZ7Fwbq v8S+ESjoQCTw9DEYglqYPw8VrXbp5yFlMkq8O3sxC7S1+OP/bn6ipXkx P3L1gKaTfakSM+sc+FwyiNFKI4Cqxu8oIerJxBk+IiOhdi4+drf5PPPD KjH46Q==
+; resign=20460416024207
+140r.subtree2. 86400 IN NSEC 141r.subtree2. A RRSIG NSEC
+140r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . pxg9E6E+3OteP4DSEUmH3dJJIXp0kdLG20xEP35PH9TA3bLgLZs0Y4ny zFDFUiRoesKOmjVithOpbjbYu8Jm0jOK1MXWN/AItzqxpgC5it6ut3xH 9briU8VTGS4IW0XfLwl5jofHnZzeUCR++7vkK89BI8VG9nPzsjORKCzl MRJ1Skjq0KeNxTl/4k+uc1RhXSToL2EPW/7AgdqsOOQI/1+bZ+8ZmsdN xkq6kZTOsnLbvx4GM8IFKz+zfQVZWgptsbDf/RiprljqUOdPbeYl9cRt JElK6hvBcXvp6KFjodMk6YwzezbjyI+pmUy5BQFn317H36UGief0Rd7T t9lbxw==
+; resign=20460416024207
+141r.subtree2. 86400 IN A 192.0.2.1
+141r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . s0M9Sv/nxCRcj/+QW0pi0RbTpTdN19RejnoYY8KYiLJzzdThRyLmwGRg FOsEIS2IbA+zAYdiXejrGxqiGP8F6Djr9jULjVdrH9bfCnpqBv1HDB2n U+ma5apsAocchcyYJjkmP4QsDAoP0vUu+jhLh+fokPzG0lnAV0qOXZSD l8DJpzKtH0F+0vTEliF/21usW9DmOmvPKPFWjB2PvBq0lsoUjSc3v8/U oLiRuFlRnruUUgAMN5m1Oo847CJ5FV4S7b304PHHQicjlOxahhBbhBGJ nKv/wvCjnqyT2l5rkgZVHg1GIDDBt6riY9+oxoYiOkjIed8oRUySJqgg /VvARg==
+; resign=20460416024207
+141r.subtree2. 86400 IN NSEC 142r.subtree2. A RRSIG NSEC
+141r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . VCDQxwBmXbc3Xg0Dx7w/+Icjl9zLziJi68YVgJC9GqynePbBGv7Y8c9l JMETd133deacHm/KO/CTE385PKkg3hxV7icsZUi+9mYxuKMSebUcq0v5 fa+BoiwMGDHq1ypx+U8/T69dM0nB8WIVXXUY7h4EojABv+nceg2ctgdB E6Q8iFXZhQtRl7KkTYOSGYXwBgaiokx8xza90SgVInEk9RjsLrfEaQN8 yRuMD5QTOF6vx59rzd55ig88tgXO0lULDbUFwwTVfM/P/wro9t1EpN6Y lEIKzB2AG34M3d1Ff+oE1xmaKGfiM3OXaDJ9biWuHNKdmcqcVVN/QfQ8 kSBgyw==
+; resign=20460416024207
+121r.subtree2. 86400 IN A 192.0.2.1
+121r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . T49hjXWYhZI/lr9ElgAbuBilAsfDoautCeXeOEcD0lq95BqhW1IL7/Ma r7jxVviyQ8q0HjDVpbwlMTGDav/CG0Xsxh1I3fN2gRBEPauO7N6CQ6ym BEF+004dH1Zmk8NgjsggapWcitlzwmiXCxDIuVFSVTCiLQ73p/uFjBDC ML0qIy14B7RQLnMwGQN/7wFMqJTYZ8hnFnzJepzFw72ykQYqV9NhuYd9 iF74bU4q3KXb/ZxU517uRQ7Nz4k8ffuNOOankIFKjjjUu327rlycziR3 Jwy9TH9uShXbvEef2mhgisiAaNVFlYh7+i/AgDSBw22Fv0a95qyMlchs kTevBw==
+; resign=20460416024207
+121r.subtree2. 86400 IN NSEC 122r.subtree2. A RRSIG NSEC
+121r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . PB03mEoq3UU1YaNTWTv2WwJeV240u76occSIJ4ydGzmTQB5Y/K7GFlck O4vk444DRKXkq5JNLNGt26y481aXteR0g2FhWZIcR4G6ryNwio6XioO9 wB3FGZNe5w1D586Y5mSqNpAITV/kbTVB9HHM6BHNjrW58OUyT90Xyfkn uGU1EmwAIu1QXMwDpUbjqRa5hAbEhHYrLjYL7bvu8wQ1OiSQ0kbQK7B7 3/l4IcMywykDmPcXwV8gm+G3DOZ+Tr9j3vgmNs8w3K9EcRMENGo9zVEQ qlnt7w2e+P8W+avwdemx/2D1DiF48QYRnfFwvCWzVpB/Gl/JdsfDZzkC ry+bCg==
+; resign=20460416024207
+142r.subtree2. 86400 IN A 192.0.2.1
+142r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . M2+OjdCI8RU/X4ziIxBR/2aUAAXP1im94Zgp9e6clzNHs+3v5213RRsb Y3QTqGsB8O9+5B+yV1vGlit4N9Zu1Pksncx9Un5fa7pC0Cw7qmmLtFgf Uaue1NnHZPB+1ImCGJfnwHRksfA4SLaOkRKYcy4MlQDZ+kGWP9pT+PQZ onPrtYHluaoZgYSQMSItld25jomaWcjNtrAeU7SdzAWXcfwneX6sf6I/ igelmxGD+k1IfrJ2fAUcQuTR/JqDEQLWVaBLsB1D3WBC8BQif3MFY53Z 7/TizcH3ScG/qn6KMYjoyLW5k+02SA90Bfds7sbR0uD+sBHAu7Yp/L/D +J7Lww==
+; resign=20460416024207
+142r.subtree2. 86400 IN NSEC 143r.subtree2. A RRSIG NSEC
+142r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . dDa7tarIl6gdQtX/uOz66itjuyZtJ/GwxEXSUuxlqWvlI1PC8lYjlHsZ 0ss7xZRUfMv740xDDXY21r3n4inlm8OjTmMczfi/j3bbQmwENPoJKFeG 5JhQQOPuFS3PVjQnaiaVSyusmpJqCBuwPMOgmqKqoN4QWWKymrxYWWft SO0qEsb+K9UYIrhjvjmTUPUA9uerNZ8v6UW3lD+AkyzP3eH8pHP8KzUT EhH2lO4sVfX1aQpgGd6Gfeu4R12yzPqqH6epfS6N0DwGYGH6Je/b46jn bUf/tP9/3BAJw3xO+LKEg25sNJdQ4TzrdMY2gvyXYNkMTFxmO8bCeKGq I9ZoxQ==
+; resign=20460416024207
+144r.subtree2. 86400 IN A 192.0.2.1
+144r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . vouYlS0l2NOkfSjVK4qj62oRQprrUvs6Vh9oXGmlEqoN7qEyj06GAwz2 tQsR/Yuz1c1AKthS5mbbLYNVIRSvHcXwz+pPx6nrcnlcMqPLZxsq8XnZ GQfTiVOyIdxLDRqppaAflpz8NwxNcNiNrVkTc+mZnTZBhZlniebZxUPz UBexrWxUBTQShUu8G5q79PH1XK+4+ZBsT1zBXRTyekUHbIF/vkxvmE++ iBft5YCnNXyJG1aXOvVvFmpOXYMj6Q0i0Z2nghVvlBw7zU9Ms8nEwS2D GBNlux7k8bA8fyPb0x7Ktw611EZNoj9IUbnnYOcGzli9FdZRkQROrUU7 7gYw/Q==
+; resign=20460416024207
+144r.subtree2. 86400 IN NSEC 145r.subtree2. A RRSIG NSEC
+144r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . LXKaIEqlhXpgW3s2wCOozeOcuZZzd6EPP5ntrD/ZF0Ef28US1RsrOAm9 ffXeIrv7zZe3elJC3ZsMvrsGe7ue2CfdXRMHYp7X/DaZfo2BsDqxNn8j yUfvawyVfByQRzoBUa+sWx8YWZBPEwsYPj5cvg14lXi8KbMTWeT5Xtgp uacp/KfXAJo150QiCv6vJRJPuV4+OgfvG3MieJKqsykOrd1zpixwvvPd OKQ2WWcURPH8p5ozimacxdVdvxabCemQ33ksiDRWFlAHxMePkDLNP48w Nb1/Kf3Xfn6lQXAe7Sf63v1bjGPmHqNMLjiq9si9AOt6SN9/kPKFh+H0 OaGzkQ==
+; resign=20460416024207
+146r.subtree2. 86400 IN A 192.0.2.1
+146r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FIf5murAK7JG32Aiquf9v1kti6C8uTHzO/zYOI+CPI5XlwD44OtViTgC FyQUu9ZGdyg7FFYKtmLXDD+irw8Rz1g86C7bBrFPHN2KntKLK6q2K7qH stsryYKqGbSyktkUU/owA5C34zzJ5ubX1kTJ6NY7GbFv6mlOTBb2vfaI xyiguxFl1Ic1XCvlkCrKE2oSesBtjAWGEAoPFYf+1oZgZbk0OB7tNpXL MreaemYoWvICTTVSPggiWOcmWyfwjzHCrtycFxK39b0s9bafKxzlwv44 GRx2sl1KvBhB5JO/Gz+KVuDyMpb9nhG6X5oOSqoNqQ4B+M/3dA7lcuDQ 8xCjOg==
+; resign=20460416024207
+146r.subtree2. 86400 IN NSEC 147r.subtree2. A RRSIG NSEC
+146r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . SrHI4fdyyLPVIbhzkzz5um2wT4eQXAEWCq13XnZcUQsn64lH+IYDQgcU wXt5PlKQBpB315hyAd6V6O7ZKBy+NWI6l+SSSIrSX1LXsgE2OfBocmlw f9hJqsD0Pt0KDODjeQ00mJF3uWz6VSASAWPeStKy1IYe4FuYWfD8vLZ4 1ZR6T8jAgP+O0TYZaTv3C2fCNiRc6PWJn5swmJydl0VYkX4nFmEdztlO yUNkmyAXDf5yjG3rd2qoX2di7x8Kk6eg1ANlPYmWhd8NpPmbTngb3tv/ c1bYg7Vo/w8EPOUmaAy1CW1GoPwXSqdXXmAPq2rXh8a7KCG/tOrz8Euv t3DDGg==
+; resign=20460416024207
+147r.subtree2. 86400 IN A 192.0.2.1
+147r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . itMxfwAPvB99xBemNGQ4wTq6q6hshfxjC4amZmFtNdOLXOVZhkwMlhMq IG2Wg36SYpEBmNSfagYxFj3ZTz9GdULbRgb4I7sMVM06lCVfumNcllUR nrvwOc6vsms3RWxntFkW19hG2x2kE4We5P5ztUitMwmVsy4ChprDyqls VRGEmqdEFv6xgmOxCeYhBsptwt5Tr3yCIvjYb4wO7F9ACmO1RUH6j//W eqm3DDZS/QGq/DjxhepWyIgbP4/CLUUPH33+NGbCTMxtwnP7V5/afLWX DSKr7hskDKDz++VLxmchw3OMzBRAHoRkRSJ26i3i711WHKOGs/kcMhIY T9xAqA==
+; resign=20460416024207
+147r.subtree2. 86400 IN NSEC 148r.subtree2. A RRSIG NSEC
+147r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Qp5LV8mmTH/nad5/DRQ3Eja/JdZbBT7d7htQBL6DizIhdXw35fa4x+Lh eRRXtRh/HgmqRLKgyQvaLKqdwC7SeuCk8dezeJmvtFirrAcgXZlacOT+ b/3yS3xgStmfDlnpwxzuhuxoIADwyxonb0BDxZYKGjGZAiAihKVZJah+ ApVZkP0ikLvWfSRwUeMGtiC8HvpL4W4c45dNz1G0SubfktzPWaBDM+bD q151REswVl7b/TpqMNG/YjAgE09zCLoFtrt40XbDTrQLOCM70r2n46s5 JQBhoj23HUh2QidQdcwHdUvO+QZOom+pxhrBx5A876AGPr/on8r0Mi8H OYoLwg==
+; resign=20460416024207
+148r.subtree2. 86400 IN A 192.0.2.1
+148r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . f3UZIkgKRmT8OO71vS1xILRITsURjmYu7Ivf8fRv0EgTY6oM7DnpxP3b wizevoLNiopyD8+ZbpeaqcA/nvW5ue45oShQsCrhDXmzjz9JlK/4/o6p kBud56M3IDRFrEXIuaaY3WCDs7/RCs8USBMarUiB0F5QLSVz5HbPcFvE WPt8FKws95CkGXhEa5FiLW9PVpmEIcvMb82vcOMLg5WeMQtXH6aay3Ve 5gauH9e9xQD4zlW31VdyzTEoegmR4shKM+N1Jj/H/O3S3iioYbp42VWh XY7L4Dhq0O9K4h9RPk2YBsv9yXYl0ea6ONouQq6GBpvL4UtkCk5WxC/p f55mfQ==
+; resign=20460416024207
+148r.subtree2. 86400 IN NSEC 149r.subtree2. A RRSIG NSEC
+148r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . A/RNTWjoB4beOyWVfe5KIeF358CXU7QSDFSlq9NkQgM/hdOoWBoP7BfD 5i7shmE8HkH73YmlacF5dXEGXds/AoBFWxloxjwuF96+XPgeATgna+Ce fcpyfHJoSptoCUB3nlu8TE3GzUBFnHYNyRa2vOPTGAI+uaDrAbbw5vb3 ID0+ezMr2m3hHlFQ6MXfz+UwlEoURz2K0T1WlGdO+WDPXZys3yIRa+IG cYQE/iM6yPW1yorjPUCP48Bg2M49Q4L+H3HrJe+mGRxQnheZG1VENFZI D6P4PCeRTQxkeo8d5L9Lik0QmHD2/PHw58/ZVQO8tUkibo/wonIDwFRY kWFSEw==
+; resign=20460416024207
+149r.subtree2. 86400 IN A 192.0.2.1
+149r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ALwPUCoxbaiFK7OZr0/LTavFs34CjElZw1KABbHPjlYcMJQ5N6bi0kdM TQxfw33vm2rCBR1hbMzYnsQqG9I5AWDnb687d9azCpN1+0jX84o4Ku2n YqRI5o/KO6MV0vhI9BZj7WFwBSXV1AMME244vDseoG957wJ0yyjTOyH9 SJZlmGewXdr6Ugy80/2/Z+S4s7sBMSe+dkLkh7ctzJuoGMHIJIDr6mrV TTGvhEV3C/Csl20SY/qzqNQMHCBui9CqPE3Hqs5ExdgNcQVH+VIcSrW0 tqaXUx9Ci4OwKZMDUuUWktKlSl058+qdfileGbSLINvIrewwZJyunPqi Kz+0Gw==
+; resign=20460416024207
+149r.subtree2. 86400 IN NSEC 14r.subtree2. A RRSIG NSEC
+149r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . xhBfQabVy2KIGOr1RLN0IT+GU3vhDaQr7fabs+VQJfLG6Z0xYzS5U5Ti 4BrhcRsIQzWQOPKnzUe08o/pNVCqkoP4djCziCx0eo3UOZd6GggXhqP7 U2EGA2YvbVuCXEScq6mEMBZNgTjEUVjWJ00zF4IJiChrfHCmK4H5Eijz h8wGd/hxMn2ZFpYGAGZ1nkrdzoJjsEF6xtUrptTUD2MT+tWKZtvDyl4A MNyj/rHOkOTpSTHotgWDXwdnmlRK7AC9LJPVwO7gebmMFZd7RAGVoLNR PJvpJY08exrpYwNnG1ub146zIS5HQuJDH128JGYaeksuJWczatJJ9OWa mrJemA==
+; resign=20460416024207
+14r.subtree2. 86400 IN A 192.0.2.1
+14r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . wAVrmJPhxufbdd1jzJXHSnYpQVYY4Wu3vlVNwqzRhi4dTEJcsWWO8SnA k9MXqNCnZKMB4KHMdr1XMqHc4swsSrzKyqOLSPlYBWR4YW5igEtgtNV+ VGkWNHBQsDGxA645mRVrOyFAFSL2GMK87IQ7TGXjFjssxUlYt7zoxt25 Mw4bwZi8oCi8ybd1q7IertVelqvWbhohKbKza9suVxArSFjayrThIedL HHd7yWncsKCwLLuK5+ZrFJ4LtETTbdPC5hybUGsJ+S5migqr7t4xyupe m2ZLmHOEVSlzexa5YuwK6UQDgCfUpBWeBT45gEjU5ULJ5H7YjFooaHZG 1Ao7AA==
+; resign=20460416024207
+14r.subtree2. 86400 IN NSEC 150r.subtree2. A RRSIG NSEC
+14r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . iClXhruzeEz+KZrnHBbaDf9Au0x/txCi2DbSSU7Kt6E8gFsrTg5mZdHW WPdJOC+vOGqoSusDlp6VAr4aZitRLXtFaNOBflAMogsgLz30hdzz4CXY jklN4ZYGYWAudbB5YHJtnSqqyjeuqeEL3yQTfX9LkFgz7tPVlQzbnMfZ mz1qQ3ZWFV75h0CTs5XlZgs+n4i+OqoiTTdf95kcwqxhDG27eo2WxJiX jVXWOPe/vSermIgYzTvgW3EiTS8H1sFgPL1kH0u4qSwk32oEQuYky8wV dLwlMvywvFK06hDWDJ3k7s986IOWenYxyKtusSnsnCAwknXlnoyc6AU6 EDpAlA==
+; resign=20460416024207
+150r.subtree2. 86400 IN A 192.0.2.1
+150r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . pML15hMe0UtCSkZozDf3GPKnCkEc1ZshVtv4K6xuxdf68H9ND/Wm8Nlz xKwJeuzOJKuesMGOP8iB4+JBuRNzP4ONCNbUqGdAoCZiznW7l1LwFjXG yzxg/JkrzAIMf+FrvGycU3m/hzQe7w3VzVrxfs2r5GbTwAnrvz8iJAp8 pqwHwsLtLb57ufLA/bQprhaEC9HmlRniBBIZBp2Sz8hWkTNySIgv4CuV tM+XDvI1l8wC7599BWdKa8aZ9N4kVUiJHb2vTuSKrgWJ5yxb6iGhhaAP J06+1IiBjF2JxyzrdDU5xUJjAIYREk6NCOsVTB7j3QApZTFRPc4lGrRe KzYLtw==
+; resign=20460416024207
+150r.subtree2. 86400 IN NSEC 151r.subtree2. A RRSIG NSEC
+150r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . t/yZAbAAQQ10vbM3j38zn8lNH0/hcFQ7cByPn1EoVu5SV5oLy0k1SRtO JdF23wXfENum3Y2S8lWKURLNPJBF3HFS0CQhhSLpQaLZgFR9L4iugiUD SssxUhKZEQNxCcRl8JXQyeVCqGhoKEJig7CoVmw8/V5zZgg6ifpLdfVD 1r5fbYg2VV7PQbcpK7QYEnfu++38XErQMOrN2vO6XUdPAVxQ3P52Bnf3 ICuklnSznX1cVWK+clEjMez5/GdI2DXmiLKOL4lcxm+RYx8JBroLgE7A tL6sk+DNlxi4DlfT80+QIBrIHRptJN/IKMolju37H7P/1kC3LL8LHF+v 10XgDg==
+; resign=20460416024207
+151r.subtree2. 86400 IN A 192.0.2.1
+151r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . D7loEcCxYOJXNKryeIFn4CwBWMRQ+n7z97b9Q2uBhhmWJm4jhjL/sDr1 eNLRRdIjWzHyZFt/iXEsN+CNsPw0iDvUQkeRPSeCpwXoY20twh4Ogb9z A6HyItif07zVVM5DAv0XjznRfC/VEQ40MvRWV7UvnFdpnRnl+6w8p+dg O+nBNCx2TlUEG4tFMxGitU8M8rD5P6G7HLRui1WeY72B3E0GfBR9DnxV 0kI0cdHp/hbQOviLYXmGsMB1GGVpN+ZNtn9sZhBjiXNLkelEgTX2f9Yx QcTy0ELv5BrtTut/L4DxCNhsu9lO6EwYc7G6pcBIwyWpZne5gYVePNKg ANfHBw==
+; resign=20460416024207
+151r.subtree2. 86400 IN NSEC 152r.subtree2. A RRSIG NSEC
+151r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . S2nBDfiRUi60h1AIMQEtzdQ3K6iCewWCSRByQVG3E37GqTXL5jt/rcyP tLYRr8pSpN5L8q2WTi3mtL+Wf9OIlaJmNpasyEscfeSGHvAoUionGMsE OK9WqFn+9JGfRLwkxUNa2SoqbZsegvUzxgFabreFncgQL4tSHaX1sI6L +bL4l25bc8vHXiyCQa6d4aSCBa/5fdlZUW4U95U6mKl17h7eLWJ73Mv1 07vZfOGXOxtA4yuz+YXTt6nRcZm6qj55j6bh2PUFiUTKFI7sGAiqzik3 MJ24wOLOHza8uydnkICFHsqBptAnlL5Y19N7IumoPzsR7OeK9DvHb1a5 lNl5Wg==
+; resign=20460416024207
+152r.subtree2. 86400 IN A 192.0.2.1
+152r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . m0jKSX1mH2X3H0FBaXx2Nm5JCiwEimWXKyxqDTagax69EdxLmpV03k47 CvDNu9TULfhzkcAn/aNRJ+0XiL29Y8DMhRuZW8AkegbR3HV2cSN/5Fgl QfOg4DDVAztIOij0PlKSQ4/nilPFgSsNTXM4AuDsW359t4iH93FeUvOj tNSVOdXh4JeVPQH7NYuhOSUXuFNMP2ScX34D6Bp1W4p2yWTRVLhSWsXE RJGtLXAjnFldVYaagXDse9Da7rSm9GjmY86skEv/kkzKtLK4px39U7bZ wYiQJ5ZnBQCbZNLpefWusnotjjF8C1xl2+MLtwUkI6hTe8+4VWZuf5+J ABrCmw==
+; resign=20460416024207
+152r.subtree2. 86400 IN NSEC 153r.subtree2. A RRSIG NSEC
+152r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . LZY2vg0maCCC4Fmm3kvxMl5gRyWkVwmtWeFfvnLwZy75QJyGZSxT+Rj9 aDU20CeOzsW9jlAUM3iB6Pcmn/smjgqaV/RJ1kcoIUh/f89UWFn4ZXjv XZKSqHaI06GABJXtnarsfiIli1W/bCsQIPng1LLqtl+mV4SEz0ZSMWIc WBsXfmnFWOj7oO59UQb+CYldaZNS/WfpdX75OA00u7sQbIvN4ASKa1iI /UZX4eyDZ8Z9dwQ8Rq8XRFFUb3wklURHA2jF8nCklcbjpcFOiq7cV9ka 9BD4fOrVnkYTqY4Aj7vR05iV+llc7dk5g0SXMC37OqHIrY1uxh5toDb/ cthv4Q==
+; resign=20460416024207
+153r.subtree2. 86400 IN A 192.0.2.1
+153r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . S0fTs2ZCGiI/bMHo9YzZgYIi8MDGOcr/844OdRhuFcxvoU0VcxU6Bhez AMjV8nbD6xH1iKx/4jhoUA6VJms+HxO0DHDjudNpZhLQWhS0UJPF2X3y vUG1XyAZC3T9g9FnOVNbEi6ORSSZ77ZYFQivlwYoIfr5PGJ6MkeOUvNb F8jSi/c+j1rAFXkPheXKFLJbHJ2PT2p3xqiwSOWX1lYfYTCzRlDrpnqb pjN1t726smKfUL+/snXV5r047AGqqvefqBIq8XmUda8Yewu978Ocs1OW ZrNrBDu0x8k3iQshitgSW7ivk/SDSw6mEJHLQhIBb/vyAt2czsHC6jfy wRAYbQ==
+; resign=20460416024207
+153r.subtree2. 86400 IN NSEC 154r.subtree2. A RRSIG NSEC
+153r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . gKkuOJf15J1G0qDffUAjjoSmp3ychacQyJw4YihvCfjZOWtvNJ44GGmw 69Z+dVjmFNlpARRVDRvMANZbZ8jQQ17OfH0ZYA7O3c9FdiCqibppR6Ai f2221EEOGjejgXxVpum2ERPPnlo5XD4OxM0mn7Kyi9gjsNVvYBvF1oo+ DmxRxuKvz/sjwhhYjE9sJU3yIR6EXj5uDEsaX0Vv9G1D9IfkKPqS2jxw tEIWPIxRQsssfZQd43qZxtIY9If+CnFVqvWmWOsmmpNdHLeMB9UmLWpd TFV5DuMiWQNWytdyEa/d4k/QaPcy1d7gDU3w7qXcsTru6+4mI3niq9FO JIlw4A==
+; resign=20460416024207
+154r.subtree2. 86400 IN A 192.0.2.1
+154r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . C1RSEI9k9LlntVROIpuZn9p4T7uMLcZtNQFacghr1qw4VeJFmziMCsww QYazrqkbIbwDufP8d+jHIajMtcYhXm+bz5GSGPSYFk41PzQbhnAmTk7k R79uIjGtdNg6tc3pzKC5+Op0TBLQPjGOzUkvGO8Z1VheCHdEumYBXw3H WmNxMvIICdmsfpN+CWfFk8INHhhw0AKSjW4mLYH4w6SY32D5km9SYXYQ 1q80fHtm4v6iNBUZlsYF2QmiIMXjgAnSbCwSYRv+9yt9gp7ADxpA4zmN gGLw7AG8xC01wYcDiziEkUQJKdPpiEcsTds3Kvc9UqjTYObEbXQelxCW DY1xew==
+; resign=20460416024207
+154r.subtree2. 86400 IN NSEC 155r.subtree2. A RRSIG NSEC
+154r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . GuFnrQeKviEGN7YtsNURisuq04tauVEnnOgAaAyAFX96WAH+pkAHeyPG 7hu1jbPkdEm9kA6j6uZEQXe9WolSlwuCfwsyhsnaXCNesrlRntlnBsRr 99wglXg1eerks4/uDub3DgZ2rtBg76hA6MVu3afBJ6xopvCDbCJjk7Kg PXX37PcCgOcKuj32dDn6GCNIhf1ZD80LB4kIZCS76r7KSj6Arq9ijWYp 7bqe+6rmfD8AgdICMYn3E5e+0C2hqSQLulrLNfQzY3zXkrLXXN94qbYf QiWW0EUcf/IHb8kZerQAYE+6o+hh/IuD1T9mWJ42ueEigd6kCdK40gBL 7ytzAg==
+; resign=20460416024207
+155r.subtree2. 86400 IN A 192.0.2.1
+155r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . gG82211egHdWycQMwsz6FtX2DrYeuaQ8mS0VCek7UIaARUhhdTfA0eQI LlF7aTFfT6kzn9VuRvhRFkeA4rVrGH4BWu6f9TfEBiq2C/VnV7j4eyD/ IOo0lLvOlBJtOooQiQ7INEhTF3vCbboZQJntm/i609vZXQFlSljnBoia uTJkeGn+B5wqVjwuKPCGrInUGy1L441B3ZV/eA3sxbNQXC+5PMf333zU N3puDUfMl6BAF307t9tBcv3LeDB063dER5uZkYHvmQilddssX5yL4jRd KR1VJ8Gb2NAQ+js0KsZ9M5/7yfIEQCmG2qHmsx/bz3niuHC8YCKSJPdn K0lAcA==
+; resign=20460416024207
+155r.subtree2. 86400 IN NSEC 156r.subtree2. A RRSIG NSEC
+155r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . UhDOIagmyaTiFRApGFkIYoKtM9/GDCRDVu4bAjbQqfuayyFE8y49piro zN0Of62liFjV8DQl4iCQ4uh7ENCe+bCefnnwKzTHgu0noDJz06AZ03vG A8USwN/NDKPuvdplGTjTxDc+07obzc6jHfwgdIIrmLdJwYk+fEMY/1qu JY4sdh+MklPZmSKQeaW52Re0cqX06/ChupapJzqTTIxS7j102vBi5Xmu yEz7YQ+j6FL0zsmdzq3t/wW6alNBRzW0HHs05PdhmUClK/PMj4NhFUyG Le2VvtAipHfjw+LLWvAWaR/BJn5WslGTZ2mHfCDegAG7/K3f0Fs9onc3 o3jsdg==
+; resign=20460416024207
+156r.subtree2. 86400 IN A 192.0.2.1
+156r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . exFzVr+RoPKSjpAmZAm1ANj8d0Aiu34YGyKvQ5j/IBUYzE3Zlx/fl8mN ABwh6JXp5nQMoRanVwNBP0JY1GzTxsWXLAfwW5LjJq+t7m0o8jXQp/0M dI4uA+6r29dAqHM7VpWPVNQGDFv6hicM249LU7VhPfd0UODvSEQFqPD+ vLj51gT8ch/gw6B5OlfY+eOLQ7OedWRnmwSJQP5gDCKPxutpmapm/MKY YjcONphDXIX+OINVGfewkq+fqSrjbqE0HTlaQMpwCvjFzk54MzI8J41u 5VCWFwVcEWAzU2Q8tDPOqNen9vVph8ltTSznqAsNDR2Ifzn113uS+jUZ jwuZfA==
+; resign=20460416024207
+156r.subtree2. 86400 IN NSEC 157r.subtree2. A RRSIG NSEC
+156r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . FHLCW/aHphFiJgzIrRrox8/5Y6jsYrhCtc0S91UAI4XXLwnNx/fOhiuB K6+z5GAF2GQiXR5O1EusZrtr5Wprp1vYOYaAZ8bzR58fgvvWAqie2FrU iinDTzDiS2dg5UDlJGts2P4kGc3XJq745EbpQSsicsELD0+XCHREv7vD 4AfohzG+RhZ2iGl+kBbsEaOPUY+3FmSShvmyjy1jq3dAcN0ygS/vHFmD ZHomYG6E7eFnWYB08cHOI2BFheyiDwTHoA7hXmxvMeK6yw9e7XoCGIf4 rliOKjRHabC/Q47kkegKUJYJvVWelvcCjTjF1BIEYQlcFQcmt1RMF41t iA4s6A==
+; resign=20460416024207
+157r.subtree2. 86400 IN A 192.0.2.1
+157r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . LqqdNvo9e+TrHcQFlW+GBbCcheSlWqNwfOhNH158MwhitwaFAdnVOTT5 N6KKCOGX/KzFmYWLBtI24agapHop0lei/wE+5UZkGTRM2OmDHm3rx8JR kHrhhmlPaNfvPl4xPKy+G/o3ddOaKAEsqW6FMTO6F/8AAKvQ6qmxBvBa lJFtz1YQMXnxIgzqfColBenWKroKlxOGW4WvdUTsfrGHCAl7daegoBuO LHp8b/3Okwz1Khm1USCp/G29H/bA4TFZ2AYJHFSsdZdrUSJGycQh+tdL DEx5Maw5pVRBP0sO4gha9VTL3+tEvCMVMeiojM3YuTuUhBUvQXwchbgE q/UoRw==
+; resign=20460416024207
+157r.subtree2. 86400 IN NSEC 158r.subtree2. A RRSIG NSEC
+157r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . fNbdH5MpGI4J7hSnqnNAVKG5WSCvRXQHZotkNbEQwShjwjgXkt9xx8OU fob5B8NKwpG3/+QADxCZRN4krLNCb13idukKvJ5I5w2GofTU/4gRz9fn kX7U6Af80+k1Uxo0APhaXD7d8HOagTg/vIXNmaEcgkNQpw7W0Ve82e3+ +y7g1Z/Z5Q62aHCHi+P4kTO9fCYmmeQ+usGeKdTu4S3LSwNb4xd77stl 4Kl8H4KnRaMZwpJqBBeZx8QDGh+yu0YfV4RTt5GG5MimOyO1hDkaO8QX bGwUYPEL7otH0HKv6EAKSZrX93UArwljjWKSOeK2pbaGJmlaVffwRpGY 10yZjg==
+; resign=20460416024207
+158r.subtree2. 86400 IN A 192.0.2.1
+158r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . GXms668xIDKeVeM6+2Fm/8TaRDcrZivaDUQvTtDjlbhB05fABVPpwUCV MSc27hvyxnVvAro8KgZuXrDUCvIVySR34c1hZRXeOt2U3BTLTHDlUdtg 9FBYobe0Rv4jrdueQXeTGgN1JrtAE3ujQwrFscebgckWC7ZqIOIH7OKw gCuvPZUdJFsy206TNEUjiTbZbNx6uHkvH8EfPI6qQektSTDvzDgBmaMD 33a7xIOAANmImj9KOKx00XeG8iokTKmEr3/B04UA2ToPf4BK+HVNjTwD TY06VSpfe1rA2eYLSX1dD6x4vjomrb7O5fmCQRM53OnvEyP2rRWYAdgt U5gFgg==
+; resign=20460416024207
+158r.subtree2. 86400 IN NSEC 159r.subtree2. A RRSIG NSEC
+158r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Y8OI/fj5Ld8cr0vH5iv7l+0nX2faZoWoUBb+M0MMPorCJ8mX5K9MAxSg Pr2pPThIIbvX8oEvJl/1TwkEKxZXcdBXNje0vMoNjEJpgnRvKPgbuvrV aTw9gxh+M0Mde+nWnMZBvhwVmDPrtfIc7Pkbj2LhzENNzaLbOckQFT3D 4uK1Pv0ikgdMiA5m8Pi3kD+vF9wd4HaDio5Vfjggt0jrBHQ9Iw2s5bdQ dloEmcumOAD+r1c5ut690r9TrK1nAbgqNykg9QtxIU/rWQa2CQy/UrcA s9khzM0pxu0QbFNJ4Z3XCqpoS1X7Hctb8iaPYMhzdwmsrUg1PQ7Ay85O hHVTrw==
+; resign=20460416024207
+159r.subtree2. 86400 IN A 192.0.2.1
+159r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . HegookV2cV09h+mzSBG9UJZ0LbH/MtVnYfnHFKmSgebBi9K6ZZ3/926o sBYj9LrBRJgcsGh1l6h11uXN91cJfSFGfhQs2M7Ak4PYlz4LiV9GTIfa fJTz3kNWs4bu0ljx+heIwo6+2XF39y1rrMLPrrNDB6FYmbs6QKVZxPc+ MUEsorETFz0g++XsunkrtyV8YzNZPrfN8OYa3gmh1oxoBdoHDKe2/+g3 dR+GRHOHDHkqCeleuLUXQ+VN6lxN+CwZwuFqpG1dCDaBIMd0Y3dm0S57 D7txrPaO0qLZjXoe68r8AlgCEJX0+j+R+VEt2SmtLSj9zvxAWU3vxXXi ah73xw==
+; resign=20460416024207
+159r.subtree2. 86400 IN NSEC 15r.subtree2. A RRSIG NSEC
+159r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . bCW3CfR3gNTSI7PV1vTJZEqklFffX7Sd8SBaPVtdadTnD+G/hvpKz0qC na+aljGCxHX8qCrs5l9i+RJ5ppC+rTdf4gWS8D2Z0FK9xFvXELvjou2Z hfFmyOXwhsSejVLpPGhbbQe7Hc2zBrShIWRjNRfBbMC7DfpBVY6c26l3 7DpzSltrzJ+hs0wNlCa7fd1Mp2dMuAIf4zIVPNID89+LWNdOSPAmyev9 eeLvhvl+bCbV+JKsEFY+mBhH88iLnj0NX85+s9kUK0vnXbf7sSIolq4u 6m725ur/k3nNFTqg7F7pxd15Pa1LLwooDVgFGfCNRUvY0ScdhdklbTzT fBUL3Q==
+; resign=20460416024207
+15r.subtree2. 86400 IN A 192.0.2.1
+15r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . IVVUyvogfv20mvIHVFB4Qh2sRM/R4AGiJWllTZDYa3hvF5iFfzOTzNpN GilwUSnQ2pg/iHhJhAFdOtz6usAvOrfQGlWCnqyKbKpDX2IVNTz04CBQ VpK/nShPRTyAbmuoqGmxcyx9BU0gXsUBJMDqTNxllv7ngVgiRAr29uf7 xzGQA/3Xf9d2g1cqoZx6yzoc/OGyu0WCd0RuhxYE4Z4qh5WPfJ3Lf2xf uDg8RGQ52+H3TZPlbbEIt7zr0HBxNzfsOjK3oVZB7ep4qfeH7QMtlBLJ HEpvY82aoVyq2pXCG0hRiCZyvUPPgXvGdrxoARAA2dLk6fkHzXnhn1kD SsKtPw==
+; resign=20460416024207
+15r.subtree2. 86400 IN NSEC 160r.subtree2. A RRSIG NSEC
+15r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . NfFA7jC6LmcZFCe7r0lggnG3N4GQhOgfreE4KBeqjzEaubmJm5iDJh/5 lDoFrQvrXzIO9XCjBpBiTKh4/TymmiApdJs5yEtFo70SwB9aDwwlBznj 9aNtwPYRfr20jfqScBRS5dn5IyLv19jOsFZJ1ke9utWeVh8zJenOMNC3 vWcZuoYwKPJx5uvTIkECABNtNac9ruA82+Uyeq8s3EoUCY8rcc7I3MRI ePRmvxP3ftF+kNZAmuw+2/5V3IKTLAo3BZ1KhlJ7WZw8eeI/AmpZD91J +LT91MzlYJ8XOu3xmBmBhtnRZnWkTgIGqihSrVo8jFQj/qhoYUl6WBDc PJdoEw==
+; resign=20460416024207
+143r.subtree2. 86400 IN A 192.0.2.1
+143r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . KXET0omXBGMO+1GiBQdhTrTZx2rExg2l1uNCNOlKbo0XxZLdBNKmG0iy VEtRDM4AhUfLQ+kDSNWJIQkBIhLESjOSp+2+oe+xBlWvgmXaYxWmZmjj jPYxdPtJoxGFI8xH4QGp8hjR9al+gGeM25Fsk3RvAzwQTVGnIP2aAv0o Zn5Qt7533ahGBuFITJxu6UCATY96EuSIiColKcmrcQ/JBF3eOcBSWyW0 Jr9TM+SYJNtLsbVP0ixjvfDv8jKPh66BkPo6GwyJQ/rb0AzSR7balPNR GVaYWHPcgkx4g6S4h/PvYspYiSulfJ1JywTSDTXptzpOJgH/SVwwRz0o PIqGVg==
+; resign=20460416024207
+143r.subtree2. 86400 IN NSEC 144r.subtree2. A RRSIG NSEC
+143r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . t2j1ZAGhbldo2YnHOWPGBQR/xp3KjRqQtt683GTB0R1DePWatP4m0fyc HnwCk+1gqp7toWFip1s6M8df627pZJTAEehzjBY0KFsoFhfIYxUIO3ut jhbsoYr5N6CBRSDfpBCfHCQNc+Tv3IUQApP/4vbfxGVUIUf2r7rBQrnk WYOv5vEpU0TCm30bQBZVEoG8VUNY8mghazonDTHaqzc13ga6LSuv4Qib cpoJb90xj6QmOfxj/QB0KNaJ58BbM4JcJWOGDdwF8n8yRKFJbpr83EYL 28bgBI3yMp38ZkKjcUb9JDRj7YijWG+LF/nGT9VB9RvMFMz6Jt3D9GhR ISD5Qg==
+; resign=20460416024207
+161r.subtree2. 86400 IN A 192.0.2.1
+161r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . vlhrynsX4HUZcUpaYIUJEHnbofrhvlr6yAIa43KctslqB97zpfrZO+RO wg/z3HCXeylyUixDpXmYr8CMfKmARFbQtuBPJlDBhRpEi3V0QsqUjCFK FlK8VHfwwn6bF9eCPi9LRVdBRXSJj0ouT0mWrfg+yySBHZ/OBXtGIgA9 aCYvaBZPBVBG44TkuoDaJkRDP9asgc5CBOHX6V2FE6/iHYAe3VIE3bBQ cWBWH5IiBakzhJ9qRLIshEBNiGnXF8FEZLTZqc71FneY0+oL2gQ0cvyH RAoHeAMTJlqxDGd6jqyrHiC1yFTq8t8x0Q7Xyq11sV+QJu9TXZPoJv1S wlLUEA==
+; resign=20460416024207
+161r.subtree2. 86400 IN NSEC 162r.subtree2. A RRSIG NSEC
+161r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . EmhrDUGPlpEcrclo+ijJp8/ge5Em4gKy/5MmI7OcflL3ai/H5iSZdqGU n7+3eaM9gkFDQk6bDy5YnfvRZ+Z4LnhM3OYsDc/CjtpU5O7IaAjCneLV HuDuyqtWo6PZkBXRiE5013G30OZXNXOee+75aP+OBvHZxYUmQO5i61bu qhQ5bR4KOQ3/EALyBqTClbJHaYtrCZLL3D1CMK25zV6Oiybqaf85uUzU JpoEl11poqNhpbGvR5oWQUQl32GgtO5E9aMADkqM9vFPjTuG40wysV7s k1ehSfFajlN7sIibEIJaHSeYklMA4MdnoxZa25AErhlBqYfA5xsOMXj9 0ggkMg==
+; resign=20460416024207
+162r.subtree2. 86400 IN A 192.0.2.1
+162r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . KF/Dz/lWJfd94GoA9l7dI39358OyKmbPh5AU2FnmQah5UPIvMFzGer3E Is4KuzGgrpJ9mRnq6zb+OU1WWT/9uLVGks5F0nMldd0B+dIiA8jg6M8T vLz0RePiK0DloAvYb+4DKNGJXVfpgR5Hp4mKGRHaU/WifbG2m+LEN5k8 Bl4zw6a45IYygqBkFrXijamNjzuDgXQn8hl/D0Qmvp4GjqEQedjVVTu6 oFkYS1dClas6dgH4Pva2Q4bD6hoG5imtFnOBiDUc4PmhUQ2tIT+bunFM XzcnLocyOoJL8lFlp+qd7cM+bWO6ZgECTYQZTKVt4duvUZFF6PZ2a/uD q8vbDQ==
+; resign=20460416024207
+162r.subtree2. 86400 IN NSEC 163r.subtree2. A RRSIG NSEC
+162r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . S+jFQ8fn0f0qm7MQNk6YG3ySVgaFWO4syGDeGQ1DB2JwP5VwiCXu4yyd 0yDAH/L9DMIB4+cRenqaXAxk/XPLJvUaozJFhoD9TrhwQLLnvucOP8zU JKch0Ue0AqkVg9LhUbxSCU54ggB+nSnx/Ys+io17WDtksclnC7mum1LB y1ZC/k7OHToVSvyDfByGn2r3H1Q/7FInUM475v32BzjGq0wfHcScf0tS xZAfgGbYch/VbE624LpCXKHuS3J6L0RY4H0EgVI8nblmGPWRIDDWvBrS S0IQIWX7lxbL0PivCtoeNRE01WFum3GJ6bYD//aPKdJUkqzlhZ8c7Rfm skWoew==
+; resign=20460416024207
+163r.subtree2. 86400 IN A 192.0.2.1
+163r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ryyFupS/F9mcMBwD1aJjXDGjREl0TzemgsTAipvPW5lY3o7Mt3k6Jmxe MGsKtrSMXWoDtFzJFEjkiNG6gMGMaJ0RSgZUotJdGZru/wK/W8uk2oKk 5mYBlSgGjt175B9zSYBcn9rot6M+7UKCY+bT02r6xhH2ckBw3HFjs3Ht ZEhj4kawEp1EaynuKHHH20ZklVAQwUBuqbSmoS9/HTwU1nS3f6b6OMGN BesHOKn6jQlSmjDvJ+a6cj74Waql9RLEEKA6HaZzfCm/vUo2NyxWROQh IleeFtokoFEkX8vWoliQ+6xfx2yfVEJaajcW5JLyBc6VI+GUiRuy54VK E2jFOw==
+; resign=20460416024207
+163r.subtree2. 86400 IN NSEC 164r.subtree2. A RRSIG NSEC
+163r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . lBd/dCiwqanWqm2GC3Jc2C3b4r6gsydAabLOjgrkZE2MyxhJofsxKl4b 2TBN4094x+OdNV7TvYmE3i+/rWJKMbGdPFyZNfn4naJBKvCyqgqT+z3p 7XdOzVfpQ7xWCG3RKRymbGWZuarPvaEHLLscOh5WVG3l2hJ24zfYmTQi 3sOtL7S8Y9BbmdziWHcclEKB3CFrrhiC9AhPLPzcuiP69kNZ/G41Zgl4 c8CRNck6S2OqQr/sysZVBVkfygfw6epX6KLfOrXh79Ouwp6IrpG90Sam a3g9OjHEduivMnQ7GjKPZo4xTmwtF8WqWlOo21tEW08BZG3Gb+hHlVS4 6K5JAw==
+; resign=20460416024207
+164r.subtree2. 86400 IN A 192.0.2.1
+164r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . TllI/FXJAkY746MaD3p6Zk+iJg6U05nR1USTnI4Gb/IcIJuP+W9X/ng8 e59kvV/wwH5qBBa637HBOWIsop2aneKobs3Dlg1rFuCVwgFIpjF3Lm7W jADJvNKmp+sds3kk9tCCsQ515lxtQKCr17+FhPV/qtsZHG1A/h6apCoF jYCGgyr/00b/cIPpn7SYLOfjKYx3LW1UZE+Ap1izUYzYkmXRcSY7EEbs C4Dok8Nxu2d+5rnV95mbMJ568RWyFpPiaGYLgf81mOLXQKy7zf4LERh3 /gTzA+RxxBgIV8xAj5OWoCxUe3fdApDFkHisAWc+7ybqskXTyvDHeW/V /npJRg==
+; resign=20460416024207
+164r.subtree2. 86400 IN NSEC 165r.subtree2. A RRSIG NSEC
+164r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . jl4i1uRBqCLOuG+nVhWrEVdqO2COoP4+1IwxGeYuwUogG6qaJfF1iPZQ DZx1cfl5OcyfCKSB4mvQcueU/9vpkHzHKAHmhQ1Qeu9/yKI8du/fizi+ xRsMljgrKWcAjCSrUwIlwghni1fMI8hUQeyQSEGpAl2X3KGQlNik2ijz q+yEIz56/kSNk9vb7gwT2MrFMCA5IRvHZbMXnmAQ9dSwvsdvMtFfWxv5 JKadYIgEw2LD8Wh6kmmR67l9wdzvh42ry+alKsjjsDD00v4wcDDasII2 HkVguKEFYhFQYiS4/Ww1H65cLcfk5jiyepLyzBUIcp/BesXJbcDq9A49 qfjFdw==
+; resign=20460416024207
+165r.subtree2. 86400 IN A 192.0.2.1
+165r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . XJq6gK7VZWwLlks73ujiv54rlxPRSavX6v8vI8BzE+DjgJKcnxmvMkuU thYSazPEq0awGUjDFthHXpRCzpn2KhKaOS/G5HfQmQ/IJpfv68usCpdF UQ2I0MXOb8vbawlG+v+F3BhKBH7eEK3M4tS+TLYK371n/v+PUfC8kmYj cR8LIH3TuHpUlIZenSv5gHJNs04ds+U0wpguOWi+Av2PZSuKMBD401s+ BaRSRe9B7l/eW7ZejuDB3NtIaxZuo4K3rlzBhI+FDKvLkTqUcYlnuKQ7 SANBCV3Bns9tb3vdze5gymVDpxjgbe+18JrZsznknNesmB3bmRpgEjrK fm011A==
+; resign=20460416024207
+165r.subtree2. 86400 IN NSEC 166r.subtree2. A RRSIG NSEC
+165r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . jLZzn94eAVa0f8gv+Vc13Q6qfYVnZIX6fU4YO7EtazZblPBbxT+zbdGn xNwlgMP57ulAgC4sPt5UwbDO25ulI+oUghsjDwUpvLyPtNF4KBqkj/Pt M1B37i387C/jrlMW/RLdW51E/qV60yHqmJdi/3rW46ybieYohFy7ql76 DTh2qfuOJGxTem/cBhtX5HlpRGDc/5+W+B7DtoxGyMFAX14qmjv9qjfG VzNXS5dCrxOo3JwfrKyIoI75oFTQhAj3gvUgpIAlNr1l0D5/+v/0XvA7 0ljGjLEgKTxR0yinJDwC4YM3PFT22ErsgE8lQw+jmEuGS4LNk8vs9O5G dmv4MA==
+; resign=20460416024207
+166r.subtree2. 86400 IN A 192.0.2.1
+166r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . gajJKxjgPg8BynOCkYsDhGTUZgXw58UR2cmtf2poKlsQcZEuCmznQIIX Y2lYKrggKMfljx6QUCfUh7y9G8RP0G5pE+//U9VuGdhoN3K0eaGhS1ti yTrFN1eO9ZHPpCBfAR6F4r8d5AsEFqDtXqJjvc2BsqaO5wHyF9pcUWWQ d3hdCgXYU7jGtGydEipIjDLmwMk00ab+it0N7fJOehkcfY0GzPyOGhP/ Ix1WhV+7PsMMevKoUYCMTo4k3ligZf5v9dOZ83OKJwRaJGpODSJhv7bP 6/KBHZf/iM8OWONfbynh8AsARuXQ1jJmy7tvwBXqGCs5EeCugDvXgupV 5GKBuA==
+; resign=20460416024207
+166r.subtree2. 86400 IN NSEC 167r.subtree2. A RRSIG NSEC
+166r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . oGhGxYrHGq0KwOvD0GJ39nK3n349p5PJwh1nc74njLxdSIK8dU9ohOqA +0MebFwkUgEI7gmv5YGsN6QQVFh/Cp/hxFR9sNcS65csNann4sH82Tto uXVEsNWgX7da+64CUvBYDeVPN5isUFoyApQMMohKWJPvDeR2Bs7ZEEY+ MJHbsFICYv2vh69a7yYXdQsVTRsVisWYkXQpyip8uhus5K3pLt1YsfPE 72lWzWHN+bQKEtOysHPCb3ioXDBSJMmS8G07n8bRcbCWB3qfe6LwAwzv HkhQP5rU7KLNPgVOHkHnLE1qTzhi6m4JtivDPvHhC8FMIFYjmXFnd0GL jW+Kyw==
+; resign=20460416024207
+167r.subtree2. 86400 IN A 192.0.2.1
+167r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . wclhILl4EoyJtbRXmxS31p52DjE8pzCVUyJS5TVcCSb6otcVJfabgonj A1YIPPE12usQoHq2yomquQEBB4t7pY1m3WMrp5zW88d0nwq7orbb5FgO iz9vgqsDsxnFbqnLNidDZTiWEhUiHVhvAfBhosdQwggnGM5f4J6b14eg 1QMbca/DOieXPRyHs7wUBza7RsYZWhMUqlRRjvVPxBlgFqck9lziz1j3 hOi8aZUfsiO8GGeOhj2smgR9hOBxqHxJscEYGD3t3oTSl1fP9gVuDKFc myOKmWJM3c6UrREEyzLWz+7SuNh/CbhCKLTh9I0H178nkiQk9EJa4ywI QugAKw==
+; resign=20460416024207
+167r.subtree2. 86400 IN NSEC 168r.subtree2. A RRSIG NSEC
+167r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . tFwQlrO7Nqpu3vU8jn9WXP5NdG6wC3IXY2tfLxRQELqpjRAXEBm/drRH s1MS+dNyF0F0lLucmtl9j2+Iu6h0hkXIIJIKWE3zbCAmYeQ3dQ8JJH/J Hg7gHBv7uqagkTFVrV94LJvaYcFkZBLHrPe0/2vOePO55q/AIvoXkegV A3gHXfOlktFEGRtXw1W4aN48jw8qZ5dLleaRS2k3S1ePInlyAwgNbpSf VDhIKbhucFodupo9MFWJ5NKfSI9NvwH9yl9G9pMeEPJTw/wIZ0oCW5EH LmTysBH1EMxkGW/FVPpD4BEkYn6ImEfdVj+z+b5aLU74N/GbB/qn9Q+T S56g3Q==
+; resign=20460416024207
+137r.subtree2. 86400 IN A 192.0.2.1
+137r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . am8+/B8ro58VTybls4aXEJuIZOJRkorAVvNIAAnoYsHJj0hrIYrZ2VmV hypJR3AOc1AXVEoEPCsTcCaDGGWI+7dnr10QTT2lq877DovzXc2WefJi 3kB90YlmMnz8t+k0GOg0iNby3iGlUT27+RSJXZ/vTjkMho92sVL6sZiq yb8nTkpC7ioZ2+so57bWch54MeX6QxN1Is9sCRqrbAFFNnW/pCFq/cYM 4qVFius3WxlURI5NXyLmfWI2ed8CwE/qUIg/GnBGb9mOFbQyYrDLc58z lIpxXvPHXyJqd4JxdG6aVfdz262ZduFlrjhhvwNo+pO160uo5qEHSWwD ZCDtjQ==
+; resign=20460416024207
+137r.subtree2. 86400 IN NSEC 138r.subtree2. A RRSIG NSEC
+137r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Jbck/tyncGC0gkLR5c+N9WcR89t9ac9/xqqPdEQAdVHWDG4VItrikPI2 l3eGysPahtWA1+f7D94yJOng7sSbNWtEUdy6b4EZeOnQFh3YAKyntbIV 6grW/iZcrOP9mvX2cSlSokp+p+1tpv904mAlQ7+X7IM+4+ty22qWYgOR FYy6SeL5v8El8H1AU/ZFNCg+4zd7S4u4LOrxZqzDaQasKI/TDhbFSqNN vdc04thKMDGPhlp55MIBr8xWiG8TCpfExNMuge2VyJJwAAMHmczBB58C 2gB5VTgSgF5IEfZlhIOAyVcuN/UIQ/3s0NXWHDuCdoXUuli+jj6PcUVg sykt7g==
+; resign=20460416024207
+168r.subtree2. 86400 IN A 192.0.2.1
+168r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . XKYTQRQKJOYcN6HxS2q7mfUafsa9CPbT9Gfiw9iIL+a2ITwsSys+btaV xcvZzA5Nz+WH/rH7oO0od4NsBVz4pbdDlYwWNBQFmCwF8C9bK/A6LKH8 IGM94cIhp+h0z59pQASHDLckP0d2VCCNf78dCeXkd8X2cSWBoy+9liav l6KUfkxUrQermCyFw0HGRyFYD30/qPFM7AL2fAcWcWO55/YHz9CCkK+W 6kFY8c1vCg6YRnsJ4s1af4YtkgPuQpc4KeMVvERYdzoeQKe07JOQ93KK Z5uthbXXwBvIbTY4cX7I3P4aMJUWiivlvdqkva8AiykfrmEyzayX1swu OQDQYg==
+; resign=20460416024207
+168r.subtree2. 86400 IN NSEC 169r.subtree2. A RRSIG NSEC
+168r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . a4ct19ypRywi4oy0h4lxjgOV8ITjyKBSOOyx9DJXYDfE8Ncs1yp6xzRi vI+/2oyMim94OarZ2Wn21GC920//ZtYKWTvVjl/7EWLjhCSPE1DqfQuC SrWnx+OMUbvRwdk7RLIO67gVbDG0CHS0BWW2uPbflKO1oZacb5l9C+9q wyg660XowU8QN8MPXjvg/tEJgJ8quWetSPmvl/sGS0PnK8D+IQZtavwr H5r2n7cvPjrHyIQlkCrr3outwr8LoDs3tZrRKaI1P6Gxv762z1Uzbmlu X0bpbe+plnneMY8vaKSOkSHrI03fSKgpFoxqfdS16DrX3S8S92R7Q3Tr Ec/KKQ==
+; resign=20460416024207
+145r.subtree2. 86400 IN A 192.0.2.1
+145r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Md3iiSliQq/6iYPsTtnWxvD6fnvDE668mCKL7aV490Ni3sqD9WSkXLC3 ph6zvb2QqZP8ekVoYQOHVnl0IwsDc9DPdWp5evjU4c2HnS9gIQ89keEL QcjP6aoUxL1N0VGyBBSdD1W0/jrcX3L/B9LykoVNyUfVLq3l9UMTGC0X d2LUwsDEPOwKRFt9pb8or/RXT3TieRAyaIGzE0boPqT5oHZ5o41ycsJD qPEhvFaz/Uo4QxYHAQ4/aobB4jn5N9mOGzopVf5EGv6EAt5UxR9PRY9d 5M7wngfrQQd627Kep5BOW32/zMmYuaT6TGkK9s5SdxHVP9SwgNx/xVWq tpcp6g==
+; resign=20460416024207
+145r.subtree2. 86400 IN NSEC 146r.subtree2. A RRSIG NSEC
+145r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . A7MVtDlGXMJG/qZa41htXBV3f7Nd5Dm7VNnuHi8R3rB06wUOddv/vNxL ZayYNiBe/yEiRfyQoY3sTP4YGfEvn8rr64q8+qIhVNQOzyxreQi5j07e lbjn4Pxd7Yj8BlQA4Pq9Kh/Gf3N85yaSXQEz52laU8DPS8t/LyEZFSRp Iq82toLyt+owNCGREyzfN4tpz+XYNqC4gNYOGYYWeGg/1OZCqcc/dp3o KEj6RHzkUFXsL9K5/SBXRlwjLYV1sti/HvKi5ydcqEC+9/CMva/xzo+Z MfMCjuSaoMKpkLMIa6gsQ32+wuqzo93+yL29ERIXm12MqXTeUxWPr4UF bLhGig==
+; resign=20460416024207
+16r.subtree2. 86400 IN A 192.0.2.1
+16r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . G4AP9+de7xsMvRzowfWmGOaCekdxocWnfuG/VJTEnC0/JB5zXwYGWG1f asn03gvGoVatG9lL5XAvHuML/ceZA7nx7/6A15maAXBsaNhgk8XFav2O h+s2XX0KoQtPliODw0VmwkwWweni/KNTNRCTr0P23dYp6w4jMv6BEIgi PB61Brz0jncB+HTri6VOLMQ3iFPXkEqDscsxjzTKoGxP5NBYoCnb/WJx RzZerXTUyNGS7hHCAqCU5GdJvZ23ZK9flyeDfguOr+1CtiPGaCguEeyY 3irZOasoidv0Nzh8EWEZBHyaqE5ungmOnXFpZ1OIsBcmpvEJK7C6gHUR Kbgqxg==
+; resign=20460416024207
+16r.subtree2. 86400 IN NSEC 170r.subtree2. A RRSIG NSEC
+16r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Dxz4qBOcfOFrkjBahDF6DRVp/ZVBRs3PhONIr1abspr4oO1Mw5qsoTlO XB6T/S0W00xNqYS+hkbw/NbrXs+Wdxt3EyDDaPBj9UQmaVKpLVarAOPb uVPU3Bh903HjVNokRew1FQokt21MQNvf+3TA7oJhJO+r2jNYW6JPQ2DA lPzuVo7PLvF6aKyR0R1Q4IiCeG9u2r/TwE4cijzCF1Ks4nNDQQgRnf0z dKL+afAkZ3IGZaktGsVvhQbfYS4QK9HSq+O9rwC9KWHcmOptETlaWE4N mlgdf2PaEvdvkXh5P0P6X9lTsJ5v7jt7dRyY5JulCTf+3qxq2GQTiZKV lSJvVw==
+; resign=20460416024207
+170r.subtree2. 86400 IN A 192.0.2.1
+170r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . tWZDCsmC7lCG9c69zyDtiK253sdW5uB8sUg4ZAhCwqzXeOnja7fHd1Hw 6LXdF/BZAr+1TfWF1G2zlCZt2HgO2/ulc00ae7r9Gg0Lmc9xHwvrYUjW KkxCvlzB28xUytRHGLBjagYdIdQe4+O6GFUdpWm9UmfLhlZYySV9Q5Zk 7iJfNhRHEqALJxC/TB/mYBVapc8mODZUwvRVzxWJGoxzPYhdEQ/SsISj MrP91NojvPBeh3MnzPfTFwFIqmbTG1iNje6oY2JM4uFVchufF3jBRvBx HNkMb4IkdE4xCZdLKSZgtyG5drb/FuFi8u0GpaaJX9/PiojPbpFsoIXN Z5vbpg==
+; resign=20460416024207
+170r.subtree2. 86400 IN NSEC 171r.subtree2. A RRSIG NSEC
+170r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . B1GDYFzFdnB8bsoPCM16C3A4ij4kL7Ohc8AUXmgUnoPdowdAxU7+LiI6 lJqc75i9v/1Q3VfNMT9ztnk0S+XoopsjdGmU0+uj7pMGw9jroF8k6Q+7 Icjh5J5zlU7Z61N/P1qsgr3nLYI9ehaY35BBxPPYmHD6+tikAyUVTliO bk13vLSVM6h/hJKZo9WZ+lIiWtvonXcgST0nr20cahGjPw0t3xk7N7H0 yxwVqDTW6ZWREhQhXQmRJeaRieF0YSXs3TWpRjaNDOmA6/R5tIasCSPo ka1TAvAQsJLS1zGhyCBbtfTy+RzpZX5AFXA84JMx8sztR1KABJmyr5yL wjXPHQ==
+; resign=20460416024207
+171r.subtree2. 86400 IN A 192.0.2.1
+171r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Px653LHulvqO8jOFEtBfBo7HOueJqdazMo0RyrGcGcJkeg/n+jfjisHK q1gQbBmbHSA6haP9kQ1vnNFrUgOfnpapB3IBHD07XxVE5arDlKzq4ibV 8+6FONagFSljXPBpLDS8e7b12IN54LhtJW53D8dnyGiyvIbnHMz8QkLj zfhG2kTVIsRPGTAiBHZ0tlH9P4y2HEcUba/Zjr15cnXwMWMY6IUur8Nr QrfwS/LFwoTFEa5NRJCAZB4Iqf+dzL1id2wlWWei7aRXUvqBEtWD8l3u ILQB+UZYUJaStVLgYd+ygvDhLukhRpQFryj5QcAnAXVf9vDQrze5ZXV8 myUJ8g==
+; resign=20460416024207
+171r.subtree2. 86400 IN NSEC 172r.subtree2. A RRSIG NSEC
+171r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . vW2qpOg6NUTT+BrwaXYqbtvgpY74qo1RWHkC0yN7eRILMu60O9cAowxP aenIu7c+7O4xtRumUOhH0P5K2XWdUtNvaA/jlKcwo8WoecaW7lagRj1P 0jz27/rtW7Mlr1lk5srSWFm1UopvGdAFw+3W4u0mvq6zukArkvDPvCVu UvGuFcHaXj7YLGxfWY7PNgs6gccQSapbmAgKkzc5EaJSzeY1kKzh1zXe tE1RFORiuiKNrDUBlaVm3UDABR6Q6566m7SrutnvhSDgOsbdMP6YKR9a oZtKwgcaSDdH9pJZSGttyR/Tdav9emt1hfh9Ty10VXEciKAJYUux/Uer EvVDxg==
+; resign=20460416024207
+172r.subtree2. 86400 IN A 192.0.2.1
+172r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . hbRpeJkC2TvCOHEBZsddt+NkbOjrzvKuUCD9u5n0wpXl6JhwMVXYkGuj CXIMEk6ytNNJRDCGtkrEtWdr4Ou2XROX3LY6t2R1vl2828n0hLpfSJk2 aJgyLb/9UO3LFb6l7BNHFWluQW/Ap2OgqQjY49BsoFS/ltYWqwRmyU44 bVyFyUUBuMGSXP4xtMw5sCCAHZz4ReCaJ7is0BH/vlLVwv70CYyXddAO Ak4ibfjX7drnWfZQ0D7ysHkAkFbeg7ryEWhAimQlykn7TTK5wsv/O72j 3r0xO/oI4LBupMgORamWuewuaNxk9zYoeMsfb2px5GZoUNwKhJPCnCta BYgsIQ==
+; resign=20460416024207
+172r.subtree2. 86400 IN NSEC 173r.subtree2. A RRSIG NSEC
+172r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . v/sTxRVW2njY0M0JGbSnnDQAW/o2G0z3YkdSKHFUJbsBGwC5eFzdbmE3 uLnQCfu9nXNv/DS1OZGcxjgNwcpZgrZ42MHn/QjcazQHlUEjvFUg1vEe nubJVc091esJ9NUS9+RPdYtGCHUXAwT0PerfCrW2l7JDSJuL2PIVrnvT DhNBKGH9hBlYtd0tRwYHGCSjk8G5ptAWjfQCwS1lrcVrF4EPAfxRya++ CXwivLvmPVoAMM946F0dPh0BSq2iF5BTEUNhNFroDg2XPsMUDm0eCoZD H4ByK01fNR0FiUUPuNYyC3aaFi8HQ3uhKjTQuA5p5F0VT50TTfFiBQas cUzswA==
+; resign=20460416024207
+173r.subtree2. 86400 IN A 192.0.2.1
+173r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . guKL6dmbL2dBabs2B/mMtO5qZ0LNyZbzdZ3i2zM/2AA3ipz9LhIPnhwb KiO5LY04IUboeV6d1q/QYJJvVWpZGVmosS8N232HK8+2/LYD0NoGZTlI QhYOC948qMmfnBbEaXfWQ9pyAvkmLgJAwQRi/Ei7x7DC8xx66R/ibF8t xcp45wcH4PMJNCxE1lNSmHLu5ZWzf+hKHo4H3w7Gof8LiuVZOEBXVs4/ j5yeExAILi+vXAnvOuNB2+6TbiLgVUOrj7ixoEaK9rvmhcAv6HeipPoW TbUjt4oGmeE7Zmro9rCPblHeEp07HAXdKyDfkRj0M9NRHedW1tLTamLi Yd/yxg==
+; resign=20460416024207
+173r.subtree2. 86400 IN NSEC 174r.subtree2. A RRSIG NSEC
+173r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . qgYaLUdwBspbKvhBBLxy7ieuMvegHlw3eYH250W+pmMyJHs9UGQq/Yv8 Ic13KxjYjkDai1fxwJjbZIvNQbFfXg+Fb0ZapVG6O0FtksnN6arKMfgh oXkhwSlp/xUBFHiVUAoSgPQHGhv+OmuNOQvomIuvWq0kBEFYnr2pYT3Y NTnEtf16t5Cw38t1T/WfepZeeqG9uNCJxXy6L6ALIQvoHy8nNjq+1n+/ nc1oee7Hf/zlKeirFMZKV5CuVlkjwC/n++JZN/LA77vew8uXk7jfDUpm taFXNclFyZHdWs3Wle3OTp9DMfIYx9AwiZGGjEW55VzyB2r7Kf5E9n5z Gz/UMQ==
+; resign=20460416024207
+174r.subtree2. 86400 IN A 192.0.2.1
+174r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . mpdvu0jUL9Zw2Na2Mm2Rh/D7elKhYU70IEwJokldQG1MjGz+uWA40EyE cfgrPF6NUQWIaOn8s0/zwwpXZ7tUZgUMpsaYTt8mHLgthPa4KoH4GuM2 bEZvtivUkmrMAEHk+hKt135f4COXeYynKYNnqs2tSoKQKcPVtWEqTnzo 66HG2B52C4xEQCkt/ZcmHpblUPyvz1WPx91oCOs6DNdUBKe5Txwp0Oks 2qTlEmXUPuPRI6vxG3HvxspkiVhEmOPSV+mds/A+hWSj8Vjg6rMSgloa 6d2hpDccnh4z9wifIcI/BtDV8hyV6cCu2eBw6asUzHDaVFHA21iTmT4S U+8Pbg==
+; resign=20460416024207
+174r.subtree2. 86400 IN NSEC 175r.subtree2. A RRSIG NSEC
+174r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . jM8a2D3Vs2ov8hKGWdijThYZx1fTS+0NGNUQP8Qp1+gSQ5GOJh6jvqGf 5RA0VDkg4wPozglhkJlnxcP/OrMU6A1Q4pC5VxBbYjWhZW7QjqW/E5AP coCpR72TbJh83DKNnSf+nYcA+Bp+FNjxFppVwwSaFIvEQi+NJqAqyn55 pjq/OXlZJ0IfxYlHxtSYeNeYAWfKRj5o70GNCJDSkrfVC6WgZatX/UlU EcuhzQ50GV+O37tTOTWf6JMhxlU3yGhMpXMkhVK2sO0p8H32ZXiDPD8Z ufaMrAORHbmGdRaZA3tQe1eyHAJxidKONX74/YfIJlB46mKPUKS2QHi3 w8xANw==
+; resign=20460416024207
+175r.subtree2. 86400 IN A 192.0.2.1
+175r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . utjEa8lBcuP5lS+jGFix4ZzVposyVZLmUFeeQsZwtwqMI32KQ0affOl9 fvid2qo8FlSmOwwB9RhZaAH/q3LD95clwvOrkROxGmOPuMeoCGo5d1jH S59+314ROpaiNyA/CC+Gt60wc+v8n9tZmhVAKKAhlE96PARCRG274bBh s7wc/W7Ip2V2aolDHUQst+rTlE7VfsC5OgzRBYe68ChrUu8F1ahpxytu EkBvfClukGDGWxpckG434mEfPVHcJL5QsorB8tDkWcSo41igSLDl6UMo 55/tXqQKS/KyNZ6+OE42tunoQSpVFXH2hUKpEra7cv8teuWmGTYHJn4p Dp7qhg==
+; resign=20460416024207
+175r.subtree2. 86400 IN NSEC 176r.subtree2. A RRSIG NSEC
+175r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . u/JMoUNzUyurSpl/q2TgTl/enDjpWoL2AqkCaKePgxaBNbyyokLUPxTR O2LRjFWEAo4gQtX2UAM+wfAKOmKioTjlSg/y0J3FAWnJUwguhjVZTSUY /vtUmI/xrBEG7eIezzIB7ibJqTwDQf+AV6Z5PPsl9yuT0t4hz1biraGM o/axt4o7nkoo53drcP5CnZ60RVkrJi2X32DDizzw3C0aCrMM1egggE5d /H26v8wUiFU1OVrNY+oW2OWB6UNNl0J/vwoRY9++uKzSE2janv2eRr68 Auz/RWlBgicvvjqKJX5dYR9C2j01IYdPzwGksLHFdMguWWFBDdyHlYbW u/FH/g==
+; resign=20460416024207
+176r.subtree2. 86400 IN A 192.0.2.1
+176r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . uaZHB8CPM6Qj8LeU0Uze9bf2AReNgfwt1MmkZ3u7i7HGrztentHGQrmY ONo6zKAUiL8ZCejno4aIPD1ma+PqFoeUWxh0QNA7hPQbQ9yjlBxUfhh2 3OkRfN1AKx7NWsCZ/F4nVro/VjF03GZFg89FqEt8cRHZvzE8EvlU7xVb YZu0f6CRL2/SIz3MWODZhJYpurQpuGi62G8LhCCmeaTYJb3EdXo3Rsmg SnhTGK1atKuawNAtwuTQgUD7Z0iUnUCEkaTtUGLuhs5qmhF37erjJWlj vuWCwEDWpftzXTQijxj7Rg30WE6iI/VB174xd6NpyxG7DZ/2HdOx9CM6 73Lwbw==
+; resign=20460416024207
+176r.subtree2. 86400 IN NSEC 177r.subtree2. A RRSIG NSEC
+176r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . AUDXf4nZuDxYVZHFkcegqpTtb0KfqdtlWBDu1i1IGwi5HID+7tSuPgzU 1mnKSMjT7CfgMzEDWL7R9i/aF5+f8OjwLo1J9EVxBvLyl8zXoojy7SvS ix7HHuoJIr4hkCLSA4YAdkVq1OeIEiH3cZMEsPSBopi55jcc+Ixbln+h XowJok5Q/cV0mT5PD95XScGLhFUKqV6B9DR+5ptltU63sgPkdEhXp31h +ywApZcqxRCWIaJ5bSUNeycLpNTmBmupDwNzFvgPmI2tufRQPKkwNeC5 7AVtfd9Y2uKKSgSakhdiIJ+lcOPNfoF+53V4i/u5CKvn/VylJp9mXNJu hIebEg==
+; resign=20460416024207
+177r.subtree2. 86400 IN A 192.0.2.1
+177r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . UxCDSPBVRcEDyJMsTe1B5Wj3i0B4ppCNpIutplRGK1TcWlCoaoZYKb7n 78C3wXFiICE1lbj4cnHTeqSKLnUTxI5XEL832lRZmu5qUR9W8nhcSxfs YzdmtMx1VOwcZAo25NM+0883J2hXkveuV3GjtkSvaZ2W1zqMARVi0dDQ z9RT83gHjwLEmL9zPbpSdmj0OOddw15qOQNmXEUJJzZzaIPMaWpkpQIZ pU5peA6EBti4LI/902HEzJeydwZdrMa89FCL6J/UIoxUYHrXIugsZkcE ptptgPQaW5WNizfKYqanNhN9JX/t+/u8JMM1mIk1zIejiwuKtpZpj3mQ WPeNFw==
+; resign=20460416024207
+177r.subtree2. 86400 IN NSEC 178r.subtree2. A RRSIG NSEC
+177r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . gZTPyJ00JsyjTV3HsyTnB5279LPKJIibVKXDdEwU5148kvBte/nxxN3F Df5x0mPXbuERbWv+DJ/9/7vZNFkXt6EDkU7Ec8JAdGtj2/HImn3TfNvh 131hgK2h0ynNlsLnLRncJqe3gs8CXXQur181y5gQs5fAKrWsVQByLINb tTUDtLOffOvP5520CmE2Aw2u4JBkxAXQOqX0wAHcEXKS9XhhJv0IqVJS 4UxYM7TefGTFq3uvYKdIR4FTGcRE+liwpl4yOIITQ+24ik9bQcyMikVc lCy5ukMUciKP525XqEAgfSpTCefmiFaf49yg/FJuft4GA6vDbnYkFOCa S947Ww==
+; resign=20460416024207
+178r.subtree2. 86400 IN A 192.0.2.1
+178r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . PqlL+UptlSvJyT0dD+Uwu6nKTXGPpX9lhRrAp4H49OhSMI5CU39Wa7TF wjRYe9TtjYKjWtu8vEqzYPg2jTY/ic76nv3l8BalRIPKvwtQULuLmZYl LBL8h9JheqSWi5MPbgwt6fm7RJ1rcrHNYe0oHmuPt6JPfTLGywQFh9U6 nWoCa8y3xuOFgu3n8uJ+aDCl+VwJp4MmJvXygP3rHevpC27AqBIQdFc7 x02xrkWClVlfXC3PLrRvWRAnrVYjNYzFyT8TIe5ABt5oJ0I3xI0d7wgh Ha9IZd81bhNPm1wLtcBcK/X+ioxpaprQgD4/1QWdnUywRORfgwXpAyRA H9DilQ==
+; resign=20460416024207
+178r.subtree2. 86400 IN NSEC 179r.subtree2. A RRSIG NSEC
+178r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . bMQIhE436QXSvlMOTipK1JC2iIZFmX9G53UkCiJtlSgsxSsdJNslyXy0 Ejv/MaJ7Ljh10OtZ6EKy/kv32WuQB3jvtbpVbrfcJAbzTF+rMI9O69Fp KZSZXBGKwX2hy6IyfCVXZS9dOQS9BXyfQH0RevNr0+rf+c8tBwJyqgiR xyj89eCBf7odNHzjVGGPuhgT4MDXGnrgqoM3y8AIy75CpX18PJK7FkS5 22KCVh0Cdp2eFowltyaJm5K6qIOnkYYGwXRK90pTgZmt+VYgEx214/Ge mZx7zaS3a6+/UWgcuAiLs84iT2kWmGERjeyWwURJZT13IK08EZ3/mzLy d2zl9w==
+; resign=20460416024207
+13r.subtree2. 86400 IN A 192.0.2.1
+13r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . sXsgdidETamVj3hMGclONQ3xs/5wp/1272MujPM3+3/gKvVNa5VEggXS r2pA5t+Mk4PWuUXLog2ihyAi9Us4UVNSbBMxvXnq3fAeISGPm2QonTsT O312FEmqWcWyVv12sv3BVt/AEUl3O1YlPICr5XXLHRmrj6KF7ITZPy+g DZd7bseKOArxNqqsU/Gkixz146yV/IkmYxD2fQmErDqN9CEYkZ966f6I NMhTyDACGAu7sYZObCw6ruBGHik6Y8R6S/R0viMq4yC4B9TZEAsjyj7O FS84crAXdKYj+zywq2BUllrMVup+m1TJOfioxtXT7O9MptZ/CZM1qErr +nAwTg==
+; resign=20460416024207
+13r.subtree2. 86400 IN NSEC 140r.subtree2. A RRSIG NSEC
+13r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . f0UIocyE7wUpGKh6HM0renbqeQXha9E0ILL8OU+9wW7Kc+we6u+GI8M9 y7FQAlGIhm4ThMWxZE06TgwudtU7deAhEfryJdsmWjW/gBLmnfkSkaLU 6XNQVrVpCwR+DcFXvH1zasDrYZaxGc14BOZVuh4/HP5RYm1cQBA/cYX4 VJDBI1IYP7iqJEJyeYCmPDvgUZLtoqw1i7rey0qv+0C2yJ0clqFHScBU 4S/A397GkHzge8i2gfn6L/5r3PEe12AoBLk/FUQH12jjqP6VljOQFSa5 1Nsz/nj3SvoSqNIWO3uQ/tT7WwKxcYGEwOSB4pXJUBGp7jsoWPHn8kWC yW33bg==
+; resign=20460416024207
+17r.subtree2. 86400 IN A 192.0.2.1
+17r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . qqay8a9aVj9bppnXSWbAAFQRl7FgyL1Pc5BQBktPBi9XV7W0eqee2kOR jL8/vmYe/EkXkc1xIgb3gonQV7mojtkHT2pDckw9T0cY1htyYxJ/nyZK 3Ny1/SvJHTe1WAPxTwd1ZkVZ/vkz5FXl/uTeJ+nCq4JAlPnPviKPk44q FTeRdSOdEF0An9H75DruvlQ6cGA831gEUoe2oXiDEQeQW5wM2wfSdmNa FG8tshu0EGp7Ss+FvJ+x61rg+Qv/B9V93Bc8g7YSl2ugalOZu7Mu+sw7 wGMAsnuw4IMWxX8L9dlpQQo+9/BvXmGsw8715njG1mw+EZL5hywUXG4B CILSSQ==
+; resign=20460416024207
+17r.subtree2. 86400 IN NSEC 180r.subtree2. A RRSIG NSEC
+17r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . AMLTNqKTOztHdQJE0gthIMmfuNJJNrbWyt6xUiY/1Q+SABIizXRCF6vA 9hbDuQ0uAHybELbw+ge7ebkYVubbucSU31ukzw+F/E3s1TeXcSr+V9R0 lft1YlBgoAwE8tqj8ZqM/4T0OdF7GoXFx/yi9blme/1o6dnRzLCy4uX8 qQ7G34k7c97H/a8BJPNFzuIZ1xhuiBpaC7qf0VS5ZklQJF9J5nczMtNC R7FI8OCKeq/+XAW+43vETW3p808VFwjVs7qBSCEYG/zCfUFINDe2SOVd LyvoI8cRpJ1pEuQsQkJT519FIlkBLXULpB/xjivT34vdGU4VsMOs9e8w IeMXuA==
+; resign=20460416024207
+180r.subtree2. 86400 IN A 192.0.2.1
+180r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . xq1SIKwFhr2vnPWv4roDf9O3ghr4e4zAc18fVMUqx9shSuP/a9WPFNGD OwVLzVC0/VZ3hsOBy5rAsI6aIplAKdhGL6PFMv2k44SSweu+dv7KsqfH qNm8ZeZY5prxBEe0V2/blXpvk1zfV4AP/ZBvYNtVf/tacbqa8UqfIUET 5vtj0LhwPQL9R6OeOlkBhekX1/4w8Ow9lDvsdcphPHwuQwLubRWdmdKN AdCAOsrjeI76BNfuRn4wB0tuIUWSCP1yTmc0vwvfAn1gCCXNyLzZwgR8 Aeff9SGrOpSHC6k3S1HP127J4F08R86As19PYX5q85EzO5J9X2lzVPdZ mXFxwg==
+; resign=20460416024207
+180r.subtree2. 86400 IN NSEC 181r.subtree2. A RRSIG NSEC
+180r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ItEKZ07Ib/R69g7gIconfMxnTDiEkaPCnuJ+Ii6a4u6hJEckeRGeTkJk 59KtkxpBQvtWydPIJBOhPkahRa9Ru4dNb2cTeBCPeuAEXu0hLOOon+h2 uJSXdku6q0JBF3dNvV342F+9pZzWlYdKXzNPXy3YTJI3KPm7fGCNqDpR hsNLdjNfaTHZE/Y7x41bCw9ClETa0l+H7ToSNs5gJS4X3a7crxOAbPJo 3cFKbgwGJ6bbzvEWMlmurRlzzhLqbq/60wFM2dRjhY2Ras+c1klh1rG1 MuQTUsbNm7VRw6W+RsYudQURzJ4jvt3b5dYyePtmz17ClO9Aql3k16zO LaiSlw==
+; resign=20460416024207
+181r.subtree2. 86400 IN A 192.0.2.1
+181r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . QyvJ2cXDj9HwoqYzIB2Uy/ohHfRkbQEF7f+X1FPiVF5WUVNOi7PWuNNP c0ehr21bZXAp6ZdROatrkKdO++Ut8U8O0DfqYdlCBJNFNvuivf94W2AZ 6JnGDOHcOtvZq+vilxmdwXOxi5DMr6FstNS+qlUfgy8Y/PLnm2GKnZj4 n4cYCk9/KQNY6V7xB6remD4oqqJwDX+Q99VPjz7Pg1EW/GMu0Re5ri8Q AAhymV2j2ZgtmkxDZi7JMdIblR6Fv3sD3Sn4lmnV+8w+cH0oAX3Zw+U3 cr/SjGWyfzYpiAGs8XTO94GXpPSRHOwoU4bs052c8zrYSRrAfblejv5J gWZA2w==
+; resign=20460416024207
+181r.subtree2. 86400 IN NSEC 182r.subtree2. A RRSIG NSEC
+181r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . P7SN5d7c0OgaJ17/MVKultmuH02Y121rwRoJ3hqDo01Xv3T2JmiNhDid Ij8XiZb3Q/z9lvOjDY2WvrDsNMyLi06YfbQ1wYkibobkiz6qY7qPfI8P KB0LgEI19XFcTT7T3Swz407URR7nHipGfBeAoeWUiHThAdRD26xZzhJA IB9EbTs7a2kNyVMovaXxJPq+HA2lDxB8fo+buSdzwq+bFXhzZqpzY10G 785jT9iRz2jZY5vFApisqt2OAh9HefOfxcYOhicLvf2JxcGdPHt8YZhY i2Yjd3sekq/0hXOej+Up+sJ/1Tdkkxgbb2egVaFRgK3rN2XYSybJsXSB yvhgkg==
+; resign=20460416024207
+182r.subtree2. 86400 IN A 192.0.2.1
+182r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . SwcpMSUFgXG1DPNHv5BBBrxviDsdjj3P4ee2pDUNeKbLpsvbydpLari+ 2baprXJa35WreaHmz5lKbip0g7wlCePvmsfPe2Voa6Tc9ZGKi0Xtp91R gug3QL/PrFd1rjClMCyOdXyrrN5jRXVvEs4uY7CNS9qZVj+JzVJ0W0ap PYO50lYbAW+qNtYSSXhOJ3qlNqCCyYUMXaCmMvSI2JOC5pmxBUrhaqpW jAjt7NWi2GVVexj5+OUCCU01mdvLX6GwxWwAUJHq8cJzrjRag3p14Fj4 Lim0zf5fj+zBJavEN5TeW+2O4D/Wo2EcHP2XUbC4xrVzL2POSliPMbgk +QXSVA==
+; resign=20460416024207
+182r.subtree2. 86400 IN NSEC 183r.subtree2. A RRSIG NSEC
+182r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . pFiBdRGB6jTW4IvDdn/kM5mYzDQVKpCtk9X/zinOe8JHN2jdFV7voDfe dOu7jNE0Nh7VYlcIyJDp0SggthbNIcKZrkbeXTHiJz7svKMq0LMkGuCM p3QyKmyC0vBOgGrcTMpMEwP5dJJmk54WXMMXodekt2LiUpdo2R1p/Q83 z25wbZ0+UuoZ4EgaFPF5evLjX3TgNJqavhNwO+u5ldX7mUBOHTpG/O0F 8OKv8AoM+el69X+9irqklleF0LCuAlfac5yM8Ns82bZS1c8qnercNqUI CavjgGJAOtBpexVi0eH5Q6nLXf1OMXmc9lqtYkQ+CH75h7Hitbsfs4ja bMPkCA==
+; resign=20460416024207
+183r.subtree2. 86400 IN A 192.0.2.1
+183r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . wf0jrowwDmc4nXD+HHbB7zEnmSZrcJexZgD6pVG++RHkXx+LiEFwJr99 Y6x9D98pNC/o9+UpaZ/Os0oncS5RuXf0O6s+CqHIfAI3aKbFJfI5AoqG wV7YAPaSoW34IxPvDk/RRU0sJDxuT4W+6T3j/awaA753VxlgLKfvTmir S4XBaYPmwxk8EQlFpDOZFijwoP7/MdgKDc+w+0uOI3ASs8AY0Yd6Wh7E oT7iAn2y+iKeMzm0g/YIxPk9psgl048bKCnVFOtJq8T2BEMq8yhkr7/p F6RAF4d/VxTEUWFVbKWSK/6GSMaO52zp/pEgnf7ff3tifTokHBCq8xHb c+Ckfw==
+; resign=20460416024207
+183r.subtree2. 86400 IN NSEC 184r.subtree2. A RRSIG NSEC
+183r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . kSxsEXVu92hNUo16LnQ8x7Z0GgejAEgZtujfYXDBusVRxChY/QGAvzfa qCY87MGehyXc0dVGHJgKnOFEPS4knYQfoyAlyW90h/c0UMMD0za+VWZU 145m158hgCsqNiWoCWl2GKZZuA0ObNX0JcIT/7CsxrP+nlCdWuYCVgqq JCsX/WLcuzZu5mrPklK8dyYjZj3rZHqvFGkInJo/M1Ey7QB46KD58jHA kxw6YiK3tezmf92RTyHTv/kXM0dpgyBWZPM5D7ICc8MhOrv3B7V1T9ir q++8Z7/0jNhnjPkoH6zweCdRqI62PbKkqdnqfh8Mbe7xz4iIEAE33w/f ELq+mQ==
+; resign=20460416024207
+185r.subtree2. 86400 IN A 192.0.2.1
+185r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . fo8NvlBCCWNX5TQ2kfgtfnwS5HMDvww56htGU81xFLaRe5Vwh/8mqfQU Wy16sbwRGfqL+0OawZcKtuQvS2vSkeM7UI5LZkp8mYNeBozlPNO8sSI8 zVNegW07ykZtlftPnnnpjjMlmPnqBtFDxMKvjqBYJpiw00YD3qYPDbDt udI6j1cLhygruBDs0I0QPtZqUqlMxFES+jRtMF+pEK9XRF3N4Ibn1R9J 5ITbheM6zfLn3dU24raZQ/Q+sKM3ezr05qJMXewMDj2E9CV9ov166QLH v3cAH7o/dRJueMO+iUZ6YLGe8RsNCb5fhgdgp9ey5Rj1M0UbtVQOsbrg MYOXFQ==
+; resign=20460416024207
+185r.subtree2. 86400 IN NSEC 186r.subtree2. A RRSIG NSEC
+185r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . eWHh0SzUo4fWaYotGJ62oN1/on4/2os2nV6/EdEN2TMHcVI3JYT7Q66d /JjWJbyGB3UcfJXO02nyYcHDzS65DTdXOwcx+G4QJaXvsf1+3frSnqD3 RMm3PGrOxNe06dmPZOAWir1LJho4VjzV3aJQTmC10TE2vN0QcZryAeKe 5aFHva/DoclqvuMA4V7n3XOL/tnfZ+hK6LD38NetFwSUGAspJ/WSxQMC aqEDoP9XrmOJE1wgsIe0IFn7CRg5a84AJ56YIy0TXGgN/GFNSkembXDl latpUOlQw7XkdaxpXFfAAz1bmV6VTWMU4GtrspJSIlSIsYrcXVYgkFwj vKUIBg==
+; resign=20460416024207
+186r.subtree2. 86400 IN A 192.0.2.1
+186r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . w8I8vrnUjIPhi21ByPsk2oZ7ozJsrJoXDKSdsYj6+pq7bqrahW22IzR0 CmIxw8Kl+woQ+I6wui0lSJIqaPf4yr/eXL6fVHde3Clu7+1MPHAJZ2ss FxZxUuxuBXMTp2JzBYuGfZV3sE10Tg/DEISwC+ZM4GqALc9LlGPU0AUb EXcWBHpi2NeA6WKVR9ayZPZnG+mjWu2Lb8bcFtwilHadmooTDsEJX70e HmFZoixX54yjvkixWtNSmJcIveXYyevWTrXsF7orzi/WcsGsdCJbwLzc bALgvwxx7MuySed/M4AuN2L10su+jTeJfo5AX6tCoIdA03q9ATSDCES0 udG/zQ==
+; resign=20460416024207
+186r.subtree2. 86400 IN NSEC 187r.subtree2. A RRSIG NSEC
+186r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . OLNBPWMExsjmLeTQco5tvaZdupvyZhR9mT5O+6X9FRXz8srWXc0y7Vsl vk2B2YwzyJyXF3Lp5nUveE3XS7bPi5wxZi9dPa0MO5lVpmGfR9ju7Bzr R2NPMnEqdk0jk6plCqzTJBpT0Tx6g8RiR4Xp3O9UN3o/5zs7eiQtDjf4 npy6fAJihRP7xNd5qk5PwIv/cjx9j04L3HUXAh18oc143mplXBjUR8nw Zkmpk2hsZm6vYmGhz3GIGM9jXc+wzRkAVUj5NoMTa8hDIOEoe44E6+zd hboz+s5VPpjkTN5PymlCiAMqYN2vUfHmRhO+iGj+dwyLUzM+BCKTDWUa 9Zx57A==
+; resign=20460416024207
+187r.subtree2. 86400 IN A 192.0.2.1
+187r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dIDIozfz1Bgm+ZML/5AzrX05Clt4mebu7ymZ+D+LHR4NOOhJ22gBnuwN LhVhUBi2zSopTmq8UxrL3CJzpbGBQFN60lFMLXt4RGTag7QCZZnTHXD5 3oK7VU67uGtjVp4EYAcrlIHh5NzHHyrZkydVvJogYMyG/KMsh+Gqi6hu +6RvtHInlxdzD0Rc1mq7bzd5iYMBB8dVFC3eFTEf3SBKIpFmLcJ2AnF+ 6AZEIzKg7D3zUi67A6Js2jJ1pIEX56KBmW0hHDfjSIkHLxECV9lRbx8+ p8qqhKFNqwk10TYj7QWcjWHfh3hi7UAQc3A7hnTFun44DHTybjojQ3ac 8Plu2g==
+; resign=20460416024207
+187r.subtree2. 86400 IN NSEC 188r.subtree2. A RRSIG NSEC
+187r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . WbioNojsR2o+n8tc+LYffEJFEmyq9W1uxT4R7pKwFH/ZJI7pqj06F4DA 4oRElc6NPKbwY95Au4d0Ys1Pt9zpeWIB5gzepDT300n6vne01CTtV/zn VA128Mywb0XsGkoKQpyOAXfApuNMwr+ehjsp8/oEITV0XyPtCOmsW+Rw ykopYhd0BbwwNBgiCsDrvWOvJCrRG1CNAOigKeMpln8SDCUwsA2XEXG0 YaSrnPGjJJqJzvPpJ3Ou13PRNGcyMCofqn9cNgxyKwwzthHoY+KBjrkz bz09228nhuICKDszvot9zI1HgWnVFAucdkfeCYLnQ2/gAbybsDIOOJqO rDOybQ==
+; resign=20460416024207
+188r.subtree2. 86400 IN A 192.0.2.1
+188r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . tbpdzGbYXHTgyeCDpJrZWppotY99N45bXmBtCPgcLLjdPcnpGlmyzEsG Ff1AIJpl7beUHJlforTD6aYPLVKNuFLIKnPti7lKHtd2sY5aRUIOfHrf 689gPeobI6fylrYlojmp1EO6W0aSy+AJrZf2vvmi4dmqc7WWn2qVSuQ5 1yw8fVa6C3GVvvVmia6wHyHIvTCqNjPANARSove1y5hVcU05c8/SOcwI rifwaYiarQ4PGYQwDJCGAfR6D9/VNmEoVH5RYlpeghHUOVphR9OEprR+ GxVaAi7xSuVzh+qsFvDaU2zsVMHC4WTIImxrsFufax0dAjYwCGTF0OVq LybCjQ==
+; resign=20460416024207
+188r.subtree2. 86400 IN NSEC 189r.subtree2. A RRSIG NSEC
+188r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . WtfODvpf3qTum3G8VHl+Cxtuhl8/oJ3g8HeUJwCF1FhDnKegjCjJV6qY rbP9N+mjqwi/CE1BvKAT1hsrWiEGk3TTWX2ss2D3GKjyH8p8Fvls0GzV X4+T3IwdPhFshoMCtOLb8DhxYp4l/tc91HgosTF+mJP5LHJcFbYcQEtn Qbwzs1HA4t4+8OHN6jVSDwbydSt8DbQidI99p3i2YM/Kg4PUPpMhuJD5 tEuUhxqDlk3tKGMh81WAk3XU9Aoz+AOu541Ko6agbUEs4d3Y2SddtAEK qOt6m1/vUPvDn3Q6BKn8X8oB+S9Msz430/vIPQoxqMZogc1hnZu7Rank tB/ceA==
+; resign=20460416024207
+189r.subtree2. 86400 IN A 192.0.2.1
+189r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . UL14E2kx6xvEAI55fX5qi4vnpfvk0XJ82EWo8hhs3hp25zNt5sd85jzg TlNr0x5dxbqFnxtdCT534ao/8Gw+zPvHxDmDWu7ygFpDTDQYub+zLVqQ PkUp/vZlpLkZ7OVjY/84x9tiQr8q5/5zGwEL+/LhUfn4ZbZo7YM5BnDu VhG0pjuSv1vbpwVIht5t9HVB/1mBsgI7Hy5AewNno8WytUzcfm3pt+Zp ns1bI7GDRvranS4y/cvcO3onmsshLmOmrWJjAMyZVHxHIUNt9RIlUJQC s0zJCcOu0yQxQnR6Za1KQBG8n7ZuWSvyRPLBZvd0OAWOJjKCBqtCof5D nqcRoA==
+; resign=20460416024207
+189r.subtree2. 86400 IN NSEC 18r.subtree2. A RRSIG NSEC
+189r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . cKcDMQGJXcf3v3RfLJF1zH1zleaK2ILfHWSb7+hB/Nm+mcLKm43KxWNZ rVJZu7EOUj8M2cHzm5NwEtmZm1SBvxa0NHASwavhNT6VfNswOxkbZy5P XanQBQ0TGc6PecbG2l8oeqhr8/9fDjyYmbN79Y73gZ2iIAIW/CFmLf2v GQ53Ct9L144s8KvxfsUnpDnob7pDnMBkM5GaMrbpgMXcdBgUnwRKoJJB uXxyE5yP5VFuWLGH8rOEIHWKdDRos5qlu/eM/ZZIf47nYy8G3rJqTjNj eCZumTPPOOdMI0jmXBJyGSkVaKQgcHjsnrfVTJqlOOy8dT/Yls6H8lV6 CBCXYQ==
+; resign=20460416024207
+18r.subtree2. 86400 IN A 192.0.2.1
+18r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Bd3k5r5o8uJIV88DwRHdF1nLGzEQ59pHGw+1ieisxP9BG7yxyxZIJmJf ZLD/crYRWeFrVZmqIHtCRJDaR8C9Wz81qNbTC610Y7yKdBAT3aFLR9OE 7ooBv+oDBeIgaGGjcWLxEaoFKA1QdrbtH3uv++KRpcCQaD6sEi5wHn38 J9DQDVRnTot6CqJykLwUA7DKt/Jemr6hXhwAeMyHwfRZtcFrYbvC+To9 m4moJLnEvyRBu6cJ/VxjIRfagLlzaUlbzy2aMkcUYcWP11BCykigd9Q6 qC7eQoDO/Ydbg2QRrYOP/3fBjNzmiSTudV3uuMOjWAkMELoPikcP/WRB W+fEcQ==
+; resign=20460416024207
+18r.subtree2. 86400 IN NSEC 190r.subtree2. A RRSIG NSEC
+18r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . LyKx01F3d/M8i1Y+hZ9AbwPKJ8jonETPnZN7PzY9GflfmyUlizrkxK1D mO9FAFbEbCAFu6ZuAScQfU7kGeYqFCDgfiEe7JRQVJTIUXloyZ2a6LGv sJWk60omdN2BZrEEeeQllh4jUquLzsMKcei3NIYmpG4BpeLbNr9jfzhC y64lwOeYjvbqw4MhRrBEWjelLdk4AwvcbDrsk3QgMhtEqOul5jQZ4SOH 86RQOy+2bVQWv10J7F8jV9OzFQwgrctLB4fkcD85KL5Phd5naqLiaiYH Lig01cudq0HVr+nlpoaNvMUzAMcaNQ8tYv3R0wmUF+pATNHsYzjHTggW 8VLbNg==
+; resign=20460416024207
+190r.subtree2. 86400 IN A 192.0.2.1
+190r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . q6SCWjzJDoMY2aeYf1unyQQAtRNwqmMJp5inkrs/4kOydKi/tOBhQkCQ +f/hqn5xx0llx7HhAzfFp8GO0L3eGH9A1kCLidcPZ21BkcGWhJ9gmEpW I89vhCBR3GFz3dtnpenQOaLYgidEiRdeXZ9qKSWlGi6zTxy1QE/XSt4C EoD2DBcPHnLJxcKi7ZaWz9+HckvyDtkfOIiX8uiZe3TVXAyAX2z9n2nS 6xQ/dqclFwI/xnUV0roQ5xL7REpVXkCQmB4RY5cOXC84mq437ksPDrAE 9m8Mzy8UGg4pgBmH9zvTLHM9aP/lSa5jD5RXi2BFiKwMm3FZ0vKCLffh VGmYzA==
+; resign=20460416024207
+190r.subtree2. 86400 IN NSEC 191r.subtree2. A RRSIG NSEC
+190r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . jvrQXPmILWkgzAqmNBvUAfUaMOLhBBJnHHR1vwgt3i1y/ng9w5NeDny9 aqpcfH0rOD8EqjjE31DgetAldcmwv9QIAtCHj8kLQT4z8RUluXSanvTA Vc8Ql074dsIUUBAqBJdAKcCTyjBNkZ7SzXtNXE8+wAInXG3yvvoHRbN1 DjDjJVSTLxikgZtLBcmE3wOylSWFII4VOXXJglzA5BNxH1dCrD5hGDZu d3SZ4d9u8rkLvNbh2ltwWbeYb9l9PJvJYVtPP6BEIEcd9viFO9zY0ibx 1Te5jZFjiWj2XDQHpTAdIob3AHJy58wDO0eSh2yZSMzJy/N6Je6sF8Rx optODw==
+; resign=20460416024207
+191r.subtree2. 86400 IN A 192.0.2.1
+191r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . coAWozM2Sbwb9a+o3pnwXDoOjmsSQKehpw9mqmcsao2389X87OrlHor8 Sdu7H+Y1Dp+5WzTH4ZAaa3CzggEGqJMrTfyaeR7ClTJm+8a2fBlXQn3D etFXVBehookIDHiphRmHazWos4ztoHcUky9ck8l2TaoK7VD7woms2HKS K6PaeWZx0KXratCJNrwfQKbqOVayWOqTVfyr1V1mRC/e2omjVh5eeag2 V0H61uq3MW8/dhFAY6BvAxaZ0coGEHipJuafphpfy8d02pOGLjmwRM2b nVWLsc+DgxSkKzgWEtoGMu6B9f/X8IZANkMlf5FNR+gurAxH028BaRRs Be5cSw==
+; resign=20460416024207
+191r.subtree2. 86400 IN NSEC 192r.subtree2. A RRSIG NSEC
+191r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Dltwr32CEvj1XDBLBckhHfu4uqW5V6+wWud6u7gJshlpaipvAnw0JFWO 0k+4a6N9aH9pWUjqXGHhnGXa+IDQtluAhljKfYNNngJ6yuPVnhDDN2yA ov34eFbGPlIw3yTxQ6ktZdyuMUyRB9nIS3+kmHcMWdOrVFc6QUDkbOa3 3HMGw4ow971BTpbqB16PHi8qPaEhDXVHUBxTIjJA0ekD0pFD8MYCKZxs /8eWWAzyjy0yVaXgMw7uecWPjARkvqq49CK7on8e537tkCT26faP5jD5 y/xWaDm+4dQpQVJCBjStO5cjCB9SNtFQlma3ZLqFLsrmRaHo6zJBQN8C ZLYFlw==
+; resign=20460416024207
+192r.subtree2. 86400 IN A 192.0.2.1
+192r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bkaQetd2sGz+FIva3mtmf61a9UGb8EJF4Eyo9Ta9ahkxqDdG6RwI/ccT cd1pjd70uvxA74N5K5g15f3V2jJmJo/mSTiF3BJLT+mJffYGiWsX3rMB GGW/UmQMq/bL2uaijBKO5Z3WcOsE6E3rTL2X8haO3EmsM9y6MMwZ3R1p 6pq0jI+FsU6rSIhijYON3plaYhjOt68KidVHovRPYJzEpV3vVj9WGQBw APWTiX3QW8AHlDV/NJsMdQMUQhKGfdCPEIEYbW+JBoxylFygoPG+f+lP 2D310QFgOTPp5hzQ/QgcjvBfJLdVPmuB0rskxg5JPkJeSrbjW5fvu+Bn YJcM6g==
+; resign=20460416024207
+192r.subtree2. 86400 IN NSEC 193r.subtree2. A RRSIG NSEC
+192r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . XCkTY6jyHmhfZmlPhHlYopBPHUMI9u+PkLgF2iGChfVTheAGSc8vK+wr Ja2B/e6w0V2naN0BNu3aXPnZ/YvhaJymWnHDyFMK3fzMAHuD+qtsAmIr kmVwpM95vP2ZLXnoWKSoiJyCCszgKxnB//zMQAfHOuOyZ0c3KCkbIkLW DlHovVBEBYQZSA/LphEdzKDlOiVCfZ088KfUXgJnIf5Yz2B21he0G53B e2s32BF+z4wp0A9n4Oo9vMUozS2t12yg3pQtDh355oZF1f2l3gEWbyWo rjCqwGGPVwKmulbpkCfQDUaeNPl7TymYwKOiDoi8lARmpvRzVmwMemcb GeW5Lg==
+; resign=20460416024207
+193r.subtree2. 86400 IN A 192.0.2.1
+193r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . tUIiI0iSpJ8g9yeENn0D/ojKe4mqkc50dv3CESzrAD704LMx9JvhOHJg wX7Yw88Y1/6hquq44H0sJRHHKDPVBHpJ0P8tYW+pydJMbwDN3hs8intL oNJgJuH7G1p5rGanBfbXXEn2wZvnY/zZZr6a98JE21Lq6xEfO3XrRU82 BdQVJLjUpIQqW39gyXXGFNJqD72kfnHa94GlCYshKzygPTvN5dUoHih5 k6MRRZpYpHCPyxRwDKdjx4Z9rkCWcoGgV8+uvq8VhIKTv5C7WsCK6jAA 0zxsEd891ABw53m0+spPnXun7BfWqMg7IsIN60cfhuy31mu4obyw4KQj 4iF3rQ==
+; resign=20460416024207
+193r.subtree2. 86400 IN NSEC 194r.subtree2. A RRSIG NSEC
+193r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . IWMCS26Ec8KWZKOM3HQMPuW9gEEu9wSwQhIPK5zB/8P8jrS2RlCUyAzz cvYExkTzqMSs6PnwA9JNDcd+z2EDr90uCtvihrBA0i4wtIn6MYkTae0X Qwse+XoWYHHG7OFVX/iu5EBVUgO3Hu93rcSox9OUL/eAoGMBjGVoUutG xj55h2ntAfo+55oE3VoqmUswnThm4uECXgRD3uynjuTgJWPK6Kbvm7Od y+iWXpqleLDzXcFHqw7R6dzI2KB4I43DDhhDCUBoL4kccVLIkmqzuP1G kP6gH2vSGLqAO+LWbboA+c2hJpCN+dJgaX+qNF7QH0pkGYlaZz1Q4nW/ kKJeSw==
+; resign=20460416024207
+169r.subtree2. 86400 IN A 192.0.2.1
+169r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . si6aWmRP77c5v3LOogMFuTO9UwJ+tiiLWOAFT682h9kBLEp2mAnYXPUK I5GOLoxFV9R79alTP/k9QYATgttTnKYQt8FWq/o+dlPNqZh2fs48SBk/ yWlHeGW1trsDoAJS7m0aLtr/A3SaB7uLz0jmHHbdlui+h4ZaeNj8KAOW yDjiCqaOM7VEY4B8+iFCGS5Q9aXesMiKpky0aVQm4jh6r5Xvb4BNEy+O R/Tjv/X5j1UkQKwwe4mDe3wVP3UbFurPy7IUYpXvfx/S6LLrahhY3P3y tuhS4/G7y8QINVzS8ojAyuN6xxr4Y0ZCbSqe64QapDcsk68PcaaigJqh RXMG9g==
+; resign=20460416024207
+169r.subtree2. 86400 IN NSEC 16r.subtree2. A RRSIG NSEC
+169r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . bGKebx2uDgCnZArPh3h5Yk0FDylJOn1t4n5nxCXeD9kyIpOkPP6z/bka W7sRDSNa3ekqwg4ZHwtdnY7nMRbw83msh1CBcePQF8AIv6iHmoMBc+3p ++XgjyHVwQ3TbZ0sIRKmZwuKty2oSteOPZQSsDxQcgG0cmep90KWGE5h +xQJM92kah9uPJWCR/KF0wDRbwJgy4c/hSEaa5OiO2A9eRrXSy4TmyIF YNNVXl7uCDnRCUnH5M7ZNHpNVpUZzBxavmQgOOEPvaqxs+6/gpP2V+ys UKOOrDKz/7lsnr2zrq2XrCOoYs6tZ9n/wLTarYmL0gyg5mc1KjEYBYag vsLt6w==
+; resign=20460416024207
+194r.subtree2. 86400 IN A 192.0.2.1
+194r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . kJlB9dWd6vWbnvUV6uB+f8Oe5WnY9RUES9yQMdnYhZOQmWkc75KVpy9v sEEau+gisX5U2rpC6nNdWERMFhPMoCR0Wmc8xMWQKdNL0dpdFap4HI9a FqDswqAqjUlzSslZn6DKm/IErMzI4vIZPFe5lSooJDJtl+MM0qhhKmdk jww1Fb3x+VLKfLb+ry4+gAb3XXOhiBNdfKKaccpu11mfJsQ/GkqEszHW e84I7wFFwG1xj+O859GX8K50QD4EPzQCT1Y5N55m7iX31jogCxLmO1zi dN3l+Ul1FBxa9+rJXgjXp4DYCJ3G8Spgp+cpN6WLs00Q/E7WQ+RExD6j A4Thcw==
+; resign=20460416024207
+194r.subtree2. 86400 IN NSEC 195r.subtree2. A RRSIG NSEC
+194r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . q14OdHwGJ6MGHiL0xrXY68tPGX6HFIomOvKTYngIXz5LqlIqZJ6Ff+0S H+ONTRFR3Jt9Rl6N109MswOYWv3xLFUyqFJOGHyrGpKUpn5I1+CXEBcp Z2CG5ABHh2G2M08QjPYibrMhVX0ydt9U33LYVCukbrOyH2xkPnITmJ2T EHe4fCPACVEtPkBH8nAceaOLfajbpyBgHnXgeQqrujLoTPonTo0rRqr2 t7dp/48CxA3VQqvrsMajn39CH0xFJfcjHD5kAOn4L16XWkvyYVfn0BiA V3drHDaErhTeRoFkDlwWNxECrfkHqccqY/AWwcz3cSnISMAXWUVYd8ZQ GsU4oA==
+; resign=20460416024207
+160r.subtree2. 86400 IN A 192.0.2.1
+160r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . jb72zIgxTA12OlCMJwQuMC/YsMJGNqM8kTQB3QftDma03gPTFy8SbSkn Ewc4Suy6bC076FbaV5TBuX9mmxa2wQL1+Km+fJ9yiKw+FqrhFWmOcB8H Q1PZm83c+at5Yg7u8jvNF1O6QxF13dz6FbURpo7coH1Y8OBKHu+GwDfS +8yiHGsPqdrczCifDmYb3nDc8cslVYNP2AmytY5vbQdkPW6EumLrnTgd HR/vrDe2SLTNwuh+MNMSfS20oKzjYT4SPF8AHelhGqci096tRGJjKboz SpBmKUHQWyOWDiL+cSGGBlz6dMzD3P1iHAPprd+zaRREkVlmAwwvXx4N XscCxg==
+; resign=20460416024207
+160r.subtree2. 86400 IN NSEC 161r.subtree2. A RRSIG NSEC
+160r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . G0iabi6n6Lxce7Q8i6zYd20At1R9I2rybt7dkh0cx14cXIoq1mt4bqvw HaT5Mv3eqazO+/RNIaJ6urOsFxDr+g1uk4HCVwEA8JBs7jr8Gll6sFuj HF8Ig+kdjjIiIc4cjnygpW/vEd71TOqKeMj3zWtx7SEyLYHl9JaUKqHX ZKPJFA/25KdLvK/TImUgGWs5wTdsqWXgzYH0bGZZjWutToNbpL8a6r5Z smStITjxAxLbmqBdO01qVHufzlsGn5AnteSNie1lRsERhGgm7/QBDz0t 2nk/wsdBVyVJc24lgngL3fwypw0w1qJf25slT73wXayCiOIqRxGkzBg0 m4V89A==
+; resign=20460416024207
+196r.subtree2. 86400 IN A 192.0.2.1
+196r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Uv46WzWSPSF7dUoIG5MEXEkf0DSXGDISkm3V+3Gv53VpzWb2nZ5UhLp/ jVSbCrBl3lST6UV5XyNphtkYBHRFq0/ACUtBSTWGFipOGFHVn9OUWMPg NkzKrEGrvWmACRAkea9qVKAFwcSLEvudQM5LeeKKPRonUGlUN3UAHr1K WA87BbQPJ7cvpkHUqvuKnkdS0HkUXAD3g5xH4lHY217wN5SPX936QdWd cyWKEvC4x+grc6hGvHniOk8/8AswsHF6bFJJdF+5tvvIN54Nn3wGdWh4 HxwAG32NW2u+BhP2KBPAHZr5PXtROXfk3x1aOIGuOwI4jQKLO3eH62Aq HlCKow==
+; resign=20460416024207
+196r.subtree2. 86400 IN NSEC 197r.subtree2. A RRSIG NSEC
+196r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Vhyr8UxBBVv2bGlmO7vt9az5doR4DqsNL74WJU2vFDI3YF0oTOdJhl08 BaYUYQ0Fnq9YTaRAmTiwdmMKvbJWWw2e38tZwUUPmUmU8luVSBXcqGKd wtGr/Ys8zhj2SAY6yZL3K5XkpEFf4x+lJG6PQxGJpHPXmVxcfVdD+yiH IzUmPUTj4hOTwuqL/dJuggbED160MrzhsIcRInt2MM2z2rqkVVo//LS+ kKfTfYCjQSa57CwUrmiokBsiMqbZX8v0f3qfGW7TD03OrEGQNWrfNxkO OEgQp9bj89SeJ15xjog31LkVPILEnPA9Xb5eAjKs/GJP8Ltal8LWCXLe DrQfqw==
+; resign=20460416024207
+198r.subtree2. 86400 IN A 192.0.2.1
+198r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Cffyp1+C01GAOk47wKdsqcqrOhXarX2w/VUS9NKTrCFv3E6CVyGKwqxO ddRx4jEE7XcZG3p849CDmnDBDaimzG5i7PbGAt/GGoH/2IGRtKRm2N9p reag4cFOELL1OgRRAZ/Qrvhp+jSiNJc5/uT15lEK5/2KQm7CP4AS5LM/ Do4VjCMQQ/rsXrqepw0fiBGoVU4fyGAzzsIH8mLxdiWMymOYWsF2fHfr fomzr3mPeRwIRDzVd/LLrZPqHjStcOkihua+c5KV4SA44criNpV3b3OD BIgEXumqakOb6J7Gld23peqd0I4h6m3KIY8pRT1BA61g7JfzR7s6XN98 qm3Sfg==
+; resign=20460416024207
+198r.subtree2. 86400 IN NSEC 199r.subtree2. A RRSIG NSEC
+198r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . riY9qitfYMNPsFQue3GSigjgNjIoJb5pu0SNRP66FH6FEJeIQlVKNBiJ 5psuMDKxJdC4KbvPJ+A4hcojeuAh4oKU1HcXArpo27OlTU2gA7aSYHc2 OJkIQUnl+yH1YUdXnzHV9W67bEGW6qh3DwdahfRBQoB+lZW+xdQomdp7 HlswZ0yn7ldfaJhc78JIcHGgZvZAI+Y0tnWFlQpxxeHyQOJa98IlD5CV 4XTnPgr/tAwypuWlKxhYRuOdLszqodpul1MqE6++x+4GnZ6cil+3cWy5 Z35lxQQkwEmvdxRmWqsL0wpTaEnQK5xpTHSjS3CkjeR3pYH06q1nGdI4 5ci5Aw==
+; resign=20460416024207
+199r.subtree2. 86400 IN A 192.0.2.1
+199r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . TBgjH7aBcIMs1KVULSMbahd5I1ltCHL7P1p/Oos4jxMsVrVmQ9edWty5 SFqDyUhgyMk4map0ssQWk/8NBSnv3WpPBIaQM8un1/S0vWZgnRXVY6EL aivSXchFMYOD7pE3wx3cce03aKlFOkORZ9yfGhyHL+8J/aQmfisx2ucS 7wm3qV8K5EFY+Faf5JZhyV2tnQhRJgrISiz/hVH29q7nGOMelhAIkVLe 7da8uVGaUrG9Us6AFmNkpI6+Q9tbF68h/zuk+4fAB014rpBCJAaREYMr Wh/4pk03BRtEIFJeknjhiVTBapmL6Ok2/4ztvYvy55l8ZAqxNSa8o5Rs 7Q7MFA==
+; resign=20460416024207
+199r.subtree2. 86400 IN NSEC 19r.subtree2. A RRSIG NSEC
+199r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Iv/ytTUdTY8VWsqkOz7qvfKExoAky1y3HXaFCqSzwLY1fHHVnQPSoeBX o9TN19xMA9EyzV8rado66UKjAiOh5i+cG1pGBUatKQfpAOfeleGkY66M M0FfOu1RfO7kbyEcQaAwqx8/nyVoHfZskhrU1Ztpj4AzwqbO5WkH0CHI 7xQIcG+pNPjpQjOV88UpHlCYp4xaTzBZoMgKKwbS/abtGWw7Tg+bgi1g B0ItHaynIXDv45hbguEw/T+yio+4nIaGyEO9V/H+TjDxp3nbS+E7benA kZWjAK6m7BqAu6HSIRitwPR0JcCEdjT0LwUgDbj4komp11ZLl7FJlKoL Dmp+Sw==
+; resign=20460416024207
+19r.subtree2. 86400 IN A 192.0.2.1
+19r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . I90j4OdKnWqA+ogjg54CDQGIqisKOTQqEMrknuNreiCPOJTYubGFkTcm lFwWNy4ciQWpYdRBT8bZoV+KELLqWvD+ZMRnWo1kQ0/ewGdABuYVgB9n 3qSh+IkfnSla2zeqyYpVly1vYjFs1umXNVoIfHvHhB9w5+PnE65cQrnt 5Peci0x0iVS46TYH+jlrsy/6nicQV1JQ2cqKKo4EzVkgYw6w5hBZb/xl AurUO4v4NvffNV1fDjiGvDsrq5lWM72wwsZYG5Sn98afpTjfMiFqFzaM U4C/awi4sSKrvZ9mwQHDrs7mer6WLlj75OyuLRwuK49aKwDDWelNY1RJ BjUAqw==
+; resign=20460416024207
+19r.subtree2. 86400 IN NSEC 1r.subtree2. A RRSIG NSEC
+19r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . P3aASMLhQQIb7UGT/uKDap1pTt9RmqoleePeWFVYeLUZ2K9nnYxGaJE8 WS1W8tTzcVGkWqc4+P3LI5yDR8Dg3QtpAqGqvDt4qogXtTaopIdFdWub xIzxXqjT2SXRtpXlUu+KOldTQRFrQq8ttibDBcWQf9oQN3hNiyYy6nlL FGQ+Xa8+CAq8dI9nw5qd+AUxsDBqwi4qxb4SUM6RIOiDUZU2t2v+jX38 O8Ps5yZOs0DocS2PirrPwP1m/kZ1NR8RSw+vursZsbs8H/jkrQ9waCxv S/9yj5CC+Y6hTzE4jf8Q5Fbsv0wIFJTQ70lhjNhaSEQerO8C5l3y9crI Yn7sxA==
+; resign=20460416024207
+1r.subtree2. 86400 IN AAAA 2001:db8::
+1r.subtree2. 86400 IN RRSIG AAAA 8 2 86400 20460416024207 20180815062314 48409 . QPdm6umQ6hgZ12897PAoWH0w+doWTmMWyy6rehLtYI6aosZmdYba/IKf USQchPvSbbpRjZl3SyNc2DJXkmZIr6DBg/4UpTsZJgCKsregVJzo1vi4 iv2NeQ4IAoXFqkGqkOMVzZI7jrBtXQe3BCXtGMh5ydSyV5vkQPFO6VKg yfObVC2g8qpMzF4hGu/KOe41dmkuUKg6OMKkaxrxg6ppscYIa+8MZS+6 8TdNJZFKBk69PmKRsmSBwxAWyLg9gzN68vyiccKJxAYeIA3cZPPZTM+Y MYPwoBLBRxDJ2IvKpVkyYHqjljDjI/SUtBMlYrUHZcxa9JlzaNlaZT1Y P9WkzA==
+; resign=20460416024207
+1r.subtree2. 86400 IN NSEC 200r.subtree2. AAAA RRSIG NSEC
+1r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . bmKqaR1EKjjdKty7b+HJS9ZckeQaD6X6CV60Ly0zoWsWR+buhfO51Fm8 p4j7YuLohXqREy354p+gUq5bbSL1UXMtw0ABJkFlmP4fAvuWvIfhW3Mr ZIKDaDF0LilZyyGHa9HAQBMA/mO0xoKsMEtLwN/3zRpHm0A27Le7kQzl Tt4qjLfdhDnW47g+ISxVNceHHKgJXXmFxJGrnLUOzh85kUTYq9OECJQL luE7/+n2uDTcsHUnoDxcTupMU32nXMMSR1k/KFSGN+XGM0rkdD8gdLZS 8px8nU1PkH5UlwJem/08S5Wf3VJakKFeUBbFOYhHyCAZrP7oZwzZBcOR 7Hqr7A==
+; resign=20460416024207
+200r.subtree2. 86400 IN A 192.0.2.1
+200r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . AdCcd+Um++YcFuEPv4aM5EjXQMa9EEM8JfJzUSbtnNgbc2dkAuhtU9/y v+Fspg0RhVw/GZeqLvikGrkvIQliZv4CETszTJt6521PTrveFkQjJRjt XztatkTf0GtwvJepxitodztMAZK3aOyXQkYSjfQgybG5c6sCSAU+crqp IJxBhV1eKIJ91ZVMq6rvlhUmkKQg2nCrgLq+V8lbaZHANar0k7O3st3U ESLyCRJ88rYhlvITZzKtawgIFpZxl8ilF6dPIqZuz1JDnI7u1N8Yk8ec OHHJReEDhK3XhupK9Xqr//laHHWiy2CyEivZpZFnP9d5ePt2Fe1/xm5U WYZtdg==
+; resign=20460416024207
+200r.subtree2. 86400 IN NSEC 201r.subtree2. A RRSIG NSEC
+200r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . arMHmTLOYus38Fu2zrYqWz7IDdR1K+tkbUbUkQT0kUhD+9o2f2JOBKSF UHWGl/sLof7v9ZDNiO2YDRNqZqqfrbzVkZ5TkViJ25BbdpLyzHQmTWkD 0jA0Vc5bASOoNBArxKGLctrdG2xTlOzr4r8larjWmAdF82rSum2VQEzg RQW+32E+fi9P4/n9N0lL7LTgGax04Fk/rT41T/00A1FY7y0WYlex0KPk 6SG3366RsA/D+ci+rYcV+o1gowZWZ2EfcIY/dqjaaYKsPlkTdWKXMFKn e5tlur46qyl0ds2Sl8nzxWrym6MBtVEfGTONQiPymhxtvfy3+x8QxCP2 BxiZxA==
+; resign=20460416024207
+201r.subtree2. 86400 IN A 192.0.2.1
+201r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . WKRZCWCyCWWUcXSdPXGuiqNJr9fp2TBt5T2Gwd6gK4D8kzyr7fzyfkex QoR2lb6i5PC7DwxP2JdMz8DeT4x8TQmsNhlgRk5W1yEWie0SXdgtIGMm CrjZqktI8qtdqoRTXTf7wk+8E9QOcOnZIErQZOcs8GWkqU7PTteyHRFx FwPv/b+ynLks/GnzmiwIuKO/5ITbFByQgpT6cuIR6r+Xl/f1PZ0yThnO +FC8jBJQVZDYAmMgPt9wa8vQeLANdVgOqrEBi5dc8xHRVESw7Yo9aHOg MN7R1/HN/1wXe1U/IGXnAfIBQxZbdICy7Ht/GBMUW5d4EuIHHSIOwzv3 Xn12/g==
+; resign=20460416024207
+201r.subtree2. 86400 IN NSEC 20r.subtree2. A RRSIG NSEC
+201r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ZDr+YoExEf+b009kZrDByKSO+NsyPNNizYUiEY6rr3+LTWvqQxghtU+N Udt9OjzETSWQxOKxTjpPr9PAcaPimpxztob4UxSdyyvhBey48AaMEHGI sYoFPaftUX4lwXDaaZRyzEaqe4nv55VJQUdg6JqTN5wvlSXWocKrKhGm gAxhfXbo6IYUp9AH41FRM6zv+AT+hqy2y+2rMpPXDy7SUafR/0hulVJ4 0JTxPIXVrhJGV7JxxWUfO4x3t0w/B3z0bCXgEro5ixke1iXz53+zGeKh RcIIwVUFx14XVgllzWkD8RaIdRLHiTOH9N4mxrw3bKje4iF+FC8XR1M2 Ao0uaQ==
+; resign=20460416024207
+20r.subtree2. 86400 IN A 192.0.2.1
+20r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . VElsKz86WloMD8ddFst3ZmP7o7rv85lui0GuD/cqc/HDHxNKlkegTzi+ RRdSCJw/XoGoLv0Gsc3oMffvX+YMombqctFWS58tK7msoKJAAxLNc4Eb IqSNI/shXP9IWLSqLMR6fCZSgNd85Q5DlvjY3ql4tRyn42299s3YCkXc PCurh+/LaePwqfj95nKD+gAj/c89stTFA8bfQza7mYEZPRXbnjKhKHoV KcWQmYVZIeJbydPLQ/dcUMbbYsRIQvzPmVGULcpCngTJQlsFG9E+nDto h9DOz4/DeMjN/1DRZP8FVVSx4b6QXJaw+lsEL3cRpA+FXzXOxFSyVxRi 0QeviQ==
+; resign=20460416024207
+20r.subtree2. 86400 IN NSEC 21r.subtree2. A RRSIG NSEC
+20r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . HKndM6ggvOdNXfO7/v20k3RwWsAKWxFGLM0o+EL1gvkw9vi1BSpGSH/6 OvRHlECyZ2zD5UZXquNy6pjP2sMtnSdNPDARm4MYAYDJQWool14QRSFF JHbEdXPBQB4Erq/NqdByq0RuEOykROi8tdiyW5o7pCWjpgm6YSmFvNFI 3jaLLYAZygTuonnJX9gXAalKo/QtAGw5blFA6X1GTDuhdMIK+ojOBDr1 QeZA2tNJAGKtkta9L/NrwZlPX+Ij+WPlPvCgzGonnYHfLGC4j0X82Ctm 5pNpzjal/ilPYBnhu+wOuNkjdrbPnjbA4q/o3zHAcTw1RHh561geSOfZ Htkbig==
+; resign=20460416024207
+21r.subtree2. 86400 IN A 192.0.2.1
+21r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Ddwfe587CQAQmgV6aWxYN6fp6gBQu7ydmCThrOYl5yHcmH46RKLjP5e2 QBHtj3EJEGSh+H0ZRaYgmuX2QNR4nSfAPs3kI4cAr/cP4lyfASm1890f 03nc8NGeLcl1t9tJR6Nu2hy979252mREBWt0hKkAtnDhu3u/CCopMkFy qQzwcusRXU6cnf2GVMOOgSXJvC9hkK/LCAlTPR1SyIViXTIyMrrvR+0z O4s+SihfAt/0LzYGEFCB8UOTj8r8U1QWrAuVxZCVPYM70b0q2IzB5aRH QmU4fQ77HaNdDD976qFOFm0MSAA864S69yBmn048yRO18wc9T4xJbfzM Ua2O1w==
+; resign=20460416024207
+21r.subtree2. 86400 IN NSEC 22r.subtree2. A RRSIG NSEC
+21r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . V5B9ljXa86R+eOEozvkkKYRzr6WmwAYblhCZtfYoH+nEcuImDLOcKppv fgpmzY6LG8yzMt8V4Cbk41D1kIvCD+balhp35hpBsvCZdzuAEBqSB//y 7/4n5CUNaCa2ThJP/rVH6ktwja4Y1YE8dKgJ/BMDVMNx1sB9M+J+xiyv +jmDM6Cnc4ihRgt5+dHFG/AkGekG4LHSEYquAhc+0ZypNoY8stC4dDpP 9HTRusbvJR5Be7a7shOkfGgUP7CdZhZPTXGhC/etGAXzrVMpIg5+vQA7 cRzH8czwgpp11hQcMpbjHRiDggC0bkAhC8Se3MyrEL0l2wwWt3r+VVWP BTL4+g==
+; resign=20460416024207
+22r.subtree2. 86400 IN A 192.0.2.1
+22r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . tBL2RsmxH4sQBpS+lGED4ig0o/jHn1kEo7ctXl4F90EZrY9PE2VOY/8+ LCq0B+O9tRZaOwZ0H9/P1AdssmdaZDX1PajDuP8+WC9zjjA21sPpOW4l eOPXoE1200W3cX0maOp+/uA6vHy6FoC1d1/WeObc8NpN7J8mNXU/tzH+ xOlyeccMsxapQ4hXJFIpWeTGFfogB0eaNOxSMHinoLWEdAXYcF26B3Jj Xxagc9YQFn0hUuOK7CIc6OYuGXnEeteegZI94dKPUF0jfqLfJomibQlr d6vsz5EFvAbJw83Va93QT4+SHcPDzEgsraVYBFd56WHoXbPZ4NZiPL7o BsgOwA==
+; resign=20460416024207
+22r.subtree2. 86400 IN NSEC 23r.subtree2. A RRSIG NSEC
+22r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . mQ+h1nOcLbnohGMzdSxudqhZ5AJoV2l2i4wkAL+syqDiHnuGVG0Znxwe Uy0Qjf0Uza+XP81Y+q4MJonVYpfriJv0QJCY9D8/r7fBrmOTnz3pdptD 9ABo0FIDtIsNzMBdMTsVqNVHESmXRs3DaJcGza+SrRl5TChGU+jkTth4 i1yl0VO2wAfox9z39BKnkZ8+bXwU3LJeBKN4EasQV91X2SJDYLzvRB4J v9cYER1xX/+HLG9pBN8I2iVy5O7UBCb94KgYtwB22V2t+8i2RwcJ1a3x FdZCEyk9fTGow8NCmjCJSMTLCqLZgoCpWhReXTB7mlJ62eYyxD39gPFz FvuhAw==
+; resign=20460416024207
+23r.subtree2. 86400 IN A 192.0.2.1
+23r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . vt9Cxd3Qaaz2ioC4luCCwsjE2cD3ySiqfJEC4WySIs/ONMlWC3ZjKW5c yS9/R9FsXMQfqQ9tpqNpLDg09UDU7BRJPW0Ouf1NlS4sPc8yfC49v9pO 7sN+gcwIjehQuPLCweXFjuckZke92b3DTgEZJ1BxnvzIEfH9gQYmDk1K 1Ul1bmK20Q/sKA4TgJSIq7rQF5JaZ5L2xR/+hZTNDhT/ApX+0By6MPSa uEKvH2/SkPS46VfeeR4iUyJqCpzZzm4rruUq7pGItL28PPPefchebCUo +85TDv5eRVP2rRHDixhqYcBNG7HVu+G+2wmX9caZ5pEGwGYdOdhzebJQ p6ECKg==
+; resign=20460416024207
+23r.subtree2. 86400 IN NSEC 24r.subtree2. A RRSIG NSEC
+23r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . DAJWX9VaLiASU85yHGBARIl9kcBXWozpt5yQSxy6kYVY/AvG0j9SSEcY 7ThX/eC6hPgHj3MOpFfJBWfYGAIKxejnzr3ATtevOYC6xugBRoc95Uyb dYo5S17O6yzI1OU6d/ll5KDW+gX4e/1+10P6FmJLlS9AzhAjbzXXIdZQ 74dcDIQ8y/cSl7VoqlwUg3LwC4hYtXOaFsrkwId/a2Ly3k8qXNIIYw63 Phu17IuoKZBceXBDNyuQkeo0CX7EfU60M0SRtaF7vohv1vy35BVA/SW5 UPEbBDHGdy4ygJv8cCwFhcdqXm8O7aYjS3xGscKdRa+HfCl0rBAdBLdo UZ56OA==
+; resign=20460416024207
+24r.subtree2. 86400 IN A 192.0.2.1
+24r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . oREQ6/5Gy5CkKpd0m/7Nfu8dGqXe3PdR1wUrLjfmsbcx6I54VQ0l0L1l G1GjHM3ci/ngmAak+4Iy3NUiDEtUxPxXFfJHDac0QunCscGpwwDxDhRM VoyB+DnQ0DZcAPUcIiBSyS56ujIZkRvfAY2PnXH5WYR8V4CfgI7Lnq82 R431Lqz1TqkwX9XYTLcloD1D6uPez3xV/fdJ5jGoOQbQYPV+mjjDrMPm d0mqRw42ubDqrjf1wZ/s7sSKV8T2e7rnpjreoGcD/TBaGQ6JYNx6NZCG eOTGBLf2NdCkN5BacbZrXMUVCk9qmgPZJ/zlcbEwB4X4VgLjHfU6l83q p2dShA==
+; resign=20460416024207
+24r.subtree2. 86400 IN NSEC 25r.subtree2. A RRSIG NSEC
+24r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . w4jw5BOrRRbRs1yvVoAZDiW6AzBNZ9czQSIx0zbPEzOytGplgWurm7iG UyHCKSnOzB4TQ6hjh1OuuQXYm5x5iJifHpLD+o8aGRoae3hnpHBkGDn1 7zlPCmNpzPrRDCNKMwwMnvzaqsXu3bBfh718dVN1o/kiFF+AWEdDZaWE 3TkAHpDIa+UUQr+dA2IEdNMzTMnH/iezAQyejxHdQLw1/eYiWOmvjzvZ 5lRiihRfTCumJXtTeUko/FbqB3mdt6ioZm/RYbONw2ouZ8OTys4BOsqe Y4pE0QSxWHqKAU4pynCI3unZdE3ckTAiu1GxlcTwujge7ifjKu+JuBdJ ynGItA==
+; resign=20460416024207
+25r.subtree2. 86400 IN A 192.0.2.1
+25r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . R4hAmO+OLOqxjHBlu5r+I95+zNrbT5deDE4C7hoStCut873rs7GXs1Ti ICmud+4oWP6w22TD+Vc+cnt9GwtRY2oZFAomfaZVPyqiUrxDI5Abd57R Nc3C6la5u86Vh/rU4dTaVhOxCe0g5365DJba3x1TCJBh9MIlLXdZC2K5 jmxEgrYatyo7tDQv4EFPxXB+J4j1IK29llcEmCkdHosaNo81bEDeH/kZ l68+SG03Fq3mHkgd1EWPs6M1IYOXVxBKhoRQZ4e8K89TAUAsyscsOVje HEg7BhfOsWtuuyMPNqDq4NhYVEQR3VQIMzMDRhJQ1njIrJgVzrW9AyQO YPVKOQ==
+; resign=20460416024207
+25r.subtree2. 86400 IN NSEC 26r.subtree2. A RRSIG NSEC
+25r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Tt14ZNNTv3ACWX5Qs41v7fB58iGZvKt4r8gDgQWSHYk0eefMrQOV7Qob LWZ+MQZXqcuNwmpbW+c0i3gsHywsU7wZTyXIJXhEHo3AKYURDf6FIjlQ VXTmLmaNvvA+51MuKzv9zyg64V58xIl44IClvNde+vEgOukzgH1UNkjL DdZKT3JpZfThPtPR5TPsuKwqKqtKsod9/D9JGNswow0ebFXLEA8X4qZG +4OfDIU0OoiGmN/5QXfor2p0RTeHHkhan2Nb365qEg+wdigmVTPjLFSv 8p2b/Mhkf9HYFv9M8/8PaXNhtAZ5whjySb+iRvTwcA5MyrXugI0nKqpH jDyBQw==
+; resign=20460416024207
+26r.subtree2. 86400 IN A 192.0.2.1
+26r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . aVWoA576Nhf/V7aCHPru31D675EVJHxtBqMA1jAutDOWtQIRnuz9CoS+ 6zG5mfywi+MPxMYHpcGYM+wxQkQjVMijBBkD6QBPE2Pf49VmYfD01AUZ R1CM/CdVZi81w7tjMDbKJT2XQs3EozsdsjyeUrWWqmtv4xnWgwPwSBcP NADFeuXyWhyJPeVIbR/S0lqPkS1e3XPZaUWn7ipe01e+dhHvMbZU1hZS y3h+EwHdeeTzG/0prP0EROMbRZflfUEdS94FAMehBDnG/2feQiKRJsTL rnrZ7y66yWvUvjHnfgW4XqAsDPq3LzEGApbvEOksdVTb87o3VBFmFpRy OZqQYQ==
+; resign=20460416024207
+26r.subtree2. 86400 IN NSEC 27r.subtree2. A RRSIG NSEC
+26r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . yBNyvINpDip6j5Pe8i2lmYd3MNeHXQrW4tfOgqzPgd3fIpc06kYSG264 FchLrX89Bsm4q6/ZlfZN5XpYHXYCwFzNWaC+CJJQh6Wj52S0UKfAsTRA 86jxe1Y8Ld6kFdjE94UW/j/l3VO3j6oZw96kpTj1RH6dqPtPxGOqhbWi BgdoMBmKV+TCGHXEhEK/MQ/InLrBD4nE40Ryr1kYhGmqvFq6OBrYwSX3 JN5R3NJQVqqkE1/cQxaUKhJlw515hucNar37ZaI3IF1G9xs5cny8HVdo mo/CSBBumcR/1ByIy3S8ZYqJGwtkTGj3E07JXVgvRo+04gxUS9aEBBD4 cLPf2A==
+; resign=20460416024207
+27r.subtree2. 86400 IN A 192.0.2.1
+27r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . xrpHpVUJTEBYfeJgoVXr3JDlXNT+v6G/S2sKYlYwpQO0w5/gloxDJFL4 0X9tEoUF0tvV5+zsqRxbZD8J5PWJlWMiee4CxzyfZtwOYRgq5Pq4hUQX T9n6jfNlL4xSKkvIFz5+upIzqfopZwFo0nd7LxUPLDakBdMMJHX+6xA1 ITBktxiCrm/smFzcIUCekMXDMBXrScntqdutctOYYmoAnLIerJLP5lcv yp+NSjZKaDCV77kV7jOf4yJr0LNpV9+TlVCQMFOUSlQiT+QtoydPoZ16 vLSKrs3jUkFNS5WgzIam2EG8KYAutFxD/f1p4mCcYtlD/axOi5lALldo UdAZAw==
+; resign=20460416024207
+27r.subtree2. 86400 IN NSEC 28r.subtree2. A RRSIG NSEC
+27r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Sn1ACKuYHZBNOuLZVaKGDJKqcEQCcVBYjyNYdXez4uPCwD4YipOAjVk5 fNbse4YUxwokWGUMA2+vo6FPCNtL4aAUdbBlbdN+wso4C2vo38AljMRp Vta+yY1QNQwQ8iocX5njYJ3PNqCqzLaRvV1DPZLNgzwjHGD/5aUlQzPl nOUwspcOA5QRT1s2yx1WkDIqJjkYhNXFsp3Yy6FZR7CW2QFvBwlGVjGs nq0K82oZJfU2TAlnWU34hz+NvRYG00irQVdsd7M3OhVgbtaAykdse+pr PSYHbWTXFrrXwTY8RamnxUDPjGEBc92403m3r90OxNY1JPlbecKuGQti uSjiRA==
+; resign=20460416024207
+28r.subtree2. 86400 IN A 192.0.2.1
+28r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . U/xbcFOZhpchMwPGJFmpAJZkMVU+RkyUIlwrfRpDFBASPEFd4tron+eU 9lOWuwre3SwQk2Ul0q9rCZr78dj9Dg6Hh5OgwaP9pmebsg512O+4j2rO z+oj7b9sI2YVwDX62nTxv0v4buhPzFuDjY+L0z7EdKTaUrb0N+kYehze RXXUMeu8+xVg8vD6nBOClI2KjcjUaivCJsQ4KHtBrXN0T1CoQG1KT2uB SFT/YohxC+9sTmiS6wPplxolxg5vZBBgDV0l9ppV9y2dE1fQsC7N30ch 2mSSgPm4/nZSmEX7We3TnvLaiyEoi7gSTy9txaBRRyUhQNsPTT7TJ/pK UA/o1A==
+; resign=20460416024207
+28r.subtree2. 86400 IN NSEC 29r.subtree2. A RRSIG NSEC
+28r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . A0707dBFvfAGDrHniS9iR6Z4znuSifFb9yvIUQBEcT+1+u6gbtyAhABC w+tNCEgOnkkl5fB651d9znwAzp889bVZiAjQF828v77vcMS992OZ3bvy 9XseZbdzedr4TRo1HgcdBPmxXR7a1PezrhZS5NgZxeBj4nEPfXW/MzT7 I8W9KcnQoltu0woOrWHyiHCQGqBKQysUHnpz26XVnhJ/LpyEhYbHa9WV uksBUDDXkONgBdGSfiby+Kl32sW/PgjdqTdy4+GZHk+LWK3C/D98UPMg wzoz+Um6k7M+ZrkZHwHwQde+l83nNgn7WYDPUe2KU5MlVCoGbyWKSaIc s4PKrg==
+; resign=20460416024207
+29r.subtree2. 86400 IN A 192.0.2.1
+29r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ilPHZ6aax0asJooMVb4cjhHUxgPo22Pn2Z6sXM3gEopb8Wy0K8Yds78P A0BUbioKG73l1PAXx5wM60Tx5Kvm88OiTKDhqUw55S2eUZ1h0X3W3Bgv +8+PKAWhp572gSbWlLcgDkwvXrl/evTapxgg0tvNGpXug8SYPUcxUmd0 6QqYDJIlUfAt2dMPT5WR0bdbNNGbsl4hz+G7KsBHTJxiHD+poQoxu/zK M90ZF+wJUPj6F+PZbPOxuP/bAnCA2oNHDQPNyUJr3SE51Iyp264vpgLx wtKV9nMNdSq8kyG84l4jf9EPGJsO3ZnNLe8kT2G8UE8TsS+cWmqHrw0t nTjrrw==
+; resign=20460416024207
+29r.subtree2. 86400 IN NSEC 2r.subtree2. A RRSIG NSEC
+29r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ZfXwUkPRWGLLhYU9Sgnx/JeybjuPWlT0bptlRsFijYQyxik3q2JyO7Zj AKpc8z3L0dTMyQDHqmROsbYRI+F34Sck96waEV2XZj/IxnISHuxvlBL4 uGXtVuVaMlzaCPMJemhMY4Bw3uliaDpudR2cWB5Yrq8BAsp2fUnbfI4i zKJ1RMpzG73ot3ps0MxUNs9bpIKm/Bce27rMFZ3dYfVOwQAJC+Qqq4DY h4izq2abPYrJZ3QBV5AyMP6b2j763IfgO3IVVEnMqe6l3lDadfG3vX8M 87Ow9NEnGhYQYJu/egivp0N6Vkgcz/h03rRvcvj/ZEv9dj5zpfPbM0yh uMN81w==
+; resign=20460416024207
+2r.subtree2. 86400 IN AAAA 2001:db8::
+2r.subtree2. 86400 IN RRSIG AAAA 8 2 86400 20460416024207 20180815062314 48409 . Hprna6yPTc4fP0vehuoaUXSrarTYKQCWXuVR+qkmpziqh53a9hmM5R7p CtTYOGGJuAhdHxBoUimhyAeyBn9WgjdikDrH/UvtXzi66jur0CpCdP/M wD4w3agcjtkLebjqR7iUJxZOYshqnu9YZpr34Te893c3Glv1fShnqi6H uT+TyEs6a/mDb6b6t7+ezHaE+gM716oPArNN1k/8A3BA56huUBDqBZWi Fj8ootIjauKf06HpOCEYHOH2DT9juLH8Z5naaWj5vjXeUFhuk/X3EfGB clnZVm/rqLyYRdro3T9Kv11KjI8vUvQbOrEyYkkqIAsBSsfQAKUjOHXp IIF9bw==
+; resign=20460416024207
+2r.subtree2. 86400 IN NSEC 30r.subtree2. AAAA RRSIG NSEC
+2r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . AqoSPZuchYPArsyXg8tr1Et4yhuBpSO44EpMxMRDNDbkLkNKrr+OMGKD OClSp5vW4npgYykJ3gxs6TAvmoywYT442Hw/SDhbVEZ1qIeH6eZ1BU1L TAVdldT53PyPfxek7HjC0gZyHN78J555pJRzif48u7aqsTfVT4Q2N9i3 GIsozjrhUqsB1Y3ovhXFqmcR0bTKpZncWC3yByjgwhlLFrxhPWpGx0t5 wJza8ncTpWab0DzkAiVxd/ErBzqNe2oGrZPcCm9kZ4dI6RRPfk7ZY8nN ekp5YKa1LCWP2uE5Qr0IOhig/IUFr9ovOuM7j5gcF44JR8YuPmV7Naaq Vt4z7g==
+; resign=20460416024207
+30r.subtree2. 86400 IN A 192.0.2.1
+30r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . TAQ4R6EVK2GqE3WKZbkV7vCpq9LyUWNWhEMZAt9732aRhTdrCa7T6tIc cqKOeBk3NP0Nu2HqoXMSjiFTu7Sqt9bWheRWPQpa+tuuhT4FOYDOMQOR GHAGyg0vWllJioJnwAUbF25PAxSrT7pyU1j5EZ+svmbbUSp2LFzDNPno exbe3f6C8MobjlJnYq8dkS5x2IfnsZHrG+IBpCAaTCeBFL2lX0XgbkoW CIjSgU7akg+J1vbZZm/W03mY46U3A9KVepnxPX5koIHtlWrFzywdPpwm 3dJHQXz7azK3/ObzW7zBkF6q7qy6fwxQ4tnrOo9q8+owHBVIJkeoeSib jS/tfQ==
+; resign=20460416024207
+30r.subtree2. 86400 IN NSEC 31r.subtree2. A RRSIG NSEC
+30r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . wS4eVreFN8KNi72+TIjrs6mnNPKyetFgZa+XOXTBYomcpB/FfJTfwTxu sSNbWXPCPfB/ebMQy3hEU9dSmEfUjsjj8+walUzihYdB1zFD1Uu+JwqE /xJO9YIbnzw8yg80bzomeijhHQ84avfEsJR2Arekxl/OcPBJE087bKxH JYtM+atz6gyoYFF6HjwEOetotnIWjKGfD2cjFKjGpIWpcQQBSBb6jnh2 /aHxtZoZQy84xnh+eH1ATFnqo2Tg8803CSDIewbj0wmnKGBBpiEvjJF2 O4jVfcmO3NQuLvFCOe+UjGdwV6w3yrSOXsBV9r/YLyYEvpY/1D4ISruW SE9Gww==
+; resign=20460416024207
+32r.subtree2. 86400 IN A 192.0.2.1
+32r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . lqk6YrQbBT8MuA/E1BYoeyQz+FHQTLDtEVPCqCaZJv+wLfUMbEUAMP6/ kZrGfqjKSzVx1yGt1JiznUAmrR56TvGqt+f3XLVum/o19P3wgHgvMjF4 /l+68dbeFV0Voq5ZyYvjJJEXm52lYmJXMFIVnG9ReNWU2u5NHa3rq7F9 5jyXOkL4nf41DH+TYgMaInugLn2ILiv+xFdluunl32JQ+CRY6dJ9gGh1 2Ji2Z8exyiDTw0yzMy2d4Wx8CFVgq4bODj9HOvUaOrhkqdFWx6Oa6wSd U4ilIpiSo1jJtpXmkydJfJW2ktr6hXWYKrimR21N8Qx/x+AnfbuRDvLA ZtPSDQ==
+; resign=20460416024207
+32r.subtree2. 86400 IN NSEC 33r.subtree2. A RRSIG NSEC
+32r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . nlM0hf5RT5YJpc6bSoTlpxtdnDcEA8tn8zJdfqscAW1ryvgvromem+6t 6xqT3S6gsfc4VTyWDsQovcfo06pqJ6/MYGgIoxG2pz8KXwahAnCvpGvg FKb7tw6iTRH80Y5AI+05X+tRP84szyPora1Mslx+2hs3yU0Ksjxb4DWC GGxCREuhl1gcoVaoCwFLym/fo2dc05Aot3qWwQ73SlzkC9rLYIqSIr6o X1LTNhQhM88HnV05tMyqAFOwI3QBMwqAadUjFH0sTTKk/7rdxBp1r7KA Ovj3I5zA6kGvzEj8QEJ24QNy2de+muOgOyiBc2irKJiR6Hcs4WOq8S92 5bMyug==
+; resign=20460416024207
+179r.subtree2. 86400 IN A 192.0.2.1
+179r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . LrFGFdv8SxFduIWMEtdjxDERVMMcMOS9VBgCc8C9yytjbzMnOJMk87OE pDOAmeeQNPKrVWRm2hmj1+m2fJ1yYeIweC37OQsODBIlfNVGjGr1QjBL srhOzgO7944hDMcn+9ieyTsAVc2DN0wnMqMceYwc/gMUSmFZvLq2cWJ7 J9d7pcvPKuFB7pG7j3J5OC6qyLM1f84eCsJ4ACHHwq9yDOIDR0U4mPuw ENlaV7hYWbv8Z6ToDzSOUAaUWDU/ux+nJ5F9jyK4gpu4gBQDbPhpTU4N AfPUBDoX+bVOqfMvXezMtLlGAH6N+bJqqqhE+dnnPTa1cJdU6tRekdGG xTlKhA==
+; resign=20460416024207
+179r.subtree2. 86400 IN NSEC 17r.subtree2. A RRSIG NSEC
+179r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . RfqIuAFqyazXWw2CBSNtbcPHzXPGCx07mw9lZUYFupendhDzQvM66C79 60qWJZY9wZ6CK28Z2j9ga2mfqkR8yFFnYkEIuDNs+J/RCcPYT/CGYFXE COv6Khoi+EjNTWKMACXU7noHW/zPHrR97M0UnakDf/dv5TAhqbXrRZgz N7bxpEofHDAM65DbqcrLqUArGWVPz1Kv+qtFW0y7XvuR9hgvcf0iAV3w bnnuRmkntHXAY8sauP5VgM68pw2AVvD2Nv8ISSC5a9amSHaJ88IRjz8Y zM9vA7cfCdYEFSWl0+RFjI9SN9H2TOaWKx6eThr2+oZ31L8kg6+WvtZL MB6Avw==
+; resign=20460416024207
+33r.subtree2. 86400 IN A 192.0.2.1
+33r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . rT6kqQOhR1sFb7OBZj7I8waE84EkXeUERjRoqS2zaPmo2xcji3DzsykK Hn92fZGLnx0xqWKM7a2eaLZgd3UJqu0OMp9BqyqD6L2eHsr3RzP8I7fq 0Pg2R1eTmILdITobl49Ef2NB3e3pS8MQPFS1zBbPoOz4koltU0JedGLm TJcq8R7WAS4sVDzqBB10N5EkZw9f7qwZnYMCdwc+Kc5gbF3b8RDyuG2X /7cKUamFjOxa2vT6aZkciY2LlIjIo2Sov2q3GCKaZXO5gAjTZjx2zn6D /YVGwrQ2+2kXgodu4Jmz1DP0CPbntI9AS7MEU+pcwlsQsZeqBrIvshj6 ACU/hw==
+; resign=20460416024207
+33r.subtree2. 86400 IN NSEC 34r.subtree2. A RRSIG NSEC
+33r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . YWg57hOL7GY6L335NC6/SAKzYEN43au0NwkUbFaUqTlYtCFf2eOFjBvV tqkU+Ft9zXV4ATqoFm5dTLRHsye5Ahx+ie/Afm/XThUKtPwJ5KTJuPei eDH19gj63Jt9T1e2BnbBNlWTWWicRBbsc+18qnPYZjdxc7KKv9RMEWmE sGp4KdmSbPAXFSC97924oltJFQeQzSwrVj+NxbvwwKjLtSJziyF16wTR sCt2XGmun5dI6hwaFAydTSgGpjeSvuCJs8KwOmRJg+ofCOluXgPbFaaf 292CyrT1QhZG5/N7PHrsgsixc7YcUHQzmCpgWFCcW449MMPwPP/IteAX AK/r8A==
+; resign=20460416024207
+34r.subtree2. 86400 IN A 192.0.2.1
+34r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . qcimjAuT269n/yygTYNnWHtjvZHyXfBabyB3AWDCnW2v4Sku0tXD0Mzf Ps02oZFoE7lglN8TYoqDlucvghXTUCpdw/Xrf2ijSM+/ulsOWzq5Q5Kv P99kO+8cbaYyXPbwLIHTLiZrxxI91yfvThyDylw1bENWcU1RQIjLkIE2 5dMkVpi6OWIvjFVyOSR2/bFn3E5pe/qJsoKlQ1H9S09vEo/TD7zRI/zl hNBdp8HFpY+qkEOMCfGyG8+nbEXprxKbrH8mMBTM0e6HI95jBWbfM3yJ B+Z0TXRISYQN1my2RH/2W7PxJnaV97Z/+bT+tsb5p/Z1ihwDq/h1EamS gBPxtg==
+; resign=20460416024207
+34r.subtree2. 86400 IN NSEC 35r.subtree2. A RRSIG NSEC
+34r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . BK0DNEGbK/AHsdgiLxzm8JVE5PdwwyIwn5z3lLtZ3YrR2OTFmxYSEpdU DEPur+1XiIMxT+Sb2yoNTXxK+gwb6HGIQRdTh3o8k1v4QLh9RbaARvO0 i+/TzVnGBmE3K1mXq/PYaV9m66vkAJq2dIs8DV1fCbQNNowsrjYso1nT PvRL5grVwt2bYq3qxeHByYWJ/XSNqz7b+ze2ZLa/y3FYDCeLoEF/zaT3 AVnoRvFqo0nvl4mTpY4Lh5IDg5XbJRyqyYjg9Y4lHJXvXiGJaTN1yCOW K02dM14Yva4eGp0HQLiceaEzlNOzEbFnNrehZTme4TIfONYLVR7/xuVC X+vEVQ==
+; resign=20460416024207
+197r.subtree2. 86400 IN A 192.0.2.1
+197r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . TLip/k1giQhyMSwC1uCfuRILSHacd+aUA+0XhbEsh8qs39mgZv/DdY5E 4xJaoZ4MzjmkMHYPofxwh/hXo07b3KXyzbGZq7ujMSsuNUlZ+gjZbzUY 6aV3zYhG5ucsTAZmBX4qQdc3ENVkz/oVDA5SV6BXgK2+b401gwy3sV+3 uZu/g6TheRyt56xRZI4Kc8NRxyjqXFBsZLJ6qTz6+WLuE/c+toy6t825 yPZKW+ZVQJ+qz8SThKZ3Y7KSRUTE/F0DWb6flkenVrt8Nw92Jps2wTn3 tnzmkGjkYcw7pB+ZZPs07zLl5euy8XSsfaSbEgfAGEg49JRwtdEPfwkU m7/xuw==
+; resign=20460416024207
+197r.subtree2. 86400 IN NSEC 198r.subtree2. A RRSIG NSEC
+197r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ACb3fWFqMV5squYz2Tscj7wvkUgL/T6OTb0dwFEBOqSqW765Dvu6qYEH fW0kZ3bbHgPNXwiEHBEa9R3QwBW7uBQtflGYy2OvuCMzh40KSE9L63rj uSpEzN/TkzncNO6U1UaGnYhc2BkfUCgWNZOLAZ9EzoFxb5aOaLMygrYI W27zzx0tG21v7WFlo1aSEpHHbIYTcq+JzhuFGDPSkeJarCif5ZzcEuJK 8OtqxTPj475hKBAv4WuC49wX9+n54koePs9KAyAI3qrkUksK4+JgSmB1 lJgW259pQahZTUrnZUC/HK8reOe+jlsYqKyynZ6lSI2VUUdbqvezz3Vq ZjiRBg==
+; resign=20460416024207
+35r.subtree2. 86400 IN A 192.0.2.1
+35r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bi5mS4szw8tn/sWCtOn0l7C36ckESCPGT9F9ONJocCnFHLpLM4TRStGX I2tKmsj0n9uKcF4zrIGGdfGSnjiHSMwUFC6S2HIS1vwEStNUtB9M6M07 gHr9uzSYJ/3IqDAtbMUgvmzdPq3ZieuKLD9HqohgVbxJHll9wp8AKm82 M/5kVgj6z6igfL6WJh8b7kXaOjAodcLu2CO3yV0A75UxXejJhFEarGDE gOcz/WXC5EugWfo3tC4jWzUGTAUtZXmSblGRlwQlDxF8xMhNguTnmKi5 KdBOVK1Det/MmrevbIH+xPkM3jSj980VBgug51VjjYqffgfqNJa85PWA nmaGmw==
+; resign=20460416024207
+35r.subtree2. 86400 IN NSEC 36r.subtree2. A RRSIG NSEC
+35r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . DgvxjQQHnA3sEgn3bwFwS0AZchch1WLPt9p/HHEFj2ZPhV5lvHkLUGog 5Kwy1MIQBg13FA4ksthXrmrfHFKVbY/6hoJQZl17QD5Fcss/5BSmffrK NNFYoWSWZBnS1fIT5GZht1PJOJaW2Tgr6Znre5qvMTzuBmdjSg7XEw7J t11xkSVGMcjDeirVuSV6f/rGE5F6sOQFm+JjIUK/eHfJnhoiyV7xfDXz C5wO11z8zOYdtUiQL0swEG9gX8agnFifILSJhiJDKvCqweS5/dQbWw7i NA8kjolnA4/d2CXSwjMNgD0dtRcECrRVZlZPWpPIYqpnOY6yTsDoSc/V GG2q5w==
+; resign=20460416024207
+195r.subtree2. 86400 IN A 192.0.2.1
+195r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . RWYPW616aK8DqdJYrm2mwQPT7pbx6/XgT4CYEHnhHh0RZNidjGY5YV67 K2+PzglmTWR2Uzedd7p84lbyPO//1XNaJRqeOLd1omwtYqEiCjUEPbIe MH0Z18BR0GKPbzzy9DSRAAJZnOGvsrumu0XDUGg2Ea4FM+qAkFCZR+z7 cp0H0mhZZLQIGanjRC5q0qix6ZKSxfiwD2H5Y2XGTcqbcRcrd3vny5Of HYymaLjznirsznf303S0itFM4tulV4CqU5HUHWoLsVm7qYv1WdMisrUo M5UB/AVxOt8I1UCx1BJQth68oVYABV2aHbyohA19hv7QYKeZA0EJrejp tks0aw==
+; resign=20460416024207
+195r.subtree2. 86400 IN NSEC 196r.subtree2. A RRSIG NSEC
+195r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . D0VbTS60UMRR9Ty6w2HgDmIp643V3JjSt/MI+CrJwwPFYIfjDA+8v6T7 BIo9m2QZS1hPJdwQEz/PV5lrkU0l09WD73VjskWPr2hiAQmQGVylPENW 38v+BNya4V+6aEckU/ldwC7V0y8zoN51b1gBnDYb2Yj5Kd/KpcpTcHhI na/S7oeOsSl9UufRAh9lUkjaYw8Y3m8ino6SVbDS7ANF7CYCwlGlyyBp bf2cSZ3TeXSf/Y7GfzBr7PTTUOUMW9AH5cIcbnbG056/kzSNXvNl4K0b 0CEGBZt3FTuT1fX3zKOEfhxegDHSaaerHvF+/PkdexK4SZNODoRRTnaw 0IKjLA==
+; resign=20460416024207
+37r.subtree2. 86400 IN A 192.0.2.1
+37r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . WA9J4U4AzItlWmFpWAfw3oRmA8pLslxmkE+L3bOTkF6kYty2ofFU/zYs D4YwPNotnRFcKYsTbfaoW9RNztVwykFAS4ibQz9FFgg4pnXoE67DgTLL d+VCU/hQOOcDKmg3Huzmf9a94GY96e0fb51hcLcSZlPNgay+7KyeNMWD 8qhUDhbum9BuYccVf97GhnxFN/0n4DI6hBPjeU0POeTstCSafVayBQiq pWX8cr3TcjoX8HEdFDdBtTs4qdS8Pz0oBZY4zEkZO5NhuhFXRoFnbRQ2 z5NJwhVNrcfOvGsUkJlh4offEmFjTVEgq+ofZocRr3yl/jkQkwXdN4B6 Iesi/Q==
+; resign=20460416024207
+37r.subtree2. 86400 IN NSEC 38r.subtree2. A RRSIG NSEC
+37r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . dRmtxyE/pd3HrfPLz4z76U2BLf7nJaGrzQXHI5h6Sbsh/t9eaAImp8OU jQmBpzOvzg+8rvZ+TFuQZ0mYMaL6bN1t3+txBcSA65pueyJK8e5i20sl DzhVmEvEjqkOVTu2P2iiUGUf9TNbAMVELk9W8I77iK+utruxgTUrMqnV Z+U+Mxa67i+NEK3H8PQ78mrLReXici1TjJMwnZpm+BuZU50WY5vMH3Rw 4FTwTZWzgpTnz+Vu/8Qih4VT2MmzoUsZ5npCxfPxOnOYv54RLX0v7otk JhYbUBIfkVq68mParT9bJsQwSRr0pY4Gwq+4oZ5LGzfeX6JBqyx1k3l4 laI+jw==
+; resign=20460416024207
+38r.subtree2. 86400 IN A 192.0.2.1
+38r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . pblieozsh+O0C6VPPENu2oJ+lGA18ZeEC+jYDhklIgLltx5W+RcUgbjq eWj7gjecaZMrI9aJ76J2JGoairSj8UmIzZ737pSwWghRypW/pyins5fJ lcnTMzRmx2vxfwJLS93HcCu5/kHZS0NWtGzhOZmDVy1I1yCgsXF0jbVP YGSk19tfpYS/4VVRhVBB2waiS3pLFAxqe4svVDoTuoFQU3fNRhr2bJCe Maz4J9d8P76aZklq6ayJSbBkOMRUVYPJzCb+tXiNam4jbHQX5PXN32eC soG7hSvUMLkWHv5lh6qlL6UkbH6TvBIfWFWP1249JRCzVauyydy8w0oD cVd3bQ==
+; resign=20460416024207
+38r.subtree2. 86400 IN NSEC 39r.subtree2. A RRSIG NSEC
+38r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . fdUgsF+Ooo37b/16LwnzUT/siY3r2sYOZbmw8AzAY7pUGoOkBTtiS18N tFxfg1FLVEJVEI5RgFio+UVHCXqo4QHi7+pPVX1rJUE3l3W6jWXgorek du7ltSs+0lI7eNLsVK3QOr+tnrGDraYEPDMSdFSHP6ut7l50nhA0z011 T5cDlTBbZ0YoDmTzRJG6mfcBJImot2fjnaXfLj7dnTcTepPYymaD2DzI 5ehDBcIEfbDitLesT66hkfPZgEiFpBgesVuXWH0Gw6UKtzVzWWy+OjPO sdOjIQSCQOCmTjleyqNOYwyjPf5Gk9G63fp5gv5u8M2P0Zz2YsbYpaNy RudjMA==
+; resign=20460416024207
+39r.subtree2. 86400 IN A 192.0.2.1
+39r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . P2mN37IFjmvQJS8FOFI9YmH9A1Fya7Pssvowi8aqe/6/vxLh++kIgQwb Qpi0qZ+q7hQPXHNL4sW9nnnSUL5EtTNIw0W3XWG8Z2iHbO0fQiK7rid6 kBuexJGDg7nwm0URucUQAeF4kDTeLa+4KVzGd+YMph7QQ0quUvWNFhZD sW3dtWs6Nyq/5KNgcUHnMX+AEMwHDKl5bKjdXdO+oVWlClx30bTjw4Y5 PAuDcyZ1qIJ6U5C+9FF88paUF9pJBKBIJHuxD8FT1yxibw2tjy7cceH5 +aeEAzgCKBPlyaqa01i/V6OvjuiVHmWkbe5NaCi4MG5tbcPBmFz2BpYL 0ndKDw==
+; resign=20460416024207
+39r.subtree2. 86400 IN NSEC 3r.subtree2. A RRSIG NSEC
+39r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . fewCkslhKIV8nmOAHl+4sSZfpEtN/wMQv1J60LylOq9eTDO7P6UkgWrb Uhp0Kmy3rTkSMUASSf9rBF5Kvp0gy7tSyzB/63AmXLowfc6DqXrudUXA yY6SlmsRoMCnHh4ZOLi9QeDnkPJ+sR0Hy88IA2OOoFmwVPxInXUT44m5 xONo+R7vBJbJqChf3tZQ7DYreGstYtIsC+wa3Y6rJB1SVISgOrOF2Thu PfoFhOQSySS4fZWTcB8VNA/vh739FQfEgA6T8wrHco+GeIUPQ+VrQ7pM GuhjU22bwpMIUbJBPzVPPhsQX4U2qkBQBfoMaaiE8+hR2DM1+lmea4EX RW/e2Q==
+; resign=20460416024207
+3r.subtree2. 86400 IN AAAA 2001:db8::
+3r.subtree2. 86400 IN RRSIG AAAA 8 2 86400 20460416024207 20180815062314 48409 . sU3DOOce80mR6N3WVfsaf2Xg0Qo6QnGLeahMzLs4YjwYS9XBxUd61VH2 mIvtoGFTfhoC6gy8I4zP5gIWNe5NjiS0BPemHH12i8Lkb+1oCo7KnWsH JsN3fSB6eVnDxV/LxzTCWh6gbB6Bm8q8TlcfvWXJtU5hCAsy8HgWf0jr CgVWTzFt51+wNpIARB3FvZyLr726l1wS7KswNywDUe1MH6wa5w5nFiE+ l5X2K3T4T0JA7nwkl/are+vHOEG2t7vAr1BIdMeshVKctmlwhd5liAp0 hYchVGlSI6OPItTZmNyPRfeV3THnDGmnyQG5b0AFqoj7Te0l2zWjtY2l PG3iAA==
+; resign=20460416024207
+3r.subtree2. 86400 IN NSEC 40r.subtree2. AAAA RRSIG NSEC
+3r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . xKHuiecej9QlBaMSRUrJ6v/Ypf4uoW9QoHwOegu8smoNff72DEqPJqae D39SxdHR2ScYSMC//s7MJWYersa3kNnlYf3SBwptmJ2ujbRtE8wnhQCK 8FYKm7GlhI/GQucUQ2wdepnvK5pgb3kCBXjhdOU37qVm6n4qZlF8dhdM dOk+lQVYOPQO3Y9B8mjRg3mZQlMElalsy1po5SQ3zl61hXNnIBPnx9jA 0S60PGW4ld5U4x5iB1FEPPA8D+Sj4Ws9bFrqg1dCb3XIOd/YjqVLancF DfqM284ADkrafTJ5UPV50ZfwrQZFGBLHEoQKPOmrWOyDOxpy9vYHRG8m Yf3XfQ==
+; resign=20460416024207
+40r.subtree2. 86400 IN A 192.0.2.1
+40r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . A7xKECnu9zOgb4F2UURLoOyUheOxxKcktttx79i1yQUSurRNYk6Ysjkb Q0gT51XiNlSUff3wmFoouSfhLf4VZiss86KceBEhFMjjQBguGCYk1/S+ xqYJv0UJTyFWOM4or7seTziJc8TmD48m5kkwl6//mTBzocKrzx9TDQuT /we45WxJ6zuuXqr0ZuvPpmCL9KzkNb0HDyPVqkZxhhiIqWFTyUupJP2g bMKZTg8sFw8DZpW1K/u78Q6d4tYT/GgwSI9qa4O5wh0XQiTbjF3n15k+ ZmvIxf1GeWByPPtKwNEyC/aDqWKO5ItidUEot++m7eiOd9zEzaz7Je96 4wA8tw==
+; resign=20460416024207
+40r.subtree2. 86400 IN NSEC 41r.subtree2. A RRSIG NSEC
+40r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . MIaDOwIBq4PYeIy9D1ylPnQ5HxzEf4VanIQA/gMOPh7Z1fzL8GeQEtSY +EvdfhdoepD/uWdlYufsDI+LCJcPFi2FCn5yh75IzDUrQrZwIkjbu7rP 2gc5BLldsVXeyWYzE6bzIZLQMjrtzRNrabm8j8S7dugK1K4XEaypnZy+ mW0ChqV9+GjiO50cadKsDvVTl559vxnHwJ7bqPJUPFjU2c+frvnjIeb0 zIhcY04c3moujdA2n6s/7dJrw4OrzeolRCINFXw2t/tmErIiY/cmjj2R CXwAs1VVJJ9k8wInh2sUqIYMGHHw5gZw926waaf6VMSaOgDqGfbYrhLB ROhzlw==
+; resign=20460416024207
+41r.subtree2. 86400 IN A 192.0.2.1
+41r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bsi86MRk/KpA19c6ZJzuyn45MfDYEASbGe7VST5/BBofJ8IbRyl0r801 vlQN9fR3dGhceYK8A/9TVctwQEJL3D2cOA5PC26GAQffdMhAWa0ymcKQ DjjIGc11IXrvHTD+m+WCpFoCEMXXjLXq7qizZMZgMH2cERe3gv5xKITn tFjGk54f0rPtz7D61Or1t+O3OK598ykTHerIuPtoBKl8jktGvuv4N0ef SLF3aGa/sVigDFX4BdMnoJ6JlLSISoEe2uPM3ErzF3emcK8cl922NrF6 HKpZN8DGaPrHHFrTST4/S7lrLshI9PI3WhAhZz4CaqgMD8rNM9CM19sv dbORgQ==
+; resign=20460416024207
+41r.subtree2. 86400 IN NSEC 42r.subtree2. A RRSIG NSEC
+41r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . LYwfi7/RPz55u29u6/IV1kcKwJ5kL7HLq5a6fy3jWyx5xgIEjNuiHbyT 6HnmsCqEEc5P5NJKd/LlOqRi5gFXdzj1oyXp1fzIjNCnG9Kwc/8PxusM eJ1COjg4FHxd9+ztUo6/PDaIrFC71pjPctc0GE3ZYO0q04mFd5XspZ5Z kEgmA0/BgeCGgOPfdoXQcgiSDUHxxVm++8zXwGBiPxoMHLFjZbSFWZUB GYyEF+v5L2bVIbUj1Bg0bCoNB6NjwRLC2i5uYp9UNIphsmL6cn84Mn4b 6rP2rZA3h6VYmthSyt9Ky9V25214UnSsjavwqwNGtye+Z70Jx+I9sG9k 5M6ZVA==
+; resign=20460416024207
+42r.subtree2. 86400 IN A 192.0.2.1
+42r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . qRnF+bZGZ00XSgjQKU4lCgVDrSJhVqGbS1Ol/V9qn8hvzCB4YfHWcA4C 56sQuaQ/KGIC+WmJyPNpvh9wgcBduHkS1hUlqPij0Da4dDGLMEMrUTFU RKK/2qzdUilH9Ults69x31CYWE/ezqcjevRqPbjn3cdManj97nJKhR5w EXB8ysIsctl2f33lp0RE/JPKUpazIZ4R0sWt4vv+CbR+KNiv5EPU0eWf 8CO89fy3elQNBVmPwERRkBwRunWpQpzbS014LeNg0xPn9nDAJf2Qe3i7 6ZO2zr4pHipvu5IGlxHXllgtj2XlWa4OTnzZlVeHk+28zHedGTaUFWR0 E3zolQ==
+; resign=20460416024207
+42r.subtree2. 86400 IN NSEC 43r.subtree2. A RRSIG NSEC
+42r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . UYhqKt3G81IiJlxhFCqv9bU40d5YJBIolLXs7LOF+nHQq+9gIIX6Bfff wbxMsKlSzJ9fJ1Y1+IxAXdh8Y/YlhrXR7UtoseUyq5VM6x0ocSkaWOOx N0+cRtQKZ6YhKJccGtkoNHHrri1uSoZ51J9j+LXxycJQ9HfRj/fDJNMo ymgX93WHDJSGh0avAWrr8Mb9MgGjXyFDsLR4cZNtTAUga6TGkajEyiuZ c6m1j9xP6K/KOolkcQ6kz4YK44PS8kOwmQs4/SXGPu+3MFEbRW4FxHMq p490lAFBaZJuVT5DcnOep1VRMjROIu0nsTYqp51ewyV2zkMJoUvCSnnn sM21eA==
+; resign=20460416024207
+43r.subtree2. 86400 IN A 192.0.2.1
+43r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Kvr544ICf8eFbn71gsp1sXzvkI0Ex0iJdgwsOWol2RpMZQMy0uuDCgJ3 EqsMrOs2ur4X/iQGdl7KEzy4gb+geMX+PiSI/KRKL+5/FNRUSsWWlSGl LE9ZibQOCG0JBatP2pr2tWhCtafPg0FYi3YoM5/o8j3FpwARAE4WoLp2 44sIXy+gr43SxGO3t7tqM9et0R2ZXcIxm/DXDeA0HvmXTHNht2blIwMM al/hKWBnnv7nFL/tdcj3ObBQ7acQvLHG5UQEs0KDa2qgEg7uhC5X9XfO x1QRaHcWsRUVdg27nSbimjdkmQ3EeUos2m51bKWYofyunxzKsghz/tD3 o4Zrpg==
+; resign=20460416024207
+43r.subtree2. 86400 IN NSEC 44r.subtree2. A RRSIG NSEC
+43r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Fn6k1x9T8zEmERcMIoy2xSkEAtktFQKwxssGawlCbMx3n6crJrP55izf MCX4XimmDGQhRo0m4qBJ7KHqwiD1+/WvAC/XTobA6MIaOXlufoX8pv5n 68DmKY51PeBVbXSNHUh8WYuH+6tJ30zGJvm6hjtq0+HuoG7ftfKOo2u/ 4CtdeJUHJZFHFe5fcWuG0Kw/myPHxOjnsG16u4Fi7VdVVBEPSsIjhrms fhOVNc7tmxboVqovy/pbWGF0OlkR8eWWSau2vfWObjz0tBCnvGpm23y8 qFiO4aE2C1U4Ih7NGTFuZTqjDqinXHDGUXqvJ7DV7GM61uR1da4Zcq05 qhXMfA==
+; resign=20460416024207
+184r.subtree2. 86400 IN A 192.0.2.1
+184r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . AoAoqS2lHHYIULSHCvxh8Ug4hHZH9jLaqQT7jp+xEo3U63ZZS/EU4oYn vafgLQVPT5mFOI5bqxewmLRJwypAom+B2dte17UwScQV/xdFRO4rEPyb p6evXP+LezVz7GxuOC4itvgqjv8l6nNGSNtelA/BmreFs4wMKk0+DHqC mOtutq8DU1wcBpqmY4DuRKoqtpa2qu51hQ2kEx0HaQvAb1UgI2Zw+uY/ nXER8wLzo+WKYhTGWjLDg6ESn8HpeJlkU16Pbs8A5kAv/sca5nj9TFw5 h+a9bSbQbD1aCWWEFjU72KynjkLMD1fZpw2PyqdviEaylyhf2AXgYhfm 2lH1Vg==
+; resign=20460416024207
+184r.subtree2. 86400 IN NSEC 185r.subtree2. A RRSIG NSEC
+184r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . OWD/nVsmu/buNCdLxqtVTdf3pMHPIed7KNxMYZR1rhMFeR4Bc0mEVmaz UXg5GY/eUhaQjehddrSCxkytGkwi4d1kwaaIrpoXvEIGAWBicYMmg/dM ZzYMfzayK+L1q49hjaitJy9k+sOQpqPY2dkKijHpjPf/hEE00SXVZxeH 93s7/CD8W6Eg4TvSGcVNaaugVqLkuOyeQ+tWK0Xln7nJvjv04OaQKKaP TaEWP+3aN+X7mHVQtL7HMA9+WrSS5XD/CZDiuhPozegtu9uHLhvdKtSV 1UcIuMTSwSwK5FjHbC9IYQ7OEq18g1xfp4eztDZgcB5Ol98WC6CqFesg Xkg/uw==
+; resign=20460416024207
+46r.subtree2. 86400 IN A 192.0.2.1
+46r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . VKFVihKX3Q+MWR6GdmeAUnl5GMsh3KB+fBEyvEEw19M7ynjMfZYzVbjH V+AG19Bv9yuh43xL8fHmEAQENB9Q9WBzjZtYEonjVgSw69S2v1R6+NYW PLtMpDaH2oOwiGZzLi2Qia2VmBt3Ahc+dGagb73ex1IOS6ufo5ypY6vO 8x1ASGTVbWXv5ohumDLHu0iS7D8Fy1uiufzozz1bacOurw7pujk9TD9l 64ez6AFWHC+nSP0XdojhZ8Ce90ovVKe/GCMTpx5OoSAMcjQtvX4Bg6J6 ujAmHyGyzm5hiDeiAvb8WVhazs2t06e2ydDpNCsI+X89HYYMcNqzFnuN QcDDtA==
+; resign=20460416024207
+46r.subtree2. 86400 IN NSEC 47r.subtree2. A RRSIG NSEC
+46r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . tx5Hn5ZIx9soDDoHxWHwU1jDu4gkXQAXTFA007LazLVO4n/egQY+dejh yA0zh6Y1G2f+sTlmlv8h9lh9ErNwjLmbAkkBDZabRRYzuypu3+94alFp MVyDHPOSycmJeqrJ60iMINk6rSMjK8W8YoPU08Nb6kuZzi961RXrUbh8 GmAQ1dkb956i4y0o/ziiJKqjytdxH1eioDRiM4Twq/Wf87kK/FeSq1XF S7naoPim1ByXoT5+/6iJU9eaCfGGKAnlvLo4KKpD1xoyGxkuB6qED5yM XhxYJC6XwyD+LG7DAAMW3om6pXIdyzvaJ9XAgzLTSBGa7FhjIA1IoUf7 3m71jA==
+; resign=20460416024207
+47r.subtree2. 86400 IN A 192.0.2.1
+47r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . A2e7UIuCTt7O/bwgjHxQRM+5g1QIqlSOGYUzIiEi1xrfvMS7Ap70D9PI uU/tRQJosxE8E6Hc07wesaBAAdXLuWKX2dXTJ6cjAMsZY//phpvn7u4y 18sRFci9QYkre5z4nYFL6Zgwxi1MM7NLM/J8lsTVzgoeOK2V3Ey6tpcc qH1BxUCBFgE0IWz1Xg5P/ZjIBdv0VMK/nGipatg2mj1b3szoT8h+fPO7 RqBAFU1PwBlzuc6bDi+KYqo6JIMF23qVR1ePTTXSkzgY67J7O5+/CO+G SXM3uoHBgQV13L8HUgcp2+KRYtwoAHupBCL2Y5UWoa6sB0i1fojPBdlK taE9Fg==
+; resign=20460416024207
+47r.subtree2. 86400 IN NSEC 48r.subtree2. A RRSIG NSEC
+47r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . VDLbZl5v/FtlQvH1xGkQBkx9eh98GJmAMBVCUx5x/tcesCBE68TJveyD AMS1uq8McnCk0x66Qlftp1bw1e1rK5HtMfXQEGENCBGEoXwCes8vpjpy uo85nAMUUsGvDnAsALGqe4DCuablB60Lt5OEn1pAMOun+DsBwFFlyw1G zbo06EHp0hzdaqNc0qcsjIpZDhUqen18KRUDoKfBNKpMe2IU+X3r108L G5kGMpWd3OlEFY5veK4t7V775oBdCE4CDfbSCpa+o2LZZDM4H0EEaDMt vFIYqnLoGO7wohqibFsbxYUOkeoPEod4CWZqPyHf/1Dgkx8J7yzLxiU8 1uCK6w==
+; resign=20460416024207
+48r.subtree2. 86400 IN A 192.0.2.1
+48r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Ykkc/1flKPWBnPKjhiRWy4wz/LAh8Tt3yNRhGnOGuDBwOHO/9Tq89xDT CNeDVQTf/+pLL5r6R+MVT9nhHQqgKdaIGHAy/d9WBswp3Pcm7ByqgNgL gnYwtGpbLrc8yOEkHCWHSfwhonB24itU7+glSdb/y4mYnkNAxV9ueaXv RCHIXugid+yLFUTrhdhB96qQbtlxzRxQ/enxj2b5O5YHyJ2Rv2FlKatS RqFamOUdG7IDLkCMFi17CrxdxWJZ5DTrHlLcke/AegTK1Yc3l0Gxa/aO xUN7CBYuFsB22Q00pGEISNAmD7+pm5Dc5TYrEGyoraFtPD1MNMHoQNI5 9N7vLQ==
+; resign=20460416024207
+48r.subtree2. 86400 IN NSEC 49r.subtree2. A RRSIG NSEC
+48r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . QymfCKG4unijOqKrhyvBanMddtMkStDiIBh6CvK3Nhf8hhk4OSBkytpp 3M2Ttx+jgKSAgSTqznWIneoNDP5vVcbyIYmgXDEkYtfAPc1DptzbfpQq +vszKECAEmyVVWeqSZyypp57TrIYErFlnEWor4w/E/EtyErisCI2i+TK Sc8yXLp5PHfvT7EFh55IW4vtFABm/8naMNPcjFAmcH7fb8WG9IvfmXtf pZ6XpxDXDK8qpmmI3R+3A406Q+odh1i2H2ThhHqdqN6CHvdHDGsPgsSO 91dJXzO8vk8JKnV8Aqv0BeOS8ibDr4Qn82HfnRzVCDJo6LD0zNSxZQRa iIfUYg==
+; resign=20460416024207
+49r.subtree2. 86400 IN A 192.0.2.1
+49r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ezm24FUxsSADHw205OzxUPFqiVQqmqU/ulXC8Zp0t3WyH6loCR7Zvkg8 J+qY+6UjHAsLsntIVsgbgdrz3hJyyMPNOv/S+xuxSVXsQtisEbLv36Pn JD9G8Bb9bKS/1jwHKG80/AHeEOWNMHp81XKw3Ed5rgygvtpN3qHsWU+2 eyEHgY0izOthVLETkAEbPXdz87+32GRunaNPExsd/yJuEB+y+55bXzzV zvABwWFPqujHtRiruqheAe/eb60YJigIESp4C8PKBgWoD+JEt1wyqssM VLG+M4itKZJamxhOkhcq13R517e1ojVBahJVN+ebGXPYu84KhThDqu4c FtHXNw==
+; resign=20460416024207
+49r.subtree2. 86400 IN NSEC 4r.subtree2. A RRSIG NSEC
+49r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . hdzkIuLtYPu/vNfcHDQKqNfpEZiya6TzbBl+TpkHVU3B6VhD56Vlu6rg j36ZBdTVBk8X6hB6rFjfBN0zFBz1IELsfrKIM0tQbceyZcvAtal07nCE bmDOjYBwKhgJAJpIm9FGHJp1NXj/QtKDaLgjjG0pDSieSb1GVBqVRurg D4F1Uu50O0BkvFSrtaNkPpvfnVoDl6jcXW7SxM+9AzNZVN8WXxGP5qkf 5zrAhV1AdpadSJRkCG/K2QE8s1ieNKnHunrbwZJddQmpI45GKqx6Y16m sujnAFuMhQVpbJu96ZJC+bAcDwZJq0k2yRRhouP7fGG8U59jDtdLrExp ombApQ==
+; resign=20460416024207
+4r.subtree2. 86400 IN A 192.0.2.1
+4r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . F9q3QcjC09ypEBWW24dfyAK7ir/MwOwPBmn+mJTDOV3yucmdddGJPIj1 VbkasV4bOfbAAZo995tpqOzajtv9GQXRJVnFPOXMhlsH0ivTTOpXNJUG uLIGE8LQ5bc9tBBFtsyKjmNzfi8wez7gD218BLsFcHjbvUtd9s4BKA8M bUQ8bmGWx/GXKQ4Y9M19kPq601BXdZsYgEgVSIR4BXnp6eN3Q0nI8SS0 7V38fkflVmkJ9bpNyd9RJ7n5uWLabp9zjYzeAKyEtYV9HEcwnfK6e4Rc zh6iCQwFzL1pGWj5JSf4kj7zmgFXDXtAl11cYQbN1dwFraA/omdhqCLF KuENQw==
+; resign=20460416024207
+4r.subtree2. 86400 IN NSEC 50r.subtree2. A RRSIG NSEC
+4r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . lWmq+K8ctJH9sOBT55z1Eezl4nH8cOiqOT/1NqOYueq37sasHFcaQjUF gQyI7y0yXjD28cV/qHp25Q628ykNdCI05QkFeZIRUTEp+VGtvsw4yz5j DdH8gju9y0eLgAbHz9KshK5mSAj/TkCkVs+nZIWlPNiphSS1v3o9bB+p iMW380SYckAzzcxMstgc6sjXnx7zyXyXOm5edpSbAKgg6l6x7/gjtriY VhwhVorMgUFCtVYlmaPMmTaLhVoZIBArnjAvJmjjCIgNqz7yCLxZjKKC k6HHFB00yEBM2I9AxoR28fIYuAfnjiAnzbjJPm55/ZMHdvHw7s+2vnbw pGOq6w==
+; resign=20460416024207
+50r.subtree2. 86400 IN A 192.0.2.1
+50r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . lLNbG28vWwUBWSYedEh/fKMmV8/Us4R8x9VI1mq3+I452myBhHOsJ3bl p+qOHv+cZEqo+xzpYDAUeUnNaobLBN/4j8kmfxNFuB1z/HkbRDXvJNr0 nbA6d6fTt7fJvnMql4fU3r5D6OitXeICpLCcbvQiwbneEohqtnHrwR+3 Q9WMazvhOw1a/2ByTejfZpc5sLON124g6FfVdMxC0XaRIEqYNM0nMAxF n26TYRn/IEuURr2eep1Tq7fptk5GzLyjKi6TayaTY0UEtcE0XNTAel+4 lv1F88cexbNZxjL2SHCknlMgqHHN9AS8z9A2gSBvsBm4jzRe7XkWuaKL FJA8tg==
+; resign=20460416024207
+50r.subtree2. 86400 IN NSEC 51r.subtree2. A RRSIG NSEC
+50r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . H3cmRJXJ4X45iOimYZCErjCfKfbHduVSaGI3YMtHJSogv8/Z1yFzmJ5I pn1GxWLz4vpi8QUCAZm9owO9yyTaswo/WW0gw8VLccV9GDLaKWFvycZ/ uHDXldXu3fc/Cm7PN3vfLMl+Uol4bfYFqeVZek9QfI6Ircx8yYzUGcpT LvnCHZybdEojzcrrvG0yk1LlZtRJNuGRw94hvDGLwnZ+a7bmLdcKUqEr MLN/TwNSnVql7gs5rbXVraf2aCoM63INfPn91lm2SpzwWmNac3nsBlaI r/5Hg/OsNoWGig+Rot7TgJjxtIv+VLY1+YN/hyHujzYpwyfQuIxigB8B TFQ1VA==
+; resign=20460416024207
+51r.subtree2. 86400 IN A 192.0.2.1
+51r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . gBNGIHyXcyLQ+ZU/0R3kRf3H2O8kb80etRU2/+5288n1fVE+nEXlM+Ya Oc2a9tl+XMRye0ZkATzgC1638pgnV0z5CSzFL9LyCMx7xe6W4gXeilG9 Aesrf02goUqc6UJ68OdplU5dcfdTT3Ij7Hl9uw+UQN1gD2D9CLSntQaK ME00tDN4Gyls3HdUOp/TlpqsD4ctntH1G/9L0Nls9YXVfFD3WMQNG4+M fmurYbS0pDBMKEqq9K61Yu8m0urSbg1PFueapf3873GefLT+4qzwGjta 9LOSfIuVKlQnWtWKRP96OLgTLOQABw1jP/p+DSH9AdNoN7BhHtJuQVBF D/fOJg==
+; resign=20460416024207
+51r.subtree2. 86400 IN NSEC 52r.subtree2. A RRSIG NSEC
+51r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . UEPbjqGh7XaADbhF0OL7V045Dzp5EpX2uqeEsXI9D/FO/yHaO0QJDVNP C7DqGiJN3MJtlFurpc83hrGf1SiTI6CADAGz+osDktqYVotn6hvXRKd3 0m3KUocCfbBucsL3sNQNGu0fBgEoVxvA0i02k5E00T+ltdWHLPsdSWMm SzdbjKpyE48Y2n2gfEtoaFKPonf5EmjjT3YdG+qW6CwhvhsfgDizXmWe y2vjBB5r8Ectcfk9RRYu4Ru7xRBioH3zQaG93RspAHfvcSACgastkBQy AP7fdnKq1LWCE4Kc/1zVnaS5CMPOw9vbVy2hr3geonnsRx3/+NXb7Q1G MSdvqg==
+; resign=20460416024207
+52r.subtree2. 86400 IN A 192.0.2.1
+52r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ewHkfBF/8w9XGYELtXG6Fp+d7WeqJTTcd4zMIpYKBsYKxB4XBi/YQvnK 3uYzsBV0sK3OlSZf1jDqUQ34lrLfQ8nGBD+ljyyvy5OgXgQS6MBN0u5o 5kD1wnSLFQPcrAzKjwVhxOK/DbfxoVdtSFII7gh0PXrXfx5jKTMd7HDc BipWsAZIz2twp4QeFvaEI54iwds9rotagYWmPYOoc5QlKYlxu81siI1g m3EmMxtPJ09BcGhsQvBU+djGqeF7oVzrN/juUGeQ/JWlRQYOrlrdUvon VQgwgjnV1rpFNqzhZ6L4md/SGOE6Izg+rdyp2Q+tU627CJTz1scKFAzR M21J3g==
+; resign=20460416024207
+52r.subtree2. 86400 IN NSEC 53r.subtree2. A RRSIG NSEC
+52r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . BRSvHeJ6gloEmQhGqk2jSenQ6x2lfeJm9KT3rDuA9z2kAdoTAQ+Wg9eU DJ3ntqXBL8sBBcnHc7U8MHblkt/jGbSsvDJ/9T0AWNMuBpflemuCimT0 lNnmNcIzUbOaiwubIolpP1FhG2OSA8vbbgt35Ne45GYw247YDEbOTjvT hB8nnh8gQ5G72qjl+InXtCXoP5aGfEDAOQlenvFrYF7HI7PIykQThodW 5KjEnKo7pPA4feI7FwlTghtHBZzFzOaAfHVdxzrLwgh70WQPmyV9AxBS o9LXuCcrPRtNfCOvxK/j7LpWUP4R70t6T0zR/IZTlzCtERxPqwtzDuxn ivNLgw==
+; resign=20460416024207
+53r.subtree2. 86400 IN A 192.0.2.1
+53r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FFU7L1h4L6Lioi1W8cu3Cp1/K1EJFvkv0zAZz5gykSQuqeOs1RY6eOQw qXndjRzl02Kel7QZK4j/Qy0rEaJ6ydwA3+c0YFOznWMngWiZiVmSlyRr m4PROgaZ22tMdYp7z0mdyquSD+CljiCf2k4PXqsD+C/NpKP2gUXe7agp rsuW3wP39QkqgbtBgbkezFWQDX3TOLeRcg8beXasRB3vsVIDW4VGWaKi lFJRBsLkZ64CC0yk6DXDQMSIeYmbOHVMneL2CIPDKFVJ67IMXg6IJnGC N+ADMuT3B7fpBZ4A59tl3tWDCYWniFxXsWkKVKDy3eZ1HXeJhMc2TpUd NXbwWg==
+; resign=20460416024207
+53r.subtree2. 86400 IN NSEC 54r.subtree2. A RRSIG NSEC
+53r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . PjP6fMBsBnPv9W/U21JDOZbPc+ZYfsmQPv1yhoS9mvIdJ9dvQ+fC+94o 1FHUp20e6LhIvtw59Yev7cqE7T+k2YLVS+7/WXDPbZbi8q5WILZWdFnR +D1pJL8c1AypOYPGEEcxi5tdyGJLPkenbLp2ItHY5qS/P7Wqq4GZYUp4 Hun+2aL53pb22DSbKYaB67as+MO65th+UM+RfR1yfcWJy2npxxrpq501 FAxFUKYBEpmav+nqb0EguHbrcIr1vuP8RN6P5h10ztS33Dm9z6QWSevU QRJKH0pibyjlx5/JUZW5dzJiB4KqwW3r7hW+VaimU+lgEX77WHCp9DiT tqsGhQ==
+; resign=20460416024207
+54r.subtree2. 86400 IN A 192.0.2.1
+54r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . BuAtQSYX7m9/L+aQNy+fGFjXRJXJneIsiDYy7pdQtzxzVGr3soBBZHjN fpjCCc6UhFWuTBnY6FAabq7foiZAMeEACFLG0vpSPyvIudRs0muhdFwG mh/BCddf4SKZO8tcdMmgqa+zsRDqGFiPf7HMcQtVVoNxZndRxP4/1Edw IPwk9KNFQH+N/QJkrrniEN1vGK3Zw0b9VRY9oUcItIhVmzeinA9a+60G Tt8MEZ+HQE/3yvuV4BtdHghwLW2w7Y7C8XRd3MZNdA0n4V9J+pQAFuaD 7JWPNC90jgrzIPqRVBCVLT3UtZcArGtrUsROQnL5OMdXFH+74OH5yCBj ioOZaQ==
+; resign=20460416024207
+54r.subtree2. 86400 IN NSEC 55r.subtree2. A RRSIG NSEC
+54r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ND4W1IR/Lbxy7T5te9P4gAj67ils/qnhHvJDZ409BLe0/Mh+cdJNZaF+ zERJElLqu6e0IiJI4R26AYoWNFgccDzLIEQLJRbHU8I9i+GoA0iGxevn /gW1hoFiWFNLONkjL7948n3n0qcrcNtfXwDmqjWB2IsblMpy5lBqAXu/ SinsqHuwqD18ApZlWMrQHwRKd5qyE/nOGv4Jc8/+WqAII4ViI0CuGrGG LEnx9rpZ9JOBg02SolW5xZiZ8SmGggm3BwWNti3XLjBun12leVWdBjB0 0z2gbPXapoP8luwm88eSZa+h0MHJCVB/980yCZW0YXMP7dYpshqMcCy2 ROJqeQ==
+; resign=20460416024207
+55r.subtree2. 86400 IN A 192.0.2.1
+55r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . MxQe6tBY2obbRhjbQS29CMBTrdxeHthfPokgR/NVaS5oWQWw7QiLh8dG dZKMAYul5kLUx62vL/Alke7O0yX+T8ccpWW7adiU4P7WFBTJ+rsfNsDM 3pne/vQmjqvwwAAnhHkj7BjC0gvWo7JeVzl32IMu4Q1MLRJ1wCY3kGRS hZi7WZCT2U6+3Hm0JNAAOY6Ikr8m/daWE4i2g4xWiixCNCcWN+bT/vxM 9mRBGWMqipLS0jTufklwFcJtp9/4NbaEa6v7D6EhCOgRddzSyCrWaxlL y8DVjGCi5c6suEKnBuC3Re3EvQVuf7xgQ+UHe/9AZ6Wxbjcwr4vqQkwI i7XKbA==
+; resign=20460416024207
+55r.subtree2. 86400 IN NSEC 56r.subtree2. A RRSIG NSEC
+55r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . u3Bl5V2fXDU+BYUu3Qgj15EqHUGFQho3sH1QM0wIK4xEQEA0uV7jRHQi tet74jndvgk9oUbWNr7+9nFkgXzP1ZY2A/VS2anLRQNnvcvAX8KUFS4e C3v/0Mgyz/2B9Fu9/5Ak7Aa7SPZDyrOn8X7U7Y8WWdCzBuuS+5JIAgxR GSN7AWD9I/niNSfRej3YGWYRWk2JrHOgyKrzKivBn19y3fZagc6nRv7I 4fDWVHIXj+zzHZi4JQV0gLB6kqYbWhylAoamA7lIGw6PJbLgm3FYZoe1 CY/YNiTB5mGfnIxQBNB6Lp7FgU2DbiKyVLna3Ba8QGSkiZqN/61XRQX0 qlUriw==
+; resign=20460416024207
+56r.subtree2. 86400 IN A 192.0.2.1
+56r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . JiBnpUpcjruH0PMTIpYIqqjT1ICqbDzEVTcJqtvrh5mGJKefbNCe8NGX ISiEphy9ZC1XFXgOBBdzdXikndfppENnRCcIwubE5ovpF82iVkoibyOZ KGuUaexu4n6iD0W/Sj1E13q3fmsncaES1C1dKlQg4GVeSSteJJg22L2d qIgzd0E8PaszRRlKL+978P3x7CpXl0v88/32L4p7oNfGzBRnyGScke6r +2jMIKJrWOLj+XLDUb4L0FzdaJiX1ty1B3uLDy5PZY37ggzwLerXgGQR Pn23fz19xmnD8mi+9+hZarFGEwCXeId1TkZN8sBe2Fpnx/mYavdzV8n3 OIVe+A==
+; resign=20460416024207
+56r.subtree2. 86400 IN NSEC 57r.subtree2. A RRSIG NSEC
+56r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . pMB3cAyTKGdteiNe1aPMT7fVDy9u45vKPP5vYLzomve7cnwKg+tQsaFi zEm2ANNhPCjHdDWmVah6Iq2Y6U08gB5dGeKWb82l5p7aEMIVTNRHYrGy sCJOYC2ByzY/opPw931B09HA3h6Ir0t2wxCVYWORnZ+CmLeh6AI33v8x /vUxvw4UZTTgDUrIPcfiHnSSs5lhwJxe/xWPtzZpJWx8I6UFwX47L3Xf LY85ddZjetCtu219uMiXIKwtJ4YPm09tVSnoJbGgiDrA+KT+n3npiEuL 761Ijp7HSx4krixhAW4QXbSNQ3C+OFRkgda5lVw1Bsaynvw/rcExT5ZY R+cg0w==
+; resign=20460416024207
+57r.subtree2. 86400 IN A 192.0.2.1
+57r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . mH91kJhf7yPY2QEGu1ypSJU/gbNAB0xTEBDCC9KuW8LC0zs2anMU95vZ j4v4ul5/9AwPIGH9yrB204vUFK3Z9UZMNZxejhORKlV+0/rJa2CFxu6Y rJMmkbrZNvqgIjqFybdpH4ZrMq7WrFlYtZ8rl84pNRvboN0O8DdoSAzy KdneNy4GdpYYsbIaHsByOnVG0XC+2MbpokznzmjHAw5A9BADJL0nT3VP 6wsWEdHbHMuq0qcBWGcSj826XqHqXDgv54YJReG00lA4Kbz3x6j/7I71 fA5pZrSH7y5uU1v4Hgs59sY1hFO6xXMA6JMwUEKxNFvik2W8xoUfmvCY i6UcsQ==
+; resign=20460416024207
+57r.subtree2. 86400 IN NSEC 58r.subtree2. A RRSIG NSEC
+57r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . TMfDYSO6BPtor14f85ZOdKLZ9hMsi2H5HA0x89CqYxUDyKU+fiZeAATB TzibP8ssGduHQaUs9OFkAyW8Jgi7xUu2QnagqYsC2INgYBm9J8hM2zrW J4TC9IhBSTu6i9YNShT3rUozgiHmSJwZNtcBeNOXeXhJBSsItpDHztQj dAjEW806vgusYpK6//s+lgAIMQPsMZfbPk2z2SxBdUA63l71rGjp1fPN XkHkPP/PYCqGh/iwN+FpLRNxcgI4QxfHfQSrto9U7sMgD7ltLhuKhsqo 3nGyRyrxscqapciJkx4huPRZqfr/j/cbCPlAg2TPROiWVuAy3/OAnduF jWvrEA==
+; resign=20460416024207
+58r.subtree2. 86400 IN A 192.0.2.1
+58r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . lmJT/mzPmeQho/b6Fqr+A1QZYYlEIsblZbrfmeVPzSWjPMHzaA3SXfAm qjXgFaLmQ7TtwOQycPYgisJn5lHefqVTE2X6XjploIGOZvT23m5Vdn1i vTSio7L3Z107E17gVXE+CMGwOjYoCOTJGV7QLKS2glj5nKi+v3nSxTbG uNucWG1bBtzoYB7kAXxwokFoJCSJN4CssAKeIoxuqXggut6DifuLlhjI 38huZRDzOnU/1RA5GwqkhF2gYHU3bVLBByp9qjK66azRaqJK3QRTfWMD rpNri+seVFLSsCWQmIiGa+1urma+6oHLq4HF+Xw4CdxeHR6rEJSNEQV/ PPeCkA==
+; resign=20460416024207
+58r.subtree2. 86400 IN NSEC 59r.subtree2. A RRSIG NSEC
+58r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . aJzQ4RCaukrSPm4TzZfw9VYqlt2qOeJMBhZOdTwz+CkkQwCnXK2wo1Nf TPgyL+dP7pIN8v7Yjo/oL6l3bZaH59u5AIm9W8ycT5IPRXwAMeQJcReb 0wpV1SbBzCJTTDGzLMIZdPXD3s3dHjwbe6rzfbThPiUlVYGiJcmwaU7/ DjCcf+7xlw9R1n6z+wvMpu/FCCWqz6XCWIvrGv9BH2aAH+XdoBJ4zWdU EfrB17VYFydyXBmDyN+jqepiUNxvDzLDPRWXENid0ODq2iUGguVK3avZ O8jM5F6jCYCWnDwo6n9yfMzPWrAqrx0p26Me9a7obj8yLqB8fhKJ0I/k B9b6Dw==
+; resign=20460416024207
+59r.subtree2. 86400 IN A 192.0.2.1
+59r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . I96IVUAMZG2YTYz5RUx9wQdMbxWi1F3j/FAR1Zen3JjJiia2UNf+pUx1 +cR+Tpxzw8gBCB5hzP7CWaHi6DSTAtiiB3G9VbGpXNR8Peg5aZpdTuEv 6qwq2MkOcjq/e8mo9uEb6cFvz5QGWqVLGhw0FYnsInZrVSYNccCMo/5L As9fKgnTOblgzluR1mLj4COnoJrzQd6zsPgq0Y9XXvCjmH8QOqcBNpI6 5rRt2jH9Y5triFXc6ai0r6DJHLEG64ZoRwgX/gnMwk3/GPSR+/OP+VoQ 2uzzopnPFc6wPhMBy0PilNVk8NaNwKL+1Ib4kDokel83lWnRSQ1x6Kz6 XWS+xA==
+; resign=20460416024207
+59r.subtree2. 86400 IN NSEC 5r.subtree2. A RRSIG NSEC
+59r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . OAkAaJYQNOsjiPjZ2OKi0fHojtz7FsSb3kGCtRs54ALIhQGN+wvIP3ec PlxRB7cycfmfCueFuCOVkmIlg31zcHPoJgnFmOJ/tKcjn5WfEFu36wxu e13Zu3zKRAqqkRaghFvfn8IIP0OtxHToUGlDV4Y8BmqXv7roCHowaAkl KNTTjm+x6BGHyHfMwZGA7QS1rHhvqmKOBqIDUdSxJm/t90tRs7t9HHBl +XAMVfl5tub8VY32QVhb/eWXXgZyDeFevbcmAAi/bBXi/5AeLsUwjGfA QQBnw3MC99Te6XBoTxUgIgFzYZ/UdKKz+OVPrhV9OWHD5fTeaYRWl0Wy PFFk8w==
+; resign=20460416024207
+5r.subtree2. 86400 IN A 192.0.2.1
+5r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . egV6Vshc7lVwL6tKACT8y0f0N+Z4kTiImRmwJFddB+ykfYfR6Q6Lbec9 DkaFz4RZEaMekxZw7VSID4/UAojGDiOjJfMqZ9nPIYjDEcFLE1k9Shmm ZuIxyed1VpUM2dh1v+62dX/6Wg99Sx06ZUcePA90+fTKyWK9lGCEluCg CMe/7GaPsUkxne561YGoS6rlKRnlhOqsh+shzLYhr9Udk4sMHvdf0G3H S3UVitbkfTHj7XmV5h/zF2Eaxh2512jyNBPduNFdyyVDnkQ6gmyzq8Q2 br1TslWD0u6s8rVL/sojaVqNbnCGxpt1GWbN3EPRyV7BUdad+zkUYqPp 8eD3mQ==
+; resign=20460416024207
+5r.subtree2. 86400 IN NSEC 60r.subtree2. A RRSIG NSEC
+5r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . JJ2BbHVqRR5P15+oc6/RgTEjYkaTj3mjETcBuMqI6ivYQa7ygDxyBayU S+a7CiYPrX+J/GH24GDShf+WmvT9HJoFNj7tHrJrP7jpWqkzU/v8Z9Y7 NgKLENUDc9IeSk+1Zs9Bhsce/MPIiTCYZrOX/kbUqKeXZqlZVjdcC7r9 aPdOGzmXy2PsWMGh30N16nJJ1ZWzpC9ln7onxGzf3XTphncnkWsccAVq yt4U3RWVqnq1Xey37h40E/aADjleyDI1S33UO0UR9DKR0kt3N+I+FBUq SoTK9bomhqrnEggo1jDQk7EP0uk9ZOP/C4hEdB9eBzXCPCGs8Iao/2vi eBA/Fg==
+; resign=20460416024207
+60r.subtree2. 86400 IN A 192.0.2.1
+60r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ZIoajgpZHkY1FbYMvAGK2dq0XRHaR6/PZuBM6Gz6gpF/1HxlcawMSdXx eyOf2+4v93XdalmCVWx0EFu9nW2o2cHymCyHmDuj56Sl8N5yC+a8JFoL US7CfweDgjHFs+4tc8V4IPo4Nwm4CjNI6D6ysfgIu6VI4rbul02YEFRT zdppfu5xxUuPunD4TtditBKA63+TVRU4W3I4ssPDgjBdFyPBqf31z5v0 itqVYFGpS9Rk/DEIqqQz+Gm+8sbvgGetWMbNUrVY4YS75cjdjqPu6B8v jVyAj52DtRIUHCYPKyC4MEKP8ZzCd1+2ke1yYdWQ9C35JV16SqkjLR8i QumDJQ==
+; resign=20460416024207
+60r.subtree2. 86400 IN NSEC 61r.subtree2. A RRSIG NSEC
+60r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . cefA/9TxZqQrYqdigonYLptj6AoACehR0l7LrglA/R+SYCDFIsEyRPfD igNgfaMetvxhfSK++eJGu3BAEgxOrSBMbgGkbNL7Pkebm4kF3YuRMcWi /aRTHpNNWuFwosI4gACavC7F/GnzhVk5JGRPW0kJ1sx6VJVejsIjnq1+ frCadVNUseK81rXuuVKfiT9X7Ol4Kplc/4soFLdB8HHAEWndmb2Y4INP w/FjXbvIDohkH7FlQc6VDCATHMki1IHIzt++wwa3J1K4A9eQxnzBXlQm GSZh2rGXXxSxk6ND5rXRQCNUoRPtiJd+1N39eo4xjzNfaVo7uqv3NTKx DWYPuQ==
+; resign=20460416024207
+61r.subtree2. 86400 IN A 192.0.2.1
+61r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . bHuRkXOHEvh4eGGHdXXzPYKjnLUG8eDGua0cGq7KU36z7GuaC2BKlSfM d6fRgrYFVA7p8nV+cGWzv6qFEc0wofoLhmaqWx5FsuxJZhPHfhERQ3zr PRqjeUrrpREHzEhb0NXF0jO2FKhtjILms1BRZJxtxhfffzB4tkl6yyGH MUVYAD3WaQO4Xt6NFR8M3J7VnTZn1CSk98grL6NvkFBJNifw8FEZaexw QSkApB1IZC0ZPl3mZNHQWhE3OKPdhrj1XT+OdBrKk8ogJUcRlw9YxbwR BhxB7r0m1LNxrjMSaL6AM89lsW6lVo1WUP0a2sldZA9QyDA5pK+qAkpw GqU3lQ==
+; resign=20460416024207
+61r.subtree2. 86400 IN NSEC 62r.subtree2. A RRSIG NSEC
+61r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . mnnAcqIn6fCsxbB7ZvqqNr59KzVVW+CA5FW3ZDZYCW94EZGw/2lUmQOv pgQk/XGkGWHWUvADK4yrSBo9AyklTfZMErsatVVgAkireKIYgigc/kvr MpMgYfu97LJgKJMJV9DQPKWW6E5/y6I8PL2KwnrTq7lCxPe2/SUe9ZIW pqyibjL+HFzLKLWlNm1FLEk+7gMTGWWYu+AmUQmBeTeKJeEizQ10yWdJ zdMMGjIRZv6eJy+g2K3pTuacpAZRECLQi1uqGvDhFi+Q9HVUDRLnkq0M wX//4OwUoUQR704UgyBqd5+88piLo4vk/V+O7ZgjN8eGs/YBWOYZRd8C tQXA/w==
+; resign=20460416024207
+62r.subtree2. 86400 IN A 192.0.2.1
+62r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . k/Oal0kT94HTQvOgFAcIgRt32IUiRqq0fxlHd8IWbx3f5IB5I/LM9Q9S eeIFFb4R4c2lhSTndjPmz0a/34bQkboNSdfRixHRLygN1ZRobTb8KOWH MZ1CKyq8KKZ0qWU5YfTq+ZrYRkXrcK4Z5V+yKyCppxi40vObZivcaN8r TRIYEBC0Ta6EuhHINZMvfGgxuls9K0tHdUUn90vPce5DQxVVp0CbPD5C 5Typj77qova2FQlJEw42C6D9TcFDHTeG7/3X99LOkij2CKqpbdmjqsCU 1RWXsmjTu6P/fdZLqMs34UgwQvEIuMfQcon7NyyydEj9vV5IX8hCTVw7 Oa/PMw==
+; resign=20460416024207
+62r.subtree2. 86400 IN NSEC 63r.subtree2. A RRSIG NSEC
+62r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . hZwtS+mGS0gICbQES7yt48A8h1eSbGTtfz3vj0HYUnnT732vPSjYjAqI FbKNlOdaP2thAhEE9twezzwaTJioYx1NJnBHuELBOFQsjWCQwt1hS/df SwAXkBk3Hfmy4oN4hr7UraXNQjGtrFoPUJjPypD2dfrF4CBiELY0joWp yTZM+aEkDRaotwgeIgEF3df5g46liP2V+GKIfdXpb5PuadG6XlAKyktv hi2jCZ2SSmrcirtjV4u2nZSLycRClgOj5MbXNVxKgMKvtfcVbsaaODcJ Y7pWKIkf0bUivmCy0nkY+ZeT0mnIp11PyaZoIYPSmCDSMWFh5mbibJV6 WKlviw==
+; resign=20460416024207
+63r.subtree2. 86400 IN A 192.0.2.1
+63r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . plZHoXjk91BPxauhgzc90PTZcJHKeIkZwB5PM2DcKDv6nnArJ29oMqek TExb13XrVtx44Ss/jHs9PdSlWIDy8NgLxfOnL2xYTj3/FRJ+/QAbCisD xINtFoFD4ozO+TJrbVAJ5lL1gTGFS/Gu/PBG0iN6TNkjCQ0tcjA7qAMp OVreYmVZSzbSE1W/oGQ50KnEm7ARPr/p0HqFxZNnV18MXbAkhcLA0tmt zush+sXq+d7RbhB4wXtrxbKntYH/WV/d7iIwprRoqE9LXGjZZMlN8hs4 CvgTdiPkP1cs0Aoucyv2SWYsS8HAwJx2pxhgFchOdoWwIeOch/ZHypL1 gULPqA==
+; resign=20460416024207
+63r.subtree2. 86400 IN NSEC 64r.subtree2. A RRSIG NSEC
+63r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . IlmuIR96rM8hkRBdmhMCTpVOkLz4Q6BAmlmWeY6AkFFnrfry4HjrpYXN nj+62rKC+l+micWTtCPzHVm3fshRKUG4klDtcMeNN2WJcMhApYoLCa1S HhmDut/Py7iGrkSYJbkJtUfVH5PobpcWjLvNBueBSped3RPFQcp+YHAF 1OgH4AKJNc/U8lO1xAHBp17IZsCOYzoUCpVH1VPQFA9eH821gBhIyScA l8tKLcb//OutsLlsG4cbC4unldVNj2EWllh4hz+KYXa038NsUhs3FoAk 626GPzzqE68+JCTl6kKvUAaz4OSSE7LLGEY9IUn4QvFFw8OeGV+luQ7f fvip5A==
+; resign=20460416024207
+64r.subtree2. 86400 IN A 192.0.2.1
+64r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . Z5DJ50ICaKG42eq93NThIuvUx6DmnQKuxxv8q9RxlNjqmoP+T9Bt15t8 QQHJFOacyxkhoPgsqIHFHyoB73Fl/9txgkyCTAeSTqB1YzoPzeZoMhrr PbLvCu0Z1Vj8r0Zytkz2V/QHxROfUV5gZzXqcgl18UNgb9WB0E82HBcy M1n6Z2ruawDuK6eBMf4K7t+ZsbdhCcOMx6D9foOzudWXR4Mn6FgNliQ2 JzhpY9t4X8rGU4HiRJuKDo6Rhk2WNLbyLDC2Jisb/FaK4q9gsao7bxYx VhYpvXNxaJeBDCa+WrnZ0QiPlKKWvPS3HYTyhX4KFl3gkWAumRelvNZA wWLfUw==
+; resign=20460416024207
+64r.subtree2. 86400 IN NSEC 65r.subtree2. A RRSIG NSEC
+64r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ZfAJzw5oh8Z3bbkLC8yfBHa02Fd9T2xEnbejczgGFT/rmOqSDtXifrfh HG+/8vRjhCD5IFIp4RpRQ79GY4vkyQnlFfxPFhaWe3zvmiVwWELutyKN yTNoxeiIeWjdLAMe6pSTcnhlB0vADYTN6edEoTZuQZHsJX+VuiU4nbgf SvPFocHH2KNiZx+Bk5+MmL/ProrfurhRKxD9mQQ4+2NZxwmgtJQQS2hK hKXivLssOkNS23NmPAtiID/iZQpBM7RtYjMm7CgCFigubIRuB8MYav1G cxLw3KqbegoDAStgCXsuvXQ4uQOtHxs4gI32N8GVaxPOUh/STxaMYsdz 0sA50w==
+; resign=20460416024207
+65r.subtree2. 86400 IN A 192.0.2.1
+65r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . JsGyJzO9z96GwXyROW5ZuSHeAfgqPWonnJU7Fm+4kOagLkGHeliGc8R0 UbN+kERWF1uC7zyQr357oyY8tVcTXCsnFQ9lEJcPQz1SqcCD2AtVQBb4 MRMHDa51mpMUJNdzpGBKbgsuOoQGQm8/xmzQncu7IicGl66yuamENzZF vIcsZMrom5pEnqI0FICjvSUoKNdMvVZ4NIbSuX7PR4ttt3eJ5ZhSrRU3 24h/sFh3ThNT5LcGnAF34UO9+Kd5YN+n65koVkBbfkkiN2M6JRczWZTa 5ldsygCg67x9ac1+5FZ3PrCjkOXBzY5GihT4ZW08+WX9uBF8MEzdSJSY lnjD3g==
+; resign=20460416024207
+65r.subtree2. 86400 IN NSEC 66r.subtree2. A RRSIG NSEC
+65r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . FUXNUkNiHFjR2SghJr+q7OniASnAoQ7XQP641A+PDXJY85ehtQb1B8N2 ukt5TPp1K2YHaYfa5aLOHSyUVTVGaR0p+QPODoiwWtOnwIO6mA/W2CYQ lN+eRBFQaUzHnjrUqEUb1sn9ZHCN6acQKKCAeG0dSaJECzVtndDcAb36 JvAydLEnu9fPgLyDlbTsBJG9sg+Yssfqa57dmTc8UWGMTOlZbQMuehnl 3pgWPxxgOLwnNu/OBNV95OJaxR1QEK5GH8ZLy5A21w/V8guIrwop7Zxz j22Qfhno3KqUU8DwKmZOOVuyz8NZU6dJk21xR9LOGiR+hRBaFvvZd/m5 gGfowA==
+; resign=20460416024207
+66r.subtree2. 86400 IN A 192.0.2.1
+66r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dH+wUC3mViU6hwRUsvRCawDXwb1qwxmsW3pTVi37882NXx5P05OehWdU chwiVN9tpOg3hibUiVa/xw2FwfO5gNVVinTAy53zbfmw3CUDx/njvMMr WaslVmRj6GLsZDaFZJW7lZHi6RKlzrDeKF9YiWPivbe5k5JqmWmEamVs YlxZCijW8TkCH6CX2x5xgqngLG4J9KsbHOasVj/MDWr5dV2HSAdsXoY5 oz12xzKAVdPBXD41Y3CfPW5Oje+G8KGUfcXDdit9Cofh0DnYS4WsGOCO ZwgTRZZ43JwkY2hk//N7ziNtcsefKV2NRbu9TtOAaUxg4AbOW2qS5YIB foLswg==
+; resign=20460416024207
+66r.subtree2. 86400 IN NSEC 67r.subtree2. A RRSIG NSEC
+66r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . FHLMEHAlqjdwmV2LFNE8V1zIQYPHTnMYsJyBBDg/x2V9USEK4wU61Hax dGXkgu3VoBhakpo959qpjr0tt9kGxCrifPbzpaE1UlABFyX3CaiPXQlO 3jIKgsnPUncvQXMgXV+Iz3T17PIVdv8HwYqeyc0aedH2wHXMkKJngbuI Tndi4n/flkoRsbK0F4U/DDtu9UK3EsxOz90yaELJryj5sxiIeDX6l5Z0 IJSjZLafZuhU5nunGdzmL/9GcKGT4sAN2PrYuK6S3Ipoq/QKSYPQNise ZTxcP58dTMX7qy+ylF8Lr8nxdJch2CuakEkudQsiVX0SEeuqwU8O8nkC M71ipA==
+; resign=20460416024207
+67r.subtree2. 86400 IN A 192.0.2.1
+67r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dw6mT5uSGLyaGRn6Oks18wYldst+JVfz9T8/d0f8jSz84d18Wy1POhQ6 +dVL24qYWh/PAzepU29SU7IbWmidOk6/zPXQnxub04/tIwDbUyNFEU56 IwnCTS98Uvbfkceb8+bnZvJWezuNYEg1kzUWmxxZ5Ye6sUPiNutTRIkn 0kSfUZbjpymAs10qocTnBmKduktn27FbQyVMcJuQF19DK52VVNrQ88OC WV0cB6T1XAyzElVzzpHdtNR0H83EZlZ4xDjeJ+RsOMpAoEJvd7AKMnSr Cqar59tIBHyH/5tV+3IFdrs8HI86OS8WcTrqJZFbaGjnDwCHKAOOq72c kXATww==
+; resign=20460416024207
+67r.subtree2. 86400 IN NSEC 68r.subtree2. A RRSIG NSEC
+67r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . kMqkEJCyfCgq43uNAsv6evzEdAcNt9PTSRklcVm60lDRnyu9+bSfeGVy x0SKa5Wn+agDBxGX997L6kUh8748VFojBIVso+maRkXEONXwWBLdgWCm avRPmTL43nOX6xIKvW7U5fftK+mAFooqIdYbuuWSnfbuYQS+uyrTwmp3 CfHeFryjYtDwzJOovOZuYGyU/Ca3Gx6+GvQn8CHxERlXAqdw0JcKQM6M tRg3FRt/LvqnHQwS5KUncAtGZPriM0xGMvi47ofkHqAwKc4mzsbJbFtM 2Fwemo6x3RQedMkBj1d/YbPxvtxEyfJfl4lug5PrvIMRGxUjUbKW5nRd KsKwxQ==
+; resign=20460416024207
+68r.subtree2. 86400 IN A 192.0.2.1
+68r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . qcyNaFw7+PzaNI/3KRPc6SMT628TgH/hsC17lgRaCO1SbqC3y3WRDHu6 ZrH4CcK9EzG63tU89Vg5N8USl+V5wVYnrqWveZXTG6Kr78bSW9HKXoW1 Jjeb9BVgQtTaRKt9MlpuLVLr2TEHD8irJFGR4GQmsfpk4R+LEssjp/8Y 8ofOuWiUECvajXZnct0UkYrxHTFVhtxvDtaFA8+gzVHU5s7dGfdY52pO sEN7z8Dmgrb8V6JuYi0fVWRcFaMxSLiuIiy5+T6PwLFS6lyRVaicV/qb Fd+ZAspcRvOjFZMr2tagang6sU3LJhCO+QC8Ojj345QFFEMtv3dt91wJ 5m5tIQ==
+; resign=20460416024207
+68r.subtree2. 86400 IN NSEC 69r.subtree2. A RRSIG NSEC
+68r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Px6K2z0p8+vmVihpeEomljipxs082D62eaX6iZ1UKWN301wf3C/OKJJW oURhL4BPoJzOGsjpo+//c+88b97uNAzmoFyHJAbc30tfkOHpgnR8Wsmb qfdkGXDiQMP4RVtTWwu1+PaUI+aHxiG9Ax4ldKi0ONTNzJXrqaYrgPJC EgYamDXS/kzx5C7vWTqUA9mE4zCW3R0MPm2P6pdU4AE6olcMAe56eKzo Z0TzF0l5VpXA1zSBKXuAdw5gNcAiNKA8oktpc/52xLbj2gB1pdJZvrSf /RqEdthnElT4HSwqgDH7Rp14fmzzpeEZ7SWpaWXUgk9LDV1MiEkt0TmA pWfezw==
+; resign=20460416024207
+31r.subtree2. 86400 IN A 192.0.2.1
+31r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . xASfmo7eeAQlDcnqUC2871BhPrLZo1RttsCBprJuqyzqI/U7IUwOLubB 9GUQBFC2h336R7goYUOvfkxItQdrKMHhtsE/5W/fkLIKfGQgKcWZ+o5M 0z94Oa+0dll+1B072+6qLTPJquFUGQcFTpc3To47tNvGCZrXw7rgIDv/ vpYPi8Di/djm/5nLKKgJjg9U42GnEG9sUyzGB4GOYlgixCAa/rGKKIpm AFYtLLBR4mjVzNywJ6EYVcAS9idC8hN1Dta4oni0t+3KMT5enk0ISmou xL8RqBQW01jc7WulRZEtMeoxedS4Dpnne4uiMkLxwE9KzNRgRewHMe9K MrzPZQ==
+; resign=20460416024207
+31r.subtree2. 86400 IN NSEC 32r.subtree2. A RRSIG NSEC
+31r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . f+5sionbddem8iXvDtoIt7I9805BerL/9diWmg2iqzoSgPFyhhtfXDps ++M+Y0iRvP6LRkF+zAA5OIOy+pSJbhj74ILZC3tvnnQuRk4jfT2mNqmt HmZJ5RcLCH17ifYj0bzfyp1+fUQ2yk1FEhT+zbOoVmNFyaAxzVOD8TpY kbW85FL4+Bic8w5o+j96Yf7sxqe2TLddzmEinKqE4JHNEEWdCfhZdq/7 nIm5b3pkRV+spJyRLMwRn5GVLQuMtJijljX3qzzgdCVXgs0WQAALoOzL AC6837pes52KTWOIoH3zKLKiiluZR9zBQLXMHacVapN9uUgmBWN6z+YB lMAMcg==
+; resign=20460416024207
+6r.subtree2. 86400 IN A 192.0.2.1
+6r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . DaE9dYZ9HhGJv/Sfw87tTCmdnWqfug3U/JEj/Q/7impFY6OPX3OYbwxu ga90xmO3xws75gGLMLUmlZSUWZeawsLQBmwlxSAD1GCsRgFEu/7GlCwD 23mHWYuHWtZ+8WyQrSKHmwpyjqaaFixIl+D0jzZ5sZYe2Wxpy3/IDDeo uWv3Du2W4ItR3PF5TV11sJTdta7Tl+5uS2iBxl5ohwtxM0t7Hk8tKr8x Gkfp4keCSNhs6j3KYh3Pjl5rObq4kt20icrm35nHyH6hElynADB+ZOxN Ei1XP1mj/WlH0GRejURI5/CmmdRT5oXYDY5R7k9Vwf0jz7+FJ5YxAdQm 75MQKw==
+; resign=20460416024207
+6r.subtree2. 86400 IN NSEC 70r.subtree2. A RRSIG NSEC
+6r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . L8pFJzoT7VeRfRgptXm62L1G7SGV0Kqrg6Ajx8j7HyN8EJia8hra/Xxe IqetVbiP6i65IdTciTeeKTcFQXJ+ZFYM1YmGFx9/7z5Y3Nu9KYHaNaBy nDJIuHrQAokLeqGetQmsZJWpLcTzNJjFMvXJ3gPxFpR9/NMi/Jd+XhXr xsVPiS5hlBw0lLtQ21kDWE84uthPXx4kFMbbnw337Cl5js2+tkSKV0bV NwySaZrR/cJdXvTY/xUlYm0MltX5j1BWL2x/2k44VUhcVxi6IJu6Byu1 AjD6kJaCtV6vGEbqmTk1GIfmrSsUgRhEt4mxc6jaP14ojBNI/Q1lcRRt ZkpvCg==
+; resign=20460416024207
+44r.subtree2. 86400 IN A 192.0.2.1
+44r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . qZMpq6KZ0gtpfR4vLChBPhzwwCJSCGNXkxKCrfdY/3ntM13NmxTL3pZd Eb2zyTPtqiE7EntPAXkRzr/Pg1+sFxSiPuF5rJhsh5AdT609Th3s0hf/ HFq0YfgoqWdfugIpox9HS85PfaHBouBGoV1kS9Mamch2D66CGMKCi/nE BlS/hnjaKeLHw+mKGuXLgUvwwZ7fCdVo/Rpq2UL/eNkN1wkslKU7LvgE sRRQMehCS6pjksYMSZBDm9nsjSuS9s3Sqn4XE47K4rS21Q1FHoiX7YHf lkAv3LS9Isip5HNFWw2QHXPNVNB6z7WUsdD+EHoV7lQjun0V290dC8JW nxDgsw==
+; resign=20460416024207
+44r.subtree2. 86400 IN NSEC 45r.subtree2. A RRSIG NSEC
+44r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . AztM2Ln9mLK2VNSlJbNxd2YUb9JzTDCj4uvJf9nf5HygpuJWd6tRvanr 9n0NAWeAP8ZIXLCerxYEBhtzDkz+WMinWE/vq4T4I9+9XtRXeqmKiNBe DAM8e4hMkZpZNb5CiLBHohm+rzDSg8wWKOxFB3bEgdomYtF0ajlkxKEf LIr5hccs04V2MT7IH04+mIw1I/a9PpOEz508Pn17KfKPyRxdCfirL/wk otbvIR2R0sLxgmN8FcooLQe5Afr7kviQDCHhTP/JCqxgRX/mZmXLkpUB 0T23BsrD+DclKwNEsMIX2wY9NXSHv0VKyn4/gMs9g/F3Kv25wOznk36E lGooww==
+; resign=20460416024207
+71r.subtree2. 86400 IN A 192.0.2.1
+71r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . xhl5CzYNam2ntB7v+jVddKUM3mgmZiuLR8M0cKHFt47F1bN/geVwDBXj F8VZisvz5YR0QeaG/EZGAW5wQYgCXbkNosRKnnamb4HSLlLn1vNkhJhk 8W+ZprTET/8mOimRW1K/VDPMSaRk2pObPGHt//wvvCp51xc60euq8zO0 olDmOrVnEV4LNTYS0IqQ/Zb4FKfcj2217laks4y8jpIA2RqsaMI9w+0O X3Umpw9KEKjWRz10UEW4gqv9uEm5E78e4ymClA/94y1tybxN6mymhrRv kMmDXpgTmVVRCU3UoqGTzNShXuWOY6j1GdZSav/ovIHrFmma+ijx0qnR GJHzKQ==
+; resign=20460416024207
+71r.subtree2. 86400 IN NSEC 72r.subtree2. A RRSIG NSEC
+71r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ZdQ6w2ryMuWp7iTgw2JNo4ZCCVW0tYCNz90B7wJzU1Ncr/rU13TmS7Up b44C8q89ExonsWOhUkcokaSFbrt45R41O6k3X3Ic9sQhwvyj2vpD2os6 w3rBiI9EEiGW1DdVEl7CmiRcWlzMeoAq1NyphkhUQCUytU7FGVM7I+ex GTTUNUmcB4wkT6z1T0mJXkmHk4nLfiEfe0aPLu3QS+UxLl4SriymzVms yYXn57+KFnpTS6ElCYIOPhJOAfSxEbipg5rPNLjG1nc3V7XuuE8PvvZX xTObbcBmhdK5U2OGc6G6RuKgQ2po2IGSA20O1bEbT1k2fbciKBuGLkZZ /iSC9A==
+; resign=20460416024207
+72r.subtree2. 86400 IN A 192.0.2.1
+72r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . weoG03ur8jEy+A8T8jx4Z3gqrrTc6TEd+uoqmL1rRC2pYBrnz29T/Q7X PL9XxXXpFIhoRdqnaLfaNaqZ8lGP5iSpEzWyvRSDtMcFtzKMzBcLRll5 IzjuiRHAGF1D2rPOR1oxJ8UbhlthyNGO3nXqc5JZ+tIFmf2Uda0KWtB5 rR/Qog5l5EgSxSgEshzN70D8sZFbS2IuelXjXW2aLR3eMIaH2zxuqkxP iIVuTh9CobtBzPewz7ZW9zImW6W6CgI8u7AkHHwfJkxPVUVAIZSUuux3 wdkjxDx3c/a/7OqjKBnlOPu0JNSpRLiKRQUKrjs2YyUPyWQC72XiG4e0 YZpYtg==
+; resign=20460416024207
+72r.subtree2. 86400 IN NSEC 73r.subtree2. A RRSIG NSEC
+72r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . sZWRAR4iaXT01LPWoixa3v/X02/ABRcP74eqs/4Pd9RiQdPYJPZxQR54 fA3pTBlaiG9r/Q7tkO7aHW4Ll+Ei08Ry/A9l/+JrJKJePdANItCsLoTu juGr1UCLKS5uTAef//sh5tY0o7tZIh8xqlH304ypIiAFPsXEATZu8opG a03DA78/e0hjr8jHar9VZEms6Rd8P4ietnFm4bot54E5toeSLXWVa/tV v69xQD6JmpBeNIf0A9/x8tqnnG0v3cEvbka74xWNwXQ53NbNbV39Lt6q Uwx9I3/2qlaDCwpxQMRosI4emPnF+xQSQRoPvIwU+2o0uo6kqMtzj4mG nL07zw==
+; resign=20460416024207
+73r.subtree2. 86400 IN A 192.0.2.1
+73r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ilUC40xFRAoBBb75GrehoJ9wqHjkwURrXN1RcqhoDE2/cVQPvvryXdK7 CUHTgTFznp14vLyqp055fNZgpDcXZJZ3ZhteIe/OZITv4p8yP1uxfjQ/ OCcP/0E8Qv3QF2p4BW8VeZ7ICjpB1LPtHpjsaVHex4KCYiVCpTPR0D9M 9/1TuerGWnS4AdOJA/MA7ZVxoulfTehHZ8Wkn8lhu0yMSU/UvkYDhDK6 jnYARY88vA+bw5FY4MOdK216/JWFZ064+qHnXw7BjxyTMWc20fCu0Y5a z9vo0mE46SHJ0zkS2IL4Ou8hzqDxf6O8UIGXASZh4gnZcUFM8WaxHIMj cznDJw==
+; resign=20460416024207
+73r.subtree2. 86400 IN NSEC 74r.subtree2. A RRSIG NSEC
+73r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . SKF5jm8SM52pUZ3i/U3U4ms8jLMWBbBLBAagxGcsFWZd5LGj0tRMO8P+ ZE7R9YSSgfYsNq4r9mJHqd1xwqzVin28OMuEw5USEfT8rSVm2sWnvk3a oDleBSjcL1V04JU0Rd/5fs2gwASqsAXZoP0ddzR8Fw+nKOw4wK4ah7D2 V/8hBzFoO8MTieiCE4iXB1Vr3+VZvduJdyoM1N1357axaQIIDg0G7PbA KUaiySfvkXNEHq8YNI6vNnVV/JUzZkKrjAsxyBtzHu7QiyO2q9y39qd3 l3BAyB4WZh2fsAo9KTqPLGoExS5JaPZ9LpHfzDlG7V+QxzbBRBLELr+Q Ipcnaw==
+; resign=20460416024207
+74r.subtree2. 86400 IN A 192.0.2.1
+74r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . hzCzNeHbVBD1gmpdxG1P2nVGK3YyoALpaoQ+az6+JRQBbal2E6cgwpgD Mw4jMTnBryhktpViSxcSjl8FXHovonJJFlQORxVEFAjhW40shnNHU4Ew ofPjNaeNn8Sxkpevncyv+/tRLqHJY9007GmVUyzPkW9nsFtmESNKiWVD 2IBZ3DEX9G++ExvxgC4pPxgeZY7vhj12sKaOuL+k3skcv+HOFBevfB2j dVfJMzQfHyYg+zoANGKnj7Eb0puXGL/lUIKvDES1voXhMMp+1zABItx/ vIRfMGAKd3fY6VO7/9XTq8uLNuSDCoBu+QvtbxB/sh0q9N7VWBhz/wQr jCGl7w==
+; resign=20460416024207
+74r.subtree2. 86400 IN NSEC 75r.subtree2. A RRSIG NSEC
+74r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . pSqVYdU0CflPEDRj0Mv6chdpOyxRdou1R0ltTBGAwH/HhkxUyH9bsVjT H3Pl93bDAQUU67PFMYcOHLzESUBgULyNnTH/ZIQhyanVCWxJdQXhumsQ bwaBjAbVvrVVLI3RwkcU1KOu5o7VCsX2pzJv/hbNiD9ZbSElpVUuKpWT rgr08bKQSSqgFEkWt7nlXBx94ufa2ryIiUd346q+U3FbGRcwW/YFaPsH nYykgmak+GJBWd5BouXIatxaDMXNUYpSY+z6X3fCItVO8JqoktmMeHK/ lXysyW56N5JgKtBqLUB/xIeGXC8kQj/K+YX48ZGCjlF2Wnuo6ZcnQd98 5qfaTQ==
+; resign=20460416024207
+75r.subtree2. 86400 IN A 192.0.2.1
+75r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ungkHYJHjOJnWwKjnx1qYF6FBcwyGqaVUPUiJcwYXb+VT2pQsjcKzAVJ wka4Ur4uAT2JJycfAYgsYhLU8TWXerh2H+KPUDOVjtGBtfcyJ+V3/GAA 56dGGnisckMgJGzOKbDln70wRHVea65RAv3RHQEgnXe0pMtw3PzZiwEZ n1kEAF5HYgV1CkNefcSv2eA91OZxRS/o14Tode6/xvzroa+C10dPqjXM m2mFyvfJyQxBaVxuXGc4BrJOtDd3pgXJIVE9ka9oLczx9NoyfVKRFfHU gCUnSSb+e/XWrJsHnJe9NKO0KunDbmdpGvQ8T3qK5qunboIp1unl795p LyrDxA==
+; resign=20460416024207
+75r.subtree2. 86400 IN NSEC 76r.subtree2. A RRSIG NSEC
+75r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . MQ+mzRMD/whzQsiJFOZnyW7O96lhum/QQ5/7xKJKNGpktBX7jNvgdSzK swAA6tgI7umIV2u1l+tI5wpyn0GzCRlw/MxVv0BY8TQU/befsN4u17tp QZNqhnzSsauhvxpypW5QeG/Nnm8nqMGcNzRDfQ3adDnG0hiYZYdvtBCG 0Ygk7LbuG2Ra04betRCerxKcSs7sCYC5EE3daJWf8bR43hWoJaC9Fa6n NtsCL2bc4Z5UQlzjZgH14V6RdkmhIKsNG0f9tbza19A2nE7YgDr1GvMM F/DUTONHV42taRDfXizCEJDax4h+ZcJ4wO7/DBEtrpSqeja3bJ9DbSA9 3udeCQ==
+; resign=20460416024207
+76r.subtree2. 86400 IN A 192.0.2.1
+76r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ifVnLFh/AL7XQnKzcxulNoe/CZgMEKm2UW8tb7JR89U8gUtuu45HKlOd SWFGE3VGylwEfSlt2VWL0dyAilSUZVcKXRqFRrDOrIjEIFkvdwgaTOGd u2foSS7ZdWGjRoNEo42kQnvis8eZ2CkHh2Oa53SYjD1GfX6Y0C+OCgwk zEyLleAhzUwdJbDpCfgKB8gKjXFjfLYltrHJkHlBStRt8Ec2+iX5oS6z FOccZSd1wb+Ch3EiYVxUAISyxv+riGh7U828SvgndU3B6xhthrdwiv2i W58xKvo0UQ/5hZSO5FFKzeWbruSE3BVYHsNb+uu8Rksa43FelX7R2Vzv vIGz2Q==
+; resign=20460416024207
+76r.subtree2. 86400 IN NSEC 77r.subtree2. A RRSIG NSEC
+76r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ingv1Z39NH7Glaak5WrMae8DZAw5SOqHtz8ugsdTlLWgfNAMYFCkJyAu m1tEPPek3Dn6Mj8UUSscFdUHXZ6ykompfaCMZj0msfw8CIJxQWakzP73 kYzufEJH7+KjiUQf2nE1SKlmeP2Ul1NaYB+bvYUttvXZvr9LTy0iH8Ij YdDrwhc3CslU6cL2S+uoL/qvyiXvLIqj/OAnCjylRzlvkLYWf+ISRnPk dv0f18ATAFt8ZavXCfP5Epyc7+OpToLByGu1yXO8/SqVcy+KvtCqPg+k uST0RpolF1INiI8GdS9eet4DdtekUYheoerQS4yVWV2Zv49gna1hulCO yHx13w==
+; resign=20460416024207
+36r.subtree2. 86400 IN A 192.0.2.1
+36r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . fEpn/LasYKUd8XzHc/ZM7/89uBNlhB8sncsnT8sGohJQQ/JFDNFqiIag rRvs4QQQNcyFa2fe5LHFBderzEybjn38GNMCnQYm7z4RkATEZussmPQA ha8rETZxLa12iZvILktns9Z7wnMwIX9WsfrsK/NLmAL/Z2+2st+Cszb5 CVr0ZfKBfRod3Srl/1FsnA/Ku8M/u1d3t+b5Z9ZY9m+2/VAhoLIyEc7C zK+0asVM36vN+LiOV1TnNQfAcmDnBT8s3+nepf+6j1S5LCNhm8+gfLAR 8iHb4LrdhCeBxfR1cs6pT1DzcwLTCs4PXLdmElsSxuqyiCas3pyXKoGk Kuns8Q==
+; resign=20460416024207
+36r.subtree2. 86400 IN NSEC 37r.subtree2. A RRSIG NSEC
+36r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . r+J2IoJGE1EUUQ/xifkSKsK49QyQifBfeXX8L140XxpRw1PwiaPSc82g stB1h4lgb9UoNomh9ISjEYkKmVKFdNxYmgXZRUOX+3gRvTNIQgX+VNyr xeELj2I9unlYar9JUKvRMgoWi7KuuLeu9YtT91Pd/WgUcFO0ZaVawIbJ 6BrnvHq0cth/ADQIncTm0F7DUSJdjRBlnXqEhE7rWAcYBfiDnUt4/BCP bIVaNKkzHuvzGubzjk1NPuNHKoFwoXNtYtT3z2GOuPmPr7ux0rVtE8Dp x1AmjzxaNGPBrsJhAS+dwREXGHA7QrtmxAojKmw0rJXZ46HPsd/e6BBv JvL7OA==
+; resign=20460416024207
+78r.subtree2. 86400 IN A 192.0.2.1
+78r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . OrFFiWwbBW147VMD+1Azi9/2dDFdww1gAwef4WECpBZx4lB29o2XoSnf jW2BDFz6U9jScXuSUhyAb6E+5dfITo4Qhnpx4PT6cNqyaqhRbSGbQT89 BpBPzFnnNvu0k6R2eGr0RSqZjKalFi7Lvzr7utZiThvh3FqNJoA7C6fd WyOcBnF8HahJYdnigYP5lwfN0aj3/LbiVHmXvqq0l7BUVDRZ6gLUhGMa pr92um8V7mquo4/0ilniteNLFx5/66lu0AqU+71SXB6MFpxjkqgdsX45 a5dcODTv65oLvW5AbAXqRl3TP9MbCgTfEkVVBlDVLmHwNP3LGI7e46pR xa0nbw==
+; resign=20460416024207
+78r.subtree2. 86400 IN NSEC 79r.subtree2. A RRSIG NSEC
+78r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . va/PGpGKLsXut42f7ZlV+nRB1xkwno589u+AmiKY5Du9CYP/G/M29GUn TnY2MGdgcu0GifwTQb0x7EyqBdkdm///9zfPvt1iI1mc2V+1CbiZoR3+ Jpft0+FKTDffHBkCnSeebEbEblvLPKnGr5nZ1ZMTZV044gYL5LhUzLvW AwSyZix+dVAYJkIS/suBWjuez3q+DbNdnayKR8rnz4nXSD0hKkvB8dT2 9/MrJGHxoiE944u4U47lUxAuEim1ab/qgKGZ0mc0hGCQQDvM6/QufbX8 YEh9BEDVui8puMru2UqST+ADGM0QcfRXmF6rNmlLjCoBXMi/RXLOcYaP KLSVUQ==
+; resign=20460416024207
+79r.subtree2. 86400 IN A 192.0.2.1
+79r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . JDBZnOKR5vFA9Zj6h9wIKhM5/cmOAcHDhYeG2upJGRhuz2grB3OZAaaH fp395ebYHAatSV/Fyov1y1EhShVeIcnuhUqm70CMgXZu3cjBn5n5pvjd 6dKxMbLMiAmngcX6497JYCMisSBqoyEzqq6jfe5Wsz8GSFEoSTVXpM4W JPg2Qy80k4okw6IAlHHxap4wVZPgcTZ7nT1DDwCB3nSY4oUXG26UYbRy vM6feasqo217jAtz2SXiH5Z/XroSGdb/V81QN+g91uZeUI9nl879lYE2 aqGrSV8oC6C3Ww5HpPXk3iBWR/ngBbsPEgMI2nGWOKsyu0kf5lmrSvqv zdJbsA==
+; resign=20460416024207
+79r.subtree2. 86400 IN NSEC 7r.subtree2. A RRSIG NSEC
+79r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . XAPiDw+8tcohl5AAzbSvQxLi3IiLkmAOjlDrbuGEtdCBo5+JCUSSQP/l tHF+skvmVdk1j1h0G08i4J//FwkCNlUfhYxfeX3132hv3Q3Nv9iHTK8U Hrp86DG5cKG3Z8H1j0cQCXLaE0qk2FzCgt0H6MCnl9ClTWtWQyEjCCZA 2bZ6HKLHxAUMUMnhAVoH9QoBjJoDi4N1deYz3FDbTAN/IH0K1vSgmGoP ztbNyz3WI/3KuJ4AIyISfk8nS/RRYL/WRE6w/WnxCH0/Mu3xDup3RYgX 9EQZuJQAhw+IcN7xgcxfb7kbTXym5xrzp21WUGZL5XobXU6mVGmsxYnL EutNVA==
+; resign=20460416024207
+7r.subtree2. 86400 IN A 192.0.2.1
+7r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . gvDi/djf1jvbm4oPF4vZvf6mOVOC1bnhH9rLA7s7Zyr+m6iq9DN1cUVv 6aHZ1U8tqYVkZTVu1Pt4iIAZ3x719yKSpe3FY5yBMjNWKqxXXO2P21tz X9Fiwb38WDsSgICZ3VHt33BFOhAXQYFTIZ/7pwsnZupnQgzagSqpos+K s4MsG44CbVRmUvVEoBYUe9TuYV+vJRLQcI80UTUxAIlki13rw18ZoWb+ CEBPoxV2D2Al9vFeq28Cdopi3hsN1D+0+imdx7Gz5kKtib1gnkb+xciZ TIVoIBnhDnOWm/y/rfuvXbq2G3JSGIPl5o73KMq+F/Q7hF/WQSnfnzXS KcP+Mw==
+; resign=20460416024207
+7r.subtree2. 86400 IN NSEC 80r.subtree2. A RRSIG NSEC
+7r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . ve8kD8ZLjqZM0Ke1iTOLQ1GSrNPCXcfRwD1dkZjXYT/SXV8fLVeiyBXN fi1hqjlUD+Mhi5elUkduTKzfcrLPQ2BnDQexSc3wuFgGSZtir/vfODDN FrfKdo7c5alC8vIkHz7IEVpd5I0aiSSgrBIC8ooWNRod/sRIBV8Fc774 o9b/Ef0KbvI40aIRANVNihrT0aPhA2/RHtZLbTUUbWIRXOp9+yWqJYu6 z7ox44cEfHWGkSNRb2IPRm+l8QN2HMA949b7FlxY2Pn5i6mTaWD6Kil7 RotIOwm1fkR7Jgsii6Ra8OBGpAo4Pg0Fkx76wTZh/DF+CoqcPjoA0w3K 9bc24Q==
+; resign=20460416024207
+80r.subtree2. 86400 IN A 192.0.2.1
+80r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . biJy4joHJcSotexQhJB7Mb7u5fevXebKBeDlrMsj2d7VdBRzSExwmO9i c+yM5Ou1P2i/3EkBKT3mCwRT7OjdHrwObXizdRutel87JwXDkk1xlti9 wTp4OJBEQqBPbx8wuY/ykmU40qkhY0vtluldOtTU5ytTr5gBRR00vEws 0FhhSuW5Mlsr5DeX6o8MDHaEcQm4s1vLsmI9XV+kDLuwuSHSuhTELJA3 v02uGCJswKj+r/LZ5m43sTKm9f2/IimBjhpdDqq9yv+9910aUUaW3hft xqWkWkPzKfpwmRhyu0K9VhQjgdvHwHe2jJ4UHt9Pja1dblLZm/qtLzz5 mTd9+Q==
+; resign=20460416024207
+80r.subtree2. 86400 IN NSEC 81r.subtree2. A RRSIG NSEC
+80r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . inmrH5256TzB5VtNY3N+E9K2wmIWbW+9fNaR7wXgTzSQD067JHMgUqLz 5d/QY9IjZFjlRMtv4Cup4tZ9KEGcg84l2pXNUcDr7LX31Ak0RsVkKvNx FVFY5tXMMbW2XWNbZZDsnLHp6VOQD16lcO8/gYb0tkwRGm8fPpMJ4Njk S4lWiAQNUj4RAhmAJkMSaZWTSjI4GXfC8k4oOynt0pGB2P65ASbU3ZnH 6cZFEH+lbDIrS184PBuvtucjMdYXw1q0p5giKKoxiIhJ4lwGiA7JlY5z 0UfS77lpnqv2lECMrOtXZDMirgLrPHMP9eVUP2quVkVlQCjW3ixJWgR+ eZvdwA==
+; resign=20460416024207
+81r.subtree2. 86400 IN A 192.0.2.1
+81r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . eZ4kaFChRslI+Biw9JbT75zlO/1sxWMtjNZl+fbV6lK6pl4PtoqqejnL ig4m0aQscpUMPzgIHO6kRhAeUmOBeEymvYquQyWk95X9XmUjWHyvUanT PFrpX9fPuPCKpWDRvodO3G9Y/77rexa9QYi2ocNjpHmlKtSO0zqmzoc6 nKice7Vpt/Caw9d3LNR6pUelveEtGNPgUgWMO6lWkx/uFTg1KPoHbCa1 KmVOPpAywEH4hKKH2vhvaocwxs3VfOV+x3/L/aGVQvPbB3vlsNDxkP53 tVMwq432ypK3effOvHvmiXobMErRqrz2fxLMB2fluwFXGn5TDAEtV5X9 3VO9jQ==
+; resign=20460416024207
+81r.subtree2. 86400 IN NSEC 82r.subtree2. A RRSIG NSEC
+81r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Tw3m1/C/lkX3o7qMo3jVb0NqBl9T3eISc3pRa5qZT47r/bG5UaUIj41u ZdVSFf1583ecSjAQCRhQFj+Obum3jkM9ZSqPQri8v4blXW4QNr3n6EVt rXNI2sYUPFdRT+lQw0L+LU9EWOCDVtXU3jjpujj2wKzD9FWbLXgi9S4a Zqi2UD7IwPVFmm/oGpqAEbhANJfH9pcxd6IQNsoELWw7f568BbR6qYsa EY5HWY135vtLBmALeDGhYYgxXa85J2jXqzOdsbSVexvVTuP4XiCTO+4w 8RN89br4vsHhkKXGompQ7Z7HQ07V05gLdxdj99TFbz4ILsshB01y2qWx Jr2zNg==
+; resign=20460416024207
+82r.subtree2. 86400 IN A 192.0.2.1
+82r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . U73fXbsssOg2Du/DqzXEL3GWHU79ZQ2RuWMuI5q9Dr1ymdN/8ZfI/M+H mgzet0FwhdwOtYPybBpzklJwUj1vduj7/lq3eSiApVTKbyURNX9FD70J QLb0tIujmQLAzewJHnXZTu0+gcTzw4BwPZv3od2Bfdv9LjdWtqFKzO5C 0ZlVkiM94X9rmLOlR7tZBvts9+AuC5M6LA9FCFBWfgUZk6f9sS6q9fuL /ApF9xG11D5z/zQ/UvQBO/rcFrkYNW8iery2MQbdqkh32iDSlMQe/N85 uUnHS59iLIzIHGLryWuPTNW4CPIJX7UyZ7OznP+NY+xZFXfE+BoAb+n7 KjgC7A==
+; resign=20460416024207
+82r.subtree2. 86400 IN NSEC 83r.subtree2. A RRSIG NSEC
+82r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . q+82SmeIWsbPXp34ti37GrX6R2ALUmf5LPwb7xtYuD3RtxtNnlXq5BAg LCIqW6lCsaIIu+mafCPj2unp7+sivYvn3Ts75oG+FMxHWL53S0zGKcnm p+m6uir8FvtsUrs3hBldo7NDJ3bJ8s/FzBXMVNgMHbvpqn5joNq8f33o 9nuOQ8yGH1+/m4oQDJMCnOmo/3ueS/PpfPdcnB0k3PFslkrQ6y3WflFH 2GXxbsF7ZugWrS/VVlxl3FLIiMbdxvkpLkVvzCefmuIhrQ48k6eG7713 dTWh24GetY96qacyLkZGtKd2ht9xDX2LM12kMGoytBs7F0dBuqcnIm5N PbnTkQ==
+; resign=20460416024207
+83r.subtree2. 86400 IN A 192.0.2.1
+83r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . V1hihHtRb0zh4uCzifwDQ9j9TfnG0RUuD8LU1VzRm4qBXri+aHMuMycH sT74f1xfClAAsfY4ws1NA+rkcoExm4yIrgfiOVBhoZNekG96JJRJRkQr Zid5VDAF2xUWFJhLImA5MDOmdYsaTfAMnvXqHX5LgHJT5D28fHZ8fFPy PfWgiBCf88dOgbjlx5JKs1Ou9GYsWQCqKbnwp2nFvAwpnCqK4Waa/n/E wJanXLd14GlyGvnRYh5ITkJTFf69FerBSS7zTTQ638jicwAo17hhdzol Q2642gt9iNpo4cr3IcQ4GBBXCFKv97/+YImANV7ahwOy+uVsqFiACt3N mYyVZQ==
+; resign=20460416024207
+83r.subtree2. 86400 IN NSEC 84r.subtree2. A RRSIG NSEC
+83r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . MSS+aIIC3ZvkhSN7PhPvDmLgXUMuViCgyXxkhW9KUkSkkpx4Eby38thp ZwhktiNXapsUO0URG2qZGs0S0lW3dTJdn2GauvXNkfzGKY1iWgZsVQvZ xnKU6Id5CSMgjXAPrfKuMqU6hYi1awsLqmYsNzdVxi4SVLPm8hvkx2jG OfeLeWGLWtfHr289viu7cWO1Yeh3AEqWoUteJNU6eugdsTvrWurnfqpB QQfidnh6OTAO18cyXcTsLCYCT3e4XVrBzpVUnaEacVG7J9MXcggOeKOB 6KvG3PlDpRjgU1HElR1XZdMWTU/c7vv8v30+q+i61cEauiyYRFAwBFvB BcCBHg==
+; resign=20460416024207
+84r.subtree2. 86400 IN A 192.0.2.1
+84r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ICS4/eZuAoeN0YbfAnYLeOTHjqYgOi0CFeMkzO1bC669gbyyMA7tcM6j LvgDnLwyJ1UT9Nm+sNYmh86fEaDM1j2DerRoqA9QVHAWcnPIUtBDOY7x QGMoHxnqSmSWOp18s60xNaoJm2f0Xyd8v4oJvnP2D4Rl9oHtxOJ2226p WIducgaPGzvLeZK+Ug0N5DisRHOWiE/2YvKV5raAMzo+t1yhIyjC0+mR FNWes3UyVOV2mahCKUM60g91UUjkB8tHdcswnapnYc7X+KLhmXZMGbXx FSia2cpobZPl7PLKbI2DEDFOVwjyYELQI4g3dPZ4aY0mMpAEUkRSwp59 a5/fOA==
+; resign=20460416024207
+84r.subtree2. 86400 IN NSEC 85r.subtree2. A RRSIG NSEC
+84r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . i1COi8BjDNgls+2f/p9xV58rS/3HQVZAPEO7t74bm40MlsFz3zwFwwP6 5hZxQBuH37erv/MMNbhcJo4IrFzdxxCiAKTm9vy4+Od8mOsNM3wBPhgh 4q1wdZQgMVHt0ujSib0M4VvQoh+foFRFFJ9Yi8UHJp9yJUuL7nwtmNhr 4YxihkEcRv1uS2M9ycXY6Igmr8diND1ZLT7AzLtPHw2Kkk7k140KjkI1 G5UcWLI/emknTRlGrLIRb4yUHtFa9HxEX7vHmGNbffKOYZOUrQ6Weh18 +NTH7SdOt96KH7bO9DdjySEUx2k3uusYDAq69U65ZeUWJHh5CV/GIfrv i5DJjA==
+; resign=20460416024207
+70r.subtree2. 86400 IN A 192.0.2.1
+70r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . An/Ib6WiyjTOKXYc1z2GOhDsve5WSEstyynUiKtPzFzskx4DAUz3oJXu WmTWj0fjh8lcS6hc9v7OuxaIVjzgeYy/4I3aiioC3m0hvKoCXX/a89Dg RGU/pMValMERnOPHQFJNfnn6bnLJK2OcncKeG+9xI8zCZ12vXvRCDFHj Wb5LB+B7az/Zpei5QAxv/RKXwTW8Z+Czrd5Rf8ArNGjvI/n+iJDRR/BS zGMd72Sdyxfq3YrNrTbSgSfDE84PW9oAXd1JGvOqvBeVx3at8YRKA+OW +mDxxeWqyaYHrwfBT7K+PoEDnianVszY9xgsDSqutQ9Add9AuVXPAHss B4Ec/A==
+; resign=20460416024207
+70r.subtree2. 86400 IN NSEC 71r.subtree2. A RRSIG NSEC
+70r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Aa1xQzeSjo2ddP5isYJnFrdxGIB41u5BfLPUcvC+C61s0XJBbh9qxs+G BwMfWWasjOD7eCE8Blpp8s02RFoLqcOZR2jfog/acgYBmke+NxPJb4Ga eJJltzGBD6pxrT8bwa2seocz/mZHRNEutTtRT6BBumsh9GHe4/j/7f6H 0JkKe2yrFmfeoAgiL+0QdYzvr228Drl5/Nd70xsLX/6Bp0ad9jVF9wqG 4+fdxgbVu5cYBl7TSBNfqGZZF2zH2s5XqS1W7kzy6k58NE0bHFmPsvt6 J4LBwzlJ9LuvVGUTt6DeEEKelpJi6rZDNOG4iBu9R4Upr/rxjD5uVOSu QEnv0Q==
+; resign=20460416024207
+45r.subtree2. 86400 IN A 192.0.2.1
+45r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . q5s21YBzlfcLpOiXVDIGCwm7vswz0+SKDguv3QQODUK7suHTq/nzPWgW E5qoFeZlsR2WmdNxT3DEWDW/b1LqnXqGvMIMKmtA5mJhU99qeaJ4Eqz0 5VXA5GCxc43iSofbOAHT4Cbx6pxJKY6uzetkMAz9j+8wZpG4doviPbw+ fHGr2X3Y8Cnikpw9sT9FD94evVVy/oDaIfqp12N3P91q5KkPNk7CroA7 y2RKP1L+xjYknTeiO37RBfkOoIHuIn/kj2T7s2tBiLBWdyqPMOHekP6V nNJLk+anPQF2ZSIgMgjVJsei/F+2RllGH+Gg4kNLZ8EXhg2XXgPnrU57 nb2Ndw==
+; resign=20460416024207
+45r.subtree2. 86400 IN NSEC 46r.subtree2. A RRSIG NSEC
+45r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . w/pT9IPEFwTRvgktRLWSCLiSVHQluPR+94ErsFy77t9CIVZ11Gf0m+mG 2QUtOg2yY1yBTPNIo999r+NiofSj82QGUQLl7BFi0jgfZgYHLMYwaAXr CkoVletffW8GFpA3Bw8bpqZugQdRGOQiNl2DvXqtlqexOS7af+3Ogcgt CDviGDcTFeO0AFAA/hD4dF7W/F6uPAQUQBj2wnxop8rAGnFl9XwFEq38 yvv0kl9ad2L3lzNZraNUq6Z/AsiSFsmDP5M8zVQda1okwPOZdzQivfmY 6k1WxCpxWqtVmiQ88Jp+2S7UhFgFsAWpjSPbYce7bkld0SU30z5nPfkZ W5DtjQ==
+; resign=20460416024207
+86r.subtree2. 86400 IN A 192.0.2.1
+86r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FiG0vw+/0qkfx3ZkNHTrxsNQB6rfb7xyNV5Gj6N9foOgpvvdIrenSD+t wGhgf0YhwYhCbO+1MZ1E7ShoFoVG4AOtU5sOrLuVUKJUr32qwgjYZtPc ePnVGVXSbSfcOWmsdQaGRtADIHysR3wVMdy8z1GI2r1EuG7WLOhFSZYJ vedJ0c+Zd+LOlZAyQA2RO/R3sBf/fMKiaLKXBaKsk/4v8rkP0nEr2pKN CM4ylF2oEk4REvAHskmQBmUilFha6lqcE5AwSFigeqeJGNw0TVG3rnSn 5cIfAj0NxGNwK4MR1C8WLbLsaS5nq9lPfKuxDr5FRDaWzvmozdIXSeJW OBxF7A==
+; resign=20460416024207
+86r.subtree2. 86400 IN NSEC 87r.subtree2. A RRSIG NSEC
+86r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . W2aE201SZaLS1WZeR5va8Ql5bAWmmkgd+vRO0a1Tlg5keuCHo2e3lk60 oVP6KP5N7oVEnfAZAJNTTdfvnt0RVpZbsBmvh0o+m4oVTRWgMp6TIK2D K4vTjckBK1fGT4BHCV3QPepn0cFjfRz5N3HStg3scJRYczYvv/igkR2P MNj1tnx2Q4Kd8xThuc/b8AnvuUcVxYhR1SRlCHBTHqxsYlbRD/CrJXVb xDqLrN8cBLwDKwMPOQfUOnYq4LdjzbJJLrJNjRkB/ptYmSE2YdwTCY3i XEyW71hJUcya9QrSrSDLXfeO47yuCDxzuRe7ia+cWMh63YnVabuQLd0P hzUebQ==
+; resign=20460416024207
+88r.subtree2. 86400 IN A 192.0.2.1
+88r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . ECdyI5EKeFIu4Jj3tL4d7By5WXstfWxgjZ3Oa1V/8rkOa6KRE3yForzO +F4Ao6t5CjKM5ZsKoeC1ixWLPJ2pE7c0jEgRx2Pey5TJAzrf8wVQKoud fVe6XFU4by1wPNqTXU+0Asu/uRLSaqz1gOIH6/7Ozm7P3/3xPVDbcVLA 0EbxnMZnfcSOOa9sewySVp+4eVbF7mvOQ1FwoIcJlXc1HdDUcO1UPEHE BqEfE2l6NFp71oDWXsaSXetWx4yJtLrIg9EH0N70l74Kboxy4nWfydQE ywuA2v8pjIBu4pz+ZBxTFiPs3cydNUltOAnAvHkL4wI+PKL7SpHM+sx6 YTNtmA==
+; resign=20460416024207
+88r.subtree2. 86400 IN NSEC 89r.subtree2. A RRSIG NSEC
+88r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . XHdir6VyCMaQ1x+1rLuON1wW1B1AXXMynTL3O3z/nDSTGLCiL+AVTm2u Y/3B+go+MK2dWrsZq+l8esBlps8CXDqltYReyuEIKUgnLk/MCa4rBO8L lWS1SJ/xdB8VJ/830aR7a4YifkKaKncQT2qb99iESz/1EqUZbdCNdGTl aoKFGPQd2xI1J5x/RJwad9YGhpHZQ61Uvxv05VIuQIV21j0EnlWHbYPo KCtbgDZfpFx8XVd4qp6qai+lxozgqviYcsCqHJa31iPMTdpaUBtjEOiV 3Cz9PSJHqbWrTGGVEVX+k45qXWPtcABjob4Eb9mM6yDN+ON3QEfR8Vhn aU4V0g==
+; resign=20460416024207
+89r.subtree2. 86400 IN A 192.0.2.1
+89r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . LtLaFzg/aJ2onaZKr5khKLgVpJUJL12P0WD95k6o500NUZbnlmweGC0I JbIqQIqhUlrrQkCYsMCXhs499SNmmUZ0BsOypN/BDfMePbd09F+PZz0o JRHvkf/yGjkBK0kEtZ6Crorl5coSuASum8NwR/nw8h6skZX5cH0+aHgI SwWW9IAnjnQ/RNLnTtLN8Mr5WuhmGGSkje1UPe9oBOlVbWjMAyhX2lVw AU77h15R4bR/Rf18Cz+zC6n1SsTkCRs52j/IS55U/cuJnHv5IfmajHTc bZWcFkbIwX5PMcxkyjS/4oT7e8FRoJPxletIXWxLWwSW+8G+OYwBKlGx ATOMTg==
+; resign=20460416024207
+89r.subtree2. 86400 IN NSEC 8r.subtree2. A RRSIG NSEC
+89r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . IJAqvknmXRDy3ZD8gN2zhCLYkhvHljU3UISARe7YeDf4WBkRLwK+07u7 B6JjiAJWf/qJ7qcQl4bIYxPJ5iLmZuT7bXGyt5aPWcxwk1LluU+At8cE HFEEna0yZshXPWHQiSULtXj+KAjz+rDDD4I9sjoYIY0R925+OXibYpgp 3vDoPD6G+mS7VCl1zoMOU3gpPFpbFwjF3s0kzcJOfW739JFyg4Sxe15H LewmsStzmC5Dy7KWErFPzio1i+e8xbpMvGVjFVapzd/gAaL5Fsw63SYJ onDpQje2zIK7ysaiEXtuezF1mFm/d/HJR5cPu3F80xf35F+CrViR2zZZ zJjWEg==
+; resign=20460416024207
+8r.subtree2. 86400 IN A 192.0.2.1
+8r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . S9i6MWPelsjhrORy81ifXaJw+PpOHNWxa4UXaIa9cFskybm2wx5pGQhN 9Csz9v3P05lOwDXasBEHybrlodlSY7+49M3g5yqLEnLVWiqlgRdulLcP zgNkLAgW98FixbbR4WdweG0HYbYuq6yJoNERdLAJGRhz6MHPgjYTL8uI jvQ2UcBPdeeB/eJ5uL208LbFXrOgCPvCjSxz3DGXgrpH6JHRFm1i6yCs sjou+AsF4gX/AwcM9XUmxkh5lD7HN+Ey4RDtid/DNL+2WrnLoBwjh/YB DdiT123+lNg62J+TlQPgvr4Wdemz+MTzcWkSfkjemdyYZ6W06IU0altW /Ufr/Q==
+; resign=20460416024207
+8r.subtree2. 86400 IN NSEC 90r.subtree2. A RRSIG NSEC
+8r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . droP8BigHxGz/QAEBLOgYzSmdABokPM5BRluOKY/zr9Nh/z2dBiBW1EO 1cV5GPK8lcx8toqEfu0Zq9+aWzdcV3ofvRhZ5q+JndY05X8GutT/0P3W gRI+96ilRFksLKU7dS2uj6dpsopssqkSqGRl685YowNnn7O9bB4LyVHP hOlbhd1sXQ40+bvxYKMui0SU3FrotvjNuU3u1CtGormUj+vjFSbI5FoE XkWDg3C1QsTD3mEjXctQIfL5mv2TTWkJqrAbPoG11wTtAa8Dm0/RjoUK jvnJPMloW/gIiKTyif6PV9MLIyDHSXDdvxOwV4pAQhpUm3up0ZkAv3Pe HMSZFA==
+; resign=20460416024207
+90r.subtree2. 86400 IN A 192.0.2.1
+90r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . sguhfNWje/190bkCeJ3v/75CjfdICbh/bno4hsC2ApZbC6Nq7XVTA/VQ U35g7ln+fjiD03UwTAf/k4RzA8REfQanK02LNhj56zFNNhhdnzIsJPrg sDcyzQITp+SMy1boseShRjukdgSMMU8E9igqs3S456YC+dlp2Zn4WrbN p9noTXUxsVt3/TJH0RaZBy5azXgEU1+PiLO7YNamHrrvTdcj57RjyVxe M811Ge269l6RWfuLR6ssV0LNO8ZrLRHNnxvtg8RvkbJXSmOjom7dbqEJ Gg+GA4/vHqDl37nJdFuHkhwUnVSIV0ntcGDbaNBliEj4t663iLB69Fz1 FYbK/g==
+; resign=20460416024207
+90r.subtree2. 86400 IN NSEC 91r.subtree2. A RRSIG NSEC
+90r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . O6+LuRnl9i6Rt+pAl8e7rtkF3aACthkrEbTQ3eMHyiYeoTJsVpVyPArX PXFTtXJxYQjqwPHVGl4jukLnJtDJy+x/OXwhLea2UWmpo/APCO8K4xrp DjCiBBe/S2uYnkVRN30wu4t2UqdojBGnstmsBmaIF9+oyVRf67OSiHet QOzttz+g8DGbfJ8KUlzYhPCPvIUR3Dh3jEfeAfO8CVZ64gXZwTwGZblk HYNZzKQs2zgga+r/R9Dpp4mHxyDVH1x5USVXx51Y9sXZ+kNJeclyEibd zZMli/iDXH9PHBTCXbyHBgwMmZOtNMU17k8/oA8uwPZKN1owUmfWO7Ar psAbxw==
+; resign=20460416024207
+91r.subtree2. 86400 IN A 192.0.2.1
+91r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dOrt/iu9d/CPmDnkLgGlI7bd1RDgVosMf0+Q3y1qg53EzrqtBCuIKZ+D /7a2RtYWTkZp3j+hyrhz+WHBTCfOr/KUtlHCsrOIExY7cpSTaYFSYA5c UR7qAkYsUNSBXBsnA/ucSyllfXoiFeBDlmO4wNnwnjI0F1hMJCxnn2Rf i5qliDwwlEojWPYMygYwzba0Rc1GMljsd1HLysjnRu2rslGNRx8dACRu QkqFNLOU/iqrJuWIAYCRmkvJTqdwNbV921oGOTxNJAtw3KWDNWMQ24hn sH1IDkyAq81FKDtI19BdnAlp9uDhBTWOGMJ32cooTWTig/ut3oMA/zqd gGp6zA==
+; resign=20460416024207
+91r.subtree2. 86400 IN NSEC 92r.subtree2. A RRSIG NSEC
+91r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . RRwaMaalChpe0eMu1K7oa/VKqUbOeXwhN4GwZLP8kANBVr2H+VEHkme7 2eTZfBZamuheOlACtuW8kwm/F4ZAtY1XTr0bFKTXV/J/X/eISDCj2JTW +a5iNuq1JHok+vCZmF6t6u4PVKM/hD/AttXrcjHHK2TfOdgO7rZ5gGaV 0cBjT7SeWbzB3RFYWH8imLOE7v469TGO7W7bGxDwdgyvEQ9ZCZV6z82e uQoKddHC2x3nwyrkJJ70Z2HzBJOiByQjXs6hCIetC128HEtLXoQ9ILKA s2gB1EEzT6+PxcARpK7TNNuOTNpIriDkw3vItpfp9AvTqaR6xRX5YwYC ufT4tg==
+; resign=20460416024207
+92r.subtree2. 86400 IN A 192.0.2.1
+92r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . elD3rVSaGOQbDjXtl1rMX3XtseJPSbIyVkORcBJffjom9JPkT2MenM5K 6d5ksiAlTgnSCcOf2gMI8AtSpJkSdmU6CBCADUc9p7rdF1x2K4tQ6WdY G4koQmAXGiojxihftE8z/N/xIt2r7oNMfwdfk7cxgKUBuJs/gabcJFLi 5UVgZcVqlWVlLmxKWk1zNbAY+LuCZrmnbP4nA1qQKqA/i/yMPnPcgdWq DZLGtpjFiSucVDxgaIoQQkobMGG6mMwwrWo5F11V1G1zmxx6NXvaKt+A 4u8pclsNxpDCQQcCPgg0znXPtLcyaQl8bkkg+lK5lXr7Ct9gPaWITzJE Z63S9g==
+; resign=20460416024207
+92r.subtree2. 86400 IN NSEC 93r.subtree2. A RRSIG NSEC
+92r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . IuwQACPEsgjR9yO0WItcJ7eyepFUEh9Dg44S7hIS4BmZPgcQrO4FeboD GzGTjbR2x/gP8nYarvTVmxK79kqQ9UATg2pPojyJMKWkoE6Cv03qJzKx nxHkAnyGFGYjIa6zFNJbPQfz+G7SX+o14ooHyVXZcKmAqwKbxxuAbYK3 oSWSMM6j+lk+Ak+GoPgm5zxrbh+aivtGqaZm7Xhg9A877a+w7TjVtOn+ WagIQB9FjG2Ilk3pGIiAskveIMrUM7NPr7bTeyvb0rmewheDfd6uJ8Ou ZirvOhuwv59rDoZ+Us6JaBQ5Y/SrsMQRe3bLwNjx6nuCQlUKedK4db4p N454kg==
+; resign=20460416024207
+93r.subtree2. 86400 IN A 192.0.2.1
+93r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . FfE3JvfkfdE56yTYiqu2CCMxMo2BUwBrjXf1XU9OZ2amya2aSGl8yAl1 yGXbm/FwLKgK6WIfZZTQHBr9Hm3UgwWNg79Z5OQj+RvIHfuIgpX0YgFR TlnLtuFWaufrxu+g+7AVRSB4RkVsN0b0i00o3RGS2pjAtAQ6S/h5R/Qo FlE/scsykd3dCPGyPICxRZdDzouk91aw9YZtxJFOESUHYdKFpqsnu0yf Sd1VQ2kFh3kgkk4Dw59L8hOmYXT8Uxi2gHOQsbb94NwpEJ45NyRAe+xI Vwu2vp+4P1talaWlrlEPqH7/eQ+2AiaAqklwZhKKkN4H9KMx8/T2lpDc ObhuJQ==
+; resign=20460416024207
+93r.subtree2. 86400 IN NSEC 94r.subtree2. A RRSIG NSEC
+93r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . DmsCcR5kIlhw7uLX5C9MiQUya6CWs5q7zTZg5n/r7XiEyV/gB9c2eFLp nTgJdbczL2ShCSEtkb0aYPRRjAvtqGF48JmGJf1NYFgWCmQj2Rei4Mfe besJvJrn36MIY6iOeGFlVGcSffsQxySISEf2+c9UcKOkqsV/O/GCPFHx dU1yIDu+bit8Szhrt7x3RhB4Uj7RWZW6pzeVA/KxBXHHFDSwl/51dygf j0KB7D1zZK5nfXqHtecwzFy9JuL9SkcvI65oPaAjcjS+AbqWZgiHpeXN djbNKhzqUDl4jP+R5wdxs3h1ONQ9WFQOT70fy8gB1Z4fTJLutbEOiMSZ n99gFg==
+; resign=20460416024207
+94r.subtree2. 86400 IN A 192.0.2.1
+94r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . CmTajnWkJnUVcGZzcokeDSqy/NnLUc4Odgi+zon5TrgSaAOEL66pm/zN BSkfK5nciTwptVSg9gpYPu2GMmFamytxizc2cu5YkC0zpcuuWDybGSAz YNw4iZBhLP8iowD1Ea/s7pDflgogShGzX24mNpnYJxVimqO2Hyhp045t xQTumsHzZQVWUlk1Hsa1OtcAOqY4JA9A1zn+gP4Fw59ytXTRPs1C2I3y F8WIOfTrWviN6NvcwFrii2tiQwC8BpI6OI/1wbdkIy2KbHT5IgXxsUh8 QgQjFg2W5pwcbUaAGBnljuAaH7ZL9EAQ70rIybJYNomSc1nEImShb7FZ 39TOSw==
+; resign=20460416024207
+94r.subtree2. 86400 IN NSEC 95r.subtree2. A RRSIG NSEC
+94r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . RcJXpMi5SCMM2tlHDYUwRpRf/BpCyhs3ZUx6hDWJZ9FkMZTJFG4/MWqA Amib2FehoHrhMHcWdsyo/nFQjni3EX28TKt4OlHUYMgo7Kw8p//R1IRA xM5YBsF29k+QZwup8RO/op4a3q2/1lsL+VedNeoJo0giTdfahq8phN1U MNszlAQZ3SuA1T3QM0EnEldKJ9I4HPXYLR/0tLKnjTkCOX6xSI976lAT 2fRGhRuDrhimzjhOWKFMzu+Is5vvAHEqNvqBO9jSIWihK/qoa5Lk+1Tm 96MWrzFMPkMgiJIm5Y6w0VIFFguN/8l+dLbyrzE7j/ytxoPgvWwItjmc gPI8Gg==
+; resign=20460416024207
+95r.subtree2. 86400 IN A 192.0.2.1
+95r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . dEvcbOlBNJYt35F+19pG6fuqzLKwxV8EKNYst0AiKnHxThDTBe6t5zTy j3BQqVaODnEl5nexcjfWigd3u1Fyp5V4U6kPDhe3Jy31FJxDZQPRPLlI hVf1iftkzse4iVx+NpYn6xDbacz/t84RNBcKQGAb2M0MXEbdTBSMI/dA AloyXIedaJAkMMMVTBCQ+b9+YJrCpFfq/uN4hI4kjWvh6hVuVj69CrHL mGD03WXdrURhmhl2mw+AXjUoIopCLGch5h0j1qEc3sAPIkTkmpcaZTvV ZaQTPypvkoK3exrlfgeOhfvHlbk7olrfLcoV6QgSJKRXO/MqRwOVagl8 xIF2Ww==
+; resign=20460416024207
+95r.subtree2. 86400 IN NSEC 96r.subtree2. A RRSIG NSEC
+95r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . E9OK+kEC4PuVEN+P7c+4KzNCAbR3Hsttzi8URw5yjixiGRPbUdS4BdV9 z618OxJzmJJ7M8mz0a5Ofp3fqeXGRmuWecSEMtzFcHJuY6e6Rr2GTXEg sXM3TZnSkEnVtzuCLa+n6nAB0pgEZVnaln3gOpMGZp3kUjfl/0dHE68e lUQ1mqyefoMMx6wsFELXdRXw8g863N8rnu13jx2RkTwufU9Ri7uxSzIw BZvLnGaGQhweCxme8mG7kXU4pZCD/CDYsUUB2trhvsr2f/6ZZkxrlgLe iDBAFB8aw0eQGlf6wPNrumye/LI9CLGwoe1Y3rR5+1O8qCnJYSIy4Bs2 q28nEQ==
+; resign=20460416024207
+96r.subtree2. 86400 IN A 192.0.2.1
+96r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . u1+d0AAtw7KTRsYrFqDlgNIWZUHG3DGvnS/OVOlLiaFrHjlJ8YMKGRoQ WB0cxJ061Hw783mmVZcIJXCXSpfZV6q/afki+b9ZwIO+0yK9jD5cY9vD H5CteywVmduCLoDs0uDYBWE4UbWcB3L8wqSgnDaY4dTB3lmj4oEA1qde a04/Y/R19ntlmDM3lS7tDjY5xRlzK9Q+e8EsxRfriI326px6HBRqdYew dn7RRxVjWbZR4H04nedDQ5jeBh0t0Jl9UUdv5rsYRczE58DR4hkeMrMD RsQv9aEMCCHZIblHS7Jo4O7T7mAjit+0n2n6HOqs8eistzURsErvZogl WvCZEA==
+; resign=20460416024207
+96r.subtree2. 86400 IN NSEC 97r.subtree2. A RRSIG NSEC
+96r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . A1rrt+oKmhhenoj0rBMlott7i5hJ4sKX6yTBi2sQWSCiJuZtPOVaZ6v/ AoOib4IgvSqYc6iIDxn600Xt116j/TWYM/skU/59bd430WbGhoDCCVpC IoNilVWmaDltDkqRsOOJygeJyt8MubUXry5v33MHjxRYywHUZk/nZz9T 05dYDB5IkPzQkUR1kpWBSmxbKhpTDMtOhVtg1oAjb9dOlIDcC6TWno8E hpW5NRJjSAihwOUScPKrubIG3pN4Wzj6yADVao0IBQ+sukm2l3BDdXnU tOI9Xsk2/f2JObVQNs7QqFgtnD6Ht0+9ZfnBCJJtPPcz3flaYIaNeGQ9 bA41rQ==
+; resign=20460416024207
+97r.subtree2. 86400 IN A 192.0.2.1
+97r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . gLTmSp8fhdoLKIOQVjqsqT08v7KC6sfuAPIUrLiauhLvDO06Tx0hIt8V i6An7KsOsaH0ELt2piRbGf6MS/aH2jHSuluFgGp2VIal74kT41A+YsL8 2CkgAcLSvD17HCtWAzxz76eplPJbA3+2nLnSooM04+qR/uckUNdP3Tnm MbZExofXSj9OG4b6U/kRZJ9H/gEbdktDCdtvnCBeJUoV6K9bQc8/RVhE cf/blPcGNm/KVf8XQZgoBTsr4t3S2f68WwpT2pyeoaqYxKr5m6k9jfWC FDRWjGXjtU5IEeKubH2EAjpgBWPLFaRUDAerTjFTqsnJneCMds2k9+gf cULClg==
+; resign=20460416024207
+97r.subtree2. 86400 IN NSEC 98r.subtree2. A RRSIG NSEC
+97r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . JenfHs6Shb7IxIUJK+cojyruYCbm9sBk6sdB7UzHDy/ezOnm3Y5tThi4 YKfvUKxT5/J0rapIIq+eIjs8SabokeG14EsVFDtOHD80xhqdaAukAy6B naSvzFhe9hod0MWx9lM1pOosoVvrA+Wv0/8DOcGxC0myK9TvOSrl3PKM Xr4y8Y9pthV960TM5g7y2GE+aXfpX2gOZiMGe0WOTqUheXQ8wC+etOdz DW5aRLV63qtwXnlY7UWC7balJ36EzELY8al2to5KVhwxwfjjdvak4rWv KH8dDTUY1gL1jX+GPMmY8uLRWMKTHtx6HA8s9AHVxLLjra0lERkbs0/m Y59/mg==
+; resign=20460416024207
+98r.subtree2. 86400 IN A 192.0.2.1
+98r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . uC88oukw3HlsaDfwK2REa9YSQ2wNlwkw3aQ/MBTHUdiOxhZ8cCjdAbLH Vrbn2zCUYcwcAyfYTNOQ51sG2xQ9IsQaclrKO6wUZTikr9vQdwk+/yYS 08o1K3dc0NUSacllCkJ277lekmq8WRhX/qLUKaLScOV2mzZpEVdfqR/7 eZYI1fjjsMiccOjjdKvQdrK63lZrR4JW8KkIlojguz7lNjIuPqV3srD5 psHZDPL8LfoMcFFV3BKr0X875JKdbCTWEeVcAlMmgfp+AZ9s++SggHix ALCBjBhrNJT5zeCTGwU/Y3dBfYYbzTX93fOMfRP60ER9LH+Ns2khIOCj 4siS1Q==
+; resign=20460416024207
+98r.subtree2. 86400 IN NSEC 99r.subtree2. A RRSIG NSEC
+98r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . JzxL54WUwM8cA11scDj5GOKD8AW9VgQT/XtJXKGhwejRMuNH9exj0uLx 6OPLNNN6gp3dgz/mu1LhcE0SiTr42AhmJlYzBJsmJuMZOJ1OGcWYX2yi Yl5udmTp4SJrGQPvH48KzSY4/te2ik4Y6lKdiKz1bd7aaH8cqExIVHMa DJEzXwjJqOQQCph2rq4d1XFfst19ghyoU2GJ1zX8iMZ1TDR/GppRaxd4 ZecfR9C9dzItIjnPo7Ky8JUeGTQY0+PvIriAIcNVTRkEm4x5+zNmLOXe fWTTnoeVhTXVJYki7sLjtKWvoe5jKdiVgJWqLN6Ps4JTJJgu3BHGJzbH fqKqxQ==
+; resign=20460416024207
+99r.subtree2. 86400 IN A 192.0.2.1
+99r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . NO/jA3/Fq6aB+mNCs5aejoZdHdH8MZ5waNKWmW6ba8Tsp58jiyMOAiIj aLiLBZ/A7vXj67NJcCgp0ffs0eE1xwtgcg8DwtsOFHey1I+zmQSjmmUI Gqi0Yi4F0G5V2URkNcZPfc0Ey6zXmpCrfVrKS0DktP8g/kjLkXilTd5F xfLZZzb4XvQA6r/UzNdWaQwe+IU1pYS9h7i4hezxDINj5RoemRykPbBa hm76bG51GX/iLcQ32SuJHM8AaQ6PnnKXLvB+LSkpMBTm9KshBLu0/Sju GeletOuG2sveR5BP6BpQR5STJ7upc5jZH0kOjBUwrV2UI0GPTg0aMl8Q jToNww==
+; resign=20460416024207
+99r.subtree2. 86400 IN NSEC 9r.subtree2. A RRSIG NSEC
+99r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . QHgZNdQItRkchoW2V8xGFn1CFeAwWEH3WlRNv5PTDopVoaOF5bZocWUC OTp+5SFJSqVZ2VZBSfCaqjurC+pwpGYviQQvxV7C31aiQFwoX+092XvU 7EM+YbOLDzg3u95z7YESo58o/ZVIti7p4+JPAp8IKPjGiPhUKUH3hArO TvoZja6adGCNpLkxbE5VFA6esI4ZTMv6IEhALBi9/IdI8ZRpv6WMG+Bn By1w9My++QCtPFQIFC1tLTqPKaIUknL/H5gqKMHmR5YteXpQ9jHtuwEN Lys7P3I/E2TVr2Jt35YyYkUUaxR/W/AMRYOu/cyzuR10nLgiQBLhc3xs 89k7Lw==
+; resign=20460416024207
+69r.subtree2. 86400 IN A 192.0.2.1
+69r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . H9e3SuKHH/ds/qxJExQwItamzQmLsoYnh4u8aAAIOHg1+LT2P0Sn/KGw ISMl/McYEeOXlFt2SGwC+3X96MlXC9GpsMxtPLy86Jt6p/O8gVdSpr7P y2bFB2Ioz1I64mGKTN+AAJtl85zeV5DbEeQcB1uCtHGdh3aGhgS/CT82 b0eFOAuLiIf45Wy5h5DFZz0n9XAUJGOCejUUqZlEdfSJ/9Y9KCjFPOf6 XDr1Ts6eJhukd2FnGImAVRsCeYuCtkm3GjSkxYG3QgqJNDUDpk++Xzw+ 5kNiOZgQ20y8d+VBfC5IJ7mZlEuUCO2Bw71EQC/BbHVkQdgDbKe1oFHn 39Gd6w==
+; resign=20460416024207
+69r.subtree2. 86400 IN NSEC 6r.subtree2. A RRSIG NSEC
+69r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . HUFhcEIpOw13gVwxCTqn4SkpOHHks/x+5qXR7zbMzeCWh3xH2e5V6xyd vh0gD4+qpb6BV0VtHTCWad0IvZADLo434fIAf1skmmkwXHK1P3s8hqeh K7iKTcKSwqE0Fx2vCpmmkutyKgNxokyzBmyhhMHk3kIbh5SqOl3Bl9wh G5WEuICCh+SxFaM+8eHOZl0iWIZAAD4EW0kVdU4Mi0GUI0rvufYL+Jv3 z2Scw+zxA3ZOBPLgHFWLrVd51zap6Sc+CpIE/E+le0TRcam/wV++Tpr/ 5tE7FN634aoVZlf0z5R9VE5rlVvrkzxeo/OYmLWaJ0JbirTMc2nUIOQF 7lFbdw==
+; resign=20460416024207
+9r.subtree2. 86400 IN A 192.0.2.1
+9r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . w3ZdS3SbdNZCYHTVb0iyxEhH6CsCcS3dzopqkxQLH1NhLlEC6zCD8vaZ 5iN3eBV55Kl751tEkmiHeCajXLRhDd6xZC71gZRLp9B8oouEX6DwofZ9 m00N7njjtUd5+ZAuqN5r4oZm4N9zVMA9xQjXszDGM5r91EjxzChohzUE lZ+b4aeOd2jA3z2nmygUq4bNYGFonmzCDhuxvhhrjw/dt/eXWGMWBxFN Rz6Z5ZTgcAgU6pjANijSQ/7Z/D1SZ9f1gDL9O/yK/et08jR5Vlt49McZ mTWcv6ZPOuzrcWSFzO14TR4ZWQEYBKWHcflACH0QRJeMoIrR7D97pPGl /nycqA==
+; resign=20460416024207
+9r.subtree2. 86400 IN NSEC . A RRSIG NSEC
+9r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . pMO6DJZKqSfiPHQjd3nRdxcwHgyDVAtSeTlLVZ5q3RBOQ1hxKa+b1DF/ lPNU/0YDsfEznEhkFPQj3ceWZtABhVLqj/tQNQy2TBkLBFVDTQuLHNWh wjSAwmg5SRUI/NG3t3c4142Sb3yc418XrRWTMu9SS147hUzqZsNls/19 6vkIX7GQLIyqhOULjedZplNFgOxpRmFa5zORTZ30ghBZj4yuH/DXKJyb POLV/h3OrXi3d6KzKkFH+ItRija8dlm3cNNvf5ibD9DsXoEDDm+xu4YM tJDHS5pcPschc99l4YzQPw3AUmOFmoDknzS3v4KSXcbb2olM24pqVb9P eAENJg==
+; resign=20460416024207
+85r.subtree2. 86400 IN A 192.0.2.1
+85r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . f3ogUidaXG4YfcQ1pk360EY2gIoH9khcvUAnb+suATWZgyBzhgzzFLcW r8hB+tF4uW7fpECLic2w+BmZUFX4yGWVDYldS0Nywvj0vApNWAnrn+3P RdNJ7zkI5/ZO1IZDGTGaRZlG1wkIv8KL4lXjRHjw/VU6vMgepld5cCNJ 5tYkhBdHKvltkBqsD3owQ1nCuvfDfIQp0z6H5gCx5EpoNsqKz2O9Z8Mr hjBvl/yVhDrvXRbN0d4o3pHdg1ozm2azNiwRllgCD/vxV48Uw7ZOkFUk Z/e0kgTOsKHCCGCV976OjH8ryFPiVwD2r7tAbzzrEctDtL3pgKocTknh aUSfsA==
+; resign=20460416024207
+85r.subtree2. 86400 IN NSEC 86r.subtree2. A RRSIG NSEC
+85r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . Nc2ArE889yWghwl7jvS5+GSHcYV7Of1aX+YDPThgr+DxZS68jKXwXhrQ NBVMGe/tPdCML/Ka7rggAUmgQJmrx4JY/s1tJMbm1GUJr/rVd23Qt2/3 5Y0OQF76JeNfKtyUfdr2K2nIKtvte0zPq4RlNa0NWm4Lmm53PES4PnO3 w5cnnxwePHMN8aQp5GucyFCdw+Ah8pRGZLRVbPJgj+iL+YhT4k4mQeI8 yoMuC46icqMRzg0lGHaBGeSE8uD1GVjbwOpngqWjB8vdYDmBX1vWNt4P dVII2ybrBIwfnqnGZptNqhs0roKaLGz2GA/0b05bwl1jHL9AhYZ5Zin2 Xz1JVw==
+; resign=20460416024207
+77r.subtree2. 86400 IN A 192.0.2.1
+77r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . QAc9wnWC//xMkla4VISWRiYme7K9/K1PJc+oLaJ+slJJSjbqqbqcqUCx EjDCw7V+a9FvnSTBs3tGpBvnQfGBT8LwbVzgrLA3p7Ad0JX2O5XlaYU7 tcbDatZdRoQkB/rxpUcPzEKe8t3mT4nzavyK+QTF6gbfrcGLRRrdADwh lUOmada+Hz/339BkLYHEvFHCdnmovmtBUOQPjgVpj2pFWPZ+cAOw5VJV 7/mLFwijuoe22Yq9E9WaI6YWJIeobu+Dht13FlUkiAgQeqyDAOCnmLjp Hf2VRjXvRktliYOHoM1gBG9c7qUHIHtOS4oXRT+0ElN9CBBovTzdIoo6 WML2DQ==
+; resign=20460416024207
+77r.subtree2. 86400 IN NSEC 78r.subtree2. A RRSIG NSEC
+77r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . jp+KYsenqjl2t7tBVdmg1VVQoq1eHgqnnGjLeVU3oGNLtwwvQWEl0fV0 MNMuBUzH5jhMw8L8VvmFihIa9RQga3PQDI+CnrvRH1YNM8OAXzaWWWrA Fs4cS/cCUo3dbfgL7bxxTYmYYG96N4QbTvBE6M/N8bvquMikTdWjsMBy rz3ZsMCoVC8CXr+i06vevOKZaqfJ08hYg/hbW8+h/XtgXaQZjLEGJ68X osO+20PkOHvRD7X3RTHVlDrT2ZZOjCokNEgl4/alp5t5xXi6A3hD0HfF T/tzTiBi8gVw/PXJRgPV8rE3BXCf7Cqwwtei/28Knkf13zHD8fOmrV08 PuQfKQ==
+; resign=20460416024207
+87r.subtree2. 86400 IN A 192.0.2.1
+87r.subtree2. 86400 IN RRSIG A 8 2 86400 20460416024207 20180815062314 48409 . fPXLpsy1AqCF8HpnyeICWkuMtVpa87akqhqWJdKTG6pKKVQR0swtNaYE e3aLriYm92PGuYzdIIrQLyBlRqfdsyNIbhcGSufBplGt0hUR6CCFP6eX wuOBqw2lhrNReC/GM+E1wjvZTfZ1qwc+JOA462jXX0t9PSrTTlFM5CEj /91mOZXJ8DTYHeDPy3jvPEjhR/137fC0WhHHrMNKI7wT0dNSObq49DXu IzqrtNpzEWtiDYQdhk37hraueb0BNFmVONLqve2Q51D320qi953XR3pz olGQ9UrI7Eeo4kbwSGLo8U7mIH2wS65RHzrO8+4U+W/pwHXLoGnQxiRw e1NfdQ==
+; resign=20460416024207
+87r.subtree2. 86400 IN NSEC 88r.subtree2. A RRSIG NSEC
+87r.subtree2. 86400 IN RRSIG NSEC 8 2 86400 20460416024207 20180815062314 48409 . JyZPoj5NUaz3hnlq+EoPq2mozjKk1VsVmD9Ipc7M8chTIxjiYLnyRVcx ZeE5p+M19oXK71RPwSdYH2UjiFCOa4cZntkIny972BYEDtezGdSYzz/z VMDf9r6XOBeECHiIAaF6q+ptR0K47188Q6+eTlcPZMNSDrckRFBfI/qT 9R99kCvDJ5WyBTY+2aT2qCP0+INJi/XQfOj3RuuJhxLh7UBbicdR43fb QW//otvC9Hb6RwxZFkrM283ddAcjA/0/L4bPmV5AQo1lGeO6e/5jmBay /uJD4HVAHwW3T7rbQyMOWjoIGyJreEaSiE2ykBptwscbgrBOygyOs2wX zZ8EEg==
+; resign=20460416024207
diff --git a/daemon/cache.test/testroot.zone.unsigned b/daemon/cache.test/testroot.zone.unsigned
new file mode 100644
index 0000000..65be9b6
--- /dev/null
+++ b/daemon/cache.test/testroot.zone.unsigned
@@ -0,0 +1,215 @@
+. 86400 SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 NS rootns.
+rootns. 86400 A 198.41.0.4
+
+subtree1. 86400 TXT "txt exists"
+subtree1. 86400 A 192.0.2.1
+b.subtree1. 86400 TXT "txt exists"
+b.subtree1. 86400 A 192.0.2.2
+a.b.subtree1. 86400 TXT "txt exists"
+a.b.subtree1. 86400 A 192.0.2.3
+a.b.subtree1. 86400 AAAA 2001:db8::
+
+; subtree2. is empty non-terminal
+1r.subtree2. 86400 AAAA 2001:db8::
+2r.subtree2. 86400 AAAA 2001:db8::1
+2r.subtree2. 86400 AAAA 2001:db8::2
+3r.subtree2. 86400 AAAA 2001:db8::
+4r.subtree2. 86400 A 192.0.2.1
+5r.subtree2. 86400 A 192.0.2.1
+6r.subtree2. 86400 A 192.0.2.1
+7r.subtree2. 86400 A 192.0.2.1
+8r.subtree2. 86400 A 192.0.2.1
+9r.subtree2. 86400 A 192.0.2.1
+10r.subtree2. 86400 A 192.0.2.1
+11r.subtree2. 86400 A 192.0.2.1
+12r.subtree2. 86400 A 192.0.2.1
+13r.subtree2. 86400 A 192.0.2.1
+14r.subtree2. 86400 A 192.0.2.1
+15r.subtree2. 86400 A 192.0.2.1
+16r.subtree2. 86400 A 192.0.2.1
+17r.subtree2. 86400 A 192.0.2.1
+18r.subtree2. 86400 A 192.0.2.1
+19r.subtree2. 86400 A 192.0.2.1
+20r.subtree2. 86400 A 192.0.2.1
+21r.subtree2. 86400 A 192.0.2.1
+22r.subtree2. 86400 A 192.0.2.1
+23r.subtree2. 86400 A 192.0.2.1
+24r.subtree2. 86400 A 192.0.2.1
+25r.subtree2. 86400 A 192.0.2.1
+26r.subtree2. 86400 A 192.0.2.1
+27r.subtree2. 86400 A 192.0.2.1
+28r.subtree2. 86400 A 192.0.2.1
+29r.subtree2. 86400 A 192.0.2.1
+30r.subtree2. 86400 A 192.0.2.1
+31r.subtree2. 86400 A 192.0.2.1
+32r.subtree2. 86400 A 192.0.2.1
+33r.subtree2. 86400 A 192.0.2.1
+34r.subtree2. 86400 A 192.0.2.1
+35r.subtree2. 86400 A 192.0.2.1
+36r.subtree2. 86400 A 192.0.2.1
+37r.subtree2. 86400 A 192.0.2.1
+38r.subtree2. 86400 A 192.0.2.1
+39r.subtree2. 86400 A 192.0.2.1
+40r.subtree2. 86400 A 192.0.2.1
+41r.subtree2. 86400 A 192.0.2.1
+42r.subtree2. 86400 A 192.0.2.1
+43r.subtree2. 86400 A 192.0.2.1
+44r.subtree2. 86400 A 192.0.2.1
+45r.subtree2. 86400 A 192.0.2.1
+46r.subtree2. 86400 A 192.0.2.1
+47r.subtree2. 86400 A 192.0.2.1
+48r.subtree2. 86400 A 192.0.2.1
+49r.subtree2. 86400 A 192.0.2.1
+50r.subtree2. 86400 A 192.0.2.1
+51r.subtree2. 86400 A 192.0.2.1
+52r.subtree2. 86400 A 192.0.2.1
+53r.subtree2. 86400 A 192.0.2.1
+54r.subtree2. 86400 A 192.0.2.1
+55r.subtree2. 86400 A 192.0.2.1
+56r.subtree2. 86400 A 192.0.2.1
+57r.subtree2. 86400 A 192.0.2.1
+58r.subtree2. 86400 A 192.0.2.1
+59r.subtree2. 86400 A 192.0.2.1
+60r.subtree2. 86400 A 192.0.2.1
+61r.subtree2. 86400 A 192.0.2.1
+62r.subtree2. 86400 A 192.0.2.1
+63r.subtree2. 86400 A 192.0.2.1
+64r.subtree2. 86400 A 192.0.2.1
+65r.subtree2. 86400 A 192.0.2.1
+66r.subtree2. 86400 A 192.0.2.1
+67r.subtree2. 86400 A 192.0.2.1
+68r.subtree2. 86400 A 192.0.2.1
+69r.subtree2. 86400 A 192.0.2.1
+70r.subtree2. 86400 A 192.0.2.1
+71r.subtree2. 86400 A 192.0.2.1
+72r.subtree2. 86400 A 192.0.2.1
+73r.subtree2. 86400 A 192.0.2.1
+74r.subtree2. 86400 A 192.0.2.1
+75r.subtree2. 86400 A 192.0.2.1
+76r.subtree2. 86400 A 192.0.2.1
+77r.subtree2. 86400 A 192.0.2.1
+78r.subtree2. 86400 A 192.0.2.1
+79r.subtree2. 86400 A 192.0.2.1
+80r.subtree2. 86400 A 192.0.2.1
+81r.subtree2. 86400 A 192.0.2.1
+82r.subtree2. 86400 A 192.0.2.1
+83r.subtree2. 86400 A 192.0.2.1
+84r.subtree2. 86400 A 192.0.2.1
+85r.subtree2. 86400 A 192.0.2.1
+86r.subtree2. 86400 A 192.0.2.1
+87r.subtree2. 86400 A 192.0.2.1
+88r.subtree2. 86400 A 192.0.2.1
+89r.subtree2. 86400 A 192.0.2.1
+90r.subtree2. 86400 A 192.0.2.1
+91r.subtree2. 86400 A 192.0.2.1
+92r.subtree2. 86400 A 192.0.2.1
+93r.subtree2. 86400 A 192.0.2.1
+94r.subtree2. 86400 A 192.0.2.1
+95r.subtree2. 86400 A 192.0.2.1
+96r.subtree2. 86400 A 192.0.2.1
+97r.subtree2. 86400 A 192.0.2.1
+98r.subtree2. 86400 A 192.0.2.1
+99r.subtree2. 86400 A 192.0.2.1
+100r.subtree2. 86400 A 192.0.2.1
+101r.subtree2. 86400 A 192.0.2.1
+102r.subtree2. 86400 A 192.0.2.1
+103r.subtree2. 86400 A 192.0.2.1
+104r.subtree2. 86400 A 192.0.2.1
+105r.subtree2. 86400 A 192.0.2.1
+106r.subtree2. 86400 A 192.0.2.1
+107r.subtree2. 86400 A 192.0.2.1
+108r.subtree2. 86400 A 192.0.2.1
+109r.subtree2. 86400 A 192.0.2.1
+110r.subtree2. 86400 A 192.0.2.1
+111r.subtree2. 86400 A 192.0.2.1
+112r.subtree2. 86400 A 192.0.2.1
+113r.subtree2. 86400 A 192.0.2.1
+114r.subtree2. 86400 A 192.0.2.1
+115r.subtree2. 86400 A 192.0.2.1
+116r.subtree2. 86400 A 192.0.2.1
+117r.subtree2. 86400 A 192.0.2.1
+118r.subtree2. 86400 A 192.0.2.1
+119r.subtree2. 86400 A 192.0.2.1
+120r.subtree2. 86400 A 192.0.2.1
+121r.subtree2. 86400 A 192.0.2.1
+122r.subtree2. 86400 A 192.0.2.1
+123r.subtree2. 86400 A 192.0.2.1
+124r.subtree2. 86400 A 192.0.2.1
+125r.subtree2. 86400 A 192.0.2.1
+126r.subtree2. 86400 A 192.0.2.1
+127r.subtree2. 86400 A 192.0.2.1
+128r.subtree2. 86400 A 192.0.2.1
+129r.subtree2. 86400 A 192.0.2.1
+130r.subtree2. 86400 A 192.0.2.1
+131r.subtree2. 86400 A 192.0.2.1
+132r.subtree2. 86400 A 192.0.2.1
+133r.subtree2. 86400 A 192.0.2.1
+134r.subtree2. 86400 A 192.0.2.1
+135r.subtree2. 86400 A 192.0.2.1
+136r.subtree2. 86400 A 192.0.2.1
+137r.subtree2. 86400 A 192.0.2.1
+138r.subtree2. 86400 A 192.0.2.1
+139r.subtree2. 86400 A 192.0.2.1
+140r.subtree2. 86400 A 192.0.2.1
+141r.subtree2. 86400 A 192.0.2.1
+142r.subtree2. 86400 A 192.0.2.1
+143r.subtree2. 86400 A 192.0.2.1
+144r.subtree2. 86400 A 192.0.2.1
+145r.subtree2. 86400 A 192.0.2.1
+146r.subtree2. 86400 A 192.0.2.1
+147r.subtree2. 86400 A 192.0.2.1
+148r.subtree2. 86400 A 192.0.2.1
+149r.subtree2. 86400 A 192.0.2.1
+150r.subtree2. 86400 A 192.0.2.1
+151r.subtree2. 86400 A 192.0.2.1
+152r.subtree2. 86400 A 192.0.2.1
+153r.subtree2. 86400 A 192.0.2.1
+154r.subtree2. 86400 A 192.0.2.1
+155r.subtree2. 86400 A 192.0.2.1
+156r.subtree2. 86400 A 192.0.2.1
+157r.subtree2. 86400 A 192.0.2.1
+158r.subtree2. 86400 A 192.0.2.1
+159r.subtree2. 86400 A 192.0.2.1
+160r.subtree2. 86400 A 192.0.2.1
+161r.subtree2. 86400 A 192.0.2.1
+162r.subtree2. 86400 A 192.0.2.1
+163r.subtree2. 86400 A 192.0.2.1
+164r.subtree2. 86400 A 192.0.2.1
+165r.subtree2. 86400 A 192.0.2.1
+166r.subtree2. 86400 A 192.0.2.1
+167r.subtree2. 86400 A 192.0.2.1
+168r.subtree2. 86400 A 192.0.2.1
+169r.subtree2. 86400 A 192.0.2.1
+170r.subtree2. 86400 A 192.0.2.1
+171r.subtree2. 86400 A 192.0.2.1
+172r.subtree2. 86400 A 192.0.2.1
+173r.subtree2. 86400 A 192.0.2.1
+174r.subtree2. 86400 A 192.0.2.1
+175r.subtree2. 86400 A 192.0.2.1
+176r.subtree2. 86400 A 192.0.2.1
+177r.subtree2. 86400 A 192.0.2.1
+178r.subtree2. 86400 A 192.0.2.1
+179r.subtree2. 86400 A 192.0.2.1
+180r.subtree2. 86400 A 192.0.2.1
+181r.subtree2. 86400 A 192.0.2.1
+182r.subtree2. 86400 A 192.0.2.1
+183r.subtree2. 86400 A 192.0.2.1
+184r.subtree2. 86400 A 192.0.2.1
+185r.subtree2. 86400 A 192.0.2.1
+186r.subtree2. 86400 A 192.0.2.1
+187r.subtree2. 86400 A 192.0.2.1
+188r.subtree2. 86400 A 192.0.2.1
+189r.subtree2. 86400 A 192.0.2.1
+190r.subtree2. 86400 A 192.0.2.1
+191r.subtree2. 86400 A 192.0.2.1
+192r.subtree2. 86400 A 192.0.2.1
+193r.subtree2. 86400 A 192.0.2.1
+194r.subtree2. 86400 A 192.0.2.1
+195r.subtree2. 86400 A 192.0.2.1
+196r.subtree2. 86400 A 192.0.2.1
+197r.subtree2. 86400 A 192.0.2.1
+198r.subtree2. 86400 A 192.0.2.1
+199r.subtree2. 86400 A 192.0.2.1
+200r.subtree2. 86400 A 192.0.2.1
+201r.subtree2. 86400 A 192.0.2.1
diff --git a/daemon/daemon.mk b/daemon/daemon.mk
new file mode 100644
index 0000000..e0d0000
--- /dev/null
+++ b/daemon/daemon.mk
@@ -0,0 +1,79 @@
+kresd_SOURCES := \
+ daemon/io.c \
+ daemon/network.c \
+ daemon/engine.c \
+ daemon/worker.c \
+ daemon/bindings.c \
+ daemon/ffimodule.c \
+ daemon/tls.c \
+ daemon/tls_ephemeral_credentials.c \
+ daemon/tls_session_ticket-srv.c \
+ daemon/zimport.c \
+ daemon/session.c \
+ daemon/main.c
+
+kresd_DIST := daemon/lua/kres.lua daemon/lua/kres-gen.lua \
+ daemon/lua/trust_anchors.lua daemon/lua/zonefile.lua
+
+# Embedded resources
+%.inc: %.lua
+ @$(call quiet,XXD_LUA,$<) $< > $@
+ifeq ($(AMALG), yes)
+kresd.amalg.c: daemon/lua/sandbox.inc daemon/lua/config.inc
+else
+daemon/engine.o: daemon/lua/sandbox.inc daemon/lua/config.inc
+kresd-lint: daemon/lua/sandbox.inc daemon/lua/config.inc
+endif
+
+# Installed FFI bindings
+bindings-install: $(kresd_DIST) $(DESTDIR)$(MODULEDIR)
+ $(INSTALL) -m 0644 $(kresd_DIST) $(DESTDIR)$(MODULEDIR)
+
+LUA_HAS_SETFUNCS := \
+ $(shell pkg-config luajit --atleast-version=2.1.0-beta3 && echo 1 || echo 0)
+
+kresd_CFLAGS := -fPIE \
+ -Dlibknot_SONAME=\"$(libknot_SONAME)\" \
+ -Dlibzscanner_SONAME=\"$(libzscanner_SONAME)\" \
+ -DROOTHINTS=\"$(ROOTHINTS)\" \
+ -DLIBEXT=\"$(LIBEXT)\" \
+ -DLUA_HAS_SETFUNCS="$(LUA_HAS_SETFUNCS)"
+kresd_DEPEND := $(libkres) $(contrib)
+kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) \
+ $(libzscanner_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS) \
+ $(gnutls_LIBS)
+
+# Enable systemd
+ifeq ($(HAS_libsystemd), yes)
+kresd_CFLAGS += -DHAS_SYSTEMD
+kresd_LIBS += $(libsystemd_LIBS)
+endif
+
+# Make binary
+$(eval $(call make_sbin,kresd,daemon,yes))
+
+# Targets
+date := $(shell head -n1 < NEWS | sed 's/.*(\(.*\)).*/\1/' | grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}$$' || date -u -r NEWS +%F)
+daemon: $(kresd) $(kresd_DIST)
+daemon-install: kresd-install bindings-install
+ifneq ($(SED),)
+ $(SED) -e "s/@VERSION@/$(VERSION)/" -e "s/@DATE@/$(date)/" \
+ -e "s|@MODULEDIR@|$(MODULEDIR)|" \
+ -e "s|@KEYFILE_DEFAULT@|$(KEYFILE_DEFAULT)|" \
+ doc/kresd.8.in > doc/kresd.8
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(MANDIR)/man8/
+ $(INSTALL) -m 0644 doc/kresd.8 $(DESTDIR)$(MANDIR)/man8/
+endif
+daemon-clean: kresd-clean
+ @$(RM) daemon/lua/*.inc daemon/lua/trust_anchors.lua
+
+daemon/lua/trust_anchors.lua: daemon/lua/trust_anchors.lua.in
+ @$(call quiet,SED,$<) -e "s|@ETCDIR@|$(ETCDIR)|g;s|@KEYFILE_DEFAULT@|$(KEYFILE_DEFAULT)|g" $< > $@
+
+daemon/lua/kres-gen.lua: | $(libkres)
+ @echo "WARNING: regenerating $@"
+ @# the sed saves some space(s)
+ daemon/lua/kres-gen.sh | sed 's/ /\t/g' > $@
+.DELETE_ON_ERROR: daemon/lua/kres-gen.lua
+
+.PHONY: daemon daemon-install daemon-clean
diff --git a/daemon/engine.c b/daemon/engine.c
new file mode 100644
index 0000000..5eebe3d
--- /dev/null
+++ b/daemon/engine.c
@@ -0,0 +1,1055 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <contrib/cleanup.h>
+#include <ccan/json/json.h>
+#include <ccan/asprintf/asprintf.h>
+#include <uv.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <libzscanner/scanner.h>
+
+#include "daemon/engine.h"
+#include "daemon/bindings.h"
+#include "daemon/ffimodule.h"
+#include "lib/nsrep.h"
+#include "lib/cache/api.h"
+#include "lib/defines.h"
+#include "lib/cache/cdb_lmdb.h"
+#include "lib/dnssec/ta.h"
+
+/* Magic defaults for the engine. */
+#ifndef LRU_RTT_SIZE
+#define LRU_RTT_SIZE 65536 /**< NS RTT cache size */
+#endif
+#ifndef LRU_REP_SIZE
+#define LRU_REP_SIZE (LRU_RTT_SIZE / 4) /**< NS reputation cache size */
+#endif
+#ifndef LRU_COOKIES_SIZE
+ #ifdef ENABLE_COOKIES
+ #define LRU_COOKIES_SIZE LRU_RTT_SIZE /**< DNS cookies cache size. */
+ #else
+ #define LRU_COOKIES_SIZE LRU_ASSOC /* simpler than guards everywhere */
+ #endif
+#endif
+
+/** @internal Compatibility wrapper for Lua < 5.2 */
+#if LUA_VERSION_NUM < 502
+#define lua_rawlen(L, obj) lua_objlen((L), (obj))
+#endif
+
+/**@internal Maximum number of incomplete TCP connections in queue.
+* Default is from Redis and Apache. */
+#ifndef TCP_BACKLOG_DEFAULT
+#define TCP_BACKLOG_DEFAULT 511
+#endif
+
+/** @internal Annotate for static checkers. */
+KR_NORETURN int lua_error (lua_State *L);
+
+/* Cleanup engine state every 5 minutes */
+const size_t CLEANUP_TIMER = 5*60*1000;
+
+/* Execute byte code */
+#define l_dobytecode(L, arr, len, name) \
+ (luaL_loadbuffer((L), (arr), (len), (name)) || lua_pcall((L), 0, LUA_MULTRET, 0))
+/** Load file in a sandbox environment. */
+#define l_dosandboxfile(L, filename) \
+ (luaL_loadfile((L), (filename)) || engine_pcall((L), 0))
+
+/*
+ * Global bindings.
+ */
+
+/** Register module callback into Lua world. */
+#define REGISTER_MODULE_CALL(L, module, cb, name) do { \
+ lua_pushlightuserdata((L), (module)); \
+ lua_pushlightuserdata((L), (cb)); \
+ lua_pushcclosure((L), l_trampoline, 2); \
+ lua_setfield((L), -2, (name)); \
+ } while (0)
+
+/** Print help and available commands. */
+static int l_help(lua_State *L)
+{
+ static const char *help_str =
+ "help()\n show this help\n"
+ "quit()\n quit\n"
+ "hostname()\n hostname\n"
+ "package_version()\n return package version\n"
+ "user(name[, group])\n change process user (and group)\n"
+ "verbose(true|false)\n toggle verbose mode\n"
+ "option(opt[, new_val])\n get/set server option\n"
+ "mode(strict|normal|permissive)\n set resolver strictness level\n"
+ "reorder_RR([true|false])\n set/get reordering of RRs within RRsets\n"
+ "resolve(name, type[, class, flags, callback])\n resolve query, callback when it's finished\n"
+ "todname(name)\n convert name to wire format\n"
+ "tojson(val)\n convert value to JSON\n"
+ "map(expr)\n run expression on all workers\n"
+ "net\n network configuration\n"
+ "cache\n network configuration\n"
+ "modules\n modules configuration\n"
+ "kres\n resolver services\n"
+ "trust_anchors\n configure trust anchors\n"
+ ;
+ lua_pushstring(L, help_str);
+ return 1;
+}
+
+static bool update_privileges(int uid, int gid)
+{
+ if ((gid_t)gid != getgid()) {
+ if (setregid(gid, gid) < 0) {
+ return false;
+ }
+ }
+ if ((uid_t)uid != getuid()) {
+ if (setreuid(uid, uid) < 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/** Set process user/group. */
+static int l_setuser(lua_State *L)
+{
+ int n = lua_gettop(L);
+ if (n < 1 || !lua_isstring(L, 1)) {
+ lua_pushliteral(L, "user(user[, group)");
+ lua_error(L);
+ }
+ /* Fetch UID/GID based on string identifiers. */
+ struct passwd *user_pw = getpwnam(lua_tostring(L, 1));
+ if (!user_pw) {
+ lua_pushliteral(L, "invalid user name");
+ lua_error(L);
+ }
+ int uid = user_pw->pw_uid;
+ int gid = getgid();
+ if (n > 1 && lua_isstring(L, 2)) {
+ struct group *group_pw = getgrnam(lua_tostring(L, 2));
+ if (!group_pw) {
+ lua_pushliteral(L, "invalid group name");
+ lua_error(L);
+ }
+ gid = group_pw->gr_gid;
+ }
+ /* Drop privileges */
+ bool ret = update_privileges(uid, gid);
+ if (!ret) {
+ lua_pushstring(L, strerror(errno));
+ lua_error(L);
+ }
+ lua_pushboolean(L, ret);
+ return 1;
+}
+
+/** Quit current executable. */
+static int l_quit(lua_State *L)
+{
+ engine_stop(engine_luaget(L));
+ return 0;
+}
+
+/** Toggle verbose mode. */
+static int l_verbose(lua_State *L)
+{
+ if (lua_isboolean(L, 1) || lua_isnumber(L, 1)) {
+ kr_verbose_set(lua_toboolean(L, 1));
+ }
+ lua_pushboolean(L, kr_verbose_status);
+ return 1;
+}
+
+char *engine_get_hostname(struct engine *engine) {
+ static char hostname_str[KNOT_DNAME_MAXLEN];
+ if (!engine) {
+ return NULL;
+ }
+
+ if (!engine->hostname) {
+ if (gethostname(hostname_str, sizeof(hostname_str)) != 0)
+ return NULL;
+ return hostname_str;
+ }
+ return engine->hostname;
+}
+
+int engine_set_hostname(struct engine *engine, const char *hostname) {
+ if (!engine || !hostname) {
+ return kr_error(EINVAL);
+ }
+
+ char *new_hostname = strdup(hostname);
+ if (!new_hostname) {
+ return kr_error(ENOMEM);
+ }
+ if (engine->hostname) {
+ free(engine->hostname);
+ }
+ engine->hostname = new_hostname;
+ network_new_hostname(&engine->net, engine);
+
+ return 0;
+}
+
+/** Return hostname. */
+static int l_hostname(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (lua_gettop(L) == 0) {
+ lua_pushstring(L, engine_get_hostname(engine));
+ return 1;
+ }
+ if ((lua_gettop(L) != 1) || !lua_isstring(L, 1)) {
+ lua_pushstring(L, "hostname takes at most one parameter: (\"fqdn\")");
+ lua_error(L);
+ }
+
+ if (engine_set_hostname(engine, lua_tostring(L, 1)) != 0) {
+ lua_pushstring(L, "setting hostname failed");
+ lua_error(L);
+ }
+
+ lua_pushstring(L, engine_get_hostname(engine));
+ return 1;
+}
+
+/** Return server package version. */
+static int l_package_version(lua_State *L)
+{
+ lua_pushliteral(L, PACKAGE_VERSION);
+ return 1;
+}
+
+char *engine_get_moduledir(struct engine *engine) {
+ return engine->moduledir;
+}
+
+int engine_set_moduledir(struct engine *engine, const char *moduledir) {
+ if (!engine || !moduledir) {
+ return kr_error(EINVAL);
+ }
+
+ char *new_moduledir = strdup(moduledir);
+ if (!new_moduledir) {
+ return kr_error(ENOMEM);
+ }
+ if (engine->moduledir) {
+ free(engine->moduledir);
+ }
+ engine->moduledir = new_moduledir;
+
+ /* Use module path for including Lua scripts */
+ char l_paths[MAXPATHLEN] = { 0 };
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wformat" /* %1$ is not in C standard */
+ /* Save original package.path to package._path */
+ snprintf(l_paths, MAXPATHLEN - 1,
+ "if package._path == nil then package._path = package.path end\n"
+ "package.path = '%1$s/?.lua;%1$s/?/init.lua;'..package._path\n"
+ "if package._cpath == nil then package._cpath = package.cpath end\n"
+ "package.cpath = '%1$s/?%2$s;'..package._cpath\n",
+ new_moduledir, LIBEXT);
+ #pragma GCC diagnostic pop
+
+ int ret = l_dobytecode(engine->L, l_paths, strlen(l_paths), "");
+ if (ret != 0) {
+ lua_pop(engine->L, 1);
+ return ret;
+ }
+ return 0;
+}
+
+/** Return hostname. */
+static int l_moduledir(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ if (lua_gettop(L) == 0) {
+ lua_pushstring(L, engine_get_moduledir(engine));
+ return 1;
+ }
+ if ((lua_gettop(L) != 1) || !lua_isstring(L, 1)) {
+ lua_pushstring(L, "moduledir takes at most one parameter: (\"directory\")");
+ lua_error(L);
+ }
+
+ if (engine_set_moduledir(engine, lua_tostring(L, 1)) != 0) {
+ lua_pushstring(L, "setting moduledir failed");
+ lua_error(L);
+ }
+
+ lua_pushstring(L, engine_get_moduledir(engine));
+ return 1;
+}
+
+/** @internal for l_trustanchor: */
+static void ta_add(zs_scanner_t *zs)
+{
+ map_t *ta = zs->process.data;
+ if (!ta)
+ return;
+ if (kr_ta_add(ta, zs->r_owner, zs->r_type, zs->r_ttl, zs->r_data, zs->r_data_length))
+ zs->process.data = NULL; /* error signalling */
+}
+/** Enable/disable trust anchor. */
+static int l_trustanchor(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ const char *anchor = lua_tostring(L, 1);
+ bool enable = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true;
+ if (!anchor || strlen(anchor) == 0) {
+ return 0;
+ }
+ /* If disabling, parse the owner string only. */
+ if (!enable) {
+ knot_dname_t *owner = knot_dname_from_str(NULL, anchor, KNOT_DNAME_MAXLEN);
+ if (!owner) {
+ lua_pushstring(L, "invalid trust anchor owner");
+ lua_error(L);
+ }
+ lua_pushboolean(L, kr_ta_del(&engine->resolver.trust_anchors, owner) == 0);
+ free(owner);
+ return 1;
+ }
+
+ /* Parse the record */
+ zs_scanner_t *zs = malloc(sizeof(*zs));
+ if (!zs || zs_init(zs, ".", 1, 0) != 0) {
+ free(zs);
+ lua_pushstring(L, "not enough memory");
+ lua_error(L);
+ }
+ zs_set_processing(zs, ta_add, NULL, &engine->resolver.trust_anchors);
+ bool ok = zs_set_input_string(zs, anchor, strlen(anchor)) == 0
+ && zs_parse_all(zs) == 0;
+ ok = ok && zs->process.data; /* reset to NULL on error in ta_add */
+
+ zs_deinit(zs);
+ free(zs);
+ /* Report errors */
+ if (!ok) {
+ lua_pushstring(L, "failed to process trust anchor RR");
+ lua_error(L);
+ }
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+/** Load root hints from zonefile. */
+static int l_hint_root_file(lua_State *L)
+{
+ struct engine *engine = engine_luaget(L);
+ struct kr_context *ctx = &engine->resolver;
+ const char *file = lua_tostring(L, 1);
+
+ const char *err = engine_hint_root_file(ctx, file);
+ if (err) {
+ if (!file) {
+ file = ROOTHINTS;
+ }
+ lua_push_printf(L, "error when opening '%s': %s", file, err);
+ lua_error(L);
+ } else {
+ lua_pushboolean(L, true);
+ return 1;
+ }
+}
+
+/** @internal for engine_hint_root_file */
+static void roothints_add(zs_scanner_t *zs)
+{
+ struct kr_zonecut *hints = zs->process.data;
+ if (!hints) {
+ return;
+ }
+ if (zs->r_type == KNOT_RRTYPE_A || zs->r_type == KNOT_RRTYPE_AAAA) {
+ kr_zonecut_add(hints, zs->r_owner, zs->r_data, zs->r_data_length);
+ }
+}
+const char* engine_hint_root_file(struct kr_context *ctx, const char *file)
+{
+ if (!file) {
+ file = ROOTHINTS;
+ }
+ if (strlen(file) == 0 || !ctx) {
+ return "invalid parameters";
+ }
+ struct kr_zonecut *root_hints = &ctx->root_hints;
+
+ zs_scanner_t zs;
+ if (zs_init(&zs, ".", 1, 0) != 0) {
+ return "not enough memory";
+ }
+ if (zs_set_input_file(&zs, file) != 0) {
+ zs_deinit(&zs);
+ return "failed to open root hints file";
+ }
+
+ kr_zonecut_set(root_hints, (const uint8_t *)"");
+ zs_set_processing(&zs, roothints_add, NULL, root_hints);
+ zs_parse_all(&zs);
+ zs_deinit(&zs);
+ return NULL;
+}
+
+/** Unpack JSON object to table */
+static void l_unpack_json(lua_State *L, JsonNode *table)
+{
+ /* Unpack POD */
+ switch(table->tag) {
+ case JSON_STRING: lua_pushstring(L, table->string_); return;
+ case JSON_NUMBER: lua_pushnumber(L, table->number_); return;
+ case JSON_BOOL: lua_pushboolean(L, table->bool_); return;
+ default: break;
+ }
+ /* Unpack object or array into table */
+ lua_newtable(L);
+ JsonNode *node = NULL;
+ json_foreach(node, table) {
+ /* Push node value */
+ switch(node->tag) {
+ case JSON_OBJECT: /* as array */
+ case JSON_ARRAY: l_unpack_json(L, node); break;
+ case JSON_STRING: lua_pushstring(L, node->string_); break;
+ case JSON_NUMBER: lua_pushnumber(L, node->number_); break;
+ case JSON_BOOL: lua_pushboolean(L, node->bool_); break;
+ default: continue;
+ }
+ /* Set table key */
+ if (node->key) {
+ lua_setfield(L, -2, node->key);
+ } else {
+ lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
+ }
+ }
+}
+
+/** @internal Recursive Lua/JSON serialization. */
+static JsonNode *l_pack_elem(lua_State *L, int top)
+{
+ switch(lua_type(L, top)) {
+ case LUA_TSTRING: return json_mkstring(lua_tostring(L, top));
+ case LUA_TNUMBER: return json_mknumber(lua_tonumber(L, top));
+ case LUA_TBOOLEAN: return json_mkbool(lua_toboolean(L, top));
+ case LUA_TTABLE: break; /* Table, iterate it. */
+ default: return json_mknull();
+ }
+ /* Use absolute indexes here, as the table may be nested. */
+ JsonNode *node = NULL;
+ lua_pushnil(L);
+ while(lua_next(L, top) != 0) {
+ bool is_array = false;
+ if (!node) {
+ is_array = (lua_type(L, top + 1) == LUA_TNUMBER);
+ node = is_array ? json_mkarray() : json_mkobject();
+ if (!node) {
+ return NULL;
+ }
+ } else {
+ is_array = node->tag == JSON_ARRAY;
+ }
+
+ /* Insert to array/table. */
+ JsonNode *val = l_pack_elem(L, top + 2);
+ if (is_array) {
+ json_append_element(node, val);
+ } else {
+ const char *key = lua_tostring(L, top + 1);
+ json_append_member(node, key, val);
+ }
+ lua_pop(L, 1);
+ }
+ /* Return empty object for empty tables. */
+ return node ? node : json_mkobject();
+}
+
+/** @internal Serialize to string */
+static char *l_pack_json(lua_State *L, int top)
+{
+ JsonNode *root = l_pack_elem(L, top);
+ if (!root) {
+ return NULL;
+ }
+ char *result = json_encode(root);
+ json_delete(root);
+ return result;
+}
+
+static int l_tojson(lua_State *L)
+{
+ auto_free char *json_str = l_pack_json(L, lua_gettop(L));
+ if (!json_str) {
+ return 0;
+ }
+ lua_pushstring(L, json_str);
+ return 1;
+}
+
+static int l_fromjson(lua_State *L)
+{
+ if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
+ lua_pushliteral(L, "a JSON string is required");
+ lua_error(L);
+ }
+
+ const char *json_str = lua_tostring(L, 1);
+ JsonNode *root_node = json_decode(json_str);
+
+ if (!root_node) {
+ lua_pushliteral(L, "invalid JSON string");
+ lua_error(L);
+ }
+ l_unpack_json(L, root_node);
+ json_delete(root_node);
+
+ return 1;
+}
+
+/** @internal Throw Lua error if expr is false */
+#define expr_checked(expr) \
+ if (!(expr)) { lua_pushboolean(L, false); lua_rawseti(L, -2, lua_rawlen(L, -2) + 1); continue; }
+
+static int l_map(lua_State *L)
+{
+ if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
+ lua_pushliteral(L, "map('string with a lua expression')");
+ lua_error(L);
+ }
+
+ struct engine *engine = engine_luaget(L);
+ const char *cmd = lua_tostring(L, 1);
+ uint32_t len = strlen(cmd);
+ lua_newtable(L);
+
+ /* Execute on leader instance */
+ int ntop = lua_gettop(L);
+ engine_cmd(L, cmd, true);
+ lua_settop(L, ntop + 1); /* Push only one return value to table */
+ lua_rawseti(L, -2, 1);
+
+ for (size_t i = 0; i < engine->ipc_set.len; ++i) {
+ int fd = engine->ipc_set.at[i];
+ /* Send command */
+ expr_checked(write(fd, &len, sizeof(len)) == sizeof(len));
+ expr_checked(write(fd, cmd, len) == len);
+ /* Read response */
+ uint32_t rlen = 0;
+ if (read(fd, &rlen, sizeof(rlen)) == sizeof(rlen)) {
+ expr_checked(rlen < UINT32_MAX);
+ auto_free char *rbuf = malloc(rlen + 1);
+ expr_checked(rbuf != NULL);
+ expr_checked(read(fd, rbuf, rlen) == rlen);
+ rbuf[rlen] = '\0';
+ /* Unpack from JSON */
+ JsonNode *root_node = json_decode(rbuf);
+ if (root_node) {
+ l_unpack_json(L, root_node);
+ } else {
+ lua_pushlstring(L, rbuf, rlen);
+ }
+ json_delete(root_node);
+ lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
+ continue;
+ }
+ /* Didn't respond */
+ lua_pushboolean(L, false);
+ lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
+ }
+ return 1;
+}
+
+#undef expr_checked
+
+
+/** Trampoline function for module properties. */
+static int l_trampoline(lua_State *L)
+{
+ struct kr_module *module = lua_touserdata(L, lua_upvalueindex(1));
+ void* callback = lua_touserdata(L, lua_upvalueindex(2));
+ struct engine *engine = engine_luaget(L);
+ if (!module) {
+ lua_pushstring(L, "module closure missing upvalue");
+ lua_error(L);
+ }
+
+ /* Now we only have property callback or config,
+ * if we expand the callables, we might need a callback_type.
+ */
+ const char *args = NULL;
+ auto_free char *cleanup_args = NULL;
+ if (lua_gettop(L) > 0) {
+ if (lua_istable(L, 1) || lua_isboolean(L, 1)) {
+ cleanup_args = l_pack_json(L, 1);
+ args = cleanup_args;
+ } else {
+ args = lua_tostring(L, 1);
+ }
+ }
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic" /* void* vs. function pointer */
+ if (callback == module->config) {
+ module->config(module, args);
+ } else {
+ kr_prop_cb *prop = (kr_prop_cb *)callback;
+ auto_free char *ret = prop(engine, module, args);
+ if (!ret) { /* No results */
+ return 0;
+ }
+ JsonNode *root_node = json_decode(ret);
+ if (root_node) {
+ l_unpack_json(L, root_node);
+ } else {
+ lua_pushstring(L, ret);
+ }
+ json_delete(root_node);
+ return 1;
+ }
+ #pragma GCC diagnostic pop
+
+ /* No results */
+ return 0;
+}
+
+/*
+ * Engine API.
+ */
+
+static int init_resolver(struct engine *engine)
+{
+ /* Note: it had been zored by engine_init(). */
+ /* Open resolution context */
+ engine->resolver.trust_anchors = map_make(NULL);
+ engine->resolver.negative_anchors = map_make(NULL);
+ engine->resolver.pool = engine->pool;
+ engine->resolver.modules = &engine->modules;
+ engine->resolver.cache_rtt_tout_retry_interval = KR_NS_TIMEOUT_RETRY_INTERVAL;
+ /* Create OPT RR */
+ engine->resolver.opt_rr = mm_alloc(engine->pool, sizeof(knot_rrset_t));
+ if (!engine->resolver.opt_rr) {
+ return kr_error(ENOMEM);
+ }
+ knot_edns_init(engine->resolver.opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
+ /* Use default TLS padding */
+ engine->resolver.tls_padding = -1;
+ /* Empty init; filled via ./lua/config.lua */
+ kr_zonecut_init(&engine->resolver.root_hints, (const uint8_t *)"", engine->pool);
+ /* Open NS rtt + reputation cache */
+ lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, engine->pool, NULL);
+ lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, engine->pool, NULL);
+ lru_create(&engine->resolver.cache_cookie, LRU_COOKIES_SIZE, engine->pool, NULL);
+
+ /* Load basic modules */
+ engine_register(engine, "iterate", NULL, NULL);
+ engine_register(engine, "validate", NULL, NULL);
+ engine_register(engine, "cache", NULL, NULL);
+
+ return array_push(engine->backends, kr_cdb_lmdb());
+}
+
+static int init_state(struct engine *engine)
+{
+ /* Initialize Lua state */
+ engine->L = luaL_newstate();
+ if (engine->L == NULL) {
+ return kr_error(ENOMEM);
+ }
+ /* Initialize used libraries. */
+ lua_gc(engine->L, LUA_GCSTOP, 0);
+ luaL_openlibs(engine->L);
+ /* Global functions */
+ lua_pushcfunction(engine->L, l_help);
+ lua_setglobal(engine->L, "help");
+ lua_pushcfunction(engine->L, l_quit);
+ lua_setglobal(engine->L, "quit");
+ lua_pushcfunction(engine->L, l_hostname);
+ lua_setglobal(engine->L, "hostname");
+ lua_pushcfunction(engine->L, l_package_version);
+ lua_setglobal(engine->L, "package_version");
+ lua_pushcfunction(engine->L, l_moduledir);
+ lua_setglobal(engine->L, "moduledir");
+ lua_pushcfunction(engine->L, l_verbose);
+ lua_setglobal(engine->L, "verbose");
+ lua_pushcfunction(engine->L, l_setuser);
+ lua_setglobal(engine->L, "user");
+ lua_pushcfunction(engine->L, l_trustanchor);
+ lua_setglobal(engine->L, "trustanchor");
+ lua_pushcfunction(engine->L, l_hint_root_file);
+ lua_setglobal(engine->L, "_hint_root_file");
+ lua_pushliteral(engine->L, libknot_SONAME);
+ lua_setglobal(engine->L, "libknot_SONAME");
+ lua_pushliteral(engine->L, libzscanner_SONAME);
+ lua_setglobal(engine->L, "libzscanner_SONAME");
+ lua_pushcfunction(engine->L, l_tojson);
+ lua_setglobal(engine->L, "tojson");
+ lua_pushcfunction(engine->L, l_fromjson);
+ lua_setglobal(engine->L, "fromjson");
+ lua_pushcfunction(engine->L, l_map);
+ lua_setglobal(engine->L, "map");
+ lua_pushlightuserdata(engine->L, engine);
+ lua_setglobal(engine->L, "__engine");
+ return kr_ok();
+}
+
+/**
+ * Start luacov measurement and store results to file specified by
+ * KRESD_COVERAGE_STATS environment variable.
+ * Do nothing if the variable is not set.
+ */
+static void init_measurement(struct engine *engine)
+{
+ const char * const statspath = getenv("KRESD_COVERAGE_STATS");
+ if (!statspath)
+ return;
+
+ char * snippet = NULL;
+ int ret = asprintf(&snippet,
+ "_luacov_runner = require('luacov.runner')\n"
+ "_luacov_runner.init({\n"
+ " statsfile = '%s',\n"
+ " exclude = {'test', 'tapered', 'lua/5.1'},\n"
+ "})\n"
+ "jit.off()\n", statspath
+ );
+ assert(ret > 0);
+
+ ret = luaL_loadstring(engine->L, snippet);
+ assert(ret == 0);
+ lua_call(engine->L, 0, 0);
+ free(snippet);
+}
+
+int engine_init(struct engine *engine, knot_mm_t *pool)
+{
+ if (engine == NULL) {
+ return kr_error(EINVAL);
+ }
+
+ memset(engine, 0, sizeof(*engine));
+ engine->pool = pool;
+
+ /* Initialize state */
+ int ret = init_state(engine);
+ if (ret != 0) {
+ engine_deinit(engine);
+ return ret;
+ }
+ init_measurement(engine);
+ /* Initialize resolver */
+ ret = init_resolver(engine);
+ if (ret != 0) {
+ engine_deinit(engine);
+ return ret;
+ }
+ /* Initialize network */
+ network_init(&engine->net, uv_default_loop(), TCP_BACKLOG_DEFAULT);
+
+ return ret;
+}
+
+static void engine_unload(struct engine *engine, struct kr_module *module)
+{
+ /* Unregister module */
+ auto_free char *name = strdup(module->name);
+ kr_module_unload(module);
+ /* Clear in Lua world, but not for embedded modules ('cache' in particular). */
+ if (name && !kr_module_embedded(name)) {
+ lua_pushnil(engine->L);
+ lua_setglobal(engine->L, name);
+ }
+ free(module);
+}
+
+void engine_deinit(struct engine *engine)
+{
+ if (engine == NULL) {
+ return;
+ }
+
+ /* Only close sockets and services,
+ * no need to clean up mempool. */
+ network_deinit(&engine->net);
+ kr_zonecut_deinit(&engine->resolver.root_hints);
+ kr_cache_close(&engine->resolver.cache);
+
+ /* The lru keys are currently malloc-ated and need to be freed. */
+ lru_free(engine->resolver.cache_rtt);
+ lru_free(engine->resolver.cache_rep);
+ lru_free(engine->resolver.cache_cookie);
+
+ /* Clear IPC pipes */
+ for (size_t i = 0; i < engine->ipc_set.len; ++i) {
+ close(engine->ipc_set.at[i]);
+ }
+
+ /* Unload modules and engine. */
+ for (size_t i = 0; i < engine->modules.len; ++i) {
+ engine_unload(engine, engine->modules.at[i]);
+ }
+ if (engine->L) {
+ lua_close(engine->L);
+ }
+
+ /* Free data structures */
+ array_clear(engine->modules);
+ array_clear(engine->backends);
+ array_clear(engine->ipc_set);
+ kr_ta_clear(&engine->resolver.trust_anchors);
+ kr_ta_clear(&engine->resolver.negative_anchors);
+ free(engine->hostname);
+ free(engine->moduledir);
+}
+
+int engine_pcall(lua_State *L, int argc)
+{
+#if LUA_VERSION_NUM >= 502
+ lua_getglobal(L, "_SANDBOX");
+ lua_setupvalue(L, -(2 + argc), 1);
+#endif
+ return lua_pcall(L, argc, LUA_MULTRET, 0);
+}
+
+int engine_cmd(lua_State *L, const char *str, bool raw)
+{
+ if (L == NULL) {
+ return kr_error(ENOEXEC);
+ }
+
+ /* Evaluate results */
+ lua_getglobal(L, "eval_cmd");
+ lua_pushstring(L, str);
+ lua_pushboolean(L, raw);
+
+ /* Check result. */
+ return engine_pcall(L, 2);
+}
+
+int engine_ipc(struct engine *engine, const char *expr)
+{
+ if (engine == NULL || engine->L == NULL) {
+ return kr_error(ENOEXEC);
+ }
+
+ /* Run expression and serialize response. */
+ engine_cmd(engine->L, expr, true);
+ if (lua_gettop(engine->L) > 0) {
+ l_tojson(engine->L);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int engine_load_sandbox(struct engine *engine)
+{
+ /* Init environment */
+ static const char sandbox_bytecode[] = {
+ #include "daemon/lua/sandbox.inc"
+ };
+ if (l_dobytecode(engine->L, sandbox_bytecode, sizeof(sandbox_bytecode), "init") != 0) {
+ fprintf(stderr, "[system] error %s\n", lua_tostring(engine->L, -1));
+ lua_pop(engine->L, 1);
+ return kr_error(ENOEXEC);
+ }
+ return kr_ok();
+}
+
+int engine_loadconf(struct engine *engine, const char *config_path)
+{
+ assert(config_path != NULL);
+ int ret = l_dosandboxfile(engine->L, config_path);
+ if (ret != 0) {
+ fprintf(stderr, "%s\n", lua_tostring(engine->L, -1));
+ lua_pop(engine->L, 1);
+ }
+ return ret;
+}
+
+int engine_load_defaults(struct engine *engine)
+{
+ /* Load defaults */
+ static const char config_bytecode[] = {
+ #include "daemon/lua/config.inc"
+ };
+ int ret = l_dobytecode(engine->L, config_bytecode, sizeof(config_bytecode), "config");
+ if (ret != 0) {
+ fprintf(stderr, "%s\n", lua_tostring(engine->L, -1));
+ lua_pop(engine->L, 1);
+ }
+ return ret;
+}
+
+int engine_start(struct engine *engine)
+{
+ /* Clean up stack and restart GC */
+ lua_settop(engine->L, 0);
+ lua_gc(engine->L, LUA_GCCOLLECT, 0);
+ lua_gc(engine->L, LUA_GCSETSTEPMUL, 50);
+ lua_gc(engine->L, LUA_GCSETPAUSE, 400);
+ lua_gc(engine->L, LUA_GCRESTART, 0);
+
+ return kr_ok();
+}
+
+void engine_stop(struct engine *engine)
+{
+ if (!engine) {
+ return;
+ }
+ uv_stop(uv_default_loop());
+}
+
+/** Register module properties in Lua environment, if any. */
+static int register_properties(struct engine *engine, struct kr_module *module)
+{
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic" /* casts in lua_pushlightuserdata() */
+ if (!module->config && !module->props) {
+ return kr_ok();
+ }
+ lua_newtable(engine->L);
+ if (module->config != NULL) {
+ REGISTER_MODULE_CALL(engine->L, module, module->config, "config");
+ }
+
+ const struct kr_prop *p = module->props == NULL ? NULL : module->props();
+ for (; p && p->name; ++p) {
+ if (p->cb != NULL) {
+ REGISTER_MODULE_CALL(engine->L, module, p->cb, p->name);
+ }
+ }
+ lua_setglobal(engine->L, module->name);
+ #pragma GCC diagnostic pop
+
+ /* Register module in Lua env */
+ lua_getglobal(engine->L, "modules_register");
+ lua_getglobal(engine->L, module->name);
+ if (engine_pcall(engine->L, 1) != 0) {
+ lua_pop(engine->L, 1);
+ }
+
+ return kr_ok();
+}
+
+/** @internal Find matching module */
+static size_t module_find(module_array_t *mod_list, const char *name)
+{
+ size_t found = mod_list->len;
+ for (size_t i = 0; i < mod_list->len; ++i) {
+ struct kr_module *mod = mod_list->at[i];
+ if (strcmp(mod->name, name) == 0) {
+ found = i;
+ break;
+ }
+ }
+ return found;
+}
+
+int engine_register(struct engine *engine, const char *name, const char *precedence, const char* ref)
+{
+ if (engine == NULL || name == NULL) {
+ return kr_error(EINVAL);
+ }
+ /* Make sure module is unloaded */
+ (void) engine_unregister(engine, name);
+ /* Find the index of referenced module. */
+ module_array_t *mod_list = &engine->modules;
+ size_t ref_pos = mod_list->len;
+ if (precedence && ref) {
+ ref_pos = module_find(mod_list, ref);
+ if (ref_pos >= mod_list->len) {
+ return kr_error(EIDRM);
+ }
+ }
+ /* Attempt to load binary module */
+ struct kr_module *module = malloc(sizeof(*module));
+ if (!module) {
+ return kr_error(ENOMEM);
+ }
+ module->data = engine;
+ int ret = kr_module_load(module, name, engine->moduledir);
+ /* Load Lua module if not a binary */
+ if (ret == kr_error(ENOENT)) {
+ ret = ffimodule_register_lua(engine, module, name);
+ } else if (ret == kr_error(ENOTSUP)) {
+ /* Print a more helpful message when module is linked against an old resolver ABI. */
+ fprintf(stderr, "[system] module '%s' links to unsupported ABI, please rebuild it\n", name);
+ }
+ if (ret != 0) {
+ free(module);
+ return ret;
+ }
+ if (array_push(engine->modules, module) < 0) {
+ engine_unload(engine, module);
+ return kr_error(ENOMEM);
+ }
+ /* Evaluate precedence operator */
+ if (precedence) {
+ struct kr_module **arr = mod_list->at;
+ size_t emplacement = mod_list->len;
+ if (strcasecmp(precedence, ">") == 0) {
+ if (ref_pos + 1 < mod_list->len)
+ emplacement = ref_pos + 1; /* Insert after target */
+ }
+ if (strcasecmp(precedence, "<") == 0) {
+ emplacement = ref_pos; /* Insert at target */
+ }
+ /* Move the tail if it has some elements. */
+ if (emplacement + 1 < mod_list->len) {
+ memmove(&arr[emplacement + 1], &arr[emplacement], sizeof(*arr) * (mod_list->len - (emplacement + 1)));
+ arr[emplacement] = module;
+ }
+ }
+
+ return register_properties(engine, module);
+}
+
+int engine_unregister(struct engine *engine, const char *name)
+{
+ module_array_t *mod_list = &engine->modules;
+ size_t found = module_find(mod_list, name);
+ if (found < mod_list->len) {
+ engine_unload(engine, mod_list->at[found]);
+ array_del(*mod_list, found);
+ return kr_ok();
+ }
+
+ return kr_error(ENOENT);
+}
+
+void engine_lualib(struct engine *engine, const char *name, lua_CFunction lib_cb)
+{
+ if (engine != NULL) {
+#if LUA_VERSION_NUM >= 502
+ luaL_requiref(engine->L, name, lib_cb, 1);
+ lua_pop(engine->L, 1);
+#else
+ lib_cb(engine->L);
+#endif
+ }
+}
+
+struct engine *engine_luaget(lua_State *L)
+{
+ lua_getglobal(L, "__engine");
+ struct engine *engine = lua_touserdata(L, -1);
+ if (!engine) luaL_error(L, "internal error, empty engine pointer");
+ lua_pop(L, 1);
+ return engine;
+}
diff --git a/daemon/engine.h b/daemon/engine.h
new file mode 100644
index 0000000..b79991a
--- /dev/null
+++ b/daemon/engine.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/*
+ * @internal These are forward decls to allow building modules with engine but without Lua.
+ */
+struct lua_State;
+
+#include "lib/utils.h"
+#include "lib/resolve.h"
+#include "daemon/network.h"
+
+/* @internal Array of file descriptors shorthand. */
+typedef array_t(int) fd_array_t;
+
+struct engine {
+ struct kr_context resolver;
+ struct network net;
+ module_array_t modules;
+ array_t(const struct kr_cdb_api *) backends;
+ fd_array_t ipc_set;
+ knot_mm_t *pool;
+ char *hostname;
+ struct lua_State *L;
+ char *moduledir;
+};
+
+int engine_init(struct engine *engine, knot_mm_t *pool);
+void engine_deinit(struct engine *engine);
+
+/** Perform a lua command within the sandbox.
+ *
+ * @return zero on success.
+ * The result will be returned on the lua stack - an error message in case of failure.
+ * http://www.lua.org/manual/5.1/manual.html#lua_pcall */
+int engine_cmd(struct lua_State *L, const char *str, bool raw);
+
+/** Execute current chunk in the sandbox */
+int engine_pcall(struct lua_State *L, int argc);
+
+int engine_ipc(struct engine *engine, const char *expr);
+
+
+int engine_load_sandbox(struct engine *engine);
+int engine_loadconf(struct engine *engine, const char *config_path);
+int engine_load_defaults(struct engine *engine);
+
+/** Start the lua engine and execute the config. */
+int engine_start(struct engine *engine);
+void engine_stop(struct engine *engine);
+int engine_register(struct engine *engine, const char *name, const char *precedence, const char* ref);
+int engine_unregister(struct engine *engine, const char *name);
+void engine_lualib(struct engine *engine, const char *name, int (*lib_cb) (struct lua_State *));
+
+
+/** Return engine light userdata. */
+struct engine *engine_luaget(struct lua_State *L);
+
+/** Set/get the per engine hostname */
+char *engine_get_hostname(struct engine *engine);
+int engine_set_hostname(struct engine *engine, const char *hostname);
+
+/** Set/get the per engine moduledir */
+char *engine_get_moduledir(struct engine *engine);
+int engine_set_moduledir(struct engine *engine, const char *moduledir);
+
+/** Load root hints from a zonefile (or config-time default if NULL).
+ *
+ * @return error message or NULL (statically allocated)
+ * @note exported to be usable from the hints module.
+ */
+KR_EXPORT
+const char* engine_hint_root_file(struct kr_context *ctx, const char *file);
+
diff --git a/daemon/ffimodule.c b/daemon/ffimodule.c
new file mode 100644
index 0000000..1cb6b71
--- /dev/null
+++ b/daemon/ffimodule.c
@@ -0,0 +1,289 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <uv.h>
+
+#include "daemon/engine.h"
+#include "daemon/ffimodule.h"
+#include "daemon/bindings.h"
+#include "lib/module.h"
+#include "lib/layer.h"
+
+#if LUA_VERSION_NUM >= 502
+#define l_resume(L, argc) lua_resume((L), NULL, (argc))
+#else
+#define l_resume(L, argc) lua_resume((L), (argc))
+#endif
+
+/** @internal Slots for layer callbacks.
+ * Each slot ID corresponds to Lua reference in module API. */
+enum {
+ SLOT_begin = 0,
+ SLOT_reset,
+ SLOT_finish,
+ SLOT_consume,
+ SLOT_produce,
+ SLOT_checkout,
+ SLOT_answer_finalize,
+ SLOT_count /* dummy, must be the last */
+};
+#define SLOT_size sizeof(int)
+
+/** @internal Helper for retrieving the right function entrypoint. */
+static inline lua_State *l_ffi_preface(struct kr_module *module, const char *call) {
+ lua_State *L = module->lib;
+ lua_getglobal(L, module->name);
+ lua_getfield(L, -1, call);
+ lua_remove(L, -2);
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ return NULL;
+ }
+ lua_pushlightuserdata(L, module);
+ return L;
+}
+
+/** @internal Continue with coroutine. */
+static void l_ffi_resume_cb(uv_idle_t *check)
+{
+ lua_State *L = check->data;
+ int status = l_resume(L, 0);
+ if (status != LUA_YIELD) {
+ uv_idle_stop(check); /* Stop coroutine */
+ uv_close((uv_handle_t *)check, (uv_close_cb)free);
+ }
+ lua_pop(L, lua_gettop(L));
+}
+
+/** @internal Schedule deferred continuation. */
+static int l_ffi_defer(lua_State *L)
+{
+ uv_idle_t *check = malloc(sizeof(*check));
+ if (!check) {
+ return kr_error(ENOMEM);
+ }
+ uv_idle_init(uv_default_loop(), check);
+ check->data = L;
+ return uv_idle_start(check, l_ffi_resume_cb);
+}
+
+/** @internal Helper for calling the entrypoint. */
+static inline int l_ffi_call(lua_State *L, int argc)
+{
+ int status = lua_pcall(L, argc, 1, 0);
+ if (status != 0) {
+ fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ return kr_error(EIO);
+ }
+ if (lua_isnumber(L, -1)) { /* Return code */
+ status = lua_tonumber(L, -1);
+ } else if (lua_isthread(L, -1)) { /* Continuations */
+ status = l_ffi_defer(lua_tothread(L, -1));
+ }
+ lua_pop(L, 1);
+ return status;
+}
+
+static int l_ffi_init(struct kr_module *module)
+{
+ lua_State *L = l_ffi_preface(module, "init");
+ if (!L) {
+ return 0;
+ }
+ return l_ffi_call(L, 1);
+}
+
+static int l_ffi_deinit(struct kr_module *module)
+{
+ /* Deinit the module in Lua (if possible) */
+ int ret = 0;
+ lua_State *L = module->lib;
+ if (l_ffi_preface(module, "deinit")) {
+ ret = l_ffi_call(L, 1);
+ }
+ module->lib = NULL;
+ /* Free the layer API wrapper (unconst it) */
+ kr_layer_api_t* api = module->data;
+ if (!api) {
+ return ret;
+ }
+ /* Unregister layer callback references from registry. */
+ for (int si = 0; si < SLOT_count; ++si) {
+ if (api->cb_slots[si] > 0) {
+ luaL_unref(L, LUA_REGISTRYINDEX, api->cb_slots[si]);
+ }
+ }
+ free(api);
+ return ret;
+}
+
+/** @internal Helper for retrieving layer Lua function by name. */
+#define LAYER_FFI_CALL(ctx, slot_name) \
+ const int *cb_slot = (ctx)->api->cb_slots + SLOT_ ## slot_name; \
+ if (*cb_slot <= 0) { \
+ return ctx->state; \
+ } \
+ struct kr_module *module = (ctx)->api->data; \
+ lua_State *L = module->lib; \
+ lua_rawgeti(L, LUA_REGISTRYINDEX, *cb_slot); \
+ lua_pushnumber(L, ctx->state)
+
+static int l_ffi_layer_begin(kr_layer_t *ctx)
+{
+ LAYER_FFI_CALL(ctx, begin);
+ lua_pushlightuserdata(L, ctx->req);
+ return l_ffi_call(L, 2);
+}
+
+static int l_ffi_layer_reset(kr_layer_t *ctx)
+{
+ LAYER_FFI_CALL(ctx, reset);
+ lua_pushlightuserdata(L, ctx->req);
+ return l_ffi_call(L, 2);
+}
+
+static int l_ffi_layer_finish(kr_layer_t *ctx)
+{
+ struct kr_request *req = ctx->req;
+ LAYER_FFI_CALL(ctx, finish);
+ lua_pushlightuserdata(L, req);
+ lua_pushlightuserdata(L, req->answer);
+ return l_ffi_call(L, 3);
+}
+
+static int l_ffi_layer_consume(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ if (ctx->state & KR_STATE_FAIL) {
+ return ctx->state; /* Already failed, skip */
+ }
+ LAYER_FFI_CALL(ctx, consume);
+ lua_pushlightuserdata(L, ctx->req);
+ lua_pushlightuserdata(L, pkt);
+ return l_ffi_call(L, 3);
+}
+
+static int l_ffi_layer_produce(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ if (ctx->state & (KR_STATE_FAIL)) {
+ return ctx->state; /* Already failed or done, skip */
+ }
+ LAYER_FFI_CALL(ctx, produce);
+ lua_pushlightuserdata(L, ctx->req);
+ lua_pushlightuserdata(L, pkt);
+ return l_ffi_call(L, 3);
+}
+
+static int l_ffi_layer_checkout(kr_layer_t *ctx, knot_pkt_t *pkt, struct sockaddr *dst, int type)
+{
+ if (ctx->state & (KR_STATE_FAIL)) {
+ return ctx->state; /* Already failed or done, skip */
+ }
+ LAYER_FFI_CALL(ctx, checkout);
+ lua_pushlightuserdata(L, ctx->req);
+ lua_pushlightuserdata(L, pkt);
+ lua_pushlightuserdata(L, dst);
+ lua_pushboolean(L, type == SOCK_STREAM);
+ return l_ffi_call(L, 5);
+}
+
+static int l_ffi_layer_answer_finalize(kr_layer_t *ctx)
+{
+ LAYER_FFI_CALL(ctx, answer_finalize);
+ lua_pushlightuserdata(L, ctx->req);
+ return l_ffi_call(L, 2);
+}
+#undef LAYER_FFI_CALL
+
+/** @internal Conditionally register layer trampoline
+ * @warning Expects 'module.layer' to be on top of Lua stack. */
+#define LAYER_REGISTER(L, api, name) do { \
+ int *cb_slot = (api)->cb_slots + SLOT_ ## name; \
+ lua_getfield((L), -1, #name); \
+ if (!lua_isnil((L), -1)) { \
+ (api)->name = l_ffi_layer_ ## name; \
+ *cb_slot = luaL_ref((L), LUA_REGISTRYINDEX); \
+ } else { \
+ lua_pop((L), 1); \
+ } \
+} while(0)
+
+/** @internal Create C layer api wrapper. */
+static kr_layer_api_t *l_ffi_layer_create(lua_State *L, struct kr_module *module)
+{
+ /* Fabricate layer API wrapping the Lua functions
+ * reserve slots after it for references to Lua callbacks. */
+ const size_t api_length = offsetof(kr_layer_api_t, cb_slots)
+ + (SLOT_count * SLOT_size);
+ kr_layer_api_t *api = malloc(api_length);
+ if (api) {
+ memset(api, 0, api_length);
+ LAYER_REGISTER(L, api, begin);
+ LAYER_REGISTER(L, api, finish);
+ LAYER_REGISTER(L, api, consume);
+ LAYER_REGISTER(L, api, produce);
+ LAYER_REGISTER(L, api, checkout);
+ LAYER_REGISTER(L, api, answer_finalize);
+ LAYER_REGISTER(L, api, reset);
+ /* Begin is always set, as it initializes layer baton. */
+ api->begin = l_ffi_layer_begin;
+ api->data = module;
+ }
+ return api;
+}
+
+/** @internal Retrieve C layer api wrapper. */
+static const kr_layer_api_t *l_ffi_layer(struct kr_module *module)
+{
+ if (module) {
+ return (const kr_layer_api_t *)module->data;
+ }
+ return NULL;
+}
+#undef LAYER_REGISTER
+
+int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name)
+{
+ /* Register module in Lua */
+ lua_State *L = engine->L;
+ lua_getglobal(L, "require");
+ lua_pushstring(L, name);
+ if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
+ fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ return kr_error(ENOENT);
+ }
+ lua_setglobal(L, name);
+ lua_getglobal(L, name);
+
+ /* Create FFI module with trampolined functions. */
+ memset(module, 0, sizeof(*module));
+ module->name = strdup(name);
+ module->init = &l_ffi_init;
+ module->deinit = &l_ffi_deinit;
+ /* Bake layer API if defined in module */
+ lua_getfield(L, -1, "layer");
+ if (!lua_isnil(L, -1)) {
+ module->layer = &l_ffi_layer;
+ module->data = l_ffi_layer_create(L, module);
+ }
+ module->lib = L;
+ lua_pop(L, 2); /* Clear the layer + module global */
+ if (module->init) {
+ return module->init(module);
+ }
+ return kr_ok();
+}
diff --git a/daemon/ffimodule.h b/daemon/ffimodule.h
new file mode 100644
index 0000000..92298f5
--- /dev/null
+++ b/daemon/ffimodule.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+/**
+ * Register Lua module as a FFI module.
+ * This fabricates a standard module interface,
+ * that trampolines to the Lua module methods.
+ *
+ * @note Lua module is loaded in it's own coroutine,
+ * so it's possible to yield and resume at arbitrary
+ * places except deinit()
+ *
+ * @param engine daemon engine
+ * @param module prepared module
+ * @param name module name
+ * @return 0 or an error
+ */
+int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name);
diff --git a/daemon/io.c b/daemon/io.c
new file mode 100644
index 0000000..f183d34
--- /dev/null
+++ b/daemon/io.c
@@ -0,0 +1,494 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <libknot/errcode.h>
+#include <contrib/ucw/lib.h>
+#include <contrib/ucw/mempool.h>
+#include <assert.h>
+
+#include "daemon/io.h"
+#include "daemon/network.h"
+#include "daemon/worker.h"
+#include "daemon/tls.h"
+#include "daemon/session.h"
+
+#define negotiate_bufsize(func, handle, bufsize_want) do { \
+ int bufsize = 0; func(handle, &bufsize); \
+ if (bufsize < bufsize_want) { \
+ bufsize = bufsize_want; \
+ func(handle, &bufsize); \
+ } \
+} while (0)
+
+static void check_bufsize(uv_handle_t* handle)
+{
+ return; /* TODO: resurrect after https://github.com/libuv/libuv/issues/419 */
+ /* We want to buffer at least N waves in advance.
+ * This is magic presuming we can pull in a whole recvmmsg width in one wave.
+ * Linux will double this the bufsize wanted.
+ */
+ const int bufsize_want = 2 * sizeof( ((struct worker_ctx *)NULL)->wire_buf ) ;
+ negotiate_bufsize(uv_recv_buffer_size, handle, bufsize_want);
+ negotiate_bufsize(uv_send_buffer_size, handle, bufsize_want);
+}
+
+#undef negotiate_bufsize
+
+static void handle_getbuf(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
+{
+ /* UDP sessions use worker buffer for wire data,
+ * TCP sessions use session buffer for wire data
+ * (see session_set_handle()).
+ * TLS sessions use buffer from TLS context.
+ * The content of the worker buffer is
+ * guaranteed to be unchanged only for the duration of
+ * udp_read() and tcp_read().
+ */
+ struct session *s = handle->data;
+ if (!session_flags(s)->has_tls) {
+ buf->base = (char *) session_wirebuf_get_free_start(s);
+ buf->len = session_wirebuf_get_free_size(s);
+ } else {
+ struct tls_common_ctx *ctx = session_tls_get_common_ctx(s);
+ buf->base = (char *) ctx->recv_buf;
+ buf->len = sizeof(ctx->recv_buf);
+ }
+}
+
+void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
+ const struct sockaddr *addr, unsigned flags)
+{
+ uv_loop_t *loop = handle->loop;
+ struct worker_ctx *worker = loop->data;
+ struct session *s = handle->data;
+ if (session_flags(s)->closing) {
+ return;
+ }
+ if (nread <= 0) {
+ if (nread < 0) { /* Error response, notify resolver */
+ worker_submit(s, NULL);
+ } /* nread == 0 is for freeing buffers, we don't need to do this */
+ return;
+ }
+ if (addr->sa_family == AF_UNSPEC) {
+ return;
+ }
+ struct sockaddr *peer = session_get_peer(s);
+ if (session_flags(s)->outgoing) {
+ assert(peer->sa_family != AF_UNSPEC);
+ if (kr_sockaddr_cmp(peer, addr) != 0) {
+ return;
+ }
+ } else {
+ memcpy(peer, addr, kr_sockaddr_len(addr));
+ }
+ ssize_t consumed = session_wirebuf_consume(s, (const uint8_t *)buf->base,
+ nread);
+ assert(consumed == nread); (void)consumed;
+ session_wirebuf_process(s);
+ session_wirebuf_discard(s);
+ mp_flush(worker->pkt_pool.ctx);
+}
+
+static int udp_bind_finalize(uv_handle_t *handle)
+{
+ check_bufsize(handle);
+ /* Handle is already created, just create context. */
+ struct session *s = session_new(handle, false);
+ assert(s);
+ session_flags(s)->outgoing = false;
+ return io_start_read(handle);
+}
+
+int udp_bind(uv_udp_t *handle, struct sockaddr *addr)
+{
+ unsigned flags = UV_UDP_REUSEADDR;
+ if (addr->sa_family == AF_INET6) {
+ flags |= UV_UDP_IPV6ONLY;
+ }
+ int ret = uv_udp_bind(handle, addr, flags);
+ if (ret != 0) {
+ return ret;
+ }
+ return udp_bind_finalize((uv_handle_t *)handle);
+}
+
+int udp_bindfd(uv_udp_t *handle, int fd)
+{
+ if (!handle) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = uv_udp_open(handle, (uv_os_sock_t) fd);
+ if (ret != 0) {
+ return ret;
+ }
+ return udp_bind_finalize((uv_handle_t *)handle);
+}
+
+void tcp_timeout_trigger(uv_timer_t *timer)
+{
+ struct session *s = timer->data;
+
+ assert(!session_flags(s)->closing);
+
+ struct worker_ctx *worker = timer->loop->data;
+
+ if (!session_tasklist_is_empty(s)) {
+ int finalized = session_tasklist_finalize_expired(s);
+ worker->stats.timeout += finalized;
+ /* session_tasklist_finalize_expired() may call worker_task_finalize().
+ * If session is a source session and there were IO errors,
+ * worker_task_finalize() can filnalize all tasks and close session. */
+ if (session_flags(s)->closing) {
+ return;
+ }
+
+ }
+ if (!session_tasklist_is_empty(s)) {
+ uv_timer_stop(timer);
+ session_timer_start(s, tcp_timeout_trigger,
+ KR_RESOLVE_TIME_LIMIT / 2,
+ KR_RESOLVE_TIME_LIMIT / 2);
+ } else {
+ /* Normally it should not happen,
+ * but better to check if there anything in this list. */
+ while (!session_waitinglist_is_empty(s)) {
+ struct qr_task *t = session_waitinglist_pop(s, false);
+ worker_task_finalize(t, KR_STATE_FAIL);
+ worker_task_unref(t);
+ worker->stats.timeout += 1;
+ if (session_flags(s)->closing) {
+ return;
+ }
+ }
+ const struct engine *engine = worker->engine;
+ const struct network *net = &engine->net;
+ uint64_t idle_in_timeout = net->tcp.in_idle_timeout;
+ uint64_t last_activity = session_last_activity(s);
+ uint64_t idle_time = kr_now() - last_activity;
+ if (idle_time < idle_in_timeout) {
+ idle_in_timeout -= idle_time;
+ uv_timer_stop(timer);
+ session_timer_start(s, tcp_timeout_trigger,
+ idle_in_timeout, idle_in_timeout);
+ } else {
+ struct sockaddr *peer = session_get_peer(s);
+ char *peer_str = kr_straddr(peer);
+ kr_log_verbose("[io] => closing connection to '%s'\n",
+ peer_str ? peer_str : "");
+ if (session_flags(s)->outgoing) {
+ worker_del_tcp_waiting(worker, peer);
+ worker_del_tcp_connected(worker, peer);
+ }
+ session_close(s);
+ }
+ }
+}
+
+static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
+{
+ struct session *s = handle->data;
+ assert(s && session_get_handle(s) == (uv_handle_t *)handle &&
+ handle->type == UV_TCP);
+
+ if (session_flags(s)->closing) {
+ return;
+ }
+
+ /* nread might be 0, which does not indicate an error or EOF.
+ * This is equivalent to EAGAIN or EWOULDBLOCK under read(2). */
+ if (nread == 0) {
+ return;
+ }
+
+ if (nread < 0 || !buf->base) {
+ if (kr_verbose_status) {
+ struct sockaddr *peer = session_get_peer(s);
+ char *peer_str = kr_straddr(peer);
+ kr_log_verbose("[io] => connection to '%s' closed by peer (%s)\n",
+ peer_str ? peer_str : "",
+ uv_strerror(nread));
+ }
+ worker_end_tcp(s);
+ return;
+ }
+
+ ssize_t consumed = 0;
+ const uint8_t *data = (const uint8_t *)buf->base;
+ ssize_t data_len = nread;
+ if (session_flags(s)->has_tls) {
+ /* buf->base points to start of the tls receive buffer.
+ Decode data free space in session wire buffer. */
+ consumed = tls_process_input_data(s, (const uint8_t *)buf->base, nread);
+ if (consumed < 0) {
+ if (kr_verbose_status) {
+ struct sockaddr *peer = session_get_peer(s);
+ char *peer_str = kr_straddr(peer);
+ kr_log_verbose("[io] => connection to '%s': "
+ "error processing TLS data, close\n",
+ peer_str ? peer_str : "");
+ }
+ worker_end_tcp(s);
+ return;
+ } else if (consumed == 0) {
+ return;
+ }
+ data = session_wirebuf_get_free_start(s);
+ data_len = consumed;
+ }
+
+ /* data points to start of the free space in session wire buffer.
+ Simple increase internal counter. */
+ consumed = session_wirebuf_consume(s, data, data_len);
+ assert(consumed == data_len);
+
+ int ret = session_wirebuf_process(s);
+ if (ret < 0) {
+ /* An error has occurred, close the session. */
+ worker_end_tcp(s);
+ }
+ session_wirebuf_compress(s);
+ struct worker_ctx *worker = handle->loop->data;
+ mp_flush(worker->pkt_pool.ctx);
+}
+
+static void _tcp_accept(uv_stream_t *master, int status, bool tls)
+{
+ if (status != 0) {
+ return;
+ }
+
+ struct worker_ctx *worker = (struct worker_ctx *)master->loop->data;
+ uv_tcp_t *client = malloc(sizeof(uv_tcp_t));
+ if (!client) {
+ return;
+ }
+ int res = io_create(master->loop, (uv_handle_t *)client,
+ SOCK_STREAM, AF_UNSPEC, tls);
+ if (res) {
+ if (res == UV_EMFILE) {
+ worker->too_many_open = true;
+ worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+ }
+ /* Since res isn't OK struct session wasn't allocated \ borrowed.
+ * We must release client handle only.
+ */
+ free(client);
+ return;
+ }
+
+ /* struct session was allocated \ borrowed from memory pool. */
+ struct session *s = client->data;
+ assert(session_flags(s)->outgoing == false);
+ assert(session_flags(s)->has_tls == tls);
+
+ if (uv_accept(master, (uv_stream_t *)client) != 0) {
+ /* close session, close underlying uv handles and
+ * deallocate (or return to memory pool) memory. */
+ session_close(s);
+ return;
+ }
+
+ /* Set deadlines for TCP connection and start reading.
+ * It will re-check every half of a request time limit if the connection
+ * is idle and should be terminated, this is an educated guess. */
+ struct sockaddr *peer = session_get_peer(s);
+ int peer_len = sizeof(union inaddr);
+ int ret = uv_tcp_getpeername(client, peer, &peer_len);
+ if (ret || peer->sa_family == AF_UNSPEC) {
+ session_close(s);
+ return;
+ }
+
+ const struct engine *engine = worker->engine;
+ const struct network *net = &engine->net;
+ uint64_t idle_in_timeout = net->tcp.in_idle_timeout;
+
+ uint64_t timeout = KR_CONN_RTT_MAX / 2;
+ if (tls) {
+ timeout += TLS_MAX_HANDSHAKE_TIME;
+ struct tls_ctx_t *ctx = session_tls_get_server_ctx(s);
+ if (!ctx) {
+ ctx = tls_new(worker);
+ if (!ctx) {
+ session_close(s);
+ return;
+ }
+ ctx->c.session = s;
+ ctx->c.handshake_state = TLS_HS_IN_PROGRESS;
+ session_tls_set_server_ctx(s, ctx);
+ }
+ }
+ session_timer_start(s, tcp_timeout_trigger, timeout, idle_in_timeout);
+ io_start_read((uv_handle_t *)client);
+}
+
+static void tcp_accept(uv_stream_t *master, int status)
+{
+ _tcp_accept(master, status, false);
+}
+
+static void tls_accept(uv_stream_t *master, int status)
+{
+ _tcp_accept(master, status, true);
+}
+
+static int set_tcp_option(uv_handle_t *handle, int option, int val)
+{
+ uv_os_fd_t fd = 0;
+ if (uv_fileno(handle, &fd) == 0) {
+ return setsockopt(fd, IPPROTO_TCP, option, &val, sizeof(val));
+ }
+ return 0; /* N/A */
+}
+
+static int tcp_bind_finalize(uv_handle_t *handle)
+{
+ /* TCP_FASTOPEN enables 1 RTT connection resumptions. */
+#ifdef TCP_FASTOPEN
+# ifdef __linux__
+ (void) set_tcp_option(handle, TCP_FASTOPEN, 16); /* Accepts queue length hint */
+# else
+ (void) set_tcp_option(handle, TCP_FASTOPEN, 1); /* Accepts on/off */
+# endif
+#endif
+
+ handle->data = NULL;
+ return 0;
+}
+
+static int _tcp_bind(uv_tcp_t *handle, struct sockaddr *addr, uv_connection_cb connection, int tcp_backlog)
+{
+ unsigned flags = 0;
+ if (addr->sa_family == AF_INET6) {
+ flags |= UV_TCP_IPV6ONLY;
+ }
+
+ int ret = uv_tcp_bind(handle, addr, flags);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* TCP_DEFER_ACCEPT delays accepting connections until there is readable data. */
+#ifdef TCP_DEFER_ACCEPT
+ if (set_tcp_option((uv_handle_t *)handle, TCP_DEFER_ACCEPT, KR_CONN_RTT_MAX/1000) != 0) {
+ kr_log_info("[ io ] tcp_bind (defer_accept): %s\n", strerror(errno));
+ }
+#endif
+
+ ret = uv_listen((uv_stream_t *)handle, tcp_backlog, connection);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return tcp_bind_finalize((uv_handle_t *)handle);
+}
+
+int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr, int tcp_backlog)
+{
+ return _tcp_bind(handle, addr, tcp_accept, tcp_backlog);
+}
+
+int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr, int tcp_backlog)
+{
+ return _tcp_bind(handle, addr, tls_accept, tcp_backlog);
+}
+
+static int _tcp_bindfd(uv_tcp_t *handle, int fd, uv_connection_cb connection, int tcp_backlog)
+{
+ if (!handle) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = uv_tcp_open(handle, (uv_os_sock_t) fd);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = uv_listen((uv_stream_t *)handle, tcp_backlog, connection);
+ if (ret != 0) {
+ return ret;
+ }
+ return tcp_bind_finalize((uv_handle_t *)handle);
+}
+
+int tcp_bindfd(uv_tcp_t *handle, int fd, int tcp_backlog)
+{
+ return _tcp_bindfd(handle, fd, tcp_accept, tcp_backlog);
+}
+
+int tcp_bindfd_tls(uv_tcp_t *handle, int fd, int tcp_backlog)
+{
+ return _tcp_bindfd(handle, fd, tls_accept, tcp_backlog);
+}
+
+int io_create(uv_loop_t *loop, uv_handle_t *handle, int type, unsigned family, bool has_tls)
+{
+ int ret = -1;
+ if (type == SOCK_DGRAM) {
+ ret = uv_udp_init(loop, (uv_udp_t *)handle);
+ } else if (type == SOCK_STREAM) {
+ ret = uv_tcp_init_ex(loop, (uv_tcp_t *)handle, family);
+ uv_tcp_nodelay((uv_tcp_t *)handle, 1);
+ }
+ if (ret != 0) {
+ return ret;
+ }
+ struct session *s = session_new(handle, has_tls);
+ if (s == NULL) {
+ ret = -1;
+ }
+ return ret;
+}
+
+void io_deinit(uv_handle_t *handle)
+{
+ if (!handle) {
+ return;
+ }
+ session_free(handle->data);
+ handle->data = NULL;
+}
+
+void io_free(uv_handle_t *handle)
+{
+ io_deinit(handle);
+ free(handle);
+}
+
+int io_start_read(uv_handle_t *handle)
+{
+ switch (handle->type) {
+ case UV_UDP:
+ return uv_udp_recv_start((uv_udp_t *)handle, &handle_getbuf, &udp_recv);
+ case UV_TCP:
+ return uv_read_start((uv_stream_t *)handle, &handle_getbuf, &tcp_recv);
+ default:
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+}
+
+int io_stop_read(uv_handle_t *handle)
+{
+ if (handle->type == UV_UDP) {
+ return uv_udp_recv_stop((uv_udp_t *)handle);
+ } else {
+ return uv_read_stop((uv_stream_t *)handle);
+ }
+}
diff --git a/daemon/io.h b/daemon/io.h
new file mode 100644
index 0000000..1d41569
--- /dev/null
+++ b/daemon/io.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <uv.h>
+#include <libknot/packet/pkt.h>
+#include <gnutls/gnutls.h>
+#include "lib/generic/array.h"
+#include "daemon/worker.h"
+
+struct tls_ctx_t;
+struct tls_client_ctx_t;
+
+int udp_bind(uv_udp_t *handle, struct sockaddr *addr);
+int udp_bindfd(uv_udp_t *handle, int fd);
+int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr, int tcp_backlog);
+int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr, int tcp_backlog);
+int tcp_bindfd(uv_tcp_t *handle, int fd, int tcp_backlog);
+int tcp_bindfd_tls(uv_tcp_t *handle, int fd, int tcp_backlog);
+void tcp_timeout_trigger(uv_timer_t *timer);
+
+/** Initialize the handle, incl. ->data = struct session * instance.
+ * \param type = SOCK_*
+ * \param family = AF_*
+ * \param has_tls has meanings only when type is SOCK_STREAM */
+int io_create(uv_loop_t *loop, uv_handle_t *handle, int type,
+ unsigned family, bool has_tls);
+void io_deinit(uv_handle_t *handle);
+void io_free(uv_handle_t *handle);
+
+int io_start_read(uv_handle_t *handle);
+int io_stop_read(uv_handle_t *handle);
diff --git a/daemon/lua/config.lua b/daemon/lua/config.lua
new file mode 100644
index 0000000..448d6dd
--- /dev/null
+++ b/daemon/lua/config.lua
@@ -0,0 +1,35 @@
+-- Listen on localhost
+if not next(net.list()) and not env.KRESD_NO_LISTEN then
+ local ok, err = pcall(net.listen, '127.0.0.1')
+ if not ok then
+ error('bind to 127.0.0.1@53 '..err)
+ end
+ -- IPv6 loopback may fail
+ ok, err = pcall(net.listen, '::1')
+ if not ok and verbose() then
+ print('bind to ::1@53 '..err)
+ end
+ -- Exit when kresd isn't listening on any interfaces
+ if not next(net.list()) then
+ panic('not listening on any interface, exiting...')
+ end
+end
+-- Open cache if not set/disabled
+if not cache.current_size then
+ cache.size = 100 * MB
+end
+
+-- If no addresses for root servers are set, load them from the default file
+if require('ffi').C.kr_zonecut_is_empty(kres.context().root_hints) then
+ _hint_root_file()
+end
+
+if not trust_anchors.keysets['\0'] and trust_anchors.keyfile_default then
+ if io.open(trust_anchors.keyfile_default, 'r') then
+ trust_anchors.config(trust_anchors.keyfile_default, true)
+ else
+ panic("cannot open default trust anchor file:'%s'",
+ trust_anchors.keyfile_default
+ )
+ end
+end
diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua
new file mode 100644
index 0000000..eeb8ff7
--- /dev/null
+++ b/daemon/lua/kres-gen.lua
@@ -0,0 +1,430 @@
+local ffi = require('ffi')
+--[[ This file is generated by ./kres-gen.sh ]] ffi.cdef[[
+
+typedef struct knot_dump_style knot_dump_style_t;
+extern const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT;
+typedef void knot_db_t;
+struct kr_cdb_api {};
+struct lru {};
+
+typedef struct knot_mm {
+ void *ctx, *alloc, *free;
+} knot_mm_t;
+
+typedef void *(*map_alloc_f)(void *, size_t);
+typedef void (*map_free_f)(void *baton, void *ptr);
+typedef void (*trace_log_f) (const struct kr_query *, const char *, const char *);
+typedef void (*trace_callback_f)(struct kr_request *);
+typedef enum {KNOT_ANSWER, KNOT_AUTHORITY, KNOT_ADDITIONAL} knot_section_t;
+typedef struct {
+ uint16_t pos;
+ uint16_t flags;
+ uint16_t compress_ptr[16];
+} knot_rrinfo_t;
+typedef unsigned char knot_dname_t;
+typedef struct {
+ uint16_t len;
+ uint8_t data[];
+} knot_rdata_t;
+typedef struct {
+ uint16_t count;
+ knot_rdata_t *rdata;
+} knot_rdataset_t;
+typedef struct {
+ knot_dname_t *_owner;
+ uint32_t _ttl;
+ uint16_t type;
+ uint16_t rclass;
+ knot_rdataset_t rrs;
+ void *additional;
+} knot_rrset_t;
+typedef struct knot_pkt knot_pkt_t;
+typedef struct {
+ uint8_t *ptr[15];
+} knot_edns_options_t;
+typedef struct {
+ knot_pkt_t *pkt;
+ uint16_t pos;
+ uint16_t count;
+} knot_pktsection_t;
+struct knot_compr {
+ uint8_t *wire;
+ knot_rrinfo_t *rrinfo;
+ struct {
+ uint16_t pos;
+ uint8_t labels;
+ } suffix;
+};
+typedef struct knot_compr knot_compr_t;
+struct knot_pkt {
+ uint8_t *wire;
+ size_t size;
+ size_t max_size;
+ size_t parsed;
+ uint16_t reserved;
+ uint16_t qname_size;
+ uint16_t rrset_count;
+ uint16_t flags;
+ knot_rrset_t *opt_rr;
+ knot_rrset_t *tsig_rr;
+ knot_edns_options_t *edns_opts;
+ struct {
+ uint8_t *pos;
+ size_t len;
+ } tsig_wire;
+ knot_section_t current;
+ knot_pktsection_t sections[3];
+ size_t rrset_allocd;
+ knot_rrinfo_t *rr_info;
+ knot_rrset_t *rr;
+ knot_mm_t mm;
+ knot_compr_t compr;
+};
+typedef struct {
+ void *root;
+ struct knot_mm *pool;
+} map_t;
+struct kr_qflags {
+ _Bool NO_MINIMIZE : 1;
+ _Bool NO_THROTTLE : 1;
+ _Bool NO_IPV6 : 1;
+ _Bool NO_IPV4 : 1;
+ _Bool TCP : 1;
+ _Bool RESOLVED : 1;
+ _Bool AWAIT_IPV4 : 1;
+ _Bool AWAIT_IPV6 : 1;
+ _Bool AWAIT_CUT : 1;
+ _Bool SAFEMODE : 1;
+ _Bool CACHED : 1;
+ _Bool NO_CACHE : 1;
+ _Bool EXPIRING : 1;
+ _Bool ALLOW_LOCAL : 1;
+ _Bool DNSSEC_WANT : 1;
+ _Bool DNSSEC_BOGUS : 1;
+ _Bool DNSSEC_INSECURE : 1;
+ _Bool DNSSEC_CD : 1;
+ _Bool STUB : 1;
+ _Bool ALWAYS_CUT : 1;
+ _Bool DNSSEC_WEXPAND : 1;
+ _Bool PERMISSIVE : 1;
+ _Bool STRICT : 1;
+ _Bool BADCOOKIE_AGAIN : 1;
+ _Bool CNAME : 1;
+ _Bool REORDER_RR : 1;
+ _Bool TRACE : 1;
+ _Bool NO_0X20 : 1;
+ _Bool DNSSEC_NODS : 1;
+ _Bool DNSSEC_OPTOUT : 1;
+ _Bool NONAUTH : 1;
+ _Bool FORWARD : 1;
+ _Bool DNS64_MARK : 1;
+ _Bool CACHE_TRIED : 1;
+ _Bool NO_NS_FOUND : 1;
+};
+typedef struct {
+ knot_rrset_t **at;
+ size_t len;
+ size_t cap;
+} rr_array_t;
+struct ranked_rr_array_entry {
+ uint32_t qry_uid;
+ uint8_t rank;
+ uint8_t revalidation_cnt;
+ _Bool cached : 1;
+ _Bool yielded : 1;
+ _Bool to_wire : 1;
+ _Bool expiring : 1;
+ knot_rrset_t *rr;
+};
+typedef struct ranked_rr_array_entry ranked_rr_array_entry_t;
+typedef struct {
+ ranked_rr_array_entry_t **at;
+ size_t len;
+ size_t cap;
+} ranked_rr_array_t;
+typedef struct trie trie_t;
+struct kr_zonecut {
+ knot_dname_t *name;
+ knot_rrset_t *key;
+ knot_rrset_t *trust_anchor;
+ struct kr_zonecut *parent;
+ trie_t *nsset;
+ knot_mm_t *pool;
+};
+typedef struct {
+ struct kr_query **at;
+ size_t len;
+ size_t cap;
+} kr_qarray_t;
+struct kr_rplan {
+ kr_qarray_t pending;
+ kr_qarray_t resolved;
+ struct kr_request *request;
+ knot_mm_t *pool;
+ uint32_t next_uid;
+};
+struct kr_request_qsource_flags {
+ _Bool tcp : 1;
+ _Bool tls : 1;
+};
+struct kr_request {
+ struct kr_context *ctx;
+ knot_pkt_t *answer;
+ struct kr_query *current_query;
+ struct {
+ const struct sockaddr *addr;
+ const struct sockaddr *dst_addr;
+ const knot_pkt_t *packet;
+ struct kr_request_qsource_flags flags;
+ size_t size;
+ } qsource;
+ struct {
+ unsigned int rtt;
+ const struct sockaddr *addr;
+ } upstream;
+ struct kr_qflags options;
+ int state;
+ ranked_rr_array_t answ_selected;
+ ranked_rr_array_t auth_selected;
+ ranked_rr_array_t add_selected;
+ rr_array_t additional;
+ _Bool answ_validated;
+ _Bool auth_validated;
+ uint8_t rank;
+ struct kr_rplan rplan;
+ trace_log_f trace_log;
+ trace_callback_f trace_finish;
+ int vars_ref;
+ knot_mm_t pool;
+ unsigned int uid;
+ void *daemon_context;
+};
+enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_TRY, KR_RANK_INDET = 4, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
+struct kr_cache {
+ knot_db_t *db;
+ const struct kr_cdb_api *api;
+ struct {
+ uint32_t hit;
+ uint32_t miss;
+ uint32_t insert;
+ uint32_t delete;
+ } stats;
+ uint32_t ttl_min;
+ uint32_t ttl_max;
+ struct timeval checkpoint_walltime;
+ uint64_t checkpoint_monotime;
+};
+
+typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
+ const struct kr_query *qry);
+
+void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
+ uint16_t type, uint16_t rclass, uint32_t ttl);
+struct kr_nsrep {
+ unsigned int score;
+ unsigned int reputation;
+ const knot_dname_t *name;
+ struct kr_context *ctx;
+ /* beware: hidden stub, to avoid hardcoding sockaddr lengths */
+};
+struct kr_query {
+ struct kr_query *parent;
+ knot_dname_t *sname;
+ uint16_t stype;
+ uint16_t sclass;
+ uint16_t id;
+ struct kr_qflags flags;
+ struct kr_qflags forward_flags;
+ uint32_t secret;
+ uint16_t fails;
+ uint16_t reorder;
+ uint64_t creation_time_mono;
+ uint64_t timestamp_mono;
+ struct timeval timestamp;
+ struct kr_zonecut zone_cut;
+ struct kr_layer_pickle *deferred;
+ uint32_t uid;
+ struct kr_query *cname_parent;
+ struct kr_request *request;
+ kr_stale_cb stale_cb;
+ struct kr_nsrep ns;
+};
+struct kr_context {
+ struct kr_qflags options;
+ knot_rrset_t *opt_rr;
+ map_t trust_anchors;
+ map_t negative_anchors;
+ struct kr_zonecut root_hints;
+ struct kr_cache cache;
+ char _stub[];
+};
+const char *knot_strerror(int);
+knot_dname_t *knot_dname_copy(const knot_dname_t *, knot_mm_t *);
+knot_dname_t *knot_dname_from_str(uint8_t *, const char *, size_t);
+int knot_dname_in_bailiwick(const knot_dname_t *, const knot_dname_t *);
+_Bool knot_dname_is_equal(const knot_dname_t *, const knot_dname_t *);
+size_t knot_dname_labels(const uint8_t *, const uint8_t *);
+size_t knot_dname_size(const knot_dname_t *);
+void knot_dname_to_lower(knot_dname_t *);
+char *knot_dname_to_str(char *, const knot_dname_t *, size_t);
+knot_rdata_t *knot_rdataset_at(const knot_rdataset_t *, uint16_t);
+int knot_rdataset_merge(knot_rdataset_t *, const knot_rdataset_t *, knot_mm_t *);
+int knot_rrset_add_rdata(knot_rrset_t *, const uint8_t *, uint16_t, knot_mm_t *);
+int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *);
+int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *);
+size_t knot_rrset_size(const knot_rrset_t *);
+int knot_pkt_begin(knot_pkt_t *, knot_section_t);
+int knot_pkt_put_question(knot_pkt_t *, const knot_dname_t *, uint16_t, uint16_t);
+int knot_pkt_put_rotate(knot_pkt_t *, uint16_t, const knot_rrset_t *, uint16_t, uint16_t);
+knot_pkt_t *knot_pkt_new(void *, uint16_t, knot_mm_t *);
+void knot_pkt_free(knot_pkt_t *);
+int knot_pkt_parse(knot_pkt_t *, unsigned int);
+struct kr_rplan *kr_resolve_plan(struct kr_request *);
+knot_mm_t *kr_resolve_pool(struct kr_request *);
+struct kr_query *kr_rplan_push(struct kr_rplan *, struct kr_query *, const knot_dname_t *, uint16_t, uint16_t);
+int kr_rplan_pop(struct kr_rplan *, struct kr_query *);
+struct kr_query *kr_rplan_resolved(struct kr_rplan *);
+struct kr_query *kr_rplan_last(struct kr_rplan *);
+int kr_nsrep_set(struct kr_query *, size_t, const struct sockaddr *);
+int kr_make_query(struct kr_query *, knot_pkt_t *);
+void kr_pkt_make_auth_header(knot_pkt_t *);
+int kr_pkt_put(knot_pkt_t *, const knot_dname_t *, uint32_t, uint16_t, uint16_t, const uint8_t *, uint16_t);
+int kr_pkt_recycle(knot_pkt_t *);
+int kr_pkt_clear_payload(knot_pkt_t *);
+uint16_t kr_pkt_qclass(const knot_pkt_t *);
+uint16_t kr_pkt_qtype(const knot_pkt_t *);
+void kr_rnd_buffered(void *, unsigned int);
+uint32_t kr_rrsig_sig_inception(const knot_rdata_t *);
+uint32_t kr_rrsig_sig_expiration(const knot_rdata_t *);
+uint16_t kr_rrsig_type_covered(const knot_rdata_t *);
+const char *kr_inaddr(const struct sockaddr *);
+int kr_inaddr_family(const struct sockaddr *);
+int kr_inaddr_len(const struct sockaddr *);
+int kr_inaddr_str(const struct sockaddr *, char *, size_t *);
+int kr_sockaddr_len(const struct sockaddr *);
+uint16_t kr_inaddr_port(const struct sockaddr *);
+int kr_straddr_family(const char *);
+int kr_straddr_subnet(void *, const char *);
+int kr_bitcmp(const char *, const char *, int);
+int kr_family_len(int);
+struct sockaddr *kr_straddr_socket(const char *, int);
+int kr_ranked_rrarray_add(ranked_rr_array_t *, const knot_rrset_t *, uint8_t, _Bool, uint32_t, knot_mm_t *);
+void kr_qflags_set(struct kr_qflags *, struct kr_qflags);
+void kr_qflags_clear(struct kr_qflags *, struct kr_qflags);
+int kr_zonecut_add(struct kr_zonecut *, const knot_dname_t *, const void *, int);
+_Bool kr_zonecut_is_empty(struct kr_zonecut *);
+void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
+uint64_t kr_now();
+const char *kr_strptime_diff(const char *, const char *, const char *, double *);
+void lru_free_items_impl(struct lru *);
+struct lru *lru_create_impl(unsigned int, knot_mm_t *, knot_mm_t *);
+void *lru_get_impl(struct lru *, const char *, unsigned int, unsigned int, _Bool, _Bool *);
+void *mm_realloc(knot_mm_t *, void *, size_t, size_t);
+knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
+int kr_ta_add(map_t *, const knot_dname_t *, uint16_t, uint32_t, const uint8_t *, uint16_t);
+int kr_ta_del(map_t *, const knot_dname_t *);
+void kr_ta_clear(map_t *);
+_Bool kr_dnssec_key_ksk(const uint8_t *);
+_Bool kr_dnssec_key_revoked(const uint8_t *);
+int kr_dnssec_key_tag(uint16_t, const uint8_t *, size_t);
+int kr_dnssec_key_match(const uint8_t *, size_t, const uint8_t *, size_t);
+int kr_cache_closest_apex(struct kr_cache *, const knot_dname_t *, _Bool, knot_dname_t **);
+int kr_cache_insert_rr(struct kr_cache *, const knot_rrset_t *, const knot_rrset_t *, uint8_t, uint32_t);
+int kr_cache_remove(struct kr_cache *, const knot_dname_t *, uint16_t);
+int kr_cache_remove_subtree(struct kr_cache *, const knot_dname_t *, _Bool, int);
+int kr_cache_sync(struct kr_cache *);
+typedef struct {
+ uint8_t bitmap[32];
+ uint8_t length;
+} zs_win_t;
+typedef struct {
+ uint8_t excl_flag;
+ uint16_t addr_family;
+ uint8_t prefix_length;
+} zs_apl_t;
+typedef struct {
+ uint32_t d1;
+ uint32_t d2;
+ uint32_t m1;
+ uint32_t m2;
+ uint32_t s1;
+ uint32_t s2;
+ uint32_t alt;
+ uint64_t siz;
+ uint64_t hp;
+ uint64_t vp;
+ int8_t lat_sign;
+ int8_t long_sign;
+ int8_t alt_sign;
+} zs_loc_t;
+typedef enum {ZS_STATE_NONE, ZS_STATE_DATA, ZS_STATE_ERROR, ZS_STATE_INCLUDE, ZS_STATE_EOF, ZS_STATE_STOP} zs_state_t;
+typedef struct zs_scanner zs_scanner_t;
+struct zs_scanner {
+ int cs;
+ int top;
+ int stack[16];
+ _Bool multiline;
+ uint64_t number64;
+ uint64_t number64_tmp;
+ uint32_t decimals;
+ uint32_t decimal_counter;
+ uint32_t item_length;
+ uint32_t item_length_position;
+ uint8_t *item_length_location;
+ uint32_t buffer_length;
+ uint8_t buffer[65535];
+ char include_filename[65535];
+ char *path;
+ zs_win_t windows[256];
+ int16_t last_window;
+ zs_apl_t apl;
+ zs_loc_t loc;
+ uint8_t addr[16];
+ _Bool long_string;
+ uint8_t *dname;
+ uint32_t *dname_length;
+ uint32_t dname_tmp_length;
+ uint32_t r_data_tail;
+ uint32_t zone_origin_length;
+ uint8_t zone_origin[318];
+ uint16_t default_class;
+ uint32_t default_ttl;
+ zs_state_t state;
+ struct {
+ _Bool automatic;
+ void (*record)(zs_scanner_t *);
+ void (*error)(zs_scanner_t *);
+ void *data;
+ } process;
+ struct {
+ const char *start;
+ const char *current;
+ const char *end;
+ _Bool eof;
+ _Bool mmaped;
+ } input;
+ struct {
+ char *name;
+ int descriptor;
+ } file;
+ struct {
+ int code;
+ uint64_t counter;
+ _Bool fatal;
+ } error;
+ uint64_t line_counter;
+ uint32_t r_owner_length;
+ uint8_t r_owner[318];
+ uint16_t r_class;
+ uint32_t r_ttl;
+ uint16_t r_type;
+ uint32_t r_data_length;
+ uint8_t r_data[65535];
+};
+void zs_deinit(zs_scanner_t *);
+int zs_init(zs_scanner_t *, const char *, const uint16_t, const uint32_t);
+int zs_parse_record(zs_scanner_t *);
+int zs_set_input_file(zs_scanner_t *, const char *);
+int zs_set_input_string(zs_scanner_t *, const char *, size_t);
+const char *zs_strerror(const int);
+]]
diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh
new file mode 100755
index 0000000..538fe23
--- /dev/null
+++ b/daemon/lua/kres-gen.sh
@@ -0,0 +1,216 @@
+#!/bin/bash
+set -o pipefail -o errexit
+
+### Dev's guide
+#
+# C declarations for lua are (mostly) generated to simplify maintenance.
+# (Avoid typos, accidental mismatches, etc.)
+#
+# To regenerate the C definitions for lua:
+# - you need to have debugging symbols for knot-dns and knot-resolver;
+# you get those by compiling with -g; for knot-dns it might be enough
+# to just install it with debugging symbols included (in your distro way)
+# - remove file ./kres-gen.lua and run make as usual
+# - the knot-dns libraries are found via pkg-config
+# - you also need gdb on $PATH
+
+
+printf -- "local ffi = require('ffi')\n"
+printf -- "--[[ This file is generated by ./kres-gen.sh ]] ffi.cdef[[\n"
+
+## Various types (mainly), from libknot and libkres
+
+printf "
+typedef struct knot_dump_style knot_dump_style_t;
+extern const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT;
+typedef void knot_db_t;
+struct kr_cdb_api {};
+struct lru {};
+"
+
+# The generator doesn't work well with typedefs of functions.
+printf "
+typedef struct knot_mm {
+ void *ctx, *alloc, *free;
+} knot_mm_t;
+
+typedef void *(*map_alloc_f)(void *, size_t);
+typedef void (*map_free_f)(void *baton, void *ptr);
+typedef void (*trace_log_f) (const struct kr_query *, const char *, const char *);
+typedef void (*trace_callback_f)(struct kr_request *);
+"
+
+./scripts/gen-cdefs.sh libkres types <<-EOF
+ knot_section_t
+ knot_rrinfo_t
+ knot_dname_t
+ knot_rdata_t
+ knot_rdataset_t
+EOF
+
+genResType() {
+ echo "$1" | ./scripts/gen-cdefs.sh libkres types
+}
+
+# No simple way to fixup this rename in ./kres.lua AFAIK.
+genResType "knot_rrset_t" | sed 's/\<owner\>/_owner/; s/\<ttl\>/_ttl/'
+
+./scripts/gen-cdefs.sh libkres types <<-EOF
+ knot_pkt_t
+ knot_edns_options_t
+ knot_pktsection_t
+ struct knot_compr
+ knot_compr_t
+ struct knot_pkt
+ # generics
+ map_t
+ # libkres
+ struct kr_qflags
+ rr_array_t
+ struct ranked_rr_array_entry
+ ranked_rr_array_entry_t
+ ranked_rr_array_t
+ trie_t
+ struct kr_zonecut
+ kr_qarray_t
+ struct kr_rplan
+ struct kr_request_qsource_flags
+ struct kr_request
+ enum kr_rank
+ struct kr_cache
+EOF
+
+printf "
+typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
+ const struct kr_query *qry);
+
+void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
+ uint16_t type, uint16_t rclass, uint32_t ttl);
+"
+
+## Some definitions would need too many deps, so shorten them.
+
+genResType "struct kr_nsrep" | sed '/union/,$ d'
+printf "\t/* beware: hidden stub, to avoid hardcoding sockaddr lengths */\n};\n"
+
+genResType "struct kr_query"
+
+genResType "struct kr_context" | sed '/kr_nsrep_rtt_lru_t/,$ d'
+printf "\tchar _stub[];\n};\n"
+
+## libknot API
+./scripts/gen-cdefs.sh libknot functions <<-EOF
+# Utils
+ knot_strerror
+# Domain names
+ knot_dname_copy
+ knot_dname_from_str
+ knot_dname_in_bailiwick
+ knot_dname_is_equal
+ knot_dname_labels
+ knot_dname_size
+ knot_dname_to_lower
+ knot_dname_to_str
+# Resource records
+ knot_rdataset_at
+ knot_rdataset_merge
+ knot_rrset_add_rdata
+ knot_rrset_txt_dump
+ knot_rrset_txt_dump_data
+ knot_rrset_size
+# Packet
+ knot_pkt_begin
+ knot_pkt_put_question
+ knot_pkt_put_rotate
+ knot_pkt_new
+ knot_pkt_free
+ knot_pkt_parse
+EOF
+
+## libkres API
+./scripts/gen-cdefs.sh libkres functions <<-EOF
+# Resolution request
+ kr_resolve_plan
+ kr_resolve_pool
+# Resolution plan
+ kr_rplan_push
+ kr_rplan_pop
+ kr_rplan_resolved
+ kr_rplan_last
+# Nameservers
+ kr_nsrep_set
+# Utils
+ kr_make_query
+ kr_pkt_make_auth_header
+ kr_pkt_put
+ kr_pkt_recycle
+ kr_pkt_clear_payload
+ kr_pkt_qclass
+ kr_pkt_qtype
+ kr_rnd_buffered
+ kr_rrsig_sig_inception
+ kr_rrsig_sig_expiration
+ kr_rrsig_type_covered
+ kr_inaddr
+ kr_inaddr_family
+ kr_inaddr_len
+ kr_inaddr_str
+ kr_sockaddr_len
+ kr_inaddr_port
+ kr_straddr_family
+ kr_straddr_subnet
+ kr_bitcmp
+ kr_family_len
+ kr_straddr_socket
+ kr_ranked_rrarray_add
+ kr_qflags_set
+ kr_qflags_clear
+ kr_zonecut_add
+ kr_zonecut_is_empty
+ kr_zonecut_set
+ kr_now
+ kr_strptime_diff
+ lru_free_items_impl
+ lru_create_impl
+ lru_get_impl
+ mm_realloc
+# Trust anchors
+ kr_ta_get
+ kr_ta_add
+ kr_ta_del
+ kr_ta_clear
+# DNSSEC
+ kr_dnssec_key_ksk
+ kr_dnssec_key_revoked
+ kr_dnssec_key_tag
+ kr_dnssec_key_match
+# Cache
+ kr_cache_closest_apex
+ kr_cache_insert_rr
+ kr_cache_remove
+ kr_cache_remove_subtree
+ kr_cache_sync
+EOF
+
+
+## libzscanner API for ./zonefile.lua
+./scripts/gen-cdefs.sh libzscanner types <<-EOF
+ zs_win_t
+ zs_apl_t
+ zs_loc_t
+ zs_state_t
+ zs_scanner_t
+ struct zs_scanner
+EOF
+./scripts/gen-cdefs.sh libzscanner functions <<-EOF
+ zs_deinit
+ zs_init
+ zs_parse_record
+ zs_set_input_file
+ zs_set_input_string
+ zs_strerror
+EOF
+
+printf "]]\n"
+
+exit 0
diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua
new file mode 100644
index 0000000..8cb0046
--- /dev/null
+++ b/daemon/lua/kres.lua
@@ -0,0 +1,952 @@
+-- LuaJIT ffi bindings for libkres, a DNS resolver library.
+-- @note Since it's statically compiled, it expects to find the symbols in the C namespace.
+
+local kres -- the module
+
+local ffi = require('ffi')
+local bit = require('bit')
+local bor = bit.bor
+local band = bit.band
+local C = ffi.C
+local knot = ffi.load(libknot_SONAME)
+
+-- Inverse table
+local function itable(t, tolower)
+ local it = {}
+ for k,v in pairs(t) do it[v] = tolower and string.lower(k) or k end
+ return it
+end
+
+-- Byte order conversions
+local function htonl(x) return x end
+local htons = htonl
+if ffi.abi('le') then
+ htonl = bit.bswap
+ function htons(x) return bit.rshift(htonl(x), 16) end
+end
+
+-- Basic types
+local u16_p = ffi.typeof('uint16_t *')
+
+-- Various declarations that are very stable.
+ffi.cdef[[
+/*
+ * Data structures
+ */
+
+/* stdlib */
+typedef long time_t;
+struct timeval {
+ time_t tv_sec;
+ time_t tv_usec;
+};
+struct sockaddr {
+ uint16_t sa_family;
+ uint8_t _stub[]; /* Do not touch */
+};
+struct knot_error {
+ int code;
+};
+
+/*
+ * libc APIs
+ */
+void * malloc(size_t size);
+void free(void *ptr);
+int inet_pton(int af, const char *src, void *dst);
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+]]
+
+require('kres-gen')
+
+-- Error code representation
+local knot_error_t = ffi.typeof('struct knot_error')
+ffi.metatype(knot_error_t, {
+ -- Convert libknot error strings
+ __tostring = function(self)
+ return ffi.string(knot.knot_strerror(self.code))
+ end,
+});
+
+-- Constant tables
+local const_class = {
+ IN = 1,
+ CH = 3,
+ NONE = 254,
+ ANY = 255,
+}
+local const_type = {
+ A = 1,
+ NS = 2,
+ MD = 3,
+ MF = 4,
+ CNAME = 5,
+ SOA = 6,
+ MB = 7,
+ MG = 8,
+ MR = 9,
+ NULL = 10,
+ WKS = 11,
+ PTR = 12,
+ HINFO = 13,
+ MINFO = 14,
+ MX = 15,
+ TXT = 16,
+ RP = 17,
+ AFSDB = 18,
+ X25 = 19,
+ ISDN = 20,
+ RT = 21,
+ NSAP = 22,
+ ['NSAP-PTR'] = 23,
+ SIG = 24,
+ KEY = 25,
+ PX = 26,
+ GPOS = 27,
+ AAAA = 28,
+ LOC = 29,
+ NXT = 30,
+ EID = 31,
+ NIMLOC = 32,
+ SRV = 33,
+ ATMA = 34,
+ NAPTR = 35,
+ KX = 36,
+ CERT = 37,
+ A6 = 38,
+ DNAME = 39,
+ SINK = 40,
+ OPT = 41,
+ APL = 42,
+ DS = 43,
+ SSHFP = 44,
+ IPSECKEY = 45,
+ RRSIG = 46,
+ NSEC = 47,
+ DNSKEY = 48,
+ DHCID = 49,
+ NSEC3 = 50,
+ NSEC3PARAM = 51,
+ TLSA = 52,
+ SMIMEA = 53,
+ HIP = 55,
+ NINFO = 56,
+ RKEY = 57,
+ TALINK = 58,
+ CDS = 59,
+ CDNSKEY = 60,
+ OPENPGPKEY = 61,
+ CSYNC = 62,
+ SPF = 99,
+ UINFO = 100,
+ UID = 101,
+ GID = 102,
+ UNSPEC = 103,
+ NID = 104,
+ L32 = 105,
+ L64 = 106,
+ LP = 107,
+ EUI48 = 108,
+ EUI64 = 109,
+ TKEY = 249,
+ TSIG = 250,
+ IXFR = 251,
+ AXFR = 252,
+ MAILB = 253,
+ MAILA = 254,
+ ANY = 255,
+ URI = 256,
+ CAA = 257,
+ AVC = 258,
+ DOA = 259,
+ TA = 32768,
+ DLV = 32769,
+}
+local const_section = {
+ ANSWER = 0,
+ AUTHORITY = 1,
+ ADDITIONAL = 2,
+}
+local const_opcode = {
+ QUERY = 0,
+ IQUERY = 1,
+ STATUS = 2,
+ NOTIFY = 4,
+ UPDATE = 5,
+}
+local const_rcode = {
+ NOERROR = 0,
+ FORMERR = 1,
+ SERVFAIL = 2,
+ NXDOMAIN = 3,
+ NOTIMPL = 4,
+ REFUSED = 5,
+ YXDOMAIN = 6,
+ YXRRSET = 7,
+ NXRRSET = 8,
+ NOTAUTH = 9,
+ NOTZONE = 10,
+ BADVERS = 16,
+ BADCOOKIE = 23,
+}
+-- This corresponds to `enum kr_rank`, it's not possible to do this without introspection unfortunately
+local const_rank = {
+ INITIAL = 0,
+ OMIT = 1,
+ TRY = 2,
+ INDET = 4,
+ BOGUS = 5,
+ MISMATCH = 6,
+ MISSING = 7,
+ INSECURE = 8,
+ AUTH = 16,
+ SECURE = 32
+}
+
+-- Constant tables
+local const_class_str = itable(const_class)
+local const_type_str = itable(const_type)
+local const_rcode_str = itable(const_rcode)
+local const_opcode_str = itable(const_opcode)
+local const_section_str = itable(const_section)
+local const_rank_str = itable(const_rank)
+
+-- Metatype for RR types to allow anonymous types
+setmetatable(const_type, {
+ __index = function (t, k)
+ local v = rawget(t, k)
+ if v then return v end
+ -- Allow TYPE%d notation
+ if string.find(k, 'TYPE', 1, true) then
+ return tonumber(k:sub(5))
+ end
+ -- Unknown type
+ return
+ end
+})
+
+-- Metatype for RR types to allow anonymous string types
+setmetatable(const_type_str, {
+ __index = function (t, k)
+ local v = rawget(t, k)
+ if v then return v end
+ return string.format('TYPE%d', k)
+ end
+})
+
+-- Metatype for timeval
+local timeval_t = ffi.typeof('struct timeval')
+
+-- Metatype for sockaddr
+local addr_buf = ffi.new('char[16]')
+local str_addr_buf = ffi.new('char[46 + 1 + 6 + 1]') -- IPv6 + #port + \0
+local str_addr_buf_len = ffi.sizeof(str_addr_buf)
+local sockaddr_t = ffi.typeof('struct sockaddr')
+ffi.metatype( sockaddr_t, {
+ __index = {
+ len = function(sa) return C.kr_inaddr_len(sa) end,
+ ip = function (sa) return C.kr_inaddr(sa) end,
+ family = function (sa) return C.kr_inaddr_family(sa) end,
+ port = function (sa) return C.kr_inaddr_port(sa) end,
+ },
+ __tostring = function(sa)
+ assert(ffi.istype(sockaddr_t, sa))
+ local len = ffi.new('size_t[1]', str_addr_buf_len)
+ local ret = C.kr_inaddr_str(sa, str_addr_buf, len)
+ if ret ~= 0 then
+ error('kr_inaddr_str failed: ' .. tostring(ret))
+ end
+ return ffi.string(str_addr_buf)
+ end,
+
+})
+
+-- Parametrized LRU table
+local typed_lru_t = 'struct { $ value_type[1]; struct lru * lru; }'
+
+-- Metatype for LRU
+local lru_metatype = {
+ -- Create a new LRU with given value type
+ -- By default the LRU will have a capacity of 65536 elements
+ -- Note: At the point the parametrized type must be finalized
+ __new = function (ct, max_slots)
+ -- {0} will make sure that the value is coercible to a number
+ local o = ffi.new(ct, {0}, C.lru_create_impl(max_slots or 65536, nil, nil))
+ if o.lru == nil then
+ return
+ end
+ return o
+ end,
+ -- Destructor to clean allocated memory
+ __gc = function (self)
+ assert(self.lru ~= nil)
+ C.lru_free_items_impl(self.lru)
+ C.free(self.lru)
+ self.lru = nil
+ end,
+ __index = {
+ -- Look up key and return reference to current
+ -- Note: The key will be inserted if it doesn't exist
+ get_ref = function (self, key, key_len, allow_insert)
+ local insert = allow_insert and true or false
+ local ptr = C.lru_get_impl(self.lru, key, key_len or #key, ffi.sizeof(self.value_type[0]), insert, nil)
+ if ptr ~= nil then
+ return ffi.cast(self.value_type, ptr)
+ end
+ end,
+ -- Look up key and return current value
+ get = function (self, key, key_len)
+ local ref = self:get_ref(key, key_len, false)
+ if ref then
+ return ref[0]
+ end
+ end,
+ -- Set value for key to given value
+ set = function (self, key, value, key_len)
+ local ref = self:get_ref(key, key_len, true)
+ if ref then
+ ref[0] = value
+ return true
+ end
+ end,
+ },
+}
+
+-- Pretty print for domain name
+local function dname2str(dname)
+ if dname == nil then return end
+ local text_name = ffi.gc(C.knot_dname_to_str(nil, dname, 0), C.free)
+ if text_name ~= nil then
+ return ffi.string(text_name)
+ end
+end
+
+-- Convert dname pointer to wireformat string
+local function dname2wire(name)
+ if name == nil then return nil end
+ return ffi.string(name, knot.knot_dname_size(name))
+end
+
+-- RR sets created in Lua must have a destructor to release allocated memory
+local function rrset_free(rr)
+ if rr._owner ~= nil then ffi.C.free(rr._owner) end
+ if rr:rdcount() > 0 then ffi.C.free(rr.rrs.rdata) end
+end
+
+-- Metatype for RR set. Beware, the indexing is 0-based (rdata, get, tostring).
+local rrset_buflen = (64 + 1) * 1024
+local rrset_buf = ffi.new('char[?]', rrset_buflen)
+local knot_rrset_pt = ffi.typeof('knot_rrset_t *')
+local knot_rrset_t = ffi.typeof('knot_rrset_t')
+ffi.metatype( knot_rrset_t, {
+ -- Create a new empty RR set object with an allocated owner and a destructor
+ __new = function (ct, owner, rrtype, rrclass, ttl)
+ local rr = ffi.new(ct)
+ C.kr_rrset_init(rr,
+ owner and knot.knot_dname_copy(owner, nil),
+ rrtype or 0,
+ rrclass or const_class.IN,
+ ttl or 0)
+ return ffi.gc(rr, rrset_free)
+ end,
+ -- BEWARE: `owner` and `rdata` are typed as a plain lua strings
+ -- and not the real types they represent.
+ __tostring = function(rr)
+ assert(ffi.istype(knot_rrset_t, rr))
+ return rr:txt_dump()
+ end,
+ __index = {
+ owner = function(rr)
+ assert(ffi.istype(knot_rrset_t, rr))
+ return dname2wire(rr._owner)
+ end,
+ ttl = function(rr)
+ assert(ffi.istype(knot_rrset_t, rr))
+ return tonumber(rr._ttl)
+ end,
+ class = function(rr, val)
+ assert(ffi.istype(knot_rrset_t, rr))
+ if val then
+ rr.rclass = val
+ end
+ return tonumber(rr.rclass)
+ end,
+ rdata_pt = function(rr, i)
+ assert(ffi.istype(knot_rrset_t, rr) and i >= 0 and i < rr:rdcount())
+ return knot.knot_rdataset_at(rr.rrs, i)
+ end,
+ rdata = function(rr, i)
+ assert(ffi.istype(knot_rrset_t, rr))
+ local rd = rr:rdata_pt(i)
+ return ffi.string(rd.data, rd.len)
+ end,
+ get = function(rr, i)
+ assert(ffi.istype(knot_rrset_t, rr) and i >= 0 and i < rr:rdcount())
+ return {owner = rr:owner(),
+ ttl = rr:ttl(),
+ class = tonumber(rr.rclass),
+ type = tonumber(rr.type),
+ rdata = rr:rdata(i)}
+ end,
+ tostring = function(rr, i)
+ assert(ffi.istype(knot_rrset_t, rr)
+ and (i == nil or (i >= 0 and i < rr:rdcount())) )
+ if rr:rdcount() > 0 then
+ local ret
+ if i ~= nil then
+ ret = knot.knot_rrset_txt_dump_data(rr, i, rrset_buf, rrset_buflen, knot.KNOT_DUMP_STYLE_DEFAULT)
+ else
+ ret = -1
+ end
+ return ret >= 0 and ffi.string(rrset_buf)
+ end
+ end,
+
+ -- Dump the rrset in presentation format (dig-like).
+ txt_dump = function(rr, style)
+ assert(ffi.istype(knot_rrset_t, rr))
+ local bufsize = 1024
+ local dump = ffi.new('char *[1]', C.malloc(bufsize))
+ -- ^ one pointer to a string
+ local size = ffi.new('size_t[1]', { bufsize }) -- one size_t = bufsize
+
+ local ret = knot.knot_rrset_txt_dump(rr, dump, size,
+ style or knot.KNOT_DUMP_STYLE_DEFAULT)
+ local result = nil
+ if ret >= 0 then
+ result = ffi.string(dump[0], ret)
+ end
+ C.free(dump[0])
+ return result
+ end,
+ -- Return RDATA count for this RR set
+ rdcount = function(rr)
+ assert(ffi.istype(knot_rrset_t, rr))
+ return tonumber(rr.rrs.count)
+ end,
+ -- Add binary RDATA to the RR set
+ add_rdata = function (rr, rdata, rdlen, no_ttl)
+ assert(ffi.istype(knot_rrset_t, rr))
+ assert(no_ttl == nil, 'add_rdata() can not accept TTL anymore')
+ local ret = knot.knot_rrset_add_rdata(rr, rdata, tonumber(rdlen), nil)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ -- Merge data from another RR set into the current one
+ merge_rdata = function (rr, source)
+ assert(ffi.istype(knot_rrset_t, rr))
+ assert(ffi.istype(knot_rrset_t, source))
+ local ret = knot.knot_rdataset_merge(rr.rrs, source.rrs, nil)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ -- Return type covered by this RRSIG
+ type_covered = function(rr, i)
+ i = i or 0
+ assert(ffi.istype(knot_rrset_t, rr) and i >= 0 and i < rr:rdcount())
+ if rr.type ~= const_type.RRSIG then return end
+ return tonumber(C.kr_rrsig_type_covered(knot.knot_rdataset_at(rr.rrs, i)))
+ end,
+ -- Check whether a RRSIG is covering current RR set
+ is_covered_by = function(rr, rrsig)
+ assert(ffi.istype(knot_rrset_t, rr))
+ assert(ffi.istype(knot_rrset_t, rrsig))
+ assert(rrsig.type == const_type.RRSIG)
+ return (rr.type == rrsig:type_covered() and rr:owner() == rrsig:owner())
+ end,
+ -- Return RR set wire size
+ wire_size = function(rr)
+ assert(ffi.istype(knot_rrset_t, rr))
+ return tonumber(knot.knot_rrset_size(rr))
+ end,
+ },
+})
+
+-- Destructor for packet accepts pointer to pointer
+local knot_pkt_t = ffi.typeof('knot_pkt_t')
+
+-- Helpers for reading/writing 16-bit numbers from packet wire
+local function pkt_u16(pkt, off, val)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ptr = ffi.cast(u16_p, pkt.wire + off)
+ if val ~= nil then ptr[0] = htons(val) end
+ return (htons(ptr[0]))
+end
+
+-- Helpers for reading/writing message header flags
+local function pkt_bit(pkt, byteoff, bitmask, val)
+ -- If the value argument is passed, set/clear the desired bit
+ if val ~= nil then
+ if val then pkt.wire[byteoff] = bit.bor(pkt.wire[byteoff], bitmask)
+ else pkt.wire[byteoff] = bit.band(pkt.wire[byteoff], bit.bnot(bitmask)) end
+ return true
+ end
+ return (bit.band(pkt.wire[byteoff], bitmask) ~= 0)
+end
+
+local function knot_pkt_rr(section, i)
+ assert(section and ffi.istype('knot_pktsection_t', section)
+ and i >= 0 and i < section.count)
+ local ret = section.pkt.rr + section.pos + i
+ assert(ffi.istype(knot_rrset_pt, ret))
+ return ret
+end
+
+-- Helpers for converting packet to text
+local function section_tostring(pkt, section_id)
+ local data = {}
+ local section = pkt.sections + section_id
+ if section.count > 0 then
+ table.insert(data, string.format('\n;; %s\n', const_section_str[section_id]))
+ for j = 0, section.count - 1 do
+ local rrset = knot_pkt_rr(section, j)
+ local rrtype = rrset.type
+ if rrtype ~= const_type.OPT and rrtype ~= const_type.TSIG then
+ table.insert(data, rrset:txt_dump())
+ end
+ end
+ end
+ return table.concat(data, '')
+end
+
+local function packet_tostring(pkt)
+ local hdr = string.format(';; ->>HEADER<<- opcode: %s; status: %s; id: %d\n',
+ const_opcode_str[pkt:opcode()], const_rcode_str[pkt:rcode()], pkt:id())
+ local flags = {}
+ for _,v in ipairs({'rd', 'tc', 'aa', 'qr', 'cd', 'ad', 'ra'}) do
+ if(pkt[v](pkt)) then table.insert(flags, v) end
+ end
+ local info = string.format(';; Flags: %s; QUERY: %d; ANSWER: %d; AUTHORITY: %d; ADDITIONAL: %d\n',
+ table.concat(flags, ' '), pkt:qdcount(), pkt:ancount(), pkt:nscount(), pkt:arcount())
+ local data = '\n'
+ if pkt.opt_rr ~= nil then
+ data = data..string.format(';; OPT PSEUDOSECTION:\n%s', pkt.opt_rr:tostring())
+ end
+ if pkt.tsig_rr ~= nil then
+ data = data..string.format(';; TSIG PSEUDOSECTION:\n%s', pkt.tsig_rr:tostring())
+ end
+ -- Zone transfer answers may omit question
+ if pkt:qdcount() > 0 then
+ data = data..string.format(';; QUESTION\n;; %s\t%s\t%s\n',
+ dname2str(pkt:qname()), const_type_str[pkt:qtype()], const_class_str[pkt:qclass()])
+ end
+ local data_sec = {}
+ for i = const_section.ANSWER, const_section.ADDITIONAL do
+ table.insert(data_sec, section_tostring(pkt, i))
+ end
+ return hdr..info..data..table.concat(data_sec, '')
+end
+
+-- Metatype for packet
+ffi.metatype( knot_pkt_t, {
+ __new = function (_, size, wire)
+ if size < 12 or size > 65535 then
+ error('packet size must be <12, 65535>')
+ end
+
+ local pkt = knot.knot_pkt_new(nil, size, nil)
+ if pkt == nil then
+ error(string.format('failed to allocate a packet of size %d', size))
+ end
+ if wire == nil then
+ C.kr_rnd_buffered(pkt.wire, 2) -- randomize the query ID
+ else
+ assert(size <= #wire)
+ ffi.copy(pkt.wire, wire, size)
+ pkt.size = size
+ pkt.parsed = 0
+ end
+
+ return ffi.gc(pkt[0], knot.knot_pkt_free)
+ end,
+ __tostring = function(pkt)
+ return pkt:tostring()
+ end,
+ __len = function(pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ return tonumber(pkt.size)
+ end,
+ __ipairs = function(self)
+ return ipairs(self:section(const_section.ANSWER))
+ end,
+ __index = {
+ -- Header
+ id = function(pkt, val) return pkt_u16(pkt, 0, val) end,
+ qdcount = function(pkt, val) return pkt_u16(pkt, 4, val) end,
+ ancount = function(pkt, val) return pkt_u16(pkt, 6, val) end,
+ nscount = function(pkt, val) return pkt_u16(pkt, 8, val) end,
+ arcount = function(pkt, val) return pkt_u16(pkt, 10, val) end,
+ opcode = function (pkt, val)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ pkt.wire[2] = (val) and bit.bor(bit.band(pkt.wire[2], 0x78), 8 * val) or pkt.wire[2]
+ return (bit.band(pkt.wire[2], 0x78) / 8)
+ end,
+ rcode = function (pkt, val)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ pkt.wire[3] = (val) and bor(band(pkt.wire[3], 0xf0), val) or pkt.wire[3]
+ return band(pkt.wire[3], 0x0f)
+ end,
+ rd = function (pkt, val) return pkt_bit(pkt, 2, 0x01, val) end,
+ tc = function (pkt, val) return pkt_bit(pkt, 2, 0x02, val) end,
+ aa = function (pkt, val) return pkt_bit(pkt, 2, 0x04, val) end,
+ qr = function (pkt, val) return pkt_bit(pkt, 2, 0x80, val) end,
+ cd = function (pkt, val) return pkt_bit(pkt, 3, 0x10, val) end,
+ ad = function (pkt, val) return pkt_bit(pkt, 3, 0x20, val) end,
+ ra = function (pkt, val) return pkt_bit(pkt, 3, 0x80, val) end,
+ -- Question
+ qname = function(pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ -- inlined knot_pkt_qname(), basically
+ if pkt == nil or pkt.qname_size == 0 then return nil end
+ return ffi.string(pkt.wire + 12, pkt.qname_size)
+ end,
+ qclass = function(pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ return C.kr_pkt_qclass(pkt)
+ end,
+ qtype = function(pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ return C.kr_pkt_qtype(pkt)
+ end,
+ rrsets = function (pkt, section_id)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local records = {}
+ local section = pkt.sections + section_id
+ for i = 1, section.count do
+ local rrset = knot_pkt_rr(section, i - 1)
+ table.insert(records, rrset)
+ end
+ return records
+ end,
+ section = function (pkt, section_id)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local records = {}
+ local section = pkt.sections + section_id
+ for i = 1, section.count do
+ local rrset = knot_pkt_rr(section, i - 1)
+ for k = 1, rrset:rdcount() do
+ table.insert(records, rrset:get(k - 1))
+ end
+ end
+ return records
+ end,
+ begin = function (pkt, section)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ assert(section >= pkt.current, 'cannot rewind to already written section')
+ assert(const_section_str[section], string.format('invalid section: %s', section))
+ local ret = knot.knot_pkt_begin(pkt, section)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ put = function (pkt, owner, ttl, rclass, rtype, rdata)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ret = C.kr_pkt_put(pkt, owner, ttl, rclass, rtype, rdata, #rdata)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ -- Put an RR set in the packet
+ -- Note: the packet doesn't take ownership of the RR set
+ put_rr = function (pkt, rr, rotate, flags)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ assert(ffi.istype(knot_rrset_t, rr))
+ local ret = C.knot_pkt_put_rotate(pkt, 0, rr, rotate or 0, flags or 0)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ recycle = function (pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ret = C.kr_pkt_recycle(pkt)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ clear_payload = function (pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ret = C.kr_pkt_clear_payload(pkt)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ question = function(pkt, qname, qclass, qtype)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ assert(qclass ~= nil, string.format('invalid class: %s', qclass))
+ assert(qtype ~= nil, string.format('invalid type: %s', qtype))
+ local ret = C.knot_pkt_put_question(pkt, qname, qclass, qtype)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ towire = function (pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ return ffi.string(pkt.wire, pkt.size)
+ end,
+ tostring = function(pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ return packet_tostring(pkt)
+ end,
+ -- Return number of remaining empty bytes in the packet
+ -- This is generally useful to check if there's enough space
+ remaining_bytes = function (pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local occupied = pkt.size + pkt.reserved
+ assert(pkt.max_size >= occupied)
+ return tonumber(pkt.max_size - occupied)
+ end,
+ -- Packet manipulation
+ parse = function (pkt)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ret = knot.knot_pkt_parse(pkt, 0)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ -- Resize packet wire to a new size
+ resize = function (pkt, new_size)
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ptr = C.mm_realloc(pkt.mm, pkt.wire, new_size, pkt.max_size)
+ if ptr == nil then return end
+ pkt.wire = ptr
+ pkt.max_size = new_size
+ return true
+ end,
+ },
+})
+-- Metatype for query
+local kr_query_t = ffi.typeof('struct kr_query')
+ffi.metatype( kr_query_t, {
+ __index = {
+ -- Return query domain name
+ name = function(qry)
+ assert(ffi.istype(kr_query_t, qry))
+ return dname2wire(qry.sname)
+ end,
+ -- Write this query into packet
+ write = function(qry, pkt)
+ assert(ffi.istype(kr_query_t, qry))
+ assert(ffi.istype(knot_pkt_t, pkt))
+ local ret = C.kr_make_query(qry, pkt)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ },
+})
+-- Metatype for request
+local kr_request_t = ffi.typeof('struct kr_request')
+ffi.metatype( kr_request_t, {
+ __index = {
+ current = function(req)
+ assert(ffi.istype(kr_request_t, req))
+ if req.current_query == nil then return nil end
+ return req.current_query
+ end,
+ -- Return last query on the resolution plan
+ last = function(req)
+ assert(ffi.istype(kr_request_t, req))
+ local query = C.kr_rplan_last(C.kr_resolve_plan(req))
+ if query == nil then return end
+ return query
+ end,
+ resolved = function(req)
+ assert(ffi.istype(kr_request_t, req))
+ local qry = C.kr_rplan_resolved(C.kr_resolve_plan(req))
+ if qry == nil then return nil end
+ return qry
+ end,
+ -- returns first resolved sub query for a request
+ first_resolved = function(req)
+ assert(ffi.istype(kr_request_t, req))
+ local rplan = C.kr_resolve_plan(req)
+ if not rplan or rplan.resolved.len < 1 then return nil end
+ return rplan.resolved.at[0]
+ end,
+ push = function(req, qname, qtype, qclass, flags, parent)
+ assert(ffi.istype(kr_request_t, req))
+ flags = kres.mk_qflags(flags) -- compatibility
+ local rplan = C.kr_resolve_plan(req)
+ local qry = C.kr_rplan_push(rplan, parent, qname, qclass, qtype)
+ if qry ~= nil and flags ~= nil then
+ C.kr_qflags_set(qry.flags, flags)
+ end
+ return qry
+ end,
+ pop = function(req, qry)
+ assert(ffi.istype(kr_request_t, req))
+ return C.kr_rplan_pop(C.kr_resolve_plan(req), qry)
+ end,
+ -- Return per-request variable table
+ -- The request can store anything in this Lua table and it will be freed
+ -- when the request is closed, it doesn't have to worry about contents.
+ vars = function (req)
+ assert(ffi.istype(kr_request_t, req))
+ -- Return variable if it's already stored
+ local var = worker.vars[req.vars_ref]
+ if var then
+ return var
+ end
+ -- Either take a slot number from freelist
+ -- or find a first free slot (expand the table)
+ local ref = worker.vars[0]
+ if ref then
+ worker.vars[0] = worker.vars[ref]
+ else
+ ref = #worker.vars + 1
+ end
+ -- Create new variables table
+ var = {}
+ worker.vars[ref] = var
+ -- Save reference in the request
+ req.vars_ref = ref
+ return var
+ end,
+ },
+})
+
+-- C array iterator
+local function c_array_iter(t, i)
+ i = i + 1
+ if i >= t.len then return end
+ return i, t.at[i][0]
+end
+
+-- Metatype for ranked record array
+local ranked_rr_array_t = ffi.typeof('ranked_rr_array_t')
+ffi.metatype(ranked_rr_array_t, {
+ __len = function(self)
+ return tonumber(self.len)
+ end,
+ __ipairs = function (self)
+ return c_array_iter, self, -1
+ end,
+ __index = {
+ get = function (self, i)
+ if i < 0 or i > self.len then return nil end
+ return self.at[i][0]
+ end,
+ }
+})
+
+-- Cache metatype
+local kr_cache_t = ffi.typeof('struct kr_cache')
+ffi.metatype( kr_cache_t, {
+ __index = {
+ insert = function (self, rr, rrsig, rank, timestamp)
+ assert(ffi.istype(kr_cache_t, self))
+ assert(ffi.istype(knot_rrset_t, rr), 'RR must be a rrset type')
+ assert(not rrsig or ffi.istype(knot_rrset_t, rrsig), 'RRSIG must be nil or of the rrset type')
+ -- Get current timestamp
+ if not timestamp then
+ local now = timeval_t()
+ C.gettimeofday(now, nil)
+ timestamp = tonumber(now.tv_sec)
+ end
+ -- Insert record into cache
+ local ret = C.kr_cache_insert_rr(self, rr, rrsig, tonumber(rank or 0), timestamp)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ sync = function (self)
+ assert(ffi.istype(kr_cache_t, self))
+ local ret = C.kr_cache_sync(self)
+ if ret ~= 0 then return nil, knot_error_t(ret) end
+ return true
+ end,
+ },
+})
+
+-- Pretty-print a single RR (which is a table with .owner .ttl .type .rdata)
+-- Extension: append .comment if exists.
+local function rr2str(rr, style)
+ -- Construct a single-RR temporary set while minimizing copying.
+ local ret
+ do
+ local rrs = knot_rrset_t(rr.owner, rr.type, kres.class.IN, rr.ttl)
+ rrs:add_rdata(rr.rdata, #rr.rdata)
+ ret = rrs:txt_dump(style)
+ end
+
+ -- Trim the newline and append comment (optionally).
+ if ret then
+ if ret:byte(-1) == string.byte('\n', -1) then
+ ret = ret:sub(1, -2)
+ end
+ if rr.comment then
+ ret = ret .. ' ;' .. rr.comment
+ end
+ end
+ return ret
+end
+
+-- Module API
+kres = {
+ -- Constants
+ class = const_class,
+ type = const_type,
+ section = const_section,
+ rcode = const_rcode,
+ opcode = const_opcode,
+ rank = const_rank,
+
+ -- Constants to strings
+ tostring = {
+ class = const_class_str,
+ type = const_type_str,
+ section = const_section_str,
+ rcode = const_rcode_str,
+ opcode = const_opcode_str,
+ rank = const_rank_str,
+ },
+
+ -- Create a struct kr_qflags from a single flag name or a list of names.
+ mk_qflags = function (names)
+ local kr_qflags = ffi.typeof('struct kr_qflags')
+ if names == 0 or names == nil then -- compatibility: nil is common in lua
+ names = {}
+ elseif type(names) == 'string' then
+ names = {names}
+ elseif ffi.istype(kr_qflags, names) then
+ return names
+ end
+
+ local fs = ffi.new(kr_qflags)
+ for _, name in pairs(names) do
+ fs[name] = true
+ end
+ return fs
+ end,
+
+ CONSUME = 1, PRODUCE = 2, DONE = 4, FAIL = 8, YIELD = 16,
+
+ -- Export types
+ rrset = knot_rrset_t,
+ packet = knot_pkt_t,
+ lru = function (max_size, value_type)
+ local ct = ffi.typeof(typed_lru_t, value_type or ffi.typeof('uint64_t'))
+ return ffi.metatype(ct, lru_metatype)(max_size)
+ end,
+
+ -- Metatypes. Beware that any pointer will be cast silently...
+ pkt_t = function (udata) return ffi.cast('knot_pkt_t *', udata) end,
+ request_t = function (udata) return ffi.cast('struct kr_request *', udata) end,
+ sockaddr_t = function (udata) return ffi.cast('struct sockaddr *', udata) end,
+
+ -- Global API functions
+ -- Convert a lua string to a lower-case wire format (inside GC-ed ffi.string).
+ str2dname = function(name)
+ if type(name) ~= 'string' then return end
+ local dname = ffi.gc(C.knot_dname_from_str(nil, name, 0), C.free)
+ if dname == nil then return nil end
+ ffi.C.knot_dname_to_lower(dname);
+ return dname2wire(dname)
+ end,
+ dname2str = dname2str,
+ dname2wire = dname2wire,
+
+ rr2str = rr2str,
+ str2ip = function (ip)
+ local family = C.kr_straddr_family(ip)
+ local ret = C.inet_pton(family, ip, addr_buf)
+ if ret ~= 1 then return nil end
+ return ffi.string(addr_buf, C.kr_family_len(family))
+ end,
+ context = function () return ffi.cast('struct kr_context *', __engine) end,
+
+ knot_pkt_rr = knot_pkt_rr,
+}
+
+return kres
diff --git a/daemon/lua/sandbox.lua b/daemon/lua/sandbox.lua
new file mode 100644
index 0000000..017e3a3
--- /dev/null
+++ b/daemon/lua/sandbox.lua
@@ -0,0 +1,458 @@
+local ffi = require('ffi')
+
+-- Units
+kB = 1024
+MB = 1024*kB
+GB = 1024*MB
+-- Time
+sec = 1000
+second = sec
+minute = 60 * sec
+min = minute
+hour = 60 * minute
+day = 24 * hour
+
+-- Logging
+function panic(fmt, ...)
+ error(string.format('error: '..fmt, ...))
+end
+function warn(fmt, ...)
+ io.stderr:write(string.format(fmt..'\n', ...))
+end
+function log(fmt, ...)
+ print(string.format(fmt, ...))
+end
+
+-- Resolver bindings
+kres = require('kres')
+if rawget(kres, 'str2dname') ~= nil then
+ todname = kres.str2dname
+end
+
+-- Compatibility wrapper for query flags.
+worker.resolve = function (qname, qtype, qclass, options, finish, init)
+ -- Alternatively use named arguments
+ if type(qname) == 'table' then
+ local t = qname
+ qname = t.name
+ qtype = t.type or kres.type.A
+ qclass = t.class or kres.class.IN
+ options = t.options
+ finish = t.finish
+ init = t.init
+ end
+
+ local init_cb, finish_cb = init, nil
+ if finish then
+ -- Create callback for finalization
+ finish_cb = ffi.cast('trace_callback_f', function (req)
+ req = kres.request_t(req)
+ finish(req.answer, req)
+ finish_cb:free()
+ end)
+ -- Wrap initialiser to install finish callback
+ init_cb = function (req)
+ req = kres.request_t(req)
+ if init then init(req) end
+ req.trace_finish = finish_cb
+ end
+ end
+
+ -- Translate options and resolve
+ options = kres.mk_qflags(options)
+ return worker.resolve_unwrapped(qname, qtype, qclass, options, init_cb)
+end
+
+resolve = worker.resolve
+
+-- Shorthand for aggregated per-worker information
+worker.info = function ()
+ local t = worker.stats()
+ t.pid = worker.pid
+ return t
+end
+
+-- Resolver mode of operation
+local current_mode = 'normal'
+local mode_table = { normal=0, strict=1, permissive=2 }
+function mode(m)
+ if not m then return current_mode end
+ if not mode_table[m] then error('unsupported mode: '..m) end
+ -- Update current operation mode
+ current_mode = m
+ option('STRICT', current_mode == 'strict')
+ option('PERMISSIVE', current_mode == 'permissive')
+ return true
+end
+
+-- Trivial option alias
+function reorder_RR(val)
+ return option('REORDER_RR', val)
+end
+
+-- Get/set resolver options via name (string)
+function option(name, val)
+ local flags = kres.context().options;
+ -- Note: no way to test existence of flags[name] but we want error anyway.
+ name = string.upper(name) -- convenience
+ if val ~= nil then
+ if (val ~= true) and (val ~= false) then
+ panic('invalid option value: ' .. tostring(val))
+ end
+ flags[name] = val;
+ end
+ return flags[name];
+end
+
+-- Function aliases
+-- `env.VAR returns os.getenv(VAR)`
+env = {}
+setmetatable(env, {
+ __index = function (_, k) return os.getenv(k) end
+})
+
+-- Quick access to interfaces
+-- `net.<iface>` => `net.interfaces()[iface]`
+-- `net = {addr1, ..}` => `net.listen(name, addr1)`
+-- `net.ipv{4,6} = {true, false}` => enable/disable IPv{4,6}
+setmetatable(net, {
+ __index = function (t, k)
+ local v = rawget(t, k)
+ if v then return v
+ elseif k == 'ipv6' then return not option('NO_IPV6')
+ elseif k == 'ipv4' then return not option('NO_IPV4')
+ else return net.interfaces()[k]
+ end
+ end,
+ __newindex = function (t,k,v)
+ if k == 'ipv6' then return option('NO_IPV6', not v)
+ elseif k == 'ipv4' then return option('NO_IPV4', not v)
+ else
+ local iname = rawget(net.interfaces(), v)
+ if iname then t.listen(iname)
+ else t.listen(v)
+ end
+ end
+ end
+})
+
+-- Syntactic sugar for module loading
+-- `modules.<name> = <config>`
+setmetatable(modules, {
+ __newindex = function (_, k, v)
+ if type(k) == 'number' then
+ k, v = v, nil
+ end
+ if not rawget(_G, k) then
+ modules.load(k)
+ k = string.match(k, '[%w_]+')
+ local mod = _G[k]
+ local config = mod and rawget(mod, 'config')
+ if mod ~= nil and config ~= nil then
+ if k ~= v then config(v)
+ else config()
+ end
+ end
+ end
+ end
+})
+
+
+cache.clear = function (name, exact_name, rr_type, chunk_size, callback, prev_state)
+ if name == nil or (name == '.' and not exact_name) then
+ -- keep same output format as for 'standard' clear
+ local total_count = cache.count()
+ if not cache.clear_everything() then
+ error('unable to clear everything')
+ end
+ return {count = total_count}
+ end
+ -- Check parameters, in order, and set defaults if missing.
+ local dname = kres.str2dname(name)
+ if not dname then error('cache.clear(): incorrect name passed') end
+ if exact_name == nil then exact_name = false end
+ if type(exact_name) ~= 'boolean'
+ then error('cache.clear(): incorrect exact_name passed') end
+
+ local cach = kres.context().cache;
+ local rettable = {}
+ -- Apex warning. If the caller passes a custom callback,
+ -- we assume they are advanced enough not to need the check.
+ -- The point is to avoid repeating the check in each callback iteration.
+ if callback == nil then
+ local apex_array = ffi.new('knot_dname_t *[1]') -- C: dname **apex_array
+ local ret = ffi.C.kr_cache_closest_apex(cach, dname, false, apex_array)
+ if ret < 0 then
+ error(ffi.string(ffi.C.knot_strerror(ret))) end
+ if not ffi.C.knot_dname_is_equal(apex_array[0], dname) then
+ local apex_str = kres.dname2str(apex_array[0])
+ rettable.not_apex = 'to clear proofs of non-existence call '
+ .. 'cache.clear(\'' .. tostring(apex_str) ..'\')'
+ rettable.subtree = apex_str
+ end
+ ffi.C.free(apex_array[0])
+ end
+
+ if rr_type ~= nil then
+ -- Special case, without any subtree searching.
+ if not exact_name
+ then error('cache.clear(): specifying rr_type only supported with exact_name') end
+ if chunk_size or callback
+ then error('cache.clear(): chunk_size and callback parameters not supported with rr_type') end
+ local ret = ffi.C.kr_cache_remove(cach, dname, rr_type)
+ if ret < 0 then error(ffi.string(ffi.C.knot_strerror(ret))) end
+ return {count = 1}
+ end
+
+ if chunk_size == nil then chunk_size = 100 end
+ if type(chunk_size) ~= 'number' or chunk_size <= 0
+ then error('cache.clear(): chunk_size has to be a positive integer') end
+
+ -- Do the C call, and add chunk_size warning.
+ rettable.count = ffi.C.kr_cache_remove_subtree(cach, dname, exact_name, chunk_size)
+ if rettable.count == chunk_size then
+ local msg_extra = ''
+ if callback == nil then
+ msg_extra = '; the default callback will continue asynchronously'
+ end
+ rettable.chunk_limit = 'chunk size limit reached' .. msg_extra
+ end
+
+ -- Default callback function: repeat after 1ms
+ if callback == nil then callback =
+ function (cbname, cbexact_name, cbrr_type, cbchunk_size, cbself, cbprev_state, cbrettable)
+ if cbrettable.count < 0 then error(ffi.string(ffi.C.knot_strerror(cbrettable.count))) end
+ if cbprev_state == nil then cbprev_state = { round = 0 } end
+ if type(cbprev_state) ~= 'table'
+ then error('cache.clear() callback: incorrect prev_state passed') end
+ cbrettable.round = cbprev_state.round + 1
+ if (cbrettable.count == cbchunk_size) then
+ event.after(1, function ()
+ cache.clear(cbname, cbexact_name, cbrr_type, cbchunk_size, cbself, cbrettable)
+ end)
+ elseif cbrettable.round > 1 then
+ log('[cache] asynchonous cache.clear(\'' .. cbname .. '\', '
+ .. tostring(cbexact_name) .. ') finished')
+ end
+ return cbrettable
+ end
+ end
+ return callback(name, exact_name, rr_type, chunk_size, callback, prev_state, rettable)
+end
+-- Syntactic sugar for cache
+-- `cache[x] -> cache.get(x)`
+-- `cache.{size|storage} = value`
+setmetatable(cache, {
+ __index = function (t, k)
+ local res = rawget(t, k)
+ if not res and not rawget(t, 'current_size') then return res end
+ -- Beware: t.get returns empty table on failure to find.
+ -- That would be confusing here (breaking kresc), so return nil instead.
+ res = t.get(k)
+ if res and next(res) ~= nil then return res else return nil end
+ end,
+ __newindex = function (t,k,v)
+ -- Defaults
+ local storage = rawget(t, 'current_storage')
+ if not storage then storage = 'lmdb://' end
+ local size = rawget(t, 'current_size')
+ if not size then size = 10*MB end
+ -- Declarative interface for cache
+ if k == 'size' then t.open(v, storage)
+ elseif k == 'storage' then t.open(size, v) end
+ end
+})
+
+-- Register module in Lua environment
+function modules_register(module)
+ -- Syntactic sugar for get() and set() properties
+ setmetatable(module, {
+ __index = function (t, k)
+ local v = rawget(t, k)
+ if v then return v
+ elseif rawget(t, 'get') then return t.get(k)
+ end
+ end,
+ __newindex = function (t, k, v)
+ local old_v = rawget(t, k)
+ if not old_v and rawget(t, 'set') then
+ t.set(k..' '..v)
+ end
+ end
+ })
+end
+
+-- Make sandboxed environment
+local function make_sandbox(defined)
+ local __protected = { worker = true, env = true, modules = true, cache = true, net = true, trust_anchors = true }
+
+ -- Compute and export the list of top-level names (hidden otherwise)
+ local nl = ""
+ for n in pairs(defined) do
+ nl = nl .. n .. "\n"
+ end
+
+ return setmetatable({ __orig_name_list = nl }, {
+ __index = defined,
+ __newindex = function (_, k, v)
+ if __protected[k] then
+ for k2,v2 in pairs(v) do
+ defined[k][k2] = v2
+ end
+ else
+ defined[k] = v
+ end
+ end
+ })
+end
+
+-- Compatibility sandbox
+if setfenv then -- Lua 5.1 and less
+ _G = make_sandbox(getfenv(0))
+ setfenv(0, _G)
+else -- Lua 5.2+
+ _SANDBOX = make_sandbox(_ENV)
+end
+
+-- Load embedded modules
+trust_anchors = require('trust_anchors')
+modules.load('ta_signal_query')
+modules.load('policy')
+modules.load('priming')
+modules.load('detect_time_skew')
+modules.load('detect_time_jump')
+modules.load('ta_sentinel')
+modules.load('edns_keepalive')
+
+-- Interactive command evaluation
+function eval_cmd(line, raw)
+ -- Compatibility sandbox code loading
+ local function load_code(code)
+ if getfenv then -- Lua 5.1
+ return loadstring(code)
+ else -- Lua 5.2+
+ return load(code, nil, 't', _ENV)
+ end
+ end
+ local err, chunk
+ chunk, err = load_code(raw and 'return '..line or 'return table_print('..line..')')
+ if err then
+ chunk, err = load_code(line)
+ end
+ if not err then
+ return chunk()
+ else
+ error(err)
+ end
+end
+
+-- Pretty printing
+function table_print (tt, indent, done)
+ done = done or {}
+ indent = indent or 0
+ local result = ""
+ -- Convert to printable string (escape unprintable)
+ local function printable(value)
+ value = tostring(value)
+ local bytes = {}
+ for i = 1, #value do
+ local c = string.byte(value, i)
+ if c >= 0x20 and c < 0x7f then table.insert(bytes, string.char(c))
+ else table.insert(bytes, '\\'..tostring(c))
+ end
+ if i > 80 then table.insert(bytes, '...') break end
+ end
+ return table.concat(bytes)
+ end
+ if type(tt) == "table" then
+ for key, value in pairs (tt) do
+ result = result .. string.rep (" ", indent)
+ if type (value) == "table" and not done [value] then
+ done [value] = true
+ result = result .. string.format("[%s] => {\n", printable (key))
+ result = result .. table_print (value, indent + 4, done)
+ result = result .. string.rep (" ", indent)
+ result = result .. "}\n"
+ else
+ result = result .. string.format("[%s] => %s\n",
+ tostring (key), printable(value))
+ end
+ end
+ else
+ result = result .. tostring(tt) .. "\n"
+ end
+ return result
+end
+
+-- This extends the worker module to allow asynchronous execution of functions and nonblocking I/O.
+-- The current implementation combines cqueues for Lua interface, and event.socket() in order to not
+-- block resolver engine while waiting for I/O or timers.
+--
+local has_cqueues, cqueues = pcall(require, 'cqueues')
+if has_cqueues then
+
+ -- Export the asynchronous sleep function
+ worker.sleep = cqueues.sleep
+
+ -- Create metatable for workers to define the API
+ -- It can schedule multiple cqueues and yield execution when there's a wait for blocking I/O or timer
+ local asynchronous_worker_mt = {
+ work = function (self)
+ local ok, err, _, co = self.cq:step(0)
+ if not ok then
+ warn('[%s] error: %s %s', self.name or 'worker', err, debug.traceback(co))
+ end
+ -- Reschedule timeout or create new one
+ local timeout = self.cq:timeout()
+ if timeout then
+ -- Throttle timeouts to avoid too frequent wakeups
+ if timeout == 0 then timeout = 0.00001 end
+ -- Convert from seconds to duration
+ timeout = timeout * sec
+ if not self.next_timeout then
+ self.next_timeout = event.after(timeout, self.on_step)
+ else
+ event.reschedule(self.next_timeout, timeout)
+ end
+ else -- Cancel running timeout when there is no next deadline
+ if self.next_timeout then
+ event.cancel(self.next_timeout)
+ self.next_timeout = nil
+ end
+ end
+ end,
+ wrap = function (self, f)
+ self.cq:wrap(f)
+ end,
+ loop = function (self)
+ self.on_step = function () self:work() end
+ self.event_fd = event.socket(self.cq:pollfd(), self.on_step)
+ end,
+ close = function (self)
+ if self.event_fd then
+ event.cancel(self.event_fd)
+ self.event_fd = nil
+ end
+ end,
+ }
+
+ -- Implement the coroutine worker with cqueues
+ local function worker_new (name)
+ return setmetatable({name = name, cq = cqueues.new()}, { __index = asynchronous_worker_mt })
+ end
+
+ -- Create a default background worker
+ worker.bg_worker = worker_new('worker.background')
+ worker.bg_worker:loop()
+
+ -- Wrap a function for asynchronous execution
+ function worker.coroutine (f)
+ worker.bg_worker:wrap(f)
+ end
+else
+ -- Disable asynchronous execution
+ local function disabled () error('cqueues are required for asynchronous execution') end
+ worker.sleep = disabled
+ worker.map = disabled
+ worker.coroutine = disabled
+end
diff --git a/daemon/lua/trust_anchors.lua.in b/daemon/lua/trust_anchors.lua.in
new file mode 100644
index 0000000..1d16018
--- /dev/null
+++ b/daemon/lua/trust_anchors.lua.in
@@ -0,0 +1,663 @@
+-- Load the module
+local ffi = require 'ffi'
+local kres = require('kres')
+local C = ffi.C
+
+local trust_anchors -- the public pseudo-module, exported as global variable
+
+-- Fetch over HTTPS with peert cert checked
+local function https_fetch(url, ca)
+ local ssl_ok, https = pcall(require, 'ssl.https')
+ local ltn_ok, ltn12 = pcall(require, 'ltn12')
+ if not ssl_ok or not ltn_ok then
+ return nil, 'luasec and luasocket needed for root TA bootstrap'
+ end
+ local resp = {}
+ local r, c = https.request{
+ url = url,
+ cafile = ca,
+ verify = {'peer', 'fail_if_no_peer_cert' },
+ protocol = 'tlsv1_2',
+ sink = ltn12.sink.table(resp),
+ }
+ if r == nil then return r, c end
+ return resp[1]
+end
+
+-- remove UTC timezone specification if present or throw error
+local function time2utc(orig_timespec)
+ local patterns = {'[+-]00:00$', 'Z$'}
+ for _, pattern in ipairs(patterns) do
+ local timespec, removals = string.gsub(orig_timespec, pattern, '')
+ if removals == 1 then
+ return timespec
+ end
+ end
+ error(string.format('unsupported time specification: %s', orig_timespec))
+end
+
+local function keydigest_is_valid(valid_from, valid_until)
+ local format = '%Y-%m-%dT%H:%M:%S'
+ local time_now = os.date('!%Y-%m-%dT%H:%M:%S') -- ! forces UTC
+ local time_diff = ffi.new('double[1]')
+ local err = ffi.C.kr_strptime_diff(
+ format, time_now, time2utc(valid_from), time_diff)
+ if (err ~= nil) then
+ error(string.format('failed to process "validFrom" constraint: %s',
+ ffi.string(err)))
+ end
+ local from_ok = time_diff[0] > 0
+
+ -- optional attribute
+ local until_ok = true
+ if valid_until then
+ err = ffi.C.kr_strptime_diff(
+ format, time_now, time2utc(valid_until), time_diff)
+ if (err ~= nil) then
+ error(string.format('failed to process "validUntil" constraint: %s',
+ ffi.string(err)))
+ end
+ until_ok = time_diff[0] < 0
+ end
+ return from_ok and until_ok
+end
+
+local function parse_xml_keydigest(attrs, inside, output)
+ local fields = {}
+ local _, n = string.gsub(attrs, "([%w]+)=\"([^\"]*)\"", function (k, v) fields[k] = v end)
+ assert(n >= 1,
+ string.format('cannot parse XML attributes from "%s"', attrs))
+ assert(fields['validFrom'],
+ string.format('mandatory KeyDigest XML attribute validFrom ' ..
+ 'not found in "%s"', attrs))
+ local valid_attrs = {id = true, validFrom = true, validUntil = true}
+ for key, _ in pairs(fields) do
+ assert(valid_attrs[key],
+ string.format('unsupported KeyDigest attribute "%s" found in "%s"',
+ key, attrs))
+ end
+
+ _, n = string.gsub(inside, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end)
+ assert(n >= 1,
+ string.format('error parsing KeyDigest XML elements from "%s"',
+ inside))
+ local mandatory_elements = {'KeyTag', 'Algorithm', 'DigestType', 'Digest'}
+ for _, key in ipairs(mandatory_elements) do
+ assert(fields[key],
+ string.format('mandatory element %s is missing in "%s"',
+ key, inside))
+ end
+ assert(n == 4, string.format('found %d elements but expected 4 in %s', n, inside))
+ table.insert(output, fields) -- append to list of parsed keydigests
+end
+
+local function generate_ds(keydigests)
+ local rrset = ''
+ for _, fields in ipairs(keydigests) do
+ local rr = string.format(
+ '. 0 IN DS %s %s %s %s',
+ fields.KeyTag, fields.Algorithm, fields.DigestType, fields.Digest)
+ if keydigest_is_valid(fields['validFrom'], fields['validUntil']) then
+ rrset = rrset .. '\n' .. rr
+ else
+ log('[ ta ] skipping trust anchor "%s" ' ..
+ 'because it is outside of validity range', rr)
+ end
+ end
+ return rrset
+end
+
+local function assert_str_match(str, pattern, expected)
+ local count = 0
+ for _ in string.gmatch(str, pattern) do
+ count = count + 1
+ end
+ assert(count == expected,
+ string.format('expected %d occurences of "%s" but got %d in "%s"',
+ expected, pattern, count, str))
+end
+
+-- Fetch root anchors in XML over HTTPS, returning a zone-file-style string
+-- or false in case of error, and a message.
+local function bootstrap(url, ca)
+ -- RFC 7958, sec. 2, but we don't do precise XML parsing.
+ -- @todo ICANN certificate is verified against current CA
+ -- this is not ideal, as it should rather verify .xml signature which
+ -- is signed by ICANN long-lived cert, but luasec has no PKCS7
+ local xml, err = https_fetch(url, ca)
+ if not xml then
+ return false, string.format('[ ta ] fetch of "%s" failed: %s', url, err)
+ end
+
+ -- we support only minimal subset of https://tools.ietf.org/html/rfc7958
+ assert_str_match(xml, '<?xml version="1%.0" encoding="UTF%-8"%?>', 1)
+ assert_str_match(xml, '<TrustAnchor ', 1)
+ assert_str_match(xml, '<Zone>.</Zone>', 1)
+ assert_str_match(xml, '</TrustAnchor>', 1)
+
+ -- Parse root trust anchor, one digest at a time, converting to a zone-file-style string.
+ local keydigests = {}
+ string.gsub(xml, "<KeyDigest([^>]*)>(.-)</KeyDigest>", function(attrs, inside)
+ parse_xml_keydigest(attrs, inside, keydigests)
+ end)
+ local rrset = generate_ds(keydigests)
+ if rrset == '' then
+ return false, string.format('[ ta ] no valid trust anchors found at "%s"', url)
+ end
+ local msg = '[ ta ] Root trust anchors bootstrapped over https with pinned certificate.\n'
+ .. ' You SHOULD verify them manually against original source:\n'
+ .. ' https://www.iana.org/dnssec/files\n'
+ .. '[ ta ] Current root trust anchors are:'
+ .. rrset
+ return rrset, msg
+end
+
+-- RFC5011 state table
+local key_state = {
+ Start = 'Start', AddPend = 'AddPend', Valid = 'Valid',
+ Missing = 'Missing', Revoked = 'Revoked', Removed = 'Removed'
+}
+
+-- Find key in current keyset
+local function ta_find(keyset, rr)
+ local rr_tag = C.kr_dnssec_key_tag(rr.type, rr.rdata, #rr.rdata)
+ assert(rr_tag >= 0 and rr_tag <= 65535, string.format('invalid RR: %s: %s',
+ kres.rr2str(rr), ffi.string(C.knot_strerror(rr_tag))))
+ for i, ta in ipairs(keyset) do
+ -- Match key owner and content
+ local ta_tag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
+ assert(ta_tag >= 0 and ta_tag <= 65535, string.format('invalid RR: %s: %s',
+ kres.rr2str(ta), ffi.string(C.knot_strerror(ta_tag))))
+ if ta.owner == rr.owner then
+ if ta.type == rr.type then
+ if rr.type == kres.type.DNSKEY then
+ if C.kr_dnssec_key_match(ta.rdata, #ta.rdata, rr.rdata, #rr.rdata) == 0 then
+ return ta
+ end
+ elseif rr.type == kres.type.DS and ta.rdata == rr.rdata then
+ return ta
+ end
+ -- DNSKEY superseding DS, inexact match
+ elseif rr.type == kres.type.DNSKEY and ta.type == kres.type.DS then
+ if ta.key_tag == rr_tag then
+ keyset[i] = rr -- Replace current DS
+ rr.state = ta.state
+ rr.key_tag = ta.key_tag
+ return rr
+ end
+ -- DS key matching DNSKEY, inexact match
+ elseif rr.type == kres.type.DS and ta.type == kres.type.DNSKEY then
+ if rr_tag == ta_tag then
+ return ta
+ end
+ end
+ end
+ end
+ return nil
+end
+
+-- Evaluate TA status of a RR according to RFC5011. The time is in seconds.
+local function ta_present(keyset, rr, hold_down_time, force_valid)
+ if rr.type == kres.type.DNSKEY and not C.kr_dnssec_key_ksk(rr.rdata) then
+ return false -- Ignore
+ end
+ -- Find the key in current key set and check its status
+ local now = os.time()
+ local key_revoked = (rr.type == kres.type.DNSKEY) and C.kr_dnssec_key_revoked(rr.rdata)
+ local key_tag = C.kr_dnssec_key_tag(rr.type, rr.rdata, #rr.rdata)
+ assert(key_tag >= 0 and key_tag <= 65535, string.format('invalid RR: %s: %s',
+ kres.rr2str(rr), ffi.string(C.knot_strerror(key_tag))))
+ local ta = ta_find(keyset, rr)
+ if ta then
+ -- Key reappears (KeyPres)
+ if ta.state == key_state.Missing then
+ ta.state = key_state.Valid
+ ta.timer = nil
+ end
+ -- Key is revoked (RevBit)
+ if ta.state == key_state.Valid or ta.state == key_state.Missing then
+ if key_revoked then
+ ta.state = key_state.Revoked
+ ta.timer = now + hold_down_time
+ end
+ end
+ -- Remove hold-down timer expires (RemTime)
+ if ta.state == key_state.Revoked and os.difftime(ta.timer, now) <= 0 then
+ ta.state = key_state.Removed
+ ta.timer = nil
+ end
+ -- Add hold-down timer expires (AddTime)
+ if ta.state == key_state.AddPend and os.difftime(ta.timer, now) <= 0 then
+ ta.state = key_state.Valid
+ ta.timer = nil
+ end
+ if rr.state ~= key_state.Valid or verbose() then
+ log('[ ta ] key: ' .. key_tag .. ' state: '..ta.state)
+ end
+ return true
+ elseif not key_revoked then -- First time seen (NewKey)
+ rr.key_tag = key_tag
+ if force_valid then
+ rr.state = key_state.Valid
+ else
+ rr.state = key_state.AddPend
+ rr.timer = now + hold_down_time
+ end
+ if rr.state ~= key_state.Valid or verbose() then
+ log('[ ta ] key: ' .. key_tag .. ' state: '..rr.state)
+ end
+ table.insert(keyset, rr)
+ return true
+ end
+ return false
+end
+
+-- TA is missing in the new key set. The time is in seconds.
+local function ta_missing(ta, hold_down_time)
+ -- Key is removed (KeyRem)
+ local keep_ta = true
+ local key_tag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
+ assert(key_tag >= 0 and key_tag <= 65535, string.format('invalid RR: %s: %s',
+ kres.rr2str(ta), ffi.string(C.knot_strerror(key_tag))))
+ if ta.state == key_state.Valid then
+ ta.state = key_state.Missing
+ ta.timer = os.time() + hold_down_time
+
+ -- Remove key that is missing for too long
+ elseif ta.state == key_state.Missing and os.difftime(ta.timer, os.time()) <= 0 then
+ ta.state = key_state.Removed
+ log('[ ta ] key: '..key_tag..' removed because missing for too long')
+ keep_ta = false
+
+ -- Purge pending key
+ elseif ta.state == key_state.AddPend then
+ log('[ ta ] key: '..key_tag..' purging')
+ keep_ta = false
+ end
+ log('[ ta ] key: '..key_tag..' state: '..ta.state)
+ return keep_ta
+end
+
+local active_refresh, update -- forwards
+
+-- Plan an event for refreshing the root DNSKEYs and re-scheduling itself
+local function refresh_plan(keyset, delay, is_initial)
+ local owner_str = kres.dname2str(keyset.owner) -- maybe fix converting back and forth?
+ keyset.refresh_ev = event.after(delay, function ()
+ resolve(owner_str, kres.type.DNSKEY, kres.class.IN, 'NO_CACHE',
+ function (pkt)
+ -- Schedule itself with updated timeout
+ local delay_new = active_refresh(keyset, kres.pkt_t(pkt), is_initial)
+ delay_new = keyset.refresh_time or trust_anchors.refresh_time or delay_new
+ log('[ ta ] next refresh for ' .. owner_str .. ' in '
+ .. delay_new/hour .. ' hours')
+ refresh_plan(keyset, delay_new)
+ end)
+ end)
+end
+
+-- Refresh the DNSKEYs from the packet, and return time to the next check.
+active_refresh = function (keyset, pkt, is_initial)
+ local retry = true
+ if pkt:rcode() == kres.rcode.NOERROR then
+ local records = pkt:section(kres.section.ANSWER)
+ local new_keys = {}
+ for _, rr in ipairs(records) do
+ if rr.type == kres.type.DNSKEY then
+ table.insert(new_keys, rr)
+ end
+ end
+ update(keyset, new_keys, is_initial)
+ retry = false
+ else
+ warn('[ ta ] active refresh failed for ' .. kres.dname2str(keyset.owner)
+ .. ' with rcode: ' .. pkt:rcode())
+ end
+ -- Calculate refresh/retry timer (RFC 5011, 2.3)
+ local min_ttl = retry and day or 15 * day
+ for _, rr in ipairs(keyset) do -- 10 or 50% of the original TTL
+ min_ttl = math.min(min_ttl, (retry and 100 or 500) * rr.ttl)
+ end
+ return math.max(hour, min_ttl)
+end
+
+-- Write keyset to a file. States and timers are stored in comments.
+local function keyset_write(keyset)
+ if not keyset.filename then return false end -- not to be persisted
+ local fname_tmp = keyset.filename .. '.lock.' .. tostring(worker.pid);
+ local file = assert(io.open(fname_tmp, 'w'))
+ for i = 1, #keyset do
+ local ta = keyset[i]
+ ta.comment = ' ' .. ta.state .. ':' .. (ta.timer or '')
+ .. ' ; KeyTag:' .. ta.key_tag -- the tag is just for humans
+ local rr_str = kres.rr2str(ta) .. '\n'
+ if ta.state ~= key_state.Valid and ta.state ~= key_state.Missing then
+ rr_str = '; '..rr_str -- Invalidate key string (for older kresd versions)
+ end
+ file:write(rr_str)
+ end
+ file:close()
+ assert(os.rename(fname_tmp, keyset.filename))
+end
+
+-- Search the values of a table and return the corrseponding key (or nil).
+local function table_search(t, val)
+ for k, v in pairs(t) do
+ if v == val then
+ return k
+ end
+ end
+ return nil
+end
+
+-- For each RR, parse .state and .timer from .comment.
+local function keyset_parse_comments(tas, default_state)
+ for _, ta in pairs(tas) do
+ ta.state = default_state
+ if ta.comment then
+ string.gsub(ta.comment, '^%s*(%a+):(%d*)', function (state, time)
+ if table_search(key_state, state) then
+ ta.state = state
+ end
+ ta.timer = tonumber(time) -- nil on failure
+ end)
+ ta.comment = nil
+ end
+ end
+ return tas
+end
+
+-- Read keyset from a file. (This includes the key states and timers.)
+local function keyset_read(path)
+ -- First load the regular entries, trusting them.
+ local zonefile = require('zonefile')
+ local tas, err = zonefile.file(path)
+ if not tas then
+ return tas, err
+ end
+ keyset_parse_comments(tas, key_state.Valid)
+
+ -- The untrusted keys are commented out but important to load.
+ for line in io.lines(path) do
+ if line:sub(1, 2) == '; ' then
+ -- Ignore the line if it fails to parse including recognized .state.
+ local l_set = zonefile.string(line:sub(3))
+ if l_set and l_set[1] then
+ keyset_parse_comments(l_set)
+ if l_set[1].state then
+ table.insert(tas, l_set[1])
+ end
+ end
+ end
+ end
+
+ for _, ta in pairs(tas) do
+ local ta_keytag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
+ if not (ta_keytag >= 0 and ta_keytag <= 65535) then
+ return nil, string.format('invalid key: "%s": %s',
+ kres.rr2str(ta), ffi.string(C.knot_strerror(ta_keytag)))
+ end
+ ta.key_tag = ta_keytag
+ end
+ return tas
+end
+
+-- Replace current TAs for given owner by the "trusted" ones from passed keyset.
+-- Return the number of trusted keys for the owner.
+local function keyset_publish(keyset)
+ local store = kres.context().trust_anchors
+ local count = 0
+ C.kr_ta_del(store, keyset.owner)
+ for _, ta in ipairs(keyset) do
+ -- Key MAY be used as a TA only in these two states (RFC5011, 4.2)
+ if ta.state == key_state.Valid or ta.state == key_state.Missing then
+ if C.kr_ta_add(store, ta.owner, ta.type, ta.ttl, ta.rdata, #ta.rdata) == 0 then
+ count = count + 1
+ end
+ end
+ end
+ if count == 0 then
+ warn('[ ta ] ERROR: no anchors are trusted for ' ..
+ kres.dname2str(keyset.owner) .. ' !')
+ end
+ return count
+end
+
+
+-- Update existing keyset; return true if successful.
+-- Param `is_initial` (bool): force .NewKey states to .Valid, i.e. init empty keyset.
+update = function (keyset, new_keys, is_initial)
+ if not new_keys then return false end
+
+ -- Filter TAs to be purged from the keyset (KeyRem), in three steps
+ -- 1: copy TAs to be kept to `keepset`
+ local hold_down = (keyset.hold_down_time or trust_anchors.hold_down_time) / 1000
+ local keepset = {}
+ local keep_removed = keyset.keep_removed or trust_anchors.keep_removed
+ for _, ta in ipairs(keyset) do
+ local keep = true
+ if not ta_find(new_keys, ta) then
+ -- Ad-hoc: RFC 5011 doesn't mention removing a Missing key.
+ -- Let's do it after a very long period has elapsed.
+ keep = ta_missing(ta, hold_down * 4)
+ end
+ -- Purge removed keys
+ if ta.state == key_state.Removed then
+ if keep_removed > 0 then
+ keep_removed = keep_removed - 1
+ else
+ keep = false
+ end
+ end
+ if keep then
+ table.insert(keepset, ta)
+ end
+ end
+ -- 2: remove all TAs - other settings etc. will remain in the keyset
+ for i, _ in ipairs(keyset) do
+ keyset[i] = nil
+ end
+ -- 3: move TAs to be kept into the keyset (same indices)
+ for k, ta in pairs(keepset) do
+ keyset[k] = ta
+ end
+
+ -- Evaluate new TAs
+ for _, rr in ipairs(new_keys) do
+ if (rr.type == kres.type.DNSKEY or rr.type == kres.type.DS) and rr.rdata ~= nil then
+ ta_present(keyset, rr, hold_down, is_initial)
+ end
+ end
+
+ -- Store the keyset
+ keyset_write(keyset)
+
+ -- Start using the new TAs.
+ if keyset_publish(keyset) == 0 then
+ -- TODO: try to rebootstrap if for root?
+ return false
+ elseif verbose() then
+ log('[ ta ] refreshed trust anchors for domain ' .. kres.dname2str(keyset.owner) .. ' are:\n'
+ .. trust_anchors.summary(keyset.owner))
+ end
+
+ return true
+end
+
+local add_file = function (path, unmanaged)
+ if not unmanaged then
+ if not io.open(path .. '.lock', 'w') then
+ error("[ ta ] ERROR: write access needed to keyfile dir '"..path.."'")
+ end
+ os.remove(path .. ".lock")
+ end
+
+ -- Bootstrap if requested and keyfile doesn't exist
+ if not unmanaged and not io.open(path, 'r') then
+ log("[ ta ] keyfile '%s': doesn't exist, bootstrapping", path);
+ local tas, msg = bootstrap(trust_anchors.bootstrap_url, trust_anchors.bootstrap_ca)
+ if not tas then
+ msg = msg .. '\n'
+ .. '[ ta ] Failed to bootstrap root trust anchors; see:\n'
+ .. ' https://knot-resolver.readthedocs.io/en/latest/daemon.html#enabling-dnssec'
+ error(msg)
+ end
+ print(msg)
+ trustanchor(tas)
+ -- Fetch DNSKEY immediately
+ if not trust_anchors.keysets['\0'] then
+ trust_anchors.keysets['\0'] = { owner = '\0' }
+ end
+ local keyset = trust_anchors.keysets['\0']
+ keyset.filename = path
+ if keyset.refresh_ev then event.cancel(keyset.refresh_ev) end
+ refresh_plan(keyset, 0, true)
+ return
+ end
+ if not unmanaged and path == (trust_anchors.keysets['\0'] or {}).filename then
+ return
+ end
+
+ -- Parse the file and check its sanity
+ local keyset, err = keyset_read(path)
+ if not keyset then
+ panic("[ ta ] ERROR: failed to read anchors from '%s' (%s)", path, err)
+ end
+ if not unmanaged then keyset.filename = path end
+ if not keyset[1] then
+ panic("[ ta ] ERROR: failed to read anchors from '%s'", path)
+ end
+ if not unmanaged then keyset.filename = path end
+ local owner = keyset[1].owner
+ for _, ta in ipairs(keyset) do
+ if ta.owner ~= owner then
+ panic("[ ta ] ERROR: mixed owner names found in file '%s'! " ..
+ "Do not mix %s and %s TAs in single file",
+ path, kres.dname2str(ta.owner), kres.dname2str(owner))
+ end
+ end
+ keyset.owner = owner
+
+ local owner_str = kres.dname2str(owner)
+ if trust_anchors.keysets[owner] then
+ warn('[ ta ] warning: overriding previously set trust anchors for ' .. owner_str)
+ local refresh_ev = trust_anchors.keysets[owner].refresh_ev
+ if refresh_ev then event.cancel(refresh_ev) end
+ end
+ trust_anchors.keysets[owner] = keyset
+
+ -- Parse new keys, refresh eventually
+ if keyset_publish(keyset) ~= 0 and verbose() then
+ log('[ ta ] installed trust anchors for domain ' .. owner_str .. ' are:\n'
+ .. trust_anchors.summary(owner))
+ end
+ -- TODO: if failed and for root, try to rebootstrap?
+
+ refresh_plan(keyset, 10 * sec, false)
+end
+
+local function ta_str(owner)
+ local owner_str = kres.dname2str(owner) .. ' '
+ local msg = ''
+ for _, nta in pairs(trust_anchors.insecure) do
+ if owner == kres.str2dname(nta) then
+ msg = owner_str .. 'is negative trust anchor\n'
+ end
+ end
+ if not trust_anchors.keysets[owner] then
+ if #msg > 0 then -- it is normal that NTA does not have explicit TA
+ return msg
+ else
+ return owner_str .. 'has no explicit trust anchors\n'
+ end
+ end
+ if #msg > 0 then
+ msg = msg .. 'WARNING! negative trust anchor also has an explicit TA\n'
+ end
+ for _, ta in ipairs(trust_anchors.keysets[owner]) do
+ msg = msg .. kres.rr2str(ta) .. '\n'
+ end
+ return msg
+end
+
+-- TA store management, for user docs see ../README.rst
+trust_anchors = {
+ -- [internal] table indexed by dname;
+ -- each item is a list of RRs and additionally contains:
+ -- - owner - that dname (for simplicity)
+ -- - [optional] filename in which to persist the state
+ -- - [optional] overrides for global defaults of
+ -- hold_down_time, refresh_time, keep_removed
+ -- The RR tables also contain some additional TA-specific fields.
+ keysets = {},
+
+ -- Documented properties:
+ insecure = {},
+ hold_down_time = 30 * day,
+ refresh_time = nil,
+ keep_removed = 0,
+
+ bootstrap_url = 'https://data.iana.org/root-anchors/root-anchors.xml',
+ bootstrap_ca = '@ETCDIR@/icann-ca.pem',
+ -- change empty string to nil
+ keyfile_default = ('@KEYFILE_DEFAULT@' ~= '' and '@KEYFILE_DEFAULT@') or nil,
+
+ -- Load keys from a file, 5011-managed by default.
+ -- If managed and the file doesn't exist, try bootstrapping the root into it.
+ add_file = add_file,
+ config = add_file,
+
+ -- Add DS/DNSKEY record(s) (unmanaged)
+ add = function (keystr)
+ local ret = trustanchor(keystr)
+ if verbose() then log(trust_anchors.summary()) end
+ return ret
+ end,
+ -- Negative TA management
+ set_insecure = function (list)
+ assert(type(list) == 'table', 'parameter must be list of domain names (e.g. {"a.test", "b.example"})')
+ local store = kres.context().negative_anchors
+ C.kr_ta_clear(store)
+ for i = 1, #list do
+ local dname = kres.str2dname(list[i])
+ C.kr_ta_add(store, dname, kres.type.DS, 0, nil, 0)
+ end
+ trust_anchors.insecure = list
+ end,
+ summary = function (single_owner)
+ if single_owner then -- single domain
+ return ta_str(single_owner)
+ end
+
+ -- all domains
+ local msg = ''
+ local ta_count = 0
+ local seen = {}
+ for _, nta_str in pairs(trust_anchors.insecure) do
+ local owner = kres.str2dname(nta_str)
+ seen[owner] = true
+ msg = msg .. ta_str(owner)
+ end
+ for owner, _ in pairs(trust_anchors.keysets) do
+ if not seen[owner] then
+ ta_count = ta_count + 1
+ msg = msg .. ta_str(owner)
+ end
+ end
+ if ta_count == 0 then
+ msg = msg .. 'No valid trust anchors, DNSSEC validation is disabled\n'
+ end
+ return msg
+ end,
+}
+
+-- Syntactic sugar for TA store
+setmetatable(trust_anchors, {
+ __newindex = function (t,k,v)
+ if k == 'file' then t.config(v)
+ elseif k == 'negative' then t.set_insecure(v)
+ else rawset(t, k, v) end
+ end,
+})
+
+return trust_anchors
diff --git a/daemon/lua/trust_anchors.test/bootstrap.test.lua b/daemon/lua/trust_anchors.test/bootstrap.test.lua
new file mode 100644
index 0000000..d5d0218
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/bootstrap.test.lua
@@ -0,0 +1,108 @@
+-- check prerequisites
+local has_http = pcall(require, 'http') and pcall(require, 'http.request')
+if not has_http then
+ pass('skipping bootstrap tests because http module is not not installed')
+ done()
+end
+
+local cqueues = require("cqueues")
+local socket = require("cqueues.socket")
+
+-- unload modules which are not related to this test
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+if priming then
+ modules.unload('priming')
+end
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function () return 1 end)
+event.cancel(ev)
+ev = event.after(0, function () return 1 end)
+
+
+-- do not attempt to contact outside world using DNS, operate only on cache
+net.ipv4 = false
+net.ipv6 = false
+-- do not listen, test is driven by config code
+env.KRESD_NO_LISTEN = true
+
+-- start test webserver
+local function start_webserver()
+ -- srvout = io.popen('luajit webserv.lua')
+ -- TODO
+ os.execute('luajit webserv.lua &')
+ -- assert(srvout, 'failed to start webserver')
+end
+
+local function wait_for_webserver()
+ local starttime = os.time()
+ local connected = false
+ while not connected and os.difftime(os.time(), starttime) < 5 do
+ local con = socket.connect("localhost", 8080)
+ connected, msg = pcall(con.connect, con, 5)
+ cqueues.sleep (0.3)
+ end
+ assert(connected, string.format('unable to connect to web server: %s', msg))
+end
+
+local host = 'https://localhost:8080/'
+-- avoid interference with configured KEYFILE_DEFAULT
+trust_anchors.keyfile_default = nil
+
+local function test_err_cert()
+ trust_anchors.bootstrap_ca = 'x509/wrongca.pem'
+ trust_anchors.bootstrap_url = host .. 'ok1.xml'
+ boom(trust_anchors.add_file, {'ok1.keys'},
+ 'fake server certificate is detected')
+end
+
+local function test_err_xml(testname, testdesc)
+ return function()
+ trust_anchors.bootstrap_ca = 'x509/ca.pem'
+ trust_anchors.bootstrap_url = host .. testname .. '.xml'
+ boom(trust_anchors.add_file, {testname .. '.keys'}, testdesc)
+ end
+end
+
+-- dumb test, right now it cannot check content of keys because
+-- it does not get written until refresh fetches DNSKEY from network
+-- (and bypassing network using policy bypasses also validation
+-- so it does not test anything)
+local function test_ok_xml(testname, testdesc)
+ return function()
+ trust_anchors.bootstrap_url = host .. testname .. '.xml'
+ same(trust_anchors.add_file(testname .. '.keys'), nil, testdesc)
+ end
+end
+
+return {
+ start_webserver,
+ wait_for_webserver,
+ test_err_cert,
+ test_err_xml('err_attr_extra_attr', 'bogus TA XML with an extra attribute'),
+ test_err_xml('err_attr_validfrom_invalid', 'bogus TA XML with invalid validFrom value'),
+ test_err_xml('err_attr_validfrom_missing', 'bogus TA XML without mandatory validFrom attribute'),
+ test_err_xml('err_elem_extra', 'bogus TA XML with an extra element'),
+ test_err_xml('err_elem_missing', 'bogus TA XML without mandatory element'),
+ test_err_xml('err_multi_ta', 'bogus TA XML with multiple TAs'),
+ test_err_xml('unsupp_nonroot', 'unsupported TA XML for non-root zone'),
+ test_err_xml('unsupp_xml_v11', 'unsupported TA XML with XML v1.1'),
+ test_err_xml('ok0_badtimes', 'TA XML with no valid keys'),
+ test_ok_xml('ok1_expired1', 'TA XML with 1 valid and 1 expired key'),
+ test_ok_xml('ok1_notyet1', 'TA XML with 1 valid and 1 not yet valid key'),
+ test_ok_xml('ok1', 'TA XML with 1 valid key'),
+ test_ok_xml('ok2', 'TA XML with 2 valid keys'),
+}
diff --git a/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml b/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml
new file mode 100644
index 0000000..2a87957
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="FC4A93EC-9F4E-4597-A766-AD6723E4A56E" source="https://localhost/err_attr_extra_attr.xml">
+<Zone>.</Zone>
+<KeyDigest unknownattr="test" id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml b/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml
new file mode 100644
index 0000000..5a4c68c
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="ABD668AB-52DF-4A59-80E3-16CE6341BC55" source="https://localhost/err_attr_validfrom_invalid.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-32T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml b/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml
new file mode 100644
index 0000000..1261b09
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="3513058C-4041-40CC-AF0A-D3CCD70F962B" source="https://localhost/err_attr_validfrom_missing.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_elem_extra.xml b/daemon/lua/trust_anchors.test/err_elem_extra.xml
new file mode 100644
index 0000000..150a3b1
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_elem_extra.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="B1854D58-1867-4FA7-872F-0099D394114D" source="https://localhost/err_elem_extra.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+<UnknownElement>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</UnknownElement>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_elem_missing.xml b/daemon/lua/trust_anchors.test/err_elem_missing.xml
new file mode 100644
index 0000000..899e1d0
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_elem_missing.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="BB074095-3A42-4B13-9CC1-CFFF644D4D54" source="https://localhost/err_elem_missing.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<!-- this element is missing: DigestType>2</DigestType-->
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_multi_ta.xml b/daemon/lua/trust_anchors.test/err_multi_ta.xml
new file mode 100644
index 0000000..20cd73f
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_multi_ta.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="9DCE46E1-FC78-48E1-81B5-94E328790BB5" source="https://localhost/err_multi_ta.xml">
+<Zone>.</Zone>
+<KeyDigest id="1" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
+<TrustAnchor id="9DCE46E1-FC78-48E1-81B5-94E328790BB5" source="https://localhost/err_multi_ta.xml">
+<Zone>test.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok0_badtimes.xml b/daemon/lua/trust_anchors.test/ok0_badtimes.xml
new file mode 100644
index 0000000..4535a41
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok0_badtimes.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="EDEDAA08-D2A0-421E-81DC-AF11F5A0CDCD" source="https://localhost/ok0_badtimes.xml">
+<Zone>.</Zone>
+<KeyDigest id="E" validFrom="2000-01-01T00:00:00+00:00" validUntil="2000-01-01T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE</Digest>
+</KeyDigest>
+<KeyDigest id="F" validFrom="2001-01-01T00:00:00+00:00" validUntil="2001-01-01T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1.xml b/daemon/lua/trust_anchors.test/ok1.xml
new file mode 100644
index 0000000..117495c
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="82E6CB77-12DF-4E61-BF49-367FB95A8BAA" source="https://localhost/ok1.xml">
+<Zone>.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1_expired1.xml b/daemon/lua/trust_anchors.test/ok1_expired1.xml
new file mode 100644
index 0000000..f1269da
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1_expired1.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="68463155-A857-4C7E-BCA6-2F6CC2EAC1BE" source="https://localhost/ok1_expired1.xml">
+<Zone>.</Zone>
+<KeyDigest id="F" validFrom="1990-01-01T00:00:00+00:00" validUntil="2000-01-01T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+<KeyDigest id="1" validFrom="2000-01-01T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1_notyet1.xml b/daemon/lua/trust_anchors.test/ok1_notyet1.xml
new file mode 100644
index 0000000..7b5881b
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1_notyet1.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="507B39D5-049E-467C-9E9A-F5BE597C9DDA" source="https://localhost/ok1_notyet1.xml">
+<Zone>.</Zone>
+<KeyDigest id="1" validFrom="2010-07-15T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+<KeyDigest id="2" validFrom="2050-12-31T23:59:59+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok2.xml b/daemon/lua/trust_anchors.test/ok2.xml
new file mode 100644
index 0000000..149f6b5
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok2.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="1DECEB91-0591-44A1-95CF-1788337514B8" source="https://localhost/ok2.xml">
+<Zone>.</Zone>
+<KeyDigest id="K1" validFrom="2010-07-15T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+<KeyDigest id="K2" validFrom="2011-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>2222222222222222222222222222222222222222222222222222222222222222</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/regen.sh b/daemon/lua/trust_anchors.test/regen.sh
new file mode 100755
index 0000000..09b334c
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/regen.sh
@@ -0,0 +1,2 @@
+for F in *.xml; do sed -i "s/TrustAnchor id=\"[^\"]*\"/TrustAnchor id=\"$(uuidgen | tr '[[:lower:]]' '[[:upper:]]')\"/" $F; done
+for F in *.xml; do sed -i "s#source=\"[^\"]*\"#source=\"https://localhost/$F\"#" $F; done
diff --git a/daemon/lua/trust_anchors.test/unsupp_nonroot.xml b/daemon/lua/trust_anchors.test/unsupp_nonroot.xml
new file mode 100644
index 0000000..51b3c0a
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/unsupp_nonroot.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="8449BFB8-FD6C-4082-B0FE-1A3E3399203B" source="https://localhost/unsupp_nonroot.xml">
+<Zone>test.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml b/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml
new file mode 100644
index 0000000..87a4b57
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml
@@ -0,0 +1,10 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<TrustAnchor id="3612AE1C-E8F3-4FD8-B8CD-96C7FDACC7A5" source="https://localhost/unsupp_xml_v11.xml">
+<Zone>.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/webserv.lua b/daemon/lua/trust_anchors.test/webserv.lua
new file mode 100644
index 0000000..458d3e5
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/webserv.lua
@@ -0,0 +1,234 @@
+-- This is a module that does the heavy lifting to provide an HTTP/2 enabled
+-- server that supports TLS by default and provides endpoint for other modules
+-- in order to enable them to export restful APIs and websocket streams.
+-- One example is statistics module that can stream live metrics on the website,
+-- or publish metrics on request for Prometheus scraper.
+local http_server = require('http.server')
+local http_headers = require('http.headers')
+local http_websocket = require('http.websocket')
+local http_util = require "http.util"
+local x509, pkey = require('openssl.x509'), require('openssl.pkey')
+
+-- Module declaration
+local M = {}
+
+-- Export HTTP service endpoints
+M.endpoints = {
+ ['/'] = {'text/html', 'test'},
+}
+
+-- Serve known requests, for methods other than GET
+-- the endpoint must be a closure and not a preloaded string
+local function serve(endpoints, h, stream)
+ local hsend = http_headers.new()
+ local path = h:get(':path')
+ local entry = endpoints[path]
+ if not entry then -- Accept top-level path match
+ entry = endpoints[path:match '^/[^/?]*']
+ end
+ -- Unpack MIME and data
+ local data, mime, ttl, err
+ if entry then
+ mime = entry[1]
+ data = entry[2]
+ ttl = entry[4]
+ end
+ -- Get string data out of service endpoint
+ if type(data) == 'function' then
+ local set_mime, set_ttl
+ data, err, set_mime, set_ttl = data(h, stream)
+ -- Override default endpoint mime/TTL
+ if set_mime then mime = set_mime end
+ if set_ttl then ttl = set_ttl end
+ -- Handler doesn't provide any data
+ if data == false then return end
+ if type(data) == 'number' then return tostring(data), err end
+ -- Methods other than GET require handler to be closure
+ elseif h:get(':method') ~= 'GET' then
+ return '501', ''
+ end
+ if not mime or type(data) ~= 'string' then
+ return '404', ''
+ else
+ -- Serve content type appropriately
+ hsend:append(':status', '200')
+ hsend:append('content-type', mime)
+ hsend:append('content-length', tostring(#data))
+ if ttl then
+ hsend:append('cache-control', string.format('max-age=%d', ttl))
+ end
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(data, true))
+ end
+end
+
+-- Web server service closure
+local function route(endpoints)
+ return function (_, stream)
+ -- HTTP/2: We're only permitted to send in open/half-closed (remote)
+ local connection = stream.connection
+ if connection.version >= 2 then
+ if stream.state ~= 'open' and stream.state ~= 'half closed (remote)' then
+ return
+ end
+ end
+ -- Start reading headers
+ local h = assert(stream:get_headers())
+ local m = h:get(':method')
+ local path = h:get(':path')
+ -- Upgrade connection to WebSocket
+ local ws = http_websocket.new_from_stream(stream, h)
+ if ws then
+ assert(ws:accept { protocols = {'json'} })
+ -- Continue streaming results to client
+ local ep = endpoints[path]
+ local cb = ep[3]
+ if cb then
+ cb(h, ws)
+ end
+ ws:close()
+ return
+ else
+ local ok, err, reason = http_util.yieldable_pcall(serve, endpoints, h, stream)
+ if not ok or err then
+ print(string.format('%s err %s %s: %s (%s)', os.date(), m, path, err or '500', reason))
+ -- Method is not supported
+ local hsend = http_headers.new()
+ hsend:append(':status', err or '500')
+ if reason then
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(reason, true))
+ else
+ assert(stream:write_headers(hsend, true))
+ end
+ else
+ print(string.format('%s ok %s %s', os.date(), m, path))
+ end
+ end
+ end
+end
+
+-- @function Prefer HTTP/2 or HTTP/1.1
+local function alpnselect(_, protos)
+ for _, proto in ipairs(protos) do
+ if proto == 'h2' or proto == 'http/1.1' then
+ return proto
+ end
+ end
+ return nil
+end
+
+-- @function Create TLS context
+local function tlscontext(crt, key)
+ local http_tls = require('http.tls')
+ local ctx = http_tls.new_server_context()
+ if ctx.setAlpnSelect then
+ ctx:setAlpnSelect(alpnselect)
+ end
+ assert(ctx:setPrivateKey(key))
+ assert(ctx:setCertificate(crt))
+ return ctx
+end
+
+-- @function Listen on given HTTP(s) host
+function M.add_interface(conf)
+ local crt, key
+ if conf.tls ~= false then
+ assert(conf.cert, 'cert missing')
+ assert(conf.key, 'private key missing')
+ -- Check if a cert file was specified
+ -- Read x509 certificate
+ local f = io.open(conf.cert, 'r')
+ if f then
+ crt = assert(x509.new(f:read('*all')))
+ f:close()
+ -- Continue reading key file
+ if crt then
+ f = io.open(conf.key, 'r')
+ key = assert(pkey.new(f:read('*all')))
+ f:close()
+ end
+ end
+ -- Check loaded certificate
+ assert(crt and key,
+ string.format('failed to load certificate "%s"', conf.cert))
+ end
+ -- Compose server handler
+ local routes = route(conf.endpoints or M.endpoints)
+ -- Check if UNIX socket path is used
+ local addr_str
+ if not conf.path then
+ conf.host = conf.host or 'localhost'
+ conf.port = conf.port or 8053
+ addr_str = string.format('%s@%d', conf.host, conf.port)
+ else
+ if conf.host or conf.port then
+ error('either "path", or "host" and "port" must be provided')
+ end
+ addr_str = conf.path
+ end
+ -- Create TLS context and start listening
+ local s, err = http_server.listen {
+ -- cq = worker.bg_worker.cq,
+ host = conf.host,
+ port = conf.port,
+ path = conf.path,
+ v6only = conf.v6only,
+ unlink = conf.unlink,
+ reuseaddr = conf.reuseaddr,
+ reuseport = conf.reuseport,
+ client_timeout = conf.client_timeout or 5,
+ ctx = crt and tlscontext(crt, key),
+ tls = conf.tls,
+ onstream = routes,
+ -- Log errors, but do not throw
+ onerror = function(myserver, context, op, err, errno) -- luacheck: ignore 212
+ local msg = '[http] ' .. op .. ' on ' .. tostring(context) .. ' failed'
+ if err then
+ msg = msg .. ': ' .. tostring(err)
+ end
+ print(msg)
+ end,
+ }
+ -- Manually call :listen() so that we are bound before calling :localname()
+ if s then
+ err = select(2, s:listen())
+ end
+ assert(not err, string.format('failed to listen on %s: %s', addr_str, err))
+ return s
+end
+
+-- init
+local files = {
+ 'ok0_badtimes.xml',
+ 'ok1.xml',
+ 'ok1_expired1.xml',
+ 'ok1_notyet1.xml',
+ 'ok2.xml',
+ 'err_attr_validfrom_missing.xml',
+ 'err_attr_validfrom_invalid.xml',
+ 'err_attr_extra_attr.xml',
+ 'err_elem_missing.xml',
+ 'err_elem_extra.xml',
+ 'err_multi_ta.xml',
+ 'unsupp_nonroot.xml',
+ 'unsupp_xml_v11.xml'
+}
+
+-- Export static pages specified at command line
+for _, name in ipairs(files) do
+ local fd = io.open(name)
+ assert(fd, string.format('unable to open file "%s"', name))
+ M.endpoints['/' .. name] = { 'text/xml', fd:read('*a') }
+ fd:close()
+end
+
+local server = M.add_interface({
+ host = 'localhost',
+ port = 8080,
+ tls = true,
+ cert = 'x509/server.pem',
+ key = 'x509/server-key.pem'
+ })
+
+server:loop()
diff --git a/daemon/lua/trust_anchors.test/x509/ca-key.pem b/daemon/lua/trust_anchors.test/x509/ca-key.pem
new file mode 100644
index 0000000..28b1f52
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:cd:d7:b2:a4:37:ae:47:8b:c2:e2:24:7a:2e:77:4a
+ 9a:aa:8e:5a:f5:68:80:f0:7c:68:08:50:30:3a:f9:77
+ bb:99:a6:67:f7:ce:45:6a:c9:11:43:81:4e:a7:92:53
+ 58:53:0c:76:fe:81:9c:a5:c8:32:e9:2e:5d:1d:16:3e
+ 5d:b2:21:c6:65:d7:33:c1:04:81:7a:8e:8c:c7:2e:8c
+ d0:73:bf:37:43:b7:1b:07:90:cb:a3:6e:7c:67:76:be
+ b0:20:28:5b:5d:d7:b3:b2:09:5e:2b:23:76:fd:32:26
+ c7:cf:de:e8:0c:5b:c2:bc:a8:52:e2:58:56:89:ad:57
+ 63:b0:01:86:b3:d1:3d:e0:6c:13:ff:b5:e6:37:f4:87
+ 64:f5:d8:9e:8c:7d:48:43:60:5c:bb:bb:73:cc:d3:3f
+ ad:76:44:ff:08:25:b8:dc:c4:47:c2:29:29:b8:00:4b
+ a7:01:84:93:40:9c:80:35:78:7d:b2:bb:70:58:b8:7a
+ d9:60:7c:e6:d6:66:36:cb:62:4d:84:e8:b9:9e:62:2f
+ 97:2c:cd:c2:28:6e:32:a5:c9:33:a1:8d:96:41:05:5c
+ 84:7a:82:80:4e:df:8b:98:75:ba:84:84:a3:c7:9c:41
+ c8:19:d8:af:37:28:f2:e8:c2:dc:b9:b2:fa:7c:26:b6
+ 31:bd:2f:e7:c3:aa:5d:c4:03:fb:db:42:3d:fe:2e:15
+ 9e:23:40:b2:e5:e1:7e:a0:e1:5d:d7:ff:aa:ed:e9:09
+ 99:55:2d:48:4c:67:95:b6:3f:d8:87:c7:b3:b6:ae:b0
+ 45:42:9c:6a:3f:a7:8e:d2:79:e7:2e:51:d6:f1:25:e8
+ 4f:4a:e4:cc:4e:2e:ae:d7:a6:b2:8a:d5:5d:76:42:ff
+ 19:eb:0d:b9:a0:8c:76:ed:9d:e6:e9:83:0c:35:d7:d3
+ 4c:16:2a:6b:25:1f:7a:f1:6d:6f:33:cf:21:8c:9f:a8
+ 43:0b:11:d3:da:cf:ec:1e:64:54:c1:3e:12:13:f1:eb
+ b5:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 00:ab:ca:e1:64:fc:b3:8f:32:ad:ab:5f:16:39:c1:85
+ 9a:1f:ce:3f:4b:a1:b4:3b:01:19:32:16:fa:a9:bd:9a
+ 98:0f:5c:3a:59:2e:e5:f0:81:6e:cf:10:14:3c:f6:7a
+ 68:b4:a7:2a:88:ae:53:b6:68:a7:54:c5:45:21:09:77
+ 73:6b:3f:94:fd:59:e5:ef:a9:7b:06:76:02:38:1a:39
+ 9b:9f:7e:6e:f9:2c:d0:7a:37:f6:3c:a7:f1:5b:c8:56
+ cd:57:89:56:f7:b3:16:5d:f8:43:87:6d:49:d9:77:09
+ b6:a9:5e:37:fc:58:78:e6:4a:f5:21:c2:e8:36:6f:5d
+ 07:ed:d4:d8:3f:2a:da:a1:7a:92:16:50:11:9b:91:91
+ 8e:49:40:48:d2:a7:9c:af:de:b4:86:59:a4:03:c6:2a
+ d6:f2:66:13:13:11:a8:7f:57:b1:2b:f2:7e:c6:fa:38
+ 29:61:b2:eb:d2:78:ca:e7:d5:6f:d2:c3:6c:b8:1e:ff
+ 26:fc:47:62:46:b6:03:c1:d9:a0:03:4f:16:5f:fe:65
+ e7:56:a2:21:38:b0:34:17:45:00:56:26:e8:5e:8b:fe
+ e0:fc:fc:a0:3e:2c:00:fb:c3:f8:dc:07:05:73:59:59
+ fd:b6:7a:c3:cd:4d:da:5a:1c:38:17:2e:15:8f:50:18
+ 52:bb:d2:a9:fe:88:6f:d2:71:d3:7e:74:85:a3:88:ba
+ 99:79:4c:ce:36:23:63:0a:17:16:00:da:fb:76:fb:90
+ bb:c1:08:77:43:0d:ce:81:a8:89:47:ea:bc:f0:40:65
+ 07:0d:d0:9c:5e:02:b5:2b:89:cb:65:56:c3:24:b0:e1
+ 39:30:20:aa:03:4c:20:7b:36:14:24:cb:8b:64:74:fc
+ 00:2e:de:d6:d1:9b:93:17:d1:98:37:7f:6a:cd:42:d3
+ 20:b2:92:2e:96:1e:3c:04:3e:99:1c:c7:03:d4:b9:87
+ 98:e2:a5:41:b8:3f:0c:1a:94:54:16:4d:2b:83:58:de
+ 01:
+
+prime1:
+ 00:f9:82:8d:c3:92:3d:bd:52:6b:ff:4e:0b:97:b3:8f
+ a2:56:53:49:05:1e:5b:20:cc:1b:fc:a4:0e:eb:ad:ce
+ 1f:79:7a:3c:e6:b3:6d:1e:1a:bf:5a:01:76:c9:14:6c
+ 0b:2d:6e:b2:56:55:b4:4d:f8:da:15:68:eb:07:59:43
+ c7:de:8b:01:14:8f:6d:3b:c5:d6:7d:86:f1:ba:9a:88
+ 0c:bc:06:96:2a:94:59:d4:e1:eb:15:dd:20:9e:98:78
+ 58:ca:ef:19:a7:52:c4:a0:35:91:d8:0b:3b:d2:93:aa
+ 60:bc:44:c3:a5:ac:1c:f4:38:3e:60:79:da:c3:53:9a
+ 6b:87:87:77:36:09:a1:27:b2:60:3e:aa:f3:73:d4:a7
+ af:f7:74:9e:c7:19:b1:e4:75:ed:79:56:67:53:05:1c
+ 4e:55:f5:be:6a:9c:3a:4b:15:73:55:90:7c:a2:e9:45
+ 07:d5:eb:a0:3f:da:d6:7f:ae:4b:62:6d:b5:8d:af:48
+ 31:
+
+prime2:
+ 00:d3:32:5e:b2:ef:2e:bf:d1:57:85:28:bb:5c:37:c0
+ 8a:ed:46:47:23:4e:22:72:2f:de:0a:a6:36:64:8f:9e
+ f5:67:a3:5d:d4:2d:2b:e2:3c:c7:b8:0c:79:37:bf:e6
+ 67:96:84:4c:be:98:1f:86:e0:3d:c9:4a:b6:50:de:2f
+ 90:61:25:74:49:ff:33:a7:93:3a:12:2b:c2:2c:38:29
+ 9f:16:d8:20:16:77:e6:04:27:23:44:35:5a:a2:a1:72
+ 40:91:b6:39:5f:e6:57:9f:59:6a:e4:5c:da:50:c7:4f
+ fe:df:1f:40:3c:e7:05:f6:f9:52:e9:c4:2c:e0:68:46
+ 47:6e:52:76:bc:c1:19:7c:2d:50:2f:ef:53:e1:67:7c
+ b8:7e:84:72:6d:60:2c:ff:ff:7f:7a:ec:1e:54:8c:b1
+ a8:64:0b:54:f5:c3:4e:dd:dc:22:3b:54:05:7f:cc:32
+ 64:d5:87:15:9f:f8:9f:07:83:4e:a0:d2:13:48:6b:be
+ c5:
+
+coefficient:
+ 2e:c4:04:3b:cf:3f:4a:dd:f0:32:e4:fc:93:fe:ef:b8
+ 83:14:8e:a9:6b:ba:73:28:b6:b1:49:57:67:d7:ca:39
+ f0:da:23:99:df:3d:9b:8c:7b:c9:9a:fe:22:69:29:87
+ a3:ad:2a:6b:a7:5a:42:09:57:fd:8e:55:0a:1a:e9:36
+ 02:e7:b3:47:82:41:c1:21:b2:8b:6a:35:30:60:17:c3
+ a5:3b:cc:2a:cb:e1:7a:23:14:6c:8a:87:29:49:8a:0a
+ c3:34:a8:aa:64:92:74:82:f1:01:3a:00:2e:bf:d6:d3
+ 00:86:01:ee:84:83:42:8d:c7:b0:88:ac:62:12:9d:b5
+ 18:28:76:13:34:24:92:fb:a9:57:e5:4c:8a:a9:bb:73
+ a5:02:64:9b:73:4c:18:6b:29:e4:ba:04:da:66:ef:b4
+ 0c:46:fd:55:ff:62:5b:76:80:a9:13:29:c1:4b:43:51
+ 0b:44:d3:01:9d:c5:e5:6b:ac:a0:e5:b9:0c:41:08:49
+
+
+exp1:
+ 00:9d:50:d4:63:4f:cc:7f:96:fd:22:de:a9:6e:7f:b7
+ 7b:4a:64:7e:b0:ac:80:16:80:ba:d0:a2:fc:09:5a:ef
+ 90:66:be:4c:b1:c4:c5:72:ea:b8:65:5e:70:ef:bd:61
+ 95:f6:92:49:fd:27:52:64:ab:17:8d:d2:36:05:cf:21
+ 6e:5e:81:54:30:0b:72:7a:f2:75:17:76:42:e9:3d:cf
+ b3:ff:c5:43:5f:1b:64:3c:56:29:2c:02:dd:33:41:bc
+ f7:77:14:24:1f:9c:8e:fe:d8:67:d9:48:d3:f2:24:4a
+ 93:6d:81:09:be:66:73:67:04:23:48:1e:ec:70:a5:40
+ c2:b5:94:12:f4:ce:43:7e:cc:f7:e3:eb:53:4e:5f:f1
+ 4e:80:7e:56:32:00:a0:6a:04:74:b3:41:68:2a:2f:19
+ b6:c6:7a:08:12:1d:e8:9f:38:aa:1c:73:da:31:b9:54
+ 5d:e9:62:04:0a:de:c6:c9:80:32:65:9f:f8:8d:99:cb
+ b1:
+
+exp2:
+ 77:f1:8f:5e:c8:00:20:e8:5f:70:3c:a5:cb:c5:ce:10
+ 18:99:65:25:63:e6:a4:3b:13:3b:b1:12:0b:22:96:00
+ 81:8f:82:66:52:11:2e:37:9e:a5:a4:4f:e3:9d:94:d9
+ 17:de:a3:47:4b:55:fc:5f:b6:37:6f:bb:03:4a:6c:70
+ ee:fb:3a:84:1b:ef:d6:28:03:3e:f6:a3:1c:41:f9:41
+ 64:d3:f1:c5:50:ea:cd:48:fc:fa:6b:e2:c1:a2:37:24
+ fc:9c:25:11:95:dc:05:9f:de:d9:3a:f2:b2:15:c0:14
+ db:da:ff:bc:96:e8:08:4f:a9:0b:22:62:ea:3f:ce:4a
+ 1b:19:b2:5d:98:bd:44:8c:e7:91:91:b6:6d:b9:3c:57
+ fb:62:75:2a:31:08:dd:8a:d9:77:92:49:d7:72:e0:22
+ e6:4e:99:3d:ca:62:2c:16:2d:4a:cc:79:23:0f:71:3f
+ 5b:15:90:ee:7d:60:b3:ff:9a:d4:32:fa:c8:92:88:91
+
+
+
+Public Key PIN:
+ pin-sha256:D8K7fp8E6Fsg1NjgFkNjJA/Mow1IQUvondTb816FnDc=
+Public Key ID:
+ sha256:0fc2bb7e9f04e85b20d4d8e0164363240fcca30d48414be89dd4dbf35e859c37
+ sha1:3017e1bccfde068e418672642d1e181a90988264
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG5AIBAAKCAYEAzdeypDeuR4vC4iR6LndKmqqOWvVogPB8aAhQMDr5d7uZpmf3
+zkVqyRFDgU6nklNYUwx2/oGcpcgy6S5dHRY+XbIhxmXXM8EEgXqOjMcujNBzvzdD
+txsHkMujbnxndr6wIChbXdezsgleKyN2/TImx8/e6AxbwryoUuJYVomtV2OwAYaz
+0T3gbBP/teY39Idk9diejH1IQ2Bcu7tzzNM/rXZE/wgluNzER8IpKbgAS6cBhJNA
+nIA1eH2yu3BYuHrZYHzm1mY2y2JNhOi5nmIvlyzNwihuMqXJM6GNlkEFXIR6goBO
+34uYdbqEhKPHnEHIGdivNyjy6MLcubL6fCa2Mb0v58OqXcQD+9tCPf4uFZ4jQLLl
+4X6g4V3X/6rt6QmZVS1ITGeVtj/Yh8eztq6wRUKcaj+njtJ55y5R1vEl6E9K5MxO
+Lq7XprKK1V12Qv8Z6w25oIx27Z3m6YMMNdfTTBYqayUfevFtbzPPIYyfqEMLEdPa
+z+weZFTBPhIT8eu1AgMBAAECggGBAKvK4WT8s48yratfFjnBhZofzj9LobQ7ARky
+FvqpvZqYD1w6WS7l8IFuzxAUPPZ6aLSnKoiuU7Zop1TFRSEJd3NrP5T9WeXvqXsG
+dgI4Gjmbn35u+SzQejf2PKfxW8hWzVeJVvezFl34Q4dtSdl3CbapXjf8WHjmSvUh
+wug2b10H7dTYPyraoXqSFlARm5GRjklASNKnnK/etIZZpAPGKtbyZhMTEah/V7Er
+8n7G+jgpYbLr0njK59Vv0sNsuB7/JvxHYka2A8HZoANPFl/+ZedWoiE4sDQXRQBW
+Juhei/7g/PygPiwA+8P43AcFc1lZ/bZ6w81N2locOBcuFY9QGFK70qn+iG/ScdN+
+dIWjiLqZeUzONiNjChcWANr7dvuQu8EId0MNzoGoiUfqvPBAZQcN0JxeArUrictl
+VsMksOE5MCCqA0wgezYUJMuLZHT8AC7e1tGbkxfRmDd/as1C0yCyki6WHjwEPpkc
+xwPUuYeY4qVBuD8MGpRUFk0rg1jeAQKBwQD5go3Dkj29Umv/TguXs4+iVlNJBR5b
+IMwb/KQO663OH3l6POazbR4av1oBdskUbAstbrJWVbRN+NoVaOsHWUPH3osBFI9t
+O8XWfYbxupqIDLwGliqUWdTh6xXdIJ6YeFjK7xmnUsSgNZHYCzvSk6pgvETDpawc
+9Dg+YHnaw1Oaa4eHdzYJoSeyYD6q83PUp6/3dJ7HGbHkde15VmdTBRxOVfW+apw6
+SxVzVZB8oulFB9XroD/a1n+uS2JttY2vSDECgcEA0zJesu8uv9FXhSi7XDfAiu1G
+RyNOInIv3gqmNmSPnvVno13ULSviPMe4DHk3v+ZnloRMvpgfhuA9yUq2UN4vkGEl
+dEn/M6eTOhIrwiw4KZ8W2CAWd+YEJyNENVqioXJAkbY5X+ZXn1lq5FzaUMdP/t8f
+QDznBfb5UunELOBoRkduUna8wRl8LVAv71PhZ3y4foRybWAs//9/euweVIyxqGQL
+VPXDTt3cIjtUBX/MMmTVhxWf+J8Hg06g0hNIa77FAoHBAJ1Q1GNPzH+W/SLeqW5/
+t3tKZH6wrIAWgLrQovwJWu+QZr5MscTFcuq4ZV5w771hlfaSSf0nUmSrF43SNgXP
+IW5egVQwC3J68nUXdkLpPc+z/8VDXxtkPFYpLALdM0G893cUJB+cjv7YZ9lI0/Ik
+SpNtgQm+ZnNnBCNIHuxwpUDCtZQS9M5Dfsz34+tTTl/xToB+VjIAoGoEdLNBaCov
+GbbGeggSHeifOKocc9oxuVRd6WIECt7GyYAyZZ/4jZnLsQKBwHfxj17IACDoX3A8
+pcvFzhAYmWUlY+akOxM7sRILIpYAgY+CZlIRLjeepaRP452U2Rfeo0dLVfxftjdv
+uwNKbHDu+zqEG+/WKAM+9qMcQflBZNPxxVDqzUj8+mviwaI3JPycJRGV3AWf3tk6
+8rIVwBTb2v+8lugIT6kLImLqP85KGxmyXZi9RIznkZG2bbk8V/tidSoxCN2K2XeS
+Sddy4CLmTpk9ymIsFi1KzHkjD3E/WxWQ7n1gs/+a1DL6yJKIkQKBwC7EBDvPP0rd
+8DLk/JP+77iDFI6pa7pzKLaxSVdn18o58Nojmd89m4x7yZr+Imkph6OtKmunWkIJ
+V/2OVQoa6TYC57NHgkHBIbKLajUwYBfDpTvMKsvheiMUbIqHKUmKCsM0qKpkknSC
+8QE6AC6/1tMAhgHuhINCjcewiKxiEp21GCh2EzQkkvupV+VMiqm7c6UCZJtzTBhr
+KeS6BNpm77QMRv1V/2JbdoCpEynBS0NRC0TTAZ3F5WusoOW5DEEISQ==
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/ca.pem b/daemon/lua/trust_anchors.test/x509/ca.pem
new file mode 100644
index 0000000..70e0fd5
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEFzCCAn+gAwIBAgIUBSlZzv0lYdpFv+zOqzsn3zZn7q0wDQYJKoZIhvcNAQEL
+BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMB4XDTE5MDEw
+MzE2MjczM1oXDTIwMDEwMzE2MjczM1owIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZl
+ciB0ZXN0aW5nIENBMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzdey
+pDeuR4vC4iR6LndKmqqOWvVogPB8aAhQMDr5d7uZpmf3zkVqyRFDgU6nklNYUwx2
+/oGcpcgy6S5dHRY+XbIhxmXXM8EEgXqOjMcujNBzvzdDtxsHkMujbnxndr6wIChb
+XdezsgleKyN2/TImx8/e6AxbwryoUuJYVomtV2OwAYaz0T3gbBP/teY39Idk9die
+jH1IQ2Bcu7tzzNM/rXZE/wgluNzER8IpKbgAS6cBhJNAnIA1eH2yu3BYuHrZYHzm
+1mY2y2JNhOi5nmIvlyzNwihuMqXJM6GNlkEFXIR6goBO34uYdbqEhKPHnEHIGdiv
+Nyjy6MLcubL6fCa2Mb0v58OqXcQD+9tCPf4uFZ4jQLLl4X6g4V3X/6rt6QmZVS1I
+TGeVtj/Yh8eztq6wRUKcaj+njtJ55y5R1vEl6E9K5MxOLq7XprKK1V12Qv8Z6w25
+oIx27Z3m6YMMNdfTTBYqayUfevFtbzPPIYyfqEMLEdPaz+weZFTBPhIT8eu1AgMB
+AAGjQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4E
+FgQUMBfhvM/eBo5BhnJkLR4YGpCYgmQwDQYJKoZIhvcNAQELBQADggGBAMpUHwLa
+v9sDAkhZ+Wp/I5LdzP/7i4f/EI8tEh+GYeoWNvW9FkvaW1ydU6ZPx+j2hzZRCpIR
+WTT/w0dB7d+2EOUJKrytPpx5O/uYIYOqCYbWAYIF6Vdk0vakwmWSg9YsdwLfDHfI
+/K6vt3cIPLCzSXQdimHzKd4+6pXZcjsEFSpmueaHk08HGErEVeWgG3Ro3XwuBJNt
+9QUN7fF8DAi3705/NuoF1fR9MvuorR3KBgYKFO/7F6gxgTVHXfwK8iRN0YZLPU02
+eUUs7zq8FS87chuq9ABodBmsmkVI6671N57U8duxVacSuSHEyYdHamYznBdGnCMv
+GCvn0VyUuqXe45LoRK4um4MC/3tPp70bY1LqyWXoCLMOdnObzI341PXoFvI/ScYa
+La2lkRz4wMqBecM0fLOJqshdDt6ZgEP3YMHgIhM87VR4savECnfH+RHAIZt/oEEt
+dJmAC9H2f2/zoxIXcRrGbU2kB5wBYW69qRzlOOtScimCmHdtVK/iAzg4KQ==
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/ca.tmpl b/daemon/lua/trust_anchors.test/x509/ca.tmpl
new file mode 100644
index 0000000..6de507d
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca.tmpl
@@ -0,0 +1,3 @@
+cn = Knot Resolver testing CA
+ca
+cert_signing_key
diff --git a/daemon/lua/trust_anchors.test/x509/gen.sh b/daemon/lua/trust_anchors.test/x509/gen.sh
new file mode 100755
index 0000000..10ecad3
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/gen.sh
@@ -0,0 +1,11 @@
+# CA
+certtool --generate-privkey > ca-key.pem
+certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca.pem
+
+# server cert signed by CA above
+certtool --generate-privkey > server-key.pem
+certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server.pem
+
+# wrong CA - unrelated to others
+certtool --generate-privkey > wrongca-key.pem
+certtool --generate-self-signed --load-privkey wrongca-key.pem --template wrongca.tmpl --outfile wrongca.pem
diff --git a/daemon/lua/trust_anchors.test/x509/server-key.pem b/daemon/lua/trust_anchors.test/x509/server-key.pem
new file mode 100644
index 0000000..4410e27
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:ba:f8:5c:15:1b:85:bd:32:5e:59:c4:ae:73:a2:b0
+ 67:06:07:69:e6:88:04:4d:98:45:5d:b6:43:78:8b:1f
+ 53:b3:22:0a:d1:b2:48:78:96:38:b8:98:1a:08:41:12
+ 2a:38:cc:3a:ae:b8:9d:73:ea:7c:ba:7a:08:ea:bc:24
+ f3:9b:1f:81:eb:54:6e:d9:16:b2:15:bc:66:36:78:43
+ 0c:06:8e:ba:aa:b6:f4:fb:12:d4:1f:04:22:b3:5b:03
+ 8f:b7:a6:25:df:58:c4:ca:b3:09:c4:54:b2:a4:25:fa
+ af:a6:24:d8:83:9f:18:fc:08:6c:da:f4:ae:68:57:75
+ d6:a8:c1:bf:db:39:f7:b0:c2:63:8d:95:18:01:0a:ee
+ 81:d0:e2:76:d5:52:5c:25:f8:aa:0c:a8:7f:34:ca:e2
+ bc:0e:34:be:63:7f:4a:01:90:36:5c:4d:d9:d9:ee:05
+ fc:e2:c8:a1:32:76:dc:39:54:33:dd:c4:b8:1e:a1:f5
+ 23:c1:7f:3b:6a:ff:84:98:60:1f:53:86:bf:ac:d6:4e
+ 58:9a:91:aa:13:1e:a5:9e:61:eb:ba:8c:35:da:89:4d
+ 48:7b:82:cf:95:d4:68:fd:24:aa:43:9c:3a:5b:86:f6
+ 7d:2d:41:dc:63:36:2c:c2:c5:0b:49:04:46:f3:c4:b9
+ e0:19:e4:06:80:4c:9f:9f:1a:6b:9a:88:42:6c:6c:a9
+ 48:1c:9d:ff:a1:71:2c:44:5a:e5:3f:b4:bc:b6:43:db
+ 47:1f:65:15:41:3f:d0:7a:8f:c1:1c:f0:93:11:c7:13
+ 74:5f:7c:47:e9:2c:bc:d0:7a:fc:c0:89:6e:e9:1e:82
+ 85:ef:a7:af:57:d3:fc:af:c7:9a:34:06:60:2e:db:bc
+ 01:d5:08:63:8e:07:27:51:3a:17:0a:71:22:56:eb:e9
+ af:f6:48:31:42:87:2d:95:05:ad:f8:c6:76:bc:17:2f
+ 50:47:68:95:4a:6b:4d:ce:ba:51:2b:1e:e1:b3:d5:79
+ 27:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 3a:95:8d:8c:d3:95:e1:45:82:08:d0:b6:f4:e6:ba:2d
+ 5d:d7:3e:d8:8c:30:04:fc:3c:67:f3:af:4a:7b:15:32
+ cd:c3:51:ee:88:d5:6a:6b:6f:94:6f:9c:60:8f:bb:18
+ 5d:b9:a8:7d:8c:bd:51:4f:dd:0b:35:27:cc:1d:6d:da
+ a2:f5:89:68:ea:88:dd:1e:de:68:2f:23:3b:d8:0c:f2
+ 1c:af:e6:4f:8d:8a:4f:8d:83:c7:c0:2c:fb:53:fe:56
+ ae:ed:b1:9a:3d:1f:54:80:2b:04:48:a1:bd:0b:65:74
+ 5a:33:db:5f:ca:9f:32:81:95:52:3a:2e:d7:e4:e7:b8
+ 7e:22:4f:72:6a:c4:70:af:48:30:59:d2:2e:a9:75:38
+ 59:f2:4b:d7:e5:b9:97:f0:45:a0:37:bf:bc:14:02:5d
+ 78:7a:10:59:ee:cd:8a:95:dc:62:a9:c6:24:22:0f:e0
+ 40:53:2b:27:3b:d5:1f:65:81:e6:f0:37:dc:e9:54:7c
+ f8:81:f0:e0:f7:80:05:ac:91:14:5b:5d:03:14:c2:b9
+ 74:64:f6:ab:6e:a5:ce:e7:bc:56:58:41:30:31:8e:e9
+ f5:6e:31:62:31:69:a8:17:44:89:b3:b9:95:5c:cd:fc
+ 40:86:2c:a1:1d:46:48:94:26:ae:35:bf:14:0e:ae:49
+ 2d:56:5f:bd:e0:d6:f5:03:ed:df:a5:a9:43:89:5c:01
+ 33:5e:e6:3e:80:da:9f:df:2d:c7:e8:13:60:32:27:0e
+ 77:11:fd:43:94:2b:6e:6b:12:79:aa:59:e6:54:b6:47
+ dc:78:7e:fe:4b:40:32:12:3a:cc:6d:d2:9f:49:fc:b2
+ dc:6f:d0:01:03:1d:1d:a8:e5:ee:60:d7:8c:26:7f:73
+ 8a:c0:81:95:ff:b6:c5:5e:d7:6b:50:1f:02:61:3b:31
+ f4:41:da:0a:a7:c6:ea:d2:a2:c4:b5:6d:ce:3f:e0:3b
+ 03:a7:38:37:db:88:82:18:09:a2:da:cf:77:3a:33:f9
+
+
+prime1:
+ 00:f7:94:41:16:98:0c:cb:a1:31:a8:33:38:96:03:f1
+ 33:bf:b7:03:1b:28:bc:43:62:40:77:e6:d9:75:64:77
+ ff:64:51:34:9c:65:3a:ca:10:0f:3e:ce:37:ef:14:85
+ d5:7d:f5:ee:29:f3:76:02:c4:dd:52:91:5c:2e:7e:ad
+ 76:6b:65:e9:60:fc:7c:30:64:9a:bb:65:22:39:a3:a0
+ 54:78:9b:15:2d:a7:e1:36:25:2f:29:ee:01:d7:1d:b6
+ f6:07:2c:b6:8f:b4:66:82:48:c0:3a:d8:2f:bb:d7:bb
+ f4:f0:54:59:ea:66:d9:e9:f8:f2:dc:a8:76:d3:5f:30
+ 8e:18:37:2e:b8:a1:64:b6:d6:14:8e:9d:ef:d2:90:45
+ a8:fe:f9:a6:75:42:9b:69:d7:99:df:2e:f9:58:b8:a0
+ 7c:57:d6:10:c4:7b:b3:30:d0:4e:80:74:37:1a:86:bb
+ d8:bf:90:9f:62:be:f1:22:bf:0c:cf:d7:c0:cf:4c:e0
+ 4b:
+
+prime2:
+ 00:c1:54:5d:70:8f:b2:93:c7:68:a0:a3:0f:3b:00:9d
+ f7:99:96:2f:6f:46:11:7a:71:e8:be:84:b4:57:3f:32
+ d0:bc:09:64:04:61:e7:ce:a9:e2:60:a4:6e:18:8a:e1
+ f0:05:88:e0:a1:ae:6e:9e:db:f9:39:8d:04:b4:12:a5
+ 0d:fe:bb:95:ce:bc:13:5a:3a:a9:18:a3:7b:70:39:99
+ d4:a4:eb:92:22:6a:85:66:f9:50:b7:fe:10:b9:a7:d3
+ f3:2b:96:66:93:e8:00:ae:c7:eb:cb:08:cc:3e:d3:ab
+ c3:aa:a4:4a:36:72:07:c8:eb:6b:75:17:f2:1f:e3:32
+ f0:db:ce:8b:5b:93:e7:dc:58:56:ab:38:5e:72:3c:3b
+ b1:08:c5:51:b0:fe:21:d9:a0:63:49:5b:bc:c6:fe:de
+ 99:1d:9e:84:37:dc:4f:63:0d:ff:0c:b5:33:8e:18:74
+ 6d:9f:07:45:ca:1b:15:c7:83:64:6f:2b:39:73:87:59
+ 15:
+
+coefficient:
+ 25:67:50:eb:3e:0e:3c:1d:a4:71:da:11:9b:64:59:83
+ ad:df:a3:82:07:aa:3e:a2:c6:cc:c1:6f:cf:5e:09:f7
+ 18:f8:a1:75:6a:43:99:c1:a8:01:2c:43:b8:d4:7f:5a
+ fe:a5:aa:3d:18:a8:39:5d:87:f6:88:fb:22:a4:13:09
+ 92:bb:8f:e4:23:5f:07:e7:3c:11:2a:55:38:35:86:ad
+ 63:44:ae:7b:25:1a:27:58:47:b2:ca:a2:07:04:d5:e5
+ c9:af:b1:09:da:1d:5c:49:0b:07:cd:93:b2:70:1e:9a
+ 2d:90:e0:80:75:93:8f:4e:97:1a:c6:af:a4:6c:9d:fe
+ 5c:41:80:5c:3f:2e:c7:b3:7f:ed:36:78:46:50:ef:c7
+ 6f:fe:1b:b0:60:f0:3a:d9:67:7f:23:74:9d:c4:10:70
+ 00:cd:27:a3:72:45:35:17:a5:86:17:be:e6:4a:70:a4
+ 03:9d:ea:70:50:64:65:f1:30:56:ce:0e:b7:e2:58:a7
+
+
+exp1:
+ 00:9e:dc:1e:37:a5:30:f0:a8:69:f8:87:85:53:9d:0b
+ f4:2c:9b:fd:fe:3b:51:31:db:a5:8a:4a:32:56:c5:34
+ ca:47:50:63:f5:c6:6e:c6:a1:2f:67:19:63:82:a1:24
+ 8f:2c:d7:d5:0e:4e:0d:f7:10:e3:02:cc:0a:de:3a:a2
+ 8b:4d:b6:82:dd:9c:a5:03:58:4a:80:dc:0f:ed:f4:34
+ 38:7f:7a:e3:47:fc:64:e2:1d:51:fa:11:a2:54:a9:d8
+ 70:5d:82:2f:52:5e:6b:38:45:fe:32:c3:ed:3d:16:dc
+ 9f:fa:65:e5:9c:26:8a:c5:3a:dc:7b:02:0d:dc:eb:43
+ 78:a9:c9:1e:cd:91:a1:d2:3f:e3:c8:ef:46:a7:51:b3
+ a1:10:9a:98:58:bd:78:83:9d:b8:3a:21:26:15:eb:c1
+ ee:87:5d:f0:3c:63:33:43:ab:25:f3:fe:9e:2d:03:2f
+ 1d:91:2d:f7:57:a1:35:91:1a:0d:da:7f:92:54:71:fb
+ a9:
+
+exp2:
+ 2b:a1:e5:c0:cc:bd:a9:fa:9c:53:7c:d9:a8:20:58:86
+ 94:24:40:2a:65:ee:f5:ea:95:73:c2:31:8d:6b:57:05
+ a3:1a:9f:77:19:bd:9e:77:da:fe:a2:bd:b2:4e:4d:f5
+ c4:da:02:90:9a:f4:9e:67:d9:14:b3:0d:f7:b2:29:8c
+ 42:0c:86:1f:f5:74:8c:ad:a6:92:47:fb:48:f5:c7:11
+ 25:f3:80:b4:c1:c3:bf:dc:ce:e9:e7:ae:50:a8:5e:fe
+ 87:bc:d7:03:d4:9d:aa:d4:b6:13:c9:b5:87:0c:70:bc
+ a5:5b:94:e0:3a:d6:24:f3:74:fa:25:60:60:ef:ff:04
+ 3b:27:9f:6e:18:b0:80:9b:73:5c:0b:49:cd:90:68:8c
+ 69:05:57:8d:91:9d:84:27:5d:a1:25:d2:32:3b:3d:73
+ e3:2a:6e:7e:c8:fb:25:c8:f7:e2:1f:57:36:5f:b0:8f
+ 39:10:04:21:3c:01:ab:58:ad:27:25:e3:3e:7e:b2:8d
+
+
+
+Public Key PIN:
+ pin-sha256:39HEiK68VoVnfvhMoLHp8J9yLV3u4CjiDlcNu1pmUxw=
+Public Key ID:
+ sha256:dfd1c488aebc5685677ef84ca0b1e9f09f722d5deee028e20e570dbb5a66531c
+ sha1:fab196e0eaaf8f48c8f4fed07c97e4aabba3a1ed
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEAuvhcFRuFvTJeWcSuc6KwZwYHaeaIBE2YRV22Q3iLH1OzIgrR
+skh4lji4mBoIQRIqOMw6rridc+p8unoI6rwk85sfgetUbtkWshW8ZjZ4QwwGjrqq
+tvT7EtQfBCKzWwOPt6Yl31jEyrMJxFSypCX6r6Yk2IOfGPwIbNr0rmhXddaowb/b
+OfewwmONlRgBCu6B0OJ21VJcJfiqDKh/NMrivA40vmN/SgGQNlxN2dnuBfziyKEy
+dtw5VDPdxLgeofUjwX87av+EmGAfU4a/rNZOWJqRqhMepZ5h67qMNdqJTUh7gs+V
+1Gj9JKpDnDpbhvZ9LUHcYzYswsULSQRG88S54BnkBoBMn58aa5qIQmxsqUgcnf+h
+cSxEWuU/tLy2Q9tHH2UVQT/Qeo/BHPCTEccTdF98R+ksvNB6/MCJbukegoXvp69X
+0/yvx5o0BmAu27wB1QhjjgcnUToXCnEiVuvpr/ZIMUKHLZUFrfjGdrwXL1BHaJVK
+a03OulErHuGz1XknAgMBAAECggGAOpWNjNOV4UWCCNC29Oa6LV3XPtiMMAT8PGfz
+r0p7FTLNw1HuiNVqa2+Ub5xgj7sYXbmofYy9UU/dCzUnzB1t2qL1iWjqiN0e3mgv
+IzvYDPIcr+ZPjYpPjYPHwCz7U/5Wru2xmj0fVIArBEihvQtldFoz21/KnzKBlVI6
+Ltfk57h+Ik9yasRwr0gwWdIuqXU4WfJL1+W5l/BFoDe/vBQCXXh6EFnuzYqV3GKp
+xiQiD+BAUysnO9UfZYHm8Dfc6VR8+IHw4PeABayRFFtdAxTCuXRk9qtupc7nvFZY
+QTAxjun1bjFiMWmoF0SJs7mVXM38QIYsoR1GSJQmrjW/FA6uSS1WX73g1vUD7d+l
+qUOJXAEzXuY+gNqf3y3H6BNgMicOdxH9Q5QrbmsSeapZ5lS2R9x4fv5LQDISOsxt
+0p9J/LLcb9ABAx0dqOXuYNeMJn9zisCBlf+2xV7Xa1AfAmE7MfRB2gqnxurSosS1
+bc4/4DsDpzg324iCGAmi2s93OjP5AoHBAPeUQRaYDMuhMagzOJYD8TO/twMbKLxD
+YkB35tl1ZHf/ZFE0nGU6yhAPPs437xSF1X317inzdgLE3VKRXC5+rXZrZelg/Hww
+ZJq7ZSI5o6BUeJsVLafhNiUvKe4B1x229gcsto+0ZoJIwDrYL7vXu/TwVFnqZtnp
++PLcqHbTXzCOGDcuuKFkttYUjp3v0pBFqP75pnVCm2nXmd8u+Vi4oHxX1hDEe7Mw
+0E6AdDcahrvYv5CfYr7xIr8Mz9fAz0zgSwKBwQDBVF1wj7KTx2igow87AJ33mZYv
+b0YRenHovoS0Vz8y0LwJZARh586p4mCkbhiK4fAFiOChrm6e2/k5jQS0EqUN/ruV
+zrwTWjqpGKN7cDmZ1KTrkiJqhWb5ULf+ELmn0/MrlmaT6ACux+vLCMw+06vDqqRK
+NnIHyOtrdRfyH+My8NvOi1uT59xYVqs4XnI8O7EIxVGw/iHZoGNJW7zG/t6ZHZ6E
+N9xPYw3/DLUzjhh0bZ8HRcobFceDZG8rOXOHWRUCgcEAntweN6Uw8Khp+IeFU50L
+9Cyb/f47UTHbpYpKMlbFNMpHUGP1xm7GoS9nGWOCoSSPLNfVDk4N9xDjAswK3jqi
+i022gt2cpQNYSoDcD+30NDh/euNH/GTiHVH6EaJUqdhwXYIvUl5rOEX+MsPtPRbc
+n/pl5ZwmisU63HsCDdzrQ3ipyR7NkaHSP+PI70anUbOhEJqYWL14g524OiEmFevB
+7odd8DxjM0OrJfP+ni0DLx2RLfdXoTWRGg3af5JUcfupAoHAK6HlwMy9qfqcU3zZ
+qCBYhpQkQCpl7vXqlXPCMY1rVwWjGp93Gb2ed9r+or2yTk31xNoCkJr0nmfZFLMN
+97IpjEIMhh/1dIytppJH+0j1xxEl84C0wcO/3M7p565QqF7+h7zXA9SdqtS2E8m1
+hwxwvKVblOA61iTzdPolYGDv/wQ7J59uGLCAm3NcC0nNkGiMaQVXjZGdhCddoSXS
+Mjs9c+Mqbn7I+yXI9+IfVzZfsI85EAQhPAGrWK0nJeM+frKNAoHAJWdQ6z4OPB2k
+cdoRm2RZg63fo4IHqj6ixszBb89eCfcY+KF1akOZwagBLEO41H9a/qWqPRioOV2H
+9oj7IqQTCZK7j+QjXwfnPBEqVTg1hq1jRK57JRonWEeyyqIHBNXlya+xCdodXEkL
+B82TsnAemi2Q4IB1k49OlxrGr6Rsnf5cQYBcPy7Hs3/tNnhGUO/Hb/4bsGDwOtln
+fyN0ncQQcADNJ6NyRTUXpYYXvuZKcKQDnepwUGRl8TBWzg634lin
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/server.pem b/daemon/lua/trust_anchors.test/x509/server.pem
new file mode 100644
index 0000000..47fb6a4
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server.pem
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEezCCAuOgAwIBAgIUAYjlKE92sFzGxwB2+PN+dV2rKOEwDQYJKoZIhvcNAQEL
+BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMB4XDTE5MDEw
+MzE2MjczM1oXDTIwMDEwMzE2MjczM1owPDESMBAGA1UEAxMJbG9jYWxob3N0MSYw
+JAYDVQQKEx1GYWtlIEROUyByb290IG9yZyB0ZXN0IHNlcnZlcjCCAaIwDQYJKoZI
+hvcNAQEBBQADggGPADCCAYoCggGBALr4XBUbhb0yXlnErnOisGcGB2nmiARNmEVd
+tkN4ix9TsyIK0bJIeJY4uJgaCEESKjjMOq64nXPqfLp6COq8JPObH4HrVG7ZFrIV
+vGY2eEMMBo66qrb0+xLUHwQis1sDj7emJd9YxMqzCcRUsqQl+q+mJNiDnxj8CGza
+9K5oV3XWqMG/2zn3sMJjjZUYAQrugdDidtVSXCX4qgyofzTK4rwONL5jf0oBkDZc
+TdnZ7gX84sihMnbcOVQz3cS4HqH1I8F/O2r/hJhgH1OGv6zWTliakaoTHqWeYeu6
+jDXaiU1Ie4LPldRo/SSqQ5w6W4b2fS1B3GM2LMLFC0kERvPEueAZ5AaATJ+fGmua
+iEJsbKlIHJ3/oXEsRFrlP7S8tkPbRx9lFUE/0HqPwRzwkxHHE3RffEfpLLzQevzA
+iW7pHoKF76evV9P8r8eaNAZgLtu8AdUIY44HJ1E6FwpxIlbr6a/2SDFChy2VBa34
+xna8Fy9QR2iVSmtNzrpRKx7hs9V5JwIDAQABo4GNMIGKMAwGA1UdEwEB/wQCMAAw
+FAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+DwEB/wQFAwMHoAAwHQYDVR0OBBYEFPqxluDqr49IyPT+0HyX5Kq7o6HtMB8GA1Ud
+IwQYMBaAFDAX4bzP3gaOQYZyZC0eGBqQmIJkMA0GCSqGSIb3DQEBCwUAA4IBgQCA
+K1GVJ9NhEbkH4vbZrRtUwyIWJgFbUXy3TzXIRZTUMgMzEZXDyVkElOcGPxev6kMt
+TdSRZrc2DteAnWpJ6fSUt3hU13O7r7H8R7jF3UvqotgiQi+lOvUKPKUiU3ecuClO
+NBFE7bjiTOtMyiGWjsVcBb3aHcPjEWm8pTPW3yuSXdg0J5pBjjxqK8m3ExMPK3P+
+sBE7eSTuHiLBWAIRgM1I/F5COV7QKX1CM2COmJWEDS1t3qORKZPzNWuaVXwtqbbA
+qC4OIpT8DakSLWyPK74vLx1yoUJu5wtoifHG9nnrFvstLE4DNLiB/fN08FI1ka13
+hJyJMQecl84kunX1hkwP/o4IrZ/pSWk2d9PCm35Td/g7jaI+06IqnTIyQblXRYIQ
+iPfmCWEyFBwFJQVND2c0JJfNeu16qVniarwnXa8z6j5eBI3E94weH0ZOdOSKD//c
+iQvU7JpoC9Gc+jJFJqVE5RE7ueZRqN+7dJbe4CyrAhm2U0zwel9XNZtWaHMHT7Y=
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/server.tmpl b/daemon/lua/trust_anchors.test/x509/server.tmpl
new file mode 100644
index 0000000..7ee40d2
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server.tmpl
@@ -0,0 +1,6 @@
+organization = Fake DNS root org test server
+cn = localhost
+tls_www_server
+encryption_key
+signing_key
+dns_name = localhost
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca-key.pem b/daemon/lua/trust_anchors.test/x509/wrongca-key.pem
new file mode 100644
index 0000000..56b69fe
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:e4:cc:5d:b2:a0:a5:0e:94:f2:d1:ca:cd:04:36:72
+ 95:9a:61:ac:c7:d6:35:24:63:d6:3b:2d:38:4b:a5:69
+ fe:91:f5:d8:a6:db:df:9a:17:fd:21:5d:bc:94:9f:3b
+ cf:f7:fa:9d:1d:7f:22:0f:90:36:91:4f:3a:92:77:55
+ 6e:33:e6:c9:94:a6:a1:c7:e6:14:f4:3d:27:18:32:5c
+ 0c:9a:5d:5a:8a:77:45:50:6e:00:e7:c5:14:cf:4f:75
+ 39:60:99:5b:5d:78:61:f1:5e:cb:6e:78:81:fb:fe:ad
+ dc:50:89:ce:b6:4d:78:79:e2:84:1c:c1:be:72:ce:d5
+ 7c:66:82:46:bb:da:ba:cc:69:4c:66:dc:a9:86:56:c3
+ 0e:bc:a4:b9:85:0b:c9:07:6f:a4:a7:24:33:ee:bc:02
+ 9d:73:61:82:e0:f0:dd:a6:e9:24:a0:ca:db:14:09:79
+ 9b:66:6f:2b:4f:19:b0:d3:44:85:04:c3:e6:b6:38:a0
+ 57:8b:bb:b2:95:03:ab:45:97:9c:fd:55:fd:bc:84:64
+ 9b:f1:f0:6a:c7:be:e3:3d:1c:ba:7b:b9:b9:3d:96:ca
+ ad:ac:c3:dc:69:80:ba:27:1a:91:73:61:11:64:09:7b
+ e6:c7:ac:ef:16:66:2f:c1:dc:8e:8c:4b:23:8f:14:39
+ 01:20:2b:97:fd:30:72:bd:12:e1:e1:4b:b7:2f:ec:08
+ 47:4b:7c:ec:8f:2f:b1:2b:5d:b0:af:fe:f0:0e:8e:5e
+ 90:87:53:3f:f9:4f:fe:cf:9e:6a:ac:41:4e:30:be:93
+ 5c:2b:7e:d3:14:c6:a6:23:ac:aa:4c:88:73:f9:79:77
+ df:e3:66:0a:9b:fa:b2:7e:1d:f4:23:1d:e9:76:48:2e
+ 48:34:0d:92:7d:30:05:ea:00:6e:57:cd:23:49:2b:35
+ d0:08:6d:84:ab:9d:6f:54:92:16:8e:cb:c5:25:76:96
+ 02:c3:9f:89:33:4c:a3:ee:d4:ee:cc:53:bc:a3:a8:30
+ a7:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 42:04:6d:ec:c2:c9:9d:81:80:e6:e3:db:70:21:bd:c2
+ 48:ff:71:f9:5f:67:8a:0e:7c:9c:2a:9a:19:c9:aa:e1
+ d7:7f:d6:79:9e:eb:cf:ec:a8:0f:5e:9a:b1:4f:98:d4
+ 93:3a:ee:e6:b9:ee:3c:0b:62:93:5f:07:09:88:01:50
+ 81:0d:50:90:e1:db:c0:70:35:0f:9c:2d:91:9f:c6:4b
+ a4:a6:d7:1f:28:f7:09:14:14:92:cb:9d:0b:8c:63:c8
+ a0:84:df:86:02:dc:4f:e7:08:4f:e1:d9:af:ba:76:b4
+ 21:51:02:22:3c:0c:4d:2e:fc:eb:c7:43:8a:a0:ff:9c
+ 9b:7f:6f:a5:78:a1:79:a5:d0:73:c5:ab:ec:a5:50:37
+ 0a:5b:85:64:4c:58:3f:1b:09:a9:68:9a:cb:81:d8:47
+ 52:29:8a:b8:19:07:fb:c7:3d:d8:5f:70:03:42:10:a2
+ b4:55:d3:6b:49:80:6a:15:55:44:60:ba:4b:4d:df:85
+ 97:7c:47:4f:3e:8c:46:ed:72:7b:d8:63:5d:4d:05:96
+ f8:47:e4:65:c9:18:8f:13:e4:36:24:cf:c7:fe:3e:2e
+ 9c:7f:09:5a:0a:3d:0a:6a:f7:e6:27:0b:ed:8c:fc:db
+ 9c:c3:77:fd:6d:f2:d5:ab:c3:0e:3a:cb:49:95:8a:f3
+ 9b:ab:3e:2c:d2:82:9a:61:f0:2c:2c:f7:37:ad:f5:32
+ ee:96:f8:cc:a4:a1:97:19:45:fc:8c:82:33:ca:73:86
+ 7e:79:94:fe:6a:a0:53:bf:8b:7d:b0:da:1c:a4:f4:7f
+ a1:d9:4f:76:75:20:35:b4:69:9c:c8:23:7e:07:b9:81
+ 4e:04:81:8e:88:d5:83:51:6e:cc:f2:6b:e9:af:ad:bc
+ 42:f9:2c:8a:c3:54:ce:f1:1a:bc:2c:8f:99:a0:a6:0a
+ cc:92:5b:6d:78:c7:c0:cc:7d:eb:42:eb:c3:69:46:0b
+ 33:d1:3e:c8:1a:13:e8:db:ee:ea:d4:91:77:0b:44:51
+
+
+prime1:
+ 00:e9:63:e7:aa:1a:2e:41:51:17:10:33:53:de:95:f1
+ 7a:8e:55:57:c5:f8:a4:25:c3:e1:83:fe:ad:68:fe:d3
+ 86:10:f7:f0:9a:d2:69:dc:15:bc:0c:e4:44:d3:98:0a
+ 0d:71:77:e6:53:36:57:a2:2e:22:b1:e7:8d:4a:64:33
+ 0f:5c:11:20:bb:ae:21:46:d4:82:35:b1:9a:95:96:22
+ 50:c6:6c:8c:e5:55:93:d0:87:9a:3a:6a:3f:13:8a:3b
+ cf:0e:04:38:b5:19:2e:95:d4:d8:2d:80:36:ac:18:63
+ 74:ad:ea:eb:20:f5:9a:13:1e:82:c2:10:9f:78:12:f8
+ 74:af:a4:ee:29:bb:da:d9:a4:fa:a7:25:4f:ae:52:3e
+ 92:02:dd:f6:65:28:0c:27:36:d1:3d:a2:7c:c7:01:55
+ 5c:c1:88:d4:3e:fd:92:70:4a:15:43:0a:5b:ec:37:ea
+ 12:42:db:7c:45:c6:2f:bc:ac:a7:c7:f2:4b:4a:b0:3c
+ 63:
+
+prime2:
+ 00:fa:f6:94:95:53:f4:c7:7e:93:e1:3c:c6:6f:97:d2
+ a0:52:44:04:56:18:40:fb:f0:c0:5b:00:cb:45:71:c9
+ 54:c9:e2:50:91:77:ee:60:f3:33:fc:c5:7e:fc:07:7e
+ 06:5e:5e:8e:db:18:72:83:9c:00:02:d0:a0:86:5c:9f
+ 80:72:37:16:3e:39:3f:b7:1c:08:c8:79:ed:51:f2:4d
+ 61:3a:48:4b:09:7d:a5:f4:7a:8e:b4:5c:cc:0d:56:66
+ 98:2e:fc:2f:26:1c:75:6f:a4:7d:2b:7d:f9:5c:dc:52
+ a9:51:f9:26:b0:94:71:5e:d2:8e:85:38:02:57:9b:31
+ 74:40:7b:81:65:ad:56:5a:b4:ac:b8:40:80:7d:b2:a2
+ 5b:81:9b:b3:c2:41:de:7d:f6:66:b0:a2:a7:13:11:a6
+ 07:51:6f:e9:79:97:43:67:dd:8f:a2:c3:e3:5b:74:50
+ d9:c2:e7:cf:2d:5b:9e:bf:01:c0:77:cf:9c:06:22:63
+ ed:
+
+coefficient:
+ 00:83:36:59:9d:73:95:c9:07:11:60:b5:0f:1e:8d:81
+ ee:78:9e:92:50:4c:e7:00:a6:21:8a:e8:fd:12:de:6c
+ 2d:b3:99:53:90:79:74:e2:75:7b:f8:d9:d1:c5:29:28
+ 9e:bc:5a:ad:28:7c:8b:47:14:17:14:a6:08:e6:ec:9d
+ dd:74:9b:d5:bb:c6:54:24:25:81:a2:b7:b6:8a:bd:e4
+ da:f5:7e:08:4a:cd:f2:7c:2a:cc:bf:ed:c3:d4:66:05
+ 3f:f8:39:07:77:e6:13:cf:88:28:d5:1e:2a:4b:13:66
+ 59:39:ef:7b:3d:43:fa:77:9f:64:81:45:52:da:03:b0
+ 2b:04:46:f1:79:a0:bc:08:b1:9b:0c:ae:91:4b:96:08
+ ad:26:a0:a6:f1:c4:d5:74:c6:f8:4a:7c:01:5c:12:99
+ 1e:58:92:b9:e5:13:20:0b:fc:b4:2a:af:00:00:a3:22
+ 24:1c:f8:f9:67:ec:37:c0:fd:22:c7:97:cb:4f:85:e5
+ fb:
+
+exp1:
+ 07:0a:5d:7d:b3:26:7c:0f:ef:2b:2c:f1:35:c0:be:35
+ 1d:40:13:d2:c4:0a:67:9d:3e:1b:56:3e:72:f1:64:fe
+ 21:5a:e9:66:32:3c:c1:47:e2:91:5c:fd:7a:88:96:9d
+ 0b:34:3b:bd:7c:e1:2d:e2:48:67:a7:7d:8a:a5:f5:28
+ 5c:75:a3:d0:25:93:99:68:65:b9:2a:ef:67:dd:cc:91
+ 35:3b:27:10:f0:00:f2:84:74:b1:98:6c:e8:b0:fd:d6
+ e4:2c:5a:6d:94:21:e4:a1:34:18:43:4a:e2:ec:25:6b
+ ea:a7:30:8a:a0:fe:11:df:94:c0:37:f2:27:94:22:ec
+ 9a:33:d6:7f:69:cc:53:4e:77:c5:3d:09:e7:4f:51:d5
+ e3:c2:40:61:92:d0:b3:0a:23:4b:c1:b0:13:ec:c5:5f
+ 73:f3:25:bb:f4:b8:4b:2c:e0:f1:51:c9:ae:19:8d:b5
+ 19:51:37:b1:7f:26:07:82:09:d9:ad:44:7a:2f:50:d3
+
+
+exp2:
+ 54:61:21:d6:0f:73:66:bb:ed:56:b6:cb:75:6b:d3:9a
+ a9:ee:4a:92:f3:f6:ad:7e:e5:fd:f3:07:65:62:fb:b1
+ 71:6b:91:71:47:a4:b3:9e:31:e5:94:35:bc:e1:7c:03
+ 02:29:c2:d8:71:a0:d7:15:55:7f:9c:cb:cc:41:4a:33
+ b2:b3:48:dc:44:fd:62:40:9f:c7:60:0f:66:15:14:e5
+ 52:e6:49:ac:78:3d:9b:34:b5:d4:78:ba:f6:e5:0c:fb
+ b0:18:84:75:c8:ed:c7:4a:c3:f7:22:94:fc:1e:ec:00
+ 18:1a:b0:62:80:96:99:ae:2b:d3:28:e0:c8:b9:da:67
+ de:e2:67:c0:5b:06:84:da:e8:93:ce:c4:24:ff:31:cd
+ 98:87:54:6a:45:21:5c:b2:c3:16:32:aa:00:24:57:f1
+ 6f:f5:33:c7:f9:0e:e5:d6:3d:dc:19:06:d1:92:0b:39
+ 1c:6a:3a:63:62:c1:be:31:05:98:83:0a:4f:99:b2:85
+
+
+
+Public Key PIN:
+ pin-sha256:75s1y3dUDBiOALg1xQKcI2/wXlZsFuALytI0Khf7WYQ=
+Public Key ID:
+ sha256:ef9b35cb77540c188e00b835c5029c236ff05e566c16e00bcad2342a17fb5984
+ sha1:f91b5944557c4e3bb4cee62a6a2a525b950bbd99
+
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEA5MxdsqClDpTy0crNBDZylZphrMfWNSRj1jstOEulaf6R9dim
+29+aF/0hXbyUnzvP9/qdHX8iD5A2kU86kndVbjPmyZSmocfmFPQ9JxgyXAyaXVqK
+d0VQbgDnxRTPT3U5YJlbXXhh8V7LbniB+/6t3FCJzrZNeHnihBzBvnLO1Xxmgka7
+2rrMaUxm3KmGVsMOvKS5hQvJB2+kpyQz7rwCnXNhguDw3abpJKDK2xQJeZtmbytP
+GbDTRIUEw+a2OKBXi7uylQOrRZec/VX9vIRkm/Hwase+4z0cunu5uT2Wyq2sw9xp
+gLonGpFzYRFkCXvmx6zvFmYvwdyOjEsjjxQ5ASArl/0wcr0S4eFLty/sCEdLfOyP
+L7ErXbCv/vAOjl6Qh1M/+U/+z55qrEFOML6TXCt+0xTGpiOsqkyIc/l5d9/jZgqb
++rJ+HfQjHel2SC5INA2SfTAF6gBuV80jSSs10AhthKudb1SSFo7LxSV2lgLDn4kz
+TKPu1O7MU7yjqDCnAgMBAAECggGAQgRt7MLJnYGA5uPbcCG9wkj/cflfZ4oOfJwq
+mhnJquHXf9Z5nuvP7KgPXpqxT5jUkzru5rnuPAtik18HCYgBUIENUJDh28BwNQ+c
+LZGfxkukptcfKPcJFBSSy50LjGPIoITfhgLcT+cIT+HZr7p2tCFRAiI8DE0u/OvH
+Q4qg/5ybf2+leKF5pdBzxavspVA3CluFZExYPxsJqWiay4HYR1IpirgZB/vHPdhf
+cANCEKK0VdNrSYBqFVVEYLpLTd+Fl3xHTz6MRu1ye9hjXU0FlvhH5GXJGI8T5DYk
+z8f+Pi6cfwlaCj0KavfmJwvtjPzbnMN3/W3y1avDDjrLSZWK85urPizSgpph8Cws
+9zet9TLulvjMpKGXGUX8jIIzynOGfnmU/mqgU7+LfbDaHKT0f6HZT3Z1IDW0aZzI
+I34HuYFOBIGOiNWDUW7M8mvpr628QvksisNUzvEavCyPmaCmCsySW214x8DMfetC
+68NpRgsz0T7IGhPo2+7q1JF3C0RRAoHBAOlj56oaLkFRFxAzU96V8XqOVVfF+KQl
+w+GD/q1o/tOGEPfwmtJp3BW8DORE05gKDXF35lM2V6IuIrHnjUpkMw9cESC7riFG
+1II1sZqVliJQxmyM5VWT0IeaOmo/E4o7zw4EOLUZLpXU2C2ANqwYY3St6usg9ZoT
+HoLCEJ94Evh0r6TuKbva2aT6pyVPrlI+kgLd9mUoDCc20T2ifMcBVVzBiNQ+/ZJw
+ShVDClvsN+oSQtt8RcYvvKynx/JLSrA8YwKBwQD69pSVU/THfpPhPMZvl9KgUkQE
+VhhA+/DAWwDLRXHJVMniUJF37mDzM/zFfvwHfgZeXo7bGHKDnAAC0KCGXJ+AcjcW
+Pjk/txwIyHntUfJNYTpISwl9pfR6jrRczA1WZpgu/C8mHHVvpH0rfflc3FKpUfkm
+sJRxXtKOhTgCV5sxdEB7gWWtVlq0rLhAgH2yoluBm7PCQd599mawoqcTEaYHUW/p
+eZdDZ92PosPjW3RQ2cLnzy1bnr8BwHfPnAYiY+0CgcAHCl19syZ8D+8rLPE1wL41
+HUAT0sQKZ50+G1Y+cvFk/iFa6WYyPMFH4pFc/XqIlp0LNDu9fOEt4khnp32KpfUo
+XHWj0CWTmWhluSrvZ93MkTU7JxDwAPKEdLGYbOiw/dbkLFptlCHkoTQYQ0ri7CVr
+6qcwiqD+Ed+UwDfyJ5Qi7Joz1n9pzFNOd8U9CedPUdXjwkBhktCzCiNLwbAT7MVf
+c/Mlu/S4Syzg8VHJrhmNtRlRN7F/JgeCCdmtRHovUNMCgcBUYSHWD3Nmu+1Wtst1
+a9Oaqe5KkvP2rX7l/fMHZWL7sXFrkXFHpLOeMeWUNbzhfAMCKcLYcaDXFVV/nMvM
+QUozsrNI3ET9YkCfx2APZhUU5VLmSax4PZs0tdR4uvblDPuwGIR1yO3HSsP3IpT8
+HuwAGBqwYoCWma4r0yjgyLnaZ97iZ8BbBoTa6JPOxCT/Mc2Yh1RqRSFcssMWMqoA
+JFfxb/Uzx/kO5dY93BkG0ZILORxqOmNiwb4xBZiDCk+ZsoUCgcEAgzZZnXOVyQcR
+YLUPHo2B7nieklBM5wCmIYro/RLebC2zmVOQeXTidXv42dHFKSievFqtKHyLRxQX
+FKYI5uyd3XSb1bvGVCQlgaK3toq95Nr1fghKzfJ8Ksy/7cPUZgU/+DkHd+YTz4go
+1R4qSxNmWTnvez1D+nefZIFFUtoDsCsERvF5oLwIsZsMrpFLlgitJqCm8cTVdMb4
+SnwBXBKZHliSueUTIAv8tCqvAACjIiQc+Pln7DfA/SLHl8tPheX7
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca.pem b/daemon/lua/trust_anchors.test/x509/wrongca.pem
new file mode 100644
index 0000000..2b536b9
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAnegAwIBAgIUSDi0iXY6awSZoHpkeTMf8gD8u8UwDQYJKoZIhvcNAQEL
+BQAwHzEdMBsGA1UEAxMUQW5vdGhlciB1bnJlbGF0ZWQgQ0EwHhcNMTkwMTAzMTYy
+NzMzWhcNMjAwMTAzMTYyNzMzWjAfMR0wGwYDVQQDExRBbm90aGVyIHVucmVsYXRl
+ZCBDQTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAOTMXbKgpQ6U8tHK
+zQQ2cpWaYazH1jUkY9Y7LThLpWn+kfXYptvfmhf9IV28lJ87z/f6nR1/Ig+QNpFP
+OpJ3VW4z5smUpqHH5hT0PScYMlwMml1aindFUG4A58UUz091OWCZW114YfFey254
+gfv+rdxQic62TXh54oQcwb5yztV8ZoJGu9q6zGlMZtyphlbDDrykuYULyQdvpKck
+M+68Ap1zYYLg8N2m6SSgytsUCXmbZm8rTxmw00SFBMPmtjigV4u7spUDq0WXnP1V
+/byEZJvx8GrHvuM9HLp7ubk9lsqtrMPcaYC6JxqRc2ERZAl75ses7xZmL8HcjoxL
+I48UOQEgK5f9MHK9EuHhS7cv7AhHS3zsjy+xK12wr/7wDo5ekIdTP/lP/s+eaqxB
+TjC+k1wrftMUxqYjrKpMiHP5eXff42YKm/qyfh30Ix3pdkguSDQNkn0wBeoAblfN
+I0krNdAIbYSrnW9UkhaOy8UldpYCw5+JM0yj7tTuzFO8o6gwpwIDAQABo0MwQTAP
+BgNVHRMBAf8EBTADAQH/MA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFPkbWURV
+fE47tM7mKmoqUluVC72ZMA0GCSqGSIb3DQEBCwUAA4IBgQB7Nbn5Pc4eX8XuVnk+
+RzkB1XZ8UubdQKBUGZ2t4TFZDBuu6MZDhgyyJUU2rD/ndp+9No0BLCEB/qhL5p5W
+SEsSb0t0jmJFmCkHdBefUPqhOW7k7ttuEGN8ctWXloczFrV1dJNR1gfcb6guhIGu
+Q5k+xM0x69VbM0iTMaXqEtAYQqzmDsEpRep6lUbd9g7MLhRE9Y5NWms4EzLlKypR
+z0TSdSFPS/Fz//bzEct/e+Wp8ss42/0JljQMIRYYD7i+x6azF1brhvnadfNmOVFE
+1iN0SnHsPeuD3+v7eji389tnRF3xjKO1Vx8BUVPkQqAWt13xxDqhV41MjyZwFynB
+aG+zGYZ0DyTE/8/ouN5+SN0eMwW/oFSckvFIvCXqS9qf3YuMo+e0eJ/xKozejg+r
+DPUVGmKEFfEZYWjxl3ZVrM4tfSkjzwRKNPZ1NaXcDU3/fbfWtR2cGnNi60AquENA
+GUxwKfDZA3n8dOJQwFRnGXiBNT7nwZZXdow00kGuN/0BZ6Q=
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca.tmpl b/daemon/lua/trust_anchors.test/x509/wrongca.tmpl
new file mode 100644
index 0000000..81dfbfc
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca.tmpl
@@ -0,0 +1,3 @@
+cn = Another unrelated CA
+ca
+cert_signing_key
diff --git a/daemon/lua/zonefile.lua b/daemon/lua/zonefile.lua
new file mode 100644
index 0000000..fdfc211
--- /dev/null
+++ b/daemon/lua/zonefile.lua
@@ -0,0 +1,91 @@
+-- LuaJIT ffi bindings for zscanner, a DNS zone parser.
+-- Author: Marek Vavrusa <marek.vavrusa@nic.cz>
+
+local ffi = require('ffi')
+local libzscanner = ffi.load(libzscanner_SONAME)
+
+-- Wrap scanner context
+local zs_scanner_t = ffi.typeof('zs_scanner_t')
+ffi.metatype( zs_scanner_t, {
+ __gc = function(zs) return libzscanner.zs_deinit(zs) end,
+ __new = function(ct, origin, class, ttl)
+ if not class then class = 1 end
+ if not ttl then ttl = 3600 end
+ local parser = ffi.new(ct)
+ libzscanner.zs_init(parser, origin, class, ttl)
+ return parser
+ end,
+ __index = {
+ open = function (zs, file)
+ assert(ffi.istype(zs, zs_scanner_t))
+ local ret = libzscanner.zs_set_input_file(zs, file)
+ if ret ~= 0 then return false, zs:strerr() end
+ return true
+ end,
+ parse = function(zs, input)
+ assert(ffi.istype(zs, zs_scanner_t))
+ if input ~= nil then libzscanner.zs_set_input_string(zs, input, #input) end
+ local ret = libzscanner.zs_parse_record(zs)
+ -- Return current state only when parsed correctly, otherwise return error
+ if ret == 0 and zs.state ~= "ZS_STATE_ERROR" then
+ return zs.state == "ZS_STATE_DATA"
+ else
+ return false, zs:strerr()
+ end
+ end,
+ current_rr = function(zs)
+ assert(ffi.istype(zs, zs_scanner_t))
+ return {
+ owner = ffi.string(zs.r_owner, zs.r_owner_length),
+ ttl = tonumber(zs.r_ttl),
+ class = tonumber(zs.r_class),
+ type = tonumber(zs.r_type),
+ rdata = ffi.string(zs.r_data, zs.r_data_length),
+ comment = zs:current_comment(),
+ }
+ end,
+ strerr = function(zs)
+ assert(ffi.istype(zs, zs_scanner_t))
+ return ffi.string(libzscanner.zs_strerror(zs.error.code))
+ end,
+ current_comment = function(zs)
+ if zs.buffer_length > 0 then
+ return ffi.string(zs.buffer, zs.buffer_length - 1)
+ else
+ return nil
+ end
+ end
+ },
+})
+
+-- Module API
+local rrparser = {
+ new = zs_scanner_t,
+
+ -- Parse a file into a list of RRs
+ file = function (path)
+ local zs = zs_scanner_t()
+ local ok, err = zs:open(path)
+ if not ok then
+ return ok, err
+ end
+ local results = {}
+ while zs:parse() do
+ table.insert(results, zs:current_rr())
+ end
+ return results
+ end,
+
+ -- Parse a string into a list of RRs.
+ string = function (input)
+ local zs = zs_scanner_t()
+ local results = {}
+ local ok = zs:parse(input)
+ while ok do
+ table.insert(results, zs:current_rr())
+ ok = zs:parse()
+ end
+ return results
+ end,
+}
+return rrparser
diff --git a/daemon/main.c b/daemon/main.c
new file mode 100644
index 0000000..15c7c1c
--- /dev/null
+++ b/daemon/main.c
@@ -0,0 +1,840 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <uv.h>
+#ifdef HAS_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+#include <libknot/error.h>
+
+#include <contrib/cleanup.h>
+#include <contrib/ucw/mempool.h>
+#include <contrib/ccan/asprintf/asprintf.h>
+#include "lib/defines.h"
+#include "lib/resolve.h"
+#include "lib/dnssec.h"
+#include "daemon/network.h"
+#include "daemon/worker.h"
+#include "daemon/engine.h"
+#include "daemon/bindings.h"
+#include "daemon/tls.h"
+#include "lib/dnssec/ta.h"
+
+/* We can fork early on Linux 3.9+ and do SO_REUSEPORT for better performance. */
+#if defined(UV_VERSION_HEX) && defined(SO_REUSEPORT) && defined(__linux__)
+ #define CAN_FORK_EARLY 1
+#endif
+
+/* @internal Array of ip address shorthand. */
+typedef array_t(char*) addr_array_t;
+
+struct args {
+ int forks;
+ addr_array_t addr_set;
+ addr_array_t tls_set;
+ fd_array_t fd_set;
+ fd_array_t tls_fd_set;
+ char *keyfile;
+ int keyfile_unmanaged;
+ const char *moduledir;
+ const char *config;
+ int control_fd;
+ const char *rundir;
+ bool interactive;
+ bool quiet;
+ bool tty_binary_output;
+};
+
+/* lua_pcall helper function */
+static inline char *lua_strerror(int lua_err) {
+ switch (lua_err) {
+ case LUA_ERRRUN: return "a runtime error";
+ case LUA_ERRMEM: return "memory allocation error.";
+ case LUA_ERRERR: return "error while running the error handler function.";
+ default: return "a unknown error";
+ }
+}
+
+/**
+ * TTY control: process input and free() the buffer.
+ *
+ * For parameters see http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb
+ *
+ * - This is just basic read-eval-print; libedit is supported through kresc;
+ * - stream->data contains program arguments (struct args);
+ */
+static void tty_process_input(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
+{
+ char *cmd = buf ? buf->base : NULL; /* To be free()d on return. */
+
+ /* Set output streams */
+ FILE *out = stdout;
+ uv_os_fd_t stream_fd = 0;
+ struct args *args = stream->data;
+ if (uv_fileno((uv_handle_t *)stream, &stream_fd)) {
+ uv_close((uv_handle_t *)stream, (uv_close_cb) free);
+ free(cmd);
+ return;
+ }
+ if (stream_fd != STDIN_FILENO) {
+ if (nread < 0) { /* Close if disconnected */
+ uv_close((uv_handle_t *)stream, (uv_close_cb) free);
+ }
+ if (nread <= 0) {
+ free(cmd);
+ return;
+ }
+ uv_os_fd_t dup_fd = dup(stream_fd);
+ if (dup_fd >= 0) {
+ out = fdopen(dup_fd, "w");
+ }
+ }
+
+ /* Execute */
+ if (stream && cmd && nread > 0) {
+ /* Ensure cmd is 0-terminated */
+ if (cmd[nread - 1] == '\n') {
+ cmd[nread - 1] = '\0';
+ } else {
+ if (nread >= buf->len) { /* only equality should be possible */
+ char *newbuf = realloc(cmd, nread + 1);
+ if (!newbuf)
+ goto finish;
+ cmd = newbuf;
+ }
+ cmd[nread] = '\0';
+ }
+
+ /* Pseudo-command for switching to "binary output"; */
+ if (strcmp(cmd, "__binary") == 0) {
+ args->tty_binary_output = true;
+ goto finish;
+ }
+
+ struct engine *engine = ((struct worker_ctx *)stream->loop->data)->engine;
+ lua_State *L = engine->L;
+ int ret = engine_cmd(L, cmd, false);
+ const char *message = "";
+ if (lua_gettop(L) > 0) {
+ message = lua_tostring(L, -1);
+ }
+
+ /* Simpler output in binary mode */
+ if (args->tty_binary_output) {
+ size_t len_s = strlen(message);
+ if (len_s > UINT32_MAX)
+ goto finish;
+ uint32_t len_n = htonl(len_s);
+ fwrite(&len_n, sizeof(len_n), 1, out);
+ fwrite(message, len_s, 1, out);
+ lua_settop(L, 0);
+ goto finish;
+ }
+
+ /* Log to remote socket if connected */
+ const char *delim = args->quiet ? "" : "> ";
+ if (stream_fd != STDIN_FILENO) {
+ fprintf(stdout, "%s\n", cmd); /* Duplicate command to logs */
+ if (message)
+ fprintf(out, "%s", message); /* Duplicate output to sender */
+ if (message || !args->quiet)
+ fprintf(out, "\n");
+ fprintf(out, "%s", delim);
+ }
+ /* Log to standard streams */
+ FILE *fp_out = ret ? stderr : stdout;
+ if (message)
+ fprintf(fp_out, "%s", message);
+ if (message || !args->quiet)
+ fprintf(fp_out, "\n");
+ fprintf(fp_out, "%s", delim);
+ lua_settop(L, 0);
+ }
+finish:
+ fflush(out);
+ free(cmd);
+ /* Close if redirected */
+ if (stream_fd != STDIN_FILENO) {
+ fclose(out);
+ }
+}
+
+static void tty_alloc(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) {
+ buf->len = suggested;
+ buf->base = malloc(suggested);
+}
+
+static void tty_accept(uv_stream_t *master, int status)
+{
+ uv_tcp_t *client = malloc(sizeof(*client));
+ struct args *args = master->data;
+ if (client) {
+ uv_tcp_init(master->loop, client);
+ if (uv_accept(master, (uv_stream_t *)client) != 0) {
+ free(client);
+ return;
+ }
+ client->data = args;
+ uv_read_start((uv_stream_t *)client, tty_alloc, tty_process_input);
+ /* Write command line */
+ if (!args->quiet) {
+ uv_buf_t buf = { "> ", 2 };
+ uv_try_write((uv_stream_t *)client, &buf, 1);
+ }
+ }
+}
+
+/* @internal AF_LOCAL reads may still be interrupted, loop it. */
+static bool ipc_readall(int fd, char *dst, size_t len)
+{
+ while (len > 0) {
+ int rb = read(fd, dst, len);
+ if (rb > 0) {
+ dst += rb;
+ len -= rb;
+ } else if (errno != EAGAIN && errno != EINTR) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void ipc_activity(uv_poll_t *handle, int status, int events)
+{
+ struct engine *engine = handle->data;
+ if (status != 0) {
+ kr_log_error("[system] ipc: %s\n", uv_strerror(status));
+ return;
+ }
+ /* Get file descriptor from handle */
+ uv_os_fd_t fd = 0;
+ (void) uv_fileno((uv_handle_t *)(handle), &fd);
+ /* Read expression from IPC pipe */
+ uint32_t len = 0;
+ auto_free char *rbuf = NULL;
+ if (!ipc_readall(fd, (char *)&len, sizeof(len))) {
+ goto failure;
+ }
+ if (len < UINT32_MAX) {
+ rbuf = malloc(len + 1);
+ } else {
+ errno = EINVAL;
+ }
+ if (!rbuf) {
+ goto failure;
+ }
+ if (!ipc_readall(fd, rbuf, len)) {
+ goto failure;
+ }
+ rbuf[len] = '\0';
+ /* Run expression */
+ const char *message = "";
+ int ret = engine_ipc(engine, rbuf);
+ if (ret > 0) {
+ message = lua_tostring(engine->L, -1);
+ }
+ /* Clear the Lua stack */
+ lua_settop(engine->L, 0);
+ /* Send response back */
+ len = strlen(message);
+ if (write(fd, &len, sizeof(len)) != sizeof(len) ||
+ write(fd, message, len) != len) {
+ goto failure;
+ }
+ return; /* success! */
+failure:
+ /* Note that if the piped command got read or written partially,
+ * we would get out of sync and only receive rubbish now.
+ * Therefore we prefer to stop IPC, but we try to continue with all else.
+ */
+ kr_log_error("[system] stopping ipc because of: %s\n", strerror(errno));
+ uv_poll_stop(handle);
+ uv_close((uv_handle_t *)handle, (uv_close_cb)free);
+}
+
+static bool ipc_watch(uv_loop_t *loop, struct engine *engine, int fd)
+{
+ uv_poll_t *poller = malloc(sizeof(*poller));
+ if (!poller) {
+ return false;
+ }
+ int ret = uv_poll_init(loop, poller, fd);
+ if (ret != 0) {
+ free(poller);
+ return false;
+ }
+ poller->data = engine;
+ ret = uv_poll_start(poller, UV_READABLE, ipc_activity);
+ if (ret != 0) {
+ free(poller);
+ return false;
+ }
+ /* libuv sets O_NONBLOCK whether we want it or not */
+ (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
+ return true;
+}
+
+static void signal_handler(uv_signal_t *handle, int signum)
+{
+ uv_stop(uv_default_loop());
+ uv_signal_stop(handle);
+}
+
+/** SIGBUS -> attempt to remove the overflowing cache file and abort. */
+static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr)
+{
+ /* We can't safely assume that printf-like functions work, but write() is OK.
+ * See POSIX for the safe functions, e.g. 2017 version just above this link:
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_04
+ */
+ #define WRITE_ERR(err_charray) \
+ (void)write(STDERR_FILENO, err_charray, sizeof(err_charray))
+ /* Unfortunately, void-cast on the write isn't enough to avoid the warning. */
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-result"
+ const char msg_typical[] =
+ "\nSIGBUS received; this is most likely due to filling up the filesystem where cache resides.\n",
+ msg_unknown[] = "\nSIGBUS received, cause unknown.\n",
+ msg_deleted[] = "Cache file deleted.\n",
+ msg_del_fail[] = "Cache file deletion failed.\n",
+ msg_final[] = "kresd can not recover reliably by itself, exiting.\n";
+ if (siginfo->si_code != BUS_ADRERR) {
+ WRITE_ERR(msg_unknown);
+ goto end;
+ }
+ WRITE_ERR(msg_typical);
+ if (!kr_cache_emergency_file_to_remove) goto end;
+ if (unlink(kr_cache_emergency_file_to_remove)) {
+ WRITE_ERR(msg_del_fail);
+ } else {
+ WRITE_ERR(msg_deleted);
+ }
+end:
+ WRITE_ERR(msg_final);
+ _exit(128 - sig); /*< regular return from OS-raised SIGBUS can't work anyway */
+ #undef WRITE_ERR
+ #pragma GCC diagnostic pop
+}
+
+/** Split away port from the address. */
+static const char *set_addr(char *addr, int *port)
+{
+ char *p = strchr(addr, '@');
+ if (!p) {
+ p = strchr(addr, '#');
+ }
+ if (p) {
+ *port = strtol(p + 1, NULL, 10);
+ *p = '\0';
+ }
+
+ return addr;
+}
+
+/*
+ * Server operation.
+ */
+
+static int fork_workers(fd_array_t *ipc_set, int forks)
+{
+ /* Fork subprocesses if requested */
+ while (--forks > 0) {
+ int sv[2] = {-1, -1};
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) < 0) {
+ perror("[system] socketpair");
+ return kr_error(errno);
+ }
+ int pid = fork();
+ if (pid < 0) {
+ perror("[system] fork");
+ return kr_error(errno);
+ }
+
+ /* Forked process */
+ if (pid == 0) {
+ array_clear(*ipc_set);
+ array_push(*ipc_set, sv[0]);
+ close(sv[1]);
+ return forks;
+ /* Parent process */
+ } else {
+ array_push(*ipc_set, sv[1]);
+ /* Do not share parent-end with other forks. */
+ (void) fcntl(sv[1], F_SETFD, FD_CLOEXEC);
+ close(sv[0]);
+ }
+ }
+ return 0;
+}
+
+static void help(int argc, char *argv[])
+{
+ printf("Usage: %s [parameters] [rundir]\n", argv[0]);
+ printf("\nParameters:\n"
+ " -a, --addr=[addr] Server address (default: localhost@53).\n"
+ " -t, --tls=[addr] Server address for TLS (default: off).\n"
+ " -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n"
+ " -T, --tlsfd=[fd] Listen using TLS on given fd (handed out by supervisor).\n"
+ " -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
+ " -k, --keyfile=[path] File with root domain trust anchors (DS or DNSKEY), automatically updated.\n"
+ " -K, --keyfile-ro=[path] File with read-only root domain trust anchors, for use with an external updater.\n"
+ " -m, --moduledir=[path] Override the default module path (" MODULEDIR ").\n"
+ " -f, --forks=N Start N forks sharing the configuration.\n"
+ " -q, --quiet No command prompt in interactive mode.\n"
+ " -v, --verbose Run in verbose mode."
+#ifdef NOVERBOSELOG
+ " (Recompile without -DNOVERBOSELOG to activate.)"
+#endif
+ "\n"
+ " -V, --version Print version of the server.\n"
+ " -h, --help Print help and usage.\n"
+ "Options:\n"
+ " [rundir] Path to the working directory (default: .)\n");
+}
+
+/** \return exit code for main() */
+static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_set, bool leader, struct args *args)
+{
+ /* Only some kinds of stdin work with uv_pipe_t.
+ * Otherwise we would abort() from libuv e.g. with </dev/null */
+ if (args->interactive) switch (uv_guess_handle(0)) {
+ case UV_TTY: /* standard terminal */
+ /* TODO: it has worked OK so far, but we'd better use uv_tty_*
+ * for this case instead of uv_pipe_*. */
+ case UV_NAMED_PIPE: /* echo 'quit()' | kresd ... */
+ break;
+ default:
+ kr_log_error(
+ "[system] error: standard input is not a terminal or pipe; "
+ "use '-f 1' if you want non-interactive mode. "
+ "Commands can be simply added to your configuration file or sent over the tty/$PID control socket.\n"
+ );
+ return 1;
+ }
+
+ /* Control sockets or TTY */
+ auto_free char *sock_file = NULL;
+ uv_pipe_t pipe;
+ uv_pipe_init(loop, &pipe, 0);
+ pipe.data = args;
+ if (args->interactive) {
+ if (!args->quiet)
+ printf("[system] interactive mode\n> ");
+ fflush(stdout);
+ uv_pipe_open(&pipe, 0);
+ uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_process_input);
+ } else {
+ int pipe_ret = -1;
+ if (args->control_fd != -1) {
+ pipe_ret = uv_pipe_open(&pipe, args->control_fd);
+ } else {
+ (void) mkdir("tty", S_IRWXU|S_IRWXG);
+ sock_file = afmt("tty/%ld", (long)getpid());
+ if (sock_file) {
+ pipe_ret = uv_pipe_bind(&pipe, sock_file);
+ }
+ }
+ if (!pipe_ret)
+ uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
+ }
+ /* Watch IPC pipes (or just assign them if leading the pgroup). */
+ if (!leader) {
+ for (size_t i = 0; i < ipc_set->len; ++i) {
+ if (!ipc_watch(loop, engine, ipc_set->at[i])) {
+ kr_log_error("[system] failed to create poller: %s\n", strerror(errno));
+ close(ipc_set->at[i]);
+ }
+ }
+ }
+ memcpy(&engine->ipc_set, ipc_set, sizeof(*ipc_set));
+
+ /* Notify supervisor. */
+#ifdef HAS_SYSTEMD
+ sd_notify(0, "READY=1");
+#endif
+ /* Run event loop */
+ uv_run(loop, UV_RUN_DEFAULT);
+ if (sock_file) {
+ unlink(sock_file);
+ }
+ uv_close((uv_handle_t *)&pipe, NULL); /* Seems OK even on the stopped loop. */
+ return 0;
+}
+
+#ifdef HAS_SYSTEMD
+static void free_sd_socket_names(char **socket_names, int count)
+{
+ for (int i = 0; i < count; i++) {
+ free(socket_names[i]);
+ }
+ free(socket_names);
+}
+#endif
+
+static int set_keyfile(struct engine *engine, char *keyfile, bool unmanaged)
+{
+ assert(keyfile != NULL);
+ auto_free char *cmd = afmt("trust_anchors.config('%s',%s)",
+ keyfile, unmanaged ? "true" : "nil");
+ if (!cmd) {
+ kr_log_error("[system] not enough memory\n");
+ return kr_error(ENOMEM);
+ }
+ int lua_ret = engine_cmd(engine->L, cmd, false);
+ if (lua_ret != 0) {
+ if (lua_gettop(engine->L) > 0) {
+ kr_log_error("%s\n", lua_tostring(engine->L, -1));
+ } else {
+ kr_log_error("[ ta ] keyfile '%s': failed to load (%s)\n",
+ keyfile, lua_strerror(lua_ret));
+ }
+ return lua_ret;
+ }
+
+ lua_settop(engine->L, 0);
+ return kr_ok();
+}
+
+
+static void args_init(struct args *args)
+{
+ memset(args, 0, sizeof(struct args));
+ args->forks = 1;
+ array_init(args->addr_set);
+ array_init(args->tls_set);
+ array_init(args->fd_set);
+ array_init(args->tls_fd_set);
+ args->moduledir = MODULEDIR;
+ args->control_fd = -1;
+ args->interactive = true;
+ args->quiet = false;
+}
+
+static long strtol_10(const char *s)
+{
+ if (!s) abort();
+ /* ^^ This shouldn't ever happen. When getopt_long() returns an option
+ * character that has a mandatory parameter, optarg can't be NULL. */
+ return strtol(s, NULL, 10);
+}
+
+/** Process arguments into struct args.
+ * @return >=0 if main() should be exited immediately.
+ */
+static int parse_args(int argc, char **argv, struct args *args)
+{
+ /* Long options. */
+ int c = 0, li = 0;
+ struct option opts[] = {
+ {"addr", required_argument, 0, 'a'},
+ {"tls", required_argument, 0, 't'},
+ {"fd", required_argument, 0, 'S'},
+ {"tlsfd", required_argument, 0, 'T'},
+ {"config", required_argument, 0, 'c'},
+ {"keyfile", required_argument, 0, 'k'},
+ {"keyfile-ro", required_argument, 0, 'K'},
+ {"forks", required_argument, 0, 'f'},
+ {"moduledir", required_argument, 0, 'm'},
+ {"verbose", no_argument, 0, 'v'},
+ {"quiet", no_argument, 0, 'q'},
+ {"version", no_argument, 0, 'V'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+ while ((c = getopt_long(argc, argv, "a:t:S:T:c:f:m:K:k:vqVh", opts, &li)) != -1) {
+ switch (c)
+ {
+ case 'a':
+ array_push(args->addr_set, optarg);
+ break;
+ case 't':
+ array_push(args->tls_set, optarg);
+ break;
+ case 'S':
+ array_push(args->fd_set, strtol_10(optarg));
+ break;
+ case 'T':
+ array_push(args->tls_fd_set, strtol_10(optarg));
+ break;
+ case 'c':
+ args->config = optarg;
+ break;
+ case 'f':
+ args->interactive = false;
+ args->forks = strtol_10(optarg);
+ if (args->forks <= 0) {
+ kr_log_error("[system] error '-f' requires a positive"
+ " number, not '%s'\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'K':
+ args->keyfile_unmanaged = 1;
+ case 'k':
+ if (args->keyfile != NULL) {
+ kr_log_error("[system] error only one of '--keyfile' and '--keyfile-ro' allowed\n");
+ return EXIT_FAILURE;
+ }
+ args->keyfile = optarg;
+ break;
+ case 'm':
+ args->moduledir = optarg;
+ break;
+ case 'v':
+ kr_verbose_set(true);
+#ifdef NOVERBOSELOG
+ kr_log_info("--verbose flag has no effect due to compilation with -DNOVERBOSELOG.\n");
+#endif
+ break;
+ case 'q':
+ args->quiet = true;
+ break;
+ case 'V':
+ kr_log_info("%s, version %s\n", "Knot Resolver", PACKAGE_VERSION);
+ return EXIT_SUCCESS;
+ case 'h':
+ case '?':
+ help(argc, argv);
+ return EXIT_SUCCESS;
+ default:
+ help(argc, argv);
+ return EXIT_FAILURE;
+ }
+ }
+ if (optind < argc) {
+ args->rundir = argv[optind];
+ }
+ return -1;
+}
+
+static int bind_fds(struct network *net, fd_array_t *fd_set, bool tls) {
+ int ret = 0;
+ for (size_t i = 0; i < fd_set->len; ++i) {
+ ret = network_listen_fd(net, fd_set->at[i], tls);
+ if (ret != 0) {
+ kr_log_error("[system] %slisten on fd=%d %s\n",
+ tls ? "TLS " : "", fd_set->at[i], kr_strerror(ret));
+ break;
+ }
+ }
+ return ret;
+}
+
+static int bind_sockets(struct network *net, addr_array_t *addr_set, bool tls) {
+ uint32_t flags = tls ? NET_TCP|NET_TLS : NET_UDP|NET_TCP;
+ int ret = 0;
+ for (size_t i = 0; i < addr_set->len; ++i) {
+ int port = tls ? KR_DNS_TLS_PORT : KR_DNS_PORT;
+ const char *addr = set_addr(addr_set->at[i], &port);
+ ret = network_listen(net, addr, (uint16_t)port, flags);
+ if (ret != 0) {
+ kr_log_error("[system] bind to '%s@%d' %s%s\n",
+ addr, port, tls ? "(TLS) " : "", kr_strerror(ret));
+ break;
+ }
+ }
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+ struct args args;
+ args_init(&args);
+ if ((ret = parse_args(argc, argv, &args)) >= 0) {
+ return ret;
+ }
+
+#ifdef HAS_SYSTEMD
+ /* Accept passed sockets from systemd supervisor. */
+ char **socket_names = NULL;
+ int sd_nsocks = sd_listen_fds_with_names(0, &socket_names);
+ for (int i = 0; i < sd_nsocks; ++i) {
+ int fd = SD_LISTEN_FDS_START + i;
+ /* when run under systemd supervision, do not use interactive mode */
+ args.interactive = false;
+ if (args.forks != 1) {
+ kr_log_error("[system] when run under systemd-style supervision, "
+ "use single-process only (bad: --forks=%d).\n", args.forks);
+ free_sd_socket_names(socket_names, sd_nsocks);
+ return EXIT_FAILURE;
+ }
+ if (!strcasecmp("control",socket_names[i])) {
+ args.control_fd = fd;
+ } else if (!strcasecmp("tls",socket_names[i])) {
+ array_push(args.tls_fd_set, fd);
+ } else {
+ array_push(args.fd_set, fd);
+ }
+ }
+ free_sd_socket_names(socket_names, sd_nsocks);
+#endif
+
+ /* Switch to rundir. */
+ if (args.rundir != NULL) {
+ /* FIXME: access isn't a good way if we start as root and drop privileges later */
+ if (access(args.rundir, W_OK) != 0) {
+ kr_log_error("[system] rundir '%s': %s\n", args.rundir, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ ret = chdir(args.rundir);
+ if (ret != 0) {
+ kr_log_error("[system] rundir '%s': %s\n", args.rundir, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (args.config && strcmp(args.config, "-") != 0 && access(args.config, R_OK) != 0) {
+ kr_log_error("[system] config '%s': %s\n", args.config, strerror(errno));
+ return EXIT_FAILURE;
+ }
+ if (!args.config && access("config", R_OK) == 0) {
+ args.config = "config";
+ }
+
+#ifndef CAN_FORK_EARLY
+ /* Forking is currently broken with libuv. We need libuv to bind to
+ * sockets etc. before forking, but at the same time can't touch it before
+ * forking otherwise it crashes, so it's a chicken and egg problem.
+ * Disabling until https://github.com/libuv/libuv/pull/846 is done. */
+ if (args.forks > 1 && args.fd_set.len == 0 && args.tls_fd_set.len == 0) {
+ kr_log_error("[system] forking >1 workers supported only on Linux 3.9+ or with supervisor\n");
+ return EXIT_FAILURE;
+ }
+#endif
+
+ /* Connect forks with local socket */
+ fd_array_t ipc_set;
+ array_init(ipc_set);
+ /* Fork subprocesses if requested */
+ int fork_id = fork_workers(&ipc_set, args.forks);
+ if (fork_id < 0) {
+ return EXIT_FAILURE;
+ }
+
+ kr_crypto_init();
+
+ /* Create a server engine. */
+ knot_mm_t pool = {
+ .ctx = mp_new (4096),
+ .alloc = (knot_mm_alloc_t) mp_alloc
+ };
+ struct engine engine;
+ ret = engine_init(&engine, &pool);
+ if (ret != 0) {
+ kr_log_error("[system] failed to initialize engine: %s\n", kr_strerror(ret));
+ return EXIT_FAILURE;
+ }
+ /* Create worker */
+ struct worker_ctx *worker = worker_create(&engine, &pool, fork_id, args.forks);
+ if (!worker) {
+ kr_log_error("[system] not enough memory\n");
+ return EXIT_FAILURE;
+ }
+
+ uv_loop_t *loop = uv_default_loop();
+ worker->loop = loop;
+ loop->data = worker;
+
+ /* Catch some signals. */
+ uv_signal_t sigint, sigterm;
+ if (true) ret = uv_signal_init(loop, &sigint);
+ if (!ret) ret = uv_signal_init(loop, &sigterm);
+ if (!ret) ret = uv_signal_start(&sigint, signal_handler, SIGINT);
+ if (!ret) ret = uv_signal_start(&sigterm, signal_handler, SIGTERM);
+ /* Block SIGPIPE; see https://github.com/libuv/libuv/issues/45 */
+ if (!ret && signal(SIGPIPE, SIG_IGN) == SIG_ERR) ret = errno;
+ if (!ret) {
+ /* Catching SIGBUS via uv_signal_* can't work; see:
+ * https://github.com/libuv/libuv/pull/1987 */
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = sigbus_handler;
+ sa.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGBUS, &sa, NULL)) {
+ ret = errno;
+ }
+ }
+ if (ret) {
+ kr_log_error("[system] failed to set up signal handlers: %s\n",
+ strerror(abs(errno)));
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+
+ /* Bind to passed fds and sockets*/
+ if (bind_fds(&engine.net, &args.fd_set, false) != 0 ||
+ bind_fds(&engine.net, &args.tls_fd_set, true) != 0 ||
+ bind_sockets(&engine.net, &args.addr_set, false) != 0 ||
+ bind_sockets(&engine.net, &args.tls_set, true) != 0
+ ) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+
+ /* Start the scripting engine */
+ engine_set_moduledir(&engine, args.moduledir);
+
+ if (engine_load_sandbox(&engine) != 0) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+ if (args.config != NULL && strcmp(args.config, "-") != 0) {
+ if(engine_loadconf(&engine, args.config) != 0) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+ lua_settop(engine.L, 0);
+ }
+ if (args.keyfile != NULL && set_keyfile(&engine, args.keyfile, args.keyfile_unmanaged) != 0) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+ if (args.config == NULL || strcmp(args.config, "-") !=0) {
+ if(engine_load_defaults(&engine) != 0) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+ }
+ if (engine_start(&engine) != 0) {
+ ret = EXIT_FAILURE;
+ goto cleanup;
+ }
+
+ /* Run the event loop */
+ ret = run_worker(loop, &engine, &ipc_set, fork_id == 0, &args);
+
+cleanup:/* Cleanup. */
+ engine_deinit(&engine);
+ worker_reclaim(worker);
+ if (loop != NULL) {
+ uv_loop_close(loop);
+ }
+ mp_delete(pool.ctx);
+ array_clear(args.addr_set);
+ array_clear(args.tls_set);
+ kr_crypto_cleanup();
+ return ret;
+}
diff --git a/daemon/network.c b/daemon/network.c
new file mode 100644
index 0000000..6a148bb
--- /dev/null
+++ b/daemon/network.c
@@ -0,0 +1,446 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <unistd.h>
+#include <assert.h>
+#include "daemon/network.h"
+#include "daemon/worker.h"
+#include "daemon/io.h"
+#include "daemon/tls.h"
+
+/* libuv 1.7.0+ is able to support SO_REUSEPORT for loadbalancing */
+#if defined(UV_VERSION_HEX)
+#if (__linux__ && SO_REUSEPORT)
+ #define handle_init(type, loop, handle, family) do { \
+ uv_ ## type ## _init_ex((loop), (handle), (family)); \
+ uv_os_fd_t hi_fd = 0; \
+ if (uv_fileno((uv_handle_t *)(handle), &hi_fd) == 0) { \
+ int hi_on = 1; \
+ int hi_ret = setsockopt(hi_fd, SOL_SOCKET, SO_REUSEPORT, &hi_on, sizeof(hi_on)); \
+ if (hi_ret) { \
+ return hi_ret; \
+ } \
+ } \
+ } while (0)
+/* libuv 1.7.0+ is able to assign fd immediately */
+#else
+ #define handle_init(type, loop, handle, family) do { \
+ uv_ ## type ## _init_ex((loop), (handle), (family)); \
+ } while (0)
+#endif
+#else
+ #define handle_init(type, loop, handle, family) \
+ uv_ ## type ## _init((loop), (handle))
+#endif
+
+void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog)
+{
+ if (net != NULL) {
+ net->loop = loop;
+ net->endpoints = map_make(NULL);
+ net->tls_client_params = map_make(NULL);
+ net->tls_session_ticket_ctx = /* unsync. random, by default */
+ tls_session_ticket_ctx_create(loop, NULL, 0);
+ net->tcp.in_idle_timeout = 10000;
+ net->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
+ net->tcp_backlog = tcp_backlog;
+ }
+}
+
+static void close_handle(uv_handle_t *handle, bool force)
+{
+ if (force) { /* Force close if event loop isn't running. */
+ uv_os_fd_t fd = 0;
+ if (uv_fileno(handle, &fd) == 0) {
+ close(fd);
+ }
+ handle->loop = NULL;
+ io_free(handle);
+ } else { /* Asynchronous close */
+ uv_close(handle, io_free);
+ }
+}
+
+static int close_endpoint(struct endpoint *ep, bool force)
+{
+ if (ep->udp) {
+ close_handle((uv_handle_t *)ep->udp, force);
+ }
+ if (ep->tcp) {
+ close_handle((uv_handle_t *)ep->tcp, force);
+ }
+
+ free(ep);
+ return kr_ok();
+}
+
+/** Endpoint visitor (see @file map.h) */
+static int close_key(const char *key, void *val, void *ext)
+{
+ endpoint_array_t *ep_array = val;
+ for (size_t i = ep_array->len; i--;) {
+ close_endpoint(ep_array->at[i], true);
+ }
+ return 0;
+}
+
+static int free_key(const char *key, void *val, void *ext)
+{
+ endpoint_array_t *ep_array = val;
+ array_clear(*ep_array);
+ free(ep_array);
+ return kr_ok();
+}
+
+void network_deinit(struct network *net)
+{
+ if (net != NULL) {
+ map_walk(&net->endpoints, close_key, 0);
+ map_walk(&net->endpoints, free_key, 0);
+ map_clear(&net->endpoints);
+ tls_credentials_free(net->tls_credentials);
+ tls_client_params_free(&net->tls_client_params);
+ net->tls_credentials = NULL;
+ tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
+ net->tcp.in_idle_timeout = 0;
+ }
+}
+
+/** Fetch or create endpoint array and insert endpoint. */
+static int insert_endpoint(struct network *net, const char *addr, struct endpoint *ep)
+{
+ /* Fetch or insert address into map */
+ endpoint_array_t *ep_array = map_get(&net->endpoints, addr);
+ if (ep_array == NULL) {
+ ep_array = malloc(sizeof(*ep_array));
+ if (ep_array == NULL) {
+ return kr_error(ENOMEM);
+ }
+ if (map_set(&net->endpoints, addr, ep_array) != 0) {
+ free(ep_array);
+ return kr_error(ENOMEM);
+ }
+ array_init(*ep_array);
+ }
+
+ if (array_push(*ep_array, ep) < 0) {
+ return kr_error(ENOMEM);
+ }
+ return kr_ok();
+}
+
+/** Open endpoint protocols. */
+static int open_endpoint(struct network *net, struct endpoint *ep, struct sockaddr *sa, uint32_t flags)
+{
+ int ret = 0;
+ if (flags & NET_UDP) {
+ ep->udp = malloc(sizeof(*ep->udp));
+ if (!ep->udp) {
+ return kr_error(ENOMEM);
+ }
+ memset(ep->udp, 0, sizeof(*ep->udp));
+ handle_init(udp, net->loop, ep->udp, sa->sa_family); /* can return! */
+ ret = udp_bind(ep->udp, sa);
+ if (ret != 0) {
+ return ret;
+ }
+ ep->flags |= NET_UDP;
+ }
+ if (flags & NET_TCP) {
+ ep->tcp = malloc(sizeof(*ep->tcp));
+ if (!ep->tcp) {
+ return kr_error(ENOMEM);
+ }
+ memset(ep->tcp, 0, sizeof(*ep->tcp));
+ handle_init(tcp, net->loop, ep->tcp, sa->sa_family); /* can return! */
+ if (flags & NET_TLS) {
+ ret = tcp_bind_tls(ep->tcp, sa, net->tcp_backlog);
+ ep->flags |= NET_TLS;
+ } else {
+ ret = tcp_bind(ep->tcp, sa, net->tcp_backlog);
+ }
+ if (ret != 0) {
+ return ret;
+ }
+ ep->flags |= NET_TCP;
+ }
+ return ret;
+}
+
+/** Open fd as endpoint. */
+static int open_endpoint_fd(struct network *net, struct endpoint *ep, int fd, int sock_type, bool use_tls)
+{
+ int ret = kr_ok();
+ if (sock_type == SOCK_DGRAM) {
+ if (use_tls) {
+ /* we do not support TLS over UDP */
+ return kr_error(EBADF);
+ }
+ if (ep->udp) {
+ return kr_error(EEXIST);
+ }
+ ep->udp = malloc(sizeof(*ep->udp));
+ if (!ep->udp) {
+ return kr_error(ENOMEM);
+ }
+ uv_udp_init(net->loop, ep->udp);
+ ret = udp_bindfd(ep->udp, fd);
+ if (ret != 0) {
+ close_handle((uv_handle_t *)ep->udp, false);
+ return ret;
+ }
+ ep->flags |= NET_UDP;
+ return kr_ok();
+ } else if (sock_type == SOCK_STREAM) {
+ if (ep->tcp) {
+ return kr_error(EEXIST);
+ }
+ ep->tcp = malloc(sizeof(*ep->tcp));
+ if (!ep->tcp) {
+ return kr_error(ENOMEM);
+ }
+ uv_tcp_init(net->loop, ep->tcp);
+ if (use_tls) {
+ ret = tcp_bindfd_tls(ep->tcp, fd, net->tcp_backlog);
+ ep->flags |= NET_TLS;
+ } else {
+ ret = tcp_bindfd(ep->tcp, fd, net->tcp_backlog);
+ }
+ if (ret != 0) {
+ close_handle((uv_handle_t *)ep->tcp, false);
+ return ret;
+ }
+ ep->flags |= NET_TCP;
+ return kr_ok();
+ }
+ return kr_error(EINVAL);
+}
+
+/** @internal Fetch endpoint array and offset of the address/port query. */
+static endpoint_array_t *network_get(struct network *net, const char *addr, uint16_t port, size_t *index)
+{
+ endpoint_array_t *ep_array = map_get(&net->endpoints, addr);
+ if (ep_array) {
+ for (size_t i = ep_array->len; i--;) {
+ struct endpoint *ep = ep_array->at[i];
+ if (ep->port == port) {
+ *index = i;
+ return ep_array;
+ }
+ }
+ }
+ return NULL;
+}
+
+int network_listen_fd(struct network *net, int fd, bool use_tls)
+{
+ /* Extract local address and socket type. */
+ int sock_type = SOCK_DGRAM;
+ socklen_t len = sizeof(sock_type);
+ int ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &sock_type, &len);
+ if (ret != 0) {
+ return kr_error(EBADF);
+ }
+ /* Extract local address for this socket. */
+ struct sockaddr_storage ss = { .ss_family = AF_UNSPEC };
+ socklen_t addr_len = sizeof(ss);
+ ret = getsockname(fd, (struct sockaddr *)&ss, &addr_len);
+ if (ret != 0) {
+ return kr_error(EBADF);
+ }
+ int port = 0;
+ char addr_str[INET6_ADDRSTRLEN]; /* https://tools.ietf.org/html/rfc4291 */
+ if (ss.ss_family == AF_INET) {
+ uv_ip4_name((const struct sockaddr_in*)&ss, addr_str, sizeof(addr_str));
+ port = ntohs(((struct sockaddr_in *)&ss)->sin_port);
+ } else if (ss.ss_family == AF_INET6) {
+ uv_ip6_name((const struct sockaddr_in6*)&ss, addr_str, sizeof(addr_str));
+ port = ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
+ } else {
+ return kr_error(EAFNOSUPPORT);
+ }
+
+ /* always create endpoint for supervisor supplied fd
+ * even if addr+port is not unique */
+ struct endpoint *ep = malloc(sizeof(*ep));
+ memset(ep, 0, sizeof(*ep));
+ ep->flags = NET_DOWN;
+ ep->port = port;
+ ret = insert_endpoint(net, addr_str, ep);
+ if (ret != 0) {
+ return ret;
+ }
+ /* Create a libuv struct for this socket. */
+ return open_endpoint_fd(net, ep, fd, sock_type, use_tls);
+}
+
+int network_listen(struct network *net, const char *addr, uint16_t port, uint32_t flags)
+{
+ if (net == NULL || addr == 0 || port == 0) {
+ return kr_error(EINVAL);
+ }
+
+ /* Already listening */
+ size_t index = 0;
+ if (network_get(net, addr, port, &index)) {
+ return kr_ok();
+ }
+
+ /* Parse address. */
+ int ret = 0;
+ struct sockaddr_storage sa;
+ if (strchr(addr, ':') != NULL) {
+ ret = uv_ip6_addr(addr, port, (struct sockaddr_in6 *)&sa);
+ } else {
+ ret = uv_ip4_addr(addr, port, (struct sockaddr_in *)&sa);
+ }
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Bind interfaces */
+ struct endpoint *ep = malloc(sizeof(*ep));
+ memset(ep, 0, sizeof(*ep));
+ ep->flags = NET_DOWN;
+ ep->port = port;
+ ret = open_endpoint(net, ep, (struct sockaddr *)&sa, flags);
+ if (ret == 0) {
+ ret = insert_endpoint(net, addr, ep);
+ }
+ if (ret != 0) {
+ close_endpoint(ep, false);
+ }
+
+ return ret;
+}
+
+int network_close(struct network *net, const char *addr, uint16_t port)
+{
+ size_t index = 0;
+ endpoint_array_t *ep_array = network_get(net, addr, port, &index);
+ if (!ep_array) {
+ return kr_error(ENOENT);
+ }
+
+ /* Close endpoint in array. */
+ close_endpoint(ep_array->at[index], false);
+ array_del(*ep_array, index);
+
+ /* Collapse key if it has no endpoint. */
+ if (ep_array->len == 0) {
+ free(ep_array);
+ map_del(&net->endpoints, addr);
+ }
+
+ return kr_ok();
+}
+
+void network_new_hostname(struct network *net, struct engine *engine)
+{
+ if (net->tls_credentials &&
+ net->tls_credentials->ephemeral_servicename) {
+ struct tls_credentials *newcreds;
+ newcreds = tls_get_ephemeral_credentials(engine);
+ if (newcreds) {
+ tls_credentials_release(net->tls_credentials);
+ net->tls_credentials = newcreds;
+ kr_log_info("[tls] Updated ephemeral X.509 cert with new hostname\n");
+ } else {
+ kr_log_error("[tls] Failed to update ephemeral X.509 cert with new hostname, using existing one\n");
+ }
+ }
+}
+
+static int set_bpf_cb(const char *key, void *val, void *ext)
+{
+#ifdef SO_ATTACH_BPF
+ endpoint_array_t *endpoints = (endpoint_array_t *)val;
+ assert(endpoints != NULL);
+ int *bpffd = (int *)ext;
+ assert(bpffd != NULL);
+
+ for (size_t i = 0; i < endpoints->len; i++) {
+ struct endpoint *endpoint = (struct endpoint *)endpoints->at[i];
+ uv_os_fd_t sockfd = -1;
+ if (endpoint->tcp != NULL) uv_fileno((const uv_handle_t *)endpoint->tcp, &sockfd);
+ if (endpoint->udp != NULL) uv_fileno((const uv_handle_t *)endpoint->udp, &sockfd);
+ assert(sockfd != -1);
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_BPF, bpffd, sizeof(int)) != 0) {
+ return 1; /* return error (and stop iterating over net->endpoints) */
+ }
+ }
+#else
+ kr_log_error("[network] SO_ATTACH_BPF socket option doesn't supported\n");
+ (void)key; (void)val; (void)ext;
+ return 1;
+#endif
+ return 0; /* OK */
+}
+
+int network_set_bpf(struct network *net, int bpf_fd)
+{
+#ifdef SO_ATTACH_BPF
+ if (map_walk(&net->endpoints, set_bpf_cb, &bpf_fd) != 0) {
+ /* set_bpf_cb() has returned error. */
+ network_clear_bpf(net);
+ return 0;
+ }
+#else
+ kr_log_error("[network] SO_ATTACH_BPF socket option doesn't supported\n");
+ (void)net;
+ (void)bpf_fd;
+ return 0;
+#endif
+ return 1;
+}
+
+static int clear_bpf_cb(const char *key, void *val, void *ext)
+{
+#ifdef SO_DETACH_BPF
+ endpoint_array_t *endpoints = (endpoint_array_t *)val;
+ assert(endpoints != NULL);
+
+ for (size_t i = 0; i < endpoints->len; i++) {
+ struct endpoint *endpoint = (struct endpoint *)endpoints->at[i];
+ uv_os_fd_t sockfd = -1;
+ if (endpoint->tcp != NULL) uv_fileno((const uv_handle_t *)endpoint->tcp, &sockfd);
+ if (endpoint->udp != NULL) uv_fileno((const uv_handle_t *)endpoint->udp, &sockfd);
+ assert(sockfd != -1);
+
+ if (setsockopt(sockfd, SOL_SOCKET, SO_DETACH_BPF, NULL, 0) != 0) {
+ kr_log_error("[network] failed to clear SO_DETACH_BPF socket option\n");
+ }
+ /* Proceed even if setsockopt() failed,
+ * as we want to process all opened sockets. */
+ }
+#else
+ kr_log_error("[network] SO_DETACH_BPF socket option doesn't supported\n");
+ (void)key; (void)val; (void)ext;
+ return 1;
+#endif
+ return 0;
+}
+
+void network_clear_bpf(struct network *net)
+{
+#ifdef SO_DETACH_BPF
+ map_walk(&net->endpoints, clear_bpf_cb, NULL);
+#else
+ kr_log_error("[network] SO_DETACH_BPF socket option doesn't supported\n");
+ (void)net;
+#endif
+}
diff --git a/daemon/network.h b/daemon/network.h
new file mode 100644
index 0000000..11e1feb
--- /dev/null
+++ b/daemon/network.h
@@ -0,0 +1,70 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <uv.h>
+#include <stdbool.h>
+
+#include "lib/generic/array.h"
+#include "lib/generic/map.h"
+
+struct engine;
+
+enum endpoint_flag {
+ NET_DOWN = 0 << 0,
+ NET_UDP = 1 << 0,
+ NET_TCP = 1 << 1,
+ NET_TLS = 1 << 2,
+};
+
+struct endpoint {
+ uv_udp_t *udp;
+ uv_tcp_t *tcp;
+ uint16_t port;
+ uint16_t flags;
+};
+
+/** @cond internal Array of endpoints */
+typedef array_t(struct endpoint*) endpoint_array_t;
+/* @endcond */
+
+struct net_tcp_param {
+ uint64_t in_idle_timeout;
+ uint64_t tls_handshake_timeout;
+};
+
+struct tls_session_ticket_ctx;
+struct network {
+ uv_loop_t *loop;
+ map_t endpoints;
+ struct tls_credentials *tls_credentials;
+ map_t tls_client_params;
+ struct tls_session_ticket_ctx *tls_session_ticket_ctx;
+ struct net_tcp_param tcp;
+ int tcp_backlog;
+};
+
+void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog);
+void network_deinit(struct network *net);
+int network_listen_fd(struct network *net, int fd, bool use_tls);
+int network_listen(struct network *net, const char *addr, uint16_t port, uint32_t flags);
+int network_close(struct network *net, const char *addr, uint16_t port);
+int network_set_tls_cert(struct network *net, const char *cert);
+int network_set_tls_key(struct network *net, const char *key);
+void network_new_hostname(struct network *net, struct engine *engine);
+int network_set_bpf(struct network *net, int bpf_fd);
+void network_clear_bpf(struct network *net);
diff --git a/daemon/session.c b/daemon/session.c
new file mode 100644
index 0000000..c870d8c
--- /dev/null
+++ b/daemon/session.c
@@ -0,0 +1,767 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include <libknot/packet/pkt.h>
+
+#include "lib/defines.h"
+#include "daemon/session.h"
+#include "daemon/engine.h"
+#include "daemon/tls.h"
+#include "daemon/worker.h"
+#include "daemon/io.h"
+#include "lib/generic/queue.h"
+
+#define TLS_CHUNK_SIZE (16 * 1024)
+
+/* Per-session (TCP or UDP) persistent structure,
+ * that exists between remote counterpart and a local socket.
+ */
+struct session {
+ struct session_flags sflags; /**< miscellaneous flags. */
+ union inaddr peer; /**< address of peer; is not set for client's UDP sessions. */
+ uv_handle_t *handle; /**< libuv handle for IO operations. */
+ uv_timer_t timeout; /**< libuv handle for timer. */
+
+ struct tls_ctx_t *tls_ctx; /**< server side tls-related data. */
+ struct tls_client_ctx_t *tls_client_ctx; /**< client side tls-related data. */
+
+ trie_t *tasks; /**< list of tasks assotiated with given session. */
+ queue_t(struct qr_task *) waiting; /**< list of tasks waiting for sending to upstream. */
+
+ uint8_t *wire_buf; /**< Buffer for DNS message. */
+ ssize_t wire_buf_size; /**< Buffer size. */
+ ssize_t wire_buf_start_idx; /**< Data start offset in wire_buf. */
+ ssize_t wire_buf_end_idx; /**< Data end offset in wire_buf. */
+ uint64_t last_activity; /**< Time of last IO activity (if any occurs).
+ * Otherwise session creation time. */
+};
+
+static void on_session_close(uv_handle_t *handle)
+{
+ struct session *session = handle->data;
+ assert(session->handle == handle); (void)session;
+ io_free(handle);
+}
+
+static void on_session_timer_close(uv_handle_t *timer)
+{
+ struct session *session = timer->data;
+ uv_handle_t *handle = session->handle;
+ assert(handle && handle->data == session);
+ assert (session->sflags.outgoing || handle->type == UV_TCP);
+ if (!uv_is_closing(handle)) {
+ uv_close(handle, on_session_close);
+ }
+}
+
+void session_free(struct session *session)
+{
+ if (session) {
+ assert(session_is_empty(session));
+ session_clear(session);
+ free(session);
+ }
+}
+
+void session_clear(struct session *session)
+{
+ assert(session_is_empty(session));
+ if (session->handle && session->handle->type == UV_TCP) {
+ free(session->wire_buf);
+ }
+ trie_clear(session->tasks);
+ trie_free(session->tasks);
+ queue_deinit(session->waiting);
+ tls_free(session->tls_ctx);
+ tls_client_ctx_free(session->tls_client_ctx);
+ memset(session, 0, sizeof(*session));
+}
+
+void session_close(struct session *session)
+{
+ assert(session_is_empty(session));
+ if (session->sflags.closing) {
+ return;
+ }
+
+ uv_handle_t *handle = session->handle;
+ io_stop_read(handle);
+ session->sflags.closing = true;
+
+ if (!uv_is_closing((uv_handle_t *)&session->timeout)) {
+ uv_timer_stop(&session->timeout);
+ if (session->tls_client_ctx) {
+ tls_close(&session->tls_client_ctx->c);
+ }
+ if (session->tls_ctx) {
+ tls_close(&session->tls_ctx->c);
+ }
+
+ session->timeout.data = session;
+ uv_close((uv_handle_t *)&session->timeout, on_session_timer_close);
+ }
+}
+
+int session_start_read(struct session *session)
+{
+ return io_start_read(session->handle);
+}
+
+int session_stop_read(struct session *session)
+{
+ return io_stop_read(session->handle);
+}
+
+int session_waitinglist_push(struct session *session, struct qr_task *task)
+{
+ queue_push(session->waiting, task);
+ worker_task_ref(task);
+ return kr_ok();
+}
+
+struct qr_task *session_waitinglist_get(const struct session *session)
+{
+ return (queue_len(session->waiting) > 0) ? (queue_head(session->waiting)) : NULL;
+}
+
+struct qr_task *session_waitinglist_pop(struct session *session, bool deref)
+{
+ struct qr_task *t = session_waitinglist_get(session);
+ queue_pop(session->waiting);
+ if (deref) {
+ worker_task_unref(t);
+ }
+ return t;
+}
+
+int session_tasklist_add(struct session *session, struct qr_task *task)
+{
+ trie_t *t = session->tasks;
+ uint16_t task_msg_id = 0;
+ const char *key = NULL;
+ size_t key_len = 0;
+ if (session->sflags.outgoing) {
+ knot_pkt_t *pktbuf = worker_task_get_pktbuf(task);
+ task_msg_id = knot_wire_get_id(pktbuf->wire);
+ key = (const char *)&task_msg_id;
+ key_len = sizeof(task_msg_id);
+ } else {
+ key = (const char *)&task;
+ key_len = sizeof(char *);
+ }
+ trie_val_t *v = trie_get_ins(t, key, key_len);
+ if (unlikely(!v)) {
+ assert(false);
+ return kr_error(ENOMEM);
+ }
+ if (*v == NULL) {
+ *v = task;
+ worker_task_ref(task);
+ } else if (*v != task) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ return kr_ok();
+}
+
+int session_tasklist_del(struct session *session, struct qr_task *task)
+{
+ trie_t *t = session->tasks;
+ uint16_t task_msg_id = 0;
+ const char *key = NULL;
+ size_t key_len = 0;
+ trie_val_t val;
+ if (session->sflags.outgoing) {
+ knot_pkt_t *pktbuf = worker_task_get_pktbuf(task);
+ task_msg_id = knot_wire_get_id(pktbuf->wire);
+ key = (const char *)&task_msg_id;
+ key_len = sizeof(task_msg_id);
+ } else {
+ key = (const char *)&task;
+ key_len = sizeof(char *);
+ }
+ int ret = trie_del(t, key, key_len, &val);
+ if (ret == kr_ok()) {
+ assert(val == task);
+ worker_task_unref(val);
+ }
+ return ret;
+}
+
+struct qr_task *session_tasklist_get_first(struct session *session)
+{
+ trie_val_t *val = trie_get_first(session->tasks, NULL, NULL);
+ return val ? (struct qr_task *) *val : NULL;
+}
+
+struct qr_task *session_tasklist_del_first(struct session *session, bool deref)
+{
+ trie_val_t val = NULL;
+ int res = trie_del_first(session->tasks, NULL, NULL, &val);
+ if (res != kr_ok()) {
+ val = NULL;
+ } else if (deref) {
+ worker_task_unref(val);
+ }
+ return (struct qr_task *)val;
+}
+struct qr_task* session_tasklist_del_msgid(const struct session *session, uint16_t msg_id)
+{
+ trie_t *t = session->tasks;
+ assert(session->sflags.outgoing);
+ struct qr_task *ret = NULL;
+ const char *key = (const char *)&msg_id;
+ size_t key_len = sizeof(msg_id);
+ trie_val_t val;
+ int res = trie_del(t, key, key_len, &val);
+ if (res == kr_ok()) {
+ if (worker_task_numrefs(val) > 1) {
+ ret = val;
+ }
+ worker_task_unref(val);
+ }
+ return ret;
+}
+
+struct qr_task* session_tasklist_find_msgid(const struct session *session, uint16_t msg_id)
+{
+ trie_t *t = session->tasks;
+ assert(session->sflags.outgoing);
+ struct qr_task *ret = NULL;
+ trie_val_t *val = trie_get_try(t, (char *)&msg_id, sizeof(msg_id));
+ if (val) {
+ ret = *val;
+ }
+ return ret;
+}
+
+struct session_flags *session_flags(struct session *session)
+{
+ return &session->sflags;
+}
+
+struct sockaddr *session_get_peer(struct session *session)
+{
+ return &session->peer.ip;
+}
+
+struct tls_ctx_t *session_tls_get_server_ctx(const struct session *session)
+{
+ return session->tls_ctx;
+}
+
+void session_tls_set_server_ctx(struct session *session, struct tls_ctx_t *ctx)
+{
+ session->tls_ctx = ctx;
+}
+
+struct tls_client_ctx_t *session_tls_get_client_ctx(const struct session *session)
+{
+ return session->tls_client_ctx;
+}
+
+void session_tls_set_client_ctx(struct session *session, struct tls_client_ctx_t *ctx)
+{
+ session->tls_client_ctx = ctx;
+}
+
+struct tls_common_ctx *session_tls_get_common_ctx(const struct session *session)
+{
+ struct tls_common_ctx *tls_ctx = session->sflags.outgoing ? &session->tls_client_ctx->c :
+ &session->tls_ctx->c;
+ return tls_ctx;
+}
+
+uv_handle_t *session_get_handle(struct session *session)
+{
+ return session->handle;
+}
+
+struct session *session_get(uv_handle_t *h)
+{
+ return h->data;
+}
+
+struct session *session_new(uv_handle_t *handle, bool has_tls)
+{
+ if (!handle) {
+ return NULL;
+ }
+ struct session *session = calloc(1, sizeof(struct session));
+ if (!session) {
+ return NULL;
+ }
+
+ queue_init(session->waiting);
+ session->tasks = trie_create(NULL);
+ if (handle->type == UV_TCP) {
+ size_t wire_buffer_size = KNOT_WIRE_MAX_PKTSIZE;
+ if (has_tls) {
+ /* When decoding large packets,
+ * gnutls gives the application chunks of size 16 kb each. */
+ wire_buffer_size += TLS_CHUNK_SIZE;
+ session->sflags.has_tls = true;
+ }
+ uint8_t *wire_buf = malloc(wire_buffer_size);
+ if (!wire_buf) {
+ free(session);
+ return NULL;
+ }
+ session->wire_buf = wire_buf;
+ session->wire_buf_size = wire_buffer_size;
+ } else if (handle->type == UV_UDP) {
+ /* We use the singleton buffer from worker for all UDP (!)
+ * libuv documentation doesn't really guarantee this is OK,
+ * but the implementation for unix systems does not hold
+ * the buffer (both UDP and TCP) - always makes a NON-blocking
+ * syscall that fills the buffer and immediately calls
+ * the callback, whatever the result of the operation.
+ * We still need to keep in mind to only touch the buffer
+ * in this callback... */
+ assert(handle->loop->data);
+ struct worker_ctx *worker = handle->loop->data;
+ session->wire_buf = worker->wire_buf;
+ session->wire_buf_size = sizeof(worker->wire_buf);
+ }
+
+ uv_timer_init(handle->loop, &session->timeout);
+
+ session->handle = handle;
+ handle->data = session;
+ session->timeout.data = session;
+ session_touch(session);
+
+ return session;
+}
+
+size_t session_tasklist_get_len(const struct session *session)
+{
+ return trie_weight(session->tasks);
+}
+
+size_t session_waitinglist_get_len(const struct session *session)
+{
+ return queue_len(session->waiting);
+}
+
+bool session_tasklist_is_empty(const struct session *session)
+{
+ return session_tasklist_get_len(session) == 0;
+}
+
+bool session_waitinglist_is_empty(const struct session *session)
+{
+ return session_waitinglist_get_len(session) == 0;
+}
+
+bool session_is_empty(const struct session *session)
+{
+ return session_tasklist_is_empty(session) &&
+ session_waitinglist_is_empty(session);
+}
+
+bool session_has_tls(const struct session *session)
+{
+ return session->sflags.has_tls;
+}
+
+void session_set_has_tls(struct session *session, bool has_tls)
+{
+ session->sflags.has_tls = has_tls;
+}
+
+void session_waitinglist_retry(struct session *session, bool increase_timeout_cnt)
+{
+ while (!session_waitinglist_is_empty(session)) {
+ struct qr_task *task = session_waitinglist_pop(session, false);
+ if (increase_timeout_cnt) {
+ worker_task_timeout_inc(task);
+ }
+ worker_task_step(task, &session->peer.ip, NULL);
+ worker_task_unref(task);
+ }
+}
+
+void session_waitinglist_finalize(struct session *session, int status)
+{
+ while (!session_waitinglist_is_empty(session)) {
+ struct qr_task *t = session_waitinglist_pop(session, false);
+ worker_task_finalize(t, status);
+ worker_task_unref(t);
+ }
+}
+
+void session_tasklist_finalize(struct session *session, int status)
+{
+ while (session_tasklist_get_len(session) > 0) {
+ struct qr_task *t = session_tasklist_del_first(session, false);
+ assert(worker_task_numrefs(t) > 0);
+ worker_task_finalize(t, status);
+ worker_task_unref(t);
+ }
+}
+
+int session_tasklist_finalize_expired(struct session *session)
+{
+ int ret = 0;
+ queue_t(struct qr_task *) q;
+ uint64_t now = kr_now();
+ trie_t *t = session->tasks;
+ trie_it_t *it;
+ queue_init(q);
+ for (it = trie_it_begin(t); !trie_it_finished(it); trie_it_next(it)) {
+ trie_val_t *v = trie_it_val(it);
+ struct qr_task *task = (struct qr_task *)*v;
+ if ((now - worker_task_creation_time(task)) >= KR_RESOLVE_TIME_LIMIT) {
+ queue_push(q, task);
+ worker_task_ref(task);
+ }
+ }
+ trie_it_free(it);
+
+ struct qr_task *task = NULL;
+ uint16_t msg_id = 0;
+ char *key = (char *)&task;
+ int32_t keylen = sizeof(struct qr_task *);
+ if (session->sflags.outgoing) {
+ key = (char *)&msg_id;
+ keylen = sizeof(msg_id);
+ }
+ while (queue_len(q) > 0) {
+ task = queue_head(q);
+ if (session->sflags.outgoing) {
+ knot_pkt_t *pktbuf = worker_task_get_pktbuf(task);
+ msg_id = knot_wire_get_id(pktbuf->wire);
+ }
+ int res = trie_del(t, key, keylen, NULL);
+ if (!worker_task_finished(task)) {
+ /* task->pending_count must be zero,
+ * but there are can be followers,
+ * so run worker_task_subreq_finalize() to ensure retrying
+ * for all the followers. */
+ worker_task_subreq_finalize(task);
+ worker_task_finalize(task, KR_STATE_FAIL);
+ }
+ if (res == KNOT_EOK) {
+ worker_task_unref(task);
+ }
+ queue_pop(q);
+ worker_task_unref(task);
+ ++ret;
+ }
+
+ queue_deinit(q);
+ return ret;
+}
+
+int session_timer_start(struct session *session, uv_timer_cb cb,
+ uint64_t timeout, uint64_t repeat)
+{
+ uv_timer_t *timer = &session->timeout;
+ assert(timer->data == session);
+ int ret = uv_timer_start(timer, cb, timeout, repeat);
+ if (ret != 0) {
+ uv_timer_stop(timer);
+ return kr_error(ENOMEM);
+ }
+ return 0;
+}
+
+int session_timer_restart(struct session *session)
+{
+ return uv_timer_again(&session->timeout);
+}
+
+int session_timer_stop(struct session *session)
+{
+ return uv_timer_stop(&session->timeout);
+}
+
+ssize_t session_wirebuf_consume(struct session *session, const uint8_t *data, ssize_t len)
+{
+ if (data != &session->wire_buf[session->wire_buf_end_idx]) {
+ /* shouldn't happen */
+ return kr_error(EINVAL);
+ }
+
+ if (len < 0) {
+ /* shouldn't happen */
+ return kr_error(EINVAL);
+ }
+
+ if (session->wire_buf_end_idx + len > session->wire_buf_size) {
+ /* shouldn't happen */
+ return kr_error(EINVAL);
+ }
+
+ session->wire_buf_end_idx += len;
+ return len;
+}
+
+knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
+{
+ session->sflags.wirebuf_error = false;
+ if (session->wire_buf_end_idx == 0) {
+ return NULL;
+ }
+
+ if (session->wire_buf_start_idx == session->wire_buf_end_idx) {
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return NULL;
+ }
+
+ if (session->wire_buf_start_idx > session->wire_buf_end_idx) {
+ session->sflags.wirebuf_error = true;
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return NULL;
+ }
+
+ const uv_handle_t *handle = session->handle;
+ uint8_t *msg_start = &session->wire_buf[session->wire_buf_start_idx];
+ ssize_t wirebuf_msg_data_size = session->wire_buf_end_idx - session->wire_buf_start_idx;
+ uint16_t msg_size = 0;
+
+ if (!handle) {
+ session->sflags.wirebuf_error = true;
+ return NULL;
+ } else if (handle->type == UV_TCP) {
+ if (wirebuf_msg_data_size < 2) {
+ return NULL;
+ }
+ msg_size = knot_wire_read_u16(msg_start);
+ if (msg_size >= session->wire_buf_size) {
+ session->sflags.wirebuf_error = true;
+ return NULL;
+ }
+ if (msg_size + 2 > wirebuf_msg_data_size) {
+ return NULL;
+ }
+ if (msg_size == 0) {
+ session->sflags.wirebuf_error = true;
+ return NULL;
+ }
+ msg_start += 2;
+ } else if (wirebuf_msg_data_size < UINT16_MAX) {
+ msg_size = wirebuf_msg_data_size;
+ } else {
+ session->sflags.wirebuf_error = true;
+ return NULL;
+ }
+
+
+ knot_pkt_t *pkt = knot_pkt_new(msg_start, msg_size, mm);
+ session->sflags.wirebuf_error = (pkt == NULL);
+ return pkt;
+}
+
+int session_discard_packet(struct session *session, const knot_pkt_t *pkt)
+{
+ uv_handle_t *handle = session->handle;
+ /* Pointer to data start in wire_buf */
+ uint8_t *wirebuf_data_start = &session->wire_buf[session->wire_buf_start_idx];
+ /* Number of data bytes in wire_buf */
+ size_t wirebuf_data_size = session->wire_buf_end_idx - session->wire_buf_start_idx;
+ /* Pointer to message start in wire_buf */
+ uint8_t *wirebuf_msg_start = wirebuf_data_start;
+ /* Number of message bytes in wire_buf.
+ * For UDP it is the same number as wirebuf_data_size. */
+ size_t wirebuf_msg_size = wirebuf_data_size;
+ /* Wire data from parsed packet. */
+ uint8_t *pkt_msg_start = pkt->wire;
+ /* Number of bytes in packet wire buffer. */
+ size_t pkt_msg_size = pkt->size;
+ if (knot_pkt_has_tsig(pkt)) {
+ pkt_msg_size += pkt->tsig_wire.len;
+ }
+
+ session->sflags.wirebuf_error = true;
+
+ if (!handle) {
+ return kr_error(EINVAL);
+ } else if (handle->type == UV_TCP) {
+ /* wire_buf contains TCP DNS message. */
+ if (wirebuf_data_size < 2) {
+ /* TCP message length field isn't in buffer, must not happen. */
+ assert(0);
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return kr_error(EINVAL);
+ }
+ wirebuf_msg_size = knot_wire_read_u16(wirebuf_msg_start);
+ wirebuf_msg_start += 2;
+ if (wirebuf_msg_size + 2 > wirebuf_data_size) {
+ /* TCP message length field is greater then
+ * number of bytes in buffer, must not happen. */
+ assert(0);
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return kr_error(EINVAL);
+ }
+ }
+
+ if (wirebuf_msg_start != pkt_msg_start) {
+ /* packet wirebuf must be located at the beginning
+ * of the session wirebuf, must not happen. */
+ assert(0);
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return kr_error(EINVAL);
+ }
+
+ if (wirebuf_msg_size < pkt_msg_size) {
+ /* Message length field is lesser then packet size,
+ * must not happen. */
+ assert(0);
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+ return kr_error(EINVAL);
+ }
+
+ if (handle->type == UV_TCP) {
+ session->wire_buf_start_idx += wirebuf_msg_size + 2;
+ } else {
+ session->wire_buf_start_idx += pkt_msg_size;
+ }
+ session->sflags.wirebuf_error = false;
+
+ wirebuf_data_size = session->wire_buf_end_idx - session->wire_buf_start_idx;
+ if (wirebuf_data_size == 0) {
+ session_wirebuf_discard(session);
+ } else if (wirebuf_data_size < KNOT_WIRE_HEADER_SIZE) {
+ session_wirebuf_compress(session);
+ }
+
+ return kr_ok();
+}
+
+void session_wirebuf_discard(struct session *session)
+{
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = 0;
+}
+
+void session_wirebuf_compress(struct session *session)
+{
+ if (session->wire_buf_start_idx == 0) {
+ return;
+ }
+ uint8_t *wirebuf_data_start = &session->wire_buf[session->wire_buf_start_idx];
+ size_t wirebuf_data_size = session->wire_buf_end_idx - session->wire_buf_start_idx;
+ if (session->wire_buf_start_idx < wirebuf_data_size) {
+ memmove(session->wire_buf, wirebuf_data_start, wirebuf_data_size);
+ } else {
+ memcpy(session->wire_buf, wirebuf_data_start, wirebuf_data_size);
+ }
+ session->wire_buf_start_idx = 0;
+ session->wire_buf_end_idx = wirebuf_data_size;
+}
+
+bool session_wirebuf_error(struct session *session)
+{
+ return session->sflags.wirebuf_error;
+}
+
+uint8_t *session_wirebuf_get_start(struct session *session)
+{
+ return session->wire_buf;
+}
+
+size_t session_wirebuf_get_size(struct session *session)
+{
+ return session->wire_buf_size;
+}
+
+uint8_t *session_wirebuf_get_free_start(struct session *session)
+{
+ return &session->wire_buf[session->wire_buf_end_idx];
+}
+
+size_t session_wirebuf_get_free_size(struct session *session)
+{
+ return session->wire_buf_size - session->wire_buf_end_idx;
+}
+
+void session_poison(struct session *session)
+{
+ kr_asan_poison(session, sizeof(*session));
+}
+
+void session_unpoison(struct session *session)
+{
+ kr_asan_unpoison(session, sizeof(*session));
+}
+
+int session_wirebuf_process(struct session *session)
+{
+ int ret = 0;
+ if (session->wire_buf_start_idx == session->wire_buf_end_idx) {
+ return ret;
+ }
+ struct worker_ctx *worker = session_get_handle(session)->loop->data;
+ size_t wirebuf_data_size = session->wire_buf_end_idx - session->wire_buf_start_idx;
+ uint32_t max_iterations = (wirebuf_data_size / (KNOT_WIRE_HEADER_SIZE + KNOT_WIRE_QUESTION_MIN_SIZE)) + 1;
+ knot_pkt_t *query = NULL;
+ while (((query = session_produce_packet(session, &worker->pkt_pool)) != NULL) &&
+ (ret < max_iterations)) {
+ assert (!session_wirebuf_error(session));
+ int res = worker_submit(session, query);
+ if (res != kr_error(EILSEQ)) {
+ /* Packet has been successfully parsed. */
+ ret += 1;
+ }
+ if (session_discard_packet(session, query) < 0) {
+ /* Packet data isn't stored in memory as expected.
+ something went wrong, normally should not happen. */
+ break;
+ }
+ }
+ if (session_wirebuf_error(session)) {
+ ret = -1;
+ }
+ return ret;
+}
+
+void session_kill_ioreq(struct session *s, struct qr_task *task)
+{
+ if (!s) {
+ return;
+ }
+ assert(s->sflags.outgoing && s->handle);
+ if (s->sflags.closing) {
+ return;
+ }
+ session_tasklist_del(s, task);
+ if (s->handle->type == UV_UDP) {
+ assert(session_tasklist_is_empty(s));
+ session_close(s);
+ return;
+ }
+}
+
+/** Update timestamp */
+void session_touch(struct session *s)
+{
+ s->last_activity = kr_now();
+}
+
+uint64_t session_last_activity(struct session *s)
+{
+ return s->last_activity;
+}
diff --git a/daemon/session.h b/daemon/session.h
new file mode 100644
index 0000000..56f7eb4
--- /dev/null
+++ b/daemon/session.h
@@ -0,0 +1,147 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <uv.h>
+
+struct qr_task;
+struct worker_ctx;
+struct session;
+
+struct session_flags {
+ bool outgoing : 1; /**< True: to upstream; false: from a client. */
+ bool throttled : 1; /**< True: data reading from peer is temporarily stopped. */
+ bool has_tls : 1; /**< True: given session uses TLS. */
+ bool connected : 1; /**< True: TCP connection is established. */
+ bool closing : 1; /**< True: session close sequence is in progress. */
+ bool wirebuf_error : 1; /**< True: last operation with wirebuf ended up with an error. */
+};
+
+/* Allocate new session for a libuv handle.
+ * If handle->tyoe is UV_UDP, tls parameter will be ignored. */
+struct session *session_new(uv_handle_t *handle, bool has_tls);
+/* Clear and free given session. */
+void session_free(struct session *session);
+/* Clear session. */
+void session_clear(struct session *session);
+/** Close session. */
+void session_close(struct session *session);
+/** Start reading from underlying libuv IO handle. */
+int session_start_read(struct session *session);
+/** Stop reading from underlying libuv IO handle. */
+int session_stop_read(struct session *session);
+
+/** List of tasks been waiting for IO. */
+/** Check if list is empty. */
+bool session_waitinglist_is_empty(const struct session *session);
+/** Add task to the end of the list. */
+int session_waitinglist_push(struct session *session, struct qr_task *task);
+/** Get the first element. */
+struct qr_task *session_waitinglist_get(const struct session *session);
+/** Get the first element and remove it from the list. */
+struct qr_task *session_waitinglist_pop(struct session *session, bool deref);
+/** Get the list length. */
+size_t session_waitinglist_get_len(const struct session *session);
+/** Retry resolution for each task in the list. */
+void session_waitinglist_retry(struct session *session, bool increase_timeout_cnt);
+/** Finalize all tasks in the list. */
+void session_waitinglist_finalize(struct session *session, int status);
+
+/** List of tasks associated with session. */
+/** Check if list is empty. */
+bool session_tasklist_is_empty(const struct session *session);
+/** Get the first element. */
+struct qr_task *session_tasklist_get_first(struct session *session);
+/** Get the first element and remove it from the list. */
+struct qr_task *session_tasklist_del_first(struct session *session, bool deref);
+/** Get the list length. */
+size_t session_tasklist_get_len(const struct session *session);
+/** Add task to the list. */
+int session_tasklist_add(struct session *session, struct qr_task *task);
+/** Remove task from the list. */
+int session_tasklist_del(struct session *session, struct qr_task *task);
+/** Remove task with given msg_id, session_flags(session)->outgoing must be true. */
+struct qr_task* session_tasklist_del_msgid(const struct session *session, uint16_t msg_id);
+/** Find task with given msg_id */
+struct qr_task* session_tasklist_find_msgid(const struct session *session, uint16_t msg_id);
+/** Finalize all tasks in the list. */
+void session_tasklist_finalize(struct session *session, int status);
+/** Finalize all expired tasks in the list. */
+int session_tasklist_finalize_expired(struct session *session);
+
+/** Both of task lists (associated & waiting). */
+/** Check if empty. */
+bool session_is_empty(const struct session *session);
+/** Get pointer to session flags */
+struct session_flags *session_flags(struct session *session);
+/** Get peer address. */
+struct sockaddr *session_get_peer(struct session *session);
+/** Get pointer to server-side tls-related data. */
+struct tls_ctx_t *session_tls_get_server_ctx(const struct session *session);
+/** Set pointer to server-side tls-related data. */
+void session_tls_set_server_ctx(struct session *session, struct tls_ctx_t *ctx);
+/** Get pointer to client-side tls-related data. */
+struct tls_client_ctx_t *session_tls_get_client_ctx(const struct session *session);
+/** Set pointer to client-side tls-related data. */
+void session_tls_set_client_ctx(struct session *session, struct tls_client_ctx_t *ctx);
+/** Get pointer to that part of tls-related data which has common structure for
+ * server and client. */
+struct tls_common_ctx *session_tls_get_common_ctx(const struct session *session);
+
+/** Get pointer to underlying libuv handle for IO operations. */
+uv_handle_t *session_get_handle(struct session *session);
+struct session *session_get(uv_handle_t *h);
+
+/** Start session timer. */
+int session_timer_start(struct session *session, uv_timer_cb cb,
+ uint64_t timeout, uint64_t repeat);
+/** Restart session timer without changing it parameters. */
+int session_timer_restart(struct session *session);
+/** Stop session timer. */
+int session_timer_stop(struct session *session);
+
+/** Get pointer to the beginning of session wirebuffer. */
+uint8_t *session_wirebuf_get_start(struct session *session);
+/** Get size of session wirebuffer. */
+size_t session_wirebuf_get_size(struct session *session);
+/** Get pointer to the beginning of free space in session wirebuffer. */
+uint8_t *session_wirebuf_get_free_start(struct session *session);
+/** Get amount of free space in session wirebuffer. */
+size_t session_wirebuf_get_free_size(struct session *session);
+/** Discard all data in session wirebuffer. */
+void session_wirebuf_discard(struct session *session);
+/** Move all data to the beginning of the buffer. */
+void session_wirebuf_compress(struct session *session);
+int session_wirebuf_process(struct session *session);
+ssize_t session_wirebuf_consume(struct session *session,
+ const uint8_t *data, ssize_t len);
+
+/** poison session structure with ASAN. */
+void session_poison(struct session *session);
+/** unpoison session structure with ASAN. */
+void session_unpoison(struct session *session);
+
+knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm);
+int session_discard_packet(struct session *session, const knot_pkt_t *pkt);
+
+void session_kill_ioreq(struct session *s, struct qr_task *task);
+/** Update timestamp */
+void session_touch(struct session *s);
+/** Returns either creation time or time of last IO activity if any occurs. */
+/* Used for TCP timeout calculation. */
+uint64_t session_last_activity(struct session *s);
diff --git a/daemon/tls.c b/daemon/tls.c
new file mode 100644
index 0000000..fd7fac5
--- /dev/null
+++ b/daemon/tls.c
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (C) 2016 American Civil Liberties Union (ACLU)
+ * 2016-2018 CZ.NIC, z.s.p.o
+ *
+ * Initial Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+ * Ondřej Surý <ondrej@sury.org>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gnutls/abstract.h>
+#include <gnutls/crypto.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <uv.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "contrib/ucw/lib.h"
+#include "contrib/base64.h"
+#include "daemon/io.h"
+#include "daemon/tls.h"
+#include "daemon/worker.h"
+#include "daemon/session.h"
+
+#define EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE 60*60*24*7
+#define GNUTLS_PIN_MIN_VERSION 0x030400
+
+/** @internal Debugging facility. */
+#ifdef DEBUG
+#define DEBUG_MSG(...) kr_log_verbose("[tls] " __VA_ARGS__)
+#else
+#define DEBUG_MSG(...)
+#endif
+
+struct async_write_ctx {
+ uv_write_t write_req;
+ struct tls_common_ctx *t;
+ char buf[];
+};
+
+static char const server_logstring[] = "tls";
+static char const client_logstring[] = "tls_client";
+
+static int client_verify_certificate(gnutls_session_t tls_session);
+
+/**
+ * Set mandatory security settings from
+ * https://tools.ietf.org/html/draft-ietf-dprive-dtls-and-tls-profiles-11#section-9
+ * Performance optimizations are not implemented at the moment.
+ */
+static int kres_gnutls_set_priority(gnutls_session_t session) {
+ static const char * const priorities =
+ "NORMAL:" /* GnuTLS defaults */
+ "-VERS-TLS1.0:-VERS-TLS1.1:" /* TLS 1.2 and higher */
+ /* Some distros by default allow features that are considered
+ * too insecure nowadays, so let's disable them explicitly. */
+ "-VERS-SSL3.0:-ARCFOUR-128:-COMP-ALL:+COMP-NULL";
+ const char *errpos = NULL;
+ int err = gnutls_priority_set_direct(session, priorities, &errpos);
+ if (err != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] setting priority '%s' failed at character %zd (...'%s') with %s (%d)\n",
+ priorities, errpos - priorities, errpos, gnutls_strerror_name(err), err);
+ }
+ return err;
+}
+
+static ssize_t kres_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
+{
+ struct tls_common_ctx *t = (struct tls_common_ctx *)h;
+ assert(t != NULL);
+
+ ssize_t avail = t->nread - t->consumed;
+ DEBUG_MSG("[%s] pull wanted: %zu available: %zu\n",
+ t->client_side ? "tls_client" : "tls", len, avail);
+ if (t->nread <= t->consumed) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ ssize_t transfer = MIN(avail, len);
+ memcpy(buf, t->buf + t->consumed, transfer);
+ t->consumed += transfer;
+ return transfer;
+}
+
+static void on_write_complete(uv_write_t *req, int status)
+{
+ assert(req->data != NULL);
+ struct async_write_ctx *async_ctx = (struct async_write_ctx *)req->data;
+ struct tls_common_ctx *t = async_ctx->t;
+ assert(t->write_queue_size);
+ t->write_queue_size -= 1;
+ free(req->data);
+}
+
+static bool stream_queue_is_empty(struct tls_common_ctx *t)
+{
+ return (t->write_queue_size == 0);
+}
+
+static ssize_t kres_gnutls_vec_push(gnutls_transport_ptr_t h, const giovec_t * iov, int iovcnt)
+{
+ struct tls_common_ctx *t = (struct tls_common_ctx *)h;
+
+ if (t == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (iovcnt == 0) {
+ return 0;
+ }
+
+ assert(t->session);
+ uv_stream_t *handle = (uv_stream_t *)session_get_handle(t->session);
+ assert(handle && handle->type == UV_TCP);
+
+ /*
+ * This is a little bit complicated. There are two different writes:
+ * 1. Immediate, these don't need to own the buffered data and return immediately
+ * 2. Asynchronous, these need to own the buffers until the write completes
+ * In order to avoid copying the buffer, an immediate write is tried first if possible.
+ * If it isn't possible to write the data without queueing, an asynchronous write
+ * is created (with copied buffered data).
+ */
+
+ size_t total_len = 0;
+ uv_buf_t uv_buf[iovcnt];
+ for (int i = 0; i < iovcnt; ++i) {
+ uv_buf[i].base = iov[i].iov_base;
+ uv_buf[i].len = iov[i].iov_len;
+ total_len += iov[i].iov_len;
+ }
+
+ /* Try to perform the immediate write first to avoid copy */
+ int ret = 0;
+ if (stream_queue_is_empty(t)) {
+ ret = uv_try_write(handle, uv_buf, iovcnt);
+ DEBUG_MSG("[%s] push %zu <%p> = %d\n",
+ t->client_side ? "tls_client" : "tls", total_len, h, ret);
+ /* from libuv documentation -
+ uv_try_write will return either:
+ > 0: number of bytes written (can be less than the supplied buffer size).
+ < 0: negative error code (UV_EAGAIN is returned if no data can be sent immediately).
+ */
+ if (ret == total_len) {
+ /* All the data were buffered by libuv.
+ * Return. */
+ return ret;
+ }
+
+ if (ret < 0 && ret != UV_EAGAIN) {
+ /* uv_try_write() has returned error code other then UV_EAGAIN.
+ * Return. */
+ ret = -1;
+ errno = EIO;
+ return ret;
+ }
+ /* Since we are here expression below is true
+ * (ret != total_len) && (ret >= 0 || ret == UV_EAGAIN)
+ * or the same
+ * (ret != total_len && ret >= 0) || (ret != total_len && ret == UV_EAGAIN)
+ * i.e. either occurs partial write or UV_EAGAIN.
+ * Proceed and copy data amount to owned memory and perform async write.
+ */
+ if (ret == UV_EAGAIN) {
+ /* No data were buffered, so we must buffer all the data. */
+ ret = 0;
+ }
+ }
+
+ /* Fallback when the queue is full, and it's not possible to do an immediate write */
+ char *p = malloc(sizeof(struct async_write_ctx) + total_len - ret);
+ if (p != NULL) {
+ struct async_write_ctx *async_ctx = (struct async_write_ctx *)p;
+ /* Save pointer to session tls context */
+ async_ctx->t = t;
+ char *buf = async_ctx->buf;
+ /* Skip data written in the partial write */
+ size_t to_skip = ret;
+ /* Copy the buffer into owned memory */
+ size_t off = 0;
+ for (int i = 0; i < iovcnt; ++i) {
+ if (to_skip > 0) {
+ /* Ignore current buffer if it's all skipped */
+ if (to_skip >= uv_buf[i].len) {
+ to_skip -= uv_buf[i].len;
+ continue;
+ }
+ /* Skip only part of the buffer */
+ uv_buf[i].base += to_skip;
+ uv_buf[i].len -= to_skip;
+ to_skip = 0;
+ }
+ memcpy(buf + off, uv_buf[i].base, uv_buf[i].len);
+ off += uv_buf[i].len;
+ }
+ uv_buf[0].base = buf;
+ uv_buf[0].len = off;
+
+ /* Create an asynchronous write request */
+ uv_write_t *write_req = &async_ctx->write_req;
+ memset(write_req, 0, sizeof(uv_write_t));
+ write_req->data = p;
+
+ /* Perform an asynchronous write with a callback */
+ if (uv_write(write_req, handle, uv_buf, 1, on_write_complete) == 0) {
+ ret = total_len;
+ t->write_queue_size += 1;
+ } else {
+ free(p);
+ errno = EIO;
+ ret = -1;
+ }
+ } else {
+ errno = ENOMEM;
+ ret = -1;
+ }
+
+ DEBUG_MSG("[%s] queued %zu <%p> = %d\n",
+ t->client_side ? "tls_client" : "tls", total_len, h, ret);
+
+ return ret;
+}
+
+/** Perform TLS handshake and handle error codes according to the documentation.
+ * See See https://gnutls.org/manual/html_node/TLS-handshake.html#TLS-handshake
+ * The function returns kr_ok() or success or non fatal error, kr_error(EAGAIN) on blocking, or kr_error(EIO) on fatal error.
+ */
+static int tls_handshake(struct tls_common_ctx *ctx, tls_handshake_cb handshake_cb) {
+ struct session *session = ctx->session;
+ const char *logstring = ctx->client_side ? client_logstring : server_logstring;
+
+ int err = gnutls_handshake(ctx->tls_session);
+ if (err == GNUTLS_E_SUCCESS) {
+ /* Handshake finished, return success */
+ ctx->handshake_state = TLS_HS_DONE;
+ struct sockaddr *peer = session_get_peer(session);
+ kr_log_verbose("[%s] TLS handshake with %s has completed\n",
+ logstring, kr_straddr(peer));
+ if (handshake_cb) {
+ if (handshake_cb(session, 0) != kr_ok()) {
+ return kr_error(EIO);
+ }
+ }
+ } else if (err == GNUTLS_E_AGAIN) {
+ return kr_error(EAGAIN);
+ } else if (gnutls_error_is_fatal(err)) {
+ /* Fatal errors, return error as it's not recoverable */
+ kr_log_verbose("[%s] gnutls_handshake failed: %s (%d)\n",
+ logstring,
+ gnutls_strerror_name(err), err);
+ if (handshake_cb) {
+ handshake_cb(session, -1);
+ }
+ return kr_error(EIO);
+ } else if (err == GNUTLS_E_WARNING_ALERT_RECEIVED) {
+ /* Handle warning when in verbose mode */
+ const char *alert_name = gnutls_alert_get_name(gnutls_alert_get(ctx->tls_session));
+ if (alert_name != NULL) {
+ struct sockaddr *peer = session_get_peer(session);
+ kr_log_verbose("[%s] TLS alert from %s received: %s\n",
+ logstring, kr_straddr(peer), alert_name);
+ }
+ }
+ return kr_ok();
+}
+
+
+struct tls_ctx_t *tls_new(struct worker_ctx *worker)
+{
+ assert(worker != NULL);
+ assert(worker->engine != NULL);
+
+ struct network *net = &worker->engine->net;
+ if (!net->tls_credentials) {
+ net->tls_credentials = tls_get_ephemeral_credentials(worker->engine);
+ if (!net->tls_credentials) {
+ kr_log_error("[tls] X.509 credentials are missing, and ephemeral credentials failed; no TLS\n");
+ return NULL;
+ }
+ kr_log_info("[tls] Using ephemeral TLS credentials:\n");
+ tls_credentials_log_pins(net->tls_credentials);
+ }
+
+ time_t now = time(NULL);
+ if (net->tls_credentials->valid_until != GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION) {
+ if (net->tls_credentials->ephemeral_servicename) {
+ /* ephemeral cert: refresh if due to expire within a week */
+ if (now >= net->tls_credentials->valid_until - EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE) {
+ struct tls_credentials *newcreds = tls_get_ephemeral_credentials(worker->engine);
+ if (newcreds) {
+ tls_credentials_release(net->tls_credentials);
+ net->tls_credentials = newcreds;
+ kr_log_info("[tls] Renewed expiring ephemeral X.509 cert\n");
+ } else {
+ kr_log_error("[tls] Failed to renew expiring ephemeral X.509 cert, using existing one\n");
+ }
+ }
+ } else {
+ /* non-ephemeral cert: warn once when certificate expires */
+ if (now >= net->tls_credentials->valid_until) {
+ kr_log_error("[tls] X.509 certificate has expired!\n");
+ net->tls_credentials->valid_until = GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION;
+ }
+ }
+ }
+
+ struct tls_ctx_t *tls = calloc(1, sizeof(struct tls_ctx_t));
+ if (tls == NULL) {
+ kr_log_error("[tls] failed to allocate TLS context\n");
+ return NULL;
+ }
+
+ int err = gnutls_init(&tls->c.tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
+ if (err != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] gnutls_init(): %s (%d)\n", gnutls_strerror_name(err), err);
+ tls_free(tls);
+ return NULL;
+ }
+ tls->credentials = tls_credentials_reserve(net->tls_credentials);
+ err = gnutls_credentials_set(tls->c.tls_session, GNUTLS_CRD_CERTIFICATE,
+ tls->credentials->credentials);
+ if (err != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] gnutls_credentials_set(): %s (%d)\n", gnutls_strerror_name(err), err);
+ tls_free(tls);
+ return NULL;
+ }
+ if (kres_gnutls_set_priority(tls->c.tls_session) != GNUTLS_E_SUCCESS) {
+ tls_free(tls);
+ return NULL;
+ }
+
+ tls->c.worker = worker;
+ tls->c.client_side = false;
+
+ gnutls_transport_set_pull_function(tls->c.tls_session, kres_gnutls_pull);
+ gnutls_transport_set_vec_push_function(tls->c.tls_session, kres_gnutls_vec_push);
+ gnutls_transport_set_ptr(tls->c.tls_session, tls);
+
+ if (net->tls_session_ticket_ctx) {
+ tls_session_ticket_enable(net->tls_session_ticket_ctx,
+ tls->c.tls_session);
+ }
+
+ return tls;
+}
+
+void tls_close(struct tls_common_ctx *ctx)
+{
+ if (ctx == NULL || ctx->tls_session == NULL) {
+ return;
+ }
+
+ assert(ctx->session);
+
+ if (ctx->handshake_state == TLS_HS_DONE) {
+ const struct sockaddr *peer = session_get_peer(ctx->session);
+ kr_log_verbose("[%s] closing tls connection to `%s`\n",
+ ctx->client_side ? "tls_client" : "tls",
+ kr_straddr(peer));
+ ctx->handshake_state = TLS_HS_CLOSING;
+ gnutls_bye(ctx->tls_session, GNUTLS_SHUT_RDWR);
+ }
+}
+
+void tls_free(struct tls_ctx_t *tls)
+{
+ if (!tls) {
+ return;
+ }
+
+ if (tls->c.tls_session) {
+ /* Don't terminate TLS connection, just tear it down */
+ gnutls_deinit(tls->c.tls_session);
+ tls->c.tls_session = NULL;
+ }
+
+ tls_credentials_release(tls->credentials);
+ free(tls);
+}
+
+int tls_write(uv_write_t *req, uv_handle_t *handle, knot_pkt_t *pkt, uv_write_cb cb)
+{
+ if (!pkt || !handle || !handle->data) {
+ return kr_error(EINVAL);
+ }
+
+ struct session *s = handle->data;
+ struct tls_common_ctx *tls_ctx = session_tls_get_common_ctx(s);
+
+ assert (tls_ctx);
+ assert (session_flags(s)->outgoing == tls_ctx->client_side);
+
+ const uint16_t pkt_size = htons(pkt->size);
+ const char *logstring = tls_ctx->client_side ? client_logstring : server_logstring;
+ gnutls_session_t tls_session = tls_ctx->tls_session;
+
+ gnutls_record_cork(tls_session);
+ ssize_t count = 0;
+ if ((count = gnutls_record_send(tls_session, &pkt_size, sizeof(pkt_size)) < 0) ||
+ (count = gnutls_record_send(tls_session, pkt->wire, pkt->size) < 0)) {
+ kr_log_error("[%s] gnutls_record_send failed: %s (%zd)\n",
+ logstring, gnutls_strerror_name(count), count);
+ return kr_error(EIO);
+ }
+
+ const ssize_t submitted = sizeof(pkt_size) + pkt->size;
+
+ int ret = gnutls_record_uncork(tls_session, GNUTLS_RECORD_WAIT);
+ if (ret < 0) {
+ if (!gnutls_error_is_fatal(ret)) {
+ return kr_error(EAGAIN);
+ } else {
+ kr_log_error("[%s] gnutls_record_uncork failed: %s (%d)\n",
+ logstring, gnutls_strerror_name(ret), ret);
+ return kr_error(EIO);
+ }
+ }
+
+ if (ret != submitted) {
+ kr_log_error("[%s] gnutls_record_uncork didn't send all data (%d of %zd)\n",
+ logstring, ret, submitted);
+ return kr_error(EIO);
+ }
+
+ /* The data is now accepted in gnutls internal buffers, the message can be treated as sent */
+ req->handle = (uv_stream_t *)handle;
+ cb(req, 0);
+
+ return kr_ok();
+}
+
+ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nread)
+{
+ struct tls_common_ctx *tls_p = session_tls_get_common_ctx(s);
+ if (!tls_p) {
+ return kr_error(ENOSYS);
+ }
+
+ assert(tls_p->session == s);
+ const bool ok = tls_p->recv_buf == buf && nread <= sizeof(tls_p->recv_buf);
+ if (!ok) {
+ assert(false);
+ /* don't risk overflowing the buffer if we have a mistake somewhere */
+ return kr_error(EINVAL);
+ }
+
+ const char *logstring = tls_p->client_side ? client_logstring : server_logstring;
+
+ tls_p->buf = buf;
+ tls_p->nread = nread >= 0 ? nread : 0;
+ tls_p->consumed = 0;
+
+ /* Ensure TLS handshake is performed before receiving data.
+ * See https://www.gnutls.org/manual/html_node/TLS-handshake.html */
+ while (tls_p->handshake_state <= TLS_HS_IN_PROGRESS) {
+ int err = tls_handshake(tls_p, tls_p->handshake_cb);
+ if (err == kr_error(EAGAIN)) {
+ return 0; /* Wait for more data */
+ } else if (err != kr_ok()) {
+ return err;
+ }
+ }
+
+ /* See https://gnutls.org/manual/html_node/Data-transfer-and-termination.html#Data-transfer-and-termination */
+ ssize_t submitted = 0;
+ uint8_t *wire_buf = session_wirebuf_get_free_start(s);
+ size_t wire_buf_size = session_wirebuf_get_free_size(s);
+ while (true) {
+ ssize_t count = gnutls_record_recv(tls_p->tls_session, wire_buf, wire_buf_size);
+ if (count == GNUTLS_E_AGAIN) {
+ break; /* No data available */
+ } else if (count == GNUTLS_E_INTERRUPTED) {
+ continue;
+ } else if (count == GNUTLS_E_REHANDSHAKE) {
+ /* See https://www.gnutls.org/manual/html_node/Re_002dauthentication.html */
+ struct sockaddr *peer = session_get_peer(s);
+ kr_log_verbose("[%s] TLS rehandshake with %s has started\n",
+ logstring, kr_straddr(peer));
+ tls_set_hs_state(tls_p, TLS_HS_IN_PROGRESS);
+ int err = kr_ok();
+ while (tls_p->handshake_state <= TLS_HS_IN_PROGRESS) {
+ err = tls_handshake(tls_p, tls_p->handshake_cb);
+ if (err == kr_error(EAGAIN)) {
+ break;
+ } else if (err != kr_ok()) {
+ return err;
+ }
+ }
+ if (err == kr_error(EAGAIN)) {
+ /* pull function is out of data */
+ break;
+ }
+ /* There are can be data available, check it. */
+ continue;
+ } else if (count < 0) {
+ kr_log_verbose("[%s] gnutls_record_recv failed: %s (%zd)\n",
+ logstring, gnutls_strerror_name(count), count);
+ return kr_error(EIO);
+ } else if (count == 0) {
+ break;
+ }
+ DEBUG_MSG("[%s] received %zd data\n", logstring, count);
+ wire_buf += count;
+ wire_buf_size -= count;
+ submitted += count;
+ if (wire_buf_size == 0 && tls_p->consumed != tls_p->nread) {
+ /* session buffer is full
+ * whereas not all the data were consumed */
+ return kr_error(ENOSPC);
+ }
+ }
+ /* Here all data must be consumed. */
+ if (tls_p->consumed != tls_p->nread) {
+ /* Something went wrong, better return error.
+ * This is most probably due to gnutls_record_recv() did not
+ * consume all available network data by calling kres_gnutls_pull().
+ * TODO assess the need for buffering of data amount.
+ */
+ return kr_error(ENOSPC);
+ }
+ return submitted;
+}
+
+#if GNUTLS_VERSION_NUMBER >= GNUTLS_PIN_MIN_VERSION
+
+/*
+ DNS-over-TLS Out of band key-pinned authentication profile uses the
+ same form of pins as HPKP:
+
+ e.g. pin-sha256="FHkyLhvI0n70E47cJlRTamTrnYVcsYdjUGbr79CfAVI="
+
+ DNS-over-TLS OOB key-pins: https://tools.ietf.org/html/rfc7858#appendix-A
+ HPKP pin reference: https://tools.ietf.org/html/rfc7469#appendix-A
+*/
+#define PINLEN (((32) * 8 + 4)/6) + 3 + 1
+
+/* out must be at least PINLEN octets long */
+static int get_oob_key_pin(gnutls_x509_crt_t crt, char *outchar, ssize_t outchar_len)
+{
+ int err;
+ gnutls_pubkey_t key;
+ gnutls_datum_t datum = { .size = 0 };
+
+ if ((err = gnutls_pubkey_init(&key)) != GNUTLS_E_SUCCESS) {
+ return err;
+ }
+
+ if ((err = gnutls_pubkey_import_x509(key, crt, 0)) != GNUTLS_E_SUCCESS) {
+ goto leave;
+ } else {
+ if ((err = gnutls_pubkey_export2(key, GNUTLS_X509_FMT_DER, &datum)) != GNUTLS_E_SUCCESS) {
+ goto leave;
+ } else {
+ uint8_t raw_pin[32];
+ if ((err = gnutls_hash_fast(GNUTLS_DIG_SHA256, datum.data, datum.size, raw_pin)) != GNUTLS_E_SUCCESS) {
+ goto leave;
+ } else {
+ base64_encode(raw_pin, sizeof(raw_pin), (uint8_t *)outchar, outchar_len);
+ }
+ }
+ }
+leave:
+ gnutls_free(datum.data);
+ gnutls_pubkey_deinit(key);
+ return err;
+}
+
+void tls_credentials_log_pins(struct tls_credentials *tls_credentials)
+{
+ for (int index = 0;; index++) {
+ int err;
+ gnutls_x509_crt_t *certs = NULL;
+ unsigned int cert_count = 0;
+
+ if ((err = gnutls_certificate_get_x509_crt(tls_credentials->credentials, index, &certs, &cert_count)) != GNUTLS_E_SUCCESS) {
+ if (err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ kr_log_error("[tls] could not get X.509 certificates (%d) %s\n", err, gnutls_strerror_name(err));
+ }
+ return;
+ }
+
+ for (int i = 0; i < cert_count; i++) {
+ char pin[PINLEN] = { 0 };
+ if ((err = get_oob_key_pin(certs[i], pin, sizeof(pin))) != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] could not calculate RFC 7858 OOB key-pin from cert %d (%d) %s\n", i, err, gnutls_strerror_name(err));
+ } else {
+ kr_log_info("[tls] RFC 7858 OOB key-pin (%d): pin-sha256=\"%s\"\n", i, pin);
+ }
+ gnutls_x509_crt_deinit(certs[i]);
+ }
+ gnutls_free(certs);
+ }
+}
+#else
+void tls_credentials_log_pins(struct tls_credentials *tls_credentials)
+{
+ kr_log_error("[tls] could not calculate RFC 7858 OOB key-pin; GnuTLS 3.4.0+ required\n");
+}
+#endif
+
+static int str_replace(char **where_ptr, const char *with)
+{
+ char *copy = with ? strdup(with) : NULL;
+ if (with && !copy) {
+ return kr_error(ENOMEM);
+ }
+
+ free(*where_ptr);
+ *where_ptr = copy;
+ return kr_ok();
+}
+
+static time_t _get_end_entity_expiration(gnutls_certificate_credentials_t creds)
+{
+ gnutls_datum_t data;
+ gnutls_x509_crt_t cert = NULL;
+ int err;
+ time_t ret = GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION;
+
+ if ((err = gnutls_certificate_get_crt_raw(creds, 0, 0, &data)) != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] failed to get cert to check expiration: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ goto done;
+ }
+ if ((err = gnutls_x509_crt_init(&cert)) != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] failed to initialize cert: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ goto done;
+ }
+ if ((err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_DER)) != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] failed to construct cert while checking expiration: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ goto done;
+ }
+
+ ret = gnutls_x509_crt_get_expiration_time (cert);
+ done:
+ /* do not free data; g_c_get_crt_raw() says to treat it as
+ * constant. */
+ gnutls_x509_crt_deinit(cert);
+ return ret;
+}
+
+int tls_certificate_set(struct network *net, const char *tls_cert, const char *tls_key)
+{
+ if (!net) {
+ return kr_error(EINVAL);
+ }
+
+ struct tls_credentials *tls_credentials = calloc(1, sizeof(*tls_credentials));
+ if (tls_credentials == NULL) {
+ return kr_error(ENOMEM);
+ }
+
+ int err = 0;
+ if ((err = gnutls_certificate_allocate_credentials(&tls_credentials->credentials)) != GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls] gnutls_certificate_allocate_credentials() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ tls_credentials_free(tls_credentials);
+ return kr_error(ENOMEM);
+ }
+ if ((err = gnutls_certificate_set_x509_system_trust(tls_credentials->credentials)) < 0) {
+ if (err != GNUTLS_E_UNIMPLEMENTED_FEATURE) {
+ kr_log_error("[tls] warning: gnutls_certificate_set_x509_system_trust() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ tls_credentials_free(tls_credentials);
+ return err;
+ }
+ }
+
+ if ((str_replace(&tls_credentials->tls_cert, tls_cert) != 0) ||
+ (str_replace(&tls_credentials->tls_key, tls_key) != 0)) {
+ tls_credentials_free(tls_credentials);
+ return kr_error(ENOMEM);
+ }
+
+ if ((err = gnutls_certificate_set_x509_key_file(tls_credentials->credentials,
+ tls_cert, tls_key, GNUTLS_X509_FMT_PEM)) != GNUTLS_E_SUCCESS) {
+ tls_credentials_free(tls_credentials);
+ kr_log_error("[tls] gnutls_certificate_set_x509_key_file(%s,%s) failed: %d (%s)\n",
+ tls_cert, tls_key, err, gnutls_strerror_name(err));
+ return kr_error(EINVAL);
+ }
+ /* record the expiration date: */
+ tls_credentials->valid_until = _get_end_entity_expiration(tls_credentials->credentials);
+
+ /* Exchange the x509 credentials */
+ struct tls_credentials *old_credentials = net->tls_credentials;
+
+ /* Start using the new x509_credentials */
+ net->tls_credentials = tls_credentials;
+ tls_credentials_log_pins(net->tls_credentials);
+
+ if (old_credentials) {
+ err = tls_credentials_release(old_credentials);
+ if (err != kr_error(EBUSY)) {
+ return err;
+ }
+ }
+
+ return kr_ok();
+}
+
+struct tls_credentials *tls_credentials_reserve(struct tls_credentials *tls_credentials) {
+ if (!tls_credentials) {
+ return NULL;
+ }
+ tls_credentials->count++;
+ return tls_credentials;
+}
+
+int tls_credentials_release(struct tls_credentials *tls_credentials) {
+ if (!tls_credentials) {
+ return kr_error(EINVAL);
+ }
+ if (--tls_credentials->count < 0) {
+ tls_credentials_free(tls_credentials);
+ } else {
+ return kr_error(EBUSY);
+ }
+ return kr_ok();
+}
+
+void tls_credentials_free(struct tls_credentials *tls_credentials) {
+ if (!tls_credentials) {
+ return;
+ }
+
+ if (tls_credentials->credentials) {
+ gnutls_certificate_free_credentials(tls_credentials->credentials);
+ }
+ if (tls_credentials->tls_cert) {
+ free(tls_credentials->tls_cert);
+ }
+ if (tls_credentials->tls_key) {
+ free(tls_credentials->tls_key);
+ }
+ if (tls_credentials->ephemeral_servicename) {
+ free(tls_credentials->ephemeral_servicename);
+ }
+ free(tls_credentials);
+}
+
+static int client_paramlist_entry_free(struct tls_client_paramlist_entry *entry)
+{
+ DEBUG_MSG("freeing TLS parameters %p\n", (void *)entry);
+
+ while (entry->ca_files.len > 0) {
+ if (entry->ca_files.at[0] != NULL) {
+ free((void *)entry->ca_files.at[0]);
+ }
+ array_del(entry->ca_files, 0);
+ }
+
+ while (entry->hostnames.len > 0) {
+ if (entry->hostnames.at[0] != NULL) {
+ free((void *)entry->hostnames.at[0]);
+ }
+ array_del(entry->hostnames, 0);
+ }
+
+ while (entry->pins.len > 0) {
+ if (entry->pins.at[0] != NULL) {
+ free((void *)entry->pins.at[0]);
+ }
+ array_del(entry->pins, 0);
+ }
+
+ array_clear(entry->ca_files);
+ array_clear(entry->hostnames);
+ array_clear(entry->pins);
+
+ if (entry->credentials) {
+ gnutls_certificate_free_credentials(entry->credentials);
+ }
+
+ if (entry->session_data.data) {
+ gnutls_free(entry->session_data.data);
+ }
+
+ free(entry);
+
+ return 0;
+}
+
+static void client_paramlist_entry_ref(struct tls_client_paramlist_entry *entry)
+{
+ if (entry != NULL) {
+ entry->refs += 1;
+ }
+}
+
+static void client_paramlist_entry_unref(struct tls_client_paramlist_entry *entry)
+{
+ if (entry != NULL) {
+ assert(entry->refs > 0);
+ entry->refs -= 1;
+
+ /* Last reference frees the object */
+ if (entry->refs == 0) {
+ client_paramlist_entry_free(entry);
+ }
+ }
+}
+
+static int client_paramlist_entry_clear(const char *k, void *v, void *baton)
+{
+ struct tls_client_paramlist_entry *entry = (struct tls_client_paramlist_entry *)v;
+ return client_paramlist_entry_free(entry);
+}
+
+struct tls_client_paramlist_entry *tls_client_try_upgrade(map_t *tls_client_paramlist,
+ const struct sockaddr *addr)
+{
+ /* Opportunistic upgrade from port 53 -> 853 */
+ if (kr_inaddr_port(addr) != KR_DNS_PORT) {
+ return NULL;
+ }
+
+ static char key[INET6_ADDRSTRLEN + 6];
+ size_t keylen = sizeof(key);
+ if (kr_inaddr_str(addr, key, &keylen) != 0) {
+ return NULL;
+ }
+
+ /* Rewrite 053 -> 853 */
+ memcpy(key + keylen - 4, "853", 3);
+
+ return map_get(tls_client_paramlist, key);
+}
+
+int tls_client_params_clear(map_t *tls_client_paramlist, const char *addr, uint16_t port)
+{
+ if (!tls_client_paramlist || !addr) {
+ return kr_error(EINVAL);
+ }
+
+ /* Parameters are OK */
+
+ char key[INET6_ADDRSTRLEN + 6];
+ size_t keylen = sizeof(key);
+ if (kr_straddr_join(addr, port, key, &keylen) != kr_ok()) {
+ return kr_error(EINVAL);
+ }
+
+ struct tls_client_paramlist_entry *entry = map_get(tls_client_paramlist, key);
+ if (entry != NULL) {
+ client_paramlist_entry_clear(NULL, (void *)entry, NULL);
+ map_del(tls_client_paramlist, key);
+ }
+
+ return kr_ok();
+}
+
+int tls_client_params_set(map_t *tls_client_paramlist,
+ const char *addr, uint16_t port,
+ const char *param, tls_client_param_t param_type)
+{
+ if (!tls_client_paramlist || !addr) {
+ return kr_error(EINVAL);
+ }
+
+ /* TLS_CLIENT_PARAM_CA can be empty */
+ if (param_type == TLS_CLIENT_PARAM_HOSTNAME ||
+ param_type == TLS_CLIENT_PARAM_PIN) {
+ if (param == NULL || param[0] == 0) {
+ return kr_error(EINVAL);
+ }
+ }
+
+ /* Parameters are OK */
+
+ char key[INET6_ADDRSTRLEN + 6];
+ size_t keylen = sizeof(key);
+ if (kr_straddr_join(addr, port, key, &keylen) != kr_ok()) {
+ kr_log_error("[tls_client] warning: '%s' is not a valid ip address, ignoring\n", addr);
+ return kr_ok();
+ }
+
+ bool is_first_entry = false;
+ struct tls_client_paramlist_entry *entry = map_get(tls_client_paramlist, key);
+ if (entry == NULL) {
+ entry = calloc(1, sizeof(struct tls_client_paramlist_entry));
+ if (entry == NULL) {
+ return kr_error(ENOMEM);
+ }
+ is_first_entry = true;
+ int ret = gnutls_certificate_allocate_credentials(&entry->credentials);
+ if (ret != GNUTLS_E_SUCCESS) {
+ free(entry);
+ kr_log_error("[tls_client] error: gnutls_certificate_allocate_credentials() fails (%s)\n",
+ gnutls_strerror_name(ret));
+ return kr_error(ENOMEM);
+ }
+ gnutls_certificate_set_verify_function(entry->credentials, client_verify_certificate);
+ client_paramlist_entry_ref(entry);
+ }
+
+ int ret = kr_ok();
+
+ if (param_type == TLS_CLIENT_PARAM_HOSTNAME) {
+ const char *hostname = param;
+ bool already_exists = false;
+ for (size_t i = 0; i < entry->hostnames.len; ++i) {
+ if (strcmp(entry->hostnames.at[i], hostname) == 0) {
+ kr_log_error("[tls_client] error: hostname '%s' for address '%s' already was set, ignoring\n", hostname, key);
+ already_exists = true;
+ break;
+ }
+ }
+ if (!already_exists) {
+ const char *value = strdup(hostname);
+ if (!value) {
+ ret = kr_error(ENOMEM);
+ } else if (array_push(entry->hostnames, value) < 0) {
+ free ((void *)value);
+ ret = kr_error(ENOMEM);
+ }
+ }
+ } else if (param_type == TLS_CLIENT_PARAM_CA) {
+ /* Import ca files only when hostname is already set */
+ if (entry->hostnames.len == 0) {
+ return kr_error(ENOENT);
+ }
+ const char *ca_file = param;
+ bool already_exists = false;
+ for (size_t i = 0; i < entry->ca_files.len; ++i) {
+ const char *imported_ca = entry->ca_files.at[i];
+ if (imported_ca[0] == 0 && (ca_file == NULL || ca_file[0] == 0)) {
+ kr_log_error("[tls_client] error: system ca for address '%s' already was set, ignoring\n", key);
+ already_exists = true;
+ break;
+ } else if (strcmp(imported_ca, ca_file) == 0) {
+ kr_log_error("[tls_client] error: ca file '%s' for address '%s' already was set, ignoring\n", ca_file, key);
+ already_exists = true;
+ break;
+ }
+ }
+ if (!already_exists) {
+ const char *value = strdup(ca_file != NULL ? ca_file : "");
+ if (!value) {
+ ret = kr_error(ENOMEM);
+ } else if (array_push(entry->ca_files, value) < 0) {
+ free ((void *)value);
+ ret = kr_error(ENOMEM);
+ } else if (value[0] == 0) {
+ int res = gnutls_certificate_set_x509_system_trust (entry->credentials);
+ if (res <= 0) {
+ kr_log_error("[tls_client] failed to import certs from system store (%s)\n",
+ gnutls_strerror_name(res));
+ /* value will be freed at cleanup */
+ ret = kr_error(EINVAL);
+ } else {
+ kr_log_verbose("[tls_client] imported %d certs from system store\n", res);
+ }
+ } else {
+ int res = gnutls_certificate_set_x509_trust_file(entry->credentials, value,
+ GNUTLS_X509_FMT_PEM);
+ if (res <= 0) {
+ kr_log_error("[tls_client] failed to import certificate file '%s' (%s)\n",
+ value, gnutls_strerror_name(res));
+ /* value will be freed at cleanup */
+ ret = kr_error(EINVAL);
+ } else {
+ kr_log_verbose("[tls_client] imported %d certs from file '%s'\n",
+ res, value);
+
+ }
+ }
+ }
+ } else if (param_type == TLS_CLIENT_PARAM_PIN) {
+ const char *pin = param;
+ for (size_t i = 0; i < entry->pins.len; ++i) {
+ if (strcmp(entry->pins.at[i], pin) == 0) {
+ kr_log_error("[tls_client] warning: pin '%s' for address '%s' already was set, ignoring\n", pin, key);
+ return kr_ok();
+ }
+ }
+ const void *value = strdup(pin);
+ if (!value) {
+ ret = kr_error(ENOMEM);
+ } else if (array_push(entry->pins, value) < 0) {
+ free ((void *)value);
+ ret = kr_error(ENOMEM);
+ }
+ }
+
+ if ((ret == kr_ok()) && is_first_entry) {
+ bool fail = (map_set(tls_client_paramlist, key, entry) != 0);
+ if (fail) {
+ ret = kr_error(ENOMEM);
+ }
+ }
+
+ if ((ret != kr_ok()) && is_first_entry) {
+ client_paramlist_entry_unref(entry);
+ }
+
+ return ret;
+}
+
+int tls_client_params_free(map_t *tls_client_paramlist)
+{
+ if (!tls_client_paramlist) {
+ return kr_error(EINVAL);
+ }
+
+ map_walk(tls_client_paramlist, client_paramlist_entry_clear, NULL);
+ map_clear(tls_client_paramlist);
+
+ return kr_ok();
+}
+
+static int client_verify_certificate(gnutls_session_t tls_session)
+{
+ struct tls_client_ctx_t *ctx = gnutls_session_get_ptr(tls_session);
+ assert(ctx->params != NULL);
+
+ if (ctx->params->pins.len == 0 && ctx->params->ca_files.len == 0) {
+ return GNUTLS_E_SUCCESS;
+ }
+
+ gnutls_certificate_type_t cert_type = gnutls_certificate_type_get(tls_session);
+ if (cert_type != GNUTLS_CRT_X509) {
+ kr_log_error("[tls_client] invalid certificate type %i has been received\n",
+ cert_type);
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+ unsigned int cert_list_size = 0;
+ const gnutls_datum_t *cert_list =
+ gnutls_certificate_get_peers(tls_session, &cert_list_size);
+ if (cert_list == NULL || cert_list_size == 0) {
+ kr_log_error("[tls_client] empty certificate list\n");
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+#if GNUTLS_VERSION_NUMBER >= GNUTLS_PIN_MIN_VERSION
+ if (ctx->params->pins.len == 0) {
+ DEBUG_MSG("[tls_client] skipping certificate PIN check\n");
+ goto skip_pins;
+ }
+
+ for (int i = 0; i < cert_list_size; i++) {
+ gnutls_x509_crt_t cert;
+ int ret = gnutls_x509_crt_init(&cert);
+ if (ret != GNUTLS_E_SUCCESS) {
+ return ret;
+ }
+
+ ret = gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER);
+ if (ret != GNUTLS_E_SUCCESS) {
+ gnutls_x509_crt_deinit(cert);
+ return ret;
+ }
+
+ char cert_pin[PINLEN] = { 0 };
+ ret = get_oob_key_pin(cert, cert_pin, sizeof(cert_pin));
+
+ gnutls_x509_crt_deinit(cert);
+
+ if (ret != GNUTLS_E_SUCCESS) {
+ return ret;
+ }
+
+ DEBUG_MSG("[tls_client] received pin : %s\n", cert_pin);
+ for (size_t j = 0; j < ctx->params->pins.len; ++j) {
+ const char *pin = ctx->params->pins.at[j];
+ bool match = (strcmp(cert_pin, pin) == 0);
+ DEBUG_MSG("[tls_client] configured pin: %s matches? %s\n",
+ pin, match ? "yes" : "no");
+ if (match) {
+ return GNUTLS_E_SUCCESS;
+ }
+ }
+ }
+
+ /* pins were set, but no one was not matched */
+ kr_log_error("[tls_client] certificate PIN check failed\n");
+#else
+ if (ctx->params->pins.len != 0) {
+ kr_log_error("[tls_client] newer gnutls is required to use PIN check\n");
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+#endif
+
+skip_pins:
+
+ if (ctx->params->ca_files.len == 0) {
+ DEBUG_MSG("[tls_client] empty CA files list\n");
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+ if (ctx->params->hostnames.len == 0) {
+ DEBUG_MSG("[tls_client] empty hostname list\n");
+ return GNUTLS_E_CERTIFICATE_ERROR;
+ }
+
+ int ret;
+ unsigned int status;
+ for (size_t i = 0; i < ctx->params->hostnames.len; ++i) {
+ ret = gnutls_certificate_verify_peers3(
+ ctx->c.tls_session,
+ ctx->params->hostnames.at[i],
+ &status);
+ if ((ret == GNUTLS_E_SUCCESS) && (status == 0)) {
+ return GNUTLS_E_SUCCESS;
+ }
+ }
+
+ if (ret == GNUTLS_E_SUCCESS) {
+ gnutls_datum_t msg;
+ ret = gnutls_certificate_verification_status_print(
+ status, gnutls_certificate_type_get(ctx->c.tls_session), &msg, 0);
+ if (ret == GNUTLS_E_SUCCESS) {
+ kr_log_error("[tls_client] failed to verify peer certificate: "
+ "%s\n", msg.data);
+ gnutls_free(msg.data);
+ } else {
+ kr_log_error("[tls_client] failed to verify peer certificate: "
+ "unable to print reason: %s (%s)\n",
+ gnutls_strerror(ret), gnutls_strerror_name(ret));
+ } /* gnutls_certificate_verification_status_print end */
+ } else {
+ kr_log_error("[tls_client] failed to verify peer certificate: "
+ "gnutls_certificate_verify_peers3 error: %s (%s)\n",
+ gnutls_strerror(ret), gnutls_strerror_name(ret));
+ } /* gnutls_certificate_verify_peers3 end */
+ return GNUTLS_E_CERTIFICATE_ERROR;
+}
+
+struct tls_client_ctx_t *tls_client_ctx_new(struct tls_client_paramlist_entry *entry,
+ struct worker_ctx *worker)
+{
+ struct tls_client_ctx_t *ctx = calloc(1, sizeof (struct tls_client_ctx_t));
+ if (!ctx) {
+ return NULL;
+ }
+ unsigned int flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK
+#ifdef GNUTLS_ENABLE_FALSE_START
+ | GNUTLS_ENABLE_FALSE_START
+#endif
+ ;
+ int ret = gnutls_init(&ctx->c.tls_session, flags);
+ if (ret != GNUTLS_E_SUCCESS) {
+ tls_client_ctx_free(ctx);
+ return NULL;
+ }
+
+ ret = kres_gnutls_set_priority(ctx->c.tls_session);
+ if (ret != GNUTLS_E_SUCCESS) {
+ tls_client_ctx_free(ctx);
+ return NULL;
+ }
+
+ /* Must take a reference on parameters as the credentials are owned by it
+ * and must not be freed while the session is active. */
+ client_paramlist_entry_ref(entry);
+ ctx->params = entry;
+
+ ret = gnutls_credentials_set(ctx->c.tls_session, GNUTLS_CRD_CERTIFICATE,
+ entry->credentials);
+ if (ret != GNUTLS_E_SUCCESS) {
+ tls_client_ctx_free(ctx);
+ return NULL;
+ }
+
+ ctx->c.worker = worker;
+ ctx->c.client_side = true;
+
+ gnutls_transport_set_pull_function(ctx->c.tls_session, kres_gnutls_pull);
+ gnutls_transport_set_vec_push_function(ctx->c.tls_session, kres_gnutls_vec_push);
+ gnutls_transport_set_ptr(ctx->c.tls_session, ctx);
+ return ctx;
+}
+
+void tls_client_ctx_free(struct tls_client_ctx_t *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ if (ctx->c.tls_session != NULL) {
+ gnutls_deinit(ctx->c.tls_session);
+ ctx->c.tls_session = NULL;
+ }
+
+ /* Must decrease the refcount for referenced parameters */
+ client_paramlist_entry_unref(ctx->params);
+
+ free (ctx);
+}
+
+int tls_pull_timeout_func(gnutls_transport_ptr_t h, unsigned int ms)
+{
+ struct tls_common_ctx *t = (struct tls_common_ctx *)h;
+ assert(t != NULL);
+ ssize_t avail = t->nread - t->consumed;
+ DEBUG_MSG("[%s] timeout check: available: %zu\n",
+ t->client_side ? "tls_client" : "tls", avail);
+ if (avail <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return avail;
+}
+
+int tls_client_connect_start(struct tls_client_ctx_t *client_ctx,
+ struct session *session,
+ tls_handshake_cb handshake_cb)
+{
+ if (session == NULL || client_ctx == NULL) {
+ return kr_error(EINVAL);
+ }
+
+ assert(session_flags(session)->outgoing && session_get_handle(session)->type == UV_TCP);
+
+ struct tls_common_ctx *ctx = &client_ctx->c;
+
+ gnutls_session_set_ptr(ctx->tls_session, client_ctx);
+ gnutls_handshake_set_timeout(ctx->tls_session, ctx->worker->engine->net.tcp.tls_handshake_timeout);
+ gnutls_transport_set_pull_timeout_function(ctx->tls_session, tls_pull_timeout_func);
+ session_tls_set_client_ctx(session, client_ctx);
+ ctx->handshake_cb = handshake_cb;
+ ctx->handshake_state = TLS_HS_IN_PROGRESS;
+ ctx->session = session;
+
+ struct tls_client_paramlist_entry *tls_params = client_ctx->params;
+ if (tls_params->session_data.data != NULL) {
+ gnutls_session_set_data(ctx->tls_session, tls_params->session_data.data,
+ tls_params->session_data.size);
+ }
+
+ /* See https://www.gnutls.org/manual/html_node/Asynchronous-operation.html */
+ while (ctx->handshake_state <= TLS_HS_IN_PROGRESS) {
+ int ret = tls_handshake(ctx, handshake_cb);
+ if (ret != kr_ok()) {
+ return ret;
+ }
+ }
+ return kr_ok();
+}
+
+tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx)
+{
+ return ctx->handshake_state;
+}
+
+int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state)
+{
+ if (state >= TLS_HS_LAST) {
+ return kr_error(EINVAL);
+ }
+ ctx->handshake_state = state;
+ return kr_ok();
+}
+
+int tls_client_ctx_set_session(struct tls_client_ctx_t *ctx, struct session *session)
+{
+ if (!ctx) {
+ return kr_error(EINVAL);
+ }
+ ctx->c.session = session;
+ return kr_ok();
+}
+
+#undef DEBUG_MSG
diff --git a/daemon/tls.h b/daemon/tls.h
new file mode 100644
index 0000000..2eb776c
--- /dev/null
+++ b/daemon/tls.h
@@ -0,0 +1,224 @@
+/* Copyright (C) 2016 American Civil Liberties Union (ACLU)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <uv.h>
+#include <gnutls/gnutls.h>
+#include <libknot/packet/pkt.h>
+#include "lib/defines.h"
+#include "lib/generic/array.h"
+#include "lib/generic/map.h"
+
+#define MAX_TLS_PADDING KR_EDNS_PAYLOAD
+#define TLS_MAX_UNCORK_RETRIES 100
+
+/* rfc 5476, 7.3 - handshake Protocol overview
+ * https://tools.ietf.org/html/rfc5246#page-33
+ * Message flow for a full handshake (only mandatory messages)
+ * ClientHello -------->
+ ServerHello
+ <-------- ServerHelloDone
+ ClientKeyExchange
+ Finished -------->
+ <-------- Finished
+ *
+ * See also https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/
+ * So it takes 2 RTT.
+ * As we use session tickets, there are additional messages, add one RTT mode.
+ */
+ #define TLS_MAX_HANDSHAKE_TIME (KR_CONN_RTT_MAX * 3)
+
+/** Transport session (opaque). */
+struct session;
+
+struct tls_ctx_t;
+struct tls_client_ctx_t;
+struct tls_credentials {
+ int count;
+ char *tls_cert;
+ char *tls_key;
+ gnutls_certificate_credentials_t credentials;
+ time_t valid_until;
+ char *ephemeral_servicename;
+};
+
+struct tls_client_paramlist_entry {
+ array_t(const char *) ca_files;
+ array_t(const char *) hostnames;
+ array_t(const char *) pins;
+ gnutls_certificate_credentials_t credentials;
+ gnutls_datum_t session_data;
+ uint32_t refs;
+};
+
+struct worker_ctx;
+struct qr_task;
+
+typedef enum tls_client_hs_state {
+ TLS_HS_NOT_STARTED = 0,
+ TLS_HS_IN_PROGRESS,
+ TLS_HS_DONE,
+ TLS_HS_CLOSING,
+ TLS_HS_LAST
+} tls_hs_state_t;
+
+typedef int (*tls_handshake_cb) (struct session *session, int status);
+
+typedef enum tls_client_param {
+ TLS_CLIENT_PARAM_NONE = 0,
+ TLS_CLIENT_PARAM_PIN,
+ TLS_CLIENT_PARAM_HOSTNAME,
+ TLS_CLIENT_PARAM_CA,
+} tls_client_param_t;
+
+struct tls_common_ctx {
+ bool client_side;
+ gnutls_session_t tls_session;
+ tls_hs_state_t handshake_state;
+ struct session *session;
+ /* for reading from the network */
+ const uint8_t *buf;
+ ssize_t nread;
+ ssize_t consumed;
+ uint8_t recv_buf[16384];
+ tls_handshake_cb handshake_cb;
+ struct worker_ctx *worker;
+ size_t write_queue_size;
+};
+
+struct tls_ctx_t {
+ /*
+ * Since pointer to tls_ctx_t needs to be casted
+ * to tls_ctx_common in some functions,
+ * this field must be always at first position
+ */
+ struct tls_common_ctx c;
+ struct tls_credentials *credentials;
+};
+
+struct tls_client_ctx_t {
+ /*
+ * Since pointer to tls_client_ctx_t needs to be casted
+ * to tls_ctx_common in some functions,
+ * this field must be always at first position
+ */
+ struct tls_common_ctx c;
+ struct tls_client_paramlist_entry *params;
+};
+
+/*! Create an empty TLS context in query context */
+struct tls_ctx_t* tls_new(struct worker_ctx *worker);
+
+/*! Close a TLS context (call gnutls_bye()) */
+void tls_close(struct tls_common_ctx *ctx);
+
+/*! Release a TLS context */
+void tls_free(struct tls_ctx_t* tls);
+
+/*! Push new data to TLS context for sending */
+int tls_write(uv_write_t *req, uv_handle_t* handle, knot_pkt_t * pkt, uv_write_cb cb);
+
+/*! Unwrap incoming data from a TLS stream and pass them to TCP session.
+ * @return the number of newly-completed requests (>=0) or an error code
+ */
+ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nread);
+
+/*! Set TLS certificate and key from files. */
+int tls_certificate_set(struct network *net, const char *tls_cert, const char *tls_key);
+
+/*! Borrow TLS credentials for context. */
+struct tls_credentials *tls_credentials_reserve(struct tls_credentials *tls_credentials);
+
+/*! Release TLS credentials for context (decrements refcount or frees). */
+int tls_credentials_release(struct tls_credentials *tls_credentials);
+
+/*! Free TLS credentials, must not be called if it holds positive refcount. */
+void tls_credentials_free(struct tls_credentials *tls_credentials);
+
+/*! Log DNS-over-TLS OOB key-pin form of current credentials:
+ * https://tools.ietf.org/html/rfc7858#appendix-A */
+void tls_credentials_log_pins(struct tls_credentials *tls_credentials);
+
+/*! Generate new ephemeral TLS credentials. */
+struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine);
+
+/*! Get TLS handshake state. */
+tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx);
+
+/*! Set TLS handshake state. */
+int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state);
+
+/*! Find TLS parameters for given address. Attempt opportunistic upgrade for port 53 to 853,
+ * if the address is configured with a working DoT on port 853.
+ */
+struct tls_client_paramlist_entry *tls_client_try_upgrade(map_t *tls_client_paramlist,
+ const struct sockaddr *addr);
+
+/*! Clear (remove) TLS parameters for given address. */
+int tls_client_params_clear(map_t *tls_client_paramlist, const char *addr, uint16_t port);
+
+/*! Set TLS authentication parameters for given address.
+ * Note: hostnames must be imported before ca files,
+ * otherwise ca files will not be imported at all.
+ */
+int tls_client_params_set(map_t *tls_client_paramlist,
+ const char *addr, uint16_t port,
+ const char *param, tls_client_param_t param_type);
+
+/*! Free TLS authentication parameters. */
+int tls_client_params_free(map_t *tls_client_paramlist);
+
+/*! Allocate new client TLS context */
+struct tls_client_ctx_t *tls_client_ctx_new(struct tls_client_paramlist_entry *entry,
+ struct worker_ctx *worker);
+
+/*! Free client TLS context */
+void tls_client_ctx_free(struct tls_client_ctx_t *ctx);
+
+int tls_client_connect_start(struct tls_client_ctx_t *client_ctx,
+ struct session *session,
+ tls_handshake_cb handshake_cb);
+
+int tls_client_ctx_set_session(struct tls_client_ctx_t *ctx, struct session *session);
+
+
+/* Session tickets, server side. Implementation in ./tls_session_ticket-srv.c */
+
+/*! Opaque struct used by tls_session_ticket_* functions. */
+struct tls_session_ticket_ctx;
+
+/*! Suggested maximum reasonable secret length. */
+#define TLS_SESSION_TICKET_SECRET_MAX_LEN 1024
+
+/*! Create a session ticket context and initialize it (secret gets copied inside).
+ *
+ * Passing zero-length secret implies using a random key, i.e. not synchronized
+ * between multiple instances.
+ *
+ * Beware that knowledge of the secret (if nonempty) breaks forward secrecy,
+ * so you should rotate the secret regularly and securely erase all past secrets.
+ * With TLS < 1.3 it's probably too risky to set nonempty secret.
+ */
+struct tls_session_ticket_ctx * tls_session_ticket_ctx_create(
+ uv_loop_t *loop, const char *secret, size_t secret_len);
+
+/*! Try to enable session tickets for a server session. */
+void tls_session_ticket_enable(struct tls_session_ticket_ctx *ctx, gnutls_session_t session);
+
+/*! Free all resources of the session ticket context. NULL is accepted as well. */
+void tls_session_ticket_ctx_destroy(struct tls_session_ticket_ctx *ctx);
+
diff --git a/daemon/tls_ephemeral_credentials.c b/daemon/tls_ephemeral_credentials.c
new file mode 100644
index 0000000..a305eb1
--- /dev/null
+++ b/daemon/tls_ephemeral_credentials.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2016 American Civil Liberties Union (ACLU)
+ * Copyright (C) 2016-2017 CZ.NIC, z.s.p.o.
+ *
+ * Initial Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <sys/file.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/crypto.h>
+
+#include "daemon/worker.h"
+#include "daemon/tls.h"
+
+#define EPHEMERAL_PRIVKEY_FILENAME "ephemeral_key.pem"
+#define INVALID_HOSTNAME "dns-over-tls.invalid"
+#define EPHEMERAL_CERT_EXPIRATION_SECONDS 60*60*24*90
+
+/* This is an attempt to grab an exclusive, advisory, non-blocking
+ * lock based on a filename. At the moment it's POSIX-only, but it
+ * should be abstract enough of an interface to make an implementation
+ * for non-posix systems if anyone cares. */
+typedef int lock_t;
+static bool _lock_is_invalid(lock_t lock)
+{
+ return lock == -1;
+}
+/* a blocking lock on a given filename */
+static lock_t _lock_filename(const char *fname)
+{
+ lock_t lockfd = open(fname, O_RDONLY|O_CREAT, 0400);
+ if (lockfd == -1)
+ return lockfd;
+ /* this should be a non-blocking lock */
+ if (flock(lockfd, LOCK_EX | LOCK_NB) != 0) {
+ close(lockfd);
+ return -1;
+ }
+ return lockfd; /* for cleanup later */
+}
+static void _lock_unlock(lock_t *lock, const char *fname)
+{
+ if (lock && !_lock_is_invalid(*lock)) {
+ flock(*lock, LOCK_UN);
+ close(*lock);
+ *lock = -1;
+ unlink(fname); /* ignore errors */
+ }
+}
+
+static gnutls_x509_privkey_t get_ephemeral_privkey ()
+{
+ gnutls_x509_privkey_t privkey = NULL;
+ int err;
+ gnutls_datum_t data = { .data = NULL, .size = 0 };
+ lock_t lock;
+ int datafd = -1;
+
+ /* Take a lock to ensure that two daemons started concurrently
+ * with a shared cache don't both create the same privkey: */
+ lock = _lock_filename(EPHEMERAL_PRIVKEY_FILENAME ".lock");
+ if (_lock_is_invalid(lock)) {
+ kr_log_error("[tls] unable to lock lockfile " EPHEMERAL_PRIVKEY_FILENAME ".lock\n");
+ goto done;
+ }
+
+ if ((err = gnutls_x509_privkey_init (&privkey)) < 0) {
+ kr_log_error("[tls] gnutls_x509_privkey_init() failed: %d (%s)\n",
+ err, gnutls_strerror_name(err));
+ goto done;
+ }
+
+ /* read from cache file (we assume that we've chdir'ed
+ * already, so we're just looking for the file in the
+ * cachedir. */
+ datafd = open(EPHEMERAL_PRIVKEY_FILENAME, O_RDONLY);
+ if (datafd != -1) {
+ struct stat stat;
+ ssize_t bytes_read;
+ if (fstat(datafd, &stat)) {
+ kr_log_error("[tls] unable to stat ephemeral private key " EPHEMERAL_PRIVKEY_FILENAME "\n");
+ goto bad_data;
+ }
+ data.data = gnutls_malloc(stat.st_size);
+ if (data.data == NULL) {
+ kr_log_error("[tls] unable to allocate memory for reading ephemeral private key\n");
+ goto bad_data;
+ }
+ data.size = stat.st_size;
+ bytes_read = read(datafd, data.data, stat.st_size);
+ if (bytes_read != stat.st_size) {
+ kr_log_error("[tls] unable to read ephemeral private key\n");
+ goto bad_data;
+ }
+ if ((err = gnutls_x509_privkey_import (privkey, &data, GNUTLS_X509_FMT_PEM)) < 0) {
+ kr_log_error("[tls] gnutls_x509_privkey_import() failed: %d (%s)\n",
+ err, gnutls_strerror_name(err));
+ /* goto bad_data; */
+ bad_data:
+ close(datafd);
+ datafd = -1;
+ }
+ if (data.data != NULL) {
+ gnutls_free(data.data);
+ data.data = NULL;
+ }
+ }
+ if (datafd == -1) {
+ /* if loading failed, then generate ... */
+#if GNUTLS_VERSION_NUMBER >= 0x030500
+ if ((err = gnutls_x509_privkey_generate(privkey, GNUTLS_PK_ECDSA, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP256R1), 0)) < 0) {
+#else
+ if ((err = gnutls_x509_privkey_generate(privkey, GNUTLS_PK_RSA, gnutls_sec_param_to_pk_bits(GNUTLS_PK_RSA, GNUTLS_SEC_PARAM_MEDIUM), 0)) < 0) {
+#endif
+ kr_log_error("[tls] gnutls_x509_privkey_init() failed: %d (%s)\n",
+ err, gnutls_strerror_name(err));
+ gnutls_x509_privkey_deinit(privkey);
+ goto done;
+ }
+ /* ... and save */
+ kr_log_info("[tls] Stashing ephemeral private key in " EPHEMERAL_PRIVKEY_FILENAME "\n");
+ if ((err = gnutls_x509_privkey_export2(privkey, GNUTLS_X509_FMT_PEM, &data)) < 0) {
+ kr_log_error("[tls] gnutls_x509_privkey_export2() failed: %d (%s), not storing\n",
+ err, gnutls_strerror_name(err));
+ } else {
+ datafd = open(EPHEMERAL_PRIVKEY_FILENAME, O_WRONLY|O_CREAT, 0600);
+ if (datafd == -1) {
+ kr_log_error("[tls] failed to open " EPHEMERAL_PRIVKEY_FILENAME " to store the ephemeral key\n");
+ } else {
+ ssize_t bytes_written;
+ bytes_written = write(datafd, data.data, data.size);
+ if (bytes_written != data.size)
+ kr_log_error("[tls] failed to write %d octets to "
+ EPHEMERAL_PRIVKEY_FILENAME
+ " (%zd written)\n",
+ data.size, bytes_written);
+ }
+ }
+ }
+ done:
+ _lock_unlock(&lock, EPHEMERAL_PRIVKEY_FILENAME ".lock");
+ if (datafd != -1) {
+ close(datafd);
+ }
+ if (data.data != NULL) {
+ gnutls_free(data.data);
+ }
+ return privkey;
+}
+
+static gnutls_x509_crt_t get_ephemeral_cert(gnutls_x509_privkey_t privkey, const char *servicename, time_t invalid_before, time_t valid_until)
+{
+ gnutls_x509_crt_t cert = NULL;
+ int err;
+ /* need a random buffer of bytes */
+ uint8_t serial[16];
+ gnutls_rnd(GNUTLS_RND_NONCE, serial, sizeof(serial));
+ /* clear the left-most bit to avoid signedness confusion: */
+ serial[0] &= 0x8f;
+ size_t namelen = strlen(servicename);
+
+#define gtx(fn, ...) \
+ if ((err = fn ( __VA_ARGS__ )) != GNUTLS_E_SUCCESS) { \
+ kr_log_error("[tls] " #fn "() failed: %d (%s)\n", \
+ err, gnutls_strerror_name(err)); \
+ goto bad; }
+
+ gtx(gnutls_x509_crt_init, &cert);
+ gtx(gnutls_x509_crt_set_activation_time, cert, invalid_before);
+ gtx(gnutls_x509_crt_set_ca_status, cert, 0);
+ gtx(gnutls_x509_crt_set_expiration_time, cert, valid_until);
+ gtx(gnutls_x509_crt_set_key, cert, privkey);
+ gtx(gnutls_x509_crt_set_key_purpose_oid, cert, GNUTLS_KP_TLS_WWW_CLIENT, 0);
+ gtx(gnutls_x509_crt_set_key_purpose_oid, cert, GNUTLS_KP_TLS_WWW_SERVER, 0);
+ gtx(gnutls_x509_crt_set_key_usage, cert, GNUTLS_KEY_DIGITAL_SIGNATURE);
+ gtx(gnutls_x509_crt_set_serial, cert, serial, sizeof(serial));
+ gtx(gnutls_x509_crt_set_subject_alt_name, cert, GNUTLS_SAN_DNSNAME, servicename, namelen, GNUTLS_FSAN_SET);
+ gtx(gnutls_x509_crt_set_dn_by_oid,cert, GNUTLS_OID_X520_COMMON_NAME, 0, servicename, namelen);
+ gtx(gnutls_x509_crt_set_version, cert, 3);
+ gtx(gnutls_x509_crt_sign2,cert, cert, privkey, GNUTLS_DIG_SHA256, 0); /* self-sign, since it doesn't look like we can just stub-sign */
+#undef gtx
+
+ return cert;
+bad:
+ gnutls_x509_crt_deinit(cert);
+ return NULL;
+}
+
+struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine)
+{
+ struct tls_credentials *creds = NULL;
+ gnutls_x509_privkey_t privkey = NULL;
+ gnutls_x509_crt_t cert = NULL;
+ int err;
+ time_t now = time(NULL);
+
+ creds = calloc(1, sizeof(*creds));
+ if (!creds) {
+ kr_log_error("[tls] failed to allocate memory for ephemeral credentials\n");
+ return NULL;
+ }
+ if ((err = gnutls_certificate_allocate_credentials(&(creds->credentials))) < 0) {
+ kr_log_error("[tls] failed to allocate memory for ephemeral credentials\n");
+ goto failure;
+ }
+
+ creds->valid_until = now + EPHEMERAL_CERT_EXPIRATION_SECONDS;
+ creds->ephemeral_servicename = strdup(engine_get_hostname(engine));
+ if (creds->ephemeral_servicename == NULL) {
+ kr_log_error("[tls] could not get server's hostname, using '" INVALID_HOSTNAME "' instead\n");
+ if ((creds->ephemeral_servicename = strdup(INVALID_HOSTNAME)) == NULL) {
+ kr_log_error("[tls] failed to allocate memory for ephemeral credentials\n");
+ goto failure;
+ }
+ }
+ if ((privkey = get_ephemeral_privkey()) == NULL) {
+ goto failure;
+ }
+ if ((cert = get_ephemeral_cert(privkey, creds->ephemeral_servicename, now - 60*15, creds->valid_until)) == NULL) {
+ goto failure;
+ }
+ if ((err = gnutls_certificate_set_x509_key(creds->credentials, &cert, 1, privkey)) < 0) {
+ kr_log_error("[tls] failed to set up ephemeral credentials\n");
+ goto failure;
+ }
+ gnutls_x509_privkey_deinit(privkey);
+ gnutls_x509_crt_deinit(cert);
+ return creds;
+ failure:
+ gnutls_x509_privkey_deinit(privkey);
+ gnutls_x509_crt_deinit(cert);
+ tls_credentials_free(creds);
+ return NULL;
+}
diff --git a/daemon/tls_session_ticket-srv.c b/daemon/tls_session_ticket-srv.c
new file mode 100644
index 0000000..ff1471b
--- /dev/null
+++ b/daemon/tls_session_ticket-srv.c
@@ -0,0 +1,262 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <uv.h>
+
+#include "lib/utils.h"
+
+/* Style: "local/static" identifiers are usually named tst_* */
+
+/** The number of seconds between synchronized rotation of TLS session ticket key. */
+#define TST_KEY_LIFETIME 4096
+
+/** Value from gnutls:lib/ext/session_ticket.c
+ * Beware: changing this needs to change the hashing implementation. */
+#define SESSION_KEY_SIZE 64
+
+/** Compile-time support for setting the secret. */
+/* This is not secure with TLS <= 1.2 but TLS 1.3 and secure configuration
+ * is not available in GnuTLS yet. See https://gitlab.com/gnutls/gnutls/issues/477
+#ifndef TLS_SESSION_RESUMPTION_SYNC
+ #define TLS_SESSION_RESUMPTION_SYNC (GNUTLS_VERSION_NUMBER >= 0x030603)
+#endif
+*/
+
+#if GNUTLS_VERSION_NUMBER < 0x030400
+ /* It's of little use anyway. We may get the secret through lua,
+ * which creates a copy outside of our control. */
+ #define gnutls_memset memset
+#endif
+
+#ifdef GNUTLS_DIG_SHA3_512
+ #define TST_HASH GNUTLS_DIG_SHA3_512
+#else
+ #define TST_HASH abort()
+#endif
+
+/** Fields are internal to tst_key_* functions. */
+typedef struct tls_session_ticket_ctx {
+ uv_timer_t timer; /**< timer for rotation of the key */
+ unsigned char key[SESSION_KEY_SIZE]; /**< the key itself */
+ bool has_secret; /**< false -> key is random for each epoch */
+ uint16_t hash_len; /**< length of `hash_data` */
+ char hash_data[]; /**< data to hash to obtain `key`;
+ * it's `time_t epoch` and then the secret string */
+} tst_ctx_t;
+
+/** Check invariants, based on gnutls version. */
+static bool tst_key_invariants(void)
+{
+ static int result = 0; /*< cache for multiple invocations */
+ if (result) return result > 0;
+ bool ok = true;
+ #if TLS_SESSION_RESUMPTION_SYNC
+ /* SHA3-512 output size may never change, but let's check it anyway :-) */
+ ok = ok && gnutls_hash_get_len(TST_HASH) == SESSION_KEY_SIZE;
+ #endif
+ /* The ticket key size might change in a different gnutls version. */
+ gnutls_datum_t key = { 0, 0 };
+ ok = ok && gnutls_session_ticket_key_generate(&key) == 0
+ && key.size == SESSION_KEY_SIZE;
+ free(key.data);
+ result = ok ? 1 : -1;
+ return ok;
+}
+
+/** Create the internal structures and copy the secret. Beware: secret must be kept secure. */
+static tst_ctx_t * tst_key_create(const char *secret, size_t secret_len, uv_loop_t *loop)
+{
+ const size_t hash_len = sizeof(time_t) + secret_len;
+ if (secret_len &&
+ (!secret || hash_len > UINT16_MAX || hash_len < secret_len)) {
+ assert(!EINVAL);
+ return NULL;
+ /* reasonable secret_len is best enforced in config API */
+ }
+ if (!tst_key_invariants()) {
+ assert(!EFAULT);
+ return NULL;
+ }
+ #if !TLS_SESSION_RESUMPTION_SYNC
+ if (secret_len) {
+ kr_log_error("[tls] session ticket: secrets were not enabled at compile-time (your GnuTLS version is not supported)\n");
+ return NULL; /* ENOTSUP */
+ }
+ #endif
+
+ tst_ctx_t *ctx = malloc(sizeof(*ctx) + hash_len); /* can be slightly longer */
+ if (!ctx) return NULL;
+ ctx->has_secret = secret_len > 0;
+ ctx->hash_len = hash_len;
+ if (secret_len) {
+ memcpy(ctx->hash_data + sizeof(time_t), secret, secret_len);
+ }
+
+ if (uv_timer_init(loop, &ctx->timer) != 0) {
+ free(ctx);
+ return NULL;
+ }
+ ctx->timer.data = ctx;
+ return ctx;
+}
+
+/** Random variant of secret rotation: generate into key_tmp and copy. */
+static int tst_key_get_random(tst_ctx_t *ctx)
+{
+ gnutls_datum_t key_tmp = { NULL, 0 };
+ int err = gnutls_session_ticket_key_generate(&key_tmp);
+ if (err) return kr_error(err);
+ if (key_tmp.size != SESSION_KEY_SIZE) {
+ assert(!EFAULT);
+ return kr_error(EFAULT);
+ }
+ memcpy(ctx->key, key_tmp.data, SESSION_KEY_SIZE);
+ gnutls_memset(key_tmp.data, 0, SESSION_KEY_SIZE);
+ free(key_tmp.data);
+ return kr_ok();
+}
+
+/** Recompute the session ticket key, if epoch has changed or forced. */
+static int tst_key_update(tst_ctx_t *ctx, time_t epoch, bool force_update)
+{
+ if (!ctx || ctx->hash_len < sizeof(epoch)) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ /* documented limitation: time_t and endianess must match
+ * on instances sharing a secret */
+ if (!force_update && memcmp(ctx->hash_data, &epoch, sizeof(epoch)) == 0) {
+ return kr_ok(); /* we are up to date */
+ }
+ memcpy(ctx->hash_data, &epoch, sizeof(epoch));
+
+ if (!ctx->has_secret) {
+ return tst_key_get_random(ctx);
+ }
+ /* Otherwise, deterministic variant of secret rotation, if supported. */
+ #if !TLS_SESSION_RESUMPTION_SYNC
+ assert(false);
+ return kr_error(ENOTSUP);
+ #else
+ int err = gnutls_hash_fast(TST_HASH, ctx->hash_data,
+ ctx->hash_len, ctx->key);
+ return err == 0 ? kr_ok() : kr_error(err);
+ #endif
+}
+
+/** Free all resources of the key (securely). */
+static void tst_key_destroy(uv_handle_t *timer)
+{
+ assert(timer);
+ tst_ctx_t *ctx = timer->data;
+ assert(ctx);
+ gnutls_memset(ctx, 0, offsetof(tst_ctx_t, hash_data) + ctx->hash_len);
+ free(ctx);
+}
+
+static void tst_key_check(uv_timer_t *timer, bool force_update);
+static void tst_timer_callback(uv_timer_t *timer)
+{
+ tst_key_check(timer, false);
+}
+
+/** Update the ST key if needed and reschedule itself via the timer. */
+static void tst_key_check(uv_timer_t *timer, bool force_update)
+{
+ tst_ctx_t *stst = (tst_ctx_t *)timer->data;
+ /* Compute the current epoch. */
+ struct timeval now;
+ if (gettimeofday(&now, NULL)) {
+ kr_log_error("[tls] session ticket: gettimeofday failed, %s\n",
+ strerror(errno));
+ return;
+ }
+ uv_update_time(timer->loop); /* to have sync. between real and mono time */
+ const time_t epoch = now.tv_sec / TST_KEY_LIFETIME;
+ /* Update the key; new sessions will fetch it from the location.
+ * Old ones hopefully can't get broken by that; documentation
+ * for gnutls_session_ticket_enable_server() doesn't say. */
+ int err = tst_key_update(stst, epoch, force_update);
+ if (err) {
+ assert(err != kr_error(EINVAL));
+ kr_log_error("[tls] session ticket: failed rotation, err = %d\n", err);
+ }
+ /* Reschedule. */
+ const time_t tv_sec_next = (epoch + 1) * TST_KEY_LIFETIME;
+ const uint64_t ms_until_second = 1000 - (now.tv_usec + 501) / 1000;
+ const uint64_t remain_ms = (tv_sec_next - now.tv_sec - 1) * (uint64_t)1000
+ + ms_until_second + 1;
+ /* ^ +1 because we don't want to wake up half a millisecond before the epoch! */
+ assert(remain_ms < (TST_KEY_LIFETIME + 1 /*rounding tolerance*/) * 1000);
+ kr_log_verbose("[tls] session ticket: epoch %"PRIu64
+ ", scheduling rotation check in %"PRIu64" ms\n",
+ (uint64_t)epoch, remain_ms);
+ err = uv_timer_start(timer, &tst_timer_callback, remain_ms, 0);
+ if (err) {
+ assert(false);
+ kr_log_error("[tls] session ticket: failed to schedule, err = %d\n", err);
+ }
+}
+
+/* Implementation for prototypes from ./tls.h */
+
+void tls_session_ticket_enable(struct tls_session_ticket_ctx *ctx, gnutls_session_t session)
+{
+ assert(ctx && session);
+ const gnutls_datum_t gd = {
+ .size = SESSION_KEY_SIZE,
+ .data = ctx->key,
+ };
+ int err = gnutls_session_ticket_enable_server(session, &gd);
+ if (err) {
+ kr_log_error("[tls] failed to enable session tickets: %s (%d)\n",
+ gnutls_strerror_name(err), err);
+ /* but continue without tickets */
+ }
+}
+
+tst_ctx_t * tls_session_ticket_ctx_create(uv_loop_t *loop, const char *secret,
+ size_t secret_len)
+{
+ assert(loop && (!secret_len || secret));
+ #if GNUTLS_VERSION_NUMBER < 0x030500
+ /* We would need different SESSION_KEY_SIZE; avoid assert. */
+ return NULL;
+ #endif
+ tst_ctx_t *ctx = tst_key_create(secret, secret_len, loop);
+ if (ctx) {
+ tst_key_check(&ctx->timer, true);
+ }
+ return ctx;
+}
+
+void tls_session_ticket_ctx_destroy(tst_ctx_t *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ uv_close((uv_handle_t *)&ctx->timer, &tst_key_destroy);
+}
+
diff --git a/daemon/worker.c b/daemon/worker.c
new file mode 100644
index 0000000..117cc91
--- /dev/null
+++ b/daemon/worker.c
@@ -0,0 +1,2010 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <uv.h>
+#include <lua.h>
+#include <libknot/packet/pkt.h>
+#include <libknot/descriptor.h>
+#include <contrib/ucw/lib.h>
+#include <contrib/ucw/mempool.h>
+#include <contrib/wire.h>
+#if defined(__GLIBC__) && defined(_GNU_SOURCE)
+#include <malloc.h>
+#endif
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include "lib/utils.h"
+#include "lib/layer.h"
+#include "daemon/worker.h"
+#include "daemon/bindings.h"
+#include "daemon/engine.h"
+#include "daemon/io.h"
+#include "daemon/tls.h"
+#include "daemon/zimport.h"
+#include "daemon/session.h"
+
+
+/* Magic defaults for the worker. */
+#ifndef MP_FREELIST_SIZE
+# ifdef __clang_analyzer__
+# define MP_FREELIST_SIZE 0
+# else
+# define MP_FREELIST_SIZE 64 /**< Maximum length of the worker mempool freelist */
+# endif
+#endif
+#ifndef QUERY_RATE_THRESHOLD
+#define QUERY_RATE_THRESHOLD (2 * MP_FREELIST_SIZE) /**< Nr of parallel queries considered as high rate */
+#endif
+#ifndef MAX_PIPELINED
+#define MAX_PIPELINED 100
+#endif
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "wrkr", __VA_ARGS__)
+
+/** Client request state. */
+struct request_ctx
+{
+ struct kr_request req;
+ struct {
+ union inaddr addr;
+ union inaddr dst_addr;
+ /* uv_handle_t *handle; */
+
+ /** NULL if the request didn't come over network. */
+ struct session *session;
+ } source;
+ struct worker_ctx *worker;
+ struct qr_task *task;
+};
+
+/** Query resolution task. */
+struct qr_task
+{
+ struct request_ctx *ctx;
+ knot_pkt_t *pktbuf;
+ qr_tasklist_t waiting;
+ struct session *pending[MAX_PENDING];
+ uint16_t pending_count;
+ uint16_t addrlist_count;
+ uint16_t addrlist_turn;
+ uint16_t timeouts;
+ uint16_t iter_count;
+ struct sockaddr *addrlist;
+ uint32_t refs;
+ bool finished : 1;
+ bool leading : 1;
+ uint64_t creation_time;
+};
+
+
+/* Convenience macros */
+#define qr_task_ref(task) \
+ do { ++(task)->refs; } while(0)
+#define qr_task_unref(task) \
+ do { if (task && --(task)->refs == 0) { qr_task_free(task); } } while (0)
+
+/** @internal get key for tcp session
+ * @note kr_straddr() return pointer to static string
+ */
+#define tcpsess_key(addr) kr_straddr(addr)
+
+/* Forward decls */
+static void qr_task_free(struct qr_task *task);
+static int qr_task_step(struct qr_task *task,
+ const struct sockaddr *packet_source,
+ knot_pkt_t *packet);
+static int qr_task_send(struct qr_task *task, struct session *session,
+ struct sockaddr *addr, knot_pkt_t *pkt);
+static int qr_task_finalize(struct qr_task *task, int state);
+static void qr_task_complete(struct qr_task *task);
+static struct session* worker_find_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr *addr);
+static int worker_add_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr *addr,
+ struct session *session);
+static struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr *addr);
+static void on_tcp_connect_timeout(uv_timer_t *timer);
+
+/** @internal Get singleton worker. */
+static inline struct worker_ctx *get_worker(void)
+{
+ return uv_default_loop()->data;
+}
+
+/*! @internal Create a UDP/TCP handle for an outgoing AF_INET* connection.
+ * socktype is SOCK_* */
+static uv_handle_t *ioreq_spawn(struct worker_ctx *worker,
+ int socktype, sa_family_t family, bool has_tls)
+{
+ bool precond = (socktype == SOCK_DGRAM || socktype == SOCK_STREAM)
+ && (family == AF_INET || family == AF_INET6);
+ if (!precond) {
+ assert(false);
+ kr_log_verbose("[work] ioreq_spawn: pre-condition failed\n");
+ return NULL;
+ }
+
+ /* Create connection for iterative query */
+ uv_handle_t *handle = malloc(socktype == SOCK_DGRAM
+ ? sizeof(uv_udp_t) : sizeof(uv_tcp_t));
+ if (!handle) {
+ return NULL;
+ }
+ int ret = io_create(worker->loop, handle, socktype, family, has_tls);
+ if (ret) {
+ if (ret == UV_EMFILE) {
+ worker->too_many_open = true;
+ worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+ }
+ free(handle);
+ return NULL;
+ }
+
+ /* Bind to outgoing address, according to IP v4/v6. */
+ union inaddr *addr;
+ if (family == AF_INET) {
+ addr = (union inaddr *)&worker->out_addr4;
+ } else {
+ addr = (union inaddr *)&worker->out_addr6;
+ }
+ if (addr->ip.sa_family != AF_UNSPEC) {
+ assert(addr->ip.sa_family == family);
+ if (socktype == SOCK_DGRAM) {
+ uv_udp_t *udp = (uv_udp_t *)handle;
+ ret = uv_udp_bind(udp, &addr->ip, 0);
+ } else if (socktype == SOCK_STREAM){
+ uv_tcp_t *tcp = (uv_tcp_t *)handle;
+ ret = uv_tcp_bind(tcp, &addr->ip, 0);
+ }
+ }
+
+ if (ret != 0) {
+ io_deinit(handle);
+ free(handle);
+ return NULL;
+ }
+
+ /* Set current handle as a subrequest type. */
+ struct session *session = handle->data;
+ session_flags(session)->outgoing = true;
+ /* Connect or issue query datagram */
+ return handle;
+}
+
+static void ioreq_kill_pending(struct qr_task *task)
+{
+ for (uint16_t i = 0; i < task->pending_count; ++i) {
+ session_kill_ioreq(task->pending[i], task);
+ }
+ task->pending_count = 0;
+}
+
+/** @cond This memory layout is internal to mempool.c, use only for debugging. */
+#if defined(__SANITIZE_ADDRESS__)
+struct mempool_chunk {
+ struct mempool_chunk *next;
+ size_t size;
+};
+static void mp_poison(struct mempool *mp, bool poison)
+{
+ if (!poison) { /* @note mempool is part of the first chunk, unpoison it first */
+ kr_asan_unpoison(mp, sizeof(*mp));
+ }
+ struct mempool_chunk *chunk = mp->state.last[0];
+ void *chunk_off = (uint8_t *)chunk - chunk->size;
+ if (poison) {
+ kr_asan_poison(chunk_off, chunk->size);
+ } else {
+ kr_asan_unpoison(chunk_off, chunk->size);
+ }
+}
+#else
+#define mp_poison(mp, enable)
+#endif
+/** @endcond */
+
+/** Get a mempool. (Recycle if possible.) */
+static inline struct mempool *pool_borrow(struct worker_ctx *worker)
+{
+ struct mempool *mp = NULL;
+ if (worker->pool_mp.len > 0) {
+ mp = array_tail(worker->pool_mp);
+ array_pop(worker->pool_mp);
+ mp_poison(mp, 0);
+ } else { /* No mempool on the freelist, create new one */
+ mp = mp_new (4 * CPU_PAGE_SIZE);
+ }
+ return mp;
+}
+
+/** Return a mempool. (Cache them up to some count.) */
+static inline void pool_release(struct worker_ctx *worker, struct mempool *mp)
+{
+ if (worker->pool_mp.len < MP_FREELIST_SIZE) {
+ mp_flush(mp);
+ array_push(worker->pool_mp, mp);
+ mp_poison(mp, 1);
+ } else {
+ mp_delete(mp);
+ }
+}
+
+/** Create a key for an outgoing subrequest: qname, qclass, qtype.
+ * @param key Destination buffer for key size, MUST be SUBREQ_KEY_LEN or larger.
+ * @return key length if successful or an error
+ */
+static const size_t SUBREQ_KEY_LEN = KR_RRKEY_LEN;
+static int subreq_key(char *dst, knot_pkt_t *pkt)
+{
+ assert(pkt);
+ return kr_rrkey(dst, knot_pkt_qclass(pkt), knot_pkt_qname(pkt),
+ knot_pkt_qtype(pkt), knot_pkt_qtype(pkt));
+}
+
+/** Create and initialize a request_ctx (on a fresh mempool).
+ *
+ * handle and addr point to the source of the request, and they are NULL
+ * in case the request didn't come from network.
+ */
+static struct request_ctx *request_create(struct worker_ctx *worker,
+ uv_handle_t *handle,
+ const struct sockaddr *addr,
+ uint32_t uid)
+{
+ knot_mm_t pool = {
+ .ctx = pool_borrow(worker),
+ .alloc = (knot_mm_alloc_t) mp_alloc
+ };
+
+ /* Create request context */
+ struct request_ctx *ctx = mm_alloc(&pool, sizeof(*ctx));
+ if (!ctx) {
+ pool_release(worker, pool.ctx);
+ return NULL;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ /* TODO Relocate pool to struct request */
+ ctx->worker = worker;
+ struct session *s = handle ? handle->data : NULL;
+ if (s) {
+ assert(session_flags(s)->outgoing == false);
+ }
+ ctx->source.session = s;
+
+ struct kr_request *req = &ctx->req;
+ req->pool = pool;
+ req->vars_ref = LUA_NOREF;
+ req->uid = uid;
+ req->daemon_context = worker;
+
+ /* Remember query source addr */
+ if (!addr || (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)) {
+ ctx->source.addr.ip.sa_family = AF_UNSPEC;
+ } else {
+ memcpy(&ctx->source.addr, addr, kr_sockaddr_len(addr));
+ ctx->req.qsource.addr = &ctx->source.addr.ip;
+ }
+
+ worker->stats.rconcurrent += 1;
+
+ if (!handle) {
+ return ctx;
+ }
+
+ /* Remember the destination address. */
+ int addr_len = sizeof(ctx->source.dst_addr);
+ struct sockaddr *dst_addr = &ctx->source.dst_addr.ip;
+ ctx->source.dst_addr.ip.sa_family = AF_UNSPEC;
+ if (handle->type == UV_UDP) {
+ if (uv_udp_getsockname((uv_udp_t *)handle, dst_addr, &addr_len) == 0) {
+ req->qsource.dst_addr = dst_addr;
+ }
+ req->qsource.flags.tcp = false;
+ req->qsource.flags.tls = false;
+ } else if (handle->type == UV_TCP) {
+ if (uv_tcp_getsockname((uv_tcp_t *)handle, dst_addr, &addr_len) == 0) {
+ req->qsource.dst_addr = dst_addr;
+ }
+ req->qsource.flags.tcp = true;
+ req->qsource.flags.tls = s && session_flags(s)->has_tls;
+ }
+
+ return ctx;
+}
+
+/** More initialization, related to the particular incoming query/packet. */
+static int request_start(struct request_ctx *ctx, knot_pkt_t *query)
+{
+ assert(query && ctx);
+ size_t answer_max = KNOT_WIRE_MIN_PKTSIZE;
+ struct kr_request *req = &ctx->req;
+
+ /* source.session can be empty if request was generated by kresd itself */
+ struct session *s = ctx->source.session;
+ if (!s || session_get_handle(s)->type == UV_TCP) {
+ answer_max = KNOT_WIRE_MAX_PKTSIZE;
+ } else if (knot_pkt_has_edns(query)) { /* EDNS */
+ answer_max = MAX(knot_edns_get_payload(query->opt_rr),
+ KNOT_WIRE_MIN_PKTSIZE);
+ }
+ req->qsource.size = query->size;
+ if (knot_pkt_has_tsig(query)) {
+ req->qsource.size += query->tsig_wire.len;
+ }
+
+ knot_pkt_t *answer = knot_pkt_new(NULL, answer_max, &req->pool);
+ if (!answer) { /* Failed to allocate answer */
+ return kr_error(ENOMEM);
+ }
+
+ knot_pkt_t *pkt = knot_pkt_new(NULL, req->qsource.size, &req->pool);
+ if (!pkt) {
+ return kr_error(ENOMEM);
+ }
+
+ int ret = knot_pkt_copy(pkt, query);
+ if (ret != KNOT_EOK && ret != KNOT_ETRAIL) {
+ return kr_error(ENOMEM);
+ }
+ req->qsource.packet = pkt;
+
+ /* Start resolution */
+ struct worker_ctx *worker = ctx->worker;
+ struct engine *engine = worker->engine;
+ kr_resolve_begin(req, &engine->resolver, answer);
+ worker->stats.queries += 1;
+ /* Throttle outbound queries only when high pressure */
+ if (worker->stats.concurrent < QUERY_RATE_THRESHOLD) {
+ req->options.NO_THROTTLE = true;
+ }
+ return kr_ok();
+}
+
+static void request_free(struct request_ctx *ctx)
+{
+ struct worker_ctx *worker = ctx->worker;
+ /* Dereference any Lua vars table if exists */
+ if (ctx->req.vars_ref != LUA_NOREF) {
+ lua_State *L = worker->engine->L;
+ /* Get worker variables table */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, worker->vars_table_ref);
+ /* Get next free element (position 0) and store it under current reference (forming a list) */
+ lua_rawgeti(L, -1, 0);
+ lua_rawseti(L, -2, ctx->req.vars_ref);
+ /* Set current reference as the next free element */
+ lua_pushinteger(L, ctx->req.vars_ref);
+ lua_rawseti(L, -2, 0);
+ lua_pop(L, 1);
+ ctx->req.vars_ref = LUA_NOREF;
+ }
+ /* Return mempool to ring or free it if it's full */
+ pool_release(worker, ctx->req.pool.ctx);
+ /* @note The 'task' is invalidated from now on. */
+ /* Decommit memory every once in a while */
+ static int mp_delete_count = 0;
+ if (++mp_delete_count == 100000) {
+ lua_gc(worker->engine->L, LUA_GCCOLLECT, 0);
+#if defined(__GLIBC__) && defined(_GNU_SOURCE)
+ malloc_trim(0);
+#endif
+ mp_delete_count = 0;
+ }
+ worker->stats.rconcurrent -= 1;
+}
+
+static struct qr_task *qr_task_create(struct request_ctx *ctx)
+{
+ /* How much can client handle? */
+ struct engine *engine = ctx->worker->engine;
+ size_t pktbuf_max = KR_EDNS_PAYLOAD;
+ if (engine->resolver.opt_rr) {
+ pktbuf_max = MAX(knot_edns_get_payload(engine->resolver.opt_rr),
+ pktbuf_max);
+ }
+
+ /* Create resolution task */
+ struct qr_task *task = mm_alloc(&ctx->req.pool, sizeof(*task));
+ if (!task) {
+ return NULL;
+ }
+ memset(task, 0, sizeof(*task)); /* avoid accidentally unintialized fields */
+
+ /* Create packet buffers for answer and subrequests */
+ knot_pkt_t *pktbuf = knot_pkt_new(NULL, pktbuf_max, &ctx->req.pool);
+ if (!pktbuf) {
+ mm_free(&ctx->req.pool, task);
+ return NULL;
+ }
+ pktbuf->size = 0;
+
+ task->ctx = ctx;
+ task->pktbuf = pktbuf;
+ array_init(task->waiting);
+ task->refs = 0;
+ assert(ctx->task == NULL);
+ ctx->task = task;
+ /* Make the primary reference to task. */
+ qr_task_ref(task);
+ task->creation_time = kr_now();
+ ctx->worker->stats.concurrent += 1;
+ return task;
+}
+
+/* This is called when the task refcount is zero, free memory. */
+static void qr_task_free(struct qr_task *task)
+{
+ struct request_ctx *ctx = task->ctx;
+
+ assert(ctx);
+
+ struct worker_ctx *worker = ctx->worker;
+
+ if (ctx->task == NULL) {
+ request_free(ctx);
+ }
+
+ /* Update stats */
+ worker->stats.concurrent -= 1;
+}
+
+/*@ Register new qr_task within session. */
+static int qr_task_register(struct qr_task *task, struct session *session)
+{
+ assert(!session_flags(session)->outgoing && session_get_handle(session)->type == UV_TCP);
+
+ session_tasklist_add(session, task);
+
+ struct request_ctx *ctx = task->ctx;
+ assert(ctx && (ctx->source.session == NULL || ctx->source.session == session));
+ ctx->source.session = session;
+ /* Soft-limit on parallel queries, there is no "slow down" RCODE
+ * that we could use to signalize to client, but we can stop reading,
+ * an in effect shrink TCP window size. To get more precise throttling,
+ * we would need to copy remainder of the unread buffer and reassemble
+ * when resuming reading. This is NYI. */
+ if (session_tasklist_get_len(session) >= task->ctx->worker->tcp_pipeline_max &&
+ !session_flags(session)->throttled && !session_flags(session)->closing) {
+ session_stop_read(session);
+ session_flags(session)->throttled = true;
+ }
+
+ return 0;
+}
+
+static void qr_task_complete(struct qr_task *task)
+{
+ struct request_ctx *ctx = task->ctx;
+
+ /* Kill pending I/O requests */
+ ioreq_kill_pending(task);
+ assert(task->waiting.len == 0);
+ assert(task->leading == false);
+
+ struct session *s = ctx->source.session;
+ if (s) {
+ assert(!session_flags(s)->outgoing && session_waitinglist_is_empty(s));
+ ctx->source.session = NULL;
+ session_tasklist_del(s, task);
+ }
+
+ /* Release primary reference to task. */
+ if (ctx->task == task) {
+ ctx->task = NULL;
+ qr_task_unref(task);
+ }
+}
+
+/* This is called when we send subrequest / answer */
+static int qr_task_on_send(struct qr_task *task, uv_handle_t *handle, int status)
+{
+
+ if (task->finished) {
+ assert(task->leading == false);
+ qr_task_complete(task);
+ }
+
+ if (!handle || handle->type != UV_TCP) {
+ return status;
+ }
+
+ struct session* s = handle->data;
+ assert(s);
+ if (status != 0) {
+ session_tasklist_del(s, task);
+ }
+
+ if (session_flags(s)->outgoing || session_flags(s)->closing) {
+ return status;
+ }
+
+ struct worker_ctx *worker = task->ctx->worker;
+ if (session_flags(s)->throttled &&
+ session_tasklist_get_len(s) < worker->tcp_pipeline_max/2) {
+ /* Start reading again if the session is throttled and
+ * the number of outgoing requests is below watermark. */
+ session_start_read(s);
+ session_flags(s)->throttled = false;
+ }
+
+ return status;
+}
+
+static void on_send(uv_udp_send_t *req, int status)
+{
+ struct qr_task *task = req->data;
+ uv_handle_t *h = (uv_handle_t *)req->handle;
+ qr_task_on_send(task, h, status);
+ qr_task_unref(task);
+ free(req);
+}
+
+static void on_write(uv_write_t *req, int status)
+{
+ struct qr_task *task = req->data;
+ uv_handle_t *h = (uv_handle_t *)req->handle;
+ qr_task_on_send(task, h, status);
+ qr_task_unref(task);
+ free(req);
+}
+
+static int qr_task_send(struct qr_task *task, struct session *session,
+ struct sockaddr *addr, knot_pkt_t *pkt)
+{
+ if (!session) {
+ return qr_task_on_send(task, NULL, kr_error(EIO));
+ }
+
+ int ret = 0;
+ struct request_ctx *ctx = task->ctx;
+
+ uv_handle_t *handle = session_get_handle(session);
+ assert(handle && handle->data == session);
+ const bool is_stream = handle->type == UV_TCP;
+ if (!is_stream && handle->type != UV_UDP) abort();
+
+ if (addr == NULL) {
+ addr = session_get_peer(session);
+ }
+
+ if (pkt == NULL) {
+ pkt = worker_task_get_pktbuf(task);
+ }
+
+ if (session_flags(session)->outgoing && handle->type == UV_TCP) {
+ size_t try_limit = session_tasklist_get_len(session) + 1;
+ uint16_t msg_id = knot_wire_get_id(pkt->wire);
+ size_t try_count = 0;
+ while (session_tasklist_find_msgid(session, msg_id) &&
+ try_count <= try_limit) {
+ ++msg_id;
+ ++try_count;
+ }
+ if (try_count > try_limit) {
+ return kr_error(ENOENT);
+ }
+ worker_task_pkt_set_msgid(task, msg_id);
+ }
+
+ uv_handle_t *ioreq = malloc(is_stream ? sizeof(uv_write_t) : sizeof(uv_udp_send_t));
+ if (!ioreq) {
+ return qr_task_on_send(task, handle, kr_error(ENOMEM));
+ }
+
+ /* Pending ioreq on current task */
+ qr_task_ref(task);
+
+ struct worker_ctx *worker = ctx->worker;
+ /* Send using given protocol */
+ assert(!session_flags(session)->closing);
+ if (session_flags(session)->has_tls) {
+ uv_write_t *write_req = (uv_write_t *)ioreq;
+ write_req->data = task;
+ ret = tls_write(write_req, handle, pkt, &on_write);
+ } else if (handle->type == UV_UDP) {
+ uv_udp_send_t *send_req = (uv_udp_send_t *)ioreq;
+ uv_buf_t buf = { (char *)pkt->wire, pkt->size };
+ send_req->data = task;
+ ret = uv_udp_send(send_req, (uv_udp_t *)handle, &buf, 1, addr, &on_send);
+ } else if (handle->type == UV_TCP) {
+ uv_write_t *write_req = (uv_write_t *)ioreq;
+ uint16_t pkt_size = htons(pkt->size);
+ uv_buf_t buf[2] = {
+ { (char *)&pkt_size, sizeof(pkt_size) },
+ { (char *)pkt->wire, pkt->size }
+ };
+ write_req->data = task;
+ ret = uv_write(write_req, (uv_stream_t *)handle, buf, 2, &on_write);
+ } else {
+ assert(false);
+ }
+
+ if (ret == 0) {
+ session_touch(session);
+ if (session_flags(session)->outgoing) {
+ session_tasklist_add(session, task);
+ }
+ if (worker->too_many_open &&
+ worker->stats.rconcurrent <
+ worker->rconcurrent_highwatermark - 10) {
+ worker->too_many_open = false;
+ }
+ } else {
+ free(ioreq);
+ qr_task_unref(task);
+ if (ret == UV_EMFILE) {
+ worker->too_many_open = true;
+ worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+ ret = kr_error(UV_EMFILE);
+ }
+ }
+
+ /* Update statistics */
+ if (session_flags(session)->outgoing && addr) {
+ if (session_flags(session)->has_tls)
+ worker->stats.tls += 1;
+ else if (handle->type == UV_UDP)
+ worker->stats.udp += 1;
+ else
+ worker->stats.tcp += 1;
+
+ if (addr->sa_family == AF_INET6)
+ worker->stats.ipv6 += 1;
+ else if (addr->sa_family == AF_INET)
+ worker->stats.ipv4 += 1;
+ }
+ return ret;
+}
+
+static struct kr_query *task_get_last_pending_query(struct qr_task *task)
+{
+ if (!task || task->ctx->req.rplan.pending.len == 0) {
+ return NULL;
+ }
+
+ return array_tail(task->ctx->req.rplan.pending);
+}
+
+static int session_tls_hs_cb(struct session *session, int status)
+{
+ assert(session_flags(session)->outgoing);
+ uv_handle_t *handle = session_get_handle(session);
+ uv_loop_t *loop = handle->loop;
+ struct worker_ctx *worker = loop->data;
+ struct sockaddr *peer = session_get_peer(session);
+ int deletion_res = worker_del_tcp_waiting(worker, peer);
+ int ret = kr_ok();
+
+ if (status) {
+ struct qr_task *task = session_waitinglist_get(session);
+ if (task) {
+ struct kr_qflags *options = &task->ctx->req.options;
+ unsigned score = options->FORWARD || options->STUB ? KR_NS_FWD_DEAD : KR_NS_DEAD;
+ kr_nsrep_update_rtt(NULL, peer, score,
+ worker->engine->resolver.cache_rtt,
+ KR_NS_UPDATE_NORESET);
+ }
+#ifndef NDEBUG
+ else {
+ /* Task isn't in the list of tasks
+ * waiting for connection to upstream.
+ * So that it MUST be unsuccessful rehandshake.
+ * Check it. */
+ assert(deletion_res != 0);
+ const char *key = tcpsess_key(peer);
+ assert(key);
+ assert(map_contains(&worker->tcp_connected, key) != 0);
+ }
+#endif
+ return ret;
+ }
+
+ /* handshake was completed successfully */
+ struct tls_client_ctx_t *tls_client_ctx = session_tls_get_client_ctx(session);
+ struct tls_client_paramlist_entry *tls_params = tls_client_ctx->params;
+ gnutls_session_t tls_session = tls_client_ctx->c.tls_session;
+ if (gnutls_session_is_resumed(tls_session) != 0) {
+ kr_log_verbose("[tls_client] TLS session has resumed\n");
+ } else {
+ kr_log_verbose("[tls_client] TLS session has not resumed\n");
+ /* session wasn't resumed, delete old session data ... */
+ if (tls_params->session_data.data != NULL) {
+ gnutls_free(tls_params->session_data.data);
+ tls_params->session_data.data = NULL;
+ tls_params->session_data.size = 0;
+ }
+ /* ... and get the new session data */
+ gnutls_datum_t tls_session_data = { NULL, 0 };
+ ret = gnutls_session_get_data2(tls_session, &tls_session_data);
+ if (ret == 0) {
+ tls_params->session_data = tls_session_data;
+ }
+ }
+
+ struct session *s = worker_find_tcp_connected(worker, peer);
+ ret = kr_ok();
+ if (deletion_res == kr_ok()) {
+ /* peer was in the waiting list, add to the connected list. */
+ if (s) {
+ /* Something went wrong,
+ * peer already is in the connected list. */
+ ret = kr_error(EINVAL);
+ } else {
+ ret = worker_add_tcp_connected(worker, peer, session);
+ }
+ } else {
+ /* peer wasn't in the waiting list.
+ * It can be
+ * 1) either successful rehandshake; in this case peer
+ * must be already in the connected list.
+ * 2) or successful handshake with session, which was timeouted
+ * by on_tcp_connect_timeout(); after successful tcp connection;
+ * in this case peer isn't in the connected list.
+ **/
+ if (!s || s != session) {
+ ret = kr_error(EINVAL);
+ }
+ }
+ if (ret == kr_ok()) {
+ while (!session_waitinglist_is_empty(session)) {
+ struct qr_task *t = session_waitinglist_get(session);
+ ret = qr_task_send(t, session, NULL, NULL);
+ if (ret != 0) {
+ break;
+ }
+ session_waitinglist_pop(session, true);
+ }
+ } else {
+ ret = kr_error(EINVAL);
+ }
+
+ if (ret != kr_ok()) {
+ /* Something went wrong.
+ * Either addition to the list of connected sessions
+ * or write to upstream failed. */
+ worker_del_tcp_connected(worker, peer);
+ session_waitinglist_finalize(session, KR_STATE_FAIL);
+ assert(session_tasklist_is_empty(session));
+ session_close(session);
+ } else {
+ session_timer_stop(session);
+ session_timer_start(session, tcp_timeout_trigger,
+ MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
+ }
+ return kr_ok();
+}
+
+static int send_waiting(struct session *session)
+{
+ int ret = 0;
+ while (!session_waitinglist_is_empty(session)) {
+ struct qr_task *t = session_waitinglist_get(session);
+ ret = qr_task_send(t, session, NULL, NULL);
+ if (ret != 0) {
+ struct worker_ctx *worker = t->ctx->worker;
+ struct sockaddr *peer = session_get_peer(session);
+ session_waitinglist_finalize(session, KR_STATE_FAIL);
+ session_tasklist_finalize(session, KR_STATE_FAIL);
+ worker_del_tcp_connected(worker, peer);
+ session_close(session);
+ break;
+ }
+ session_waitinglist_pop(session, true);
+ }
+ return ret;
+}
+
+static void on_connect(uv_connect_t *req, int status)
+{
+ struct worker_ctx *worker = get_worker();
+ uv_stream_t *handle = req->handle;
+ struct session *session = handle->data;
+ struct sockaddr *peer = session_get_peer(session);
+ free(req);
+
+ assert(session_flags(session)->outgoing);
+
+ if (session_flags(session)->closing) {
+ worker_del_tcp_waiting(worker, peer);
+ assert(session_is_empty(session));
+ return;
+ }
+
+ /* Check if the connection is in the waiting list.
+ * If no, most likely this is timeouted connection
+ * which was removed from waiting list by
+ * on_tcp_connect_timeout() callback. */
+ struct session *s = worker_find_tcp_waiting(worker, peer);
+ if (!s || s != session) {
+ /* session isn't on the waiting list.
+ * it's timeouted session. */
+ if (VERBOSE_STATUS) {
+ const char *peer_str = kr_straddr(peer);
+ kr_log_verbose( "[wrkr]=> connected to '%s', but session "
+ "is already timeouted, close\n",
+ peer_str ? peer_str : "");
+ }
+ assert(session_tasklist_is_empty(session));
+ session_waitinglist_retry(session, false);
+ session_close(session);
+ return;
+ }
+
+ s = worker_find_tcp_connected(worker, peer);
+ if (s) {
+ /* session already in the connected list.
+ * Something went wrong, it can be due to races when kresd has tried
+ * to reconnect to upstream after unsuccessful attempt. */
+ if (VERBOSE_STATUS) {
+ const char *peer_str = kr_straddr(peer);
+ kr_log_verbose( "[wrkr]=> connected to '%s', but peer "
+ "is already connected, close\n",
+ peer_str ? peer_str : "");
+ }
+ assert(session_tasklist_is_empty(session));
+ session_waitinglist_retry(session, false);
+ session_close(session);
+ return;
+ }
+
+ if (status != 0) {
+ if (VERBOSE_STATUS) {
+ const char *peer_str = kr_straddr(peer);
+ kr_log_verbose( "[wrkr]=> connection to '%s' failed (%s), flagged as 'bad'\n",
+ peer_str ? peer_str : "", uv_strerror(status));
+ }
+ worker_del_tcp_waiting(worker, peer);
+ struct qr_task *task = session_waitinglist_get(session);
+ if (task && status != UV_ETIMEDOUT) {
+ /* Penalize upstream.
+ * In case of UV_ETIMEDOUT upstream has been
+ * already penalized in on_tcp_connect_timeout() */
+ struct kr_qflags *options = &task->ctx->req.options;
+ unsigned score = options->FORWARD || options->STUB ? KR_NS_FWD_DEAD : KR_NS_DEAD;
+ kr_nsrep_update_rtt(NULL, peer, score,
+ worker->engine->resolver.cache_rtt,
+ KR_NS_UPDATE_NORESET);
+ }
+ assert(session_tasklist_is_empty(session));
+ session_waitinglist_retry(session, false);
+ session_close(session);
+ return;
+ }
+
+ if (!session_flags(session)->has_tls) {
+ /* if there is a TLS, session still waiting for handshake,
+ * otherwise remove it from waiting list */
+ if (worker_del_tcp_waiting(worker, peer) != 0) {
+ /* session isn't in list of waiting queries, *
+ * something gone wrong */
+ session_waitinglist_finalize(session, KR_STATE_FAIL);
+ assert(session_tasklist_is_empty(session));
+ session_close(session);
+ return;
+ }
+ }
+
+ if (VERBOSE_STATUS) {
+ const char *peer_str = kr_straddr(peer);
+ kr_log_verbose( "[wrkr]=> connected to '%s'\n", peer_str ? peer_str : "");
+ }
+
+ session_flags(session)->connected = true;
+ session_start_read(session);
+
+ int ret = kr_ok();
+ if (session_flags(session)->has_tls) {
+ struct tls_client_ctx_t *tls_ctx = session_tls_get_client_ctx(session);
+ ret = tls_client_connect_start(tls_ctx, session, session_tls_hs_cb);
+ if (ret == kr_error(EAGAIN)) {
+ session_timer_stop(session);
+ session_timer_start(session, tcp_timeout_trigger,
+ MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
+ return;
+ }
+ } else {
+ worker_add_tcp_connected(worker, peer, session);
+ }
+
+ ret = send_waiting(session);
+ if (ret != 0) {
+ return;
+ }
+
+ session_timer_stop(session);
+ session_timer_start(session, tcp_timeout_trigger,
+ MAX_TCP_INACTIVITY, MAX_TCP_INACTIVITY);
+}
+
+static void on_tcp_connect_timeout(uv_timer_t *timer)
+{
+ struct session *session = timer->data;
+
+ uv_timer_stop(timer);
+ struct worker_ctx *worker = get_worker();
+
+ assert (session_tasklist_is_empty(session));
+
+ struct sockaddr *peer = session_get_peer(session);
+ worker_del_tcp_waiting(worker, peer);
+
+ struct qr_task *task = session_waitinglist_get(session);
+ if (!task) {
+ /* Normally shouldn't happen. */
+ const char *peer_str = kr_straddr(peer);
+ VERBOSE_MSG(NULL, "=> connection to '%s' failed (internal timeout), empty waitinglist\n",
+ peer_str ? peer_str : "");
+ return;
+ }
+
+ struct kr_query *qry = task_get_last_pending_query(task);
+ WITH_VERBOSE (qry) {
+ const char *peer_str = kr_straddr(peer);
+ VERBOSE_MSG(qry, "=> connection to '%s' failed (internal timeout)\n",
+ peer_str ? peer_str : "");
+ }
+
+ unsigned score = qry->flags.FORWARD || qry->flags.STUB ? KR_NS_FWD_DEAD : KR_NS_DEAD;
+ kr_nsrep_update_rtt(NULL, peer, score,
+ worker->engine->resolver.cache_rtt,
+ KR_NS_UPDATE_NORESET);
+
+ worker->stats.timeout += session_waitinglist_get_len(session);
+ session_waitinglist_retry(session, true);
+ assert (session_tasklist_is_empty(session));
+ /* uv_cancel() doesn't support uv_connect_t request,
+ * so that we can't cancel it.
+ * There still exists possibility of successful connection
+ * for this request.
+ * So connection callback (on_connect()) must check
+ * if connection is in the list of waiting connection.
+ * If no, most likely this is timeouted connection even if
+ * it was successful. */
+}
+
+/* This is called when I/O timeouts */
+static void on_udp_timeout(uv_timer_t *timer)
+{
+ struct session *session = timer->data;
+ assert(session_get_handle(session)->data == session);
+ assert(session_tasklist_get_len(session) == 1);
+ assert(session_waitinglist_is_empty(session));
+
+ uv_timer_stop(timer);
+
+ /* Penalize all tried nameservers with a timeout. */
+ struct qr_task *task = session_tasklist_get_first(session);
+ struct worker_ctx *worker = task->ctx->worker;
+ if (task->leading && task->pending_count > 0) {
+ struct kr_query *qry = array_tail(task->ctx->req.rplan.pending);
+ struct sockaddr_in6 *addrlist = (struct sockaddr_in6 *)task->addrlist;
+ for (uint16_t i = 0; i < MIN(task->pending_count, task->addrlist_count); ++i) {
+ struct sockaddr *choice = (struct sockaddr *)(&addrlist[i]);
+ WITH_VERBOSE(qry) {
+ char *addr_str = kr_straddr(choice);
+ VERBOSE_MSG(qry, "=> server: '%s' flagged as 'bad'\n", addr_str ? addr_str : "");
+ }
+ unsigned score = qry->flags.FORWARD || qry->flags.STUB ? KR_NS_FWD_DEAD : KR_NS_DEAD;
+ kr_nsrep_update_rtt(&qry->ns, choice, score,
+ worker->engine->resolver.cache_rtt,
+ KR_NS_UPDATE_NORESET);
+ }
+ }
+ task->timeouts += 1;
+ worker->stats.timeout += 1;
+ qr_task_step(task, NULL, NULL);
+}
+
+static uv_handle_t *retransmit(struct qr_task *task)
+{
+ uv_handle_t *ret = NULL;
+ if (task && task->addrlist && task->addrlist_count > 0) {
+ struct sockaddr_in6 *choice = &((struct sockaddr_in6 *)task->addrlist)[task->addrlist_turn];
+ if (!choice) {
+ return ret;
+ }
+ if (task->pending_count >= MAX_PENDING) {
+ return ret;
+ }
+ /* Checkout answer before sending it */
+ struct request_ctx *ctx = task->ctx;
+ if (kr_resolve_checkout(&ctx->req, NULL, (struct sockaddr *)choice, SOCK_DGRAM, task->pktbuf) != 0) {
+ return ret;
+ }
+ ret = ioreq_spawn(ctx->worker, SOCK_DGRAM, choice->sin6_family, false);
+ if (!ret) {
+ return ret;
+ }
+ struct sockaddr *addr = (struct sockaddr *)choice;
+ struct session *session = ret->data;
+ struct sockaddr *peer = session_get_peer(session);
+ assert (peer->sa_family == AF_UNSPEC && session_flags(session)->outgoing);
+ memcpy(peer, addr, kr_sockaddr_len(addr));
+ if (qr_task_send(task, session, (struct sockaddr *)choice,
+ task->pktbuf) != 0) {
+ session_close(session);
+ ret = NULL;
+ } else {
+ task->pending[task->pending_count] = session;
+ task->pending_count += 1;
+ task->addrlist_turn = (task->addrlist_turn + 1) %
+ task->addrlist_count; /* Round robin */
+ session_start_read(session); /* Start reading answer */
+ }
+ }
+ return ret;
+}
+
+static void on_retransmit(uv_timer_t *req)
+{
+ struct session *session = req->data;
+ assert(session_tasklist_get_len(session) == 1);
+
+ uv_timer_stop(req);
+ struct qr_task *task = session_tasklist_get_first(session);
+ if (retransmit(task) == NULL) {
+ /* Not possible to spawn request, start timeout timer with remaining deadline. */
+ struct kr_qflags *options = &task->ctx->req.options;
+ uint64_t timeout = options->FORWARD || options->STUB ? KR_NS_FWD_TIMEOUT / 2 :
+ KR_CONN_RTT_MAX - task->pending_count * KR_CONN_RETRY;
+ uv_timer_start(req, on_udp_timeout, timeout, 0);
+ } else {
+ uv_timer_start(req, on_retransmit, KR_CONN_RETRY, 0);
+ }
+}
+
+static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_source, knot_pkt_t *pkt)
+{
+ if (!task || task->finished) {
+ return;
+ }
+ /* Close pending timer */
+ ioreq_kill_pending(task);
+ /* Clear from outgoing table. */
+ if (!task->leading)
+ return;
+ char key[SUBREQ_KEY_LEN];
+ const int klen = subreq_key(key, task->pktbuf);
+ if (klen > 0) {
+ void *val_deleted;
+ int ret = trie_del(task->ctx->worker->subreq_out, key, klen, &val_deleted);
+ assert(ret == KNOT_EOK && val_deleted == task); (void)ret;
+ }
+ /* Notify waiting tasks. */
+ struct kr_query *leader_qry = array_tail(task->ctx->req.rplan.pending);
+ for (size_t i = task->waiting.len; i > 0; i--) {
+ struct qr_task *follower = task->waiting.at[i - 1];
+ /* Reuse MSGID and 0x20 secret */
+ if (follower->ctx->req.rplan.pending.len > 0) {
+ struct kr_query *qry = array_tail(follower->ctx->req.rplan.pending);
+ qry->id = leader_qry->id;
+ qry->secret = leader_qry->secret;
+ leader_qry->secret = 0; /* Next will be already decoded */
+ }
+ qr_task_step(follower, packet_source, pkt);
+ qr_task_unref(follower);
+ }
+ task->waiting.len = 0;
+ task->leading = false;
+}
+
+static void subreq_lead(struct qr_task *task)
+{
+ assert(task);
+ char key[SUBREQ_KEY_LEN];
+ const int klen = subreq_key(key, task->pktbuf);
+ if (klen < 0)
+ return;
+ struct qr_task **tvp = (struct qr_task **)
+ trie_get_ins(task->ctx->worker->subreq_out, key, klen);
+ if (unlikely(!tvp))
+ return; /*ENOMEM*/
+ if (unlikely(*tvp != NULL)) {
+ assert(false);
+ return;
+ }
+ *tvp = task;
+ task->leading = true;
+}
+
+static bool subreq_enqueue(struct qr_task *task)
+{
+ assert(task);
+ char key[SUBREQ_KEY_LEN];
+ const int klen = subreq_key(key, task->pktbuf);
+ if (klen < 0)
+ return false;
+ struct qr_task **leader = (struct qr_task **)
+ trie_get_try(task->ctx->worker->subreq_out, key, klen);
+ if (!leader /*ENOMEM*/ || !*leader)
+ return false;
+ /* Enqueue itself to leader for this subrequest. */
+ int ret = array_push_mm((*leader)->waiting, task,
+ kr_memreserve, &(*leader)->ctx->req.pool);
+ if (unlikely(ret < 0)) /*ENOMEM*/
+ return false;
+ qr_task_ref(task);
+ return true;
+}
+
+static int qr_task_finalize(struct qr_task *task, int state)
+{
+ assert(task && task->leading == false);
+ if (task->finished) {
+ return 0;
+ }
+ struct request_ctx *ctx = task->ctx;
+ struct session *source_session = ctx->source.session;
+ kr_resolve_finish(&ctx->req, state);
+
+ task->finished = true;
+ if (source_session == NULL) {
+ (void) qr_task_on_send(task, NULL, kr_error(EIO));
+ return state == KR_STATE_DONE ? 0 : kr_error(EIO);
+ }
+
+ /* Reference task as the callback handler can close it */
+ qr_task_ref(task);
+
+ /* Send back answer */
+ assert(!session_flags(source_session)->closing);
+ assert(ctx->source.addr.ip.sa_family != AF_UNSPEC);
+ int res = qr_task_send(task, source_session,
+ (struct sockaddr *)&ctx->source.addr,
+ ctx->req.answer);
+ if (res != kr_ok()) {
+ (void) qr_task_on_send(task, NULL, kr_error(EIO));
+ /* Since source session is erroneous detach all tasks. */
+ while (!session_tasklist_is_empty(source_session)) {
+ struct qr_task *t = session_tasklist_del_first(source_session, false);
+ struct request_ctx *c = t->ctx;
+ assert(c->source.session == source_session);
+ c->source.session = NULL;
+ /* Don't finalize them as there can be other tasks
+ * waiting for answer to this particular task.
+ * (ie. task->leading is true) */
+ worker_task_unref(t);
+ }
+ session_close(source_session);
+ }
+
+ qr_task_unref(task);
+
+ return state == KR_STATE_DONE ? 0 : kr_error(EIO);
+}
+
+static int udp_task_step(struct qr_task *task,
+ const struct sockaddr *packet_source, knot_pkt_t *packet)
+{
+ struct request_ctx *ctx = task->ctx;
+ struct kr_request *req = &ctx->req;
+
+ /* If there is already outgoing query, enqueue to it. */
+ if (subreq_enqueue(task)) {
+ return kr_ok(); /* Will be notified when outgoing query finishes. */
+ }
+ /* Start transmitting */
+ uv_handle_t *handle = retransmit(task);
+ if (handle == NULL) {
+ subreq_finalize(task, packet_source, packet);
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ /* Check current query NSLIST */
+ struct kr_query *qry = array_tail(req->rplan.pending);
+ assert(qry != NULL);
+ /* Retransmit at default interval, or more frequently if the mean
+ * RTT of the server is better. If the server is glued, use default rate. */
+ size_t timeout = qry->ns.score;
+ if (timeout > KR_NS_GLUED) {
+ /* We don't have information about variance in RTT, expect +10ms */
+ timeout = MIN(qry->ns.score + 10, KR_CONN_RETRY);
+ } else {
+ timeout = KR_CONN_RETRY;
+ }
+ /* Announce and start subrequest.
+ * @note Only UDP can lead I/O as it doesn't touch 'task->pktbuf' for reassembly.
+ */
+ subreq_lead(task);
+ struct session *session = handle->data;
+ assert(session_get_handle(session) == handle && (handle->type == UV_UDP));
+ int ret = session_timer_start(session, on_retransmit, timeout, 0);
+ /* Start next step with timeout, fatal if can't start a timer. */
+ if (ret != 0) {
+ subreq_finalize(task, packet_source, packet);
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ return kr_ok();
+}
+
+static int tcp_task_waiting_connection(struct session *session, struct qr_task *task)
+{
+ assert(session_flags(session)->outgoing);
+ if (session_flags(session)->closing) {
+ /* Something went wrong. Better answer with KR_STATE_FAIL.
+ * TODO: normally should not happen,
+ * consider possibility to transform this into
+ * assert(!session_flags(session)->closing). */
+ return kr_error(EINVAL);
+ }
+ /* Add task to the end of list of waiting tasks.
+ * It will be notified in on_connect() or qr_task_on_send(). */
+ int ret = session_waitinglist_push(session, task);
+ if (ret < 0) {
+ return kr_error(EINVAL);
+ }
+ return kr_ok();
+}
+
+static int tcp_task_existing_connection(struct session *session, struct qr_task *task)
+{
+ assert(session_flags(session)->outgoing);
+ struct request_ctx *ctx = task->ctx;
+ struct worker_ctx *worker = ctx->worker;
+
+ if (session_flags(session)->closing) {
+ /* Something went wrong. Better answer with KR_STATE_FAIL.
+ * TODO: normally should not happen,
+ * consider possibility to transform this into
+ * assert(!session_flags(session)->closing). */
+ return kr_error(EINVAL);
+ }
+
+ /* If there are any unsent queries, send it first. */
+ int ret = send_waiting(session);
+ if (ret != 0) {
+ return kr_error(EINVAL);
+ }
+
+ /* No unsent queries at that point. */
+ if (session_tasklist_get_len(session) >= worker->tcp_pipeline_max) {
+ /* Too many outstanding queries, answer with SERFVAIL, */
+ return kr_error(EINVAL);
+ }
+
+ /* Send query to upstream. */
+ ret = qr_task_send(task, session, NULL, NULL);
+ if (ret != 0) {
+ /* Error, finalize task with SERVFAIL and
+ * close connection to upstream. */
+ session_tasklist_finalize(session, KR_STATE_FAIL);
+ worker_del_tcp_connected(worker, session_get_peer(session));
+ session_close(session);
+ return kr_error(EINVAL);
+ }
+
+ return kr_ok();
+}
+
+static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr *addr)
+{
+ struct request_ctx *ctx = task->ctx;
+ struct worker_ctx *worker = ctx->worker;
+
+ /* Check if there must be TLS */
+ struct engine *engine = worker->engine;
+ struct network *net = &engine->net;
+ const char *key = tcpsess_key(addr);
+ struct tls_client_ctx_t *tls_ctx = NULL;
+ struct tls_client_paramlist_entry *entry = map_get(&net->tls_client_params, key);
+ if (entry) {
+ /* Address is configured to be used with TLS.
+ * We need to allocate auxiliary data structure. */
+ tls_ctx = tls_client_ctx_new(entry, worker);
+ if (!tls_ctx) {
+ return kr_error(EINVAL);
+ }
+ }
+
+ uv_connect_t *conn = malloc(sizeof(uv_connect_t));
+ if (!conn) {
+ tls_client_ctx_free(tls_ctx);
+ return kr_error(EINVAL);
+ }
+ bool has_tls = (tls_ctx != NULL);
+ uv_handle_t *client = ioreq_spawn(worker, SOCK_STREAM, addr->sa_family, has_tls);
+ if (!client) {
+ tls_client_ctx_free(tls_ctx);
+ free(conn);
+ return kr_error(EINVAL);
+ }
+ struct session *session = client->data;
+ assert(session_flags(session)->has_tls == has_tls);
+ if (has_tls) {
+ tls_client_ctx_set_session(tls_ctx, session);
+ session_tls_set_client_ctx(session, tls_ctx);
+ }
+
+ /* Add address to the waiting list.
+ * Now it "is waiting to be connected to." */
+ int ret = worker_add_tcp_waiting(ctx->worker, addr, session);
+ if (ret < 0) {
+ free(conn);
+ session_close(session);
+ return kr_error(EINVAL);
+ }
+
+ conn->data = session;
+ /* Store peer address for the session. */
+ struct sockaddr *peer = session_get_peer(session);
+ memcpy(peer, addr, kr_sockaddr_len(addr));
+
+ /* Start watchdog to catch eventual connection timeout. */
+ ret = session_timer_start(session, on_tcp_connect_timeout,
+ KR_CONN_RTT_MAX, 0);
+ if (ret != 0) {
+ worker_del_tcp_waiting(ctx->worker, addr);
+ free(conn);
+ session_close(session);
+ return kr_error(EINVAL);
+ }
+
+ struct kr_query *qry = task_get_last_pending_query(task);
+ WITH_VERBOSE (qry) {
+ const char *peer_str = kr_straddr(peer);
+ VERBOSE_MSG(qry, "=> connecting to: '%s'\n", peer_str ? peer_str : "");
+ }
+
+ /* Start connection process to upstream. */
+ ret = uv_tcp_connect(conn, (uv_tcp_t *)client, addr , on_connect);
+ if (ret != 0) {
+ session_timer_stop(session);
+ worker_del_tcp_waiting(ctx->worker, addr);
+ free(conn);
+ session_close(session);
+ unsigned score = qry->flags.FORWARD || qry->flags.STUB ? KR_NS_FWD_DEAD : KR_NS_DEAD;
+ kr_nsrep_update_rtt(NULL, peer, score,
+ worker->engine->resolver.cache_rtt,
+ KR_NS_UPDATE_NORESET);
+ WITH_VERBOSE (qry) {
+ const char *peer_str = kr_straddr(peer);
+ kr_log_verbose( "[wrkr]=> connect to '%s' failed (%s), flagged as 'bad'\n",
+ peer_str ? peer_str : "", uv_strerror(ret));
+ }
+ return kr_error(EAGAIN);
+ }
+
+ /* Add task to the end of list of waiting tasks.
+ * Will be notified either in on_connect() or in qr_task_on_send(). */
+ ret = session_waitinglist_push(session, task);
+ if (ret < 0) {
+ session_timer_stop(session);
+ worker_del_tcp_waiting(ctx->worker, addr);
+ free(conn);
+ session_close(session);
+ return kr_error(EINVAL);
+ }
+
+ return kr_ok();
+}
+
+static int tcp_task_step(struct qr_task *task,
+ const struct sockaddr *packet_source, knot_pkt_t *packet)
+{
+ assert(task->pending_count == 0);
+
+ /* target */
+ const struct sockaddr *addr = task->addrlist;
+ if (addr->sa_family == AF_UNSPEC) {
+ /* Target isn't defined. Finalize task with SERVFAIL.
+ * Although task->pending_count is zero, there are can be followers,
+ * so we need to call subreq_finalize() to handle them properly. */
+ subreq_finalize(task, packet_source, packet);
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ /* Checkout task before connecting */
+ struct request_ctx *ctx = task->ctx;
+ if (kr_resolve_checkout(&ctx->req, NULL, (struct sockaddr *)addr,
+ SOCK_STREAM, task->pktbuf) != 0) {
+ subreq_finalize(task, packet_source, packet);
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ int ret;
+ struct session* session = NULL;
+ if ((session = worker_find_tcp_waiting(ctx->worker, addr)) != NULL) {
+ /* Connection is in the list of waiting connections.
+ * It means that connection establishing is coming right now. */
+ ret = tcp_task_waiting_connection(session, task);
+ } else if ((session = worker_find_tcp_connected(ctx->worker, addr)) != NULL) {
+ /* Connection has been already established. */
+ ret = tcp_task_existing_connection(session, task);
+ } else {
+ /* Make connection. */
+ ret = tcp_task_make_connection(task, addr);
+ }
+
+ if (ret != kr_ok()) {
+ subreq_finalize(task, addr, packet);
+ if (ret == kr_error(EAGAIN)) {
+ ret = qr_task_step(task, addr, NULL);
+ } else {
+ ret = qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ }
+
+ return ret;
+}
+
+static int qr_task_step(struct qr_task *task,
+ const struct sockaddr *packet_source, knot_pkt_t *packet)
+{
+ /* No more steps after we're finished. */
+ if (!task || task->finished) {
+ return kr_error(ESTALE);
+ }
+
+ /* Close pending I/O requests */
+ subreq_finalize(task, packet_source, packet);
+ if ((kr_now() - worker_task_creation_time(task)) >= KR_RESOLVE_TIME_LIMIT) {
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+
+ /* Consume input and produce next query */
+ struct request_ctx *ctx = task->ctx;
+ assert(ctx);
+ struct kr_request *req = &ctx->req;
+ struct worker_ctx *worker = ctx->worker;
+ int sock_type = -1;
+ task->addrlist = NULL;
+ task->addrlist_count = 0;
+ task->addrlist_turn = 0;
+
+ if (worker->too_many_open) {
+ /* */
+ struct kr_rplan *rplan = &req->rplan;
+ if (worker->stats.rconcurrent <
+ worker->rconcurrent_highwatermark - 10) {
+ worker->too_many_open = false;
+ } else {
+ if (packet && kr_rplan_empty(rplan)) {
+ /* new query; TODO - make this detection more obvious */
+ kr_resolve_consume(req, packet_source, packet);
+ }
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ }
+
+ int state = kr_resolve_consume(req, packet_source, packet);
+ while (state == KR_STATE_PRODUCE) {
+ state = kr_resolve_produce(req, &task->addrlist,
+ &sock_type, task->pktbuf);
+ if (unlikely(++task->iter_count > KR_ITER_LIMIT ||
+ task->timeouts >= KR_TIMEOUT_LIMIT)) {
+ return qr_task_finalize(task, KR_STATE_FAIL);
+ }
+ }
+
+ /* We're done, no more iterations needed */
+ if (state & (KR_STATE_DONE|KR_STATE_FAIL)) {
+ return qr_task_finalize(task, state);
+ } else if (!task->addrlist || sock_type < 0) {
+ return qr_task_step(task, NULL, NULL);
+ }
+
+ /* Count available address choices */
+ struct sockaddr_in6 *choice = (struct sockaddr_in6 *)task->addrlist;
+ for (size_t i = 0; i < KR_NSREP_MAXADDR && choice->sin6_family != AF_UNSPEC; ++i) {
+ task->addrlist_count += 1;
+ choice += 1;
+ }
+
+ /* Upgrade to TLS if the upstream address is configured as DoT capable. */
+ if (task->addrlist_count > 0 && kr_inaddr_port(task->addrlist) == KR_DNS_PORT) {
+ /* TODO if there are multiple addresses (task->addrlist_count > 1)
+ * check all of them. */
+ struct engine *engine = worker->engine;
+ struct network *net = &engine->net;
+ struct tls_client_paramlist_entry *tls_entry =
+ tls_client_try_upgrade(&net->tls_client_params, task->addrlist);
+ if (tls_entry != NULL) {
+ kr_inaddr_set_port(task->addrlist, KR_DNS_TLS_PORT);
+ packet_source = NULL;
+ sock_type = SOCK_STREAM;
+ /* TODO in this case in tcp_task_make_connection() will be performed
+ * redundant map_get() call. */
+ }
+ }
+
+ int ret = 0;
+ if (sock_type == SOCK_DGRAM) {
+ /* Start fast retransmit with UDP. */
+ ret = udp_task_step(task, packet_source, packet);
+ } else {
+ /* TCP. Connect to upstream or send the query if connection already exists. */
+ assert (sock_type == SOCK_STREAM);
+ ret = tcp_task_step(task, packet_source, packet);
+ }
+ return ret;
+}
+
+static int parse_packet(knot_pkt_t *query)
+{
+ if (!query){
+ return kr_error(EINVAL);
+ }
+
+ /* Parse query packet. */
+ int ret = knot_pkt_parse(query, 0);
+ if (ret == KNOT_ETRAIL) {
+ /* Extra data after message end. */
+ ret = kr_error(EMSGSIZE);
+ } else if (ret != KNOT_EOK) {
+ /* Malformed query. */
+ ret = kr_error(EPROTO);
+ } else {
+ ret = kr_ok();
+ }
+
+ return ret;
+}
+
+int worker_submit(struct session *session, knot_pkt_t *query)
+{
+ if (!session) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+
+ uv_handle_t *handle = session_get_handle(session);
+ bool OK = handle && handle->loop->data;
+ if (!OK) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+
+ struct worker_ctx *worker = handle->loop->data;
+
+ /* Parse packet */
+ int ret = parse_packet(query);
+
+ const bool is_query = (knot_wire_get_qr(query->wire) == 0);
+ const bool is_outgoing = session_flags(session)->outgoing;
+ /* Ignore badly formed queries. */
+ if (!query ||
+ (ret != kr_ok() && ret != kr_error(EMSGSIZE)) ||
+ (is_query == is_outgoing)) {
+ if (query && !is_outgoing) worker->stats.dropped += 1;
+ return kr_error(EILSEQ);
+ }
+
+ /* Start new task on listening sockets,
+ * or resume if this is subrequest */
+ struct qr_task *task = NULL;
+ struct sockaddr *addr = NULL;
+ if (!is_outgoing) { /* request from a client */
+ struct request_ctx *ctx = request_create(worker, handle,
+ session_get_peer(session),
+ knot_wire_get_id(query->wire));
+ if (!ctx) {
+ return kr_error(ENOMEM);
+ }
+
+ ret = request_start(ctx, query);
+ if (ret != 0) {
+ request_free(ctx);
+ return kr_error(ENOMEM);
+ }
+
+ task = qr_task_create(ctx);
+ if (!task) {
+ request_free(ctx);
+ return kr_error(ENOMEM);
+ }
+
+ if (handle->type == UV_TCP && qr_task_register(task, session)) {
+ return kr_error(ENOMEM);
+ }
+ } else if (query) { /* response from upstream */
+ task = session_tasklist_del_msgid(session, knot_wire_get_id(query->wire));
+ if (task == NULL) {
+ return kr_error(ENOENT);
+ }
+ assert(!session_flags(session)->closing);
+ addr = session_get_peer(session);
+ }
+ assert(uv_is_closing(session_get_handle(session)) == false);
+
+ /* Packet was successfully parsed.
+ * Task was created (found). */
+ session_touch(session);
+ /* Consume input and produce next message */
+ return qr_task_step(task, addr, query);
+}
+
+static int map_add_tcp_session(map_t *map, const struct sockaddr* addr,
+ struct session *session)
+{
+ assert(map && addr);
+ const char *key = tcpsess_key(addr);
+ assert(key);
+ assert(map_contains(map, key) == 0);
+ int ret = map_set(map, key, session);
+ return ret ? kr_error(EINVAL) : kr_ok();
+}
+
+static int map_del_tcp_session(map_t *map, const struct sockaddr* addr)
+{
+ assert(map && addr);
+ const char *key = tcpsess_key(addr);
+ assert(key);
+ int ret = map_del(map, key);
+ return ret ? kr_error(ENOENT) : kr_ok();
+}
+
+static struct session* map_find_tcp_session(map_t *map,
+ const struct sockaddr *addr)
+{
+ assert(map && addr);
+ const char *key = tcpsess_key(addr);
+ assert(key);
+ struct session* ret = map_get(map, key);
+ return ret;
+}
+
+int worker_add_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr* addr,
+ struct session *session)
+{
+#ifndef NDEBUG
+ assert(addr);
+ const char *key = tcpsess_key(addr);
+ assert(key);
+ assert(map_contains(&worker->tcp_connected, key) == 0);
+#endif
+ return map_add_tcp_session(&worker->tcp_connected, addr, session);
+}
+
+int worker_del_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr* addr)
+{
+ assert(addr && tcpsess_key(addr));
+ return map_del_tcp_session(&worker->tcp_connected, addr);
+}
+
+static struct session* worker_find_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr* addr)
+{
+ return map_find_tcp_session(&worker->tcp_connected, addr);
+}
+
+static int worker_add_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr* addr,
+ struct session *session)
+{
+#ifndef NDEBUG
+ assert(addr);
+ const char *key = tcpsess_key(addr);
+ assert(key);
+ assert(map_contains(&worker->tcp_waiting, key) == 0);
+#endif
+ return map_add_tcp_session(&worker->tcp_waiting, addr, session);
+}
+
+int worker_del_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr* addr)
+{
+ assert(addr && tcpsess_key(addr));
+ return map_del_tcp_session(&worker->tcp_waiting, addr);
+}
+
+static struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr* addr)
+{
+ return map_find_tcp_session(&worker->tcp_waiting, addr);
+}
+
+int worker_end_tcp(struct session *session)
+{
+ if (!session) {
+ return kr_error(EINVAL);
+ }
+
+ session_timer_stop(session);
+
+ uv_handle_t *handle = session_get_handle(session);
+ struct worker_ctx *worker = handle->loop->data;
+ struct sockaddr *peer = session_get_peer(session);
+
+ worker_del_tcp_waiting(worker, peer);
+ worker_del_tcp_connected(worker, peer);
+ session_flags(session)->connected = false;
+
+ struct tls_client_ctx_t *tls_client_ctx = session_tls_get_client_ctx(session);
+ if (tls_client_ctx) {
+ /* Avoid gnutls_bye() call */
+ tls_set_hs_state(&tls_client_ctx->c, TLS_HS_NOT_STARTED);
+ }
+
+ struct tls_ctx_t *tls_ctx = session_tls_get_server_ctx(session);
+ if (tls_ctx) {
+ /* Avoid gnutls_bye() call */
+ tls_set_hs_state(&tls_ctx->c, TLS_HS_NOT_STARTED);
+ }
+
+ while (!session_waitinglist_is_empty(session)) {
+ struct qr_task *task = session_waitinglist_pop(session, false);
+ assert(task->refs > 1);
+ session_tasklist_del(session, task);
+ if (session_flags(session)->outgoing) {
+ if (task->ctx->req.options.FORWARD) {
+ /* We are in TCP_FORWARD mode.
+ * To prevent failing at kr_resolve_consume()
+ * qry.flags.TCP must be cleared.
+ * TODO - refactoring is needed. */
+ struct kr_request *req = &task->ctx->req;
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *qry = array_tail(rplan->pending);
+ qry->flags.TCP = false;
+ }
+ qr_task_step(task, NULL, NULL);
+ } else {
+ assert(task->ctx->source.session == session);
+ task->ctx->source.session = NULL;
+ }
+ worker_task_unref(task);
+ }
+ while (!session_tasklist_is_empty(session)) {
+ struct qr_task *task = session_tasklist_del_first(session, false);
+ if (session_flags(session)->outgoing) {
+ if (task->ctx->req.options.FORWARD) {
+ struct kr_request *req = &task->ctx->req;
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *qry = array_tail(rplan->pending);
+ qry->flags.TCP = false;
+ }
+ qr_task_step(task, NULL, NULL);
+ } else {
+ assert(task->ctx->source.session == session);
+ task->ctx->source.session = NULL;
+ }
+ worker_task_unref(task);
+ }
+ session_close(session);
+ return kr_ok();
+}
+
+struct qr_task *worker_resolve_start(struct worker_ctx *worker, knot_pkt_t *query, struct kr_qflags options)
+{
+ if (!worker || !query) {
+ assert(!EINVAL);
+ return NULL;
+ }
+
+
+ struct request_ctx *ctx = request_create(worker, NULL, NULL, worker->next_request_uid);
+ if (!ctx) {
+ return NULL;
+ }
+
+ /* Create task */
+ struct qr_task *task = qr_task_create(ctx);
+ if (!task) {
+ request_free(ctx);
+ return NULL;
+ }
+
+ /* Start task */
+ int ret = request_start(ctx, query);
+ if (ret != 0) {
+ /* task is attached to request context,
+ * so dereference (and deallocate) it first */
+ ctx->task = NULL;
+ qr_task_unref(task);
+ request_free(ctx);
+ return NULL;
+ }
+
+ worker->next_request_uid += 1;
+ if (worker->next_request_uid == 0) {
+ worker->next_request_uid = UINT16_MAX + 1;
+ }
+
+ /* Set options late, as qr_task_start() -> kr_resolve_begin() rewrite it. */
+ kr_qflags_set(&task->ctx->req.options, options);
+ return task;
+}
+
+int worker_resolve_exec(struct qr_task *task, knot_pkt_t *query)
+{
+ if (!task) {
+ return kr_error(EINVAL);
+ }
+ return qr_task_step(task, NULL, query);
+}
+
+int worker_task_numrefs(const struct qr_task *task)
+{
+ return task->refs;
+}
+
+struct kr_request *worker_task_request(struct qr_task *task)
+{
+ if (!task || !task->ctx) {
+ return NULL;
+ }
+
+ return &task->ctx->req;
+}
+
+int worker_task_finalize(struct qr_task *task, int state)
+{
+ return qr_task_finalize(task, state);
+}
+
+ int worker_task_step(struct qr_task *task, const struct sockaddr *packet_source,
+ knot_pkt_t *packet)
+ {
+ return qr_task_step(task, packet_source, packet);
+ }
+
+void worker_task_complete(struct qr_task *task)
+{
+ qr_task_complete(task);
+}
+
+void worker_task_ref(struct qr_task *task)
+{
+ qr_task_ref(task);
+}
+
+void worker_task_unref(struct qr_task *task)
+{
+ qr_task_unref(task);
+}
+
+void worker_task_timeout_inc(struct qr_task *task)
+{
+ task->timeouts += 1;
+}
+
+knot_pkt_t *worker_task_get_pktbuf(const struct qr_task *task)
+{
+ return task->pktbuf;
+}
+
+struct request_ctx *worker_task_get_request(struct qr_task *task)
+{
+ return task->ctx;
+}
+
+struct session *worker_request_get_source_session(struct request_ctx *ctx)
+{
+ return ctx->source.session;
+}
+
+void worker_request_set_source_session(struct request_ctx *ctx, struct session *session)
+{
+ ctx->source.session = session;
+}
+
+uint16_t worker_task_pkt_get_msgid(struct qr_task *task)
+{
+ knot_pkt_t *pktbuf = worker_task_get_pktbuf(task);
+ uint16_t msg_id = knot_wire_get_id(pktbuf->wire);
+ return msg_id;
+}
+
+void worker_task_pkt_set_msgid(struct qr_task *task, uint16_t msgid)
+{
+ knot_pkt_t *pktbuf = worker_task_get_pktbuf(task);
+ knot_wire_set_id(pktbuf->wire, msgid);
+ struct kr_query *q = task_get_last_pending_query(task);
+ q->id = msgid;
+}
+
+uint64_t worker_task_creation_time(struct qr_task *task)
+{
+ return task->creation_time;
+}
+
+void worker_task_subreq_finalize(struct qr_task *task)
+{
+ subreq_finalize(task, NULL, NULL);
+}
+
+bool worker_task_finished(struct qr_task *task)
+{
+ return task->finished;
+}
+/** Reserve worker buffers */
+static int worker_reserve(struct worker_ctx *worker, size_t ring_maxlen)
+{
+ array_init(worker->pool_mp);
+ if (array_reserve(worker->pool_mp, ring_maxlen)) {
+ return kr_error(ENOMEM);
+ }
+ memset(&worker->pkt_pool, 0, sizeof(worker->pkt_pool));
+ worker->pkt_pool.ctx = mp_new (4 * sizeof(knot_pkt_t));
+ worker->pkt_pool.alloc = (knot_mm_alloc_t) mp_alloc;
+ worker->subreq_out = trie_create(NULL);
+ worker->tcp_connected = map_make(NULL);
+ worker->tcp_waiting = map_make(NULL);
+ worker->tcp_pipeline_max = MAX_PIPELINED;
+ memset(&worker->stats, 0, sizeof(worker->stats));
+ return kr_ok();
+}
+
+static inline void reclaim_mp_freelist(mp_freelist_t *list)
+{
+ for (unsigned i = 0; i < list->len; ++i) {
+ struct mempool *e = list->at[i];
+ kr_asan_unpoison(e, sizeof(*e));
+ mp_delete(e);
+ }
+ array_clear(*list);
+}
+
+void worker_reclaim(struct worker_ctx *worker)
+{
+ reclaim_mp_freelist(&worker->pool_mp);
+ mp_delete(worker->pkt_pool.ctx);
+ worker->pkt_pool.ctx = NULL;
+ trie_free(worker->subreq_out);
+ worker->subreq_out = NULL;
+ map_clear(&worker->tcp_connected);
+ map_clear(&worker->tcp_waiting);
+ if (worker->z_import != NULL) {
+ zi_free(worker->z_import);
+ worker->z_import = NULL;
+ }
+}
+
+struct worker_ctx *worker_create(struct engine *engine, knot_mm_t *pool,
+ int worker_id, int worker_count)
+{
+ /* Load bindings */
+ engine_lualib(engine, "modules", lib_modules);
+ engine_lualib(engine, "net", lib_net);
+ engine_lualib(engine, "cache", lib_cache);
+ engine_lualib(engine, "event", lib_event);
+ engine_lualib(engine, "worker", lib_worker);
+
+ /* Create main worker. */
+ struct worker_ctx *worker = mm_alloc(pool, sizeof(*worker));
+ if (!worker) {
+ return NULL;
+ }
+ memset(worker, 0, sizeof(*worker));
+ worker->id = worker_id;
+ worker->count = worker_count;
+ worker->engine = engine;
+ worker->next_request_uid = UINT16_MAX + 1;
+ worker_reserve(worker, MP_FREELIST_SIZE);
+ worker->out_addr4.sin_family = AF_UNSPEC;
+ worker->out_addr6.sin6_family = AF_UNSPEC;
+ /* Register worker in Lua thread */
+ lua_pushlightuserdata(engine->L, worker);
+ lua_setglobal(engine->L, "__worker");
+ lua_getglobal(engine->L, "worker");
+ lua_pushnumber(engine->L, worker_id);
+ lua_setfield(engine->L, -2, "id");
+ lua_pushnumber(engine->L, getpid());
+ lua_setfield(engine->L, -2, "pid");
+ lua_pushnumber(engine->L, worker_count);
+ lua_setfield(engine->L, -2, "count");
+ /* Register table for worker per-request variables */
+ lua_newtable(engine->L);
+ lua_setfield(engine->L, -2, "vars");
+ lua_getfield(engine->L, -1, "vars");
+ worker->vars_table_ref = luaL_ref(engine->L, LUA_REGISTRYINDEX);
+ lua_pop(engine->L, 1);
+ return worker;
+}
+
+#undef VERBOSE_MSG
diff --git a/daemon/worker.h b/daemon/worker.h
new file mode 100644
index 0000000..f56e10d
--- /dev/null
+++ b/daemon/worker.h
@@ -0,0 +1,171 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "daemon/engine.h"
+#include "lib/generic/array.h"
+#include "lib/generic/map.h"
+
+
+/** Query resolution task (opaque). */
+struct qr_task;
+/** Worker state (opaque). */
+struct worker_ctx;
+/** Transport session (opaque). */
+struct session;
+/** Zone import context (opaque). */
+struct zone_import_ctx;
+
+/** Create and initialize the worker. */
+struct worker_ctx *worker_create(struct engine *engine, knot_mm_t *pool,
+ int worker_id, int worker_count);
+
+/**
+ * Process an incoming packet (query from a client or answer from upstream).
+ *
+ * @param session session the where packet came from
+ * @param query the packet, or NULL on an error from the transport layer
+ * @return 0 or an error code
+ */
+int worker_submit(struct session *session, knot_pkt_t *query);
+
+/**
+ * End current DNS/TCP session, this disassociates pending tasks from this session
+ * which may be freely closed afterwards.
+ */
+int worker_end_tcp(struct session *session);
+
+/**
+ * Start query resolution with given query.
+ *
+ * @return task or NULL
+ */
+struct qr_task *worker_resolve_start(struct worker_ctx *worker, knot_pkt_t *query, struct kr_qflags options);
+
+/**
+ * Execute a request with given query.
+ * It expects task to be created with \fn worker_resolve_start.
+ *
+ * @return 0 or an error code
+ */
+int worker_resolve_exec(struct qr_task *task, knot_pkt_t *query);
+
+/** @return struct kr_request associated with opaque task */
+struct kr_request *worker_task_request(struct qr_task *task);
+
+/** Collect worker mempools */
+void worker_reclaim(struct worker_ctx *worker);
+
+int worker_task_step(struct qr_task *task, const struct sockaddr *packet_source,
+ knot_pkt_t *packet);
+
+int worker_task_numrefs(const struct qr_task *task);
+
+/** Finalize given task */
+int worker_task_finalize(struct qr_task *task, int state);
+
+void worker_task_complete(struct qr_task *task);
+
+void worker_task_ref(struct qr_task *task);
+
+void worker_task_unref(struct qr_task *task);
+
+void worker_task_timeout_inc(struct qr_task *task);
+
+int worker_add_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr *addr,
+ struct session *session);
+int worker_del_tcp_connected(struct worker_ctx *worker,
+ const struct sockaddr *addr);
+int worker_del_tcp_waiting(struct worker_ctx *worker,
+ const struct sockaddr* addr);
+knot_pkt_t *worker_task_get_pktbuf(const struct qr_task *task);
+
+struct request_ctx *worker_task_get_request(struct qr_task *task);
+
+struct session *worker_request_get_source_session(struct request_ctx *);
+
+void worker_request_set_source_session(struct request_ctx *, struct session *session);
+
+uint16_t worker_task_pkt_get_msgid(struct qr_task *task);
+void worker_task_pkt_set_msgid(struct qr_task *task, uint16_t msgid);
+uint64_t worker_task_creation_time(struct qr_task *task);
+void worker_task_subreq_finalize(struct qr_task *task);
+bool worker_task_finished(struct qr_task *task);
+
+/** @cond internal */
+
+/** Number of request within timeout window. */
+#define MAX_PENDING KR_NSREP_MAXADDR
+
+/** Maximum response time from TCP upstream, milliseconds */
+#define MAX_TCP_INACTIVITY (KR_RESOLVE_TIME_LIMIT + KR_CONN_RTT_MAX)
+
+#ifndef RECVMMSG_BATCH /* see check_bufsize() */
+#define RECVMMSG_BATCH 1
+#endif
+
+/** Freelist of available mempools. */
+typedef array_t(struct mempool *) mp_freelist_t;
+
+/** List of query resolution tasks. */
+typedef array_t(struct qr_task *) qr_tasklist_t;
+
+/** \details Worker state is meant to persist during the whole life of daemon. */
+struct worker_ctx {
+ struct engine *engine;
+ uv_loop_t *loop;
+ int id;
+ int count;
+ int vars_table_ref;
+ unsigned tcp_pipeline_max;
+
+ /** Addresses to bind for outgoing connections or AF_UNSPEC. */
+ struct sockaddr_in out_addr4;
+ struct sockaddr_in6 out_addr6;
+
+ uint8_t wire_buf[RECVMMSG_BATCH * KNOT_WIRE_MAX_PKTSIZE];
+
+ struct {
+ size_t concurrent;
+ size_t rconcurrent;
+ size_t udp;
+ size_t tcp;
+ size_t tls;
+ size_t ipv4;
+ size_t ipv6;
+ size_t queries;
+ size_t dropped;
+ size_t timeout;
+ } stats;
+
+ struct zone_import_ctx* z_import;
+ bool too_many_open;
+ size_t rconcurrent_highwatermark;
+ /** List of active outbound TCP sessions */
+ map_t tcp_connected;
+ /** List of outbound TCP sessions waiting to be accepted */
+ map_t tcp_waiting;
+ /** Subrequest leaders (struct qr_task*), indexed by qname+qtype+qclass. */
+ trie_t *subreq_out;
+ mp_freelist_t pool_mp;
+ knot_mm_t pkt_pool;
+ unsigned int next_request_uid;
+};
+
+/** @endcond */
+
diff --git a/daemon/zimport.c b/daemon/zimport.c
new file mode 100644
index 0000000..ede0dbf
--- /dev/null
+++ b/daemon/zimport.c
@@ -0,0 +1,818 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/* Module is intended to import resource records from file into resolver's cache.
+ * File supposed to be a standard DNS zone file
+ * which contains text representations of resource records.
+ * For now only root zone import is supported.
+ *
+ * Import process consists of two stages.
+ * 1) Zone file parsing.
+ * 2) Import of parsed entries into the cache.
+ *
+ * These stages are implemented as two separate functions
+ * (zi_zone_import and zi_zone_process) which runs sequentially with the
+ * pause between them. This is done because resolver is a single-threaded
+ * application, so it can't process user's requests during the whole import
+ * process. Separation into two stages allows to reduce the
+ * continuous time interval when resolver can't serve user requests.
+ * Since root zone isn't large it is imported as single
+ * chunk. If it would be considered as necessary, import stage can be
+ * split into shorter stages.
+ *
+ * zi_zone_import() uses libzscanner to parse zone file.
+ * Parsed records are stored to internal storage from where they are imported to
+ * cache during the second stage.
+ *
+ * zi_zone_process() imports parsed resource records to cache.
+ * It imports rrset by creating request that will never be sent to upstream.
+ * After request creation resolver creates pseudo-answer which must contain
+ * all necessary data for validation. Then resolver process answer as if he had
+ * been received from network.
+ */
+
+#include <inttypes.h> /* PRIu64 */
+#include <stdlib.h>
+#include <uv.h>
+#include <ucw/mempool.h>
+#include <libknot/rrset.h>
+#include <libzscanner/scanner.h>
+
+#include "lib/utils.h"
+#include "lib/dnssec/ta.h"
+#include "daemon/worker.h"
+#include "daemon/zimport.h"
+#include "lib/generic/map.h"
+#include "lib/generic/array.h"
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "zimport", __VA_ARGS__)
+
+/* Pause between parse and import stages, milliseconds.
+ * See comment in zi_zone_import() */
+#define ZONE_IMPORT_PAUSE 100
+
+typedef array_t(knot_rrset_t *) qr_rrsetlist_t;
+
+struct zone_import_ctx {
+ struct worker_ctx *worker;
+ bool started;
+ knot_dname_t *origin;
+ knot_rrset_t *ta;
+ knot_rrset_t *key;
+ uint64_t start_timestamp;
+ size_t rrset_idx;
+ uv_timer_t timer;
+ map_t rrset_indexed;
+ qr_rrsetlist_t rrset_sorted;
+ knot_mm_t pool;
+ zi_callback cb;
+ void *cb_param;
+};
+
+typedef struct zone_import_ctx zone_import_ctx_t;
+
+static int RRSET_IS_ALREADY_IMPORTED = 1;
+
+/** @internal Allocate zone import context.
+ * @return pointer to zone import context or NULL. */
+static zone_import_ctx_t *zi_ctx_alloc()
+{
+ return (zone_import_ctx_t *)malloc(sizeof(zone_import_ctx_t));
+}
+
+/** @internal Free zone import context. */
+static void zi_ctx_free(zone_import_ctx_t *z_import)
+{
+ if (z_import != NULL) {
+ free(z_import);
+ }
+}
+
+/** @internal Reset all fields in the zone import context to their default values.
+ * Flushes memory pool, but doesn't reallocate memory pool buffer.
+ * Doesn't affect timer handle, pointers to callback and callback parameter.
+ * @return 0 if success; -1 if failed. */
+static int zi_reset(struct zone_import_ctx *z_import, size_t rrset_sorted_list_size)
+{
+ mp_flush(z_import->pool.ctx);
+
+ z_import->started = false;
+ z_import->start_timestamp = 0;
+ z_import->rrset_idx = 0;
+ z_import->pool.alloc = (knot_mm_alloc_t) mp_alloc;
+ z_import->rrset_indexed = map_make(&z_import->pool);
+
+ array_init(z_import->rrset_sorted);
+
+ int ret = 0;
+ if (rrset_sorted_list_size) {
+ ret = array_reserve_mm(z_import->rrset_sorted, rrset_sorted_list_size,
+ kr_memreserve, &z_import->pool);
+ }
+
+ return ret;
+}
+
+/** @internal Close callback for timer handle.
+ * @note Actually frees zone import context. */
+static void on_timer_close(uv_handle_t *handle)
+{
+ zone_import_ctx_t *z_import = (zone_import_ctx_t *)handle->data;
+ if (z_import != NULL) {
+ zi_ctx_free(z_import);
+ }
+}
+
+zone_import_ctx_t *zi_allocate(struct worker_ctx *worker,
+ zi_callback cb, void *param)
+{
+ if (worker->loop == NULL) {
+ return NULL;
+ }
+ zone_import_ctx_t *z_import = zi_ctx_alloc();
+ if (!z_import) {
+ return NULL;
+ }
+ void *mp = mp_new (8192);
+ if (!mp) {
+ zi_ctx_free(z_import);
+ return NULL;
+ }
+ memset(z_import, 0, sizeof(*z_import));
+ z_import->pool.ctx = mp;
+ z_import->worker = worker;
+ int ret = zi_reset(z_import, 0);
+ if (ret < 0) {
+ mp_delete(mp);
+ zi_ctx_free(z_import);
+ return NULL;
+ }
+ uv_timer_init(z_import->worker->loop, &z_import->timer);
+ z_import->timer.data = z_import;
+ z_import->cb = cb;
+ z_import->cb_param = param;
+ return z_import;
+}
+
+void zi_free(zone_import_ctx_t *z_import)
+{
+ z_import->started = false;
+ z_import->start_timestamp = 0;
+ z_import->rrset_idx = 0;
+ mp_delete(z_import->pool.ctx);
+ z_import->pool.ctx = NULL;
+ z_import->pool.alloc = NULL;
+ z_import->worker = NULL;
+ z_import->cb = NULL;
+ z_import->cb_param = NULL;
+ uv_close((uv_handle_t *)&z_import->timer, on_timer_close);
+}
+
+/** @internal Mark rrset that has been already imported
+ * to avoid repeated import. */
+static inline void zi_rrset_mark_as_imported(knot_rrset_t *rr)
+{
+ rr->additional = (void *)&RRSET_IS_ALREADY_IMPORTED;
+}
+
+/** @internal Check if rrset is marked as "already imported".
+ * @return true if marked, false if isn't */
+static inline bool zi_rrset_is_marked_as_imported(knot_rrset_t *rr)
+{
+ return (rr->additional == &RRSET_IS_ALREADY_IMPORTED);
+}
+
+/** @internal Try to find rrset with given requisites amongst parsed rrsets
+ * and put it to given packet. If there is RRSIG which covers that rrset, it
+ * will be added as well. If rrset found and successfully put, it marked as
+ * "already imported" to avoid repeated import. The same is true for RRSIG.
+ * @return -1 if failed
+ * 0 if required record been actually put into the packet
+ * 1 if required record could not be found */
+static int zi_rrset_find_put(struct zone_import_ctx *z_import,
+ knot_pkt_t *pkt, const knot_dname_t *owner,
+ uint16_t class, uint16_t type, uint16_t additional)
+{
+ if (type != KNOT_RRTYPE_RRSIG) {
+ /* If required rrset isn't rrsig, these must be the same values */
+ additional = type;
+ }
+
+ char key[KR_RRKEY_LEN];
+ int err = kr_rrkey(key, class, owner, type, additional);
+ if (err <= 0) {
+ return -1;
+ }
+ knot_rrset_t *rr = map_get(&z_import->rrset_indexed, key);
+ if (!rr) {
+ return 1;
+ }
+ err = knot_pkt_put(pkt, 0, rr, 0);
+ if (err != KNOT_EOK) {
+ return -1;
+ }
+ zi_rrset_mark_as_imported(rr);
+
+ if (type != KNOT_RRTYPE_RRSIG) {
+ /* Try to find corresponding rrsig */
+ err = zi_rrset_find_put(z_import, pkt, owner,
+ class, KNOT_RRTYPE_RRSIG, type);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+/** @internal Try to put given rrset to the given packet.
+ * If there is RRSIG which covers that rrset, it will be added as well.
+ * If rrset successfully put in the packet, it marked as
+ * "already imported" to avoid repeated import.
+ * The same is true for RRSIG.
+ * @return -1 if failed
+ * 0 if required record been actually put into the packet */
+static int zi_rrset_put(struct zone_import_ctx *z_import, knot_pkt_t *pkt,
+ knot_rrset_t *rr)
+{
+ assert(rr);
+ assert(rr->type != KNOT_RRTYPE_RRSIG);
+ int err = knot_pkt_put(pkt, 0, rr, 0);
+ if (err != KNOT_EOK) {
+ return -1;
+ }
+ zi_rrset_mark_as_imported(rr);
+ /* Try to find corresponding RRSIG */
+ err = zi_rrset_find_put(z_import, pkt, rr->owner, rr->rclass,
+ KNOT_RRTYPE_RRSIG, rr->type);
+ return (err < 0) ? err : 0;
+}
+
+/** @internal Try to put DS & NSEC* for rset->owner to given packet.
+ * @return -1 if failed;
+ * 0 if no errors occurred (it doesn't mean
+ * that records were actually added). */
+static int zi_put_delegation(zone_import_ctx_t *z_import, knot_pkt_t *pkt,
+ knot_rrset_t *rr)
+{
+ int err = zi_rrset_find_put(z_import, pkt, rr->owner,
+ rr->rclass, KNOT_RRTYPE_DS, 0);
+ if (err == 1) {
+ /* DS not found, maybe there are NSEC* */
+ err = zi_rrset_find_put(z_import, pkt, rr->owner,
+ rr->rclass, KNOT_RRTYPE_NSEC, 0);
+ if (err >= 0) {
+ err = zi_rrset_find_put(z_import, pkt, rr->owner,
+ rr->rclass, KNOT_RRTYPE_NSEC3, 0);
+ }
+ }
+ return err < 0 ? err : 0;
+}
+
+/** @internal Try to put A & AAAA records for rset->owner to given packet.
+ * @return -1 if failed;
+ * 0 if no errors occurred (it doesn't mean
+ * that records were actually added). */
+static int zi_put_glue(zone_import_ctx_t *z_import, knot_pkt_t *pkt,
+ knot_rrset_t *rr)
+{
+ int err = 0;
+ knot_rdata_t *rdata_i = rr->rrs.rdata;
+ for (uint16_t i = 0; i < rr->rrs.count;
+ ++i, rdata_i = knot_rdataset_next(rdata_i)) {
+ const knot_dname_t *ns_name = knot_ns_name(rdata_i);
+ err = zi_rrset_find_put(z_import, pkt, ns_name,
+ rr->rclass, KNOT_RRTYPE_A, 0);
+ if (err < 0) {
+ break;
+ }
+
+ err = zi_rrset_find_put(z_import, pkt, ns_name,
+ rr->rclass, KNOT_RRTYPE_AAAA, 0);
+ if (err < 0) {
+ break;
+ }
+ }
+ return err < 0 ? err : 0;
+}
+
+/** @internal Create query. */
+static knot_pkt_t *zi_query_create(zone_import_ctx_t *z_import, knot_rrset_t *rr)
+{
+ knot_mm_t *pool = &z_import->pool;
+
+ uint32_t msgid = kr_rand_bytes(2);
+
+ knot_pkt_t *query = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, pool);
+ if (!query) {
+ return NULL;
+ }
+
+ knot_pkt_put_question(query, rr->owner, rr->rclass, rr->type);
+ knot_pkt_begin(query, KNOT_ANSWER);
+ knot_wire_set_rd(query->wire);
+ knot_wire_set_id(query->wire, msgid);
+ int err = knot_pkt_parse(query, 0);
+ if (err != KNOT_EOK) {
+ knot_pkt_free(query);
+ return NULL;
+ }
+
+ return query;
+}
+
+/** @internal Import given rrset to cache.
+ * @return -1 if failed; 0 if success */
+static int zi_rrset_import(zone_import_ctx_t *z_import, knot_rrset_t *rr)
+{
+ struct worker_ctx *worker = z_import->worker;
+
+ assert(worker);
+
+ /* Create "pseudo query" which asks for given rrset. */
+ knot_pkt_t *query = zi_query_create(z_import, rr);
+ if (!query) {
+ return -1;
+ }
+
+ knot_mm_t *pool = &z_import->pool;
+ uint8_t *dname = rr->owner;
+ uint16_t rrtype = rr->type;
+ uint16_t rrclass = rr->rclass;
+
+ /* Create "pseudo answer". */
+ knot_pkt_t *answer = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, pool);
+ if (!answer) {
+ knot_pkt_free(query);
+ return -1;
+ }
+ knot_pkt_put_question(answer, dname, rrclass, rrtype);
+ knot_pkt_begin(answer, KNOT_ANSWER);
+
+ struct kr_qflags options;
+ memset(&options, 0, sizeof(options));
+ options.DNSSEC_WANT = true;
+ options.NO_MINIMIZE = true;
+
+ /* This call creates internal structures which necessary for
+ * resolving - qr_task & request_ctx. */
+ struct qr_task *task = worker_resolve_start(worker, query, options);
+ if (!task) {
+ knot_pkt_free(query);
+ knot_pkt_free(answer);
+ return -1;
+ }
+
+ /* Push query to the request resolve plan.
+ * Actually query will never been sent to upstream. */
+ struct kr_request *request = worker_task_request(task);
+ struct kr_rplan *rplan = &request->rplan;
+ struct kr_query *qry = kr_rplan_push(rplan, NULL, dname, rrclass, rrtype);
+ int state = KR_STATE_FAIL;
+ bool origin_is_owner = knot_dname_is_equal(rr->owner, z_import->origin);
+ bool is_referral = (rrtype == KNOT_RRTYPE_NS && !origin_is_owner);
+ uint32_t msgid = knot_wire_get_id(query->wire);
+
+ qry->id = msgid;
+
+ /* Prepare zonecut. It must have all the necessary requisites for
+ * successful validation - matched zone name & keys & trust-anchors. */
+ kr_zonecut_init(&qry->zone_cut, z_import->origin, pool);
+ qry->zone_cut.key = z_import->key;
+ qry->zone_cut.trust_anchor = z_import->ta;
+
+ if (knot_pkt_init_response(request->answer, query) != 0) {
+ goto cleanup;
+ }
+
+ /* Since "pseudo" query asks for NS for subzone,
+ * "pseudo" answer must simulate referral. */
+ if (is_referral) {
+ knot_pkt_begin(answer, KNOT_AUTHORITY);
+ }
+
+ /* Put target rrset to ANSWER\AUTHORIRY as well as corresponding RRSIG */
+ int err = zi_rrset_put(z_import, answer, rr);
+ if (err != 0) {
+ goto cleanup;
+ }
+
+ if (!is_referral) {
+ knot_wire_set_aa(answer->wire);
+ } else {
+ /* Type is KNOT_RRTYPE_NS and owner is not equal to origin.
+ * It will be "referral" answer and must contain delegation. */
+ err = zi_put_delegation(z_import, answer, rr);
+ if (err < 0) {
+ goto cleanup;
+ }
+ }
+
+ knot_pkt_begin(answer, KNOT_ADDITIONAL);
+
+ if (rrtype == KNOT_RRTYPE_NS) {
+ /* Try to find glue addresses. */
+ err = zi_put_glue(z_import, answer, rr);
+ if (err < 0) {
+ goto cleanup;
+ }
+ }
+
+ knot_wire_set_id(answer->wire, msgid);
+ answer->parsed = answer->size;
+ err = knot_pkt_parse(answer, 0);
+ if (err != KNOT_EOK) {
+ goto cleanup;
+ }
+
+ /* Importing doesn't imply communication with upstream at all.
+ * "answer" contains pseudo-answer from upstream and must be successfully
+ * validated in CONSUME stage. If not, something gone wrong. */
+ state = kr_resolve_consume(request, NULL, answer);
+
+cleanup:
+
+ knot_pkt_free(query);
+ knot_pkt_free(answer);
+ worker_task_finalize(task, state);
+ return state == (is_referral ? KR_STATE_PRODUCE : KR_STATE_DONE) ? 0 : -1;
+}
+
+/** @internal Create element in qr_rrsetlist_t rrset_list for
+ * given node of map_t rrset_sorted. */
+static int zi_mapwalk_preprocess(const char *k, void *v, void *baton)
+{
+ zone_import_ctx_t *z_import = (zone_import_ctx_t *)baton;
+
+ int ret = array_push_mm(z_import->rrset_sorted, v, kr_memreserve, &z_import->pool);
+
+ return (ret < 0);
+}
+
+/** @internal Iterate over parsed rrsets and try to import each of them. */
+static void zi_zone_process(uv_timer_t* handle)
+{
+ zone_import_ctx_t *z_import = (zone_import_ctx_t *)handle->data;
+
+ assert(z_import->worker);
+
+ size_t failed = 0;
+ size_t ns_imported = 0;
+ size_t other_imported = 0;
+
+ /* At the moment import of root zone only is supported.
+ * Check the name of the parsed zone.
+ * TODO - implement importing of arbitrary zone. */
+ KR_DNAME_GET_STR(zone_name_str, z_import->origin);
+
+ if (strcmp(".", zone_name_str) != 0) {
+ kr_log_error("[zimport] unexpected zone name `%s` (root zone expected), fail\n",
+ zone_name_str);
+ failed = 1;
+ goto finish;
+ }
+
+ if (z_import->rrset_sorted.len <= 0) {
+ VERBOSE_MSG(NULL, "zone is empty\n");
+ goto finish;
+ }
+
+ /* TA have been found, zone is secured.
+ * DNSKEY must be somewhere amongst the imported records. Find it.
+ * TODO - For those zones that provenly do not have TA this step must be skipped. */
+ char key[KR_RRKEY_LEN];
+ int err = kr_rrkey(key, KNOT_CLASS_IN, z_import->origin,
+ KNOT_RRTYPE_DNSKEY, KNOT_RRTYPE_DNSKEY);
+ if (err <= 0) {
+ failed = 1;
+ goto finish;
+ }
+
+ knot_rrset_t *rr_key = map_get(&z_import->rrset_indexed, key);
+ if (!rr_key) {
+ /* DNSKEY MUST be here. If not found - fail. */
+ kr_log_error("[zimport] DNSKEY not found for `%s`, fail\n", zone_name_str);
+ failed = 1;
+ goto finish;
+ }
+ z_import->key = rr_key;
+
+ VERBOSE_MSG(NULL, "started: zone: '%s'\n", zone_name_str);
+
+ z_import->start_timestamp = kr_now();
+
+ /* Import DNSKEY at first step. If any validation problems will appear,
+ * cancel import of whole zone. */
+ KR_DNAME_GET_STR(kname_str, rr_key->owner);
+ KR_RRTYPE_GET_STR(ktype_str, rr_key->type);
+
+ VERBOSE_MSG(NULL, "importing: name: '%s' type: '%s'\n",
+ kname_str, ktype_str);
+
+ int res = zi_rrset_import(z_import, rr_key);
+ if (res != 0) {
+ VERBOSE_MSG(NULL, "import failed: qname: '%s' type: '%s'\n",
+ kname_str, ktype_str);
+ failed = 1;
+ goto finish;
+ }
+
+ /* Import all NS records */
+ for (size_t i = 0; i < z_import->rrset_sorted.len; ++i) {
+ knot_rrset_t *rr = z_import->rrset_sorted.at[i];
+
+ if (rr->type != KNOT_RRTYPE_NS) {
+ continue;
+ }
+
+ KR_DNAME_GET_STR(name_str, rr->owner);
+ KR_RRTYPE_GET_STR(type_str, rr->type);
+ VERBOSE_MSG(NULL, "importing: name: '%s' type: '%s'\n",
+ name_str, type_str);
+ int ret = zi_rrset_import(z_import, rr);
+ if (ret == 0) {
+ ++ns_imported;
+ } else {
+ VERBOSE_MSG(NULL, "import failed: name: '%s' type: '%s'\n",
+ name_str, type_str);
+ ++failed;
+ }
+ z_import->rrset_sorted.at[i] = NULL;
+ }
+
+ /* NS records have been imported as well as relative DS, NSEC* and glue.
+ * Now import what's left. */
+ for (size_t i = 0; i < z_import->rrset_sorted.len; ++i) {
+
+ knot_rrset_t *rr = z_import->rrset_sorted.at[i];
+ if (rr == NULL) {
+ continue;
+ }
+
+ if (zi_rrset_is_marked_as_imported(rr)) {
+ continue;
+ }
+
+ if (rr->type == KNOT_RRTYPE_DNSKEY || rr->type == KNOT_RRTYPE_RRSIG) {
+ continue;
+ }
+
+ KR_DNAME_GET_STR(name_str, rr->owner);
+ KR_RRTYPE_GET_STR(type_str, rr->type);
+ VERBOSE_MSG(NULL, "importing: name: '%s' type: '%s'\n",
+ name_str, type_str);
+ res = zi_rrset_import(z_import, rr);
+ if (res == 0) {
+ ++other_imported;
+ } else {
+ VERBOSE_MSG(NULL, "import failed: name: '%s' type: '%s'\n",
+ name_str, type_str);
+ ++failed;
+ }
+ }
+
+ uint64_t elapsed = kr_now() - z_import->start_timestamp;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+
+ VERBOSE_MSG(NULL, "finished in %"PRIu64" ms; zone: `%s`; ns: %zd"
+ "; other: %zd; failed: %zd\n",
+ elapsed, zone_name_str, ns_imported, other_imported, failed);
+
+finish:
+
+ uv_timer_stop(&z_import->timer);
+ z_import->started = false;
+
+ int import_state = 0;
+
+ if (failed != 0) {
+ if (ns_imported == 0 && other_imported == 0) {
+ import_state = -1;
+ VERBOSE_MSG(NULL, "import failed; zone `%s` \n", zone_name_str);
+ } else {
+ import_state = 1;
+ }
+ } else {
+ import_state = 0;
+ }
+
+ if (z_import->cb != NULL) {
+ z_import->cb(import_state, z_import->cb_param);
+ }
+}
+
+/** @internal Store rrset that has been imported to zone import context memory pool.
+ * @return -1 if failed; 0 if success. */
+static int zi_record_store(zs_scanner_t *s)
+{
+ if (s->r_data_length > UINT16_MAX) {
+ /* Due to knot_rrset_add_rdata(..., const uint16_t size, ...); */
+ kr_log_error("[zscanner] line %"PRIu64": rdata is too long\n",
+ s->line_counter);
+ return -1;
+ }
+
+ if (knot_dname_size(s->r_owner) != strlen((const char *)(s->r_owner)) + 1) {
+ kr_log_error("[zscanner] line %"PRIu64
+ ": owner name contains zero byte, skip\n",
+ s->line_counter);
+ return 0;
+ }
+
+ zone_import_ctx_t *z_import = (zone_import_ctx_t *)s->process.data;
+
+ knot_rrset_t *new_rr = knot_rrset_new(s->r_owner, s->r_type, s->r_class,
+ s->r_ttl, &z_import->pool);
+ if (!new_rr) {
+ kr_log_error("[zscanner] line %"PRIu64": error creating rrset\n",
+ s->line_counter);
+ return -1;
+ }
+ int res = knot_rrset_add_rdata(new_rr, s->r_data, s->r_data_length,
+ &z_import->pool);
+ if (res != KNOT_EOK) {
+ kr_log_error("[zscanner] line %"PRIu64": error adding rdata to rrset\n",
+ s->line_counter);
+ return -1;
+ }
+
+ /* Records in zone file may not be grouped by name and RR type.
+ * Use map to create search key and
+ * avoid ineffective searches across all the imported records. */
+ char key[KR_RRKEY_LEN];
+ uint16_t additional_key_field = kr_rrset_type_maysig(new_rr);
+
+ res = kr_rrkey(key, new_rr->rclass, new_rr->owner, new_rr->type,
+ additional_key_field);
+ if (res <= 0) {
+ kr_log_error("[zscanner] line %"PRIu64": error constructing rrkey\n",
+ s->line_counter);
+ return -1;
+ }
+
+ knot_rrset_t *saved_rr = map_get(&z_import->rrset_indexed, key);
+ if (saved_rr) {
+ res = knot_rdataset_merge(&saved_rr->rrs, &new_rr->rrs,
+ &z_import->pool);
+ } else {
+ res = map_set(&z_import->rrset_indexed, key, new_rr);
+ }
+ if (res != 0) {
+ kr_log_error("[zscanner] line %"PRIu64": error saving parsed rrset\n",
+ s->line_counter);
+ return -1;
+ }
+
+ return 0;
+}
+
+/** @internal zscanner callback. */
+static int zi_state_parsing(zs_scanner_t *s)
+{
+ while (zs_parse_record(s) == 0) {
+ switch (s->state) {
+ case ZS_STATE_DATA:
+ if (zi_record_store(s) != 0) {
+ return -1;
+ }
+ zone_import_ctx_t *z_import = (zone_import_ctx_t *) s->process.data;
+ if (z_import->origin == 0) {
+ z_import->origin = knot_dname_copy(s->zone_origin,
+ &z_import->pool);
+ } else if (!knot_dname_is_equal(z_import->origin, s->zone_origin)) {
+ kr_log_error("[zscanner] line: %"PRIu64
+ ": zone origin changed unexpectedly\n",
+ s->line_counter);
+ return -1;
+ }
+ break;
+ case ZS_STATE_ERROR:
+ kr_log_error("[zscanner] line: %"PRIu64
+ ": parse error; code: %i ('%s')\n",
+ s->line_counter, s->error.code,
+ zs_strerror(s->error.code));
+ return -1;
+ case ZS_STATE_INCLUDE:
+ kr_log_error("[zscanner] line: %"PRIu64
+ ": INCLUDE is not supported\n",
+ s->line_counter);
+ return -1;
+ case ZS_STATE_EOF:
+ case ZS_STATE_STOP:
+ return (s->error.counter == 0) ? 0 : -1;
+ default:
+ kr_log_error("[zscanner] line: %"PRIu64
+ ": unexpected parse state: %i\n",
+ s->line_counter, s->state);
+ return -1;
+ }
+ }
+
+ return -1;
+}
+
+int zi_zone_import(struct zone_import_ctx *z_import,
+ const char *zone_file, const char *origin,
+ uint16_t rclass, uint32_t ttl)
+{
+ assert (z_import != NULL && "[zimport] empty <z_import> parameter");
+ assert (z_import->worker != NULL && "[zimport] invalid <z_import> parameter\n");
+ assert (zone_file != NULL && "[zimport] empty <zone_file> parameter\n");
+
+ zs_scanner_t *s = malloc(sizeof(zs_scanner_t));
+ if (s == NULL) {
+ kr_log_error("[zscanner] error creating instance of zone scanner (malloc() fails)\n");
+ return -1;
+ }
+
+ /* zs_init(), zs_set_input_file(), zs_set_processing() returns -1 in case of error,
+ * so don't print error code as it meaningless. */
+ int res = zs_init(s, origin, rclass, ttl);
+ if (res != 0) {
+ kr_log_error("[zscanner] error initializing zone scanner instance, error: %i (%s)\n",
+ s->error.code, zs_strerror(s->error.code));
+ free(s);
+ return -1;
+ }
+
+ res = zs_set_input_file(s, zone_file);
+ if (res != 0) {
+ kr_log_error("[zscanner] error opening zone file `%s`, error: %i (%s)\n",
+ zone_file, s->error.code, zs_strerror(s->error.code));
+ zs_deinit(s);
+ free(s);
+ return -1;
+ }
+
+ /* Don't set processing and error callbacks as we don't use automatic parsing.
+ * Parsing as well error processing will be performed in zi_state_parsing().
+ * Store pointer to zone import context for further use. */
+ if (zs_set_processing(s, NULL, NULL, (void *)z_import) != 0) {
+ kr_log_error("[zscanner] zs_set_processing() failed for zone file `%s`, "
+ "error: %i (%s)\n",
+ zone_file, s->error.code, zs_strerror(s->error.code));
+ zs_deinit(s);
+ free(s);
+ return -1;
+ }
+
+ uint64_t elapsed = 0;
+ int ret = zi_reset(z_import, 4096);
+ if (ret == 0) {
+ z_import->started = true;
+ z_import->start_timestamp = kr_now();
+ VERBOSE_MSG(NULL, "[zscanner] started; zone file `%s`\n",
+ zone_file);
+ ret = zi_state_parsing(s);
+ /* Try to find TA for worker->z_import.origin. */
+ map_t *trust_anchors = &z_import->worker->engine->resolver.trust_anchors;
+ knot_rrset_t *rr = kr_ta_get(trust_anchors, z_import->origin);
+ if (rr) {
+ z_import->ta = rr;
+ } else {
+ /* For now - fail.
+ * TODO - query DS and continue after answer had been obtained. */
+ KR_DNAME_GET_STR(zone_name_str, z_import->origin);
+ kr_log_error("[zimport] no TA found for `%s`, fail\n", zone_name_str);
+ ret = 1;
+ }
+ elapsed = kr_now() - z_import->start_timestamp;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+ }
+ zs_deinit(s);
+ free(s);
+
+ if (ret != 0) {
+ kr_log_error("[zscanner] error parsing zone file `%s`\n", zone_file);
+ z_import->started = false;
+ return ret;
+ }
+
+ VERBOSE_MSG(NULL, "[zscanner] finished in %"PRIu64" ms; zone file `%s`\n",
+ elapsed, zone_file);
+ map_walk(&z_import->rrset_indexed, zi_mapwalk_preprocess, z_import);
+
+ /* Zone have been parsed already, so start the import. */
+ uv_timer_start(&z_import->timer, zi_zone_process,
+ ZONE_IMPORT_PAUSE, ZONE_IMPORT_PAUSE);
+
+ return 0;
+}
+
+bool zi_import_started(struct zone_import_ctx *z_import)
+{
+ return z_import ? z_import->started : false;
+}
diff --git a/daemon/zimport.h b/daemon/zimport.h
new file mode 100644
index 0000000..57b246e
--- /dev/null
+++ b/daemon/zimport.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+struct worker_ctx;
+/** Zone import context (opaque). */
+struct zone_import_ctx;
+
+/**
+ * Completion callback
+ *
+ * @param state -1 - fail
+ * 0 - success
+ * 1 - success, but there are non-critical errors
+ * @param pointer to user data
+ */
+typedef void (*zi_callback)(int state, void *param);
+
+/**
+ * Allocate and initialize zone import context.
+ *
+ * @param worker pointer to worker state
+ * @return NULL or pointer to zone import context.
+ */
+struct zone_import_ctx *zi_allocate(struct worker_ctx *worker,
+ zi_callback cb, void *param);
+
+/** Free zone import context. */
+void zi_free(struct zone_import_ctx *z_import);
+
+/**
+ * Import zone from file.
+ *
+ * @note only root zone import is supported; origin must be NULL or "."
+ * @param z_import pointer to zone import context
+ * @param zone_file zone file name
+ * @param origin default origin
+ * @param rclass default class
+ * @param ttl default ttl
+ * @return 0 or an error code
+ */
+int zi_zone_import(struct zone_import_ctx *z_import,
+ const char *zone_file, const char *origin,
+ uint16_t rclass, uint32_t ttl);
+
+/**
+ * Check if import already in process.
+ *
+ * @param z_import pointer to zone import context.
+ * @return true if import already in process; false otherwise.
+ */
+bool zi_import_started(struct zone_import_ctx *z_import);
diff --git a/distro/arch/PKGBUILD b/distro/arch/PKGBUILD
new file mode 100644
index 0000000..87f8aa7
--- /dev/null
+++ b/distro/arch/PKGBUILD
@@ -0,0 +1,56 @@
+# Maintainer: Tomas Krizek <tomas.krizek@mailbox.org>
+# Contributor: Ondřej Surý <ondrej@sury.org>
+
+pkgname=knot-resolver
+pkgver=__VERSION__
+pkgrel=1
+pkgdesc='full caching DNS resolver implementation'
+url='https://www.knot-resolver.cz/'
+arch=('x86_64' 'armv7h')
+license=('GPL3')
+backup=('etc/knot-resolver/kresd.conf')
+options=(debug strip)
+install=install
+depends=('cmocka'
+ 'dnssec-anchors'
+ 'gnutls'
+ 'knot>=2.7.2'
+ 'libedit'
+ 'libsystemd'
+ 'libuv'
+ 'lmdb'
+ 'lua51-sec'
+ 'lua51-socket'
+ 'luajit')
+source=("knot-resolver_${pkgver}.orig.tar.xz")
+
+_makevars="PREFIX=/usr SBINDIR=/usr/bin LIBDIR=/usr/lib INCLUDEDIR=/usr/include ETCDIR=/etc/knot-resolver KEYFILE_DEFAULT=/etc/trusted-key.key V=1"
+
+sha256sums=('SKIP')
+
+build() {
+ cd "${srcdir}/${pkgname}-${pkgver}"
+ make ${_makevars}
+}
+
+check() {
+ cd "${srcdir}/${pkgname}-${pkgver}"
+ make check-unit ${_makevars}
+}
+
+package() {
+ cd "${srcdir}/${pkgname}-${pkgver}"
+
+ make ${_makevars} DESTDIR="${pkgdir}" install
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd.socket" "${pkgdir}/usr/lib/systemd/system/kresd.socket"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd-control@.socket" "${pkgdir}/usr/lib/systemd/system/kresd-control@.socket"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd-tls.socket" "${pkgdir}/usr/lib/systemd/system/kresd-tls.socket"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd@.service" "${pkgdir}/usr/lib/systemd/system/kresd@.service"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd.target" "${pkgdir}/usr/lib/systemd/system/kresd.target"
+ install -dm 0755 "${pkgdir}/usr/lib/systemd/system/multi-user.target.wants"
+ ln -s ../kresd.target "${pkgdir}/usr/lib/systemd/system/multi-user.target.wants/kresd.target"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/systemd/kresd.systemd.7" "${pkgdir}/usr/share/man/man7/kresd.systemd.7"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/tmpfiles/knot-resolver.conf" "${pkgdir}/usr/lib/tmpfiles.d/knot-resolver.conf"
+ install -dm 0775 "${pkgdir}/etc/knot-resolver"
+ install -Dm 0644 "${srcdir}/${pkgname}-${pkgver}/distro/common/kresd.no_ta.conf" "${pkgdir}/etc/knot-resolver/kresd.conf"
+}
diff --git a/distro/arch/install b/distro/arch/install
new file mode 100644
index 0000000..de23d59
--- /dev/null
+++ b/distro/arch/install
@@ -0,0 +1,15 @@
+post_install() {
+ getent group knot-resolver &>/dev/null || groupadd -r knot-resolver >/dev/null
+ getent passwd knot-resolver &>/dev/null || useradd -r -g knot-resolver -d /dev/null -s /bin/false -c knot-resolver knot-resolver >/dev/null
+ chown -R root:knot-resolver /etc/knot-resolver
+}
+
+post_upgrade() {
+ chown -R root:knot-resolver /etc/knot-resolver
+}
+
+post_remove() {
+ getent passwd knot-resolver &>/dev/null && userdel knot-resolver >/dev/null
+ getent group knot-resolver &>/dev/null && groupdel knot-resolver >/dev/null
+ true
+}
diff --git a/distro/common/kresd.conf b/distro/common/kresd.conf
new file mode 100644
index 0000000..a82a893
--- /dev/null
+++ b/distro/common/kresd.conf
@@ -0,0 +1,19 @@
+-- vim:syntax=lua:
+-- Refer to manual: http://knot-resolver.readthedocs.org/en/latest/daemon.html#configuration
+
+-- Load useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ 'predict', -- Prefetch expiring/frequent records
+}
+
+-- See kresd.systemd(7) about configuring network interfaces when using systemd
+-- Listen on localhost (default)
+-- net = { '127.0.0.1', '::1' }
+
+-- Enable DNSSEC validation
+trust_anchors.file = '/etc/knot-resolver/root.keys'
+
+-- Cache size
+cache.size = 100 * MB
diff --git a/distro/common/kresd.no_ta.conf b/distro/common/kresd.no_ta.conf
new file mode 100644
index 0000000..e452f0e
--- /dev/null
+++ b/distro/common/kresd.no_ta.conf
@@ -0,0 +1,19 @@
+-- vim:syntax=lua:
+-- Refer to manual: http://knot-resolver.readthedocs.org/en/latest/daemon.html#configuration
+
+-- Load useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ 'predict', -- Prefetch expiring/frequent records
+}
+
+-- See kresd.systemd(7) about configuring network interfaces when using systemd
+-- Listen on localhost (default)
+-- net = { '127.0.0.1', '::1' }
+
+-- To disable DNSSEC validation, uncomment the following line (not recommended)
+-- trust_anchors.keyfile_default = nil
+
+-- Cache size
+cache.size = 100 * MB
diff --git a/distro/common/root.keys b/distro/common/root.keys
new file mode 100644
index 0000000..7578e04
--- /dev/null
+++ b/distro/common/root.keys
@@ -0,0 +1,2 @@
+. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
+. IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
diff --git a/distro/common/systemd/README.md b/distro/common/systemd/README.md
new file mode 100644
index 0000000..433f92f
--- /dev/null
+++ b/distro/common/systemd/README.md
@@ -0,0 +1,31 @@
+Running Knot Resolver under systemd (or equivalent) socket activation
+=====================================================================
+
+You can use the files in this directory to run kresd under supervision
+by systemd (or any supervisor that provides equivalent file descriptor
+initialization via the interface supported by
+sd_listen_fds_with_names(3)).
+
+Usage and Configuration
+-----------------------
+
+See kresd.systemd(7) for details.
+
+Compatibility with older systemd
+--------------------------------
+
+If you're using systemd prior to version 227, use the systemd-compat.conf
+drop-in file to use manual activation. In this case, socket files shouldn't
+be packaged, because they won't be used.
+
+Notes
+-----
+
+* If you're using the upstream systemd unit files, don't forget to also include
+ kresd.systemd.7 manual page in the package.
+* Distributions using systemd-sysv-generator should mask kresd.service to
+ be consistent with other distributions. Any use of kresd.service instead of
+ kresd@N.service is discouraged to avoid confusing the users.
+* kresd.target should be enabled by default by linking it to systemd lib/
+ directory. Instances of kresd@.service are then added manually to
+ kresd.target when the user enables them.
diff --git a/distro/common/systemd/drop-in/listen-tls.conf b/distro/common/systemd/drop-in/listen-tls.conf
new file mode 100644
index 0000000..6c798f0
--- /dev/null
+++ b/distro/common/systemd/drop-in/listen-tls.conf
@@ -0,0 +1,7 @@
+# /etc/systemd/system/kresd-tls.socket.d/override.conf
+
+# Configure which interfaces should kresd listen on.
+# ListenStream can be added multiple times.
+
+[Socket]
+ListenStream=192.0.2.115:853
diff --git a/distro/common/systemd/drop-in/listen-udp-tcp.conf b/distro/common/systemd/drop-in/listen-udp-tcp.conf
new file mode 100644
index 0000000..480767a
--- /dev/null
+++ b/distro/common/systemd/drop-in/listen-udp-tcp.conf
@@ -0,0 +1,8 @@
+# /etc/systemd/system/kresd.socket.d/override.conf
+
+# Configure which interfaces should kresd listen on.
+# ListenDatagram and ListenStream can be added multiple times.
+
+[Socket]
+ListenDatagram=192.0.2.115:53
+ListenStream=192.0.2.115:53
diff --git a/distro/common/systemd/drop-in/systemd-compat.conf b/distro/common/systemd/drop-in/systemd-compat.conf
new file mode 100644
index 0000000..d251c41
--- /dev/null
+++ b/distro/common/systemd/drop-in/systemd-compat.conf
@@ -0,0 +1,17 @@
+# /usr/lib/systemd/system/kresd@.service.d/override.conf
+
+# If systemd.227+ isn't available (e.g. CentOS 7), socket activation can't be used
+# and the following modifications are required to use the service with
+# manual activation.
+
+# CAP_NET_BIND_SERVICE is necessary to be able to bind to a well-known port
+# as an unprivilidged user.
+
+# Explicit --forks=1 turns off interactive mode.
+
+[Service]
+Type=simple
+AmbientCapabilities=CAP_NET_BIND_SERVICE
+ExecStart=
+ExecStart=/usr/sbin/kresd --config=/etc/knot-resolver/kresd.conf --forks=1
+Sockets=
diff --git a/distro/common/systemd/kresd-control@.socket b/distro/common/systemd/kresd-control@.socket
new file mode 100644
index 0000000..6937436
--- /dev/null
+++ b/distro/common/systemd/kresd-control@.socket
@@ -0,0 +1,16 @@
+[Unit]
+Description=Knot Resolver control socket
+Documentation=man:kresd.systemd(7)
+Documentation=man:kresd(8)
+Before=sockets.target
+PartOf=kresd@%i.service
+
+[Socket]
+Service=kresd@%i.service
+ListenStream=/run/knot-resolver/control@%i
+FileDescriptorName=control
+SocketMode=0660
+Slice=system-kresd.slice
+
+[Install]
+WantedBy=sockets.target
diff --git a/distro/common/systemd/kresd-tls.socket b/distro/common/systemd/kresd-tls.socket
new file mode 100644
index 0000000..ab16c81
--- /dev/null
+++ b/distro/common/systemd/kresd-tls.socket
@@ -0,0 +1,16 @@
+[Unit]
+Description=Knot Resolver TLS network listener
+Documentation=man:kresd.systemd(7)
+Documentation=man:kresd(8)
+Before=sockets.target
+
+[Socket]
+FreeBind=true
+FileDescriptorName=tls
+ListenStream=[::1]:853
+ListenStream=127.0.0.1:853
+Service=kresd@1.service
+Slice=system-kresd.slice
+
+[Install]
+WantedBy=sockets.target
diff --git a/distro/common/systemd/kresd.socket b/distro/common/systemd/kresd.socket
new file mode 100644
index 0000000..9dd9424
--- /dev/null
+++ b/distro/common/systemd/kresd.socket
@@ -0,0 +1,17 @@
+[Unit]
+Description=Knot Resolver network listeners
+Documentation=man:kresd.systemd(7)
+Documentation=man:kresd(8)
+Before=sockets.target
+
+[Socket]
+FreeBind=true
+ListenDatagram=[::1]:53
+ListenStream=[::1]:53
+ListenDatagram=127.0.0.1:53
+ListenStream=127.0.0.1:53
+Service=kresd@1.service
+Slice=system-kresd.slice
+
+[Install]
+WantedBy=sockets.target
diff --git a/distro/common/systemd/kresd.systemd.7 b/distro/common/systemd/kresd.systemd.7
new file mode 100644
index 0000000..420b110
--- /dev/null
+++ b/distro/common/systemd/kresd.systemd.7
@@ -0,0 +1,230 @@
+.TH "kresd.systemd" "7" "2018-06-04" "CZ.NIC" "Knot Resolver Systemd Units"
+.\"
+.\" kresd.systemd.7 -- man page for systemd units for kresd
+.\"
+.\" Copyright (c) 2018, CZ.NIC. All rights reserved.
+.\"
+.\" See COPYING for the license.
+.\"
+.\"
+.SH "NAME"
+kresd.systemd
+\- managing Knot Resolver through systemd.
+
+.SH "SYNOPSIS"
+.nf
+kresd@.service
+kresd.socket
+kresd-tls.socket
+kresd-control@.socket
+kresd.target
+system-kresd.slice
+.fi
+
+.SH "DESCRIPTION"
+.P
+This manual page describes how to manage \fBkresd\fR using \fBsystemd\fR
+units. Depending on your distribution, this can be either be done with
+socket-based activation or without it. The following assumes socket-based activation.
+For differences see \fINOTES\fR below.
+
+\fBkresd\fR daemon can be executed in multiple independent processes, which can be
+managed with \fBsystemd\fR via systemd templates (see \fBsystemd.unit\fR(5)).
+Each \fBsystemd\fR service instance of \fBkresd\fR (\fIkresd@.service\fR) represents a
+single, independent kresd process.
+
+The systemd-managed \fBkresd\fR service set is grouped in the
+\fIsystem-kresd.slice\fR slice. The slice includes one or more
+running daemons (instances of \fIkresd@.service\fR), public listening
+sockets (the same listening sockets are shared by all daemons) and a
+dedicated control socket for each running daemon.
+
+Each instance of \fIkresd@.service\fR has three systemd sockets (see
+\fBsystemd.socket(5)\fR) associated with it:
+
+.nf
+.RS
+\fIkresd.socket\fR - UDP/TCP network socket (default: localhost:53), shared with other instances
+\fIkresd-tls.socket\fR - network socket for DNS-over-TLS (default: localhost:853), shared with other instances
+\fIkresd-control@.socket\fR - UNIX socket with control terminal, dedicated
+.RE
+.fi
+
+.B Configuring network interfaces
+
+When using socket-based activation, the daemon requires neither root privileges
+nor any special capabilities, because the sockets are created by \fBsystemd\fR and
+passed to \fBkresd\fR. This means \fBkresd\fR can't bind to ports below 1024 when
+configured in \fI/etc/knot-resolver/kresd.conf\fR.
+
+To configure \fBkresd\fR to listen on public interfaces, drop-in files (see
+\fBsystemd.unit\fR(5)) should be used. These can be created with:
+
+.nf
+.RS 4n
+.B systemctl edit kresd.socket
+.B systemctl edit kresd-tls.socket
+.RE
+.fi
+
+For example, to configure \fBkresd\fR to listen on 192.0.2.115 on ports 53 and
+853, the drop-in files would look like:
+
+.nf
+.RS 4n
+# /etc/systemd/system/kresd.socket.d/override.conf
+[Socket]
+ListenDatagram=192.0.2.115:53
+ListenStream=192.0.2.115:53
+
+# /etc/systemd/system/kresd-tls.socket.d/override.conf
+[Socket]
+ListenStream=192.0.2.115:853
+.RE
+.fi
+
+For more detailed socket configuration, see \fBsystemd.socket\fR(5).
+
+.B Concurrent daemons
+
+If you have more than one CPU core available, a single running
+\fBkresd\fR daemon will only be able to make use of one core at a
+time, leaving the other cores idle. If you want \fBkresd\fR to take
+advantage of all available cores, while sharing both cache and public
+listening ports, you should enable and start as many instances of the
+\fBkresd@.service\fR as you have cores. Typically, each instance is
+just named \fIkresd@\fBN\fI.service\fR, where \fIN\fR is a decimal
+number. To enable 3 concurrent daemons:
+
+.nf
+.RS 4n
+.B systemctl enable --now kresd@1.service kresd@2.service kresd@3.service
+.RE
+.fi
+
+.B Using system-kresd.slice and kresd.target
+
+The following commands may not work with older systemd (e.g. on CentOS 7).
+See notes for more info.
+
+The easiest way to view the status of systemd-supervised \fBkresd\fR
+instances is to use the \fIsystem-kresd.slice\fR:
+
+.nf
+.RS 4n
+.B systemctl status system-kresd.slice
+.RE
+.fi
+
+You can also use the slice to restart all sockets as well as daemons:
+
+.nf
+.RS 4n
+.B systemctl restart system-kresd.slice
+.RE
+.fi
+
+Or you can use it to stop kresd altogether (e.g. during package removal):
+
+.nf
+.RS 4n
+.B systemctl stop system-kresd.slice
+.RE
+.fi
+
+To start all enabled kresd daemons, use the provided \fIkresd.target\fR:
+
+.nf
+.RS 4n
+.B systemctl start kresd.target
+.RE
+.fi
+
+.SH "NOTES"
+
+.IP * 2
+When an instance of \fIkresd@.service\fR is started, stopped or
+restarted, its associated control socket is also automatically
+started, stopped or restarted, but the public listening sockets remain
+open. As long as either of the public sockets are listening, at least
+\fIkresd@1.service\fR will be automatically activated when a request arrives.
+
+.IP * 2
+If your distribution doesn't use socket-based activation, you can configure the
+network interfaces for \fBkresd\fR in \fI/etc/knot-resolver/kresd.conf\fR. The
+service can be started or enabled in the same way as in the examples below, but
+it doesn't have any sockets associated with it.
+
+.IP * 2
+Controlling the service with \fIsystem-kresd.slice\fR requires newer systemd.
+It may not work in some distributions, notably CentOS 7. To control multiple
+kresd instances, use \fIkresd@*.service\fR or \fIBrace Expansion\fR mentioned
+below.
+
+.SH "EXAMPLES"
+
+.B Single instance
+.RS 4n
+
+To start the service:
+.nf
+.RS 4n
+.B systemctl start kresd@1.service
+.RE
+.fi
+
+To start the service at boot:
+.nf
+.RS 4n
+.B systemctl enable kresd@1.service
+.RE
+.fi
+
+To delay the service startup until some traffic arrives, start (or enable) just
+the sockets:
+.nf
+.RS 4n
+.B systemctl start kresd.socket
+.B systemctl start kresd-tls.socket
+.RE
+.fi
+
+To disable the TLS socket, you can mask it:
+
+.RS 4n
+.B systemctl mask kresd-tls.socket
+.RE
+
+.RE
+
+.B Multiple instances
+.RS 4n
+
+Multiple instances can be handled with the use of \fIBrace Expansion\fR (see
+\fBbash\fR(1)).
+
+To enable multiple concurrent daemons, for example 16:
+.nf
+.RS
+.B systemctl enable kresd@{1..16}.service
+.RE
+.fi
+
+To start all enabled daemons:
+.nf
+.RS
+.B systemctl start kresd.target
+.RE
+.fi
+
+.RE
+
+.SH "SEE ALSO"
+\fIkresd(8)\fR,
+\fIsystemd.unit(5)\fR,
+\fIsystemd.socket(5)\fR,
+\fIhttps://knot-resolver.readthedocs.io\fR
+
+.SH "AUTHORS"
+.B kresd
+developers are mentioned in the AUTHORS file in the distribution.
diff --git a/distro/common/systemd/kresd.target b/distro/common/systemd/kresd.target
new file mode 100644
index 0000000..9b524da
--- /dev/null
+++ b/distro/common/systemd/kresd.target
@@ -0,0 +1,8 @@
+[Unit]
+Description=Knot Resolver daemons
+Documentation=man:kresd.systemd(7)
+Documentation=man:kresd(8)
+After=network-online.target
+
+[Install]
+WantedBy=multi-user.target
diff --git a/distro/common/systemd/kresd@.service b/distro/common/systemd/kresd@.service
new file mode 100644
index 0000000..048aee0
--- /dev/null
+++ b/distro/common/systemd/kresd@.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Knot Resolver daemon
+Documentation=man:kresd.systemd(7)
+Documentation=man:kresd(8)
+
+[Service]
+Type=notify
+WorkingDirectory=/var/cache/knot-resolver
+ExecStart=/usr/sbin/kresd --config=/etc/knot-resolver/kresd.conf
+User=knot-resolver
+Restart=on-failure
+Sockets=kresd.socket
+Sockets=kresd-tls.socket
+Sockets=kresd-control@%i.socket
+
+[Install]
+WantedBy=kresd.target
diff --git a/distro/common/tmpfiles/knot-resolver.conf b/distro/common/tmpfiles/knot-resolver.conf
new file mode 100644
index 0000000..9ac5952
--- /dev/null
+++ b/distro/common/tmpfiles/knot-resolver.conf
@@ -0,0 +1,4 @@
+# tmpfiles.d(5) runtime directory for knot-resolver (kresd)
+#Type Path Mode UID GID Age Argument
+ d /run/knot-resolver 0750 root root - -
+ d /var/cache/knot-resolver 0750 knot-resolver knot-resolver - -
diff --git a/distro/deb/NEWS b/distro/deb/NEWS
new file mode 100644
index 0000000..e81403c
--- /dev/null
+++ b/distro/deb/NEWS
@@ -0,0 +1,23 @@
+knot-resolver (2.0.0-1) unstable; urgency=medium
+
+ Knot Resolver systemd service units are now templated, so that multiple
+ processes can run concurrently on multi-core systems. For a full
+ overview of the status of all the running daemons, use:
+
+ systemctl status system-kresd.slice
+
+ For more information about this setup, please see kresd.systemd(7).
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net> Sat, 03 Feb 2018 22:51:02 -0500
+
+knot-resolver (1.1.0~git2016072900-1) unstable; urgency=medium
+
+ Knot Resolver now starts and runs under unprivileged user and uses a
+ socket activations to bind on the privileged ports. That means that if
+ you use anything more complicated than that you need to either override
+ the default service file with `systemd edit kresd.service` and
+ `systemd edit kresd.socket` to add more IP addresses, or just disable
+ it with `systemd mask kresd*.socket kresd.service` and provide your
+ own custom system service file tailored to your needs.
+
+ -- Ondřej Surý <ondrej@debian.org> Thu, 04 Aug 2016 09:04:53 +0200
diff --git a/distro/deb/README.source b/distro/deb/README.source
new file mode 100644
index 0000000..657fc28
--- /dev/null
+++ b/distro/deb/README.source
@@ -0,0 +1,70 @@
+Tracking upstream sources in git
+--------------------------------
+
+This debian package is tracked in the git "debian/master" branch at
+https://salsa.debian.org/dns-team/knot-resolver, which
+includes the commits from the upstream git repository at
+https://gitlab.labs.nic.cz/knot/knot-resolver.git. When importing
+upstream tarballs, make sure you've fetched from the upstream repo
+before using "gbp import-orig" the tarball. We rely on
+upstream-vcs-tag from debian/gbp.conf to link upstream git history
+with new package history.
+
+See Joey Hess's thoughts about why tracking upstream git history is
+useful: https://joeyh.name/blog/entry/upstream_git_repositories/, as
+well as DEP-14 for the branch-naming scheme:
+http://dep.debian.net/deps/dep14/
+
+Rebuilding epoch.js and epoch.css
+---------------------------------
+
+ If you need to rebuild epoch.js and epoch.css using only tools
+ available in Debian, read gulpfile.js in d/missing-sources/epoch/ and
+ adjust following script if any files has been changed. You also need
+ to install ruby-sass, coffeescript and node-uglify
+
+cat > build.sh << EOF
+#!/bin/sh
+
+coffee -b -c \
+ src/epoch.coffee \
+ src/core/context.coffee \
+ src/core/util.coffee \
+ src/core/d3.coffee \
+ src/core/format.coffee \
+ src/core/chart.coffee \
+ src/core/css.coffee \
+ src/data.coffee \
+ src/model.coffee \
+ src/basic.coffee \
+ src/basic/*.coffee \
+ src/time.coffee \
+ src/time/*.coffee \
+ src/adapters.coffee \
+ src/adapters/*.coffee
+
+cat \
+ src/epoch.js \
+ src/core/context.js \
+ src/core/util.js \
+ src/core/d3.js \
+ src/core/format.js \
+ src/core/chart.js \
+ src/core/css.js \
+ src/data.js \
+ src/model.js \
+ src/basic.js \
+ src/basic/*.js \
+ src/time.js \
+ src/time/*.js \
+ src/adapters.js \
+ src/adapters/*.js \
+ > dist/js/epoch.js
+
+uglifyjs dist/js/epoch.js > dist/js/epoch.min.js
+
+sass -t compact sass/epoch.scss > dist/css/epoch.css
+sass -t compressed sass/epoch.scss > dist/css/epoch.min.css
+EOF
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>, Thu, 22 Feb 2018 13:25:27 -0800
diff --git a/distro/deb/changelog b/distro/deb/changelog
new file mode 100644
index 0000000..b0a6a3f
--- /dev/null
+++ b/distro/deb/changelog
@@ -0,0 +1,6 @@
+knot-resolver (__VERSION__-1) unstable; urgency=medium
+
+ * move changelog to OBS
+ * see NEWS or https://knot-resolver.cz
+
+ -- Tomas Krizek <tomas.krizek@nic.cz> Tue, 20 Feb 2018 19:36:45 +0100
diff --git a/distro/deb/clean b/distro/deb/clean
new file mode 100644
index 0000000..2ef7cbc
--- /dev/null
+++ b/distro/deb/clean
@@ -0,0 +1,4 @@
+doc/kresd.8
+libkres.pc
+lib/libkres.a
+lib/libkres.so.9
diff --git a/distro/deb/compat b/distro/deb/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/distro/deb/compat
@@ -0,0 +1 @@
+9
diff --git a/distro/deb/control b/distro/deb/control
new file mode 100644
index 0000000..012ff2b
--- /dev/null
+++ b/distro/deb/control
@@ -0,0 +1,137 @@
+Source: knot-resolver
+Section: net
+Priority: optional
+Maintainer: Knot Resolver <knot-resolver@labs.nic.cz>
+Uploaders:
+ Tomas Krizek <tomas.krizek@nic.cz>
+Build-Depends-Indep:
+ doxygen,
+ python3-breathe,
+ python3-sphinx,
+ python3-sphinx-rtd-theme,
+Build-Depends:
+ debhelper (>= 9~),
+ dns-root-data,
+ libcmocka-dev (>= 1.0.0),
+ libedit-dev,
+ libgeoip-dev,
+ libgnutls28-dev,
+ libknot-dev (>= 2.7.2),
+ liblmdb-dev,
+ libluajit-5.1-dev,
+ libsystemd-dev (>= 227) [linux-any],
+ libuv1-dev,
+ luajit,
+ pkg-config,
+Homepage: https://www.knot-resolver.cz/
+Rules-Requires-Root: no
+
+Package: knot-resolver
+Architecture: any
+Depends:
+ adduser,
+ dns-root-data,
+ libkres9 (= ${binary:Version}),
+ lua-sec,
+ lua-socket,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Recommends:
+ knot-resolver-module-http,
+Description: caching, DNSSEC-validating DNS resolver
+ The Knot Resolver is a caching full resolver implementation
+ written in C and LuaJIT, including both a resolver library and a
+ daemon. Modular architecture of the library keeps the core tiny and
+ efficient, and provides a state-machine like API for
+ extensions. There are three built-in modules - iterator, cache,
+ validator, and many external.
+ .
+ The Lua modules, switchable and shareable cache, and fast FFI
+ bindings makes it great to tap into resolution process, or be used
+ for your recursive DNS service. It's the OpenResty of DNS.
+ .
+ The server adopts a different scaling strategy than the rest of the
+ DNS recursors - no threading, shared-nothing architecture (except
+ MVCC cache that may be shared). You can start and stop additional
+ nodes depending on the contention without downtime.
+
+Package: knot-resolver-module-http
+Architecture: all
+Depends:
+ libjs-bootstrap,
+ libjs-d3,
+ libjs-jquery,
+ lua-http,
+ lua-mmdb,
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ knot-resolver-module-tinyweb (<< 1.1.0~git20160713-1~),
+Description: HTTP/2 module for Knot Resolver
+ The Knot Resolver is a caching full resolver implementation
+ written in C and LuaJIT, including both a resolver library and a
+ daemon. Modular architecture of the library keeps the core tiny and
+ efficient, and provides a state-machine like API for
+ extensions. There are three built-in modules - iterator, cache,
+ validator, and many external.
+ .
+ This package contains HTTP/2 module for local visualization of the
+ resolver cache and queries.
+
+Package: knot-resolver-doc
+Architecture: all
+Section: doc
+Depends:
+ libjs-jquery,
+ libjs-underscore,
+ ${misc:Depends},
+Description: Documentation for Knot Resolver
+ The Knot Resolver is a caching full resolver implementation
+ written in C and LuaJIT, including both a resolver library and a
+ daemon. Modular architecture of the library keeps the core tiny and
+ efficient, and provides a state-machine like API for
+ extensions. There are three built-in modules - iterator, cache,
+ validator, and many external.
+ .
+ This package contains Knot Resolver Documentation.
+
+Package: libkres9
+Architecture: any
+Section: libs
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ knot-resolver (<< 3.2.0-1),
+Replaces:
+ knot-resolver (<< 3.2.0-1),
+Description: caching, DNSSEC-validating DNS resolver (shared library)
+ The Knot Resolver is a caching full resolver implementation
+ written in C and LuaJIT, including both a resolver library and a
+ daemon. Modular architecture of the library keeps the core tiny and
+ efficient, and provides a state-machine like API for
+ extensions.
+ .
+ This package contains the libkres shared library used by Knot
+ Resolver.
+
+Package: libkres-dev
+Architecture: any
+Section: libdevel
+Depends:
+ libkres9 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Breaks:
+ knot-resolver (<< 3.2.0-1),
+Replaces:
+ knot-resolver (<< 3.2.0-1),
+Description: caching, DNSSEC-validating DNS resolver (shared library development files)
+ The Knot Resolver is a caching full resolver implementation
+ written in C and LuaJIT, including both a resolver library and a
+ daemon. Modular architecture of the library keeps the core tiny and
+ efficient, and provides a state-machine like API for
+ extensions.
+ .
+ This package provides development files for use when building against
+ the libkres shared library.
diff --git a/distro/deb/copyright b/distro/deb/copyright
new file mode 100644
index 0000000..10ecbf3
--- /dev/null
+++ b/distro/deb/copyright
@@ -0,0 +1,448 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: knot-resolver
+Source: https://www.knot-resolver.cz/
+
+Files: *
+Copyright: 2015-2018 CZ.NIC
+License: GPL-3.0+
+
+Files: contrib/ccan/asprintf/*
+Copyright: Rusty Russell
+License: Expat
+
+Files: contrib/ccan/compiler/*
+ contrib/ccan/ilog/*
+Copyright: Rusty Russell
+License: CC0
+
+Files: tests/config/tapered/*
+Copyright: 2012-2017, Peter Aronoff
+License: BSD-3-clause
+
+Files: contrib/lmdb/*
+Copyright: 1999-2003 The OpenLDAP Foundation
+License: OpenLDAP
+
+Files: tests/deckard/contrib/libfaketime/*
+Copyright: 2003-2017 Wolfgang Hommel
+License: GPL-2
+
+Files: tests/deckard/contrib/libswrap/*
+Copyright: 2005,2008 Jelmer Vernooij <jelmer@samba.org>
+ 2006-2009 Stefan Metzmacher <metze@samba.org>
+ 2013 Andreas Schneider <asn@samba.org>
+License: BSD-3-clause
+
+Files: contrib/murmurhash3/*
+Copyright: Austin Appleby
+License: CC0-1.0
+
+Files: debian/missing-sources/dygraph-combined.js
+ modules/http/static/dygraph-combined.js
+Copyright: 2006-2014 Dan Vanderkam <danvdk@gmail.com>
+ 2016 Paul Miller
+ 2011 Robert Konigsberg <konigsberg@google.com>
+ 2013 David Eberlein <david.eberlein@ch.sauter-bc.com>
+License: MIT
+
+Files: contrib/ucw/*
+Copyright: 1997-2015 Martin Mares
+ 2005-2014 Tomas Valla
+ 2006 Robert Spalek
+ 2007-2015 Pavel Charvat
+License: LGPL-2.1
+
+Files: contrib/ccan/json/*
+Copyright: 2011 Joey Adams
+License: Expat
+
+Files: lib/generic/map.c lib/generic/map.h
+Copyright: Dan Bernstein
+ Jonas Gehring
+ Adam Langley
+ Marek Vavrusa
+License: public-domain
+
+Files: modules/policy/lua-aho-corasick/*
+Copyright: 2013 CloudFlare, Inc.
+License: BSD-3-CloudFlare
+
+Files: modules/http/static/jquery.js
+Copyright: 2005-2011 John Resig, Brandon Aaron & Jörn Zaefferer
+License: GPL-2 or Expat
+
+Files: modules/http/static/d3.js
+ modules/http/static/topojson.js
+Copyright: 2010-2015 Michael Bostock
+License: BSD-3-clause
+
+Files: modules/http/static/epoch.*
+ debian/missing-sources/epoch/*
+ debian/missing-sources/epoch.*
+Copyright: 2014 Fastly, Inc.
+License: Expat
+
+Files: modules/http/static/datamaps.world.min.js
+Copyright: 2012 Mark DiMarco
+License: Expat
+
+Files: modules/http/static/bootstrap.min.css
+ modules/http/static/bootstrap.min.js
+ modules/http/static/bootstrap-theme.min.css
+ modules/http/static/glyphicons-halflings-regular.woff2
+Copyright: 2012-2016 Thomas Park
+ 2011-2015 Twitter, Inc.
+License: Expat
+
+Files: modules/http/static/selectize.bootstrap3.min.css
+ modules/http/static/selectize.min.css
+ modules/http/static/selectize.min.js
+Copyright: 2013–2015 Brian Reavis & contributors
+License: Apache-2.0
+
+Files: debian/*
+Copyright: 2015 Ondřej Surý <ondrej@debian.org>
+License: GPL-3.0+
+
+License: LGPL-2.1
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+ .
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <https://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/LGPL-2.1".
+
+License: GPL-3.0+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
+
+License: Expat
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+ .
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+License: CC0
+ Statement of Purpose
+ .
+ The laws of most jurisdictions throughout the world automatically
+ confer exclusive Copyright and Related Rights (defined below) upon
+ the creator and subsequent owner(s) (each and all, an "owner") of an
+ original work of authorship and/or a database (each, a "Work").
+ .
+ Certain owners wish to permanently relinquish those rights to a Work
+ for the purpose of contributing to a commons of creative, cultural
+ and scientific works ("Commons") that the public can reliably and
+ without fear of later claims of infringement build upon, modify,
+ incorporate in other works, reuse and redistribute as freely as
+ possible in any form whatsoever and for any purposes, including
+ without limitation commercial purposes. These owners may contribute
+ to the Commons to promote the ideal of a free culture and the further
+ production of creative, cultural and scientific works, or to gain
+ reputation or greater distribution for their Work in part through the
+ use and efforts of others.
+ .
+ For these and/or other purposes and motivations, and without any
+ expectation of additional consideration or compensation, the person
+ associating CC0 with a Work (the "Affirmer"), to the extent that he
+ or she is an owner of Copyright and Related Rights in the Work,
+ voluntarily elects to apply CC0 to the Work and publicly distribute
+ the Work under its terms, with knowledge of his or her Copyright and
+ Related Rights in the Work and the meaning and intended legal effect
+ of CC0 on those rights.
+ .
+ 1. Copyright and Related Rights. A Work made available under CC0 may
+ be protected by copyright and related or neighboring rights
+ ("Copyright and Related Rights"). Copyright and Related Rights
+ include, but are not limited to, the following:
+ .
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or
+ performer(s);
+ iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a
+ Work, subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse
+ of data in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC
+ of the European Parliament and of the Council of 11 March 1996
+ on the legal protection of databases, and under any national
+ implementation thereof, including any amended or successor
+ version of such directive); and
+ vii. other similar, equivalent or corresponding rights throughout
+ the world based on applicable law or treaty, and any national
+ implementations thereof.
+ .
+ 2. Waiver. To the greatest extent permitted by, but not in
+ contravention of, applicable law, Affirmer hereby overtly, fully,
+ permanently, irrevocably and unconditionally waives, abandons, and
+ surrenders all of Affirmer's Copyright and Related Rights and
+ associated claims and causes of action, whether now known or
+ unknown (including existing as well as future claims and causes of
+ action), in the Work (i) in all territories worldwide, (ii) for
+ the maximum duration provided by applicable law or treaty
+ (including future time extensions), (iii) in any current or future
+ medium and for any number of copies, and (iv) for any purpose
+ whatsoever, including without limitation commercial, advertising
+ or promotional purposes (the "Waiver"). Affirmer makes the Waiver
+ for the benefit of each member of the public at large and to the
+ detriment of Affirmer's heirs and successors, fully intending that
+ such Waiver shall not be subject to revocation, rescission,
+ cancellation, termination, or any other legal or equitable action
+ to disrupt the quiet enjoyment of the Work by the public as
+ contemplated by Affirmer's express Statement of Purpose.
+ .
+ 3. Public License Fallback. Should any part of the Waiver for any
+ reason be judged legally invalid or ineffective under applicable
+ law, then the Waiver shall be preserved to the maximum extent
+ permitted taking into account Affirmer's express Statement of
+ Purpose. In addition, to the extent the Waiver is so judged
+ Affirmer hereby grants to each affected person a royalty-free, non
+ transferable, non sublicensable, non exclusive, irrevocable and
+ unconditional license to exercise Affirmer's Copyright and Related
+ Rights in the Work (i) in all territories worldwide, (ii) for the
+ maximum duration provided by applicable law or treaty (including
+ future time extensions), (iii) in any current or future medium and
+ for any number of copies, and (iv) for any purpose whatsoever,
+ including without limitation commercial, advertising or
+ promotional purposes (the "License"). The License shall be deemed
+ effective as of the date CC0 was applied by Affirmer to the
+ Work. Should any part of the License for any reason be judged
+ legally invalid or ineffective under applicable law, such partial
+ invalidity or ineffectiveness shall not invalidate the remainder
+ of the License, and in such case Affirmer hereby affirms that he
+ or she will not (i) exercise any of his or her remaining Copyright
+ and Related Rights in the Work or (ii) assert any associated
+ claims and causes of action with respect to the Work, in either
+ case contrary to Affirmer's express Statement of Purpose.
+ .
+ 4. Limitations and Disclaimers.
+ .
+ a. No trademark or patent rights held by Affirmer are waived,
+ abandoned, surrendered, licensed or otherwise affected by this
+ document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties
+ of title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects,
+ accuracy, or the present or absence of errors, whether or not
+ discoverable, all to the greatest extent permissible under
+ applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other
+ persons that may apply to the Work or any use thereof, including
+ without limitation any person's Copyright and Related Rights in
+ the Work. Further, Affirmer disclaims responsibility for
+ obtaining any necessary consents, permissions or other rights
+ required for any use of the Work.
+ d. Affirmer understands and acknowledges that Creative Commons is
+ not a party to this document and has no duty or obligation with
+ respect to this CC0 or use of the Work.
+
+License: BSD-3-CloudFlare
+ 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 CloudFlare, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ OWNER 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.
+
+License: BSD-3-clause
+ 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 author 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 AUTHOR 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 AUTHOR 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.
+
+
+License: GPL-2
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ .
+ On Debian systems, the complete text of the GNU General Public
+ License version 2 can be found in "/usr/share/common-licenses/GPL-2".
+
+License: Apache-2.0
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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
+ .
+ https://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.
+ .
+ On Debian systems, the full text of the Apache Software License version 2 can
+ be found in the file `/usr/share/common-licenses/Apache-2.0'.
+
+License: MIT
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+ .
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+License: OpenLDAP
+ Redistribution and use of this software and associated documentation
+ ("Software"), with or without modification, are permitted provided
+ that the following conditions are met:
+ .
+ 1. Redistributions in source form must retain copyright statements
+ and notices,
+ .
+ 2. Redistributions in binary form must reproduce applicable copyright
+ statements and notices, this list of conditions, and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution, and
+ .
+ 3. Redistributions must contain a verbatim copy of this document.
+ .
+ The OpenLDAP Foundation may revise this license from time to time.
+ Each revision is distinguished by a version number. You may use
+ this Software under terms of this license revision or under the
+ terms of any subsequent revision of the license.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
+ CONTRIBUTORS ``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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
+ OR OWNER(S) OF THE SOFTWARE 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.
+ .
+ The names of the authors and copyright holders must not be used in
+ advertising or otherwise to promote the sale, use or other dealing
+ in this Software without specific, written prior permission. Title
+ to copyright in this Software shall at all times remain with copyright
+ holders.
+ .
+ OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+License: CC0-1.0
+ This work is licensed under the "Creative Commons Zero" license.
+ .
+ On debian systems, a copy of the Creative Commons Zero license may be
+ found at /usr/share/common-licenses/CC0-1.0.
+
+License: public-domain
+ This work has been released into the public domain. The map
+ implementation builds off of prior public domain work from Dan
+ Bernstein (qhasm) and Adam Langley (critbit).
diff --git a/distro/deb/docs b/distro/deb/docs
new file mode 100644
index 0000000..b43bf86
--- /dev/null
+++ b/distro/deb/docs
@@ -0,0 +1 @@
+README.md
diff --git a/distro/deb/init-d-script b/distro/deb/init-d-script
new file mode 100755
index 0000000..334dc32
--- /dev/null
+++ b/distro/deb/init-d-script
@@ -0,0 +1,239 @@
+#!/bin/sh
+# See init-d-script(5) for instructions on how to use this library.
+#=============================================================================
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh
+# script. Scripts running before mountnfs.sh should remove the /usr/*
+# entries.
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+export PATH
+
+is_call_implemented() {
+ command -V $1 > /dev/null 2>&1
+}
+
+do_usage() {
+ if is_call_implemented do_reload ; then
+ echo "Usage: $SCRIPTNAME {start|stop|status|reload|restart|try-restart|force-reload}" >&2
+ else
+ echo "Usage: $SCRIPTNAME {start|stop|status|restart|try-restart|force-reload}" >&2
+ fi
+}
+
+call() {
+ cmd="$1"
+ shift
+ if is_call_implemented ${cmd}_override ; then
+ ${cmd}_override "$@"
+ else
+ ${cmd} "$@"
+ fi
+}
+
+#
+# Function that starts the daemon/service
+#
+
+# Return
+# 0 if daemon has been started
+# 1 if daemon was already running
+# 2 if daemon could not be started
+do_start_cmd() {
+ start-stop-daemon --start --quiet ${PIDFILE:+--pidfile ${PIDFILE}} \
+ $START_ARGS \
+ --startas $DAEMON --name $NAME --exec $DAEMON --test > /dev/null \
+ || return 1
+ start-stop-daemon --start --quiet ${PIDFILE:+--pidfile ${PIDFILE}} \
+ $START_ARGS \
+ --startas $DAEMON --name $NAME --exec $DAEMON -- $DAEMON_ARGS \
+ || return 2
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+do_start()
+{
+ if is_call_implemented do_start_prepare ; then
+ call do_start_prepare
+ fi
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ call do_start_cmd
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ if is_call_implemented do_start_cleanup ; then
+ call do_start_cleanup
+ fi
+}
+
+#
+# Function that stops the daemon/service
+#
+
+# Return
+# 0 if daemon has been stopped
+# 1 if daemon was already stopped
+# 2 if daemon could not be stopped
+# other if a failure occurred
+do_stop_cmd() {
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
+ $STOP_ARGS \
+ ${PIDFILE:+--pidfile ${PIDFILE}} --name $NAME --exec $DAEMON
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 \
+ $STOP_ARGS \
+ --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return $RETVAL
+}
+
+do_stop()
+{
+ if is_call_implemented do_stop_prepare ; then
+ call do_stop_prepare
+ fi
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ call do_stop_cmd
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ if is_call_implemented do_stop_cleanup ; then
+ call do_stop_cleanup
+ fi
+}
+
+do_restart() {
+ [ "$VERBOSE" != no ] && log_daemon_msg "Restarting $DESC" "$NAME"
+ call do_stop_cmd
+ call do_start_cmd
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+}
+
+do_force_reload() {
+ if is_call_implemented do_reload ; then
+ call do_reload
+ else
+ call do_restart
+ fi
+}
+
+# Enable this using
+# alias do_reload=do_reload_sigusr1
+do_reload_sigusr1() {
+ log_daemon_msg "Reloading $DESC configuration files" "$NAME"
+ start-stop-daemon --oknodo --stop --signal 1 --quiet \
+ --pidfile "$PIDFILE" --exec "$DAEMON"
+ log_end_msg $?
+}
+
+do_status() {
+ status_of_proc "$DAEMON" "$NAME" && return 0 || return $?
+}
+
+if [ "$DEBUG" = "true" ] ; then
+ set -x
+fi
+
+SCRIPTNAME=$1
+scriptbasename="$(basename $1)"
+if [ "$scriptbasename" != "init-d-script" ] ; then
+ script="$1"
+ shift
+ . $script
+else
+ exit 0
+fi
+
+NAME=${NAME:=$(basename $DAEMON)}
+DESC=${DESC:=$NAME}
+
+# Do not use pid file if $PIDFILE is 'none'. Otherwise, generate from
+# $NAME or use the value provided by the init.d script.
+if [ none = "$PIDFILE" ] ; then
+ PIDFILE=
+elif [ -z "$PIDFILE" ] ; then
+ PIDFILE=/var/run/$NAME.pid
+fi
+
+# Exit if the package is not installed
+if [ none != "$DAEMON" ] && [ ! -x "$DAEMON" ] ; then
+ exit 0
+fi
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+if [ -t 0 ] ; then # Be verbose when called from a terminal
+ VERBOSE=yes
+fi
+
+case "$1" in
+ start)
+ call do_start
+ ;;
+ stop)
+ call do_stop
+ ;;
+ status)
+ call do_status
+ ;;
+ reload)
+ if is_call_implemented do_reload ; then
+ do_reload
+ else
+ call do_usage
+ exit 3
+ fi
+ ;;
+ force-reload)
+ call do_force_reload
+ ;;
+ restart)
+ call do_restart
+ ;;
+ try-restart)
+ log_daemon_msg "Trying to restart $DESC" "$NAME"
+ if call do_status > /dev/null 2>&1 ; then
+ call do_restart
+ log_end_msg $?
+ else
+ log_progress_msg "is not running."
+ log_end_msg 1
+ fi
+ ;;
+ '')
+ call do_usage
+ exit 3
+ ;;
+ *)
+ if is_call_implemented do_unknown ; then
+ call do_unknown "$1"
+ exit 3
+ else
+ call do_usage
+ exit 3
+ fi
+ ;;
+esac
+exit 0
diff --git a/distro/deb/knot-resolver-doc.doc-base b/distro/deb/knot-resolver-doc.doc-base
new file mode 100644
index 0000000..f82b8ba
--- /dev/null
+++ b/distro/deb/knot-resolver-doc.doc-base
@@ -0,0 +1,11 @@
+Document: knot-resolver
+Title: Knot Resolver documentation
+Author: CZ.NIC labs
+Abstract: Documentation for the Knot Resolver,
+ including building from source, using the library,
+ and configuration and operation of the daemon.
+Section: Network/Communication
+
+Format: HTML
+Index: /usr/share/doc/knot-resolver/index.html
+Files: /usr/share/doc/knot-resolver/*.html
diff --git a/distro/deb/knot-resolver-doc.docs b/distro/deb/knot-resolver-doc.docs
new file mode 100644
index 0000000..3ff7356
--- /dev/null
+++ b/distro/deb/knot-resolver-doc.docs
@@ -0,0 +1 @@
+doc/html/*
diff --git a/distro/deb/knot-resolver-doc.links b/distro/deb/knot-resolver-doc.links
new file mode 100644
index 0000000..4c7c74f
--- /dev/null
+++ b/distro/deb/knot-resolver-doc.links
@@ -0,0 +1,2 @@
+usr/share/javascript/jquery/jquery.min.js usr/share/doc/knot-resolver/_static/jquery.js
+usr/share/javascript/underscore/underscore.min.js usr/share/doc/knot-resolver/_static/underscore.js
diff --git a/distro/deb/knot-resolver-module-http.install b/distro/deb/knot-resolver-module-http.install
new file mode 100644
index 0000000..3c2d56b
--- /dev/null
+++ b/distro/deb/knot-resolver-module-http.install
@@ -0,0 +1,6 @@
+usr/lib/knot-resolver/http.lua
+usr/lib/knot-resolver/http/*.css
+usr/lib/knot-resolver/http/*.ico
+usr/lib/knot-resolver/http/*.js
+usr/lib/knot-resolver/http/*.tpl
+usr/lib/knot-resolver/http/*.woff2
diff --git a/distro/deb/knot-resolver-module-http.links b/distro/deb/knot-resolver-module-http.links
new file mode 100644
index 0000000..322529c
--- /dev/null
+++ b/distro/deb/knot-resolver-module-http.links
@@ -0,0 +1,5 @@
+/usr/share/javascript/bootstrap/css/bootstrap-theme.min.css /usr/lib/knot-resolver/http/bootstrap-theme.min.css
+/usr/share/javascript/bootstrap/css/bootstrap.min.css /usr/lib/knot-resolver/http/bootstrap.min.css
+/usr/share/javascript/bootstrap/js/bootstrap.min.js /usr/lib/knot-resolver/http/bootstrap.min.js
+/usr/share/javascript/d3/d3.min.js /usr/lib/knot-resolver/http/d3.js
+/usr/share/javascript/jquery/jquery.min.js /usr/lib/knot-resolver/http/jquery.js
diff --git a/distro/deb/knot-resolver-module-tinyweb.install b/distro/deb/knot-resolver-module-tinyweb.install
new file mode 100644
index 0000000..905241c
--- /dev/null
+++ b/distro/deb/knot-resolver-module-tinyweb.install
@@ -0,0 +1 @@
+usr/lib/knot-resolver/tinyweb/*
diff --git a/distro/deb/knot-resolver.dirs b/distro/deb/knot-resolver.dirs
new file mode 100644
index 0000000..472b32a
--- /dev/null
+++ b/distro/deb/knot-resolver.dirs
@@ -0,0 +1,3 @@
+/etc/knot-resolver
+/usr/share/doc/knot-resolver/examples/
+/var/lib/knot-resolver
diff --git a/distro/deb/knot-resolver.install b/distro/deb/knot-resolver.install
new file mode 100644
index 0000000..d6c9b10
--- /dev/null
+++ b/distro/deb/knot-resolver.install
@@ -0,0 +1,38 @@
+debian/init-d-script usr/lib/knot-resolver/
+debian/kresd.conf etc/knot-resolver/
+etc/knot-resolver/config.* /usr/share/doc/knot-resolver/examples/
+distro/common/systemd/kresd-control@.socket lib/systemd/system/
+distro/common/systemd/kresd-tls.socket lib/systemd/system/
+distro/common/systemd/kresd.socket lib/systemd/system/
+distro/common/systemd/kresd@.service lib/systemd/system/
+distro/common/systemd/kresd.target lib/systemd/system/
+distro/common/tmpfiles/knot-resolver.conf usr/lib/tmpfiles.d/
+usr/lib/knot-resolver/*.so
+usr/lib/knot-resolver/basexx.lua
+usr/lib/knot-resolver/daf.lua
+usr/lib/knot-resolver/daf/
+usr/lib/knot-resolver/detect_time_jump.lua
+usr/lib/knot-resolver/detect_time_skew.lua
+usr/lib/knot-resolver/dns64.lua
+usr/lib/knot-resolver/etcd.lua
+usr/lib/knot-resolver/experimental_dot_auth.lua
+usr/lib/knot-resolver/graphite.lua
+usr/lib/knot-resolver/http_trace.lua
+usr/lib/knot-resolver/kres-gen.lua
+usr/lib/knot-resolver/kres.lua
+usr/lib/knot-resolver/policy.lua
+usr/lib/knot-resolver/predict.lua
+usr/lib/knot-resolver/prefill.lua
+usr/lib/knot-resolver/priming.lua
+usr/lib/knot-resolver/prometheus.lua
+usr/lib/knot-resolver/rebinding.lua
+usr/lib/knot-resolver/renumber.lua
+usr/lib/knot-resolver/serve_stale.lua
+usr/lib/knot-resolver/ta_sentinel.lua
+usr/lib/knot-resolver/ta_signal_query.lua
+usr/lib/knot-resolver/trust_anchors.lua
+usr/lib/knot-resolver/view.lua
+usr/lib/knot-resolver/workarounds.lua
+usr/lib/knot-resolver/zonefile.lua
+usr/sbin/kresc
+usr/sbin/kresd
diff --git a/distro/deb/knot-resolver.kresd.default b/distro/deb/knot-resolver.kresd.default
new file mode 100644
index 0000000..f7c46e5
--- /dev/null
+++ b/distro/deb/knot-resolver.kresd.default
@@ -0,0 +1,13 @@
+# /etc/default/kresd
+
+# This file is used only under sysvinit. If you use systemd and you
+# want to modify the arguments with which kresd is invoked, you should
+# instead use "systemctl edit kresd@.service" to override ExecStart=
+# in the [Service] section (see kresd.systemd(7) for more details).
+
+# For sysvinit users: KRESD_ARGS used to exist for historical reasons,
+# but that variable is deprecated and may stop working at some point
+# in the future. You are encouraged to merge any local changes into
+# DAEMON_ARGS directly.
+
+DAEMON_ARGS="--config=/etc/knot-resolver/kresd.conf --addr=127.0.0.1#53 --addr=::1#53 $KRESD_ARGS"
diff --git a/distro/deb/knot-resolver.kresd.init b/distro/deb/knot-resolver.kresd.init
new file mode 100644
index 0000000..b1361fd
--- /dev/null
+++ b/distro/deb/knot-resolver.kresd.init
@@ -0,0 +1,59 @@
+#!/bin/sh
+# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
+if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
+ if [ -x /lib/init/init-d-script ]; then
+ set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
+ else
+ set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /usr/lib/knot-resolver/init-d-script
+ fi
+fi
+### BEGIN INIT INFO
+# Provides: kresd
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Knot Resolver
+# Description: Knot Resolver
+### END INIT INFO
+
+# Author: Ondřej Surý <ondrej@debian.org>
+
+NAME=kresd
+DESC="Knot Resolver"
+DAEMON=/usr/sbin/kresd
+START_ARGS="--background --make-pidfile"
+
+do_tmpfiles() {
+ local tmpfile type path mode user group age argument
+ tmpfile=/usr/lib/tmpfiles.d/$1.conf
+ if [ -r "$tmpfile" ]; then
+ if [ -x /bin/systemd-tmpfiles ]; then
+ /bin/systemd-tmpfiles --create "$tmpfile"
+ else
+ while read type path mode user group age argument; do
+ case "$type" in
+ d)
+ mkdir -p "$path";
+ chmod "$mode" "$path";
+ chown "$user:$group" "$path";
+ ;;
+ L)
+ if [ ! -e "$path" ]; then ln -s "$argument" "$path"; fi
+ ;;
+ \#*)
+ ;;
+ *)
+ log_warning_msg "tmpfile.d type '$type' is not supported yet"
+ ;;
+ esac
+ done < "$tmpfile"
+ fi
+ else
+ log_warning_msg "tmpfiles.d file '$1' doesn't exist or is not readable"
+ fi
+}
+
+do_start_prepare() {
+ do_tmpfiles knot-resolver
+}
diff --git a/distro/deb/knot-resolver.links b/distro/deb/knot-resolver.links
new file mode 100644
index 0000000..8196524
--- /dev/null
+++ b/distro/deb/knot-resolver.links
@@ -0,0 +1,2 @@
+dev/null lib/systemd/system/kresd.service
+lib/systemd/system/kresd.target lib/systemd/system/multi-user.target.wants/kresd.target
diff --git a/distro/deb/knot-resolver.manpages b/distro/deb/knot-resolver.manpages
new file mode 100644
index 0000000..9f97677
--- /dev/null
+++ b/distro/deb/knot-resolver.manpages
@@ -0,0 +1,2 @@
+debian/tmp/usr/share/man/man8/kresd.8
+distro/common/systemd/kresd.systemd.7
diff --git a/distro/deb/knot-resolver.postinst b/distro/deb/knot-resolver.postinst
new file mode 100644
index 0000000..7c4bc5b
--- /dev/null
+++ b/distro/deb/knot-resolver.postinst
@@ -0,0 +1,30 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = "configure" ]; then
+ adduser --quiet --system --group --no-create-home --home /var/cache/knot-resolver knot-resolver
+fi
+
+# Restart any running kresd instances if the root key is updated.
+# Note: if knot-resolver upstream watches this file and reloads it
+# upon a change, we can and should remove this trigger.
+if [ "$1" = "triggered" ]; then
+ if [ "$2" = "/usr/share/dns/root.key" ]; then
+ # systemctl of the sub-services is the preferred method to restart
+ systemctl try-restart 'kresd@*.service' || true
+ # but if we are running sysvinit, we can try to restart that process anyway
+ # (kresd.service is masked on systems that use systemd)
+ invoke-rc.d kresd try-restart || true
+ fi
+ exit 0
+fi
+
+if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
+ if [ -d /run/systemd/system ]; then
+ systemctl try-restart 'kresd@*.service' || true
+ else
+ invoke-rc.d kresd try-restart || true
+ fi
+fi
+
+#DEBHELPER#
diff --git a/distro/deb/knot-resolver.postrm b/distro/deb/knot-resolver.postrm
new file mode 100644
index 0000000..d67739e
--- /dev/null
+++ b/distro/deb/knot-resolver.postrm
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = "remove" ] && [ -x "/bin/systemctl" ]; then
+ systemctl stop system-kresd.slice || true
+fi
+
+#DEBHELPER#
diff --git a/distro/deb/knot-resolver.triggers b/distro/deb/knot-resolver.triggers
new file mode 100644
index 0000000..e8d8246
--- /dev/null
+++ b/distro/deb/knot-resolver.triggers
@@ -0,0 +1 @@
+interest-noawait /usr/share/dns/root.key
diff --git a/distro/deb/kresd.conf b/distro/deb/kresd.conf
new file mode 100644
index 0000000..e452f0e
--- /dev/null
+++ b/distro/deb/kresd.conf
@@ -0,0 +1,19 @@
+-- vim:syntax=lua:
+-- Refer to manual: http://knot-resolver.readthedocs.org/en/latest/daemon.html#configuration
+
+-- Load useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ 'predict', -- Prefetch expiring/frequent records
+}
+
+-- See kresd.systemd(7) about configuring network interfaces when using systemd
+-- Listen on localhost (default)
+-- net = { '127.0.0.1', '::1' }
+
+-- To disable DNSSEC validation, uncomment the following line (not recommended)
+-- trust_anchors.keyfile_default = nil
+
+-- Cache size
+cache.size = 100 * MB
diff --git a/distro/deb/libkres-dev.install b/distro/deb/libkres-dev.install
new file mode 100644
index 0000000..d565b38
--- /dev/null
+++ b/distro/deb/libkres-dev.install
@@ -0,0 +1,3 @@
+usr/include/libkres/*.h
+usr/lib/*.so
+usr/lib/pkgconfig/libkres.pc
diff --git a/distro/deb/libkres9.install b/distro/deb/libkres9.install
new file mode 100644
index 0000000..093956b
--- /dev/null
+++ b/distro/deb/libkres9.install
@@ -0,0 +1 @@
+usr/lib/*.so.*
diff --git a/distro/deb/libkres9.symbols b/distro/deb/libkres9.symbols
new file mode 100644
index 0000000..444e333
--- /dev/null
+++ b/distro/deb/libkres9.symbols
@@ -0,0 +1,144 @@
+libkres.so.9 libkres9 #MINVER#
+ cache_api@Base 2.1.0
+ iterate_api@Base 2.1.0
+ kr_bitcmp@Base 2.1.0
+ kr_cache_clear@Base 2.1.0
+ kr_cache_close@Base 2.1.0
+ kr_cache_closest_apex@Base 3.1.0
+ kr_cache_emergency_file_to_remove@Base 3.1.0
+ kr_cache_insert_rr@Base 3.0.0
+ kr_cache_match@Base 3.1.0
+ kr_cache_materialize@Base 2.1.0
+ kr_cache_open@Base 2.1.0
+ kr_cache_peek_exact@Base 2.1.0
+ kr_cache_remove@Base 3.1.0
+ kr_cache_remove_subtree@Base 3.1.0
+ kr_cache_sync@Base 2.1.0
+ kr_cache_ttl@Base 2.1.0
+ kr_cdb_lmdb@Base 2.1.0
+ kr_crypto_cleanup@Base 2.1.0
+ kr_crypto_init@Base 2.1.0
+ kr_crypto_reinit@Base 2.1.0
+ kr_dnssec_key_ksk@Base 2.1.0
+ kr_dnssec_key_match@Base 2.1.0
+ kr_dnssec_key_revoked@Base 2.1.0
+ kr_dnssec_key_tag@Base 2.1.0
+ kr_dnssec_key_zsk@Base 2.1.0
+ kr_family_len@Base 2.1.0
+ kr_inaddr@Base 2.1.0
+ kr_inaddr_family@Base 2.1.0
+ kr_inaddr_len@Base 2.1.0
+ kr_inaddr_port@Base 2.1.0
+ kr_inaddr_set_port@Base 3.1.0
+ kr_inaddr_str@Base 2.1.0
+ kr_log_qverbose_impl@Base 3.2.0
+ kr_log_trace@Base 2.1.0
+ kr_log_verbose@Base 2.1.0
+ kr_make_query@Base 3.0.0
+ kr_memreserve@Base 2.1.0
+ kr_module_call@Base 2.1.0
+ kr_module_embedded@Base 2.1.0
+ kr_module_load@Base 2.1.0
+ kr_module_unload@Base 2.1.0
+ kr_now@Base 2.1.0
+ kr_nsrep_elect@Base 2.1.0
+ kr_nsrep_elect_addr@Base 2.1.0
+ kr_nsrep_set@Base 2.1.0
+ kr_nsrep_sort@Base 3.2.0
+ kr_nsrep_update_rep@Base 2.1.0
+ kr_nsrep_update_rtt@Base 2.1.0
+ kr_pkt_clear_payload@Base 2.1.0
+ kr_pkt_make_auth_header@Base 2.1.0
+ kr_pkt_put@Base 2.1.0
+ kr_pkt_qclass@Base 3.0.0
+ kr_pkt_qtype@Base 3.0.0
+ kr_pkt_recycle@Base 2.1.0
+ kr_qflags_clear@Base 2.1.0
+ kr_qflags_set@Base 2.1.0
+ kr_ranked_rrarray_add@Base 2.1.0
+ kr_resolve_begin@Base 2.1.0
+ kr_resolve_checkout@Base 2.1.0
+ kr_resolve_consume@Base 2.1.0
+ kr_resolve_finish@Base 2.1.0
+ kr_resolve_plan@Base 2.1.0
+ kr_resolve_pool@Base 2.1.0
+ kr_resolve_produce@Base 2.1.0
+ kr_rnd_buffered@Base 3.2.0
+ kr_rplan_deinit@Base 2.1.0
+ kr_rplan_empty@Base 2.1.0
+ kr_rplan_find_resolved@Base 2.1.0
+ kr_rplan_init@Base 2.1.0
+ kr_rplan_last@Base 2.1.0
+ kr_rplan_pop@Base 2.1.0
+ kr_rplan_push@Base 2.1.0
+ kr_rplan_push_empty@Base 2.1.0
+ kr_rplan_resolved@Base 2.1.0
+ kr_rplan_satisfies@Base 2.1.0
+ kr_rrkey@Base 2.1.0
+ kr_rrset_init@Base 3.0.0
+ kr_rrsig_sig_expiration@Base 3.0.0
+ kr_rrsig_sig_inception@Base 3.0.0
+ kr_rrsig_type_covered@Base 3.0.0
+ kr_sockaddr_cmp@Base 3.0.0
+ kr_sockaddr_len@Base 2.1.0
+ kr_straddr_family@Base 2.1.0
+ kr_straddr_join@Base 2.1.0
+ kr_straddr_socket@Base 2.1.0
+ kr_straddr_split@Base 2.1.0
+ kr_straddr_subnet@Base 2.1.0
+ kr_strcatdup@Base 2.1.0
+ kr_ta_add@Base 2.1.0
+ kr_ta_clear@Base 2.1.0
+ kr_ta_covers@Base 2.1.0
+ kr_ta_covers_qry@Base 2.1.0
+ kr_ta_del@Base 2.1.0
+ kr_ta_get@Base 2.1.0
+ kr_ta_get_longest_name@Base 2.1.0
+ kr_unpack_cache_key@Base 3.1.0
+ kr_verbose_set@Base 2.1.0
+ kr_verbose_status@Base 2.1.0
+ kr_zonecut_add@Base 3.2.0
+ kr_zonecut_copy@Base 2.1.0
+ kr_zonecut_copy_trust@Base 2.1.0
+ kr_zonecut_deinit@Base 2.1.0
+ kr_zonecut_del@Base 3.2.0
+ kr_zonecut_del_all@Base 2.1.0
+ kr_zonecut_find@Base 2.1.0
+ kr_zonecut_find_cached@Base 2.1.0
+ kr_zonecut_init@Base 2.1.0
+ kr_zonecut_is_empty@Base 3.0.0
+ kr_zonecut_move@Base 3.2.0
+ kr_zonecut_set@Base 2.1.0
+ kr_zonecut_set_sbelt@Base 2.1.0
+ lru_apply_impl@Base 2.1.0
+ lru_create_impl@Base 2.1.0
+ lru_free_items_impl@Base 2.1.0
+ lru_get_impl@Base 2.1.0
+ map_clear@Base 2.1.0
+ map_contains@Base 2.1.0
+ map_del@Base 2.1.0
+ map_get@Base 2.1.0
+ map_set@Base 2.1.0
+ map_walk_prefixed@Base 2.1.0
+ mm_realloc@Base 3.2.0
+ queue_deinit_impl@Base 3.1.0
+ queue_init_impl@Base 3.1.0
+ queue_push_head_impl@Base 3.1.0
+ queue_push_impl@Base 3.1.0
+ trie_clear@Base 3.0.0
+ trie_create@Base 3.0.0
+ trie_del@Base 3.0.0
+ trie_del_first@Base 3.1.0
+ trie_free@Base 3.0.0
+ trie_get_first@Base 3.1.0
+ trie_get_ins@Base 3.0.0
+ trie_get_leq@Base 3.1.0
+ trie_get_try@Base 3.0.0
+ trie_it_begin@Base 3.0.0
+ trie_it_finished@Base 3.0.0
+ trie_it_free@Base 3.0.0
+ trie_it_key@Base 3.0.0
+ trie_it_next@Base 3.0.0
+ trie_it_val@Base 3.0.0
+ trie_weight@Base 3.0.0
+ validate_api@Base 2.1.0
diff --git a/distro/deb/not-installed b/distro/deb/not-installed
new file mode 100644
index 0000000..590e3b2
--- /dev/null
+++ b/distro/deb/not-installed
@@ -0,0 +1 @@
+usr/lib/knot-resolver/http/LICENSE
diff --git a/distro/deb/patches/0001-Update-documentation-of-keyfile-ro.patch b/distro/deb/patches/0001-Update-documentation-of-keyfile-ro.patch
new file mode 100644
index 0000000..53e6bb3
--- /dev/null
+++ b/distro/deb/patches/0001-Update-documentation-of-keyfile-ro.patch
@@ -0,0 +1,41 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Sat, 17 Feb 2018 15:52:20 -0500
+Subject: Update documentation of --keyfile-ro
+
+On Debian systems, we depend on the OS package management to update
+the dns root data. Make the documentation for running with this
+option less scary-sounding, as it is the default.
+---
+ doc/kresd.8.in | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/doc/kresd.8.in b/doc/kresd.8.in
+index 266e9f0..6c5195b 100644
+--- a/doc/kresd.8.in
++++ b/doc/kresd.8.in
+@@ -123,7 +123,7 @@ file at the default location (\fIconfig\fR). The syntax is
+ described in \fIdaemon/README.md\fR.
+ .TP
+ .B \-k\fI keyfile\fR, \fB\-\-keyfile=\fI<keyfile>
+-(Recommended!) Automatically managed root trust anchors file.
++Automatically managed root trust anchors file.
+ Root trust anchors in this file are managed using standard RFC 5011 (Automated Updates of DNS Security Trust Anchors).
+ Kresd needs write access to the directory containing the keyfile.
+
+@@ -134,9 +134,14 @@ The file contains DNSKEY/DS records in presentation format,
+ and is compatible with Unbound and BIND 9 root key files.
+ .TP
+ .B \-K\fI keyfile\fR, \fB\-\-keyfile\-ro=\fI<keyfile>
+-(Discouraged) Static root trust anchors file. The file is not updated by kresd. Use of this option is discouraged because it will break your installation when the trust anchor key changes!
++Static root trust anchors file. The file is not updated by
++kresd. Please ensure that any running kresd instances are restarted if
++the trust anchors change. (On Debian, kresd will be restarted
++automatically when the dns-root-data package updates
++/usr/share/dns/root.key, so nothing extra needs to be done unless you
++diverge from the default here.)
+
+-Default: "@KEYFILE_DEFAULT@" (can be empty if your distribution did not provide one)
++Default: "@KEYFILE_DEFAULT@"
+ .TP
+ .B \-m\fI path\fR, \fB\-\-moduledir=\fI<path>
+ Override the directory that is searched for modules. Default: @MODULEDIR@
diff --git a/distro/deb/patches/series b/distro/deb/patches/series
new file mode 100644
index 0000000..5f6f9b5
--- /dev/null
+++ b/distro/deb/patches/series
@@ -0,0 +1 @@
+0001-Update-documentation-of-keyfile-ro.patch
diff --git a/distro/deb/rules b/distro/deb/rules
new file mode 100755
index 0000000..758f30c
--- /dev/null
+++ b/distro/deb/rules
@@ -0,0 +1,68 @@
+#!/usr/bin/make -f
+
+# see FEATURE AREAS in dpkg-buildflags(1)
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all,-pie
+
+# see ENVIRONMENT in dpkg-buildflags(1)
+# package maintainers to append CFLAGS
+export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic -fno-omit-frame-pointer
+# package maintainers to append LDFLAGS
+export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
+
+# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/default.mk
+
+export ARCH=$(DEB_HOST_GNU_CPU)
+export PREFIX=/usr
+export MODULEDIR=/usr/lib/knot-resolver
+export ETCDIR=/etc/knot-resolver
+
+RUN_TESTS := yes
+ifeq ($(DEB_HOST_ARCH),$(filter $(DEB_HOST_ARCH),hurd-i386 mips mipsel ppc64 ppc64el armel armhf arm64 kfreebsd-amd64 kfreebsd-i386))
+ $(warning Disabling checks on $(DEB_HOST_ARCH))
+ RUN_TESTS := no
+endif
+
+%:
+ dh $@
+
+override_dh_auto_clean-indep:
+ dh_auto_clean -- doc-clean http-clean
+
+override_dh_auto_build-arch:
+ CFLAGS="$${CFLAGS} -DNDEBUG" dh_auto_build -- V=1 BUILDMODE=static lib
+ CFLAGS="$${CFLAGS} -DNDEBUG" dh_auto_build -- V=1 \
+ ROOTHINTS=/usr/share/dns/root.hints \
+ KEYFILE_DEFAULT=/usr/share/dns/root.key
+
+override_dh_auto_build-indep:
+ dh_auto_build -- V=1 http
+ dh_auto_build -- V=1 doc-doxygen
+ cd doc && sphinx-build -b html -D html_theme=nature . html
+
+override_dh_auto_install-arch:
+ dh_auto_install --destdir=debian/tmp -- V=1 KEYFILE_DEFAULT=/usr/share/dns/root.key
+ rm -f debian/tmp/etc/knot-resolver/root.hints debian/tmp/etc/knot-resolver/icann-ca.pem
+
+override_dh_auto_install-indep:
+# install just the http/2 module
+ make http-install DESTDIR=debian/tmp V=1
+
+override_dh_installinit:
+ dh_installinit -pknot-resolver --name=kresd --no-start
+
+override_dh_installsystemd:
+ dh_installsystemd -pknot-resolver --name=kresd kresd-tls.socket kresd.socket
+
+override_dh_auto_test-indep:
+override_dh_auto_test-arch:
+ifeq ($(RUN_TESTS),yes)
+ dh_auto_test -- V=1
+endif
+
+override_dh_missing:
+ dh_missing --fail-missing
+
+override_dh_installchangelogs:
+ dh_installchangelogs NEWS
diff --git a/distro/deb/source/format b/distro/deb/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/distro/deb/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/distro/deb/tests/control b/distro/deb/tests/control
new file mode 100644
index 0000000..be666d7
--- /dev/null
+++ b/distro/deb/tests/control
@@ -0,0 +1,2 @@
+Test-Command: make installcheck
+Depends: @, @builddeps@
diff --git a/distro/rpm/knot-resolver.spec b/distro/rpm/knot-resolver.spec
new file mode 100644
index 0000000..359e5b6
--- /dev/null
+++ b/distro/rpm/knot-resolver.spec
@@ -0,0 +1,235 @@
+%global _hardened_build 1
+%{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}}
+
+%define GPG_CHECK 0
+%define VERSION __VERSION__
+%define repodir %{_builddir}/%{name}-%{version}
+
+Name: knot-resolver
+Version: %{VERSION}
+Release: 1%{?dist}
+Summary: Caching full DNS Resolver
+
+License: GPLv3
+URL: https://www.knot-resolver.cz/
+Source0: knot-resolver_%{version}.orig.tar.xz
+
+# LuaJIT only on these arches
+%if 0%{?rhel}
+# RHEL 7 does not have aarch64 LuaJIT
+ExclusiveArch: %{ix86} x86_64
+%else
+ExclusiveArch: %{arm} aarch64 %{ix86} x86_64
+%endif
+
+%if 0%{GPG_CHECK}
+Source1: knot-resolver-%{version}.tar.xz.asc
+# PGP keys used to sign upstream releases
+# Export with --armor using command from https://fedoraproject.org/wiki/PackagingDrafts:GPGSignatures
+# Don't forget to update %%prep section when adding/removing keys
+Source100: gpgkey-B6006460B60A80E782062449E747DF1F9575A3AA.gpg.asc
+Source101: gpgkey-BE26EBB9CBE059B3910CA35BCE8DD6A1A50A21E4.gpg.asc
+Source102: gpgkey-4A8BA48C2AED933BD495C509A1FBA5F7EF8C4869.gpg.asc
+BuildRequires: gnupg2
+%endif
+
+BuildRequires: gcc
+BuildRequires: gcc-c++
+BuildRequires: pkgconfig(cmocka)
+BuildRequires: pkgconfig(gnutls)
+BuildRequires: pkgconfig(libedit)
+BuildRequires: pkgconfig(libknot) >= 2.7.2
+BuildRequires: pkgconfig(libzscanner) >= 2.7.2
+BuildRequires: pkgconfig(libdnssec) >= 2.7.2
+BuildRequires: pkgconfig(libsystemd)
+BuildRequires: pkgconfig(libuv)
+BuildRequires: pkgconfig(luajit) >= 2.0
+BuildRequires: pkgconfig(systemd)
+
+# Distro-dependent dependencies
+%if 0%{?rhel}
+BuildRequires: lmdb-devel
+# Lua 5.1 version of the libraries have different package names
+Requires: lua-socket
+Requires: lua-sec
+Requires(pre): shadow-utils
+%endif
+%if 0%{?fedora}
+BuildRequires: pkgconfig(lmdb)
+BuildRequires: python3-sphinx
+Requires: lua-socket-compat
+Requires: lua-sec-compat
+Requires(pre): shadow-utils
+%endif
+%if 0%{?suse_version}
+BuildRequires: lmdb-devel
+BuildRequires: python3-Sphinx
+Requires: lua51-luasocket
+Requires: lua51-luasec
+Requires(pre): shadow
+%endif
+
+%if "x%{?rhel}" == "x"
+# dependencies for doc package; disable in EPEL (missing fonts)
+# https://bugzilla.redhat.com/show_bug.cgi?id=1492884
+BuildRequires: doxygen
+BuildRequires: python3-breathe
+BuildRequires: python3-sphinx_rtd_theme
+%endif
+
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+
+%description
+The Knot Resolver is a caching full resolver implementation written in C
+and LuaJIT, including both a resolver library and a daemon. Modular
+architecture of the library keeps the core tiny and efficient, and provides
+a state-machine like API for extensions.
+
+The package is pre-configured as local caching resolver.
+To start using it, start a single kresd instance:
+$ systemctl start kresd@1.service
+
+%package devel
+Summary: Development headers for Knot Resolver
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%description devel
+The package contains development headers for Knot Resolver.
+
+%if "x%{?rhel}" == "x"
+%package doc
+Summary: Documentation for Knot Resolver
+BuildArch: noarch
+Requires: %{name} = %{version}-%{release}
+
+%description doc
+Documentation for Knot Resolver
+%endif
+
+%prep
+%if 0%{GPG_CHECK}
+export GNUPGHOME=./gpg-keyring
+mkdir ${GNUPGHOME}
+gpg2 --import %{SOURCE100} %{SOURCE101} %{SOURCE102}
+gpg2 --verify %{SOURCE1} %{SOURCE0}
+%endif
+%setup -q -n %{name}-%{version}
+
+%build
+%global build_paths PREFIX=%{_prefix} BINDIR=%{_bindir} LIBDIR=%{_libdir} INCLUDEDIR=%{_includedir} ETCDIR=%{_sysconfdir}/knot-resolver
+%global build_flags V=1 CFLAGS="%{optflags}" LDFLAGS="%{?__global_ldflags}" %{build_paths} HAS_go=no
+%make_build %{build_flags}
+
+%if "x%{?rhel}" == "x"
+# build documentation
+make doc
+%endif
+
+%check
+make %{?_smp_mflags} check
+
+%install
+%make_install %{build_flags}
+
+# move sample configuration files to documentation
+install -m 0755 -d %{buildroot}%{_pkgdocdir}
+mv %{buildroot}%{_sysconfdir}/knot-resolver/config.* %{buildroot}%{_pkgdocdir}
+chmod 0644 %{buildroot}%{_pkgdocdir}/config.*
+
+# install configuration files
+mkdir -p %{buildroot}%{_sysconfdir}
+install -m 0755 -d %{buildroot}%{_sysconfdir}/knot-resolver
+install -m 0644 -p %{repodir}/distro/common/kresd.conf %{buildroot}%{_sysconfdir}/knot-resolver/kresd.conf
+install -m 0664 -p %{repodir}/distro/common/root.keys %{buildroot}%{_sysconfdir}/knot-resolver/root.keys
+
+# install systemd units and doc
+mkdir -p %{buildroot}%{_unitdir}
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd@.service %{buildroot}%{_unitdir}/kresd@.service
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd.target %{buildroot}%{_unitdir}/kresd.target
+install -m 0755 -d %{buildroot}%{_unitdir}/multi-user.target.wants
+ln -s ../kresd.target %{buildroot}%{_unitdir}/multi-user.target.wants/kresd.target
+mkdir -p %{buildroot}%{_mandir}/man7
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd.systemd.7 %{buildroot}%{_mandir}/man7/kresd.systemd.7
+
+%if 0%{?rhel}
+# no socket activation for CentOS 7 (requires systemd.227)
+mkdir -p %{buildroot}%{_unitdir}/kresd@.service.d
+install -m 0644 -p %{repodir}/distro/common/systemd/drop-in/systemd-compat.conf %{buildroot}%{_unitdir}/kresd@.service.d/override.conf
+%endif
+%if "x%{?rhel}" == "x"
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd.socket %{buildroot}%{_unitdir}/kresd.socket
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd-control@.socket %{buildroot}%{_unitdir}/kresd-control@.socket
+install -m 0644 -p %{repodir}/distro/common/systemd/kresd-tls.socket %{buildroot}%{_unitdir}/kresd-tls.socket
+%endif
+
+# install tmpfiles.d
+mkdir -p %{buildroot}%{_tmpfilesdir}
+install -m 0644 -p %{repodir}/distro/common/tmpfiles/knot-resolver.conf %{buildroot}%{_tmpfilesdir}/knot-resolver.conf
+mkdir -p %{buildroot}%{_rundir}
+install -m 0750 -d %{buildroot}%{_rundir}/knot-resolver
+
+# install cache
+mkdir -p %{buildroot}%{_localstatedir}/cache
+install -m 0750 -d %{buildroot}%{_localstatedir}/cache/knot-resolver
+
+# remove module with unsatisfied dependencies
+rm -r %{buildroot}%{_libdir}/kdns_modules/{http,http.lua}
+
+%pre
+getent group knot-resolver >/dev/null || groupadd -r knot-resolver
+getent passwd knot-resolver >/dev/null || useradd -r -g knot-resolver -d %{_sysconfdir}/knot-resolver -s /sbin/nologin -c "Knot Resolver" knot-resolver
+
+%post
+%systemd_post 'kresd@*.service'
+/sbin/ldconfig
+
+%preun
+%systemd_preun 'kresd@*.service' kresd.target kresd.socket kresd-tls.socket
+
+%postun
+# NOTE: this doesn't restart the services on CentOS 7
+%systemd_postun_with_restart 'kresd@*.service'
+/sbin/ldconfig
+
+%files
+%license COPYING
+%doc %{_pkgdocdir}
+%attr(775,root,knot-resolver) %dir %{_sysconfdir}/knot-resolver
+%attr(644,root,knot-resolver) %config(noreplace) %{_sysconfdir}/knot-resolver/kresd.conf
+%attr(664,root,knot-resolver) %config(noreplace) %{_sysconfdir}/knot-resolver/root.keys
+%attr(644,root,knot-resolver) %config(noreplace) %{_sysconfdir}/knot-resolver/root.hints
+%attr(644,root,knot-resolver) %config(noreplace) %{_sysconfdir}/knot-resolver/icann-ca.pem
+%attr(750,knot-resolver,knot-resolver) %dir %{_localstatedir}/cache/knot-resolver
+%{_unitdir}/kresd*.service
+%{_unitdir}/kresd.target
+%{_unitdir}/multi-user.target.wants/kresd.target
+%if 0%{?rhel}
+%{_unitdir}/kresd@.service.d/override.conf
+%endif
+%if "x%{?rhel}" == "x"
+%{_unitdir}/kresd*.socket
+%endif
+%{_tmpfilesdir}/knot-resolver.conf
+%{_sbindir}/kresd
+%{_sbindir}/kresc
+%{_libdir}/libkres.so.*
+%{_libdir}/kdns_modules
+%{_mandir}/man8/kresd.8.gz
+%{_mandir}/man7/kresd.systemd.7.gz
+
+%files devel
+%{_includedir}/libkres
+%{_libdir}/pkgconfig/libkres.pc
+%{_libdir}/libkres.so
+
+%if "x%{?rhel}" == "x"
+%files doc
+%doc doc/html
+%endif
+
+%changelog
+* Fri Feb 16 2018 Tomas Krizek <tomas.krizek@nic.cz> - 2.1.0-1
+- see NEWS or https://www.knot-resolver.cz/
+- move spec file to upstream
diff --git a/distro/tests/README.md b/distro/tests/README.md
new file mode 100644
index 0000000..f528348
--- /dev/null
+++ b/distro/tests/README.md
@@ -0,0 +1,42 @@
+Requirements
+------------
+
+- ansible
+- vagrant
+- libvirt (+vagrant-libvirt) / virtualbox
+
+Usage
+-----
+
+`vagrant up` command is configured to trigger ansible provisioning
+which configures OBS repository, installs the knot-resolver package,
+starts the kresd@1 service and finally attempts to use it to resolve
+a domain name. It also tests that DNSSEC validation is turned on.
+
+By default, the *knot-resolver-devel* repo (for knot-resolver) along
+with *knot-resoler-latest* (for knot) is used. To test only the
+*knot-resolver-latest* repo, set it in `repos.yaml` (or use the
+test-distro.sh script which overwrites this file). If you're running
+tests in parallel, they all HAVE TO use the same repo(s).
+
+Run the following command for every distro (aka directory with
+Vagrantfile):
+
+```
+./test-distro.sh devel debian9
+```
+
+or
+
+```
+./test-distro.sh testing debian9
+```
+
+or
+
+```
+./test-distro.sh latest debian9
+```
+
+At the end of the test, the package version that was tested is
+printed out. Make sure you're testing what you intended to.
diff --git a/distro/tests/arch/Vagrantfile b/distro/tests/arch/Vagrantfile
new file mode 100644
index 0000000..8e3677e
--- /dev/null
+++ b/distro/tests/arch/Vagrantfile
@@ -0,0 +1,16 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "archlinux/archlinux"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "arch_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ end
+ end
+
+end
diff --git a/distro/tests/centos7/Vagrantfile b/distro/tests/centos7/Vagrantfile
new file mode 100644
index 0000000..a03e599
--- /dev/null
+++ b/distro/tests/centos7/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "centos/7"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "centos7_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python2"
+ }
+ end
+ end
+
+end
diff --git a/distro/tests/debian9/Vagrantfile b/distro/tests/debian9/Vagrantfile
new file mode 100644
index 0000000..3b7891b
--- /dev/null
+++ b/distro/tests/debian9/Vagrantfile
@@ -0,0 +1,16 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "debian/stretch64"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "debian9_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ end
+ end
+
+end
diff --git a/distro/tests/fedora28/Vagrantfile b/distro/tests/fedora28/Vagrantfile
new file mode 100644
index 0000000..0171b4f
--- /dev/null
+++ b/distro/tests/fedora28/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "generic/fedora28"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "fedora28_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python3"
+ }
+ end
+ end
+
+end
diff --git a/distro/tests/fedora29/Vagrantfile b/distro/tests/fedora29/Vagrantfile
new file mode 100644
index 0000000..67407e8
--- /dev/null
+++ b/distro/tests/fedora29/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "generic/fedora29"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "fedora29_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python3"
+ }
+ end
+ end
+
+end
diff --git a/distro/tests/knot-resolver-test.yaml b/distro/tests/knot-resolver-test.yaml
new file mode 100644
index 0000000..33d07aa
--- /dev/null
+++ b/distro/tests/knot-resolver-test.yaml
@@ -0,0 +1,148 @@
+---
+- hosts: all
+
+ remote_user: root
+ become: true
+
+ vars:
+ dig_package:
+ Debian: dnsutils
+ Ubuntu: dnsutils
+ Fedora: bind-utils
+ CentOS: bind-utils
+ openSUSE Leap: bind-utils
+ openSUSE Tumbleweed: bind-utils
+ Archlinux: bind-tools
+ configure_obs_repo:
+ Fedora: |
+ dnf config-manager --add-repo https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/Fedora_{{ ansible_distribution_major_version }}/home:CZ-NIC:{{ item }}.repo
+ CentOS: |
+ yum install -y wget &&
+ wget -i wget https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/CentOS_7_EPEL/home:CZ-NIC:{{ item }}.repo -O /etc/yum.repos.d/home:CZ-NIC:{{ item }}.repo
+ Debian: |
+ echo 'deb http://download.opensuse.org/repositories/home:/CZ-NIC:/{{ item }}/Debian_9.0/ /' > /etc/apt/sources.list.d/{{ item }}.list &&
+ wget -nv https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/Debian_9.0/Release.key -O Release.key &&
+ apt-key add - < Release.key &&
+ apt-get update
+ Ubuntu: |
+ echo 'deb http://download.opensuse.org/repositories/home:/CZ-NIC:/{{ item }}/xUbuntu_{{ ansible_distribution_version }}/ /' > /etc/apt/sources.list.d/{{ item }}.list &&
+ wget -nv https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/xUbuntu_{{ ansible_distribution_version }}/Release.key -O Release.key &&
+ apt-key add - < Release.key &&
+ apt-get update
+ openSUSE Tumbleweed: |
+ zypper addrepo https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/openSUSE_Tumbleweed/home:CZ-NIC:{{ item }}.repo &&
+ zypper --gpg-auto-import-keys refresh
+ openSUSE Leap: |
+ zypper addrepo https://download.opensuse.org/repositories/home:CZ-NIC:{{ item }}/openSUSE_Leap_15.0/home:CZ-NIC:{{ item }}.repo &&
+ zypper --gpg-auto-import-keys refresh
+ show_package_version:
+ Archlinux:
+ pacman -Qi knot-resolver | grep '^Version'
+ Fedora: &pkg_version_rpm |
+ rpm -qi knot-resolver | grep '^Version'
+ CentOS: *pkg_version_rpm
+ openSUSE Leap: *pkg_version_rpm
+ openSUSE Tumbleweed: *pkg_version_rpm
+ Debian:
+ dpkg -s knot-resolver | grep '^Version'
+ Ubuntu: |
+ dpkg -s knot-resolver | grep '^Version'
+ vars_files:
+ - repos.yaml
+
+ gather_facts: false
+ pre_tasks:
+ - name: install python3 (Arch)
+ raw: |
+ (pacman-key --init && pacman-key --populate archlinux && \
+ pacman -Sy python3 --noconfirm) || :
+ ignore_errors: true
+ - name: gather facts
+ setup:
+
+ tasks:
+ - name: install epel
+ package:
+ name: epel-release
+ state: present
+ when: ansible_distribution == 'CentOS'
+
+ - name: configure OBS repository
+ shell: "{{ configure_obs_repo[ansible_distribution] }}"
+ args:
+ warn: false
+ with_items: "{{ repos }}"
+ when: ansible_distribution_file_variety != 'Archlinux'
+
+ - block:
+ - name: configure OBS repository (Arch)
+ blockinfile:
+ block: |
+ [home_CZ-NIC_{{ item }}_Arch]
+ SigLevel = Never
+ Server = https://download.opensuse.org/repositories/home:/CZ-NIC:/{{ item }}/Arch/$arch
+ insertbefore: '^\[core\]'
+ path: /etc/pacman.conf
+ state: present
+ with_items: "{{ repos }}"
+ - name: set up package mirrors
+ copy:
+ content: |
+ ## Arch Linux repository mirrorlist
+ ## Generated on 2018-12-10
+ ## Czechia
+ Server = http://mirrors.nic.cz/archlinux/$repo/os/$arch
+ Server = http://ftp.fi.muni.cz/pub/linux/arch/$repo/os/$arch
+ Server = http://ftp.sh.cvut.cz/arch/$repo/os/$arch
+ Server = http://gluttony.sin.cvut.cz/arch/$repo/os/$arch
+ dest: /etc/pacman.d/mirrorlist
+ - name: sync repos (Arch)
+ shell: pacman -Syu --noconfirm
+ args:
+ warn: false
+ when: ansible_distribution_file_variety == 'Archlinux'
+
+ - name: install knot-resolver
+ package:
+ name: knot-resolver
+ state: latest
+
+ - name: get installed package version
+ shell: "{{ show_package_version[ansible_distribution] }}"
+ args:
+ warn: false
+ register: package_version
+
+ - name: install dig
+ package:
+ name: "{{ dig_package[ansible_distribution] }}"
+ state: present
+
+ - name: testing block
+ block:
+ - name: start kresd@1.service
+ service:
+ name: kresd@1.service
+ state: restarted
+
+ - name: resolve nic.cz
+ shell: dig @127.0.0.1 nic.cz
+ register: res
+ failed_when: '"status: NOERROR" not in res.stdout'
+
+ - name: test dnssec is turned on
+ block:
+ - name: test dnssec-failed.org +cd returns NOERROR
+ shell: dig +cd @127.0.0.1 dnssec-failed.org
+ register: res
+ failed_when: '"status: NOERROR" not in res.stdout'
+
+ - name: test dnssec-failed.org returns SERVFAIL
+ shell: dig @127.0.0.1 dnssec-failed.org
+ register: res
+ failed_when: '"status: SERVFAIL" not in res.stdout'
+
+ always:
+ - name: show installed version
+ debug:
+ var: package_version.stdout
diff --git a/distro/tests/leap15/Vagrantfile b/distro/tests/leap15/Vagrantfile
new file mode 100644
index 0000000..14bae76
--- /dev/null
+++ b/distro/tests/leap15/Vagrantfile
@@ -0,0 +1,16 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "opensuse/openSUSE-15.0-x86_64"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "leap15_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ end
+ end
+
+end
diff --git a/distro/tests/repos.yaml b/distro/tests/repos.yaml
new file mode 100644
index 0000000..9827fe7
--- /dev/null
+++ b/distro/tests/repos.yaml
@@ -0,0 +1,3 @@
+repos:
+ - knot-resolver-latest
+ - knot-resolver-devel
diff --git a/distro/tests/test-distro.sh b/distro/tests/test-distro.sh
new file mode 100755
index 0000000..0ae8662
--- /dev/null
+++ b/distro/tests/test-distro.sh
@@ -0,0 +1,32 @@
+#!/bin/bash -x
+
+# ./test-distro.sh {devel|latest} {distro}
+# Example usage: ./test-distro.sh devel debian9
+
+distro=$2
+repo=$1
+
+# Select repos
+echo -e 'repos:\n - knot-resolver-latest' > repos.yaml # latest is needed for knot
+case "$repo" in
+ devel)
+ echo -e ' - knot-resolver-devel' >> repos.yaml
+ ;;
+ testing)
+ echo -e 'repos:\n - knot-resolver-testing' > repos.yaml
+ ;;
+ latest)
+ ;;
+ *)
+ echo "Unknown repo, choose devel|latest|testing"
+ exit 1
+ ;;
+esac
+
+cd "$distro"
+vagrant destroy -f &>/dev/null
+vagrant up
+ret=$?
+vagrant destroy -f &>/dev/null
+exit $ret
+
diff --git a/distro/tests/tumbleweed/Vagrantfile b/distro/tests/tumbleweed/Vagrantfile
new file mode 100644
index 0000000..ba0dada
--- /dev/null
+++ b/distro/tests/tumbleweed/Vagrantfile
@@ -0,0 +1,16 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "opensuse/openSUSE-Tumbleweed-x86_64"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "tumbleweed_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ end
+ end
+
+end
diff --git a/distro/tests/ubuntu1604/Vagrantfile b/distro/tests/ubuntu1604/Vagrantfile
new file mode 100644
index 0000000..40e0492
--- /dev/null
+++ b/distro/tests/ubuntu1604/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "generic/ubuntu1604"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "ubuntu1604_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python3"
+ }
+ end
+ end
+
+end
diff --git a/distro/tests/ubuntu1804/Vagrantfile b/distro/tests/ubuntu1804/Vagrantfile
new file mode 100644
index 0000000..57e210d
--- /dev/null
+++ b/distro/tests/ubuntu1804/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "generic/ubuntu1804"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "ubuntu1804_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python3"
+ }
+ end
+ end
+
+end
diff --git a/distro/tests/ubuntu1810/Vagrantfile b/distro/tests/ubuntu1810/Vagrantfile
new file mode 100644
index 0000000..c560be1
--- /dev/null
+++ b/distro/tests/ubuntu1810/Vagrantfile
@@ -0,0 +1,19 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+
+Vagrant.configure(2) do |config|
+
+ config.vm.box = "generic/ubuntu1810"
+ config.vm.synced_folder ".", "/vagrant", disabled: true
+
+ config.vm.define "ubuntu1810_knot-resolver" do |machine|
+ machine.vm.provision "ansible" do |ansible|
+ ansible.playbook = "../knot-resolver-test.yaml"
+ ansible.extra_vars = {
+ ansible_python_interpreter: "/usr/bin/python3"
+ }
+ end
+ end
+
+end
diff --git a/doc/Doxyfile b/doc/Doxyfile
new file mode 100644
index 0000000..6e57cb3
--- /dev/null
+++ b/doc/Doxyfile
@@ -0,0 +1,19 @@
+PROJECT_NAME = Knot Resolver library
+GENERATE_HTML = NO
+GENERATE_XML = YES
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+GENERATE_RTF = NO
+CASE_SENSE_NAMES = NO
+INPUT = ../lib
+FILE_PATTERNS = *.h
+QUIET = YES
+RECURSIVE = YES
+JAVADOC_AUTOBRIEF = YES
+AUTOLINK_SUPPORT = YES
+XML_OUTPUT = doxyxml
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+OPTIMIZE_OUTPUT_FOR_C = YES
+ENABLE_PREPROCESSING = YES
+PREDEFINED = NDEBUG
diff --git a/doc/NEWS.rst b/doc/NEWS.rst
new file mode 100644
index 0000000..4eb8194
--- /dev/null
+++ b/doc/NEWS.rst
@@ -0,0 +1,6 @@
+*************
+Release notes
+*************
+
+.. include:: ../NEWS
+
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000..6860672
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,27 @@
+## Documentation
+
+Each directory contains a README.md with the basic information, examples and usage.
+It does not however contain API documentation, which is built separately in this directory.
+
+### Requirements
+
+The code is documented with [Doxygen][doxygen] JavaDoc style, a prettified documentation
+also requires [breathe][breathe] and [Sphinx][sphinx] for building sane documentation pages.
+It is not however required.
+
+[doxygen]:https://www.stack.nl/~dimitri/doxygen/manual/index.html
+[breathe]: https://github.com/michaeljones/breathe
+[sphinx]: http://sphinx-doc.org/
+
+You can get the extra dependencies with pip:
+
+```sh
+pip install -U Sphinx breathe
+# Alternatively
+pip -r doc/requirements.txt
+```
+
+### Building documentation
+
+If you satisfy the requirements, it's as easy as `make doc`, which builds the documentation in this folder.
+
diff --git a/doc/_static/.gitignore b/doc/_static/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/_static/.gitignore
diff --git a/doc/build.rst b/doc/build.rst
new file mode 100644
index 0000000..55667a4
--- /dev/null
+++ b/doc/build.rst
@@ -0,0 +1,321 @@
+Building project
+================
+
+Installing from packages
+------------------------
+
+The resolver is packaged for Debian, Fedora+EPEL, Ubuntu, Docker, NixOS/NixPkgs, FreeBSD, HomeBrew, and Turris Omnia.
+Some of these are maintained directly by the knot-resolver team.
+
+Refer to `project page <https://www.knot-resolver.cz/download>`_ for information about
+installing from packages. If packages are not available for your OS, see following sections
+to see how you can build it from sources (or package it), or use official `Docker images`_.
+
+Platform considerations
+-----------------------
+
+Knot-resolver is written for UNIX-like systems, mainly in C99.
+Portable I/O is provided by libuv_.
+Some 64-bit systems with LuaJIT 2.1 may be affected by
+`a problem <https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/status.html#L100>`_
+-- Linux on x86_64 is unaffected but `Linux on aarch64 is
+<https://gitlab.labs.nic.cz/knot/knot-resolver/issues/216>`_.
+
+Windows systems might theoretically work without large changes,
+but it's most likely broken and currently not planned to be supported.
+
+Requirements
+------------
+
+The following is a list of software required to build Knot Resolver from sources.
+
+.. csv-table::
+ :header: "Requirement", "Required by", "Notes"
+
+ "`GNU Make`_ 3.80+", "*all*", "*(build only)*"
+ "C and C++ compiler", "*all*", "*(build only)* [#]_"
+ "`pkg-config`_", "*all*", "*(build only)* [#]_"
+ "hexdump or xxd", "``daemon``", "*(build only)*"
+ "libknot_ 2.7.2+", "*all*", "Knot DNS libraries - requires autotools, GnuTLS, ..."
+ "LuaJIT_ 2.0+", "``daemon``", "Embedded scripting language."
+ "libuv_ 1.7+", "``daemon``", "Multiplatform I/O and services (libuv_ 1.0 with limitations [#]_)."
+ "lmdb", "``daemon``", "If missing, a static version is embedded."
+
+There are also *optional* packages that enable specific functionality in Knot Resolver, they are useful mainly for developers to build documentation and tests.
+
+.. csv-table::
+ :header: "Optional", "Needed for", "Notes"
+
+ "`lua-http`_", "``modules/http``", "HTTP/2 client/server for Lua."
+ "luasocket_", "``trust anchors, modules/stats``", "Sockets for Lua."
+ "luasec_", "``trust anchors``", "TLS for Lua."
+ "cmocka_", "``unit tests``", "Unit testing framework."
+ "Doxygen_", "``documentation``", "Generating API documentation."
+ "Sphinx_ and sphinx_rtd_theme_", "``documentation``", "Building this HTML/PDF documentation."
+ "breathe_", "``documentation``", "Exposing Doxygen API doc to Sphinx."
+ "libsystemd_", "``daemon``", "Systemd socket activation support."
+ "libprotobuf_ 3.0+", "``modules/dnstap``", "Protocol Buffers support for dnstap_."
+ "`libprotobuf-c`_ 1.0+", "``modules/dnstap``", "C bindings for Protobuf."
+ "libfstrm_ 0.2+", "``modules/dnstap``", "Frame Streams data transport protocol."
+ "luacheck_", "``lint-lua``", "Syntax and static analysis checker for Lua."
+ "`clang-tidy`_", "``lint-c``", "Syntax and static analysis checker for C."
+ "luacov_", "``check-config``", "Code coverage analysis for Lua modules."
+
+.. [#] Requires C99, ``__attribute__((cleanup))`` and ``-MMD -MP`` for dependency file generation. GCC, Clang and ICC are supported.
+.. [#] You can use variables ``<dependency>_CFLAGS`` and ``<dependency>_LIBS`` to configure dependencies manually (i.e. ``libknot_CFLAGS`` and ``libknot_LIBS``).
+.. [#] libuv 1.7 brings SO_REUSEPORT support that is needed for multiple forks. libuv < 1.7 can be still used, but only in single-process mode. Use :ref:`different method <daemon-reuseport>` for load balancing.
+
+Packaged dependencies
+~~~~~~~~~~~~~~~~~~~~~
+
+Most of the dependencies can be resolved from packages, here's an overview for several platforms.
+
+* **Debian** (since *sid*) - current stable doesn't have libknot and libuv, which must be installed from sources.
+
+.. code-block:: bash
+
+ sudo apt-get install pkg-config libknot-dev libuv1-dev libcmocka-dev libluajit-5.1-dev
+
+* **Ubuntu** - unknown.
+* **Fedora**
+
+.. code-block:: bash
+
+ # minimal build
+ sudo dnf install @buildsys-build knot-devel libuv-devel luajit-devel
+ # unit tests
+ sudo dnf install libcmocka-devel
+ # integration tests
+ sudo dnf install cmake git python-dns python-jinja2
+ # optional features
+ sudo dnf install lua-sec-compat lua-socket-compat systemd-devel
+ # docs
+ sudo dnf install doxygen python-breathe python-sphinx
+
+* **RHEL/CentOS** - unknown.
+* **openSUSE** - there is an `experimental package <https://build.opensuse.org/package/show/server:dns/knot-resolver>`_.
+* **FreeBSD** - when installing from ports, all dependencies will install automatically, corresponding to the selected options.
+* **NetBSD** - unknown.
+* **OpenBSD** - unknown.
+* **Mac OS X** - the dependencies can be found through `Homebrew <http://brew.sh/>`_.
+
+.. code-block:: bash
+
+ brew install pkg-config libuv luajit cmocka
+
+Building from sources
+---------------------
+
+Initialize git submodules first.
+
+.. code-block:: bash
+
+ $ git submodule update --init --recursive
+
+The Knot Resolver depends on the the Knot DNS library, recent version of libuv_, and LuaJIT_.
+
+.. code-block:: bash
+
+ $ make info # See what's missing
+
+When you have all the dependencies ready, you can build and install.
+
+.. code-block:: bash
+
+ $ make PREFIX="/usr/local"
+ $ make install PREFIX="/usr/local"
+
+.. note:: Always build with ``PREFIX`` if you want to install, as it is hardcoded in the executable for module search path.
+ Production code should be compiled with ``-DNDEBUG``.
+ If you build the binary with ``-DNOVERBOSELOG``, it won't be possible to turn on verbose logging; we advise packagers against using that flag.
+
+.. note:: If you build with ``PREFIX``, you may need to also set the ``LDFLAGS`` for the libraries:
+
+.. code-block:: bash
+
+ make LDFLAGS="-Wl,-rpath=/usr/local/lib" PREFIX="/usr/local"
+
+Alternatively you can build only specific parts of the project, i.e. ``library``.
+
+.. code-block:: bash
+
+ $ make lib
+ $ make lib-install
+
+.. note:: Documentation is not built by default, run ``make doc`` to build it.
+
+Building with security compiler flags
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Knot Resolver enables certain `security compile-time flags <https://wiki.debian.org/Hardening#Notes_on_Memory_Corruption_Mitigation_Methods>`_ that do not affect performance.
+You can add more flags to the build by appending them to `CFLAGS` variable, e.g. ``make CFLAGS="-fstack-protector"``.
+
+ .. csv-table::
+ :header: "Method", "Status", "Notes"
+
+ "-fstack-protector", "*disabled*", "(must be specifically enabled in CFLAGS)"
+ "-D_FORTIFY_SOURCE=2", "**enabled**", ""
+ "-pie", "**enabled**", "enables ASLR for kresd (disable with ``make HARDENING=no``)"
+ "RELRO", "**enabled**", "full [#]_"
+
+You can also disable linker hardening when it's unsupported with ``make HARDENING=no``.
+
+.. [#] See `checksec.sh <http://www.trapkit.de/tools/checksec.html>`_
+
+Building for packages
+~~~~~~~~~~~~~~~~~~~~~
+
+The build system supports DESTDIR_
+
+.. Our amalgamation has fallen into an unmaintained state and probably doesn't work.
+.. and `amalgamated builds <https://www.sqlite.org/amalgamation.html>`_.
+
+.. code-block:: bash
+
+ $ make install DESTDIR=/tmp/stage
+.. $ make all install AMALG=yes # Amalgamated build
+
+.. Amalgamated build assembles everything in one source file and compiles it. It is useful for packages, as the compiler sees the whole program and is able to produce a smaller and faster binary. On the other hand, it complicates debugging.
+
+.. tip:: There is a template for service file and AppArmor profile to help you kickstart the package.
+
+Default paths
+~~~~~~~~~~~~~
+
+The default installation follows FHS with several custom paths for configuration and modules.
+All paths are prefixed with ``PREFIX`` variable by default if not specified otherwise.
+
+ .. csv-table::
+ :header: "Component", "Variable", "Default", "Notes"
+
+ "library", "``LIBDIR``", "``$(PREFIX)/lib``", "pkg-config is auto-generated [#]_"
+ "daemon", "``SBINDIR``", "``$(PREFIX)/sbin``", ""
+ "configuration", "``ETCDIR``", "``$(PREFIX)/etc/knot-resolver``", "Configuration file, templates."
+ "modules", "``MODULEDIR``", "``$(LIBDIR)/kdns_modules``", "Runtime directory for loading dynamic modules [#]_."
+ "trust anchor file", "``KEYFILE_DEFAULT``", "*(none)*", "Path to read-only trust anchor file, which is used as fallback when no other file is specified. [#]_"
+ "work directory", "", "the current directory", "Run directory for daemon. (Only relevant during run time, not e.g. during installation.)"
+
+.. [#] The ``libkres.pc`` is installed in ``$(LIBDIR)/pkgconfig``.
+.. [#] The default moduledir can be changed with `-m` option to `kresd` daemon or by calling `moduledir()` function from lua.
+.. [#] If no other trust anchor is specified by user, the compiled-in path ``KEYFILE_DEFAULT`` must contain a valid trust anchor. This is typically used by distributions which provide DNSSEC root trust anchors as part of distribution package. Users can disable the built-in trust anchor by adding ``trust_anchors.keyfile_default = nil`` to their configuration.
+
+.. note:: Each module is self-contained and may install additional bundled files within ``$(MODULEDIR)/$(modulename)``. These files should be read-only, non-executable.
+
+Static or dynamic?
+~~~~~~~~~~~~~~~~~~
+
+By default the resolver library is built as a dynamic library with versioned ABI. You can revert to static build with ``BUILDMODE`` variable.
+
+.. code-block:: bash
+
+ $ make BUILDMODE=dynamic # Default, create dynamic library
+ $ make BUILDMODE=static # Create static library
+
+When the library is linked statically, it usually produces a smaller binary. However linking it to various C modules might violate ODR and increase the size.
+
+Resolving dependencies
+~~~~~~~~~~~~~~~~~~~~~~
+
+The build system relies on `pkg-config`_ to find dependencies.
+You can override it to force custom versions of the software by environment variables.
+
+.. code-block:: bash
+
+ $ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -ldnssec"
+
+Optional dependencies may be disabled as well using ``HAS_x=yes|no`` variable.
+
+.. code-block:: bash
+
+ $ make HAS_go=no HAS_cmocka=no
+
+.. warning:: If the dependencies lie outside of library search path, you need to add them somehow.
+ Try ``LD_LIBRARY_PATH`` on Linux/BSD, and ``DYLD_FALLBACK_LIBRARY_PATH`` on OS X.
+ Otherwise you need to add the locations to linker search path.
+
+Building extras
+~~~~~~~~~~~~~~~
+
+The project can be built with code coverage tracking using the ``COVERAGE=1`` variable.
+
+The `make coverage` target gathers both gcov code coverage for C files, and luacov_ code coverage for Lua files and merges it for analysis. It requires lcov_ to be installed.
+
+.. code-block:: bash
+
+ $ make coverage
+
+Running unit and integration tests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The linter requires luacheck_ and `clang-tidy`_ and is executed by ``make lint``.
+The unit tests require cmocka_ and are executed by ``make check``.
+Tests for the dnstap module need go and are executed by ``make ckeck-dnstap``.
+
+The integration tests use Deckard, the `DNS test harness <deckard>`_.
+
+.. code-block:: bash
+
+ $ make check-integration
+
+Note that the daemon and modules must be installed first before running integration tests, the reason is that the daemon
+is otherwise unable to find and load modules.
+
+Read the `documentation <deckard_doc>`_ for more information about requirements, how to run it and extend it.
+
+Getting Docker image
+--------------------
+
+Docker images require only either Linux or a Linux VM (see boot2docker_ on OS X).
+
+.. code-block:: bash
+
+ $ docker run cznic/knot-resolver
+
+See the `Docker images`_ page for more information and options.
+You can hack on the container by changing the container entrypoint to shell like:
+
+.. code-block:: bash
+
+ $ docker run -it --entrypoint=/bin/bash cznic/knot-resolver
+
+.. tip:: You can build the Docker image yourself with ``docker build -t knot-resolver scripts``.
+
+.. _Docker images: https://hub.docker.com/r/cznic/knot-resolver
+.. _libuv: https://github.com/libuv/libuv
+.. _MSVC: https://msdn.microsoft.com/en-us/vstudio/hh386302.aspx
+.. _MinGW: http://www.mingw.org/
+.. _Dockerfile: https://registry.hub.docker.com/u/cznic/knot-resolver/dockerfile/
+
+.. _Lua: https://www.lua.org/about.html
+.. _LuaJIT: http://luajit.org/luajit.html
+.. _Go: https://golang.org
+.. _geoip: https://github.com/abh/geoip
+.. _Doxygen: https://www.stack.nl/~dimitri/doxygen/manual/index.html
+.. _breathe: https://github.com/michaeljones/breathe
+.. _Sphinx: http://sphinx-doc.org/
+.. _sphinx_rtd_theme: https://pypi.python.org/pypi/sphinx_rtd_theme
+.. _GNU Make: https://www.gnu.org/software/make/
+.. _pkg-config: https://www.freedesktop.org/wiki/Software/pkg-config/
+.. _libknot: https://gitlab.labs.nic.cz/knot/knot-dns
+.. _cmocka: https://cmocka.org/
+.. _Python: https://www.python.org/
+.. _luasec: https://luarocks.org/modules/brunoos/luasec
+.. _luasocket: https://luarocks.org/modules/luarocks/luasocket
+.. _lua-http: https://luarocks.org/modules/daurnimator/http
+
+.. _boot2docker: http://boot2docker.io/
+
+.. _deckard: https://gitlab.labs.nic.cz/knot/deckard
+.. _deckard_doc: https://gitlab.labs.nic.cz/knot/knot-resolver/blob/master/tests/README.rst
+
+.. _libsystemd: https://www.freedesktop.org/wiki/Software/systemd/
+.. _dnstap: http://dnstap.info/
+.. _libprotobuf: https://developers.google.com/protocol-buffers/
+.. _libprotobuf-c: https://github.com/protobuf-c/protobuf-c/wiki
+.. _libfstrm: https://github.com/farsightsec/fstrm
+.. _luacheck: http://luacheck.readthedocs.io
+.. _clang-tidy: http://clang.llvm.org/extra/clang-tidy/index.html
+.. _luacov: https://keplerproject.github.io/luacov/
+.. _lcov: http://ltp.sourceforge.net/coverage/lcov.php
+
+.. _DESTDIR: https://www.gnu.org/prep/standards/html_node/DESTDIR.html
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..dc7411d
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+import sys, os, re, subprocess
+
+import sphinx_rtd_theme
+
+# -- General configuration -----------------------------------------------------
+
+if os.environ.get('READTHEDOCS', None) == 'True':
+ subprocess.call('doxygen')
+
+# Add any Sphinx extension module names here, as strings.
+extensions = ['sphinx.ext.todo', 'sphinx.ext.viewcode', 'breathe']
+
+# Breathe configuration
+breathe_projects = { "libkres": "doxyxml" }
+breathe_default_project = "libkres"
+breathe_domain_by_extension = {"h" : "c"}
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+master_doc = 'index'
+
+# General information about the project.
+project = u'Knot Resolver'
+copyright = u'2014-2018 CZ.NIC labs'
+version = { k[0][0]: k[0][1] for k in filter(None, [re.findall(r'(MAJOR|MINOR|PATCH) := ([0-9]+)',line) for line in open('../config.mk')])}
+version = '%s.%s.%s' % (version['MAJOR'], version['MINOR'], version['PATCH'])
+release = version
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+highlight_language = 'c'
+primary_domain = 'c'
+
+# -- Options for HTML output ---------------------------------------------------
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'apidoc'
+
+# Theme
+html_theme = 'sphinx_rtd_theme'
+html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'format.tex', u'Knot Resolver',
+ u'CZ.NIC Labs', 'manual'),
+]
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'libkres', u'libkres documentation',
+ [u'CZ.NIC Labs'], 1)
+]
+
diff --git a/doc/daemon.rst b/doc/daemon.rst
new file mode 100644
index 0000000..dbeecab
--- /dev/null
+++ b/doc/daemon.rst
@@ -0,0 +1 @@
+.. include:: ../daemon/README.rst \ No newline at end of file
diff --git a/doc/doc.mk b/doc/doc.mk
new file mode 100644
index 0000000..58c299e
--- /dev/null
+++ b/doc/doc.mk
@@ -0,0 +1,14 @@
+ifeq ($(HAS_doxygen)|$(HAS_sphinx-build), yes|yes)
+doc-doxygen:
+ @cd doc && $(doxygen_BIN)
+doc-html: doc-doxygen
+ @cd doc && $(sphinx-build_BIN) $(SPHINXFLAGS) -b html . html
+else
+doc-html:
+ $(error doxygen and sphinx must be installed)
+endif
+doc-clean:
+ rm -rf doc/doxyxml doc/*.db doc/html
+
+.PHONY: doc-doxygen doc-html doc-clean
+
diff --git a/doc/index.rst b/doc/index.rst
new file mode 100644
index 0000000..683c77c
--- /dev/null
+++ b/doc/index.rst
@@ -0,0 +1,26 @@
+#############
+Knot Resolver
+#############
+
+Knot Resolver is a minimalistic implementation of a caching validating DNS resolver.
+Modular architecture keeps the core tiny and efficient,
+and it provides a state-machine like API for extensions.
+
+.. toctree::
+ :maxdepth: 2
+
+ daemon
+ modules
+ build
+ lib
+ modules_api
+ NEWS
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/doc/kresd.8.in b/doc/kresd.8.in
new file mode 100644
index 0000000..0fa8cc9
--- /dev/null
+++ b/doc/kresd.8.in
@@ -0,0 +1,172 @@
+.TH "kresd" "8" "@DATE@" "CZ.NIC" "Knot Resolver @VERSION@"
+.\"
+.\" kresd.8 -- kresd daemon manpage
+.\"
+.\" Copyright (c) 2016, CZ.NIC. All rights reserved.
+.\"
+.\" See COPYING for the license.
+.\"
+.\"
+.SH "NAME"
+.B kresd
+\- Knot @VERSION@ full caching resolver.
+.SH "SYNOPSIS"
+.B kresd
+.RB [ \-a | \-\-addr
+.IR addr[@port] ]
+.RB [ \-t | \-\-tls
+.IR addr[@port] ]
+.RB [ \-S | \-\-fd
+.IR fd ]
+.RB [ \-T | \-\-tlsfd
+.IR fd ]
+.RB [ \-c | \-\-config
+.IR config ]
+.RB [ \-k | \-\-keyfile
+.IR keyfile ]
+.RB [ \-K | \-\-keyfile\-ro
+.IR keyfile ]
+.RB [ \-m | \-\-moduledir
+.IR path ]
+.RB [ \-f | \-\-forks
+.IR N ]
+.RB [ \-q | \-\-quiet ]
+.RB [ \-v | \-\-verbose ]
+.RB [ \-V | \-\-version ]
+.RB [ \-h | \-\-help ]
+.IR [rundir]
+.SH "DESCRIPTION"
+.B Knot Resolver is a DNSSEC-enabled full caching resolver.
+.P
+Default mode of operation: when it receives a DNS query it iteratively
+asks authoritative nameservers starting from root zone (.) and ending
+with a nameservers authoritative for queried name. Automatic DNSSEC means
+verification of integrity of authoritative responses by following
+keys and signatures starting from root. Root trust anchor is automatically
+bootstrapped from IANA, or you can provide a file with root trust anchors
+(same format as Unbound or BIND9 root keys file).
+
+The daemon also caches intermediate answers into cache, which by default
+uses LMDB memory-mapped database. This has a significant advantage over
+in-memory caches as the process may be stopped and restarted without
+loss of cache entries. In multi-user scenario a shared cache
+is potential privacy/security issue, with kresd each user can have resolver cache
+in their private directory and use it in similar fashion to keychain.
+
+By default, no configuration is needed, only a directory where the daemon can store
+runtime data (cache, control sockets, ...)
+.P
+To use a locally running
+.B kresd
+for resolving put
+.sp
+.RS 6n
+nameserver 127.0.0.1
+.RE
+.sp
+into
+.IR resolv.conf (5)
+and start
+.B kresd
+.PP
+.nf
+.RS 6n
+$ kresd -a 127.0.0.1 -k root.keys
+[system] interactive mode
+>
+.RE
+.fi
+.PP
+.P
+The daemon may be configured also as a plain forwarder using query policies, that requires
+creating a file
+.B config
+in daemon runtime directory. See \fIdaemon/README.md\fR for more information about interacting
+with CLI and configuration file options, or visit
+.B https://knot-resolver.readthedocs.io
+online documentation.
+.PP
+.nf
+.RS 6n
+# Create a basic forwarder configuration
+$ cat << EOF > config
+modules = { 'policy' }
+policy.add(policy.all(policy.FORWARD('192.168.1.1')))
+$ kresd -a 127.0.0.1 -k root.keys
+EOF
+.RE
+.fi
+.PP
+.P
+The available CLI options are:
+.TP
+.B \-a\fI addr[@port]\fR, \fB\-\-addr=\fI<addr[@port]>
+Listen on given address (and port) pair. If no port is given, \fI53\fR is used as a default.
+Option may be passed multiple times to listen on more addresses.
+.TP
+.B \-t\fI addr[@port]\fR, \fB\-\-tls=\fI<addr[@port]>
+Listen using TLS on given address (and port) pair. If no port is
+given, \fI853\fR is used as a default. Option may be passed multiple
+times to listen on more addresses.
+.TP
+.B \-S\fI fd\fR, \fB\-\-fd=\fI<fd>
+Listen on given file descriptor(s), passed by supervisor.
+Option may be passed multiple times to listen on more file descriptors.
+.TP
+.B \-T\fI fd\fR, \-\-tlsfd=\fI<fd>
+Listen using TLS on given file descriptor(s), passed by supervisor.
+Option may be passed multiple times to listen on more file descriptors.
+.TP
+.B \-c\fI config\fR, \fB\-\-config=\fI<config>
+Set the config file with settings for kresd to read instead of reading the
+file at the default location (\fIconfig\fR). The syntax is
+described in \fIdaemon/README.md\fR.
+.TP
+.B \-k\fI keyfile\fR, \fB\-\-keyfile=\fI<keyfile>
+(Recommended!) Automatically managed root trust anchors file.
+Root trust anchors in this file are managed using standard RFC 5011 (Automated Updates of DNS Security Trust Anchors).
+Kresd needs write access to the directory containing the keyfile.
+
+If the file does not exist, it will be automatically boostrapped from IANA using HTTPS protocol
+and warning that you need to to check the key before trusting it will be issued.
+
+The file contains DNSKEY/DS records in presentation format,
+and is compatible with Unbound and BIND 9 root key files.
+.TP
+.B \-K\fI keyfile\fR, \fB\-\-keyfile\-ro=\fI<keyfile>
+(Discouraged) Static root trust anchors file. The file is not updated by kresd. Use of this option is discouraged because it will break your installation when the trust anchor key changes!
+
+Default: "@KEYFILE_DEFAULT@" (can be empty if your distribution did not provide one)
+.TP
+.B \-m\fI path\fR, \fB\-\-moduledir=\fI<path>
+Override the directory that is searched for modules. Default: @MODULEDIR@
+.TP
+.B \-f\fI N\fR, \fB\-\-forks=\fI<N>
+With this option, the daemon is started in non-interactive mode and instead creates a
+UNIX socket in \fIrundir\fR that the operator can connect to for interactive session.
+A number greater than 1 forks the daemon N times, all forks will bind to same addresses
+and the kernel will load-balance between them on Linux with \fISO_REUSEPORT\fR support.
+
+When socket-activated and supervised by systemd or the equivalent, kresd defaults to
+--forks=1, and must not be set to any other value. If you want multiple concurrent
+processes supervised in this way, they should be supervised independently (see
+\fBkresd.systemd(7)\fR).
+.TP
+.B \-q\fR, \fB\-\-quiet
+Daemon will refrain from printing the command prompt.
+.TP
+.B \-v\fR, \fB\-\-verbose
+Increase verbosity. If given multiple times, more information is logged.
+This is in addition to the verbosity (if any) from the config file.
+.TP
+.B \-h
+Show short commandline option help.
+.TP
+.B \-V
+Show the version.
+.SH "SEE ALSO"
+\fIkresd.systemd(7)\fR,
+\fIhttps://knot-resolver.readthedocs.io\fR
+.SH "AUTHORS"
+.B kresd
+developers are mentioned in the AUTHORS file in the distribution.
diff --git a/doc/lib.rst b/doc/lib.rst
new file mode 100644
index 0000000..6eeaa13
--- /dev/null
+++ b/doc/lib.rst
@@ -0,0 +1,58 @@
+.. _lib_index:
+
+.. include:: ../lib/README.rst
+
+API reference
+=============
+
+.. contents::
+ :depth: 1
+ :local:
+
+.. _lib_api_rplan:
+
+Name resolution
+---------------
+
+.. doxygenfile:: resolve.h
+ :project: libkres
+.. doxygenfile:: rplan.h
+ :project: libkres
+
+.. _lib_api_cache:
+
+Cache
+-----
+
+.. doxygenfile:: cache/api.h
+ :project: libkres
+
+.. _lib_api_nameservers:
+
+Nameservers
+-----------
+
+.. doxygenfile:: nsrep.h
+ :project: libkres
+.. doxygenfile:: zonecut.h
+ :project: libkres
+
+.. _lib_api_modules:
+
+Modules
+-------
+
+.. doxygenfile:: module.h
+ :project: libkres
+
+Utilities
+---------
+
+.. doxygenfile:: utils.h
+ :project: libkres
+.. doxygenfile:: defines.h
+ :project: libkres
+
+.. _lib_generics:
+
+.. include:: ../lib/generic/README.rst
diff --git a/doc/modules.rst b/doc/modules.rst
new file mode 100644
index 0000000..ce65940
--- /dev/null
+++ b/doc/modules.rst
@@ -0,0 +1,37 @@
+.. _modules-implemented:
+
+*********************
+Knot Resolver modules
+*********************
+
+.. contents::
+ :depth: 1
+ :local:
+
+.. include:: ../modules/hints/README.rst
+.. include:: ../modules/stats/README.rst
+.. include:: ../modules/policy/README.rst
+.. include:: ../modules/view/README.rst
+.. include:: ../modules/predict/README.rst
+.. include:: ../modules/http/README.rst
+.. include:: ../modules/daf/README.rst
+.. include:: ../modules/rebinding/README.rst
+.. include:: ../modules/graphite/README.rst
+.. include:: ../modules/etcd/README.rst
+.. include:: ../modules/dns64/README.rst
+.. include:: ../modules/renumber/README.rst
+.. .. include:: ../modules/cookies/README.rst
+.. include:: ../modules/bogus_log/README.rst
+.. include:: ../modules/nsid/README.rst
+.. include:: ../modules/workarounds/README.rst
+.. include:: ../modules/dnstap/README.rst
+.. include:: ../modules/ta_signal_query/README.rst
+.. include:: ../modules/ta_sentinel/README.rst
+.. include:: ../modules/priming/README.rst
+.. include:: ../modules/detect_time_skew/README.rst
+.. include:: ../modules/detect_time_jump/README.rst
+.. include:: ../modules/rfc7706.rst
+.. include:: ../modules/prefill/README.rst
+.. include:: ../modules/serve_stale/README.rst
+.. include:: ../modules/edns_keepalive/README.rst
+.. include:: ../modules/experimental_dot_auth/README.rst
diff --git a/doc/modules_api.rst b/doc/modules_api.rst
new file mode 100644
index 0000000..2f0f147
--- /dev/null
+++ b/doc/modules_api.rst
@@ -0,0 +1 @@
+.. include:: ../modules/README.rst \ No newline at end of file
diff --git a/doc/requirements.txt b/doc/requirements.txt
new file mode 100644
index 0000000..7f36028
--- /dev/null
+++ b/doc/requirements.txt
@@ -0,0 +1,2 @@
+Sphinx
+breathe
diff --git a/doc/resolution.png b/doc/resolution.png
new file mode 100644
index 0000000..65d5027
--- /dev/null
+++ b/doc/resolution.png
Binary files differ
diff --git a/etc/config.cluster b/etc/config.cluster
new file mode 100644
index 0000000..8647587
--- /dev/null
+++ b/etc/config.cluster
@@ -0,0 +1,40 @@
+-- Config file example useable for larger resolver farms
+-- In this case cache should be made as large as possible, and prefetching turned off
+-- as the resolver is busy most of the time.
+-- Alternative is using `etcd` as a configuration backend.
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+
+-- Listen on localhost and external interface
+net = { '127.0.0.1', '::1', '192.168.1.1' }
+
+-- Drop root privileges
+user('knot-resolver', 'knot-resolver')
+
+-- Auto-maintain root TA
+trust_anchors.file = 'root.keys'
+
+-- Large cache size, so we don't need to flush ever
+-- This can be larger than available RAM, least frequently accessed
+-- records will be paged out as long as there's enough disk space to back it
+cache.size = 100 * GB
+
+-- Load Useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ graphite = { -- Send statistics to local InfluxDB
+ -- `worker.id` allows us to keep per-fork statistics
+ prefix = hostname()..worker.id,
+ -- Address of the Graphite/InfluxDB server
+ host = '192.168.1.2',
+ },
+}
+
+-- Use local root server copy for performance reasons
+hints.root({
+ ['j.root-servers.net.'] = { '192.168.1.4', '2001:503:c27::2:30', '192.58.128.30' }
+})
+
+-- Apply RPZ for all clients, default rule is DENY
+policy.add(policy.rpz(policy.DENY, 'blacklist.rpz'))
+
diff --git a/etc/config.docker b/etc/config.docker
new file mode 100644
index 0000000..d239dba
--- /dev/null
+++ b/etc/config.docker
@@ -0,0 +1,39 @@
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+
+-- Listen on all interfaces (localhost would not work in Docker)
+net.listen('0.0.0.0')
+net.listen('0.0.0.0', 853, {tls=true})
+
+-- Auto-maintain root TA
+trust_anchors.file = '/etc/knot-resolver/root.keys'
+
+-- Load Useful modules
+modules = {
+ 'stats', -- Track internal statistics
+ -- Load HTTP module with defaults
+ http = {
+ host = '0.0.0.0',
+ port = 8053,
+ },
+}
+
+-- Smaller cache size
+cache.size = 10 * MB
+
+function print_help()
+ print('\nUsage\n'
+ .. '=====\n'
+ .. 'Run this container using command:\n'
+ .. '$ docker run -Pti cznic/knot-resolver\n'
+ .. '\n'
+ .. 'Docker will map ports 53, 853, and 8053 to some other numbers, see\n'
+ .. '$ docker ps\n'
+ .. '(column PORTS)\n'
+ .. '53 -> DNS protocol over UDP and TCP\n'
+ .. '853 -> DNS-over-TLS protocol\n'
+ .. '8053 -> web interface\n'
+ .. '\n'
+ .. 'For verbose logging enter following command to prompt below:\n'
+ .. 'verbose(true)\n')
+end
+print_help()
diff --git a/etc/config.isp b/etc/config.isp
new file mode 100644
index 0000000..27dc76e
--- /dev/null
+++ b/etc/config.isp
@@ -0,0 +1,36 @@
+-- Config file example useable for multi-user ISP resolver
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+
+-- Listen on localhost and external interface
+net = { '127.0.0.1', '::1', '192.168.1.1' }
+
+-- Drop root privileges
+user('knot-resolver', 'knot-resolver')
+
+-- Auto-maintain root TA
+trust_anchors.file = 'root.keys'
+
+-- Large cache size, so we don't need to flush often
+-- This can be larger than available RAM, least frequently accessed
+-- records will be paged out
+cache.size = 4 * GB
+
+-- Load Useful modules
+modules = {
+ 'view', -- Views for certain clients
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ graphite = { -- Send statistics to local InfluxDB
+ -- `worker.id` allows us to keep per-fork statistics
+ prefix = hostname()..worker.id,
+ -- Address of the Graphite/InfluxDB server
+ host = '192.168.1.2',
+ },
+}
+
+-- Block all `site.nl` for `10.0.0.0/24` subnet
+view:addr('10.0.0.0/24', policy.suffix(policy.DROP, {todname('site.nl')}))
+-- Force all clients from `192.168.2.0/24` to TCP
+view:addr('192.168.2.0/24', policy.all(policy.TC))
+-- Apply RPZ for all clients, default rule is DENY
+policy.add(policy.rpz(policy.DENY, 'blacklist.rpz'))
diff --git a/etc/config.personal b/etc/config.personal
new file mode 100644
index 0000000..74bdd0e
--- /dev/null
+++ b/etc/config.personal
@@ -0,0 +1,23 @@
+-- Config file example useable for personal resolver.
+-- The goal is to have a validating resolver with tiny memory footprint,
+-- while actively tracking and refreshing frequent records to lower user latency.
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+
+-- Listen on localhost (default)
+-- net = { '127.0.0.1', '::1' }
+
+-- Drop root privileges
+user('knot-resolver', 'knot-resolver')
+
+-- Auto-maintain root TA
+trust_anchors.file = 'root.keys'
+
+-- Load Useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ 'predict', -- Prefetch expiring/frequent records
+}
+
+-- Smaller cache size
+cache.size = 10 * MB
diff --git a/etc/config.splitview b/etc/config.splitview
new file mode 100644
index 0000000..fbd0140
--- /dev/null
+++ b/etc/config.splitview
@@ -0,0 +1,33 @@
+-- Config file with split-view for internal zone
+-- Refer to manual: https://knot-resolver.readthedocs.io/en/latest/daemon.html#configuration
+
+-- Listen on localhost and external interface
+net = { '127.0.0.1', '::1', '192.168.1.1' }
+
+-- Drop root privileges
+user('knot-resolver', 'knot-resolver')
+
+-- Auto-maintain root TA
+trust_anchors.file = 'root.keys'
+
+-- Load Useful modules
+modules = {
+ 'hints > iterate', -- Load /etc/hosts and allow custom root hints
+ 'stats', -- Track internal statistics
+ graphite = { -- Send statistics to local InfluxDB
+ -- `worker.id` allows us to keep per-fork statistics
+ prefix = hostname()..worker.id,
+ -- Address of the Graphite/InfluxDB server
+ host = '192.168.1.2',
+ },
+ -- Use DNS64 with specified NAT64 address
+ dns64 = 'fe80::21b:77ff:0:0',
+}
+
+-- Large cache size, so we don't need to flush often
+-- This can be larger than available RAM, least frequently accessed
+-- records will be paged out
+cache.size = 4 * GB
+
+-- Forward everything below `company.cz` to `192.168.1.3`
+policy.add(policy.suffix(policy.FORWARD('192.168.1.3'), {todname('company.cz')}))
diff --git a/etc/etc.mk b/etc/etc.mk
new file mode 100644
index 0000000..b42d30a
--- /dev/null
+++ b/etc/etc.mk
@@ -0,0 +1,16 @@
+etc_SOURCES := icann-ca.pem \
+ config.cluster \
+ config.isp \
+ config.personal \
+ config.splitview \
+ root.hints
+
+etc-install: $(DESTDIR)$(ETCDIR)
+ $(INSTALL) -m 0644 $(addprefix etc/,$(etc_SOURCES)) $(DESTDIR)$(ETCDIR)
+
+etc: etc/root.hints
+
+etc/root.hints:
+ wget -O $@ https://www.internic.net/domain/named.root
+
+.PHONY: etc-install
diff --git a/etc/icann-ca.pem b/etc/icann-ca.pem
new file mode 100644
index 0000000..0ae28d6
--- /dev/null
+++ b/etc/icann-ca.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
+ Validity
+ Not Before: Nov 10 00:00:00 2006 GMT
+ Not After : Nov 10 00:00:00 2031 GMT
+ Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:e2:3b:e1:11:72:de:a8:a4:d3:a3:57:aa:50:a2:
+ 8f:0b:77:90:c9:a2:a5:ee:12:ce:96:5b:01:09:20:
+ cc:01:93:a7:4e:30:b7:53:f7:43:c4:69:00:57:9d:
+ e2:8d:22:dd:87:06:40:00:81:09:ce:ce:1b:83:bf:
+ df:cd:3b:71:46:e2:d6:66:c7:05:b3:76:27:16:8f:
+ 7b:9e:1e:95:7d:ee:b7:48:a3:08:da:d6:af:7a:0c:
+ 39:06:65:7f:4a:5d:1f:bc:17:f8:ab:be:ee:28:d7:
+ 74:7f:7a:78:99:59:85:68:6e:5c:23:32:4b:bf:4e:
+ c0:e8:5a:6d:e3:70:bf:77:10:bf:fc:01:f6:85:d9:
+ a8:44:10:58:32:a9:75:18:d5:d1:a2:be:47:e2:27:
+ 6a:f4:9a:33:f8:49:08:60:8b:d4:5f:b4:3a:84:bf:
+ a1:aa:4a:4c:7d:3e:cf:4f:5f:6c:76:5e:a0:4b:37:
+ 91:9e:dc:22:e6:6d:ce:14:1a:8e:6a:cb:fe:cd:b3:
+ 14:64:17:c7:5b:29:9e:32:bf:f2:ee:fa:d3:0b:42:
+ d4:ab:b7:41:32:da:0c:d4:ef:f8:81:d5:bb:8d:58:
+ 3f:b5:1b:e8:49:28:a2:70:da:31:04:dd:f7:b2:16:
+ f2:4c:0a:4e:07:a8:ed:4a:3d:5e:b5:7f:a3:90:c3:
+ af:27
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+ X509v3 Authority Key Identifier:
+ keyid:03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+
+ Signature Algorithm: sha1WithRSAEncryption
+ cb:9c:37:aa:48:13:12:0a:fa:dd:44:9c:4f:52:b0:f4:df:ae:
+ 04:f5:79:79:08:a3:24:18:fc:4b:2b:84:c0:2d:b9:d5:c7:fe:
+ f4:c1:1f:58:cb:b8:6d:9c:7a:74:e7:98:29:ab:11:b5:e3:70:
+ a0:a1:cd:4c:88:99:93:8c:91:70:e2:ab:0f:1c:be:93:a9:ff:
+ 63:d5:e4:07:60:d3:a3:bf:9d:5b:09:f1:d5:8e:e3:53:f4:8e:
+ 63:fa:3f:a7:db:b4:66:df:62:66:d6:d1:6e:41:8d:f2:2d:b5:
+ ea:77:4a:9f:9d:58:e2:2b:59:c0:40:23:ed:2d:28:82:45:3e:
+ 79:54:92:26:98:e0:80:48:a8:37:ef:f0:d6:79:60:16:de:ac:
+ e8:0e:cd:6e:ac:44:17:38:2f:49:da:e1:45:3e:2a:b9:36:53:
+ cf:3a:50:06:f7:2e:e8:c4:57:49:6c:61:21:18:d5:04:ad:78:
+ 3c:2c:3a:80:6b:a7:eb:af:15:14:e9:d8:89:c1:b9:38:6c:e2:
+ 91:6c:8a:ff:64:b9:77:25:57:30:c0:1b:24:a3:e1:dc:e9:df:
+ 47:7c:b5:b4:24:08:05:30:ec:2d:bd:0b:bf:45:bf:50:b9:a9:
+ f3:eb:98:01:12:ad:c8:88:c6:98:34:5f:8d:0a:3c:c6:e9:d5:
+ 95:95:6d:de
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
diff --git a/etc/root.hints b/etc/root.hints
new file mode 100644
index 0000000..e4d8d99
--- /dev/null
+++ b/etc/root.hints
@@ -0,0 +1,92 @@
+; This file holds the information on root name servers needed to
+; initialize cache of Internet domain name servers
+; (e.g. reference this file in the "cache . <file>"
+; configuration file of BIND domain name servers).
+;
+; This file is made available by InterNIC
+; under anonymous FTP as
+; file /domain/named.cache
+; on server FTP.INTERNIC.NET
+; -OR- RS.INTERNIC.NET
+;
+; last update: October 24, 2017
+; related version of root zone: 2017102400
+;
+; FORMERLY NS.INTERNIC.NET
+;
+. 3600000 NS A.ROOT-SERVERS.NET.
+A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
+A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30
+;
+; FORMERLY NS1.ISI.EDU
+;
+. 3600000 NS B.ROOT-SERVERS.NET.
+B.ROOT-SERVERS.NET. 3600000 A 199.9.14.201
+B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:200::b
+;
+; FORMERLY C.PSI.NET
+;
+. 3600000 NS C.ROOT-SERVERS.NET.
+C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
+C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c
+;
+; FORMERLY TERP.UMD.EDU
+;
+. 3600000 NS D.ROOT-SERVERS.NET.
+D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13
+D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d
+;
+; FORMERLY NS.NASA.GOV
+;
+. 3600000 NS E.ROOT-SERVERS.NET.
+E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
+E.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:a8::e
+;
+; FORMERLY NS.ISC.ORG
+;
+. 3600000 NS F.ROOT-SERVERS.NET.
+F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
+F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f
+;
+; FORMERLY NS.NIC.DDN.MIL
+;
+. 3600000 NS G.ROOT-SERVERS.NET.
+G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
+G.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:12::d0d
+;
+; FORMERLY AOS.ARL.ARMY.MIL
+;
+. 3600000 NS H.ROOT-SERVERS.NET.
+H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53
+H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53
+;
+; FORMERLY NIC.NORDU.NET
+;
+. 3600000 NS I.ROOT-SERVERS.NET.
+I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
+I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53
+;
+; OPERATED BY VERISIGN, INC.
+;
+. 3600000 NS J.ROOT-SERVERS.NET.
+J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30
+J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30
+;
+; OPERATED BY RIPE NCC
+;
+. 3600000 NS K.ROOT-SERVERS.NET.
+K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
+K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1
+;
+; OPERATED BY ICANN
+;
+. 3600000 NS L.ROOT-SERVERS.NET.
+L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42
+L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9f::42
+;
+; OPERATED BY WIDE
+;
+. 3600000 NS M.ROOT-SERVERS.NET.
+M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
+M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35
+; End of file \ No newline at end of file
diff --git a/lib/README.rst b/lib/README.rst
new file mode 100644
index 0000000..2905676
--- /dev/null
+++ b/lib/README.rst
@@ -0,0 +1,314 @@
+*********************
+Knot Resolver library
+*********************
+
+Requirements
+============
+
+* libknot_ 2.0 (Knot DNS high-performance DNS library.)
+
+For users
+=========
+
+The library as described provides basic services for name resolution, which should cover the usage,
+examples are in the :ref:`resolve API <lib_api_rplan>` documentation.
+
+.. tip:: If you're migrating from ``getaddrinfo()``, see *"synchronous"* API, but the library offers iterative API as well to plug it into your event loop for example.
+
+.. _lib-layers:
+
+For developers
+==============
+
+The resolution process starts with the functions in :ref:`resolve.c <lib_api_rplan>`, they are responsible for:
+
+* reacting to state machine state (i.e. calling consume layers if we have an answer ready)
+* interacting with the library user (i.e. asking caller for I/O, accepting queries)
+* fetching assets needed by layers (i.e. zone cut)
+
+This is the *driver*. The driver is not meant to know *"how"* the query resolves, but rather *"when"* to execute *"what"*.
+
+.. image:: ../doc/resolution.png
+ :align: center
+
+On the other side are *layers*. They are responsible for dissecting the packets and informing the driver about the results. For example, a *produce* layer generates query, a *consume* layer validates answer.
+
+.. tip:: Layers are executed asynchronously by the driver. If you need some asset beforehand, you can signalize the driver using returning state or current query flags. For example, setting a flag ``AWAIT_CUT`` forces driver to fetch zone cut information before the packet is consumed; setting a ``RESOLVED`` flag makes it pop a query after the current set of layers is finished; returning ``FAIL`` state makes it fail current query.
+
+Layers can also change course of resolution, for example by appending additional queries.
+
+.. code-block:: lua
+
+ consume = function (state, req, answer)
+ answer = kres.pkt_t(answer)
+ if answer:qtype() == kres.type.NS then
+ req = kres.request_t(req)
+ local qry = req:push(answer:qname(), kres.type.SOA, kres.class.IN)
+ qry.flags.AWAIT_CUT = true
+ end
+ return state
+ end
+
+This **doesn't** block currently processed query, and the newly created sub-request will start as soon as driver finishes processing current. In some cases you might need to issue sub-request and process it **before** continuing with the current, i.e. validator may need a DNSKEY before it can validate signatures. In this case, layers can yield and resume afterwards.
+
+.. code-block:: lua
+
+ consume = function (state, req, answer)
+ answer = kres.pkt_t(answer)
+ if state == kres.YIELD then
+ print('continuing yielded layer')
+ return kres.DONE
+ else
+ if answer:qtype() == kres.type.NS then
+ req = kres.request_t(req)
+ local qry = req:push(answer:qname(), kres.type.SOA, kres.class.IN)
+ qry.flags.AWAIT_CUT = true
+ print('planned SOA query, yielding')
+ return kres.YIELD
+ end
+ return state
+ end
+ end
+
+The ``YIELD`` state is a bit special. When a layer returns it, it interrupts current walk through the layers. When the layer receives it,
+it means that it yielded before and now it is resumed. This is useful in a situation where you need a sub-request to determine whether current answer is valid or not.
+
+Writing layers
+==============
+
+.. warning:: FIXME: this dev-docs section is outdated! Better see comments in files instead, for now.
+
+The resolver :ref:`library <lib_index>` leverages the processing API from the libknot to separate packet processing code into layers.
+
+.. note:: This is only crash-course in the library internals, see the resolver :ref:`library <lib_index>` documentation for the complete overview of the services.
+
+The library offers following services:
+
+- :ref:`Cache <lib_api_cache>` - MVCC cache interface for retrieving/storing resource records.
+- :ref:`Resolution plan <lib_api_rplan>` - Query resolution plan, a list of partial queries (with hierarchy) sent in order to satisfy original query. This contains information about the queries, nameserver choice, timing information, answer and its class.
+- :ref:`Nameservers <lib_api_nameservers>` - Reputation database of nameservers, this serves as an aid for nameserver choice.
+
+A processing layer is going to be called by the query resolution driver for each query,
+so you're going to work with :ref:`struct kr_request <lib_api_rplan>` as your per-query context.
+This structure contains pointers to resolution context, resolution plan and also the final answer.
+
+.. code-block:: c
+
+ int consume(kr_layer_t *ctx, knot_pkt_t *pkt)
+ {
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ }
+
+This is only passive processing of the incoming answer. If you want to change the course of resolution, say satisfy a query from a local cache before the library issues a query to the nameserver, you can use states (see the :ref:`Static hints <mod-hints>` for example).
+
+.. code-block:: c
+
+ int produce(kr_layer_t *ctx, knot_pkt_t *pkt)
+ {
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ /* Query can be satisfied locally. */
+ if (can_satisfy(qry)) {
+ /* This flag makes the resolver move the query
+ * to the "resolved" list. */
+ qry->flags.RESOLVED = true;
+ return KR_STATE_DONE;
+ }
+
+ /* Pass-through. */
+ return ctx->state;
+ }
+
+It is possible to not only act during the query resolution, but also to view the complete resolution plan afterwards. This is useful for analysis-type tasks, or *"per answer"* hooks.
+
+.. code-block:: c
+
+ int finish(kr_layer_t *ctx)
+ {
+ struct kr_request *req = ctx->req;
+ struct kr_rplan *rplan = req->rplan;
+
+ /* Print the query sequence with start time. */
+ char qname_str[KNOT_DNAME_MAXLEN];
+ struct kr_query *qry = NULL
+ WALK_LIST(qry, rplan->resolved) {
+ knot_dname_to_str(qname_str, qry->sname, sizeof(qname_str));
+ printf("%s at %u\n", qname_str, qry->timestamp);
+ }
+
+ return ctx->state;
+ }
+
+APIs in Lua
+===========
+
+The APIs in Lua world try to mirror the C APIs using LuaJIT FFI, with several differences and enhancements.
+There is not comprehensive guide on the API yet, but you can have a look at the bindings_ file.
+
+Elementary types and constants
+------------------------------
+
+* States are directly in ``kres`` table, e.g. ``kres.YIELD, kres.CONSUME, kres.PRODUCE, kres.DONE, kres.FAIL``.
+* DNS classes are in ``kres.class`` table, e.g. ``kres.class.IN`` for Internet class.
+* DNS types are in ``kres.type`` table, e.g. ``kres.type.AAAA`` for AAAA type.
+* DNS rcodes types are in ``kres.rcode`` table, e.g. ``kres.rcode.NOERROR``.
+* Packet sections (QUESTION, ANSWER, AUTHORITY, ADDITIONAL) are in the ``kres.section`` table.
+
+Working with domain names
+-------------------------
+
+The internal API usually works with domain names in label format, you can convert between text and wire freely.
+
+.. code-block:: lua
+
+ local dname = kres.str2dname('business.se')
+ local strname = kres.dname2str(dname)
+
+Working with resource records
+-----------------------------
+
+Resource records are stored as tables.
+
+.. code-block:: lua
+
+ local rr = { owner = kres.str2dname('owner'),
+ ttl = 0,
+ class = kres.class.IN,
+ type = kres.type.CNAME,
+ rdata = kres.str2dname('someplace') }
+ print(kres.rr2str(rr))
+
+RRSets in packet can be accessed using FFI, you can easily fetch single records.
+
+.. code-block:: lua
+
+ local rrset = { ... }
+ local rr = rrset:get(0) -- Return first RR
+ print(kres.dname2str(rr:owner()))
+ print(rr:ttl())
+ print(kres.rr2str(rr))
+
+Working with packets
+--------------------
+
+Packet is the data structure that you're going to see in layers very often. They consists of a header, and four sections: QUESTION, ANSWER, AUTHORITY, ADDITIONAL. The first section is special, as it contains the query name, type, and class; the rest of the sections contain RRSets.
+
+First you need to convert it to a type known to FFI and check basic properties. Let's start with a snippet of a *consume* layer.
+
+.. code-block:: lua
+
+ consume = function (state, req, pkt)
+ pkt = kres.pkt_t(answer)
+ print('rcode:', pkt:rcode())
+ print('query:', kres.dname2str(pkt:qname()), pkt:qclass(), pkt:qtype())
+ if pkt:rcode() ~= kres.rcode.NOERROR then
+ print('error response')
+ end
+ end
+
+You can enumerate records in the sections.
+
+.. code-block:: lua
+
+ local records = pkt:section(kres.section.ANSWER)
+ for i = 1, #records do
+ local rr = records[i]
+ if rr.type == kres.type.AAAA then
+ print(kres.rr2str(rr))
+ end
+ end
+
+During *produce* or *begin*, you might want to want to write to packet. Keep in mind that you have to write packet sections in sequence,
+e.g. you can't write to ANSWER after writing AUTHORITY, it's like stages where you can't go back.
+
+.. code-block:: lua
+
+ pkt:rcode(kres.rcode.NXDOMAIN)
+ -- Clear answer and write QUESTION
+ pkt:recycle()
+ pkt:question('\7blocked', kres.class.IN, kres.type.SOA)
+ -- Start writing data
+ pkt:begin(kres.section.ANSWER)
+ -- Nothing in answer
+ pkt:begin(kres.section.AUTHORITY)
+ local soa = { owner = '\7blocked', ttl = 900, class = kres.class.IN, type = kres.type.SOA, rdata = '...' }
+ pkt:put(soa.owner, soa.ttl, soa.class, soa.type, soa.rdata)
+
+Working with requests
+---------------------
+
+The request holds information about currently processed query, enabled options, cache, and other extra data.
+You primarily need to retrieve currently processed query.
+
+.. code-block:: lua
+
+ consume = function (state, req, pkt)
+ req = kres.request_t(req)
+ print(req.options)
+ print(req.state)
+
+ -- Print information about current query
+ local current = req:current()
+ print(kres.dname2str(current.owner))
+ print(current.stype, current.sclass, current.id, current.flags)
+ end
+
+In layers that either begin or finalize, you can walk the list of resolved queries.
+
+.. code-block:: lua
+
+ local last = req:resolved()
+ print(last.stype)
+
+As described in the layers, you can not only retrieve information about current query, but also push new ones or pop old ones.
+
+.. code-block:: lua
+
+ -- Push new query
+ local qry = req:push(pkt:qname(), kres.type.SOA, kres.class.IN)
+ qry.flags.AWAIT_CUT = true
+
+ -- Pop the query, this will erase it from resolution plan
+ req:pop(qry)
+
+
+.. _libknot: https://gitlab.labs.nic.cz/knot/knot-dns/tree/master/src/libknot
+.. _bindings: https://gitlab.labs.nic.cz/knot/knot-resolver/blob/master/daemon/lua/kres.lua
+
+
+Significant Lua API changes
+---------------------------
+
+Incompatible changes since 3.0.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the main ``kres.*`` lua binding, there was only change in struct knot_rrset_t:
+
+- constructor now accepts TTL as additional parameter (defaulting to zero)
+- add_rdata() doesn't accept TTL anymore (and will throw an error if passed)
+
+In case you used knot_* functions and structures bound to lua:
+
+- knot_dname_is_sub(a, b): knot_dname_in_bailiwick(a, b) > 0
+- knot_rdata_rdlen(): knot_rdataset_at().len
+- knot_rdata_data(): knot_rdataset_at().data
+- knot_rdata_array_size(): offsetof(struct knot_data_t, data) + knot_rdataset_at().len
+- struct knot_rdataset: field names were renamed to .count and .rdata
+- some functions got inlined from headers, but you can use their kr_* clones:
+ kr_rrsig_sig_inception(), kr_rrsig_sig_expiration(), kr_rrsig_type_covered().
+ Note that these functions now accept knot_rdata_t* instead of a pair
+ knot_rdataset_t* and size_t - you can use knot_rdataset_at() for that.
+
+- knot_rrset_add_rdata() doesn't take TTL parameter anymore
+- knot_rrset_init_empty() was inlined, but in lua you can use the constructor
+- knot_rrset_ttl() was inlined, but in lua you can use :ttl() method instead
+
+- knot_pkt_qname(), _qtype(), _qclass(), _rr(), _section() were inlined,
+ but in lua you can use methods instead, e.g. myPacket:qname()
+- knot_pkt_free() takes knot_pkt_t* instead of knot_pkt_t**, but from lua
+ you probably didn't want to use that; constructor ensures garbage collection.
+
+
+.. |---| unicode:: U+02014 .. em dash
diff --git a/lib/cache/api.c b/lib/cache/api.c
new file mode 100644
index 0000000..c0591d6
--- /dev/null
+++ b/lib/cache/api.c
@@ -0,0 +1,889 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libknot/descriptor.h>
+#include <libknot/dname.h>
+#include <libknot/errcode.h>
+#include <libknot/rrtype/rrsig.h>
+
+#include "contrib/cleanup.h"
+#include "contrib/ucw/lib.h"
+#include "lib/cache/api.h"
+#include "lib/cache/cdb_lmdb.h"
+#include "lib/defines.h"
+#include "lib/generic/trie.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+#include "lib/utils.h"
+
+#include "lib/cache/impl.h"
+
+/* TODO:
+ * - Reconsider when RRSIGs are put in and retrieved from the cache.
+ * Currently it's always done, which _might_ be spurious, depending
+ * on how kresd will use the returned result.
+ * There's also the "problem" that kresd ATM does _not_ ask upstream
+ * with DO bit in some cases.
+ */
+
+
+/** Cache version */
+static const uint16_t CACHE_VERSION = 5;
+/** Key size */
+#define KEY_HSIZE (sizeof(uint8_t) + sizeof(uint16_t))
+#define KEY_SIZE (KEY_HSIZE + KNOT_DNAME_MAXLEN)
+
+
+/** @internal Forward declarations of the implementation details
+ * \param optout[out] Set *optout = true; when encountering an opt-out NSEC3 (optional). */
+static ssize_t stash_rrset(struct kr_cache *cache, const struct kr_query *qry,
+ const knot_rrset_t *rr, const knot_rrset_t *rr_sigs, uint32_t timestamp,
+ uint8_t rank, trie_t *nsec_pmap, bool *has_optout);
+/** Preliminary checks before stash_rrset(). Don't call if returns <= 0. */
+static int stash_rrset_precond(const knot_rrset_t *rr, const struct kr_query *qry/*logs*/);
+
+/** @internal Removes all records from cache. */
+static inline int cache_clear(struct kr_cache *cache)
+{
+ cache->stats.delete += 1;
+ return cache_op(cache, clear);
+}
+
+/** @internal Open cache db transaction and check internal data version. */
+static int assert_right_version(struct kr_cache *cache)
+{
+ /* Check cache ABI version. */
+ /* CACHE_KEY_DEF: to avoid collisions with kr_cache_match(). */
+ uint8_t key_str[4] = "VERS";
+ knot_db_val_t key = { .data = key_str, .len = sizeof(key_str) };
+ knot_db_val_t val = { NULL, 0 };
+ int ret = cache_op(cache, read, &key, &val, 1);
+ if (ret == 0 && val.len == sizeof(CACHE_VERSION)
+ && memcmp(val.data, &CACHE_VERSION, sizeof(CACHE_VERSION)) == 0) {
+ ret = kr_error(EEXIST);
+ } else {
+ int oldret = ret;
+ /* Version doesn't match. Recreate cache and write version key. */
+ ret = cache_op(cache, count);
+ if (ret != 0) { /* Non-empty cache, purge it. */
+ kr_log_info("[ ][cach] incompatible cache database detected, purging\n");
+ if (oldret) {
+ kr_log_verbose("bad ret: %d\n", oldret);
+ } else if (val.len != sizeof(CACHE_VERSION)) {
+ kr_log_verbose("bad length: %d\n", (int)val.len);
+ } else {
+ uint16_t ver;
+ memcpy(&ver, val.data, sizeof(ver));
+ kr_log_verbose("bad version: %d\n", (int)ver);
+ }
+ ret = cache_clear(cache);
+ }
+ /* Either purged or empty. */
+ if (ret == 0) {
+ /* Key/Val is invalidated by cache purge, recreate it */
+ val.data = /*const-cast*/(void *)&CACHE_VERSION;
+ val.len = sizeof(CACHE_VERSION);
+ ret = cache_op(cache, write, &key, &val, 1);
+ }
+ }
+ kr_cache_sync(cache);
+ return ret;
+}
+
+int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct kr_cdb_opts *opts, knot_mm_t *mm)
+{
+ if (!cache) {
+ return kr_error(EINVAL);
+ }
+ /* Open cache */
+ if (!api) {
+ api = kr_cdb_lmdb();
+ }
+ cache->api = api;
+ int ret = cache->api->open(&cache->db, opts, mm);
+ if (ret != 0) {
+ return ret;
+ }
+ memset(&cache->stats, 0, sizeof(cache->stats));
+ cache->ttl_min = KR_CACHE_DEFAULT_TTL_MIN;
+ cache->ttl_max = KR_CACHE_DEFAULT_TTL_MAX;
+ /* Check cache ABI version */
+ kr_cache_make_checkpoint(cache);
+ (void)assert_right_version(cache);
+
+ char *fpath;
+ ret = asprintf(&fpath, "%s/data.mdb", opts->path);
+ if (ret > 0) {
+ kr_cache_emergency_file_to_remove = fpath;
+ } else {
+ assert(false); /* non-critical, but still */
+ }
+ return 0;
+}
+
+const char *kr_cache_emergency_file_to_remove = NULL;
+
+
+#define cache_isvalid(cache) ((cache) && (cache)->api && (cache)->db)
+
+void kr_cache_close(struct kr_cache *cache)
+{
+ if (cache_isvalid(cache)) {
+ cache_op(cache, close);
+ cache->db = NULL;
+ }
+ free(/*const-cast*/(char*)kr_cache_emergency_file_to_remove);
+ kr_cache_emergency_file_to_remove = NULL;
+}
+
+int kr_cache_sync(struct kr_cache *cache)
+{
+ if (!cache_isvalid(cache)) {
+ return kr_error(EINVAL);
+ }
+ if (cache->api->sync) {
+ return cache_op(cache, sync);
+ }
+ return kr_ok();
+}
+
+int kr_cache_insert_rr(struct kr_cache *cache, const knot_rrset_t *rr, const knot_rrset_t *rrsig, uint8_t rank, uint32_t timestamp)
+{
+ int err = stash_rrset_precond(rr, NULL);
+ if (err <= 0) {
+ return kr_ok();
+ }
+ ssize_t written = stash_rrset(cache, NULL, rr, rrsig, timestamp, rank, NULL, NULL);
+ /* Zone's NSEC* parames aren't updated, but that's probably OK
+ * for kr_cache_insert_rr() */
+ if (written >= 0) {
+ return kr_ok();
+ }
+
+ return (int) written;
+}
+
+int kr_cache_clear(struct kr_cache *cache)
+{
+ if (!cache_isvalid(cache)) {
+ return kr_error(EINVAL);
+ }
+ int ret = cache_clear(cache);
+ if (ret == 0) {
+ kr_cache_make_checkpoint(cache);
+ ret = assert_right_version(cache);
+ }
+ return ret;
+}
+
+/* When going stricter, BEWARE of breaking entry_h_consistent_NSEC() */
+struct entry_h * entry_h_consistent(knot_db_val_t data, uint16_t type)
+{
+ (void) type; /* unused, for now */
+ if (!data.data) return NULL;
+ /* Length checks. */
+ if (data.len < offsetof(struct entry_h, data))
+ return NULL;
+ const struct entry_h *eh = data.data;
+ if (eh->is_packet) {
+ uint16_t pkt_len;
+ if (data.len < offsetof(struct entry_h, data) + sizeof(pkt_len)) {
+ return NULL;
+ }
+ memcpy(&pkt_len, eh->data, sizeof(pkt_len));
+ if (data.len < offsetof(struct entry_h, data) + sizeof(pkt_len)
+ + pkt_len) {
+ return NULL;
+ }
+ }
+
+ bool ok = true;
+ ok = ok && kr_rank_check(eh->rank);
+ ok = ok && (!kr_rank_test(eh->rank, KR_RANK_BOGUS)
+ || eh->is_packet);
+ ok = ok && (eh->is_packet || !eh->has_optout);
+
+ return ok ? /*const-cast*/(struct entry_h *)eh : NULL;
+}
+
+int32_t get_new_ttl(const struct entry_h *entry, const struct kr_query *qry,
+ const knot_dname_t *owner, uint16_t type, uint32_t now)
+{
+ int32_t diff = now - entry->time;
+ if (diff < 0) {
+ /* We may have obtained the record *after* the request started. */
+ diff = 0;
+ }
+ int32_t res = entry->ttl - diff;
+ if (res < 0 && owner && qry && qry->stale_cb) {
+ /* Stale-serving decision, delegated to a callback. */
+ int res_stale = qry->stale_cb(res, owner, type, qry);
+ if (res_stale >= 0)
+ return res_stale;
+ }
+ return res;
+}
+
+int32_t kr_cache_ttl(const struct kr_cache_p *peek, const struct kr_query *qry,
+ const knot_dname_t *name, uint16_t type)
+{
+ const struct entry_h *eh = peek->raw_data;
+ return get_new_ttl(eh, qry, name, type, qry->timestamp.tv_sec);
+}
+
+/** Check that no label contains a zero character, incl. a log trace.
+ *
+ * We refuse to work with those, as LF and our cache keys might become ambiguous.
+ * Assuming uncompressed name, as usual.
+ * CACHE_KEY_DEF
+ */
+static bool check_dname_for_lf(const knot_dname_t *n, const struct kr_query *qry/*logging*/)
+{
+ const bool ret = knot_dname_size(n) == strlen((const char *)n) + 1;
+ if (!ret) { WITH_VERBOSE(qry) {
+ auto_free char *n_str = kr_dname_text(n);
+ VERBOSE_MSG(qry, "=> skipping zero-containing name %s\n", n_str);
+ } }
+ return ret;
+}
+
+/** Return false on types to be ignored. Meant both for sname and direct cache requests. */
+static bool check_rrtype(uint16_t type, const struct kr_query *qry/*logging*/)
+{
+ const bool ret = !knot_rrtype_is_metatype(type)
+ && type != KNOT_RRTYPE_RRSIG;
+ if (!ret) { WITH_VERBOSE(qry) {
+ auto_free char *type_str = kr_rrtype_text(type);
+ VERBOSE_MSG(qry, "=> skipping RR type %s\n", type_str);
+ } }
+ return ret;
+}
+
+/** Like key_exact_type() but omits a couple checks not holding for pkt cache. */
+knot_db_val_t key_exact_type_maypkt(struct key *k, uint16_t type)
+{
+ assert(check_rrtype(type, NULL));
+ switch (type) {
+ case KNOT_RRTYPE_RRSIG: /* no RRSIG query caching, at least for now */
+ assert(false);
+ return (knot_db_val_t){ NULL, 0 };
+ /* xNAME lumped into NS. */
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_DNAME:
+ type = KNOT_RRTYPE_NS;
+ default:
+ break;
+ }
+
+ int name_len = k->buf[0];
+ k->buf[name_len + 1] = 0; /* make sure different names can never match */
+ k->buf[name_len + 2] = 'E'; /* tag for exact name+type matches */
+ memcpy(k->buf + name_len + 3, &type, 2);
+ k->type = type;
+ /* CACHE_KEY_DEF: key == dname_lf + '\0' + 'E' + RRTYPE */
+ return (knot_db_val_t){ k->buf + 1, name_len + 4 };
+}
+
+
+/** The inside for cache_peek(); implementation separated to ./peek.c */
+int peek_nosync(kr_layer_t *ctx, knot_pkt_t *pkt);
+/** function for .produce phase */
+int cache_peek(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ /* We first check various exit-conditions and then call the _real function. */
+
+ if (!kr_cache_is_open(&req->ctx->cache)
+ || ctx->state & (KR_STATE_FAIL|KR_STATE_DONE) || qry->flags.NO_CACHE
+ || (qry->flags.CACHE_TRIED && !qry->stale_cb)
+ || !check_rrtype(qry->stype, qry) /* LATER: some other behavior for some of these? */
+ || qry->sclass != KNOT_CLASS_IN) {
+ return ctx->state; /* Already resolved/failed or already tried, etc. */
+ }
+ /* ATM cache only peeks for qry->sname and that would be useless
+ * to repeat on every iteration, so disable it from now on.
+ * LATER(optim.): assist with more precise QNAME minimization. */
+ qry->flags.CACHE_TRIED = true;
+
+ if (qry->stype == KNOT_RRTYPE_NSEC) {
+ VERBOSE_MSG(qry, "=> skipping stype NSEC\n");
+ return ctx->state;
+ }
+ if (!check_dname_for_lf(qry->sname, qry)) {
+ return ctx->state;
+ }
+
+ int ret = peek_nosync(ctx, pkt);
+ kr_cache_sync(&req->ctx->cache);
+ return ret;
+}
+
+
+
+/** It's simply inside of cycle taken out to decrease indentation. \return error code. */
+static int stash_rrarray_entry(ranked_rr_array_t *arr, int arr_i,
+ const struct kr_query *qry, struct kr_cache *cache,
+ int *unauth_cnt, trie_t *nsec_pmap, bool *has_optout);
+/** Stash a single nsec_p. \return 0 (errors are ignored). */
+static int stash_nsec_p(const knot_dname_t *dname, const char *nsec_p_v,
+ struct kr_request *req);
+
+/** The whole .consume phase for the cache module. */
+int cache_stash(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ struct kr_cache *cache = &req->ctx->cache;
+
+ /* Note: we cache even in KR_STATE_FAIL. For example,
+ * BOGUS answer can go to +cd cache even without +cd request. */
+ if (!kr_cache_is_open(cache) || !qry
+ || qry->flags.CACHED || !check_rrtype(knot_pkt_qtype(pkt), qry)
+ || qry->sclass != KNOT_CLASS_IN) {
+ return ctx->state;
+ }
+ /* Do not cache truncated answers, at least for now. LATER */
+ if (knot_wire_get_tc(pkt->wire)) {
+ return ctx->state;
+ }
+ /* Stash individual records. */
+ ranked_rr_array_t *selected[] = kr_request_selected(req);
+ int unauth_cnt = 0;
+ trie_t *nsec_pmap = trie_create(&req->pool);
+ if (!nsec_pmap) {
+ assert(!ENOMEM);
+ goto finally;
+ }
+ bool has_optout = false;
+ /* ^^ DNSSEC_OPTOUT is not fired in cases like `com. A`,
+ * but currently we don't stash separate NSEC3 proving that. */
+ for (int psec = KNOT_ANSWER; psec <= KNOT_ADDITIONAL; ++psec) {
+ ranked_rr_array_t *arr = selected[psec];
+ /* uncached entries are located at the end */
+ for (ssize_t i = arr->len - 1; i >= 0; --i) {
+ ranked_rr_array_entry_t *entry = arr->at[i];
+ if (entry->qry_uid != qry->uid) {
+ continue;
+ /* TODO: probably safe to break but maybe not worth it */
+ }
+ int ret = stash_rrarray_entry(arr, i, qry, cache, &unauth_cnt,
+ nsec_pmap, &has_optout);
+ if (ret) {
+ VERBOSE_MSG(qry, "=> stashing RRs errored out\n");
+ goto finally;
+ }
+ /* LATER(optim.): maybe filter out some type-rank combinations
+ * that won't be useful as separate RRsets. */
+ }
+ }
+
+ trie_it_t *it;
+ for (it = trie_it_begin(nsec_pmap); !trie_it_finished(it); trie_it_next(it)) {
+ stash_nsec_p((const knot_dname_t *)trie_it_key(it, NULL),
+ (const char *)*trie_it_val(it), req);
+ }
+ trie_it_free(it);
+ /* LATER(optim.): typically we also have corresponding NS record in the list,
+ * so we might save a cache operation. */
+
+ stash_pkt(pkt, qry, req, has_optout);
+
+finally:
+ if (unauth_cnt) {
+ VERBOSE_MSG(qry, "=> stashed also %d nonauth RRsets\n", unauth_cnt);
+ };
+ kr_cache_sync(cache);
+ return ctx->state; /* we ignore cache-stashing errors */
+}
+
+/** Preliminary checks before stash_rrset(). Don't call if returns <= 0. */
+static int stash_rrset_precond(const knot_rrset_t *rr, const struct kr_query *qry/*logs*/)
+{
+ if (!rr || rr->rclass != KNOT_CLASS_IN) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ if (!check_rrtype(rr->type, qry)) {
+ return kr_ok();
+ }
+ if (!check_dname_for_lf(rr->owner, qry)) {
+ return kr_ok();
+ }
+ return 1/*proceed*/;
+}
+
+static ssize_t stash_rrset(struct kr_cache *cache, const struct kr_query *qry,
+ const knot_rrset_t *rr, const knot_rrset_t *rr_sigs, uint32_t timestamp,
+ uint8_t rank, trie_t *nsec_pmap, bool *has_optout)
+{
+ assert(stash_rrset_precond(rr, qry) > 0);
+ if (!cache) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ const int wild_labels = rr_sigs == NULL ? 0 :
+ knot_dname_labels(rr->owner, NULL) - knot_rrsig_labels(rr_sigs->rrs.rdata);
+ if (wild_labels < 0) {
+ return kr_ok();
+ }
+ const knot_dname_t *encloser = rr->owner; /**< the closest encloser name */
+ for (int i = 0; i < wild_labels; ++i) {
+ encloser = knot_wire_next_label(encloser, NULL);
+ }
+ int ret = 0;
+
+ /* Construct the key under which RRs will be stored,
+ * and add corresponding nsec_pmap item (if necessary). */
+ struct key k_storage, *k = &k_storage;
+ knot_db_val_t key;
+ switch (rr->type) {
+ case KNOT_RRTYPE_NSEC3:
+ /* Skip "suspicious" or opt-out NSEC3 sets. */
+ if (rr->rrs.count != 1) return kr_ok();
+ if (KNOT_NSEC3_FLAG_OPT_OUT & knot_nsec3_flags(rr->rrs.rdata)) {
+ if (has_optout) *has_optout = true;
+ return kr_ok();
+ }
+ /* fall through */
+ case KNOT_RRTYPE_NSEC:
+ if (!kr_rank_test(rank, KR_RANK_SECURE)) {
+ /* Skip any NSEC*s that aren't validated. */
+ return kr_ok();
+ }
+ if (!rr_sigs || !rr_sigs->rrs.count || !rr_sigs->rrs.rdata) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ const knot_dname_t *signer = knot_rrsig_signer_name(rr_sigs->rrs.rdata);
+ const int signer_size = knot_dname_size(signer);
+ k->zlf_len = signer_size - 1;
+
+ void **npp = nsec_pmap == NULL ? NULL
+ : trie_get_ins(nsec_pmap, (const char *)signer, signer_size);
+ assert(!nsec_pmap || (npp && ENOMEM));
+ if (rr->type == KNOT_RRTYPE_NSEC) {
+ key = key_NSEC1(k, encloser, wild_labels);
+ break;
+ }
+
+ assert(rr->type == KNOT_RRTYPE_NSEC3);
+ const knot_rdata_t * const rdata = rr->rrs.rdata;
+ if (rdata->len <= 4) return kr_error(EILSEQ); /*< data from outside; less trust */
+ const int np_dlen = nsec_p_rdlen(rdata->data);
+ if (np_dlen > rdata->len) return kr_error(EILSEQ);
+ key = key_NSEC3(k, encloser, nsec_p_mkHash(rdata->data));
+ if (npp && !*npp) {
+ *npp = mm_alloc(&qry->request->pool, np_dlen);
+ if (!*npp) {
+ assert(!ENOMEM);
+ break;
+ }
+ memcpy(*npp, rdata->data, np_dlen);
+ }
+ break;
+ default:
+ ret = kr_dname_lf(k->buf, encloser, wild_labels);
+ if (ret) {
+ assert(!ret);
+ return kr_error(ret);
+ }
+ key = key_exact_type(k, rr->type);
+ }
+
+ /* Compute materialized sizes of the new data. */
+ const knot_rdataset_t *rds_sigs = rr_sigs ? &rr_sigs->rrs : NULL;
+ const int rr_ssize = rdataset_dematerialize_size(&rr->rrs);
+ assert(rr_ssize == to_even(rr_ssize));
+ knot_db_val_t val_new_entry = {
+ .data = NULL,
+ .len = offsetof(struct entry_h, data) + rr_ssize
+ + rdataset_dematerialize_size(rds_sigs),
+ };
+
+ /* Prepare raw memory for the new entry. */
+ ret = entry_h_splice(&val_new_entry, rank, key, k->type, rr->type,
+ rr->owner, qry, cache, timestamp);
+ if (ret) return kr_ok(); /* some aren't really errors */
+ assert(val_new_entry.data);
+
+ const uint32_t ttl = rr->ttl;
+ /* FIXME: consider TTLs and expirations of RRSIGs as well, just in case. */
+
+ /* Write the entry itself. */
+ struct entry_h *eh = val_new_entry.data;
+ memset(eh, 0, offsetof(struct entry_h, data));
+ eh->time = timestamp;
+ eh->ttl = MAX(MIN(ttl, cache->ttl_max), cache->ttl_min);
+ eh->rank = rank;
+ if (rdataset_dematerialize(&rr->rrs, eh->data)
+ || rdataset_dematerialize(rds_sigs, eh->data + rr_ssize)) {
+ /* minimize the damage from incomplete write; TODO: better */
+ eh->time = 0;
+ eh->ttl = 0;
+ eh->rank = 0;
+ assert(false);
+ }
+ assert(entry_h_consistent(val_new_entry, rr->type));
+
+ #if 0 /* Occasionally useful when debugging some kinds of changes. */
+ {
+ kr_cache_sync(cache);
+ knot_db_val_t val = { NULL, 0 };
+ ret = cache_op(cache, read, &key, &val, 1);
+ if (ret != kr_error(ENOENT)) { // ENOENT might happen in some edge case, I guess
+ assert(!ret);
+ entry_list_t el;
+ entry_list_parse(val, el);
+ }
+ }
+ #endif
+
+ /* Update metrics */
+ cache->stats.insert += 1;
+
+ /* Verbose-log some not-too-common cases. */
+ WITH_VERBOSE(qry) { if (kr_rank_test(rank, KR_RANK_AUTH)
+ || rr->type == KNOT_RRTYPE_NS) {
+ auto_free char *type_str = kr_rrtype_text(rr->type),
+ *encl_str = kr_dname_text(encloser);
+ VERBOSE_MSG(qry, "=> stashed %s%s %s, rank 0%.2o, "
+ "%d B total, incl. %d RRSIGs\n",
+ (wild_labels ? "*." : ""), encl_str, type_str, rank,
+ (int)val_new_entry.len, (rr_sigs ? rr_sigs->rrs.count : 0)
+ );
+ } }
+
+ return (ssize_t) val_new_entry.len;
+}
+
+static int stash_rrarray_entry(ranked_rr_array_t *arr, int arr_i,
+ const struct kr_query *qry, struct kr_cache *cache,
+ int *unauth_cnt, trie_t *nsec_pmap, bool *has_optout)
+{
+ ranked_rr_array_entry_t *entry = arr->at[arr_i];
+ if (entry->cached) {
+ return kr_ok();
+ }
+ const knot_rrset_t *rr = entry->rr;
+ if (rr->type == KNOT_RRTYPE_RRSIG) {
+ return kr_ok(); /* reduce verbose logging from the following call */
+ }
+ int ret = stash_rrset_precond(rr, qry);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ /* Try to find corresponding signatures, always. LATER(optim.): speed. */
+ ranked_rr_array_entry_t *entry_rrsigs = NULL;
+ const knot_rrset_t *rr_sigs = NULL;
+ for (ssize_t j = arr->len - 1; j >= 0; --j) {
+ /* TODO: ATM we assume that some properties are the same
+ * for all RRSIGs in the set (esp. label count). */
+ ranked_rr_array_entry_t *e = arr->at[j];
+ bool ok = e->qry_uid == qry->uid && !e->cached
+ && e->rr->type == KNOT_RRTYPE_RRSIG
+ && knot_rrsig_type_covered(e->rr->rrs.rdata) == rr->type
+ && knot_dname_is_equal(rr->owner, e->rr->owner);
+ if (!ok) continue;
+ entry_rrsigs = e;
+ rr_sigs = e->rr;
+ break;
+ }
+
+ ssize_t written = stash_rrset(cache, qry, rr, rr_sigs, qry->timestamp.tv_sec,
+ entry->rank, nsec_pmap, has_optout);
+ if (written < 0) {
+ kr_log_error("[%05u.%02u][cach] stash failed, ret = %d\n", qry->request->uid,
+ qry->uid, ret);
+ return (int) written;
+ }
+
+ if (written > 0) {
+ /* Mark entry as cached for the rest of the query processing */
+ entry->cached = true;
+ if (entry_rrsigs) {
+ entry_rrsigs->cached = true;
+ }
+ if (!kr_rank_test(entry->rank, KR_RANK_AUTH) && rr->type != KNOT_RRTYPE_NS) {
+ *unauth_cnt += 1;
+ }
+ }
+
+ return kr_ok();
+}
+
+static int stash_nsec_p(const knot_dname_t *dname, const char *nsec_p_v,
+ struct kr_request *req)
+{
+ const struct kr_query *qry = req->current_query;
+ struct kr_cache *cache = &req->ctx->cache;
+ uint32_t valid_until = qry->timestamp.tv_sec + cache->ttl_max;
+ /* LATER(optim.): be more precise here ^^ and reduce calls. */
+ static const int32_t ttl_margin = 3600;
+ const uint8_t *nsec_p = (const uint8_t *)nsec_p_v;
+ int data_stride = sizeof(valid_until) + nsec_p_rdlen(nsec_p);
+
+ unsigned int log_hash = 0xFeeeFeee; /* this type is simpler for printf args */
+ auto_free char *log_dname = NULL;
+ WITH_VERBOSE(qry) {
+ log_hash = nsec_p_v ? nsec_p_mkHash((const uint8_t *)nsec_p_v) : 0;
+ log_dname = kr_dname_text(dname);
+ }
+ /* Find what's in the cache. */
+ struct key k_storage, *k = &k_storage;
+ int ret = kr_dname_lf(k->buf, dname, false);
+ if (ret) return kr_error(ret);
+ knot_db_val_t key = key_exact_type(k, KNOT_RRTYPE_NS);
+ knot_db_val_t val_orig = { NULL, 0 };
+ ret = cache_op(cache, read, &key, &val_orig, 1);
+ if (ret && ret != -ABS(ENOENT)) {
+ VERBOSE_MSG(qry, "=> EL read failed (ret: %d)\n", ret);
+ return kr_ok();
+ }
+ /* Prepare new entry_list_t so we can just write at el[0]. */
+ entry_list_t el;
+ int log_refresh_by = 0;
+ if (ret == -ABS(ENOENT)) {
+ memset(el, 0, sizeof(el));
+ } else {
+ ret = entry_list_parse(val_orig, el);
+ if (ret) {
+ VERBOSE_MSG(qry, "=> EL parse failed (ret: %d)\n", ret);
+ return kr_error(0);
+ }
+ /* Find the index to replace. */
+ int i_replace = ENTRY_APEX_NSECS_CNT - 1;
+ for (int i = 0; i < ENTRY_APEX_NSECS_CNT; ++i) {
+ if (el[i].len != data_stride) continue;
+ if (nsec_p && memcmp(nsec_p, (uint8_t *)el[i].data + sizeof(uint32_t),
+ data_stride - sizeof(uint32_t)) != 0) {
+ continue;
+ }
+ /* Save a cache operation if TTL extended only a little. */
+ uint32_t valid_orig;
+ memcpy(&valid_orig, el[i].data, sizeof(valid_orig));
+ const int32_t ttl_extended_by = valid_until - valid_orig;
+ if (ttl_extended_by < ttl_margin) {
+ VERBOSE_MSG(qry,
+ "=> nsec_p stash for %s skipped (extra TTL: %d, hash: %x)\n",
+ log_dname, ttl_extended_by, log_hash);
+ return kr_ok();
+ }
+ i_replace = i;
+ log_refresh_by = ttl_extended_by;
+ break;
+ }
+ /* Shift the other indices: move the first `i_replace` blocks
+ * by one position. */
+ if (i_replace) {
+ memmove(&el[1], &el[0], sizeof(el[0]) * i_replace);
+ }
+ }
+ /* Prepare old data into a buffer. See entry_h_splice() for why. LATER(optim.) */
+ el[0].len = data_stride;
+ el[0].data = NULL;
+ knot_db_val_t val;
+ val.len = entry_list_serial_size(el),
+ val.data = mm_alloc(&req->pool, val.len),
+ entry_list_memcpy(val.data, el);
+ /* Prepare the new data chunk */
+ memcpy(el[0].data, &valid_until, sizeof(valid_until));
+ if (nsec_p) {
+ memcpy((uint8_t *)el[0].data + sizeof(valid_until), nsec_p,
+ data_stride - sizeof(valid_until));
+ }
+ /* Write it all to the cache */
+ ret = cache_op(cache, write, &key, &val, 1);
+ if (ret || !val.data) {
+ VERBOSE_MSG(qry, "=> EL write failed (ret: %d)\n", ret);
+ return kr_ok();
+ }
+ if (log_refresh_by) {
+ VERBOSE_MSG(qry, "=> nsec_p stashed for %s (refresh by %d, hash: %x)\n",
+ log_dname, log_refresh_by, log_hash);
+ } else {
+ VERBOSE_MSG(qry, "=> nsec_p stashed for %s (new, hash: %x)\n",
+ log_dname, log_hash);
+ }
+ return kr_ok();
+}
+
+
+static int peek_exact_real(struct kr_cache *cache, const knot_dname_t *name, uint16_t type,
+ struct kr_cache_p *peek)
+{
+ if (!check_rrtype(type, NULL) || !check_dname_for_lf(name, NULL)) {
+ return kr_error(ENOTSUP);
+ }
+ struct key k_storage, *k = &k_storage;
+
+ int ret = kr_dname_lf(k->buf, name, false);
+ if (ret) return kr_error(ret);
+
+ knot_db_val_t key = key_exact_type(k, type);
+ knot_db_val_t val = { NULL, 0 };
+ ret = cache_op(cache, read, &key, &val, 1);
+ if (!ret) ret = entry_h_seek(&val, type);
+ if (ret) return kr_error(ret);
+
+ const struct entry_h *eh = entry_h_consistent(val, type);
+ if (!eh || eh->is_packet) {
+ // TODO: no packets, but better get rid of whole kr_cache_peek_exact().
+ return kr_error(ENOENT);
+ }
+ *peek = (struct kr_cache_p){
+ .time = eh->time,
+ .ttl = eh->ttl,
+ .rank = eh->rank,
+ .raw_data = val.data,
+ .raw_bound = knot_db_val_bound(val),
+ };
+ return kr_ok();
+}
+int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16_t type,
+ struct kr_cache_p *peek)
+{ /* Just wrap with extra verbose logging. */
+ const int ret = peek_exact_real(cache, name, type, peek);
+ if (false && VERBOSE_STATUS) { /* too noisy for usual --verbose */
+ auto_free char *type_str = kr_rrtype_text(type),
+ *name_str = kr_dname_text(name);
+ const char *result_str = (ret == kr_ok() ? "hit" :
+ (ret == kr_error(ENOENT) ? "miss" : "error"));
+ VERBOSE_MSG(NULL, "_peek_exact: %s %s %s (ret: %d)",
+ type_str, name_str, result_str, ret);
+ }
+ return ret;
+}
+
+int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name, uint16_t type)
+{
+ if (!cache_isvalid(cache)) {
+ return kr_error(EINVAL);
+ }
+ if (!cache->api->remove) {
+ return kr_error(ENOSYS);
+ }
+ struct key k_storage, *k = &k_storage;
+ int ret = kr_dname_lf(k->buf, name, false);
+ if (ret) return kr_error(ret);
+
+ knot_db_val_t key = key_exact_type(k, type);
+ return cache_op(cache, remove, &key, 1);
+}
+
+int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name,
+ bool exact_name, knot_db_val_t keyval[][2], int maxcount)
+{
+ if (!cache_isvalid(cache)) {
+ return kr_error(EINVAL);
+ }
+ if (!cache->api->match) {
+ return kr_error(ENOSYS);
+ }
+
+ struct key k_storage, *k = &k_storage;
+
+ int ret = kr_dname_lf(k->buf, name, false);
+ if (ret) return kr_error(ret);
+
+ // use a mock type
+ knot_db_val_t key = key_exact_type(k, KNOT_RRTYPE_A);
+ /* CACHE_KEY_DEF */
+ key.len -= sizeof(uint16_t); /* the type */
+ if (!exact_name) {
+ key.len -= 2; /* '\0' 'E' */
+ if (name[0] == '\0') ++key.len; /* the root name is special ATM */
+ }
+ return cache_op(cache, match, &key, keyval, maxcount);
+}
+
+int kr_unpack_cache_key(knot_db_val_t key, knot_dname_t *buf, uint16_t *type)
+{
+ if (key.data == NULL || buf == NULL || type == NULL) {
+ return kr_error(EINVAL);
+ }
+
+ int len = -1;
+ const char *tag, *key_data = key.data;
+ for (tag = key_data + 1; tag < key_data + key.len; ++tag) {
+ /* CACHE_KEY_DEF */
+ if (tag[-1] == '\0' && (tag == key_data + 1 || tag[-2] == '\0')) {
+ if (tag[0] != 'E') return kr_error(EINVAL);
+ len = tag - 1 - key_data;
+ break;
+ }
+ }
+
+ if (len == -1 || len > KNOT_DNAME_MAXLEN) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = knot_dname_lf2wire(buf, len, key.data);
+ if (ret < 0) {
+ return kr_error(ret);
+ }
+
+ /* CACHE_KEY_DEF: jump over "\0 E/1" */
+ memcpy(type, tag + 1, sizeof(uint16_t));
+
+ return kr_ok();
+}
+
+
+int kr_cache_remove_subtree(struct kr_cache *cache, const knot_dname_t *name,
+ bool exact_name, int maxcount)
+{
+ if (!cache_isvalid(cache)) {
+ return kr_error(EINVAL);
+ }
+
+ knot_db_val_t keyval[maxcount][2], keys[maxcount];
+ int ret = kr_cache_match(cache, name, exact_name, keyval, maxcount);
+ if (ret <= 0) { /* ENOENT -> nothing to remove */
+ return (ret == KNOT_ENOENT) ? 0 : ret;
+ }
+ const int count = ret;
+ /* Duplicate the key strings, as deletion may invalidate the pointers. */
+ int i;
+ for (i = 0; i < count; ++i) {
+ keys[i].len = keyval[i][0].len;
+ keys[i].data = malloc(keys[i].len);
+ if (!keys[i].data) {
+ ret = kr_error(ENOMEM);
+ goto cleanup;
+ }
+ memcpy(keys[i].data, keyval[i][0].data, keys[i].len);
+ }
+ ret = cache->api->remove(cache->db, keys, count);
+cleanup:
+ kr_cache_sync(cache); /* Sync even after just kr_cache_match(). */
+ /* Free keys */
+ while (--i >= 0) {
+ free(keys[i].data);
+ }
+ return ret;
+}
+
diff --git a/lib/cache/api.h b/lib/cache/api.h
new file mode 100644
index 0000000..61bf796
--- /dev/null
+++ b/lib/cache/api.h
@@ -0,0 +1,201 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/consts.h>
+#include <libknot/rrset.h>
+#include <sys/time.h>
+#include "lib/cache/cdb_api.h"
+#include "lib/defines.h"
+#include "contrib/ucw/config.h" /*uint*/
+
+/** When knot_pkt is passed from cache without ->wire, this is the ->size. */
+static const size_t PKT_SIZE_NOWIRE = -1;
+
+
+#include "lib/module.h"
+/* Prototypes for the 'cache' module implementation. */
+int cache_peek(kr_layer_t *ctx, knot_pkt_t *pkt);
+int cache_stash(kr_layer_t *ctx, knot_pkt_t *pkt);
+
+
+/**
+ * Cache structure, keeps API, instance and metadata.
+ */
+struct kr_cache
+{
+ knot_db_t *db; /**< Storage instance */
+ const struct kr_cdb_api *api; /**< Storage engine */
+ struct {
+ uint32_t hit; /**< Number of cache hits */
+ uint32_t miss; /**< Number of cache misses */
+ uint32_t insert; /**< Number of insertions */
+ uint32_t delete; /**< Number of deletions */
+ } stats;
+
+ uint32_t ttl_min, ttl_max; /**< TTL limits */
+
+ /* A pair of stamps for detection of real-time shifts during runtime. */
+ struct timeval checkpoint_walltime; /**< Wall time on the last check-point. */
+ uint64_t checkpoint_monotime; /**< Monotonic milliseconds on the last check-point. */
+};
+
+/**
+ * Open/create cache with provided storage options.
+ * @param cache cache structure to be initialized
+ * @param api storage engine API
+ * @param opts storage-specific options (may be NULL for default)
+ * @param mm memory context.
+ * @return 0 or an error code
+ */
+KR_EXPORT
+int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct kr_cdb_opts *opts, knot_mm_t *mm);
+
+/**
+ * Path to cache file to remove on critical out-of-space error. (do NOT modify it)
+ */
+KR_EXPORT extern
+const char *kr_cache_emergency_file_to_remove;
+
+/**
+ * Close persistent cache.
+ * @note This doesn't clear the data, just closes the connection to the database.
+ * @param cache structure
+ */
+KR_EXPORT
+void kr_cache_close(struct kr_cache *cache);
+
+/** Run after a row of operations to release transaction/lock if needed. */
+KR_EXPORT
+int kr_cache_sync(struct kr_cache *cache);
+
+/**
+ * Return true if cache is open and enabled.
+ */
+static inline bool kr_cache_is_open(struct kr_cache *cache)
+{
+ return cache->db != NULL;
+}
+
+/** (Re)set the time pair to the current values. */
+static inline void kr_cache_make_checkpoint(struct kr_cache *cache)
+{
+ cache->checkpoint_monotime = kr_now();
+ gettimeofday(&cache->checkpoint_walltime, NULL);
+}
+
+/**
+ * Insert RRSet into cache, replacing any existing data.
+ * @param cache cache structure
+ * @param rr inserted RRSet
+ * @param rrsig RRSIG for inserted RRSet (optional)
+ * @param rank rank of the data
+ * @param timestamp current time
+ * @return 0 or an errcode
+ */
+KR_EXPORT
+int kr_cache_insert_rr(struct kr_cache *cache, const knot_rrset_t *rr, const knot_rrset_t *rrsig, uint8_t rank, uint32_t timestamp);
+
+/**
+ * Clear all items from the cache.
+ * @param cache cache structure
+ * @return 0 or an errcode
+ */
+KR_EXPORT
+int kr_cache_clear(struct kr_cache *cache);
+
+
+/* ** This interface is temporary. ** */
+
+struct kr_cache_p {
+ uint32_t time; /**< The time of inception. */
+ uint32_t ttl; /**< TTL at inception moment. Assuming it fits into int32_t ATM. */
+ uint8_t rank; /**< See enum kr_rank */
+ struct {
+ /* internal: pointer to eh struct */
+ void *raw_data, *raw_bound;
+ };
+};
+KR_EXPORT
+int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16_t type,
+ struct kr_cache_p *peek);
+/* Parameters (qry, name, type) are used for timestamp and stale-serving decisions. */
+KR_EXPORT
+int32_t kr_cache_ttl(const struct kr_cache_p *peek, const struct kr_query *qry,
+ const knot_dname_t *name, uint16_t type);
+
+KR_EXPORT
+int kr_cache_materialize(knot_rdataset_t *dst, const struct kr_cache_p *ref,
+ knot_mm_t *pool);
+
+
+/**
+ * Remove an entry from cache.
+ * @param cache cache structure
+ * @param name dname
+ * @param type rr type
+ * @return number of deleted records, or negative error code
+ * @note only "exact hits" are considered ATM, and
+ * some other information may be removed alongside.
+ */
+KR_EXPORT
+int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name, uint16_t type);
+
+/**
+ * Get keys matching a dname lf prefix
+ * @param cache cache structure
+ * @param name dname
+ * @param exact_name whether to only consider exact name matches
+ * @param keyval matched key-value pairs
+ * @param maxcount limit on the number of returned key-value pairs
+ * @return result count or an errcode
+ * @note the cache keys are matched by prefix, i.e. it very much depends
+ * on their structure; CACHE_KEY_DEF.
+ */
+KR_EXPORT
+int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name,
+ bool exact_name, knot_db_val_t keyval[][2], int maxcount);
+
+/**
+ * Remove a subtree in cache. It's like _match but removing them instead of returning.
+ * @return number of deleted entries or an errcode
+ */
+KR_EXPORT
+int kr_cache_remove_subtree(struct kr_cache *cache, const knot_dname_t *name,
+ bool exact_name, int maxcount);
+
+/**
+ * Find the closest cached zone apex for a name (in cache).
+ * @param is_DS start searching one name higher
+ * @return the number of labels to remove from the name, or negative error code
+ * @note timestamp is found by a syscall, and stale-serving is not considered
+ */
+KR_EXPORT
+int kr_cache_closest_apex(struct kr_cache *cache, const knot_dname_t *name, bool is_DS,
+ knot_dname_t **apex);
+
+/**
+ * Unpack dname and type from db key
+ * @param key db key representation
+ * @param buf output buffer of domain name in dname format
+ * @param type output for type
+ * @return length of dname or an errcode
+ * @note only "exact hits" are considered ATM, moreover xNAME records
+ * are "hidden" as NS. (see comments in struct entry_h)
+ */
+KR_EXPORT
+int kr_unpack_cache_key(knot_db_val_t key, knot_dname_t *buf, uint16_t *type);
diff --git a/lib/cache/cdb_api.h b/lib/cache/cdb_api.h
new file mode 100644
index 0000000..814a5f5
--- /dev/null
+++ b/lib/cache/cdb_api.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <libknot/db/db.h>
+
+/* Cache options. */
+struct kr_cdb_opts {
+ const char *path; /*!< Cache URI path. */
+ size_t maxsize; /*!< Suggested cache size in bytes. */
+};
+
+/*! Cache database API.
+ * This is a simplified version of generic DB API from libknot,
+ * that is tailored to caching purposes.
+ */
+struct kr_cdb_api {
+ const char *name;
+
+ /* Context operations */
+
+ int (*open)(knot_db_t **db, struct kr_cdb_opts *opts, knot_mm_t *mm);
+ void (*close)(knot_db_t *db);
+ int (*count)(knot_db_t *db);
+ int (*clear)(knot_db_t *db);
+
+ /** Run after a row of operations to release transaction/lock if needed. */
+ int (*sync)(knot_db_t *db);
+
+ /* Data access */
+
+ int (*read)(knot_db_t *db, const knot_db_val_t *key, knot_db_val_t *val,
+ int maxcount);
+ int (*write)(knot_db_t *db, const knot_db_val_t *key, knot_db_val_t *val,
+ int maxcount);
+
+ /** Remove maxcount keys.
+ * \returns the number of succesfully removed keys or the first error code
+ * It returns on first error, but ENOENT is not considered an error. */
+ int (*remove)(knot_db_t *db, knot_db_val_t keys[], int maxcount);
+
+ /* Specialised operations */
+
+ /** Find key-value pairs that are prefixed by the given key, limited by maxcount.
+ * \return the number of pairs or negative error. */
+ int (*match)(knot_db_t *db, knot_db_val_t *key, knot_db_val_t keyval[][2], int maxcount);
+ /** Not implemented ATM. */
+ int (*prune)(knot_db_t *db, int maxcount);
+
+ /** Less-or-equal search (lexicographic ordering).
+ * On successful return, key->data and val->data point to DB-owned data.
+ * return: 0 for equality, > 0 for less, < 0 kr_error */
+ int (*read_leq)(knot_db_t *db, knot_db_val_t *key, knot_db_val_t *val);
+};
diff --git a/lib/cache/cdb_lmdb.c b/lib/cache/cdb_lmdb.c
new file mode 100644
index 0000000..621d2e8
--- /dev/null
+++ b/lib/cache/cdb_lmdb.c
@@ -0,0 +1,710 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <lmdb.h>
+
+#include "contrib/cleanup.h"
+#include "lib/cache/cdb_lmdb.h"
+#include "lib/cache/api.h"
+#include "lib/utils.h"
+
+
+/* Defines */
+#define LMDB_DIR_MODE 0770
+#define LMDB_FILE_MODE 0660
+
+struct lmdb_env
+{
+ size_t mapsize;
+ MDB_dbi dbi;
+ MDB_env *env;
+
+ /** Cached transactions
+ *
+ * - only one of (ro,rw) may be active at once
+ * - non-NULL .ro may be active or reset
+ * - non-NULL .rw is always active
+ */
+ struct {
+ bool ro_active, ro_curs_active;
+ MDB_txn *ro, *rw;
+ MDB_cursor *ro_curs;
+ } txn;
+};
+
+/** @brief Convert LMDB error code. */
+static int lmdb_error(int error)
+{
+ /* _BAD_TXN may happen with overfull DB,
+ * even during mdb_get with a single fork :-/ */
+ if (error == MDB_BAD_TXN) {
+ kr_log_info("[cache] MDB_BAD_TXN, probably overfull\n");
+ error = ENOSPC;
+ }
+ switch (error) {
+ case MDB_SUCCESS:
+ return kr_ok();
+ case MDB_NOTFOUND:
+ return kr_error(ENOENT);
+ case ENOSPC:
+ case MDB_MAP_FULL:
+ case MDB_TXN_FULL:
+ return kr_error(ENOSPC);
+ default:
+ kr_log_error("[cache] LMDB error: %s\n", mdb_strerror(error));
+ return kr_error(error);
+ }
+}
+
+/** Conversion between knot and lmdb structs for values. */
+static inline knot_db_val_t val_mdb2knot(MDB_val v)
+{
+ return (knot_db_val_t){ .len = v.mv_size, .data = v.mv_data };
+}
+static inline MDB_val val_knot2mdb(knot_db_val_t v)
+{
+ return (MDB_val){ .mv_size = v.len, .mv_data = v.data };
+}
+
+
+/*! \brief Set the environment map size.
+ * \note This also sets the maximum database size, see \fn mdb_env_set_mapsize
+ */
+static int set_mapsize(MDB_env *env, size_t map_size)
+{
+ long page_size = sysconf(_SC_PAGESIZE);
+ if (page_size <= 0) {
+ return KNOT_ERROR;
+ }
+
+ /* Round to page size. */
+ map_size = (map_size / page_size) * page_size;
+ int ret = mdb_env_set_mapsize(env, map_size);
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+
+ return 0;
+}
+
+#define FLAG_RENEW (2*MDB_RDONLY)
+/** mdb_txn_begin or _renew + handle MDB_MAP_RESIZED.
+ *
+ * The retrying logic for MDB_MAP_RESIZED is so ugly that it has its own function.
+ * \note this assumes no transactions are active
+ * \return MDB_ errcode, not usual kr_error(...)
+ */
+static int txn_get_noresize(struct lmdb_env *env, unsigned int flag, MDB_txn **txn)
+{
+ assert(!env->txn.rw && (!env->txn.ro || !env->txn.ro_active));
+ int ret;
+ if (flag == FLAG_RENEW) {
+ ret = mdb_txn_renew(*txn);
+ } else {
+ ret = mdb_txn_begin(env->env, NULL, flag, txn);
+ }
+ if (ret != MDB_MAP_RESIZED) {
+ return ret;
+ }
+ //:unlikely
+ /* Another process increased the size; let's try to recover. */
+ kr_log_info("[cache] detected size increased by another process\n");
+ ret = mdb_env_set_mapsize(env->env, 0);
+ if (ret != MDB_SUCCESS) {
+ return ret;
+ }
+ if (flag == FLAG_RENEW) {
+ ret = mdb_txn_renew(*txn);
+ } else {
+ ret = mdb_txn_begin(env->env, NULL, flag, txn);
+ }
+ return ret;
+}
+
+/** Obtain a transaction. (they're cached in env->txn) */
+static int txn_get(struct lmdb_env *env, MDB_txn **txn, bool rdonly)
+{
+ assert(env && txn);
+ if (env->txn.rw) {
+ /* Reuse the *open* RW txn even if only reading is requested.
+ * We leave the management of this to the cdb_sync command.
+ * The user may e.g. want to do some reads between the writes. */
+ *txn = env->txn.rw;
+ return kr_ok();
+ }
+
+ if (!rdonly) {
+ /* avoid two active transactions */
+ if (env->txn.ro && env->txn.ro_active) {
+ mdb_txn_reset(env->txn.ro);
+ env->txn.ro_active = false;
+ env->txn.ro_curs_active = false;
+ }
+ int ret = txn_get_noresize(env, 0/*RW*/, &env->txn.rw);
+ if (ret == MDB_SUCCESS) {
+ *txn = env->txn.rw;
+ assert(*txn);
+ }
+ return lmdb_error(ret);
+ }
+
+ /* Get an active RO txn and return it. */
+ int ret = MDB_SUCCESS;
+ if (!env->txn.ro) { //:unlikely
+ ret = txn_get_noresize(env, MDB_RDONLY, &env->txn.ro);
+ } else if (!env->txn.ro_active) {
+ ret = txn_get_noresize(env, FLAG_RENEW, &env->txn.ro);
+ }
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+ env->txn.ro_active = true;
+ *txn = env->txn.ro;
+ assert(*txn);
+ return kr_ok();
+}
+
+static int cdb_sync(knot_db_t *db)
+{
+ struct lmdb_env *env = db;
+ int ret = kr_ok();
+ if (env->txn.rw) {
+ ret = lmdb_error(mdb_txn_commit(env->txn.rw));
+ env->txn.rw = NULL; /* the transaction got freed even in case of errors */
+ } else if (env->txn.ro && env->txn.ro_active) {
+ mdb_txn_reset(env->txn.ro);
+ env->txn.ro_active = false;
+ env->txn.ro_curs_active = false;
+ }
+ return ret;
+}
+
+/** Obtain a read-only cursor (and a read-only transaction). */
+static int txn_curs_get(struct lmdb_env *env, MDB_cursor **curs)
+{
+ assert(env && curs);
+ if (env->txn.ro_curs_active) {
+ goto success;
+ }
+ /* Only in a read-only txn; TODO: it's a bit messy/coupled */
+ if (env->txn.rw) {
+ int ret = cdb_sync(env);
+ if (ret) return ret;
+ }
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, true);
+ if (ret) return ret;
+
+ if (env->txn.ro_curs) {
+ ret = mdb_cursor_renew(txn, env->txn.ro_curs);
+ } else {
+ ret = mdb_cursor_open(txn, env->dbi, &env->txn.ro_curs);
+ }
+ if (ret) return ret;
+ env->txn.ro_curs_active = true;
+success:
+ assert(env->txn.ro_curs_active && env->txn.ro && env->txn.ro_active
+ && !env->txn.rw);
+ *curs = env->txn.ro_curs;
+ assert(*curs);
+ return kr_ok();
+}
+
+static void free_txn_ro(struct lmdb_env *env)
+{
+ if (env->txn.ro) {
+ mdb_txn_abort(env->txn.ro);
+ env->txn.ro = NULL;
+ }
+ if (env->txn.ro_curs) {
+ mdb_cursor_close(env->txn.ro_curs);
+ env->txn.ro_curs = NULL;
+ }
+}
+
+/*! \brief Close the database. */
+static void cdb_close_env(struct lmdb_env *env)
+{
+ assert(env && env->env);
+
+ /* Get rid of any transactions. */
+ cdb_sync(env);
+ free_txn_ro(env);
+
+ mdb_env_sync(env->env, 1);
+ mdb_dbi_close(env->env, env->dbi);
+ mdb_env_close(env->env);
+ memset(env, 0, sizeof(*env));
+}
+
+/*! \brief Open database environment. */
+static int cdb_open_env(struct lmdb_env *env, unsigned flags, const char *path, size_t mapsize)
+{
+ int ret = mkdir(path, LMDB_DIR_MODE);
+ if (ret == -1 && errno != EEXIST) {
+ return kr_error(errno);
+ }
+
+ MDB_env *mdb_env = NULL;
+ ret = mdb_env_create(&mdb_env);
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+
+ ret = set_mapsize(mdb_env, mapsize);
+ if (ret != 0) {
+ mdb_env_close(mdb_env);
+ return ret;
+ }
+
+ ret = mdb_env_open(mdb_env, path, flags, LMDB_FILE_MODE);
+ if (ret != MDB_SUCCESS) {
+ mdb_env_close(mdb_env);
+ return lmdb_error(ret);
+ }
+
+ /* Keep the environment pointer. */
+ env->env = mdb_env;
+ env->mapsize = mapsize;
+ return 0;
+}
+
+static int cdb_open(struct lmdb_env *env, const char *path, size_t mapsize)
+{
+ /* Cache doesn't require durability, we can be
+ * loose with the requirements as a tradeoff for speed. */
+ const unsigned flags = MDB_WRITEMAP | MDB_MAPASYNC | MDB_NOTLS;
+ int ret = cdb_open_env(env, flags, path, mapsize);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Open the database. */
+ MDB_txn *txn = NULL;
+ ret = mdb_txn_begin(env->env, NULL, 0, &txn);
+ if (ret != MDB_SUCCESS) {
+ mdb_env_close(env->env);
+ return lmdb_error(ret);
+ }
+
+ ret = mdb_dbi_open(txn, NULL, 0, &env->dbi);
+ if (ret != MDB_SUCCESS) {
+ mdb_txn_abort(txn);
+ mdb_env_close(env->env);
+ return lmdb_error(ret);
+ }
+
+ ret = mdb_txn_commit(txn);
+ if (ret != MDB_SUCCESS) {
+ mdb_env_close(env->env);
+ return lmdb_error(ret);
+ }
+
+ return 0;
+}
+
+static int cdb_init(knot_db_t **db, struct kr_cdb_opts *opts, knot_mm_t *pool)
+{
+ if (!db || !opts) {
+ return kr_error(EINVAL);
+ }
+
+ struct lmdb_env *env = malloc(sizeof(*env));
+ if (!env) {
+ return kr_error(ENOMEM);
+ }
+ memset(env, 0, sizeof(struct lmdb_env));
+
+ /* Clear stale lockfiles. */
+ auto_free char *lockfile = kr_strcatdup(2, opts->path, "/.cachelock");
+ if (lockfile) {
+ if (unlink(lockfile) == 0) {
+ kr_log_info("[cache] cleared stale lockfile '%s'\n", lockfile);
+ } else if (errno != ENOENT) {
+ kr_log_info("[cache] failed to clear stale lockfile '%s': %s\n", lockfile,
+ strerror(errno));
+ }
+ }
+
+ /* Open the database. */
+ int ret = cdb_open(env, opts->path, opts->maxsize);
+ if (ret != 0) {
+ free(env);
+ return ret;
+ }
+
+ *db = env;
+ return 0;
+}
+
+static void cdb_deinit(knot_db_t *db)
+{
+ struct lmdb_env *env = db;
+ cdb_close_env(env);
+ free(env);
+}
+
+static int cdb_count(knot_db_t *db)
+{
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, true);
+ if (ret != 0) {
+ return ret;
+ }
+
+ MDB_stat stat;
+ ret = mdb_stat(txn, env->dbi, &stat);
+
+ return (ret == MDB_SUCCESS) ? stat.ms_entries : lmdb_error(ret);
+}
+
+static int cdb_clear(knot_db_t *db)
+{
+ struct lmdb_env *env = db;
+ /* First try mdb_drop() to clear the DB; this may fail with ENOSPC. */
+ /* If we didn't do this, explicit cache.clear() ran on an instance
+ * would lead to the instance detaching from the cache of others,
+ * until they reopened cache explicitly or cleared it for some reason.
+ */
+ {
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, false);
+ if (ret == kr_ok()) {
+ ret = lmdb_error(mdb_drop(txn, env->dbi, 0));
+ if (ret == kr_ok()) {
+ ret = cdb_sync(db);
+ }
+ if (ret == kr_ok()) {
+ return ret;
+ }
+ }
+ kr_log_info("[cache] clearing error, falling back\n");
+ }
+
+ /* We are about to switch to a different file, so end all txns, to be sure. */
+ (void) cdb_sync(db);
+ free_txn_ro(db);
+
+ /* Since there is no guarantee that there will be free
+ * pages to hold whole dirtied db for transaction-safe clear,
+ * we simply remove the database files and reopen.
+ * We can afford this since other readers will continue to read
+ * from removed file, but will reopen when encountering next
+ * error. */
+ mdb_filehandle_t fd = -1;
+ int ret = mdb_env_get_fd(env->env, &fd);
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+ const char *path = NULL;
+ ret = mdb_env_get_path(env->env, &path);
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+
+ auto_free char *mdb_datafile = kr_strcatdup(2, path, "/data.mdb");
+ auto_free char *mdb_lockfile = kr_strcatdup(2, path, "/lock.mdb");
+ auto_free char *lockfile = kr_strcatdup(2, path, "/.cachelock");
+ if (!mdb_datafile || !mdb_lockfile || !lockfile) {
+ return kr_error(ENOMEM);
+ }
+ /* Find if we get a lock on lockfile. */
+ ret = open(lockfile, O_CREAT|O_EXCL|O_RDONLY, S_IRUSR);
+ if (ret == -1) {
+ kr_log_error("[cache] clearing failed to get ./.cachelock; retry later\n");
+ /* As we're out of space (almost certainly - mdb_drop didn't work),
+ * we will retry on the next failing write operation. */
+ return kr_error(errno);
+ }
+ close(ret);
+ /* We acquired lockfile. Now find whether *.mdb are what we have open now. */
+ struct stat old_stat, new_stat;
+ if (fstat(fd, &new_stat) || stat(mdb_datafile, &old_stat)) {
+ ret = errno;
+ unlink(lockfile);
+ return kr_error(ret);
+ }
+ /* Remove underlying files only if current open environment
+ * points to file on the disk. Otherwise just reopen as someone
+ * else has already removed the files.
+ */
+ if (old_stat.st_dev == new_stat.st_dev && old_stat.st_ino == new_stat.st_ino) {
+ kr_log_verbose("[cache] clear: identical files, unlinking\n");
+ // coverity[toctou]
+ unlink(mdb_datafile);
+ unlink(mdb_lockfile);
+ } else
+ kr_log_verbose("[cache] clear: not identical files, reopening\n");
+ /* Keep copy as it points to current handle internals. */
+ auto_free char *path_copy = strdup(path);
+ size_t mapsize = env->mapsize;
+ cdb_close_env(env);
+ ret = cdb_open(env, path_copy, mapsize);
+ /* Environment updated, release lockfile. */
+ unlink(lockfile);
+ return ret;
+}
+
+static int cdb_readv(knot_db_t *db, const knot_db_val_t *key, knot_db_val_t *val,
+ int maxcount)
+{
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, true);
+ if (ret) {
+ return ret;
+ }
+
+ for (int i = 0; i < maxcount; ++i) {
+ /* Convert key structs */
+ MDB_val _key = val_knot2mdb(key[i]);
+ MDB_val _val = val_knot2mdb(val[i]);
+ ret = mdb_get(txn, env->dbi, &_key, &_val);
+ if (ret != MDB_SUCCESS) {
+ ret = lmdb_error(ret);
+ if (ret == kr_error(ENOSPC)) {
+ /* we're likely to be forced to cache clear anyway */
+ ret = kr_error(ENOENT);
+ }
+ return ret;
+ }
+ /* Update the result. */
+ val[i] = val_mdb2knot(_val);
+ }
+ return kr_ok();
+}
+
+static int cdb_write(struct lmdb_env *env, MDB_txn **txn, const knot_db_val_t *key,
+ knot_db_val_t *val, unsigned flags)
+{
+ /* Convert key structs and write */
+ MDB_val _key = val_knot2mdb(*key);
+ MDB_val _val = val_knot2mdb(*val);
+ int ret = mdb_put(*txn, env->dbi, &_key, &_val, flags);
+
+ /* Try to recover from doing too much writing in a single transaction. */
+ if (ret == MDB_TXN_FULL) {
+ ret = cdb_sync(env);
+ if (ret) {
+ ret = txn_get(env, txn, false);
+ }
+ if (ret) {
+ ret = mdb_put(*txn, env->dbi, &_key, &_val, flags);
+ }
+ }
+ if (ret != MDB_SUCCESS) {
+ return lmdb_error(ret);
+ }
+
+ /* Update the result. */
+ val->data = _val.mv_data;
+ val->len = _val.mv_size;
+ return kr_ok();
+}
+
+static int cdb_writev(knot_db_t *db, const knot_db_val_t *key, knot_db_val_t *val,
+ int maxcount)
+{
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, false);
+
+ for (int i = 0; ret == kr_ok() && i < maxcount; ++i) {
+ /* This is LMDB specific optimisation,
+ * if caller specifies value with NULL data and non-zero length,
+ * LMDB will preallocate the entry for caller and leave write
+ * transaction open, caller is responsible for syncing thus committing transaction.
+ */
+ unsigned mdb_flags = 0;
+ if (val[i].len > 0 && val[i].data == NULL) {
+ mdb_flags |= MDB_RESERVE;
+ }
+ ret = cdb_write(env, &txn, &key[i], &val[i], mdb_flags);
+ }
+
+ return ret;
+}
+
+static int cdb_remove(knot_db_t *db, knot_db_val_t keys[], int maxcount)
+{
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, false);
+ int deleted = 0;
+
+ for (int i = 0; ret == kr_ok() && i < maxcount; ++i) {
+ MDB_val _key = val_knot2mdb(keys[i]);
+ MDB_val val = { 0, NULL };
+ ret = lmdb_error(mdb_del(txn, env->dbi, &_key, &val));
+ if (ret == kr_ok())
+ deleted++;
+ else if (ret == KNOT_ENOENT)
+ ret = kr_ok(); /* skip over non-existing entries */
+ }
+
+ return ret < 0 ? ret : deleted;
+}
+
+static int cdb_match(knot_db_t *db, knot_db_val_t *key, knot_db_val_t keyval[][2], int maxcount)
+{
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, true);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* LATER(optim.): use txn_curs_get() instead, to save resources. */
+ MDB_cursor *cur = NULL;
+ ret = mdb_cursor_open(txn, env->dbi, &cur);
+ if (ret != 0) {
+ return lmdb_error(ret);
+ }
+
+ MDB_val cur_key = val_knot2mdb(*key);
+ MDB_val cur_val = { 0, NULL };
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_SET_RANGE);
+ if (ret != MDB_SUCCESS) {
+ mdb_cursor_close(cur);
+ return lmdb_error(ret);
+ }
+
+ int results = 0;
+ while (ret == MDB_SUCCESS) {
+ /* Retrieve current key and compare with prefix */
+ if (cur_key.mv_size < key->len || memcmp(cur_key.mv_data, key->data, key->len) != 0) {
+ break;
+ }
+ /* Add to result set */
+ if (results < maxcount) {
+ keyval[results][0] = val_mdb2knot(cur_key);
+ keyval[results][1] = val_mdb2knot(cur_val);
+ ++results;
+ } else {
+ break;
+ }
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_NEXT);
+ }
+
+ mdb_cursor_close(cur);
+ return results;
+}
+
+
+static int cdb_prune(knot_db_t *db, int limit)
+{
+ return -1;
+#if 0
+ /* Sync in-flight transactions */
+ cdb_sync(db);
+
+ /* Prune old records */
+ struct lmdb_env *env = db;
+ MDB_txn *txn = NULL;
+ int ret = txn_get(env, &txn, false);
+ if (ret != 0) {
+ return ret;
+ }
+
+ MDB_cursor *cur = NULL;
+ ret = mdb_cursor_open(txn, env->dbi, &cur);
+ if (ret != 0) {
+ return lmdb_error(ret);
+ }
+
+ MDB_val cur_key, cur_val;
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_FIRST);
+ if (ret != 0) {
+ mdb_cursor_close(cur);
+ return lmdb_error(ret);
+ }
+
+ int results = 0;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ while (ret == 0 && results < limit) {
+ /* Ignore special namespaces. */
+ if (cur_key.mv_size < 2 || ((const char *)cur_key.mv_data)[0] == 'V') {
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_NEXT);
+ continue;
+ }
+ /* Check entry age. */
+ struct kr_cache_entry *entry = cur_val.mv_data;
+ if (entry->timestamp > now.tv_sec ||
+ (now.tv_sec - entry->timestamp) < entry->ttl) {
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_NEXT);
+ continue;
+ }
+ /* Remove entry */
+ mdb_cursor_del(cur, 0);
+ ++results;
+ ret = mdb_cursor_get(cur, &cur_key, &cur_val, MDB_NEXT);
+ }
+ mdb_cursor_close(cur);
+ return ret < 0 ? ret : results;
+#endif
+}
+
+static int cdb_read_leq(knot_db_t *env, knot_db_val_t *key, knot_db_val_t *val)
+{
+ assert(env && key && key->data && val);
+ MDB_cursor *curs = NULL;
+ int ret = txn_curs_get(env, &curs);
+ if (ret) return ret;
+
+ MDB_val key2_m = val_knot2mdb(*key);
+ MDB_val val2_m = { 0, NULL };
+ ret = mdb_cursor_get(curs, &key2_m, &val2_m, MDB_SET_RANGE);
+ if (ret) return lmdb_error(ret);
+ /* test for equality //:unlikely */
+ if (key2_m.mv_size == key->len
+ && memcmp(key2_m.mv_data, key->data, key->len) == 0) {
+ ret = 0; /* equality */
+ goto success;
+ }
+ /* we must be greater than key; do one step to smaller */
+ ret = mdb_cursor_get(curs, &key2_m, &val2_m, MDB_PREV);
+ if (ret) return lmdb_error(ret);
+ ret = 1;
+success:
+ /* finalize the output */
+ *key = val_mdb2knot(key2_m);
+ *val = val_mdb2knot(val2_m);
+ return ret;
+}
+
+
+const struct kr_cdb_api *kr_cdb_lmdb(void)
+{
+ static const struct kr_cdb_api api = {
+ "lmdb",
+ cdb_init, cdb_deinit, cdb_count, cdb_clear, cdb_sync,
+ cdb_readv, cdb_writev, cdb_remove,
+ cdb_match, cdb_prune,
+ cdb_read_leq
+ };
+
+ return &api;
+}
diff --git a/lib/cache/cdb_lmdb.h b/lib/cache/cdb_lmdb.h
new file mode 100644
index 0000000..bc2c7d6
--- /dev/null
+++ b/lib/cache/cdb_lmdb.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "lib/cache/cdb_api.h"
+#include "lib/defines.h"
+
+KR_EXPORT KR_CONST
+const struct kr_cdb_api *kr_cdb_lmdb(void);
diff --git a/lib/cache/entry_list.c b/lib/cache/entry_list.c
new file mode 100644
index 0000000..6a5001c
--- /dev/null
+++ b/lib/cache/entry_list.c
@@ -0,0 +1,293 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of chaining in struct entry_h. Prototypes in ./impl.h
+ */
+
+#include "lib/cache/impl.h"
+#include "lib/utils.h"
+
+
+static int entry_h_len(knot_db_val_t val);
+
+
+void entry_list_memcpy(struct entry_apex *ea, entry_list_t list)
+{
+ assert(ea);
+ memset(ea, 0, offsetof(struct entry_apex, data));
+ ea->has_ns = list[EL_NS ].len;
+ ea->has_cname = list[EL_CNAME ].len;
+ ea->has_dname = list[EL_DNAME ].len;
+ for (int i = 0; i < ENTRY_APEX_NSECS_CNT; ++i) {
+ ea->nsecs[i] = list[i].len == 0 ? 0 :
+ (list[i].len == 4 ? 1 : 3);
+ }
+ uint8_t *it = ea->data;
+ for (int i = 0; i < EL_LENGTH; ++i) {
+ if (list[i].data) {
+ memcpy(it, list[i].data, list[i].len);
+ /* LATER(optim.): coalesce consecutive writes? */
+ } else {
+ list[i].data = it;
+ }
+ it += to_even(list[i].len);
+ }
+}
+
+int entry_list_parse(const knot_db_val_t val, entry_list_t list)
+{
+ const bool ok = val.data && val.len && list;
+ if (!ok) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ /* Parse the apex itself (nsec parameters). */
+ const struct entry_apex *ea = entry_apex_consistent(val);
+ if (!ea) {
+ return kr_error(EILSEQ);
+ }
+ const uint8_t *it = ea->data,
+ *it_bound = knot_db_val_bound(val);
+ for (int i = 0; i < ENTRY_APEX_NSECS_CNT; ++i) {
+ if (it > it_bound) {
+ return kr_error(EILSEQ);
+ }
+ list[i].data = (void *)it;
+ switch (ea->nsecs[i]) {
+ case 0:
+ list[i].len = 0;
+ break;
+ case 1:
+ list[i].len = sizeof(uint32_t); /* just timestamp */
+ break;
+ case 3: { /* timestamp + NSEC3PARAM wire */
+ if (it + sizeof(uint32_t) + 4 > it_bound) {
+ return kr_error(EILSEQ);
+ }
+ list[i].len = sizeof(uint32_t)
+ + nsec_p_rdlen(it + sizeof(uint32_t));
+ break;
+ }
+ default:
+ return kr_error(EILSEQ);
+ };
+ it += to_even(list[i].len);
+ }
+ /* Parse every entry_h. */
+ for (int i = ENTRY_APEX_NSECS_CNT; i < EL_LENGTH; ++i) {
+ list[i].data = (void *)it;
+ bool has_type;
+ switch (i) {
+ case EL_NS: has_type = ea->has_ns; break;
+ case EL_CNAME: has_type = ea->has_cname; break;
+ case EL_DNAME: has_type = ea->has_dname; break;
+ default: assert(false); return kr_error(EINVAL); /* something very bad */
+ }
+ if (!has_type) {
+ list[i].len = 0;
+ continue;
+ }
+ if (it >= it_bound) {
+ assert(!EILSEQ);
+ return kr_error(EILSEQ);
+ }
+ const int len = entry_h_len(
+ (knot_db_val_t){ .data = (void *)it, .len = it_bound - it });
+ if (len < 0) {
+ assert(false);
+ return kr_error(len);
+ }
+ list[i].len = len;
+ it += to_even(len);
+ }
+ assert(it == it_bound);
+ return kr_ok();
+}
+
+/** Given a valid entry header, find its length (i.e. offset of the next entry).
+ * \param val The beginning of the data and the bound (read only).
+ */
+static int entry_h_len(const knot_db_val_t val)
+{
+ const bool ok = val.data && ((ssize_t)val.len) > 0;
+ if (!ok) return kr_error(EINVAL);
+ const struct entry_h *eh = val.data;
+ const uint8_t *d = eh->data; /* iterates over the data in entry */
+ const uint8_t *data_bound = knot_db_val_bound(val);
+ if (d >= data_bound) return kr_error(EILSEQ);
+ if (!eh->is_packet) { /* Positive RRset + its RRsig set (may be empty). */
+ int sets = 2;
+ while (sets-- > 0) {
+ d += rdataset_dematerialized_size(d);
+ if (d > data_bound) {
+ assert(!EILSEQ);
+ return kr_error(EILSEQ);
+ }
+ }
+ } else { /* A "packet" (opaque ATM). */
+ uint16_t len;
+ if (d + sizeof(len) > data_bound) return kr_error(EILSEQ);
+ memcpy(&len, d, sizeof(len));
+ d += 2 + to_even(len);
+ }
+ if (d > data_bound) {
+ assert(!EILSEQ);
+ return kr_error(EILSEQ);
+ }
+ return d - (uint8_t *)val.data;
+}
+
+struct entry_apex * entry_apex_consistent(knot_db_val_t val)
+{
+ //XXX: check lengths, etc.
+ return val.data;
+}
+
+/* See the header file. */
+int entry_h_seek(knot_db_val_t *val, uint16_t type)
+{
+ int i = -1;
+ switch (type) {
+ case KNOT_RRTYPE_NS: i = EL_NS; break;
+ case KNOT_RRTYPE_CNAME: i = EL_CNAME; break;
+ case KNOT_RRTYPE_DNAME: i = EL_DNAME; break;
+ default: return kr_ok();
+ }
+
+ entry_list_t el;
+ int ret = entry_list_parse(*val, el);
+ if (ret) return ret;
+ *val = el[i];
+ return val->len ? kr_ok() : kr_error(ENOENT);
+}
+
+static int cache_write_or_clear(struct kr_cache *cache, const knot_db_val_t *key,
+ knot_db_val_t *val, const struct kr_query *qry)
+{
+ int ret = cache_op(cache, write, key, val, 1);
+ if (!ret) return kr_ok();
+ /* Clear cache if overfull. It's nontrivial to do better with LMDB.
+ * LATER: some garbage-collection mechanism. */
+ if (ret == kr_error(ENOSPC)) {
+ ret = kr_cache_clear(cache);
+ const char *msg = "[cache] clearing because overfull, ret = %d\n";
+ if (ret) {
+ kr_log_error(msg, ret);
+ } else {
+ kr_log_info(msg, ret);
+ ret = kr_error(ENOSPC);
+ }
+ return ret;
+ }
+ VERBOSE_MSG(qry, "=> failed backend write, ret = %d\n", ret);
+ return kr_error(ret ? ret : ENOSPC);
+}
+
+
+/* See the header file. */
+int entry_h_splice(
+ knot_db_val_t *val_new_entry, uint8_t rank,
+ const knot_db_val_t key, const uint16_t ktype, const uint16_t type,
+ const knot_dname_t *owner/*log only*/,
+ const struct kr_query *qry, struct kr_cache *cache, uint32_t timestamp)
+{
+ //TODO: another review, perhaps incuding the API
+ const bool ok = val_new_entry && val_new_entry->len > 0;
+ if (!ok) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ int i_type;
+ switch (type) {
+ case KNOT_RRTYPE_NS: i_type = EL_NS; break;
+ case KNOT_RRTYPE_CNAME: i_type = EL_CNAME; break;
+ case KNOT_RRTYPE_DNAME: i_type = EL_DNAME; break;
+ default: i_type = 0;
+ }
+
+ /* Get eh_orig (original entry), and also el list if multi-entry case. */
+ const struct entry_h *eh_orig = NULL;
+ entry_list_t el;
+ int ret = -1;
+ if (!kr_rank_test(rank, KR_RANK_SECURE) || ktype == KNOT_RRTYPE_NS) {
+ knot_db_val_t val;
+ ret = cache_op(cache, read, &key, &val, 1);
+ if (i_type) {
+ if (!ret) ret = entry_list_parse(val, el);
+ if (ret) memset(el, 0, sizeof(el));
+ val = el[i_type];
+ }
+ /* val is on the entry, in either case (or error) */
+ if (!ret) {
+ eh_orig = entry_h_consistent(val, type);
+ }
+ } else {
+ /* We want to fully overwrite the entry, so don't even read it. */
+ memset(el, 0, sizeof(el));
+ }
+
+ if (!kr_rank_test(rank, KR_RANK_SECURE) && eh_orig) {
+ /* If equal rank was accepted, spoofing a *single* answer would be
+ * enough to e.g. override NS record in AUTHORITY section.
+ * This way they would have to hit the first answer
+ * (whenever TTL nears expiration).
+ * Stale-serving is NOT considered, but TTL 1 would be considered
+ * as expiring anyway, ... */
+ int32_t old_ttl = get_new_ttl(eh_orig, qry, NULL, 0, timestamp);
+ if (old_ttl > 0 && !is_expiring(eh_orig->ttl, old_ttl)
+ && rank <= eh_orig->rank) {
+ WITH_VERBOSE(qry) {
+ auto_free char *type_str = kr_rrtype_text(type),
+ *owner_str = kr_dname_text(owner);
+ VERBOSE_MSG(qry, "=> not overwriting %s %s\n",
+ type_str, owner_str);
+ }
+ return kr_error(EEXIST);
+ }
+ }
+
+ if (!i_type) {
+ /* The non-list types are trivial now. */
+ return cache_write_or_clear(cache, &key, val_new_entry, qry);
+ }
+ /* Now we're in trouble. In some cases, parts of data to be written
+ * is an lmdb entry that may be invalidated by our write request.
+ * (lmdb does even in-place updates!) Therefore we copy all into a buffer.
+ * (We don't bother deallocating from the mempool.)
+ * LATER(optim.): do this only when neccessary, or perhaps another approach.
+ * This is also complicated by the fact that the val_new_entry part
+ * is to be written *afterwards* by the caller.
+ */
+ el[i_type] = (knot_db_val_t){
+ .len = val_new_entry->len,
+ .data = NULL, /* perhaps unclear in the entry_h_splice() API */
+ };
+ knot_db_val_t val = {
+ .len = entry_list_serial_size(el),
+ .data = NULL,
+ };
+ void *buf = mm_alloc(&qry->request->pool, val.len);
+ entry_list_memcpy(buf, el);
+ ret = cache_write_or_clear(cache, &key, &val, qry);
+ if (ret) return kr_error(ret);
+ memcpy(val.data, buf, val.len); /* we also copy the "empty" space, but well... */
+ val_new_entry->data = (uint8_t *)val.data
+ + ((uint8_t *)el[i_type].data - (uint8_t *)buf);
+ return kr_ok();
+}
+
diff --git a/lib/cache/entry_pkt.c b/lib/cache/entry_pkt.c
new file mode 100644
index 0000000..00e73d4
--- /dev/null
+++ b/lib/cache/entry_pkt.c
@@ -0,0 +1,224 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of packet-caching. Prototypes in ./impl.h
+ *
+ * The packet is stashed in entry_h::data as uint16_t length + full packet wire format.
+ */
+
+#include "lib/utils.h"
+#include "lib/layer/iterate.h" /* kr_response_classify */
+#include "lib/cache/impl.h"
+
+
+/** Compute TTL for a packet. Generally it's minimum TTL, with extra conditions. */
+static uint32_t packet_ttl(const knot_pkt_t *pkt, bool is_negative)
+{
+ bool has_ttl = false;
+ uint32_t ttl = UINT32_MAX;
+ /* Find minimum entry TTL in the packet or SOA minimum TTL. */
+ for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
+ for (unsigned k = 0; k < sec->count; ++k) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, k);
+ if (is_negative) {
+ /* Use SOA minimum TTL for negative answers. */
+ if (rr->type == KNOT_RRTYPE_SOA) {
+ return MIN(rr->ttl, knot_soa_minimum(rr->rrs.rdata));
+ } else {
+ continue; /* Use SOA only for negative answers. */
+ }
+ }
+ if (knot_rrtype_is_metatype(rr->type)) {
+ continue; /* Skip metatypes. */
+ }
+ ttl = MIN(ttl, rr->ttl);
+ }
+ }
+ /* If no valid TTL present, go with zero (will get clamped to minimum). */
+ return has_ttl ? ttl : 0;
+}
+
+
+void stash_pkt(const knot_pkt_t *pkt, const struct kr_query *qry,
+ const struct kr_request *req, const bool has_optout)
+{
+ /* In some cases, stash also the packet. */
+ const bool is_negative = kr_response_classify(pkt)
+ & (PKT_NODATA|PKT_NXDOMAIN);
+ const struct kr_qflags * const qf = &qry->flags;
+ const bool want_negative = qf->DNSSEC_INSECURE || !qf->DNSSEC_WANT || has_optout;
+ const bool want_pkt = qf->DNSSEC_BOGUS /*< useful for +cd answers */
+ || (is_negative && want_negative);
+
+ if (!want_pkt || !knot_wire_get_aa(pkt->wire)
+ || pkt->parsed != pkt->size /*< malformed packet; still can't detect KNOT_EFEWDATA */
+ ) {
+ return;
+ }
+
+ /* Compute rank. If cd bit is set or we got answer via non-validated
+ * forwarding, make the rank bad; otherwise it depends on flags.
+ * TODO: probably make validator attempt validation even with +cd. */
+ uint8_t rank = KR_RANK_AUTH;
+ const bool risky_vldr = is_negative && qf->FORWARD && qf->CNAME;
+ /* ^^ CNAME'ed NXDOMAIN answer in forwarding mode can contain
+ * unvalidated records; original commit: d6e22f476. */
+ if (knot_wire_get_cd(req->qsource.packet->wire) || qf->STUB || risky_vldr) {
+ kr_rank_set(&rank, KR_RANK_OMIT);
+ } else {
+ if (qf->DNSSEC_BOGUS) {
+ kr_rank_set(&rank, KR_RANK_BOGUS);
+ } else if (qf->DNSSEC_INSECURE) {
+ kr_rank_set(&rank, KR_RANK_INSECURE);
+ } else if (!qf->DNSSEC_WANT) {
+ /* no TAs at all, leave _RANK_AUTH */
+ } else if (has_optout) {
+ /* All bad cases should be filtered above,
+ * at least the same way as pktcache in kresd 1.5.x. */
+ kr_rank_set(&rank, KR_RANK_SECURE);
+ } else assert(false);
+ }
+
+ const uint16_t pkt_type = knot_pkt_qtype(pkt);
+ const knot_dname_t *owner = knot_pkt_qname(pkt); /* qname can't be compressed */
+
+ // LATER: nothing exists under NXDOMAIN. Implement that (optionally)?
+#if 0
+ if (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NXDOMAIN
+ /* && !qf->DNSSEC_INSECURE */ ) {
+ pkt_type = KNOT_RRTYPE_NS;
+ }
+#endif
+
+ /* Construct the key under which the pkt will be stored. */
+ struct key k_storage, *k = &k_storage;
+ knot_db_val_t key;
+ int ret = kr_dname_lf(k->buf, owner, false);
+ if (ret) {
+ /* A server might (incorrectly) reply with QDCOUNT=0. */
+ assert(owner == NULL);
+ return;
+ }
+ key = key_exact_type_maypkt(k, pkt_type);
+
+ /* For now we stash the full packet byte-exactly as it came from upstream. */
+ const uint16_t pkt_size = pkt->size;
+ knot_db_val_t val_new_entry = {
+ .data = NULL,
+ .len = offsetof(struct entry_h, data) + sizeof(pkt_size) + pkt->size,
+ };
+ /* Prepare raw memory for the new entry and fill it. */
+ struct kr_cache *cache = &req->ctx->cache;
+ ret = entry_h_splice(&val_new_entry, rank, key, k->type, pkt_type,
+ owner, qry, cache, qry->timestamp.tv_sec);
+ if (ret) return; /* some aren't really errors */
+ assert(val_new_entry.data);
+ struct entry_h *eh = val_new_entry.data;
+ memset(eh, 0, offsetof(struct entry_h, data));
+ eh->time = qry->timestamp.tv_sec;
+ eh->ttl = MAX(MIN(packet_ttl(pkt, is_negative), cache->ttl_max), cache->ttl_min);
+ eh->rank = rank;
+ eh->is_packet = true;
+ eh->has_optout = qf->DNSSEC_OPTOUT;
+ memcpy(eh->data, &pkt_size, sizeof(pkt_size));
+ memcpy(eh->data + sizeof(pkt_size), pkt->wire, pkt_size);
+
+ WITH_VERBOSE(qry) {
+ auto_free char *type_str = kr_rrtype_text(pkt_type),
+ *owner_str = kr_dname_text(owner);
+ VERBOSE_MSG(qry, "=> stashed packet: rank 0%.2o, TTL %d, "
+ "%s %s (%d B)\n",
+ eh->rank, eh->ttl,
+ type_str, owner_str, (int)val_new_entry.len);
+ }
+}
+
+
+int answer_from_pkt(kr_layer_t *ctx, knot_pkt_t *pkt, uint16_t type,
+ const struct entry_h *eh, const void *eh_bound, uint32_t new_ttl)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ uint16_t pkt_len;
+ memcpy(&pkt_len, eh->data, sizeof(pkt_len));
+ if (pkt_len > pkt->max_size) {
+ return kr_error(ENOENT);
+ }
+
+ /* Copy answer and reparse it, but keep the original message id. */
+ uint16_t msgid = knot_wire_get_id(pkt->wire);
+ knot_pkt_clear(pkt);
+ memcpy(pkt->wire, eh->data + 2, pkt_len);
+ pkt->size = pkt_len;
+ int ret = knot_pkt_parse(pkt, 0);
+ if (ret == KNOT_EFEWDATA || ret == KNOT_EMALF) {
+ return kr_error(ENOENT);
+ /* LATER(opt): try harder to avoid stashing such packets */
+ }
+ if (ret != KNOT_EOK) {
+ assert(!ret);
+ return kr_error(ret);
+ }
+ knot_wire_set_id(pkt->wire, msgid);
+
+ /* Add rank into the additional field. */
+ for (size_t i = 0; i < pkt->rrset_count; ++i) {
+ assert(!pkt->rr[i].additional);
+ uint8_t *rr_rank = mm_alloc(&pkt->mm, sizeof(*rr_rank));
+ if (!rr_rank) {
+ return kr_error(ENOMEM);
+ }
+ *rr_rank = eh->rank;
+ pkt->rr[i].additional = rr_rank;
+ }
+
+ /* Adjust TTL in each record. */
+ const uint32_t drift = eh->ttl - new_ttl;
+ for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
+ for (unsigned k = 0; k < sec->count; ++k) {
+ knot_rrset_t *rrs = // vv FIXME??
+ /*const-cast*/(knot_rrset_t *)knot_pkt_rr(sec, k);
+ /* We need to be careful: due to enforcing minimum TTL
+ * on packet, some records may be below that value.
+ * We keep those records at TTL 0. */
+ if (rrs->ttl >= drift) {
+ rrs->ttl -= drift;
+ } else {
+ rrs->ttl = 0;
+ }
+ }
+ }
+
+ /* Finishing touches. TODO: perhaps factor out */
+ struct kr_qflags * const qf = &qry->flags;
+ qf->EXPIRING = is_expiring(eh->ttl, new_ttl);
+ qf->CACHED = true;
+ qf->NO_MINIMIZE = true;
+ qf->DNSSEC_INSECURE = kr_rank_test(eh->rank, KR_RANK_INSECURE);
+ qf->DNSSEC_BOGUS = kr_rank_test(eh->rank, KR_RANK_BOGUS);
+ if (qf->DNSSEC_INSECURE || qf->DNSSEC_BOGUS) {
+ qf->DNSSEC_WANT = false;
+ }
+ qf->DNSSEC_OPTOUT = eh->has_optout;
+ VERBOSE_MSG(qry, "=> satisfied by exact packet: rank 0%.2o, new TTL %d\n",
+ eh->rank, new_ttl);
+ return kr_ok();
+}
+
diff --git a/lib/cache/entry_rr.c b/lib/cache/entry_rr.c
new file mode 100644
index 0000000..94dd0e8
--- /dev/null
+++ b/lib/cache/entry_rr.c
@@ -0,0 +1,146 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of RRset (de)materialization, i.e. (de)serialization to storage
+ * format used in cache (some repeated fields are omitted). Prototypes in ./impl.h
+ */
+
+#include "lib/cache/impl.h"
+
+int rdataset_dematerialize(const knot_rdataset_t *rds, uint8_t * restrict data)
+{
+ /* FIXME: either give up on even alignment and thus direct usability
+ * of rdatasets as they are in lmdb, or align inside cdb_* functions
+ * (request sizes one byte longer and shift iff on an odd address). */
+ //if ((size_t)data & 1) VERBOSE_MSG(NULL, "dematerialize: odd address\n");
+ //const uint8_t *data0 = data;
+ if (!data) {
+ assert(data);
+ return kr_error(EINVAL);
+ }
+ const uint16_t rr_count = rds ? rds->count : 0;
+ memcpy(data, &rr_count, sizeof(rr_count));
+ data += sizeof(rr_count);
+ if (rr_count) {
+ size_t size = knot_rdataset_size(rds);
+ memcpy(data, rds->rdata, size);
+ data += size;
+ }
+ //VERBOSE_MSG(NULL, "dematerialized to %d B\n", (int)(data - data0));
+ (void)data;
+ return kr_ok();
+}
+
+/** Materialize a knot_rdataset_t from cache with given TTL.
+ * Return the number of bytes consumed or an error code.
+ */
+static int rdataset_materialize(knot_rdataset_t * restrict rds, const uint8_t * const data,
+ const uint8_t *data_bound, knot_mm_t *pool)
+{
+ assert(rds && data && data_bound && data_bound > data && !rds->rdata
+ /*&& !((size_t)data & 1)*/);
+ assert(pool); /* not required, but that's our current usage; guard leaks */
+ const uint8_t *d = data; /* iterates over the cache data */
+ {
+ uint16_t rr_count;
+ memcpy(&rr_count, d, sizeof(rr_count));
+ d += sizeof(rr_count);
+ rds->count = rr_count;
+ if (!rr_count) { /* avoid mm_alloc(pool, 0); etc. */
+ return d - data;
+ }
+ }
+ /* First sum up the sizes for wire format length. */
+ const knot_rdataset_t rds_tmp = {
+ .count = rds->count,
+ .rdata = (knot_rdata_t *)d,
+ };
+ size_t rds_size = knot_rdataset_size(&rds_tmp); /* TODO: we might overrun here already,
+ but we need to trust cache anyway...*/
+ if (d + rds_size > data_bound) {
+ VERBOSE_MSG(NULL, "materialize: EILSEQ!\n");
+ return kr_error(EILSEQ);
+ }
+ rds->rdata = mm_alloc(pool, rds_size);
+ if (!rds->rdata) {
+ return kr_error(ENOMEM);
+ }
+ memcpy(rds->rdata, d, rds_size);
+ d += rds_size;
+ //VERBOSE_MSG(NULL, "materialized from %d B\n", (int)(d - data));
+ return d - data;
+}
+
+int kr_cache_materialize(knot_rdataset_t *dst, const struct kr_cache_p *ref,
+ knot_mm_t *pool)
+{
+ struct entry_h *eh = ref->raw_data;
+ return rdataset_materialize(dst, eh->data, ref->raw_bound, pool);
+}
+
+
+int entry2answer(struct answer *ans, int id,
+ const struct entry_h *eh, const uint8_t *eh_bound,
+ const knot_dname_t *owner, uint16_t type, uint32_t new_ttl)
+{
+ /* We assume it's zeroed. Do basic sanity check. */
+ if (ans->rrsets[id].set.rr || ans->rrsets[id].sig_rds.rdata
+ || (type == KNOT_RRTYPE_NSEC && ans->nsec_p.raw)
+ || (type == KNOT_RRTYPE_NSEC3 && !ans->nsec_p.raw)
+ )
+ {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ /* Materialize the base RRset. */
+ knot_rrset_t *rr = ans->rrsets[id].set.rr
+ = knot_rrset_new(owner, type, KNOT_CLASS_IN, new_ttl, ans->mm);
+ if (!rr) {
+ assert(!ENOMEM);
+ return kr_error(ENOMEM);
+ }
+ int ret = rdataset_materialize(&rr->rrs, eh->data, eh_bound, ans->mm);
+ if (ret < 0) goto fail;
+ size_t data_off = ret;
+ ans->rrsets[id].set.rank = eh->rank;
+ ans->rrsets[id].set.expiring = is_expiring(eh->ttl, new_ttl);
+ /* Materialize the RRSIG RRset for the answer in (pseudo-)packet. */
+ bool want_rrsigs = true; /* LATER(optim.): might be omitted in some cases. */
+ if (want_rrsigs) {
+ ret = rdataset_materialize(&ans->rrsets[id].sig_rds, eh->data + data_off,
+ eh_bound, ans->mm);
+ if (ret < 0) goto fail;
+ /* Sanity check: we consumed exactly all data. */
+ int unused_bytes = eh_bound - (uint8_t *)eh->data - data_off - ret;
+ if (unused_bytes) {
+ kr_log_error("[cach] entry2answer ERROR: unused bytes: %d\n",
+ unused_bytes);
+ assert(!EILSEQ);
+ ret = kr_error(EILSEQ);
+ goto fail; /* to be on the safe side */
+ }
+ }
+ return kr_ok();
+fail:
+ assert(/*false*/!ret);
+ /* Cleanup the item that we might've (partially) written to. */
+ knot_rrset_free(ans->rrsets[id].set.rr, ans->mm);
+ knot_rdataset_clear(&ans->rrsets[id].sig_rds, ans->mm);
+ memset(&ans->rrsets[id], 0, sizeof(ans->rrsets[id]));
+ return kr_error(ret);
+}
+
diff --git a/lib/cache/impl.h b/lib/cache/impl.h
new file mode 100644
index 0000000..a08f355
--- /dev/null
+++ b/lib/cache/impl.h
@@ -0,0 +1,412 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Header internal for cache implementation(s).
+ * Only LMDB works for now.
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <libdnssec/error.h>
+#include <libdnssec/nsec.h>
+#include <libknot/consts.h>
+#include <libknot/db/db.h>
+#include <libknot/dname.h>
+
+#include "contrib/cleanup.h"
+#include "contrib/murmurhash3/murmurhash3.h" /* hash() for nsec_p_hash() */
+#include "lib/cache/cdb_api.h"
+#include "lib/resolve.h"
+
+/* Cache entry values - binary layout.
+ *
+ * It depends on type which is recognizable by the key.
+ * Code depending on the contents of the key is marked by CACHE_KEY_DEF.
+ *
+ * 'E' entry (exact hit):
+ * - ktype == NS: struct entry_apex - multiple types inside (NS and xNAME);
+ * - ktype != NS: struct entry_h
+ * * is_packet: uint16_t length, the rest is opaque and handled by ./entry_pkt.c
+ * * otherwise RRset + its RRSIG set (possibly empty).
+ * '1' or '3' entry (NSEC or NSEC3)
+ * - struct entry_h, contents is the same as for exact hit
+ * - flags don't make sense there
+ */
+
+struct entry_h {
+ uint32_t time; /**< The time of inception. */
+ uint32_t ttl; /**< TTL at inception moment. Assuming it fits into int32_t ATM. */
+ uint8_t rank : 6; /**< See enum kr_rank */
+ bool is_packet : 1; /**< Negative-answer packet for insecure/bogus name. */
+ bool has_optout : 1; /**< Only for packets; persisted DNSSEC_OPTOUT. */
+ uint8_t _pad; /**< We need even alignment for data now. */
+ uint8_t data[];
+};
+struct entry_apex;
+
+/** Check basic consistency of entry_h for 'E' entries, not looking into ->data.
+ * (for is_packet the length of data is checked)
+ */
+struct entry_h * entry_h_consistent(knot_db_val_t data, uint16_t type);
+
+struct entry_apex * entry_apex_consistent(knot_db_val_t val);
+
+/** Consistency check, ATM common for NSEC and NSEC3. */
+static inline struct entry_h * entry_h_consistent_NSEC(knot_db_val_t data)
+{
+ /* ATM it's enough to just extend the checks for exact entries. */
+ const struct entry_h *eh = entry_h_consistent(data, KNOT_RRTYPE_NSEC);
+ bool ok = eh != NULL;
+ ok = ok && !eh->is_packet && !eh->has_optout;
+ return ok ? /*const-cast*/(struct entry_h *)eh : NULL;
+}
+
+
+/* nsec_p* - NSEC* chain parameters */
+
+static inline int nsec_p_rdlen(const uint8_t *rdata)
+{
+ //TODO: do we really need the zero case?
+ return rdata ? 5 + rdata[4] : 0; /* rfc5155 4.2 and 3.2. */
+}
+static const int NSEC_P_MAXLEN = sizeof(uint32_t) + 5 + 255; // TODO: remove??
+
+/** Hash of NSEC3 parameters, used as a tag to separate different chains for same zone. */
+typedef uint32_t nsec_p_hash_t;
+static inline nsec_p_hash_t nsec_p_mkHash(const uint8_t *nsec_p)
+{
+ assert(nsec_p && !(KNOT_NSEC3_FLAG_OPT_OUT & nsec_p[1]));
+ return hash((const char *)nsec_p, nsec_p_rdlen(nsec_p));
+}
+
+/** NSEC* parameters for the chain. */
+struct nsec_p {
+ const uint8_t *raw; /**< Pointer to raw NSEC3 parameters; NULL for NSEC. */
+ nsec_p_hash_t hash; /**< Hash of `raw`, used for cache keys. */
+ dnssec_nsec3_params_t libknot; /**< Format for libknot; owns malloced memory! */
+};
+
+
+
+/** LATER(optim.): this is overshot, but struct key usage should be cheap ATM. */
+#define KR_CACHE_KEY_MAXLEN (KNOT_DNAME_MAXLEN + 100) /* CACHE_KEY_DEF */
+
+struct key {
+ const knot_dname_t *zname; /**< current zone name (points within qry->sname) */
+ uint8_t zlf_len; /**< length of current zone's lookup format */
+
+ /** Corresponding key type; e.g. NS for CNAME.
+ * Note: NSEC type is ambiguous (exact and range key). */
+ uint16_t type;
+ /** The key data start at buf+1, and buf[0] contains some length.
+ * For details see key_exact* and key_NSEC* functions. */
+ uint8_t buf[KR_CACHE_KEY_MAXLEN];
+ /* LATER(opt.): ^^ probably change the anchoring, so that kr_dname_lf()
+ * doesn't need to move data after knot_dname_lf(). */
+};
+
+static inline size_t key_nwz_off(const struct key *k)
+{
+ /* CACHE_KEY_DEF: zone name lf + 0 ('1' or '3').
+ * NSEC '1' case continues just with the name within zone. */
+ return k->zlf_len + 2;
+}
+static inline size_t key_nsec3_hash_off(const struct key *k)
+{
+ /* CACHE_KEY_DEF NSEC3: tag (nsec_p_hash_t) + 20 bytes NSEC3 name hash) */
+ return key_nwz_off(k) + sizeof(nsec_p_hash_t);
+}
+/** Hash is always SHA1; I see no plans to standardize anything else.
+ * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml#dnssec-nsec3-parameters-3
+ */
+static const int NSEC3_HASH_LEN = 20,
+ NSEC3_HASH_TXT_LEN = 32;
+
+/** Finish constructing string key for for exact search.
+ * It's assumed that kr_dname_lf(k->buf, owner, *) had been ran.
+ */
+knot_db_val_t key_exact_type_maypkt(struct key *k, uint16_t type);
+
+/** Like key_exact_type_maypkt but with extra checks if used for RRs only. */
+static inline knot_db_val_t key_exact_type(struct key *k, uint16_t type)
+{
+ switch (type) {
+ /* Sanity check: forbidden types represented in other way(s). */
+ case KNOT_RRTYPE_NSEC:
+ case KNOT_RRTYPE_NSEC3:
+ assert(false);
+ return (knot_db_val_t){ NULL, 0 };
+ }
+ return key_exact_type_maypkt(k, type);
+}
+
+
+/* entry_h chaining; implementation in ./entry_list.c */
+
+enum { ENTRY_APEX_NSECS_CNT = 2 };
+
+/** Header of 'E' entry with ktype == NS. Inside is private to ./entry_list.c
+ *
+ * We store xNAME at NS type to lower the number of searches in closest_NS().
+ * CNAME is only considered for equal name, of course.
+ * We also store NSEC* parameters at NS type.
+ */
+struct entry_apex {
+ /* ENTRY_H_FLAGS */
+ bool has_ns : 1;
+ bool has_cname : 1;
+ bool has_dname : 1;
+
+ uint8_t pad_; /**< Weird: 1 byte + 2 bytes + x bytes; let's do 2+2+x. */
+ int8_t nsecs[ENTRY_APEX_NSECS_CNT]; /**< values: 0: none, 1: NSEC, 3: NSEC3 */
+ uint8_t data[];
+ /* XXX: if not first, stamp of last being the first?
+ * Purpose: save cache operations if rolled the algo/params long ago. */
+};
+
+/** Indices for decompressed entry_list_t. */
+enum EL {
+ EL_NS = ENTRY_APEX_NSECS_CNT,
+ EL_CNAME,
+ EL_DNAME,
+ EL_LENGTH
+};
+/** Decompressed entry_apex. It's an array of unparsed entry_h references.
+ * Note: arrays are passed "by reference" to functions (in C99). */
+typedef knot_db_val_t entry_list_t[EL_LENGTH];
+
+static inline uint16_t EL2RRTYPE(enum EL i)
+{
+ switch (i) {
+ case EL_NS: return KNOT_RRTYPE_NS;
+ case EL_CNAME: return KNOT_RRTYPE_CNAME;
+ case EL_DNAME: return KNOT_RRTYPE_DNAME;
+ default: assert(false); return 0;
+ }
+}
+
+/** There may be multiple entries within, so rewind `val` to the one we want.
+ *
+ * ATM there are multiple types only for the NS ktype - it also accommodates xNAMEs.
+ * \note `val->len` represents the bound of the whole list, not of a single entry.
+ * \note in case of ENOENT, `val` is still rewound to the beginning of the next entry.
+ * \return error code
+ * TODO: maybe get rid of this API?
+ */
+int entry_h_seek(knot_db_val_t *val, uint16_t type);
+
+/** Prepare space to insert an entry.
+ *
+ * Some checks are performed (rank, TTL), the current entry in cache is copied
+ * with a hole ready for the new entry (old one of the same type is cut out).
+ *
+ * \param val_new_entry The only changing parameter; ->len is read, ->data written.
+ * \return error code
+ */
+int entry_h_splice(
+ knot_db_val_t *val_new_entry, uint8_t rank,
+ const knot_db_val_t key, const uint16_t ktype, const uint16_t type,
+ const knot_dname_t *owner/*log only*/,
+ const struct kr_query *qry, struct kr_cache *cache, uint32_t timestamp);
+
+/** Parse an entry_apex into individual items. @return error code. */
+int entry_list_parse(const knot_db_val_t val, entry_list_t list);
+
+static inline size_t to_even(size_t n)
+{
+ return n + (n & 1);
+}
+
+static inline int entry_list_serial_size(const entry_list_t list)
+{
+ int size = offsetof(struct entry_apex, data);
+ for (int i = 0; i < EL_LENGTH; ++i) {
+ size += to_even(list[i].len);
+ }
+ return size;
+}
+
+/** Fill contents of an entry_apex.
+ *
+ * @note NULL pointers are overwritten - caller may like to fill the space later.
+ */
+void entry_list_memcpy(struct entry_apex *ea, entry_list_t list);
+
+
+
+/* Packet caching; implementation in ./entry_pkt.c */
+
+/** Stash the packet into cache (if suitable, etc.)
+ * \param has_optout whether the packet contains an opt-out NSEC3 */
+void stash_pkt(const knot_pkt_t *pkt, const struct kr_query *qry,
+ const struct kr_request *req, bool has_optout);
+
+/** Try answering from packet cache, given an entry_h.
+ *
+ * This assumes the TTL is OK and entry_h_consistent, but it may still return error.
+ * On success it handles all the rest, incl. qry->flags.
+ */
+int answer_from_pkt(kr_layer_t *ctx, knot_pkt_t *pkt, uint16_t type,
+ const struct entry_h *eh, const void *eh_bound, uint32_t new_ttl);
+
+
+/** Record is expiring if it has less than 1% TTL (or less than 5s) */
+static inline bool is_expiring(uint32_t orig_ttl, uint32_t new_ttl)
+{
+ int64_t nttl = new_ttl; /* avoid potential over/under-flow */
+ return 100 * (nttl - 5) < orig_ttl;
+}
+
+/** Returns signed result so you can inspect how much stale the RR is.
+ *
+ * @param owner name for stale-serving decisions. You may pass NULL to disable stale.
+ * @note: NSEC* uses zone name ATM; for NSEC3 the owner may not even be knowable.
+ * @param type for stale-serving.
+ */
+int32_t get_new_ttl(const struct entry_h *entry, const struct kr_query *qry,
+ const knot_dname_t *owner, uint16_t type, uint32_t now);
+
+
+/* RRset (de)materialization; implementation in ./entry_rr.c */
+
+/** Size of the RR count field */
+#define KR_CACHE_RR_COUNT_SIZE sizeof(uint16_t)
+
+/** Compute size of serialized rdataset. NULL is accepted as empty set. */
+static inline int rdataset_dematerialize_size(const knot_rdataset_t *rds)
+{
+ return KR_CACHE_RR_COUNT_SIZE + (rds == NULL ? 0 : knot_rdataset_size(rds));
+}
+
+static inline int rdataset_dematerialized_size(const uint8_t *data)
+{
+ knot_rdataset_t rds;
+ memcpy(&rds.count, data, sizeof(rds.count));
+ rds.rdata = (knot_rdata_t *)(data + sizeof(rds.count));
+ return sizeof(rds.count) + knot_rdataset_size(&rds);
+}
+
+/** Serialize an rdataset. */
+int rdataset_dematerialize(const knot_rdataset_t *rds, uint8_t * restrict data);
+
+
+/** Partially constructed answer when gathering RRsets from cache. */
+struct answer {
+ int rcode; /**< PKT_NODATA, etc. */
+ struct nsec_p nsec_p; /**< Don't mix different NSEC* parameters in one answer. */
+ knot_mm_t *mm; /**< Allocator for rrsets */
+ struct answer_rrset {
+ ranked_rr_array_entry_t set; /**< set+rank for the main data */
+ knot_rdataset_t sig_rds; /**< RRSIG data, if any */
+ } rrsets[1+1+3]; /**< see AR_ANSWER and friends; only required records are filled */
+};
+enum {
+ AR_ANSWER = 0, /**< Positive answer record. It might be wildcard-expanded. */
+ AR_SOA, /**< SOA record. */
+ AR_NSEC, /**< NSEC* covering or matching the SNAME (next closer name in NSEC3 case). */
+ AR_WILD, /**< NSEC* covering or matching the source of synthesis. */
+ AR_CPE, /**< NSEC3 matching the closest provable encloser. */
+};
+
+/** Materialize RRset + RRSIGs into ans->rrsets[id].
+ * LATER(optim.): it's slightly wasteful that we allocate knot_rrset_t for the packet
+ *
+ * \return error code. They are all bad conditions and "guarded" by assert.
+ */
+int entry2answer(struct answer *ans, int id,
+ const struct entry_h *eh, const uint8_t *eh_bound,
+ const knot_dname_t *owner, uint16_t type, uint32_t new_ttl);
+
+
+/* Preparing knot_pkt_t for cache answer from RRs; implementation in ./knot_pkt.c */
+
+/** Prepare answer packet to be filled by RRs (without RR data in wire). */
+int pkt_renew(knot_pkt_t *pkt, const knot_dname_t *name, uint16_t type);
+
+/** Append RRset + its RRSIGs into the current section (*shallow* copy), with given rank.
+ * \note it works with empty set as well (skipped)
+ * \note pkt->wire is not updated in any way
+ * \note KNOT_CLASS_IN is assumed
+ */
+int pkt_append(knot_pkt_t *pkt, const struct answer_rrset *rrset, uint8_t rank);
+
+
+
+/* NSEC (1) stuff. Implementation in ./nsec1.c */
+
+/** Construct a string key for for NSEC (1) predecessor-search.
+ * \param add_wildcard Act as if the name was extended by "*."
+ * \note k->zlf_len is assumed to have been correctly set */
+knot_db_val_t key_NSEC1(struct key *k, const knot_dname_t *name, bool add_wildcard);
+
+/** Closest encloser check for NSEC (1).
+ * To understand the interface, see the call point.
+ * \param k space to store key + input: zname and zlf_len
+ * \return 0: success; >0: try other (NSEC3); <0: exit cache immediately. */
+int nsec1_encloser(struct key *k, struct answer *ans,
+ const int sname_labels, int *clencl_labels,
+ knot_db_val_t *cover_low_kwz, knot_db_val_t *cover_hi_kwz,
+ const struct kr_query *qry, struct kr_cache *cache);
+
+/** Source of synthesis (SS) check for NSEC (1).
+ * To understand the interface, see the call point.
+ * \return 0: continue; <0: exit cache immediately;
+ * AR_SOA: skip to adding SOA (SS was covered or matched for NODATA). */
+int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ knot_db_val_t cover_low_kwz, knot_db_val_t cover_hi_kwz,
+ const struct kr_query *qry, struct kr_cache *cache);
+
+
+/* NSEC3 stuff. Implementation in ./nsec3.c */
+
+/** Construct a string key for for NSEC3 predecessor-search, from an NSEC3 name.
+ * \note k->zlf_len is assumed to have been correctly set */
+knot_db_val_t key_NSEC3(struct key *k, const knot_dname_t *nsec3_name,
+ const nsec_p_hash_t nsec_p_hash);
+
+/** TODO. See nsec1_encloser(...) */
+int nsec3_encloser(struct key *k, struct answer *ans,
+ const int sname_labels, int *clencl_labels,
+ const struct kr_query *qry, struct kr_cache *cache);
+
+/** TODO. See nsec1_src_synth(...) */
+int nsec3_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ const struct kr_query *qry, struct kr_cache *cache);
+
+
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE((qry), "cach", ## __VA_ARGS__)
+
+/** Shorthand for operations on cache backend */
+#define cache_op(cache, op, ...) (cache)->api->op((cache)->db, ## __VA_ARGS__)
+
+
+static inline uint16_t get_uint16(const void *address)
+{
+ uint16_t tmp;
+ memcpy(&tmp, address, sizeof(tmp));
+ return tmp;
+}
+
+/** Useful pattern, especially as void-pointer arithmetic isn't standard-compliant. */
+static inline uint8_t * knot_db_val_bound(knot_db_val_t val)
+{
+ return (uint8_t *)val.data + val.len;
+}
+
diff --git a/lib/cache/knot_pkt.c b/lib/cache/knot_pkt.c
new file mode 100644
index 0000000..56836a6
--- /dev/null
+++ b/lib/cache/knot_pkt.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of preparing knot_pkt_t for filling with RRs.
+ * Prototypes in ./impl.h
+ */
+
+#include "lib/cache/impl.h"
+
+int pkt_renew(knot_pkt_t *pkt, const knot_dname_t *name, uint16_t type)
+{
+ /* Update packet question if needed. */
+ if (!knot_dname_is_equal(knot_pkt_qname(pkt), name)
+ || knot_pkt_qtype(pkt) != type || knot_pkt_qclass(pkt) != KNOT_CLASS_IN) {
+ int ret = kr_pkt_recycle(pkt);
+ if (ret) return kr_error(ret);
+ ret = knot_pkt_put_question(pkt, name, KNOT_CLASS_IN, type);
+ if (ret) return kr_error(ret);
+ }
+
+ pkt->parsed = pkt->size = PKT_SIZE_NOWIRE;
+ knot_wire_set_qr(pkt->wire);
+ knot_wire_set_aa(pkt->wire);
+ return kr_ok();
+}
+
+/** Reserve space for additional `count` RRsets.
+ * \note pkt->rr_info gets correct length but is always zeroed
+ */
+static int pkt_alloc_space(knot_pkt_t *pkt, int count)
+{
+ size_t allocd_orig = pkt->rrset_allocd;
+ if (pkt->rrset_count + count <= allocd_orig) {
+ return kr_ok();
+ }
+ /* A simple growth strategy, amortized O(count). */
+ pkt->rrset_allocd = MAX(
+ pkt->rrset_count + count,
+ pkt->rrset_count + allocd_orig);
+
+ pkt->rr = mm_realloc(&pkt->mm, pkt->rr,
+ sizeof(pkt->rr[0]) * pkt->rrset_allocd,
+ sizeof(pkt->rr[0]) * allocd_orig);
+ if (!pkt->rr) {
+ return kr_error(ENOMEM);
+ }
+ /* Allocate pkt->rr_info to be certain, but just leave it zeroed. */
+ mm_free(&pkt->mm, pkt->rr_info);
+ pkt->rr_info = mm_alloc(&pkt->mm, sizeof(pkt->rr_info[0]) * pkt->rrset_allocd);
+ if (!pkt->rr_info) {
+ return kr_error(ENOMEM);
+ }
+ memset(pkt->rr_info, 0, sizeof(pkt->rr_info[0]) * pkt->rrset_allocd);
+ return kr_ok();
+}
+
+int pkt_append(knot_pkt_t *pkt, const struct answer_rrset *rrset, uint8_t rank)
+{
+ /* allocate space, to be sure */
+ int rrset_cnt = (rrset->set.rr->rrs.count > 0) + (rrset->sig_rds.count > 0);
+ int ret = pkt_alloc_space(pkt, rrset_cnt);
+ if (ret) return kr_error(ret);
+ /* write both sets */
+ const knot_rdataset_t *rdss[2] = { &rrset->set.rr->rrs, &rrset->sig_rds };
+ for (int i = 0; i < rrset_cnt; ++i) {
+ assert(rdss[i]->count);
+ /* allocate rank */
+ uint8_t *rr_rank = mm_alloc(&pkt->mm, sizeof(*rr_rank));
+ if (!rr_rank) return kr_error(ENOMEM);
+ *rr_rank = (i == 0) ? rank : (KR_RANK_OMIT | KR_RANK_AUTH);
+ /* rank for RRSIGs isn't really useful: ^^ */
+ if (i == 0) {
+ pkt->rr[pkt->rrset_count] = *rrset->set.rr;
+ pkt->rr[pkt->rrset_count].additional = rr_rank;
+ } else {
+ /* append the RR array */
+ pkt->rr[pkt->rrset_count] = (knot_rrset_t){
+ .owner = knot_dname_copy(rrset->set.rr->owner, &pkt->mm),
+ /* ^^ well, another copy isn't really needed */
+ .ttl = rrset->set.rr->ttl,
+ .type = KNOT_RRTYPE_RRSIG,
+ .rclass = KNOT_CLASS_IN,
+ .rrs = *rdss[i],
+ .additional = rr_rank,
+ };
+ }
+ ++pkt->rrset_count;
+ ++(pkt->sections[pkt->current].count);
+ }
+ return kr_ok();
+}
+
diff --git a/lib/cache/nsec1.c b/lib/cache/nsec1.c
new file mode 100644
index 0000000..74b3d34
--- /dev/null
+++ b/lib/cache/nsec1.c
@@ -0,0 +1,511 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of NSEC (1) handling. Prototypes in ./impl.h
+ */
+
+#include "lib/cache/impl.h"
+#include "lib/dnssec/nsec.h"
+#include "lib/layer/iterate.h"
+
+
+/** Reconstruct a name into a buffer (assuming length at least KNOT_DNAME_MAXLEN).
+ * \return kr_ok() or error code (<0). */
+static int dname_wire_reconstruct(knot_dname_t *buf, const struct key *k,
+ knot_db_val_t kwz)
+{
+ /* Reconstruct from key: first the ending, then zone name. */
+ int ret = knot_dname_lf2wire(buf, kwz.len, kwz.data);
+ if (ret < 0) {
+ VERBOSE_MSG(NULL, "=> NSEC: LF2wire ret = %d\n", ret);
+ assert(false);
+ return ret;
+ }
+ /* The last written byte is the zero label for root -> overwrite. */
+ knot_dname_t *zone_start = buf + ret - 1;
+ assert(*zone_start == '\0');
+ ret = knot_dname_to_wire(zone_start, k->zname, KNOT_DNAME_MAXLEN - kwz.len);
+ if (ret != k->zlf_len + 1) {
+ assert(false);
+ return ret < 0 ? ret : kr_error(EILSEQ);
+ }
+ return kr_ok();
+}
+
+
+knot_db_val_t key_NSEC1(struct key *k, const knot_dname_t *name, bool add_wildcard)
+{
+ /* we basically need dname_lf with two bytes added
+ * on a correct place within the name (the cut) */
+ int ret;
+ const bool ok = k && name
+ && !(ret = kr_dname_lf(k->buf, name, add_wildcard));
+ if (!ok) {
+ assert(false);
+ return (knot_db_val_t){ NULL, 0 };
+ }
+
+ uint8_t *begin = k->buf + 1 + k->zlf_len; /* one byte after zone's zero */
+ uint8_t *end = k->buf + 1 + k->buf[0]; /* we don't use the final zero in key,
+ * but move it anyway */
+ if (end < begin) {
+ assert(false);
+ return (knot_db_val_t){ NULL, 0 };
+ }
+ int key_len;
+ if (end > begin) {
+ memmove(begin + 2, begin, end - begin);
+ key_len = k->buf[0] + 1;
+ } else {
+ key_len = k->buf[0] + 2;
+ }
+ /* CACHE_KEY_DEF: key == zone's dname_lf + '\0' + '1' + dname_lf
+ * of the name within the zone without the final 0. Iff the latter is empty,
+ * there's no zero to cut and thus the key_len difference.
+ */
+ begin[0] = 0;
+ begin[1] = '1'; /* tag for NSEC1 */
+ k->type = KNOT_RRTYPE_NSEC;
+
+ /*
+ VERBOSE_MSG(NULL, "<> key_NSEC1; name: ");
+ kr_dname_print(name, add_wildcard ? "*." : "" , " ");
+ kr_log_verbose("(zone name LF length: %d; total key length: %d)\n",
+ k->zlf_len, key_len);
+ */
+
+ return (knot_db_val_t){ k->buf + 1, key_len };
+}
+
+
+/** Assuming that k1 < k4, find where k2 is. (Considers DNS wrap-around.)
+ *
+ * \return Intuition: position of k2 among kX.
+ * 0: k2 < k1; 1: k1 == k2; 2: k1 is a prefix of k2 < k4;
+ * 3: k1 < k2 < k4 (and not 2); 4: k2 == k4; 5: k2 > k4
+ * \note k1.data may be NULL, meaning assumption that k1 < k2 and not a prefix
+ * (i.e. return code will be > 2)
+ */
+static int kwz_between(knot_db_val_t k1, knot_db_val_t k2, knot_db_val_t k4)
+{
+ assert(k2.data && k4.data);
+ /* CACHE_KEY_DEF; we need to beware of one key being a prefix of another */
+ int ret_maybe; /**< result, assuming we confirm k2 < k4 */
+ if (k1.data) {
+ const int cmp12 = memcmp(k1.data, k2.data, MIN(k1.len, k2.len));
+ if (cmp12 == 0 && k1.len == k2.len) /* iff k1 == k2 */
+ return 1;
+ if (cmp12 > 0 || (cmp12 == 0 && k1.len > k2.len)) /* iff k1 > k2 */
+ return 0;
+ ret_maybe = cmp12 == 0 ? 2 : 3;
+ } else {
+ ret_maybe = 3;
+ }
+ if (k4.len == 0) { /* wrap-around */
+ return k2.len > 0 ? ret_maybe : 4;
+ } else {
+ const int cmp24 = memcmp(k2.data, k4.data, MIN(k2.len, k4.len));
+ if (cmp24 == 0 && k2.len == k4.len) /* iff k2 == k4 */
+ return 4;
+ if (cmp24 > 0 || (cmp24 == 0 && k2.len > k4.len)) /* iff k2 > k4 */
+ return 5;
+ return ret_maybe;
+ }
+}
+
+
+/** NSEC1 range search.
+ *
+ * \param key Pass output of key_NSEC1(k, ...)
+ * \param value[out] The raw data of the NSEC cache record (optional; consistency checked).
+ * \param exact_match[out] Whether the key was matched exactly or just covered (optional).
+ * \param kwz_low[out] Output the low end of covering NSEC, pointing within DB (optional).
+ * \param kwz_high[in,out] Storage for the high end of covering NSEC (optional).
+ * It's only set if !exact_match.
+ * \param new_ttl[out] New TTL of the NSEC (optional).
+ * \return Error message or NULL.
+ * \note The function itself does *no* bitmap checks, e.g. RFC 6840 sec. 4.
+ */
+static const char * find_leq_NSEC1(struct kr_cache *cache, const struct kr_query *qry,
+ const knot_db_val_t key, const struct key *k, knot_db_val_t *value,
+ bool *exact_match, knot_db_val_t *kwz_low, knot_db_val_t *kwz_high,
+ uint32_t *new_ttl)
+{
+ /* Do the cache operation. */
+ const size_t nwz_off = key_nwz_off(k);
+ if (!key.data || key.len < nwz_off) {
+ assert(false);
+ return "range search ERROR";
+ }
+ knot_db_val_t key_nsec = key;
+ knot_db_val_t val = { NULL, 0 };
+ int ret = cache_op(cache, read_leq, &key_nsec, &val);
+ if (ret < 0) {
+ if (ret == kr_error(ENOENT)) {
+ return "range search miss";
+ } else {
+ assert(false);
+ return "range search ERROR";
+ }
+ }
+ if (value) {
+ *value = val;
+ }
+ /* Check consistency, TTL, rank. */
+ const bool is_exact = (ret == 0);
+ if (exact_match) {
+ *exact_match = is_exact;
+ }
+ const struct entry_h *eh = entry_h_consistent_NSEC(val);
+ if (!eh) {
+ /* This might be just finding something else than NSEC1 entry,
+ * in case we searched before the very first one in the zone. */
+ return "range search found inconsistent entry";
+ }
+ /* Passing just zone name instead of owner, as we don't
+ * have it reconstructed at this point. */
+ int32_t new_ttl_ = get_new_ttl(eh, qry, k->zname, KNOT_RRTYPE_NSEC,
+ qry->timestamp.tv_sec);
+ if (new_ttl_ < 0 || !kr_rank_test(eh->rank, KR_RANK_SECURE)) {
+ return "range search found stale or insecure entry";
+ /* TODO: remove the stale record *and* retry,
+ * in case we haven't run off. Perhaps start by in_zone check. */
+ }
+ if (new_ttl) {
+ *new_ttl = new_ttl_;
+ }
+ if (kwz_low) {
+ *kwz_low = (knot_db_val_t){
+ .data = (uint8_t *)key_nsec.data + nwz_off,
+ .len = key_nsec.len - nwz_off,
+ }; /* CACHE_KEY_DEF */
+ }
+ if (is_exact) {
+ /* Nothing else to do. */
+ return NULL;
+ }
+ /* The NSEC starts strictly before our target name;
+ * now check that it still belongs into that zone. */
+ const bool nsec_in_zone = key_nsec.len >= nwz_off
+ /* CACHE_KEY_DEF */
+ && memcmp(key.data, key_nsec.data, nwz_off) == 0;
+ if (!nsec_in_zone) {
+ return "range search miss (!nsec_in_zone)";
+ }
+ /* We know it starts before sname, so let's check the other end.
+ * 1. construct the key for the next name - kwz_hi. */
+ /* it's *full* name ATM */
+ const knot_rdata_t *next = (const knot_rdata_t *)
+ (eh->data + KR_CACHE_RR_COUNT_SIZE);
+ if (KR_CACHE_RR_COUNT_SIZE != 2 || get_uint16(eh->data) == 0) {
+ assert(false);
+ return "ERROR";
+ /* TODO: more checks? */
+ }
+ /*
+ WITH_VERBOSE {
+ VERBOSE_MSG(qry, "=> NSEC: next name: ");
+ kr_dname_print(next, "", "\n");
+ }
+ */
+ knot_dname_t ch_buf[KNOT_DNAME_MAXLEN];
+ knot_dname_t *chs = kwz_high ? kwz_high->data : ch_buf;
+ if (!chs) {
+ assert(false);
+ return "EINVAL";
+ }
+ {
+ /* Lower-case chs; see also RFC 6840 5.1.
+ * LATER(optim.): we do lots of copying etc. */
+ knot_dname_t lower_buf[KNOT_DNAME_MAXLEN];
+ ret = knot_dname_to_wire(lower_buf, next->data,
+ MIN(next->len, KNOT_DNAME_MAXLEN));
+ if (ret < 0) { /* _ESPACE */
+ return "range search found record with incorrect contents";
+ }
+ knot_dname_to_lower(lower_buf);
+ ret = kr_dname_lf(chs, lower_buf, false);
+ }
+ if (ret) {
+ assert(false);
+ return "ERROR";
+ }
+ knot_db_val_t kwz_hi = { /* skip the zone name */
+ .data = chs + 1 + k->zlf_len,
+ .len = chs[0] - k->zlf_len,
+ };
+ assert((ssize_t)(kwz_hi.len) >= 0);
+ /* 2. do the actual range check. */
+ const knot_db_val_t kwz_sname = {
+ .data = (void *)/*const-cast*/(k->buf + 1 + nwz_off),
+ .len = k->buf[0] - k->zlf_len,
+ };
+ assert((ssize_t)(kwz_sname.len) >= 0);
+ bool covers = /* we know for sure that the low end is before kwz_sname */
+ 3 == kwz_between((knot_db_val_t){ NULL, 0 }, kwz_sname, kwz_hi);
+ if (!covers) {
+ return "range search miss (!covers)";
+ }
+ if (kwz_high) {
+ *kwz_high = kwz_hi;
+ }
+ return NULL;
+}
+
+
+int nsec1_encloser(struct key *k, struct answer *ans,
+ const int sname_labels, int *clencl_labels,
+ knot_db_val_t *cover_low_kwz, knot_db_val_t *cover_hi_kwz,
+ const struct kr_query *qry, struct kr_cache *cache)
+{
+ static const int ESKIP = ABS(ENOENT);
+ /* Basic sanity check. */
+ const bool ok = k && ans && clencl_labels && cover_low_kwz && cover_hi_kwz
+ && qry && cache;
+ if (!ok) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ /* Find a previous-or-equal name+NSEC in cache covering the QNAME,
+ * checking TTL etc. */
+ knot_db_val_t key = key_NSEC1(k, qry->sname, false);
+ knot_db_val_t val = { NULL, 0 };
+ bool exact_match;
+ uint32_t new_ttl;
+ const char *err = find_leq_NSEC1(cache, qry, key, k, &val,
+ &exact_match, cover_low_kwz, cover_hi_kwz, &new_ttl);
+ if (err) {
+ VERBOSE_MSG(qry, "=> NSEC sname: %s\n", err);
+ return ESKIP;
+ }
+
+ /* Get owner name of the record. */
+ const knot_dname_t *owner;
+ knot_dname_t owner_buf[KNOT_DNAME_MAXLEN];
+ if (exact_match) {
+ owner = qry->sname;
+ } else {
+ int ret = dname_wire_reconstruct(owner_buf, k, *cover_low_kwz);
+ if (unlikely(ret)) return ESKIP;
+ owner = owner_buf;
+ }
+ /* Basic checks OK -> materialize data. */
+ {
+ const struct entry_h *nsec_eh = val.data;
+ int ret = entry2answer(ans, AR_NSEC, nsec_eh, knot_db_val_bound(val),
+ owner, KNOT_RRTYPE_NSEC, new_ttl);
+ if (ret) return kr_error(ret);
+ }
+
+ /* Final checks, split for matching vs. covering our sname. */
+ const knot_rrset_t *nsec_rr = ans->rrsets[AR_NSEC].set.rr;
+ const uint8_t *bm = knot_nsec_bitmap(nsec_rr->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec_rr->rrs.rdata);
+ assert(bm);
+
+ if (exact_match) {
+ if (kr_nsec_bitmap_nodata_check(bm, bm_size, qry->stype, nsec_rr->owner) != 0) {
+ VERBOSE_MSG(qry,
+ "=> NSEC sname: match but failed type check\n");
+ return ESKIP;
+ }
+ /* NODATA proven; just need to add SOA+RRSIG later */
+ VERBOSE_MSG(qry, "=> NSEC sname: match proved NODATA, new TTL %d\n",
+ new_ttl);
+ ans->rcode = PKT_NODATA;
+ return kr_ok();
+ } /* else */
+
+ /* Inexact match. First check if sname is delegated by that NSEC. */
+ const int nsec_matched = knot_dname_matched_labels(nsec_rr->owner, qry->sname);
+ const bool is_sub = nsec_matched == knot_dname_labels(nsec_rr->owner, NULL);
+ if (is_sub && kr_nsec_children_in_zone_check(bm, bm_size) != 0) {
+ VERBOSE_MSG(qry, "=> NSEC sname: covered but delegated (or error)\n");
+ return ESKIP;
+ }
+ /* NXDOMAIN proven *except* for wildcards. */
+ WITH_VERBOSE(qry) {
+ auto_free char *owner_str = kr_dname_text(nsec_rr->owner),
+ *next_str = kr_dname_text(knot_nsec_next(nsec_rr->rrs.rdata));
+ VERBOSE_MSG(qry, "=> NSEC sname: covered by: %s -> %s, new TTL %d\n",
+ owner_str, next_str, new_ttl);
+ }
+
+ /* Find label count of the closest encloser.
+ * Both endpoints in an NSEC do exist (though possibly in a child zone)
+ * and any prefixes of those names as well (empty non-terminals),
+ * but nothing else exists inside this "triangle".
+ *
+ * Note that we have to lower-case the next name for comparison,
+ * even though we have canonicalized NSEC already; see RFC 6840 5.1.
+ * LATER(optim.): it might be faster to use the LFs we already have.
+ */
+ knot_dname_t next[KNOT_DNAME_MAXLEN];
+ int ret = knot_dname_to_wire(next, knot_nsec_next(nsec_rr->rrs.rdata), sizeof(next));
+ if (ret < 0) {
+ assert(!ret);
+ return kr_error(ret);
+ }
+ knot_dname_to_lower(next);
+ *clencl_labels = MAX(
+ nsec_matched,
+ knot_dname_matched_labels(qry->sname, next)
+ );
+
+ /* Empty non-terminals don't need to have
+ * a matching NSEC record. */
+ if (sname_labels == *clencl_labels) {
+ ans->rcode = PKT_NODATA;
+ VERBOSE_MSG(qry,
+ "=> NSEC sname: empty non-terminal by the same RR\n");
+ } else {
+ ans->rcode = PKT_NXDOMAIN;
+ }
+ return kr_ok();
+}
+
+/** Verify non-existence after kwz_between() call. */
+static bool nonexistence_ok(int cmp, const knot_rrset_t *rrs)
+{
+ if (cmp == 3) {
+ return true;
+ }
+ if (cmp != 2) {
+ return false;
+ }
+ const uint8_t *bm = knot_nsec_bitmap(rrs->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(rrs->rrs.rdata);
+ return kr_nsec_children_in_zone_check(bm, bm_size) != 0;
+}
+
+int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ knot_db_val_t cover_low_kwz, knot_db_val_t cover_hi_kwz,
+ const struct kr_query *qry, struct kr_cache *cache)
+{
+ /* Construct key for the source of synthesis. */
+ knot_db_val_t key = key_NSEC1(k, clencl_name, true);
+ const size_t nwz_off = key_nwz_off(k);
+ if (!key.data || key.len < nwz_off) {
+ assert(false);
+ return kr_error(1);
+ }
+ /* Check if our sname-covering NSEC also covers/matches SS. */
+ knot_db_val_t kwz = {
+ .data = (uint8_t *)key.data + nwz_off,
+ .len = key.len - nwz_off,
+ };
+ assert((ssize_t)(kwz.len) >= 0);
+ const int cmp = kwz_between(cover_low_kwz, kwz, cover_hi_kwz);
+ if (nonexistence_ok(cmp, ans->rrsets[AR_NSEC].set.rr)) {
+ VERBOSE_MSG(qry, "=> NSEC wildcard: covered by the same RR\n");
+ return AR_SOA;
+ }
+ const knot_rrset_t *nsec_rr = NULL; /**< the wildcard proof NSEC */
+ bool exact_match; /**< whether it matches the source of synthesis */
+ if (cmp == 1) {
+ exact_match = true;
+ nsec_rr = ans->rrsets[AR_NSEC].set.rr;
+ } else {
+ /* Try to find the NSEC for SS. */
+ knot_db_val_t val = { NULL, 0 };
+ knot_db_val_t wild_low_kwz = { NULL, 0 };
+ uint32_t new_ttl;
+ const char *err = find_leq_NSEC1(cache, qry, key, k, &val,
+ &exact_match, &wild_low_kwz, NULL, &new_ttl);
+ if (err) {
+ VERBOSE_MSG(qry, "=> NSEC wildcard: %s\n", err);
+ return kr_ok();
+ }
+ /* Materialize the record into answer (speculatively). */
+ knot_dname_t owner[KNOT_DNAME_MAXLEN];
+ int ret = dname_wire_reconstruct(owner, k, wild_low_kwz);
+ if (ret) return kr_error(ret);
+ const struct entry_h *nsec_eh = val.data;
+ ret = entry2answer(ans, AR_WILD, nsec_eh, knot_db_val_bound(val),
+ owner, KNOT_RRTYPE_NSEC, new_ttl);
+ if (ret) return kr_error(ret);
+ nsec_rr = ans->rrsets[AR_WILD].set.rr;
+ }
+
+ assert(nsec_rr);
+ const uint32_t new_ttl_log =
+ kr_verbose_status ? nsec_rr->ttl : -1;
+ const uint8_t *bm = knot_nsec_bitmap(nsec_rr->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec_rr->rrs.rdata);
+ int ret;
+ struct answer_rrset * const arw = &ans->rrsets[AR_WILD];
+ if (!bm) {
+ assert(false);
+ ret = kr_error(1);
+ goto clean_wild;
+ }
+ if (!exact_match) {
+ /* Finish verification that the source of synthesis doesn't exist. */
+ const int nsec_matched =
+ knot_dname_matched_labels(nsec_rr->owner, clencl_name);
+ /* we don't need to use the full source of synthesis ^ */
+ const bool is_sub =
+ nsec_matched == knot_dname_labels(nsec_rr->owner, NULL);
+ if (is_sub && kr_nsec_children_in_zone_check(bm, bm_size) != 0) {
+ VERBOSE_MSG(qry,
+ "=> NSEC wildcard: covered but delegated (or error)\n");
+ ret = kr_ok();
+ goto clean_wild;
+ }
+ /* We have a record proving wildcard non-existence. */
+ WITH_VERBOSE(qry) {
+ auto_free char *owner_str = kr_dname_text(nsec_rr->owner),
+ *next_str = kr_dname_text(knot_nsec_next(nsec_rr->rrs.rdata));
+ VERBOSE_MSG(qry, "=> NSEC wildcard: covered by: %s -> %s, new TTL %d\n",
+ owner_str, next_str, new_ttl_log);
+ }
+ return AR_SOA;
+ }
+
+ /* The wildcard exists. Find if it's NODATA - check type bitmap. */
+ if (kr_nsec_bitmap_nodata_check(bm, bm_size, qry->stype, nsec_rr->owner) == 0) {
+ /* NODATA proven; just need to add SOA+RRSIG later */
+ WITH_VERBOSE(qry) {
+ const char *msg_start = "=> NSEC wildcard: match proved NODATA";
+ if (arw->set.rr) {
+ auto_free char *owner_str = kr_dname_text(nsec_rr->owner);
+ VERBOSE_MSG(qry, "%s: %s, new TTL %d\n",
+ msg_start, owner_str, new_ttl_log);
+ } else {
+ /* don't repeat the RR if it's the same */
+ VERBOSE_MSG(qry, "%s, by the same RR\n", msg_start);
+ }
+ }
+ ans->rcode = PKT_NODATA;
+ return AR_SOA;
+
+ } /* else */
+ /* The data probably exists -> don't add this NSEC
+ * and (later) try to find the real wildcard data */
+ VERBOSE_MSG(qry, "=> NSEC wildcard: should exist (or error)\n");
+ ans->rcode = PKT_NOERROR;
+ ret = kr_ok();
+clean_wild:
+ if (arw->set.rr) { /* we may have matched AR_NSEC */
+ knot_rrset_free(arw->set.rr, ans->mm);
+ arw->set.rr = NULL;
+ knot_rdataset_clear(&arw->sig_rds, ans->mm);
+ }
+ return ret;
+}
+
diff --git a/lib/cache/nsec3.c b/lib/cache/nsec3.c
new file mode 100644
index 0000000..d2ae72a
--- /dev/null
+++ b/lib/cache/nsec3.c
@@ -0,0 +1,501 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Implementation of NSEC3 handling. Prototypes in ./impl.h
+ */
+
+#include "lib/cache/impl.h"
+
+#include "contrib/base32hex.h"
+#include "lib/dnssec/nsec.h"
+#include "lib/layer/iterate.h"
+
+#include <libknot/rrtype/nsec3.h>
+
+static const knot_db_val_t VAL_EMPTY = { NULL, 0 };
+
+/** Common part: write all but the NSEC3 hash. */
+static knot_db_val_t key_NSEC3_common(struct key *k, const knot_dname_t *zname,
+ const nsec_p_hash_t nsec_p_hash)
+{
+ int ret;
+ const bool ok = k && zname
+ && !(ret = kr_dname_lf(k->buf, zname, false));
+ if (!ok) {
+ assert(false);
+ return VAL_EMPTY;
+ }
+
+ /* CACHE_KEY_DEF: key == zone's dname_lf + '\0' + '3' + nsec_p hash (4B)
+ * + NSEC3 hash (20B == NSEC3_HASH_LEN binary!)
+ * LATER(optim.) nsec_p hash: perhaps 2B would give a sufficient probability
+ * of avoiding collisions.
+ */
+ uint8_t *begin = k->buf + 1 + k->zlf_len; /* one byte after zone's zero */
+ begin[0] = 0;
+ begin[1] = '3'; /* tag for NSEC3 */
+ k->type = KNOT_RRTYPE_NSEC3;
+ memcpy(begin + 2, &nsec_p_hash, sizeof(nsec_p_hash));
+ return (knot_db_val_t){
+ .data = k->buf + 1,
+ .len = begin + 2 + sizeof(nsec_p_hash) - (k->buf + 1),
+ };
+}
+
+knot_db_val_t key_NSEC3(struct key *k, const knot_dname_t *nsec3_name,
+ const nsec_p_hash_t nsec_p_hash)
+{
+ knot_db_val_t val = key_NSEC3_common(k, nsec3_name /*only zname required*/,
+ nsec_p_hash);
+ if (!val.data) return val;
+ int len = base32hex_decode(nsec3_name + 1, nsec3_name[0],
+ knot_db_val_bound(val), KR_CACHE_KEY_MAXLEN - val.len);
+ if (len != NSEC3_HASH_LEN) {
+ return VAL_EMPTY;
+ }
+ val.len += len;
+ return val;
+}
+
+/** Construct a string key for for NSEC3 predecessor-search, from an non-NSEC3 name.
+ * \note k->zlf_len and k->zname are assumed to have been correctly set */
+static knot_db_val_t key_NSEC3_name(struct key *k, const knot_dname_t *name,
+ const bool add_wildcard, const struct nsec_p *nsec_p)
+{
+ bool ok = k && name && nsec_p && nsec_p->raw;
+ if (!ok) return VAL_EMPTY;
+ knot_db_val_t val = key_NSEC3_common(k, k->zname, nsec_p->hash);
+ if (!val.data) return val;
+
+ /* Make `name` point to correctly wildcarded owner name. */
+ uint8_t buf[KNOT_DNAME_MAXLEN];
+ int name_len;
+ if (add_wildcard) {
+ buf[0] = '\1';
+ buf[1] = '*';
+ name_len = knot_dname_to_wire(buf + 2, name, sizeof(buf) - 2);
+ if (name_len < 0) return VAL_EMPTY; /* wants wildcard but doesn't fit */
+ name = buf;
+ name_len += 2;
+ } else {
+ name_len = knot_dname_size(name);
+ }
+ /* Append the NSEC3 hash. */
+ const dnssec_binary_t dname = {
+ .size = name_len,
+ .data = (uint8_t *)/*const-cast*/name,
+ };
+
+ #if 0 // LATER(optim.): this requires a patched libdnssec - tries to realloc()
+ dnssec_binary_t hash = {
+ .size = KR_CACHE_KEY_MAXLEN - val.len,
+ .data = val.data + val.len,
+ };
+ int ret = dnssec_nsec3_hash(&dname, &nsec_p->libknot, &hash);
+ if (ret != DNSSEC_EOK) return VAL_EMPTY;
+ assert(hash.size == NSEC3_HASH_LEN);
+
+ #else
+ dnssec_binary_t hash = { .size = 0, .data = NULL };
+ int ret = dnssec_nsec3_hash(&dname, &nsec_p->libknot, &hash);
+ if (ret != DNSSEC_EOK) return VAL_EMPTY;
+ if (hash.size != NSEC3_HASH_LEN || !hash.data) {
+ assert(false);
+ return VAL_EMPTY;
+ }
+ memcpy(knot_db_val_bound(val), hash.data, NSEC3_HASH_LEN);
+ free(hash.data);
+ #endif
+
+ val.len += hash.size;
+ return val;
+}
+
+/** Return h1 < h2, semantically on NSEC3 hashes. */
+static inline bool nsec3_hash_ordered(const uint8_t *h1, const uint8_t *h2)
+{
+ return memcmp(h1, h2, NSEC3_HASH_LEN) < 0;
+}
+
+/** NSEC3 range search.
+ *
+ * \param key Pass output of key_NSEC3(k, ...)
+ * \param nsec_p Restrict to this NSEC3 parameter-set.
+ * \param value[out] The raw data of the NSEC3 cache record (optional; consistency checked).
+ * \param exact_match[out] Whether the key was matched exactly or just covered (optional).
+ * \param hash_low[out] Output the low end hash of covering NSEC3, pointing within DB (optional).
+ * \param new_ttl[out] New TTL of the NSEC3 (optional).
+ * \return Error message or NULL.
+ * \note The function itself does *no* bitmap checks, e.g. RFC 6840 sec. 4.
+ */
+static const char * find_leq_NSEC3(struct kr_cache *cache, const struct kr_query *qry,
+ const knot_db_val_t key, const struct key *k, const struct nsec_p *nsec_p,
+ knot_db_val_t *value, bool *exact_match, const uint8_t **hash_low,
+ uint32_t *new_ttl)
+{
+ /* Do the cache operation. */
+ const size_t hash_off = key_nsec3_hash_off(k);
+ if (!key.data || key.len < hash_off) {
+ assert(false);
+ return "range search ERROR";
+ }
+ knot_db_val_t key_found = key;
+ knot_db_val_t val = { NULL, 0 };
+ int ret = cache_op(cache, read_leq, &key_found, &val);
+ /* ^^ LATER(optim.): incrementing key and doing less-than search
+ * would probably be slightly more efficient with LMDB,
+ * but the code complexity would grow considerably. */
+ if (ret < 0) {
+ if (ret == kr_error(ENOENT)) {
+ return "range search miss";
+ } else {
+ assert(false);
+ return "range search ERROR";
+ }
+ }
+ if (value) {
+ *value = val;
+ }
+ /* Check consistency, TTL, rank. */
+ const bool is_exact = (ret == 0);
+ if (exact_match) {
+ *exact_match = is_exact;
+ }
+ const struct entry_h *eh = entry_h_consistent_NSEC(val);
+ if (!eh) {
+ /* This might be just finding something else than NSEC3 entry,
+ * in case we searched before the very first one in the zone. */
+ return "range search found inconsistent entry";
+ }
+ /* Passing just zone name instead of owner. */
+ int32_t new_ttl_ = get_new_ttl(eh, qry, k->zname, KNOT_RRTYPE_NSEC3,
+ qry->timestamp.tv_sec);
+ if (new_ttl_ < 0 || !kr_rank_test(eh->rank, KR_RANK_SECURE)) {
+ return "range search found stale or insecure entry";
+ /* TODO: remove the stale record *and* retry,
+ * in case we haven't run off. Perhaps start by in_zone check. */
+ }
+ if (new_ttl) {
+ *new_ttl = new_ttl_;
+ }
+ if (hash_low) {
+ *hash_low = (uint8_t *)key_found.data + hash_off;
+ }
+ if (is_exact) {
+ /* Nothing else to do. */
+ return NULL;
+ }
+ /* The NSEC3 starts strictly before our target name;
+ * now check that it still belongs into that zone and chain. */
+ const uint8_t *nsec_p_raw = eh->data + KR_CACHE_RR_COUNT_SIZE
+ + 2 /* RDLENGTH from rfc1034 */;
+ const int nsec_p_len = nsec_p_rdlen(nsec_p_raw);
+ const bool same_chain = key_found.len == hash_off + NSEC3_HASH_LEN
+ /* CACHE_KEY_DEF */
+ && memcmp(key.data, key_found.data, hash_off) == 0
+ /* exact comparison of NSEC3 parameters */
+ && nsec_p_len == nsec_p_rdlen(nsec_p->raw)
+ && memcmp(nsec_p_raw, nsec_p->raw, nsec_p_len) == 0;
+ if (!same_chain) {
+ return "range search miss (!same_chain)";
+ }
+ /* We know it starts before sname, so let's check the other end.
+ * A. find the next hash and check its length. */
+ if (KR_CACHE_RR_COUNT_SIZE != 2 || get_uint16(eh->data) == 0) {
+ assert(false);
+ return "ERROR";
+ /* TODO: more checks? Also, `next` computation is kinda messy. */
+ }
+ const uint8_t *hash_next = nsec_p_raw + nsec_p_len
+ + sizeof(uint8_t) /* hash length from rfc5155 */;
+ if (hash_next[-1] != NSEC3_HASH_LEN) {
+ return "unexpected next hash length";
+ }
+ /* B. do the actual range check. */
+ const uint8_t * const hash_searched = (uint8_t *)key.data + hash_off;
+ bool covers = /* we know for sure that the low end is before the searched name */
+ nsec3_hash_ordered(hash_searched, hash_next)
+ /* and the wrap-around case */
+ || nsec3_hash_ordered(hash_next, (const uint8_t *)key_found.data + hash_off);
+ if (!covers) {
+ return "range search miss (!covers)";
+ }
+ return NULL;
+}
+
+/** Extract textual representation of NSEC3 hash from a cache key.
+ * \param text must have length at least NSEC3_HASH_TXT_LEN+1 (will get 0-terminated). */
+static void key_NSEC3_hash2text(const knot_db_val_t key, char *text)
+{
+ assert(key.data && key.len > NSEC3_HASH_LEN);
+ const uint8_t *hash_raw = knot_db_val_bound(key) - NSEC3_HASH_LEN;
+ /* CACHE_KEY_DEF ^^ */
+ int len = base32hex_encode(hash_raw, NSEC3_HASH_LEN, (uint8_t *)text,
+ NSEC3_HASH_TXT_LEN);
+ assert(len == NSEC3_HASH_TXT_LEN); (void)len;
+ text[NSEC3_HASH_TXT_LEN] = '\0';
+}
+
+/** Reconstruct a name into a buffer (assuming length at least KNOT_DNAME_MAXLEN).
+ * \return kr_ok() or error code (<0). */
+static int dname_wire_reconstruct(knot_dname_t *buf, const knot_dname_t *zname,
+ const uint8_t *hash_raw)
+{
+ int len = base32hex_encode(hash_raw, NSEC3_HASH_LEN, buf + 1, NSEC3_HASH_TXT_LEN);
+ if (len != NSEC3_HASH_TXT_LEN) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ buf[0] = len;
+ int ret = knot_dname_to_wire(buf + 1 + len, zname, KNOT_DNAME_MAXLEN - 1 - len);
+ return ret < 0 ? kr_error(ret) : kr_ok();
+}
+
+static void nsec3_hash2text(const knot_dname_t *owner, char *text)
+{
+ assert(owner[0] == NSEC3_HASH_TXT_LEN);
+ memcpy(text, owner + 1, MIN(owner[0], NSEC3_HASH_TXT_LEN));
+ text[NSEC3_HASH_TXT_LEN] = '\0';
+}
+
+int nsec3_encloser(struct key *k, struct answer *ans,
+ const int sname_labels, int *clencl_labels,
+ const struct kr_query *qry, struct kr_cache *cache)
+{
+ static const int ESKIP = ABS(ENOENT);
+ /* Basic sanity check. */
+ const bool ok = k && k->zname && ans && clencl_labels
+ && qry && cache;
+ if (!ok) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ /*** Find the closest encloser - cycle: name starting at sname,
+ * proceeding while longer than zname, shortening by one label on step.
+ * We need a pair where a name doesn't exist *and* its parent does. */
+ /* LATER(optim.): perhaps iterate in the other order - that
+ * should help significantly against deep queries where we have
+ * a shallow proof in the cache. We can also optimize by using
+ * only exact search unless we had a match in the previous iteration. */
+ const int zname_labels = knot_dname_labels(k->zname, NULL);
+ int last_nxproven_labels = -1;
+ const knot_dname_t *name = qry->sname;
+ for (int name_labels = sname_labels; name_labels >= zname_labels;
+ --name_labels, name += 1 + name[0]) {
+ /* Find a previous-or-equal NSEC3 in cache covering the name,
+ * checking TTL etc. */
+ const knot_db_val_t key = key_NSEC3_name(k, name, false, &ans->nsec_p);
+ if (!key.data) continue;
+ WITH_VERBOSE(qry) {
+ char hash_txt[NSEC3_HASH_TXT_LEN + 1];
+ key_NSEC3_hash2text(key, hash_txt);
+ VERBOSE_MSG(qry, "=> NSEC3 depth %d: hash %s\n",
+ name_labels - zname_labels, hash_txt);
+ }
+ knot_db_val_t val = { NULL, 0 };
+ bool exact_match;
+ uint32_t new_ttl;
+ const uint8_t *hash_low;
+ const char *err = find_leq_NSEC3(cache, qry, key, k, &ans->nsec_p, &val,
+ &exact_match, &hash_low, &new_ttl);
+ if (err) {
+ WITH_VERBOSE(qry) {
+ auto_free char *name_str = kr_dname_text(name);
+ VERBOSE_MSG(qry, "=> NSEC3 encloser error for %s: %s\n",
+ name_str, err);
+ }
+ continue;
+ }
+ if (exact_match && name_labels != sname_labels
+ && name_labels + 1 != last_nxproven_labels) {
+ /* This name exists (checked rank and TTL), and it's
+ * neither of the two interesting cases, so we do not
+ * keep searching for non-existence above this name. */
+ VERBOSE_MSG(qry,
+ "=> NSEC3 encloser: only found existence of an ancestor\n");
+ return ESKIP;
+ }
+ /* Optimization: avoid the rest of the last iteration if pointless. */
+ if (!exact_match && name_labels == zname_labels
+ && last_nxproven_labels != name_labels + 1) {
+ break;
+ }
+
+ /* Basic checks OK -> materialize data, cleaning any previous
+ * records on that answer index (unsuccessful attempts). */
+ knot_dname_t owner[KNOT_DNAME_MAXLEN];
+ {
+ int ret = dname_wire_reconstruct(owner, k->zname, hash_low);
+ if (unlikely(ret)) continue;
+ }
+ const int ans_id = (exact_match && name_labels + 1 == last_nxproven_labels)
+ ? AR_CPE : AR_NSEC;
+ {
+ const struct entry_h *nsec_eh = val.data;
+ memset(&ans->rrsets[ans_id], 0, sizeof(ans->rrsets[ans_id]));
+ int ret = entry2answer(ans, ans_id, nsec_eh, knot_db_val_bound(val),
+ owner, KNOT_RRTYPE_NSEC3, new_ttl);
+ if (ret) return kr_error(ret);
+ }
+
+ if (!exact_match) {
+ /* Non-existence proven, but we don't know if `name`
+ * is the next closer name.
+ * Note: we don't need to check for the sname being
+ * delegated away by this record, as with NSEC3 only
+ * *exact* match on an ancestor could do that. */
+ last_nxproven_labels = name_labels;
+ WITH_VERBOSE(qry) {
+ char hash_low_txt[NSEC3_HASH_TXT_LEN + 1];
+ nsec3_hash2text(owner, hash_low_txt);
+ VERBOSE_MSG(qry,
+ "=> NSEC3 depth %d: covered by %s -> TODO, new TTL %d\n",
+ name_labels - zname_labels, hash_low_txt, new_ttl);
+ }
+ continue;
+ }
+
+ /* Exactly matched NSEC3: two cases, one after another. */
+ const knot_rrset_t *nsec_rr = ans->rrsets[ans_id].set.rr;
+ const uint8_t *bm = knot_nsec3_bitmap(nsec_rr->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(nsec_rr->rrs.rdata);
+ assert(bm);
+ if (name_labels == sname_labels) {
+ if (kr_nsec_bitmap_nodata_check(bm, bm_size, qry->stype,
+ nsec_rr->owner) != 0) {
+ VERBOSE_MSG(qry,
+ "=> NSEC3 sname: match but failed type check\n");
+ return ESKIP;
+ }
+ /* NODATA proven; just need to add SOA+RRSIG later */
+ VERBOSE_MSG(qry,
+ "=> NSEC3 sname: match proved NODATA, new TTL %d\n",
+ new_ttl);
+ ans->rcode = PKT_NODATA;
+ return kr_ok();
+
+ } /* else */
+
+ assert(name_labels + 1 == last_nxproven_labels);
+ if (kr_nsec_children_in_zone_check(bm, bm_size) != 0) {
+ VERBOSE_MSG(qry,
+ "=> NSEC3 encloser: found but delegated (or error)\n");
+ return ESKIP;
+ }
+ /* NXDOMAIN proven *except* for wildcards. */
+ WITH_VERBOSE(qry) {
+ auto_free char *name_str = kr_dname_text(name);
+ VERBOSE_MSG(qry,
+ "=> NSEC3 encloser: confirmed as %s, new TTL %d\n",
+ name_str, new_ttl);
+ }
+ *clencl_labels = name_labels;
+ ans->rcode = PKT_NXDOMAIN;
+ /* Avoid repeated NSEC3 - remove either if the hashes match.
+ * This is very unlikely in larger zones: 1/size (per attempt).
+ * Well, deduplication would happen anyway when the answer
+ * from cache is read by kresd (internally). */
+ if (unlikely(0 == memcmp(ans->rrsets[AR_NSEC].set.rr->owner + 1,
+ ans->rrsets[AR_CPE ].set.rr->owner + 1,
+ NSEC3_HASH_LEN))) {
+ memset(&ans->rrsets[AR_CPE], 0, sizeof(ans->rrsets[AR_CPE]));
+ /* LATER(optim.): perhaps check this earlier and avoid some work? */
+ }
+ return kr_ok();
+ }
+
+ /* We've ran out of options. */
+ if (last_nxproven_labels > 0) {
+ /* We didn't manage to prove existence of the closest encloser,
+ * meaning the only chance left is a *positive* wildcard record. */
+ *clencl_labels = last_nxproven_labels - 1;
+ ans->rcode = PKT_NXDOMAIN;
+ /* FIXME: review */
+ }
+ return ESKIP;
+}
+
+int nsec3_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ const struct kr_query *qry, struct kr_cache *cache)
+{
+ /* Find a previous-or-equal NSEC3 in cache covering or matching
+ * the source of synthesis, checking TTL etc. */
+ const knot_db_val_t key = key_NSEC3_name(k, clencl_name, true, &ans->nsec_p);
+ if (!key.data) return kr_error(1);
+ WITH_VERBOSE(qry) {
+ char hash_txt[NSEC3_HASH_TXT_LEN + 1];
+ key_NSEC3_hash2text(key, hash_txt);
+ VERBOSE_MSG(qry, "=> NSEC3 wildcard: hash %s\n", hash_txt);
+ }
+ knot_db_val_t val = { NULL, 0 };
+ bool exact_match;
+ uint32_t new_ttl;
+ const uint8_t *hash_low;
+ const char *err = find_leq_NSEC3(cache, qry, key, k, &ans->nsec_p, &val,
+ &exact_match, &hash_low, &new_ttl);
+ if (err) {
+ VERBOSE_MSG(qry, "=> NSEC3 wildcard: %s\n", err);
+ return kr_ok();
+ }
+
+ /* LATER(optim.): avoid duplicities in answer. */
+
+ /* Basic checks OK -> materialize the data (speculatively). */
+ knot_dname_t owner[KNOT_DNAME_MAXLEN];
+ {
+ int ret = dname_wire_reconstruct(owner, k->zname, hash_low);
+ if (unlikely(ret)) return kr_ok();
+ const struct entry_h *nsec_eh = val.data;
+ ret = entry2answer(ans, AR_WILD, nsec_eh, knot_db_val_bound(val),
+ owner, KNOT_RRTYPE_NSEC3, new_ttl);
+ if (ret) return kr_error(ret);
+ }
+ const knot_rrset_t *nsec_rr = ans->rrsets[AR_WILD].set.rr;
+
+ if (!exact_match) {
+ /* The record proves wildcard non-existence. */
+ WITH_VERBOSE(qry) {
+ char hash_low_txt[NSEC3_HASH_TXT_LEN + 1];
+ nsec3_hash2text(owner, hash_low_txt);
+ VERBOSE_MSG(qry,
+ "=> NSEC3 wildcard: covered by %s -> TODO, new TTL %d\n",
+ hash_low_txt, new_ttl);
+ }
+ return AR_SOA;
+ }
+
+ /* The wildcard exists. Find if it's NODATA - check type bitmap. */
+ const uint8_t *bm = knot_nsec3_bitmap(nsec_rr->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(nsec_rr->rrs.rdata);
+ assert(bm);
+ if (kr_nsec_bitmap_nodata_check(bm, bm_size, qry->stype, nsec_rr->owner) == 0) {
+ /* NODATA proven; just need to add SOA+RRSIG later */
+ VERBOSE_MSG(qry, "=> NSEC3 wildcard: match proved NODATA, new TTL %d\n",
+ new_ttl);
+ ans->rcode = PKT_NODATA;
+ return AR_SOA;
+
+ } /* else */
+ /* The data probably exists -> don't add this NSEC3
+ * and (later) try to find the real wildcard data */
+ VERBOSE_MSG(qry, "=> NSEC3 wildcard: should exist (or error)\n");
+ ans->rcode = PKT_NOERROR;
+ memset(&ans->rrsets[AR_WILD], 0, sizeof(ans->rrsets[AR_WILD]));
+ return kr_ok();
+}
+
diff --git a/lib/cache/peek.c b/lib/cache/peek.c
new file mode 100644
index 0000000..1af1627
--- /dev/null
+++ b/lib/cache/peek.c
@@ -0,0 +1,724 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/cache/impl.h"
+
+#include "lib/dnssec/ta.h"
+#include "lib/layer/iterate.h"
+
+/* The whole file only exports peek_nosync().
+ * Forwards for larger chunks of code: */
+
+static int found_exact_hit(kr_layer_t *ctx, knot_pkt_t *pkt, knot_db_val_t val,
+ uint8_t lowest_rank);
+static int closest_NS(struct kr_cache *cache, struct key *k, entry_list_t el,
+ struct kr_query *qry, bool only_NS, bool is_DS);
+static int answer_simple_hit(kr_layer_t *ctx, knot_pkt_t *pkt, uint16_t type,
+ const struct entry_h *eh, const void *eh_bound, uint32_t new_ttl);
+static int try_wild(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ uint16_t type, uint8_t lowest_rank,
+ const struct kr_query *qry, struct kr_cache *cache);
+
+static int peek_encloser(
+ struct key *k, struct answer *ans, int sname_labels,
+ uint8_t lowest_rank, const struct kr_query *qry, struct kr_cache *cache);
+
+
+static int nsec_p_init(struct nsec_p *nsec_p, knot_db_val_t nsec_p_entry, bool with_knot)
+{
+ const size_t stamp_len = sizeof(uint32_t);
+ if (nsec_p_entry.len <= stamp_len) { /* plain NSEC if equal */
+ nsec_p->raw = NULL;
+ nsec_p->hash = 0;
+ return kr_ok();
+ }
+ nsec_p->raw = (uint8_t *)nsec_p_entry.data + stamp_len;
+ nsec_p->hash = nsec_p_mkHash(nsec_p->raw);
+ if (!with_knot) return kr_ok();
+ /* Convert NSEC3 params to another format. */
+ const dnssec_binary_t rdata = {
+ .size = nsec_p_rdlen(nsec_p->raw),
+ .data = (uint8_t *)/*const-cast*/nsec_p->raw,
+ };
+ int ret = dnssec_nsec3_params_from_rdata(&nsec_p->libknot, &rdata);
+ return ret == DNSSEC_EOK ? kr_ok() : kr_error(ret);
+}
+
+static void nsec_p_cleanup(struct nsec_p *nsec_p)
+{
+ dnssec_binary_free(&nsec_p->libknot.salt);
+ /* We don't really need to clear it, but it's not large. (`salt` zeroed above) */
+ memset(nsec_p, 0, sizeof(*nsec_p));
+}
+
+/** Compute new TTL for nsec_p entry, using SOA serial arith.
+ * \param new_ttl (optionally) write the new TTL (even if negative)
+ * \return error code, e.g. kr_error(ESTALE) */
+static int nsec_p_ttl(knot_db_val_t entry, const uint32_t timestamp, int32_t *new_ttl)
+{
+ if (!entry.data) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ uint32_t stamp;
+ if (!entry.len) {
+ return kr_error(ENOENT);
+ }
+ if (entry.len < sizeof(stamp)) {
+ assert(!EILSEQ);
+ return kr_error(EILSEQ);
+ }
+ memcpy(&stamp, entry.data, sizeof(stamp));
+ int32_t newttl = stamp - timestamp;
+ if (new_ttl) *new_ttl = newttl;
+ return newttl < 0 ? kr_error(ESTALE) : kr_ok();
+}
+
+static uint8_t get_lowest_rank(const struct kr_request *req, const struct kr_query *qry)
+{
+ /* TODO: move rank handling into the iterator (DNSSEC_* flags)? */
+ const bool allow_unverified =
+ knot_wire_get_cd(req->qsource.packet->wire) || qry->flags.STUB;
+ /* in stub mode we don't trust RRs anyway ^^ */
+ if (qry->flags.NONAUTH) {
+ return KR_RANK_INITIAL;
+ /* Note: there's little sense in validation status for non-auth records.
+ * In case of using NONAUTH to get NS IPs, knowing that you ask correct
+ * IP doesn't matter much for security; it matters whether you can
+ * validate the answers from the NS.
+ */
+ } else if (!allow_unverified) {
+ /* Records not present under any TA don't have their security
+ * verified at all, so we also accept low ranks in that case. */
+ const bool ta_covers = kr_ta_covers_qry(req->ctx, qry->sname, qry->stype);
+ /* ^ TODO: performance? TODO: stype - call sites */
+ if (ta_covers) {
+ return KR_RANK_INSECURE | KR_RANK_AUTH;
+ } /* else falltrhough */
+ }
+ return KR_RANK_INITIAL | KR_RANK_AUTH;
+}
+
+
+/** Almost whole .produce phase for the cache module.
+ * \note we don't transition to KR_STATE_FAIL even in case of "unexpected errors".
+ */
+int peek_nosync(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ struct kr_cache *cache = &req->ctx->cache;
+
+ struct key k_storage, *k = &k_storage;
+ int ret = kr_dname_lf(k->buf, qry->sname, false);
+ if (unlikely(ret)) {
+ assert(false);
+ return ctx->state;
+ }
+
+ const uint8_t lowest_rank = get_lowest_rank(req, qry);
+
+ /**** 1. find the name or the closest (available) zone, not considering wildcards
+ **** 1a. exact name+type match (can be negative answer in insecure zones) */
+ {
+ knot_db_val_t key = key_exact_type_maypkt(k, qry->stype);
+ knot_db_val_t val = { NULL, 0 };
+ ret = cache_op(cache, read, &key, &val, 1);
+ if (!ret) {
+ /* found an entry: test conditions, materialize into pkt, etc. */
+ ret = found_exact_hit(ctx, pkt, val, lowest_rank);
+ }
+ }
+ if (ret && ret != -abs(ENOENT)) {
+ VERBOSE_MSG(qry, "=> exact hit error: %d %s\n", ret, kr_strerror(ret));
+ assert(false);
+ return ctx->state;
+ } else if (!ret) {
+ return KR_STATE_DONE;
+ }
+
+ /**** 1b. otherwise, find the longest prefix zone/xNAME (with OK time+rank). [...] */
+ k->zname = qry->sname;
+ ret = kr_dname_lf(k->buf, k->zname, false); /* LATER(optim.): probably remove */
+ if (unlikely(ret)) {
+ assert(false);
+ return ctx->state;
+ }
+ entry_list_t el;
+ ret = closest_NS(cache, k, el, qry, false, qry->stype == KNOT_RRTYPE_DS);
+ if (ret) {
+ assert(ret == kr_error(ENOENT));
+ if (ret != kr_error(ENOENT) || !el[0].len) {
+ return ctx->state;
+ }
+ }
+ switch (k->type) {
+ case KNOT_RRTYPE_CNAME: {
+ const knot_db_val_t v = el[EL_CNAME];
+ assert(v.data && v.len);
+ const int32_t new_ttl = get_new_ttl(v.data, qry, qry->sname,
+ KNOT_RRTYPE_CNAME, qry->timestamp.tv_sec);
+ ret = answer_simple_hit(ctx, pkt, KNOT_RRTYPE_CNAME, v.data,
+ knot_db_val_bound(v), new_ttl);
+ /* TODO: ^^ cumbersome code; we also recompute the TTL */
+ return ret == kr_ok() ? KR_STATE_DONE : ctx->state;
+ }
+ case KNOT_RRTYPE_DNAME:
+ VERBOSE_MSG(qry, "=> DNAME not supported yet\n"); // LATER
+ return ctx->state;
+ }
+
+ /* We have to try proving from NSEC*. */
+ auto_free char *log_zname = NULL;
+ WITH_VERBOSE(qry) {
+ log_zname = kr_dname_text(k->zname);
+ if (!el[0].len) {
+ VERBOSE_MSG(qry, "=> no NSEC* cached for zone: %s\n", log_zname);
+ }
+ }
+
+#if 0
+ if (!eh) { /* fall back to root hints? */
+ ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
+ if (ret) return ctx->state;
+ assert(!qry->zone_cut.parent);
+
+ //VERBOSE_MSG(qry, "=> using root hints\n");
+ //qry->flags.AWAIT_CUT = false;
+ return ctx->state;
+ }
+
+ /* Now `eh` points to the closest NS record that we've found,
+ * and that's the only place to start - we may either find
+ * a negative proof or we may query upstream from that point. */
+ kr_zonecut_set(&qry->zone_cut, k->zname);
+ ret = kr_make_query(qry, pkt); // TODO: probably not yet - qname minimization
+ if (ret) return ctx->state;
+#endif
+
+ /** Structure for collecting multiple NSEC* + RRSIG records,
+ * in preparation for the answer, and for tracking the progress. */
+ struct answer ans;
+ memset(&ans, 0, sizeof(ans));
+ ans.mm = &pkt->mm;
+ const int sname_labels = knot_dname_labels(qry->sname, NULL);
+
+ /* Try the NSEC* parameters in order, until success.
+ * Let's not mix different parameters for NSEC* RRs in a single proof. */
+ for (int i = 0; ;) {
+ int32_t log_new_ttl = -123456789; /* visually recognizable value */
+ ret = nsec_p_ttl(el[i], qry->timestamp.tv_sec, &log_new_ttl);
+ if (!ret || VERBOSE_STATUS) {
+ nsec_p_init(&ans.nsec_p, el[i], !ret);
+ }
+ if (ret) {
+ VERBOSE_MSG(qry, "=> skipping zone: %s, %s, hash %x;"
+ "new TTL %d, ret %d\n",
+ log_zname, (ans.nsec_p.raw ? "NSEC3" : "NSEC"),
+ (unsigned)ans.nsec_p.hash, (int)log_new_ttl, ret);
+ /* no need for nsec_p_cleanup() in this case */
+ goto cont;
+ }
+ VERBOSE_MSG(qry, "=> trying zone: %s, %s, hash %x\n",
+ log_zname, (ans.nsec_p.raw ? "NSEC3" : "NSEC"),
+ (unsigned)ans.nsec_p.hash);
+ /**** 2. and 3. inside */
+ ret = peek_encloser(k, &ans, sname_labels,
+ lowest_rank, qry, cache);
+ nsec_p_cleanup(&ans.nsec_p);
+ if (!ret) break;
+ if (ret < 0) return ctx->state;
+ cont:
+ /* Otherwise we try another nsec_p, if available. */
+ if (++i == ENTRY_APEX_NSECS_CNT) return ctx->state;
+ /* clear possible partial answers in `ans` (no need to deallocate) */
+ ans.rcode = 0;
+ memset(&ans.rrsets, 0, sizeof(ans.rrsets));
+ }
+
+ /**** 4. add SOA iff needed */
+ if (ans.rcode != PKT_NOERROR) {
+ /* Assuming k->buf still starts with zone's prefix,
+ * look up the SOA in cache. */
+ k->buf[0] = k->zlf_len;
+ knot_db_val_t key = key_exact_type(k, KNOT_RRTYPE_SOA);
+ knot_db_val_t val = { NULL, 0 };
+ ret = cache_op(cache, read, &key, &val, 1);
+ const struct entry_h *eh;
+ if (ret || !(eh = entry_h_consistent(val, KNOT_RRTYPE_SOA))) {
+ assert(ret); /* only want to catch `eh` failures */
+ VERBOSE_MSG(qry, "=> SOA missed\n");
+ return ctx->state;
+ }
+ /* Check if the record is OK. */
+ int32_t new_ttl = get_new_ttl(eh, qry, k->zname, KNOT_RRTYPE_SOA,
+ qry->timestamp.tv_sec);
+ if (new_ttl < 0 || eh->rank < lowest_rank || eh->is_packet) {
+ VERBOSE_MSG(qry, "=> SOA unfit %s: rank 0%.2o, new TTL %d\n",
+ (eh->is_packet ? "packet" : "RR"),
+ eh->rank, new_ttl);
+ return ctx->state;
+ }
+ /* Add the SOA into the answer. */
+ ret = entry2answer(&ans, AR_SOA, eh, knot_db_val_bound(val),
+ k->zname, KNOT_RRTYPE_SOA, new_ttl);
+ if (ret) return ctx->state;
+ }
+
+ /* Find our target RCODE. */
+ int real_rcode;
+ switch (ans.rcode) {
+ case PKT_NODATA:
+ case PKT_NOERROR: /* positive wildcarded response */
+ real_rcode = KNOT_RCODE_NOERROR;
+ break;
+ case PKT_NXDOMAIN:
+ real_rcode = KNOT_RCODE_NXDOMAIN;
+ break;
+ default:
+ assert(false);
+ case 0: /* i.e. nothing was found */
+ /* LATER(optim.): zone cut? */
+ VERBOSE_MSG(qry, "=> cache miss\n");
+ return ctx->state;
+ }
+
+ if (pkt_renew(pkt, qry->sname, qry->stype)
+ || knot_pkt_begin(pkt, KNOT_ANSWER)
+ ) {
+ assert(false);
+ return ctx->state;
+ }
+ knot_wire_set_rcode(pkt->wire, real_rcode);
+
+ bool expiring = false; // TODO
+ VERBOSE_MSG(qry, "=> writing RRsets: ");
+ for (int i = 0; i < sizeof(ans.rrsets) / sizeof(ans.rrsets[0]); ++i) {
+ if (i == 1) knot_pkt_begin(pkt, KNOT_AUTHORITY);
+ if (!ans.rrsets[i].set.rr) continue;
+ expiring = expiring || ans.rrsets[i].set.expiring;
+ ret = pkt_append(pkt, &ans.rrsets[i], ans.rrsets[i].set.rank);
+ if (ret) {
+ assert(false);
+ return ctx->state;
+ }
+ kr_log_verbose(kr_rank_test(ans.rrsets[i].set.rank, KR_RANK_SECURE)
+ ? "+" : "-");
+ }
+ kr_log_verbose("\n");
+
+ /* Finishing touches. */
+ struct kr_qflags * const qf = &qry->flags;
+ qf->EXPIRING = expiring;
+ qf->CACHED = true;
+ qf->NO_MINIMIZE = true;
+
+ return KR_STATE_DONE;
+}
+
+/**
+ * This is where the high-level "business logic" of aggressive cache is.
+ * \return 0: success (may need SOA); >0: try other nsec_p; <0: exit cache immediately.
+ */
+static int peek_encloser(
+ struct key *k, struct answer *ans, const int sname_labels,
+ uint8_t lowest_rank, const struct kr_query *qry, struct kr_cache *cache)
+{
+ /** Start of NSEC* covering the sname;
+ * it's part of key - the one within zone (read only) */
+ knot_db_val_t cover_low_kwz = { NULL, 0 };
+ knot_dname_t cover_hi_storage[KNOT_DNAME_MAXLEN];
+ /** End of NSEC* covering the sname. */
+ knot_db_val_t cover_hi_kwz = {
+ .data = cover_hi_storage,
+ .len = sizeof(cover_hi_storage),
+ };
+
+ /**** 2. Find a closest (provable) encloser (of sname). */
+ int clencl_labels = -1;
+ bool clencl_is_tentative = false;
+ if (!ans->nsec_p.raw) { /* NSEC */
+ int ret = nsec1_encloser(k, ans, sname_labels, &clencl_labels,
+ &cover_low_kwz, &cover_hi_kwz, qry, cache);
+ if (ret) return ret;
+ } else {
+ int ret = nsec3_encloser(k, ans, sname_labels, &clencl_labels,
+ qry, cache);
+ clencl_is_tentative = ret == ABS(ENOENT) && clencl_labels >= 0;
+ /* ^^ Last chance: *positive* wildcard record under this clencl. */
+ if (ret && !clencl_is_tentative) return ret;
+ }
+
+ /* We should have either a match or a cover at this point. */
+ if (ans->rcode != PKT_NODATA && ans->rcode != PKT_NXDOMAIN) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ const bool ncloser_covered = ans->rcode == PKT_NXDOMAIN;
+
+ /** Name of the closest (provable) encloser. */
+ const knot_dname_t *clencl_name = qry->sname;
+ for (int l = sname_labels; l > clencl_labels; --l)
+ clencl_name = knot_wire_next_label(clencl_name, NULL);
+
+ /**** 3. source of synthesis checks, in case the next closer name was covered.
+ **** 3a. We want to query for NSEC* of source of synthesis (SS) or its
+ * predecessor, providing us with a proof of its existence or non-existence. */
+ if (ncloser_covered && !ans->nsec_p.raw) {
+ int ret = nsec1_src_synth(k, ans, clencl_name,
+ cover_low_kwz, cover_hi_kwz, qry, cache);
+ if (ret == AR_SOA) return 0;
+ assert(ret <= 0);
+ if (ret) return ret;
+
+ } else if (ncloser_covered && ans->nsec_p.raw && !clencl_is_tentative) {
+ int ret = nsec3_src_synth(k, ans, clencl_name, qry, cache);
+ if (ret == AR_SOA) return 0;
+ assert(ret <= 0);
+ if (ret) return ret;
+
+ } /* else (!ncloser_covered) so no wildcard checks needed,
+ * as we proved that sname exists. */
+
+ /**** 3b. find wildcarded answer, if next closer name was covered
+ * and we don't have a full proof yet. (common for NSEC*) */
+ if (!ncloser_covered)
+ return kr_ok(); /* decrease indentation */
+ /* Construct key for exact qry->stype + source of synthesis. */
+ int ret = kr_dname_lf(k->buf, clencl_name, true);
+ if (ret) {
+ assert(!ret);
+ return kr_error(ret);
+ }
+ const uint16_t types[] = { qry->stype, KNOT_RRTYPE_CNAME };
+ for (int i = 0; i < (2 - (qry->stype == KNOT_RRTYPE_CNAME)); ++i) {
+ ret = try_wild(k, ans, clencl_name, types[i],
+ lowest_rank, qry, cache);
+ if (ret == kr_ok()) {
+ return kr_ok();
+ } else if (ret != -ABS(ENOENT) && ret != -ABS(ESTALE)) {
+ assert(false);
+ return kr_error(ret);
+ }
+ /* else continue */
+ }
+ /* Neither attempt succeeded, but the NSEC* proofs were found,
+ * so skip trying other parameters, as it seems very unlikely
+ * to turn out differently than by the same wildcard search. */
+ return -ABS(ENOENT);
+}
+
+
+static int answer_simple_hit(kr_layer_t *ctx, knot_pkt_t *pkt, uint16_t type,
+ const struct entry_h *eh, const void *eh_bound, uint32_t new_ttl)
+#define CHECK_RET(ret) do { \
+ if ((ret) < 0) { assert(false); return kr_error((ret)); } \
+} while (false)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ /* All OK, so start constructing the (pseudo-)packet. */
+ int ret = pkt_renew(pkt, qry->sname, qry->stype);
+ CHECK_RET(ret);
+
+ /* Materialize the sets for the answer in (pseudo-)packet. */
+ struct answer ans;
+ memset(&ans, 0, sizeof(ans));
+ ans.mm = &pkt->mm;
+ ret = entry2answer(&ans, AR_ANSWER, eh, eh_bound,
+ qry->sname, type, new_ttl);
+ CHECK_RET(ret);
+ /* Put links to the materialized data into the pkt. */
+ ret = pkt_append(pkt, &ans.rrsets[AR_ANSWER], eh->rank);
+ CHECK_RET(ret);
+
+ /* Finishing touches. */
+ struct kr_qflags * const qf = &qry->flags;
+ qf->EXPIRING = is_expiring(eh->ttl, new_ttl);
+ qf->CACHED = true;
+ qf->NO_MINIMIZE = true;
+ qf->DNSSEC_INSECURE = kr_rank_test(eh->rank, KR_RANK_INSECURE);
+ if (qf->DNSSEC_INSECURE) {
+ qf->DNSSEC_WANT = false;
+ }
+ VERBOSE_MSG(qry, "=> satisfied by exact %s: rank 0%.2o, new TTL %d\n",
+ (type == KNOT_RRTYPE_CNAME ? "CNAME" : "RRset"),
+ eh->rank, new_ttl);
+ return kr_ok();
+}
+#undef CHECK_RET
+
+
+/** TODO: description; see the single call site for now. */
+static int found_exact_hit(kr_layer_t *ctx, knot_pkt_t *pkt, knot_db_val_t val,
+ uint8_t lowest_rank)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ int ret = entry_h_seek(&val, qry->stype);
+ if (ret) return ret;
+ const struct entry_h *eh = entry_h_consistent(val, qry->stype);
+ if (!eh) {
+ assert(false);
+ return kr_error(ENOENT);
+ // LATER: recovery in case of error, perhaps via removing the entry?
+ // LATER(optim): pehaps optimize the zone cut search
+ }
+
+ int32_t new_ttl = get_new_ttl(eh, qry, qry->sname, qry->stype,
+ qry->timestamp.tv_sec);
+ if (new_ttl < 0 || eh->rank < lowest_rank) {
+ /* Positive record with stale TTL or bad rank.
+ * LATER(optim.): It's unlikely that we find a negative one,
+ * so we might theoretically skip all the cache code. */
+
+ VERBOSE_MSG(qry, "=> skipping exact %s: rank 0%.2o (min. 0%.2o), new TTL %d\n",
+ eh->is_packet ? "packet" : "RR", eh->rank, lowest_rank, new_ttl);
+ return kr_error(ENOENT);
+ }
+
+ const uint8_t *eh_bound = knot_db_val_bound(val);
+ if (eh->is_packet) {
+ /* Note: we answer here immediately, even if it's (theoretically)
+ * possible that we could generate a higher-security negative proof.
+ * Rank is high-enough so we take it to save time searching. */
+ return answer_from_pkt (ctx, pkt, qry->stype, eh, eh_bound, new_ttl);
+ } else {
+ return answer_simple_hit(ctx, pkt, qry->stype, eh, eh_bound, new_ttl);
+ }
+}
+
+
+/** Try to satisfy via wildcard (positively). See the single call site. */
+static int try_wild(struct key *k, struct answer *ans, const knot_dname_t *clencl_name,
+ const uint16_t type, const uint8_t lowest_rank,
+ const struct kr_query *qry, struct kr_cache *cache)
+{
+ knot_db_val_t key = key_exact_type(k, type);
+ /* Find the record. */
+ knot_db_val_t val = { NULL, 0 };
+ int ret = cache_op(cache, read, &key, &val, 1);
+ if (!ret) {
+ ret = entry_h_seek(&val, type);
+ }
+ if (ret) {
+ if (ret != -ABS(ENOENT)) {
+ VERBOSE_MSG(qry, "=> wildcard: hit error %d %s\n",
+ ret, strerror(abs(ret)));
+ assert(false);
+ }
+ WITH_VERBOSE(qry) {
+ auto_free char *clencl_str = kr_dname_text(clencl_name),
+ *type_str = kr_rrtype_text(type);
+ VERBOSE_MSG(qry, "=> wildcard: not found: *.%s %s\n",
+ clencl_str, type_str);
+ }
+ return ret;
+ }
+ /* Check if the record is OK. */
+ const struct entry_h *eh = entry_h_consistent(val, type);
+ if (!eh) {
+ assert(false);
+ return kr_error(ret);
+ // LATER: recovery in case of error, perhaps via removing the entry?
+ }
+ int32_t new_ttl = get_new_ttl(eh, qry, qry->sname, type, qry->timestamp.tv_sec);
+ /* ^^ here we use the *expanded* wildcard name */
+ if (new_ttl < 0 || eh->rank < lowest_rank || eh->is_packet) {
+ /* Wildcard record with stale TTL, bad rank or packet. */
+ VERBOSE_MSG(qry, "=> wildcard: skipping %s, rank 0%.2o, new TTL %d\n",
+ eh->is_packet ? "packet" : "RR", eh->rank, new_ttl);
+ return -ABS(ESTALE);
+ }
+ /* Add the RR into the answer. */
+ ret = entry2answer(ans, AR_ANSWER, eh, knot_db_val_bound(val),
+ qry->sname, type, new_ttl);
+ VERBOSE_MSG(qry, "=> wildcard: answer expanded, ret = %d, new TTL %d\n",
+ ret, (int)new_ttl);
+ if (ret) return kr_error(ret);
+ ans->rcode = PKT_NOERROR;
+ return kr_ok();
+}
+
+int kr_cache_closest_apex(struct kr_cache *cache, const knot_dname_t *name, bool is_DS,
+ knot_dname_t ** apex)
+{
+ if (!cache || !cache->db || !name || !apex || *apex) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ struct key k_storage, *k = &k_storage;
+ int ret = kr_dname_lf(k->buf, name, false);
+ if (ret)
+ return kr_error(ret);
+ entry_list_t el_;
+ k->zname = name;
+ ret = closest_NS(cache, k, el_, NULL, true, is_DS);
+ if (ret && ret != -abs(ENOENT))
+ return ret;
+ *apex = knot_dname_copy(k->zname, NULL);
+ if (!*apex)
+ return kr_error(ENOMEM);
+ return kr_ok();
+}
+
+/** \internal for closest_NS. Check suitability of a single entry, setting k->type if OK.
+ * \return error code, negative iff whole list should be skipped.
+ */
+static int check_NS_entry(struct key *k, knot_db_val_t entry, int i,
+ bool exact_match, bool is_DS,
+ const struct kr_query *qry, uint32_t timestamp);
+
+/**
+ * Find the longest prefix zone/xNAME (with OK time+rank), starting at k->*.
+ *
+ * The found type is returned via k->type; the values are returned in el.
+ * \note we use k->type = KNOT_RRTYPE_NS also for the nsec_p result.
+ * \param qry can be NULL (-> gettimeofday(), but you lose the stale-serve hook)
+ * \param only_NS don't consider xNAMEs
+ * \return error code
+ */
+static int closest_NS(struct kr_cache *cache, struct key *k, entry_list_t el,
+ struct kr_query *qry, const bool only_NS, const bool is_DS)
+{
+ /* get the current timestamp */
+ uint32_t timestamp;
+ if (qry) {
+ timestamp = qry->timestamp.tv_sec;
+ } else {
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL)) return kr_error(errno);
+ timestamp = tv.tv_sec;
+ }
+
+ int zlf_len = k->buf[0];
+
+ // LATER(optim): if stype is NS, we check the same value again
+ bool exact_match = true;
+ bool need_zero = true;
+ /* Inspect the NS/xNAME entries, shortening by a label on each iteration. */
+ do {
+ k->buf[0] = zlf_len;
+ knot_db_val_t key = key_exact_type(k, KNOT_RRTYPE_NS);
+ knot_db_val_t val;
+ int ret = cache_op(cache, read, &key, &val, 1);
+ if (ret == -abs(ENOENT)) goto next_label;
+ if (ret) {
+ assert(!ret);
+ if (need_zero) memset(el, 0, sizeof(entry_list_t));
+ return kr_error(ret);
+ }
+
+ /* Check consistency, find any type;
+ * using `goto` for shortening by another label. */
+ ret = entry_list_parse(val, el);
+ if (ret) {
+ assert(!ret); // do something about it?
+ goto next_label;
+ }
+ need_zero = false;
+ /* More types are possible; try in order.
+ * For non-fatal failures just "continue;" to try the next type. */
+ const int el_count = only_NS ? EL_NS + 1 : EL_LENGTH;
+ for (int i = 0; i < el_count; ++i) {
+ ret = check_NS_entry(k, el[i], i, exact_match, is_DS,
+ qry, timestamp);
+ if (ret < 0) goto next_label; else
+ if (!ret) {
+ /* We found our match. */
+ k->zlf_len = zlf_len;
+ return kr_ok();
+ }
+ }
+
+ next_label:
+ /* remove one more label */
+ exact_match = false;
+ if (k->zname[0] == 0) {
+ /* We miss root NS in cache, but let's at least assume it exists. */
+ k->type = KNOT_RRTYPE_NS;
+ k->zlf_len = zlf_len;
+ assert(zlf_len == 0);
+ if (need_zero) memset(el, 0, sizeof(entry_list_t));
+ return kr_error(ENOENT);
+ }
+ zlf_len -= (k->zname[0] + 1);
+ k->zname += (k->zname[0] + 1);
+ k->buf[zlf_len + 1] = 0;
+ } while (true);
+}
+
+static int check_NS_entry(struct key *k, const knot_db_val_t entry, const int i,
+ const bool exact_match, const bool is_DS,
+ const struct kr_query *qry, uint32_t timestamp)
+{
+ const int ESKIP = ABS(ENOENT);
+ if (!entry.len
+ /* On a zone cut we want DS from the parent zone. */
+ || (i <= EL_NS && exact_match && is_DS)
+ /* CNAME is interesting only if we
+ * directly hit the name that was asked.
+ * Note that we want it even in the DS case. */
+ || (i == EL_CNAME && !exact_match)
+ /* DNAME is interesting only if we did NOT
+ * directly hit the name that was asked. */
+ || (i == EL_DNAME && exact_match)
+ ) {
+ return ESKIP;
+ }
+
+ uint16_t type;
+ if (i < ENTRY_APEX_NSECS_CNT) {
+ type = KNOT_RRTYPE_NS;
+ int32_t log_new_ttl = -123456789; /* visually recognizable value */
+ const int err = nsec_p_ttl(entry, timestamp, &log_new_ttl);
+ if (err) {
+ VERBOSE_MSG(qry,
+ "=> skipping unfit nsec_p: new TTL %d, error %d\n",
+ (int)log_new_ttl, err);
+ return ESKIP;
+ }
+ } else {
+ type = EL2RRTYPE(i);
+ /* Find the entry for the type, check positivity, TTL */
+ const struct entry_h *eh = entry_h_consistent(entry, type);
+ if (!eh) {
+ VERBOSE_MSG(qry, "=> EH not consistent\n");
+ assert(false);
+ return kr_error(EILSEQ);
+ }
+ const int32_t log_new_ttl = get_new_ttl(eh, qry, k->zname, type, timestamp);
+ const uint8_t rank_min = KR_RANK_INSECURE | KR_RANK_AUTH;
+ const bool ok = /* For NS any kr_rank is accepted,
+ * as insecure or even nonauth is OK */
+ (type == KNOT_RRTYPE_NS || eh->rank >= rank_min)
+ /* Not interested in negative bogus or outdated RRs. */
+ && !eh->is_packet && log_new_ttl >= 0;
+ WITH_VERBOSE(qry) { if (!ok) {
+ auto_free char *type_str = kr_rrtype_text(type);
+ const char *packet_str = eh->is_packet ? "packet" : "RR";
+ VERBOSE_MSG(qry,
+ "=> skipping unfit %s %s: rank 0%.2o, new TTL %d\n",
+ type_str, packet_str, eh->rank, (int)log_new_ttl);
+ } }
+ if (!ok) return ESKIP;
+ }
+ k->type = type;
+ return kr_ok();
+}
+
diff --git a/lib/cookies/alg_containers.c b/lib/cookies/alg_containers.c
new file mode 100644
index 0000000..a80487d
--- /dev/null
+++ b/lib/cookies/alg_containers.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <libknot/cookies/alg-fnv64.h>
+
+#include "lib/cookies/alg_containers.h"
+#include "lib/cookies/alg_sha.h"
+
+const struct knot_cc_alg *kr_cc_alg_get(int id)
+{
+ /*
+ * Client algorithm identifiers are used to index this array of
+ * pointers.
+ */
+ static const struct knot_cc_alg *const cc_algs[] = {
+ /* 0 */ &knot_cc_alg_fnv64,
+ /* 1 */ &knot_cc_alg_hmac_sha256_64
+ };
+
+ if (id >= 0 && id < 2) {
+ return cc_algs[id];
+ }
+
+ return NULL;
+}
+
+const knot_lookup_t kr_cc_alg_names[] = {
+ { 0, "FNV-64" },
+ { 1, "HMAC-SHA256-64" },
+ { -1, NULL }
+};
+
+const struct knot_sc_alg *kr_sc_alg_get(int id)
+{
+ /*
+ * Server algorithm identifiers are used to index this array of
+ * pointers.
+ */
+ static const struct knot_sc_alg *const sc_algs[] = {
+ /* 0 */ &knot_sc_alg_fnv64,
+ /* 1 */ &knot_sc_alg_hmac_sha256_64
+ };
+
+ if (id >= 0 && id < 2) {
+ return sc_algs[id];
+ }
+
+ return NULL;
+}
+
+const knot_lookup_t kr_sc_alg_names[] = {
+ { 0, "FNV-64" },
+ { 1, "HMAC-SHA256-64" },
+ { -1, NULL }
+};
diff --git a/lib/cookies/alg_containers.h b/lib/cookies/alg_containers.h
new file mode 100644
index 0000000..1e2aef6
--- /dev/null
+++ b/lib/cookies/alg_containers.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/cookies/client.h>
+#include <libknot/cookies/server.h>
+#include <libknot/lookup.h>
+
+#include "lib/defines.h"
+
+/**
+ * @brief Returns pointer to client cookie algorithm.
+ *
+ * @param id algorithm identifier as defined by lookup table
+ * @return pointer to algorithm structure with given id or NULL on error
+ */
+KR_EXPORT
+const struct knot_cc_alg *kr_cc_alg_get(int id);
+
+/** Binds client algorithm identifiers onto names. */
+KR_EXPORT
+extern const knot_lookup_t kr_cc_alg_names[];
+
+/**
+ * @brief Returns pointer to server cookie algorithm.
+ *
+ * @param id algorithm identifier as defined by lookup table
+ * @return pointer to algorithm structure with given id or NULL on error
+ */
+KR_EXPORT
+const struct knot_sc_alg *kr_sc_alg_get(int id);
+
+/** Binds server algorithm identifiers onto names. */
+KR_EXPORT
+extern const knot_lookup_t kr_sc_alg_names[];
diff --git a/lib/cookies/alg_sha.c b/lib/cookies/alg_sha.c
new file mode 100644
index 0000000..e23c983
--- /dev/null
+++ b/lib/cookies/alg_sha.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <nettle/hmac.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <libknot/errcode.h>
+#include <libknot/rrtype/opt-cookie.h>
+
+#include "lib/cookies/alg_sha.h"
+#include "lib/utils.h"
+
+/**
+ * @brief Update hash value.
+ *
+ * @param ctx HMAC-SHA256 context to be updated.
+ * @param sa Socket address.
+ */
+static inline void update_hash(struct hmac_sha256_ctx *ctx,
+ const struct sockaddr *sa)
+{
+ assert(ctx && sa);
+
+ int addr_len = kr_inaddr_len(sa);
+ const uint8_t *addr = (uint8_t *)kr_inaddr(sa);
+
+ if (addr && addr_len > 0) {
+ hmac_sha256_update(ctx, addr_len, addr);
+ }
+}
+
+/**
+ * @brief Compute client cookie using HMAC-SHA256-64.
+ * @note At least one of the arguments must be non-null.
+ * @param input input parameters
+ * @param cc_out buffer for computed client cookie
+ * @param cc_len buffer size
+ * @return Non-zero size of written data on success, 0 in case of a failure.
+ */
+static uint16_t cc_gen_hmac_sha256_64(const struct knot_cc_input *input,
+ uint8_t *cc_out, uint16_t cc_len)
+{
+ if (!knot_cc_input_is_valid(input) ||
+ !cc_out || cc_len < KNOT_OPT_COOKIE_CLNT) {
+ return 0;
+ }
+
+ struct hmac_sha256_ctx ctx;
+ hmac_sha256_set_key(&ctx, input->secret_len, input->secret_data);
+
+ if (input->clnt_sockaddr) {
+ update_hash(&ctx, input->clnt_sockaddr);
+ }
+
+ if (input->srvr_sockaddr) {
+ update_hash(&ctx, input->srvr_sockaddr);
+ }
+
+ /* KNOT_OPT_COOKIE_CLNT <= SHA256_DIGEST_SIZE */
+
+ hmac_sha256_digest(&ctx, KNOT_OPT_COOKIE_CLNT, cc_out);
+
+ return KNOT_OPT_COOKIE_CLNT;
+}
+
+#define SRVR_HMAC_SHA256_64_HASH_SIZE 8
+
+/**
+ * @brief Compute server cookie hash using HMAC-SHA256-64).
+ * @note Server cookie = nonce | time | HMAC-SHA256-64( server secret, client cookie | nonce| time | client IP )
+ * @param input data to compute cookie from
+ * @param hash_out hash output buffer
+ * @param hash_len buffer size
+ * @return Non-zero size of written data on success, 0 in case of a failure.
+ */
+static uint16_t sc_gen_hmac_sha256_64(const struct knot_sc_input *input,
+ uint8_t *hash_out, uint16_t hash_len)
+{
+ if (!knot_sc_input_is_valid(input) ||
+ !hash_out || hash_len < SRVR_HMAC_SHA256_64_HASH_SIZE) {
+ return 0;
+ }
+
+ struct hmac_sha256_ctx ctx;
+ hmac_sha256_set_key(&ctx, input->srvr_data->secret_len,
+ input->srvr_data->secret_data);
+
+ hmac_sha256_update(&ctx, input->cc_len, input->cc);
+
+ if (input->nonce && input->nonce_len) {
+ hmac_sha256_update(&ctx, input->nonce_len, input->nonce);
+ }
+
+ if (input->srvr_data->clnt_sockaddr) {
+ update_hash(&ctx, input->srvr_data->clnt_sockaddr);
+ }
+
+ /* SRVR_HMAC_SHA256_64_HASH_SIZE < SHA256_DIGEST_SIZE */
+
+ hmac_sha256_digest(&ctx, SRVR_HMAC_SHA256_64_HASH_SIZE, hash_out);
+
+ return SRVR_HMAC_SHA256_64_HASH_SIZE;
+}
+
+const struct knot_cc_alg knot_cc_alg_hmac_sha256_64 = { KNOT_OPT_COOKIE_CLNT, cc_gen_hmac_sha256_64 };
+
+const struct knot_sc_alg knot_sc_alg_hmac_sha256_64 = { SRVR_HMAC_SHA256_64_HASH_SIZE, sc_gen_hmac_sha256_64 };
diff --git a/lib/cookies/alg_sha.h b/lib/cookies/alg_sha.h
new file mode 100644
index 0000000..5b0d0c9
--- /dev/null
+++ b/lib/cookies/alg_sha.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/cookies/client.h>
+#include <libknot/cookies/server.h>
+
+#include "lib/defines.h"
+
+/* These structures are not meant to be part of public interface. */
+
+/** HMAC-SHA256-64 client cookie algorithm. */
+extern const struct knot_cc_alg knot_cc_alg_hmac_sha256_64;
+
+/** HMAC-SHA256-64 server cookie algorithm. */
+extern const struct knot_sc_alg knot_sc_alg_hmac_sha256_64;
diff --git a/lib/cookies/control.h b/lib/cookies/control.h
new file mode 100644
index 0000000..1bf503f
--- /dev/null
+++ b/lib/cookies/control.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "lib/defines.h"
+
+/** Holds secret quantity. */
+struct kr_cookie_secret {
+ size_t size; /*!< Secret quantity size. */
+ uint8_t data[]; /*!< Secret quantity data. */
+};
+
+/** Holds settings that have direct influence on cookie values computation. */
+struct kr_cookie_comp {
+ struct kr_cookie_secret *secr; /*!< Secret data. */
+ int alg_id; /*!< Cookie algorithm identifier. */
+};
+
+/** Holds settings that control client/server cookie behaviour. */
+struct kr_cookie_settings {
+ bool enabled; /**< Enable/disables DNS cookies functionality. */
+
+ struct kr_cookie_comp current; /**< Current cookie settings. */
+ struct kr_cookie_comp recent; /**< Recent cookie settings. */
+};
+
+/** DNS cookies controlling structure. */
+struct kr_cookie_ctx {
+ struct kr_cookie_settings clnt; /**< Client settings. */
+ struct kr_cookie_settings srvr; /**< Server settings. */
+};
diff --git a/lib/cookies/helper.c b/lib/cookies/helper.c
new file mode 100644
index 0000000..e07b8cb
--- /dev/null
+++ b/lib/cookies/helper.c
@@ -0,0 +1,296 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <libknot/rrtype/opt.h>
+#include <libknot/rrtype/opt-cookie.h>
+
+#include "lib/cookies/helper.h"
+#include "lib/defines.h"
+
+/**
+ * @brief Check whether there is a cached cookie that matches the current
+ * client cookie.
+ */
+static const uint8_t *peek_and_check_cc(kr_cookie_lru_t *cache, const void *sa,
+ const uint8_t *cc, uint16_t cc_len)
+{
+ assert(cache && sa && cc && cc_len);
+
+ const uint8_t *cached_opt = kr_cookie_lru_get(cache, sa);
+ if (!cached_opt) {
+ return NULL;
+ }
+
+ const uint8_t *cached_cc = knot_edns_opt_get_data((uint8_t *) cached_opt);
+
+ if (cc_len == KNOT_OPT_COOKIE_CLNT &&
+ 0 == memcmp(cc, cached_cc, cc_len)) {
+ return cached_opt;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Put a client cookie into the RR Set.
+ */
+static int opt_rr_put_cookie(knot_rrset_t *opt_rr, uint8_t *data,
+ uint16_t data_len, knot_mm_t *mm)
+{
+ assert(opt_rr && data && data_len > 0);
+
+ const uint8_t *cc = NULL, *sc = NULL;
+ uint16_t cc_len = 0, sc_len = 0;
+
+ int ret = knot_edns_opt_cookie_parse(data, data_len, &cc, &cc_len,
+ &sc, &sc_len);
+ if (ret != KNOT_EOK) {
+ return kr_error(EINVAL);
+ }
+ assert(data_len == cc_len + sc_len);
+
+ uint16_t cookies_size = data_len;
+ uint8_t *cookies_data = NULL;
+
+ ret = knot_edns_reserve_unique_option(opt_rr, KNOT_EDNS_OPTION_COOKIE,
+ cookies_size, &cookies_data, mm);
+ if (ret != KNOT_EOK) {
+ return kr_error(EINVAL);
+ }
+ assert(cookies_data != NULL);
+
+ cookies_size = knot_edns_opt_cookie_write(cc, cc_len, sc, sc_len,
+ cookies_data, cookies_size);
+ if (cookies_size == 0) {
+ return kr_error(EINVAL);
+ }
+ assert(cookies_size == data_len);
+
+ return kr_ok();
+}
+
+/**
+ * @brief Puts entire EDNS option into the RR Set.
+ */
+static int opt_rr_put_cookie_opt(knot_rrset_t *opt_rr, uint8_t *option, knot_mm_t *mm)
+{
+ assert(opt_rr && option);
+
+ uint16_t opt_code = knot_edns_opt_get_code(option);
+ if (opt_code != KNOT_EDNS_OPTION_COOKIE) {
+ return kr_error(EINVAL);
+ }
+
+ uint16_t opt_len = knot_edns_opt_get_length(option);
+ uint8_t *opt_data = knot_edns_opt_get_data(option);
+ if (!opt_data || opt_len == 0) {
+ return kr_error(EINVAL);
+ }
+
+ return opt_rr_put_cookie(opt_rr, opt_data, opt_len, mm);
+}
+
+int kr_request_put_cookie(const struct kr_cookie_comp *clnt_comp,
+ kr_cookie_lru_t *cookie_cache,
+ const struct sockaddr *clnt_sa,
+ const struct sockaddr *srvr_sa,
+ struct kr_request *req)
+{
+ if (!clnt_comp || !req) {
+ return kr_error(EINVAL);
+ }
+
+ if (!req->ctx->opt_rr) {
+ return kr_ok();
+ }
+
+ if (!clnt_comp->secr || (clnt_comp->alg_id < 0) || !cookie_cache) {
+ return kr_error(EINVAL);
+ }
+
+ /*
+ * Generate client cookie from client address, server address and
+ * secret quantity.
+ */
+ struct knot_cc_input input = {
+ .clnt_sockaddr = clnt_sa,
+ .srvr_sockaddr = srvr_sa,
+ .secret_data = clnt_comp->secr->data,
+ .secret_len = clnt_comp->secr->size
+ };
+ uint8_t cc[KNOT_OPT_COOKIE_CLNT];
+ uint16_t cc_len = KNOT_OPT_COOKIE_CLNT;
+ const struct knot_cc_alg *cc_alg = kr_cc_alg_get(clnt_comp->alg_id);
+ if (!cc_alg) {
+ return kr_error(EINVAL);
+ }
+ assert(cc_alg->gen_func);
+ cc_len = cc_alg->gen_func(&input, cc, cc_len);
+ if (cc_len != KNOT_OPT_COOKIE_CLNT) {
+ return kr_error(EINVAL);
+ }
+
+ const uint8_t *cached_cookie = peek_and_check_cc(cookie_cache,
+ srvr_sa, cc, cc_len);
+
+ /* Add cookie option. */
+ int ret;
+ if (cached_cookie) {
+ ret = opt_rr_put_cookie_opt(req->ctx->opt_rr,
+ (uint8_t *)cached_cookie,
+ req->ctx->pool);
+ } else {
+ ret = opt_rr_put_cookie(req->ctx->opt_rr, cc, cc_len,
+ req->ctx->pool);
+ }
+
+ return ret;
+}
+
+int kr_answer_write_cookie(struct knot_sc_input *sc_input,
+ const struct kr_nonce_input *nonce,
+ const struct knot_sc_alg *alg, knot_pkt_t *pkt)
+{
+ if (!sc_input || !sc_input->cc || sc_input->cc_len == 0) {
+ return kr_error(EINVAL);
+ }
+
+ if (!sc_input->srvr_data || !sc_input->srvr_data->clnt_sockaddr ||
+ !sc_input->srvr_data->secret_data ||
+ !sc_input->srvr_data->secret_len) {
+ return kr_error(EINVAL);
+ }
+
+ if (!nonce) {
+ return kr_error(EINVAL);
+ }
+
+ if (!alg || !alg->hash_size || !alg->hash_func) {
+ return kr_error(EINVAL);
+ }
+
+ if (!pkt || !pkt->opt_rr) {
+ return kr_error(EINVAL);
+ }
+
+ uint16_t nonce_len = KR_NONCE_LEN;
+ uint16_t hash_len = alg->hash_size;
+
+ /*
+ * Space for cookie is reserved inside the EDNS OPT RR of
+ * the answer packet.
+ */
+ uint8_t *cookie = NULL;
+ uint16_t cookie_len = knot_edns_opt_cookie_data_len(sc_input->cc_len,
+ nonce_len + hash_len);
+ if (cookie_len == 0) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = knot_edns_reserve_unique_option(pkt->opt_rr,
+ KNOT_EDNS_OPTION_COOKIE,
+ cookie_len, &cookie,
+ &pkt->mm);
+ if (ret != KNOT_EOK) {
+ return kr_error(ENOMEM);
+ }
+ assert(cookie != NULL);
+
+ /*
+ * Function knot_edns_opt_cookie_data_len() returns the sum of its
+ * parameters or zero. Anyway, let's check again.
+ */
+ if (cookie_len < (sc_input->cc_len + nonce_len + hash_len)) {
+ return kr_error(EINVAL);
+ }
+
+ /* Copy client cookie data portion. */
+ memcpy(cookie, sc_input->cc, sc_input->cc_len);
+
+ if (nonce_len) {
+ /* Write nonce data portion. */
+ kr_nonce_write_wire(cookie + sc_input->cc_len, nonce_len,
+ nonce);
+ /* Adjust input for written nonce value. */
+ sc_input->nonce = cookie + sc_input->cc_len;
+ sc_input->nonce_len = nonce_len;
+ }
+
+ hash_len = alg->hash_func(sc_input,
+ cookie + sc_input->cc_len + nonce_len,
+ hash_len);
+ /* Zero nonce values. */
+ sc_input->nonce = NULL;
+ sc_input->nonce_len = 0;
+
+ return (hash_len != 0) ? kr_ok() : kr_error(EINVAL);
+}
+
+int kr_pkt_set_ext_rcode(knot_pkt_t *pkt, uint16_t whole_rcode)
+{
+ /*
+ * RFC6891 6.1.3 -- extended RCODE forms the upper 8 bits of whole
+ * 12-bit RCODE (together with the 4 bits of 'normal' RCODE).
+ *
+ * | 11 10 09 08 07 06 05 04 | 03 02 01 00 |
+ * | 12-bit whole RCODE |
+ * | 8-bit extended RCODE | 4-bit RCODE |
+ */
+
+ if (!pkt || !knot_pkt_has_edns(pkt)) {
+ return kr_error(EINVAL);
+ }
+
+ uint8_t rcode = whole_rcode & 0x0f;
+ uint8_t ext_rcode = whole_rcode >> 4;
+ knot_wire_set_rcode(pkt->wire, rcode);
+ knot_edns_set_ext_rcode(pkt->opt_rr, ext_rcode);
+
+ return kr_ok();
+}
+
+uint8_t *kr_no_question_cookie_query(const knot_pkt_t *pkt)
+{
+ if (!pkt || knot_wire_get_qdcount(pkt->wire) > 0) {
+ return false;
+ }
+
+ if (knot_wire_get_qr(pkt->wire) != 0 || !pkt->opt_rr) {
+ return false;
+ }
+
+ return knot_edns_get_option(pkt->opt_rr, KNOT_EDNS_OPTION_COOKIE);
+}
+
+int kr_parse_cookie_opt(uint8_t *cookie_opt, struct knot_dns_cookies *cookies)
+{
+ if (!cookie_opt || !cookies) {
+ return kr_error(EINVAL);
+ }
+
+ const uint8_t *cookie_data = knot_edns_opt_get_data(cookie_opt);
+ uint16_t cookie_len = knot_edns_opt_get_length(cookie_opt);
+ if (!cookie_data || cookie_len == 0) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = knot_edns_opt_cookie_parse(cookie_data, cookie_len,
+ &cookies->cc, &cookies->cc_len,
+ &cookies->sc, &cookies->sc_len);
+
+ return (ret == KNOT_EOK) ? kr_ok() : kr_error(EINVAL);
+}
diff --git a/lib/cookies/helper.h b/lib/cookies/helper.h
new file mode 100644
index 0000000..e5659ce
--- /dev/null
+++ b/lib/cookies/helper.h
@@ -0,0 +1,86 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/packet/pkt.h>
+
+#include "lib/cookies/alg_containers.h"
+#include "lib/cookies/control.h"
+#include "lib/cookies/lru_cache.h"
+#include "lib/cookies/nonce.h"
+#include "lib/defines.h"
+#include "lib/resolve.h"
+
+/**
+ * @brief Updates DNS cookie in the request EDNS options.
+ * @note This function must be called before the request packet is finalised.
+ * @param clnt_comp client cookie control structure
+ * @param cookie_cache cookie cache
+ * @param clnt_sa client socket address
+ * @param srvr_sa server socket address
+ * @param req name resolution request
+ * @return kr_ok() or error code
+ */
+KR_EXPORT
+int kr_request_put_cookie(const struct kr_cookie_comp *clnt_comp,
+ kr_cookie_lru_t *cookie_cache,
+ const struct sockaddr *clnt_sa,
+ const struct sockaddr *srvr_sa,
+ struct kr_request *req);
+
+/**
+ * @brief Inserts a cookie option into the OPT RR. It does not write any
+ * wire data.
+ * @note The content of @a sc_input is modified. Any pre-set nonce value is
+ * ignored. After retuning its nonce value will be null.
+ * @param sc_input data needed to compute server cookie, nonce is ignored
+ * @param nonce nonce value that is actually used
+ * @param alg hash algorithm
+ * @param pkt DNS response packet
+ */
+KR_EXPORT
+int kr_answer_write_cookie(struct knot_sc_input *sc_input,
+ const struct kr_nonce_input *nonce,
+ const struct knot_sc_alg *alg, knot_pkt_t *pkt);
+
+/**
+ * @brief Set RCODE and extended RCODE.
+ * @param pkt DNS packet
+ * @param whole_rcode RCODE value
+ * @return kr_ok() or error code
+ */
+KR_EXPORT
+int kr_pkt_set_ext_rcode(knot_pkt_t *pkt, uint16_t whole_rcode);
+
+/**
+ * @brief Check whether packet is a server cookie request according to
+ * RFC7873 5.4.
+ * @param pkt Packet to be examined.
+ * @return Pointer to entire cookie option if is a server cookie query, NULL on
+ * errors or if packet doesn't contain cookies or if QDCOUNT > 0.
+ */
+KR_EXPORT
+uint8_t *kr_no_question_cookie_query(const knot_pkt_t *pkt);
+
+/**
+ * @brief Parse cookies from cookie option.
+ * @param cookie_opt Cookie option.
+ * @param cookies Cookie structure to be set.
+ * @return kr_ok() on success, error if cookies are malformed.
+ */
+KR_EXPORT
+int kr_parse_cookie_opt(uint8_t *cookie_opt, struct knot_dns_cookies *cookies);
diff --git a/lib/cookies/lru_cache.c b/lib/cookies/lru_cache.c
new file mode 100644
index 0000000..8ea97ab
--- /dev/null
+++ b/lib/cookies/lru_cache.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <libknot/rrtype/opt.h>
+#include <string.h>
+
+#include "lib/cookies/lru_cache.h"
+#include "lib/utils.h"
+
+const uint8_t *kr_cookie_lru_get(kr_cookie_lru_t *cache,
+ const struct sockaddr *sa)
+{
+ if (!cache || !sa) {
+ return NULL;
+ }
+
+ int addr_len = kr_inaddr_len(sa);
+ const char *addr = kr_inaddr(sa);
+ if (!addr || addr_len <= 0) {
+ return NULL;
+ }
+
+ struct cookie_opt_data *cached = lru_get_try(cache, addr, addr_len);
+ return cached ? cached->opt_data : NULL;
+}
+
+int kr_cookie_lru_set(kr_cookie_lru_t *cache, const struct sockaddr *sa,
+ uint8_t *opt)
+{
+ if (!cache || !sa) {
+ return kr_error(EINVAL);
+ }
+
+ if (!opt) {
+ return kr_ok();
+ }
+
+ int addr_len = kr_inaddr_len(sa);
+ const char *addr = kr_inaddr(sa);
+ if (!addr || addr_len <= 0) {
+ return kr_error(EINVAL);
+ }
+
+ uint16_t opt_size = KNOT_EDNS_OPTION_HDRLEN +
+ knot_edns_opt_get_length(opt);
+
+ if (opt_size > KR_COOKIE_OPT_MAX_LEN) {
+ return kr_error(EINVAL);
+ }
+
+ struct cookie_opt_data *cached = lru_get_new(cache, addr, addr_len, NULL);
+ if (cached) {
+ memcpy(cached->opt_data, opt, opt_size);
+ }
+
+ return kr_ok();
+}
diff --git a/lib/cookies/lru_cache.h b/lib/cookies/lru_cache.h
new file mode 100644
index 0000000..8ce0a01
--- /dev/null
+++ b/lib/cookies/lru_cache.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <netinet/in.h>
+#include <stdint.h>
+
+#if defined(ENABLE_COOKIES)
+#include <libknot/rrtype/opt.h>
+#include <libknot/rrtype/opt-cookie.h>
+#else
+#define KNOT_OPT_COOKIE_CLNT 8
+#define KNOT_OPT_COOKIE_SRVR_MAX 32
+#endif /* defined(ENABLE_COOKIES) */
+
+#include "lib/defines.h"
+#include "lib/generic/lru.h"
+
+/** Maximal size of a cookie option. */
+#define KR_COOKIE_OPT_MAX_LEN (KNOT_EDNS_OPTION_HDRLEN + KNOT_OPT_COOKIE_CLNT + KNOT_OPT_COOKIE_SRVR_MAX)
+
+/**
+ * Cookie option entry.
+ */
+struct cookie_opt_data {
+ uint8_t opt_data[KR_COOKIE_OPT_MAX_LEN];
+};
+
+/**
+ * DNS cookies tracking.
+ */
+typedef lru_t(struct cookie_opt_data) kr_cookie_lru_t;
+
+/**
+ * @brief Obtain LRU cache entry.
+ *
+ * @param cache cookie LRU cache
+ * @param sa socket address serving as key
+ * @return pointer to cached option or NULL if not found or error occurred
+ */
+KR_EXPORT
+const uint8_t *kr_cookie_lru_get(kr_cookie_lru_t *cache,
+ const struct sockaddr *sa);
+
+/**
+ * @brief Stores cookie option into LRU cache.
+ *
+ * @param cache cookie LRU cache
+ * @param sa socket address serving as key
+ * @param opt cookie option to be stored
+ * @return kr_ok() or error code
+ */
+KR_EXPORT
+int kr_cookie_lru_set(kr_cookie_lru_t *cache, const struct sockaddr *sa,
+ uint8_t *opt);
diff --git a/lib/cookies/nonce.c b/lib/cookies/nonce.c
new file mode 100644
index 0000000..4ad72c8
--- /dev/null
+++ b/lib/cookies/nonce.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "contrib/wire.h"
+#include "lib/cookies/nonce.h"
+
+uint16_t kr_nonce_write_wire(uint8_t *buf, uint16_t buf_len,
+ const struct kr_nonce_input *input)
+{
+ if (!buf || buf_len < KR_NONCE_LEN || !input) {
+ return 0;
+ }
+
+ wire_write_u32(buf, input->rand);
+ wire_write_u32(buf + sizeof(uint32_t), input->time);
+ buf_len = 2 * sizeof(uint32_t);
+
+ return buf_len;
+}
diff --git a/lib/cookies/nonce.h b/lib/cookies/nonce.h
new file mode 100644
index 0000000..99c54d3
--- /dev/null
+++ b/lib/cookies/nonce.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/defines.h"
+
+/* RFC7873 Appendix B.2 mentions an algorithm using two values before the
+ * actual server cookie hash. */
+
+/** Nonce value length. */
+#define KR_NONCE_LEN 8
+
+/** Input data to generate nonce from. */
+struct kr_nonce_input {
+ uint32_t rand; /**< some random value */
+ uint32_t time; /**< time stamp */
+};
+
+/**
+ * @brief Writes server cookie nonce value into given buffer.
+ *
+ * @param buf buffer to write nonce data in wire format into
+ * @param buf_len buffer size
+ * @param input data to generate wire data from
+ * @return non-zero size of written data on success, 0 on failure
+ */
+KR_EXPORT
+uint16_t kr_nonce_write_wire(uint8_t *buf, uint16_t buf_len,
+ const struct kr_nonce_input *input);
diff --git a/lib/defines.h b/lib/defines.h
new file mode 100644
index 0000000..84da059
--- /dev/null
+++ b/lib/defines.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <libknot/errcode.h>
+#include <libknot/dname.h>
+#include <libknot/rrset.h>
+
+/* Function attributes */
+#if __GNUC__ >= 4
+#define KR_EXPORT __attribute__ ((visibility ("default")))
+#define KR_CONST __attribute__((__const__))
+#define KR_PURE __attribute__((__pure__))
+#define KR_NORETURN __attribute__((__noreturn__))
+#define KR_COLD __attribute__((__cold__))
+#define KR_PRINTF(n) __attribute__((format (printf, n, (n+1))))
+#else
+#define KR_EXPORT
+#define KR_CONST
+#define KR_PURE
+#define KR_NORETURN
+#define KR_COLD
+#define KR_PRINTF(n)
+#endif
+
+#ifndef uint /* Redefining typedef is a C11 feature. */
+typedef unsigned int uint;
+#define uint uint
+#endif
+
+/*
+ * Error codes.
+ */
+#define kr_ok() 0
+/* Mark as cold to mark all branches as unlikely. */
+static inline int KR_COLD kr_error(int x) {
+ return x <= 0 ? x : -x;
+}
+#define kr_strerror(x) strerror(abs(x))
+
+/*
+ * Connection limits.
+ * @cond internal
+ */
+#define KR_CONN_RTT_MAX 2000 /* Timeout for network activity */
+#define KR_CONN_RETRY 200 /* Retry interval for network activity */
+#define KR_ITER_LIMIT 100 /* Built-in iterator limit */
+#define KR_RESOLVE_TIME_LIMIT 10000 /* Upper limit for resolution time of single query, ms */
+#define KR_CNAME_CHAIN_LIMIT 40 /* Built-in maximum CNAME chain length */
+#define KR_TIMEOUT_LIMIT 4 /* Maximum number of retries after timeout. */
+#define KR_QUERY_NSRETRY_LIMIT 4 /* Maximum number of retries per query. */
+
+/*
+ * Defines.
+ */
+#define KR_DNS_PORT 53
+#define KR_DNS_TLS_PORT 853
+#define KR_EDNS_VERSION 0
+#define KR_EDNS_PAYLOAD 4096 /* Default UDP payload (max unfragmented UDP is 1452B) */
+#define KR_CACHE_DEFAULT_TTL_MIN (5) /* avoid bursts of queries */
+#define KR_CACHE_DEFAULT_TTL_MAX (6 * 24 * 3600) /* 6 days, like the root NS TTL */
+
+#define KR_DNAME_STR_MAXLEN (KNOT_DNAME_TXT_MAXLEN + 1)
+#define KR_RRTYPE_STR_MAXLEN (16 + 1)
+
+/*
+ * Address sanitizer hints.
+ */
+#if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
+# if __has_feature(address_sanitizer)
+# define __SANITIZE_ADDRESS__ 1
+# endif
+#endif
+#if defined(__SANITIZE_ADDRESS__)
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#define kr_asan_poison(addr, size) __asan_poison_memory_region((addr), (size))
+#define kr_asan_unpoison(addr, size) __asan_unpoison_memory_region((addr), (size))
+#define kr_asan_custom_poison(fn, addr) fn ##_poison((addr))
+#define kr_asan_custom_unpoison(fn, addr) fn ##_unpoison((addr))
+#else
+#define kr_asan_poison(addr, size)
+#define kr_asan_unpoison(addr, size)
+#define kr_asan_custom_poison(fn, addr)
+#define kr_asan_custom_unpoison(fn, addr)
+#endif
+/* @endcond */
diff --git a/lib/dnssec.c b/lib/dnssec.c
new file mode 100644
index 0000000..4f8ad8a
--- /dev/null
+++ b/lib/dnssec.c
@@ -0,0 +1,473 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <libdnssec/binary.h>
+#include <libdnssec/crypto.h>
+#include <libdnssec/error.h>
+#include <libdnssec/key.h>
+#include <libdnssec/sign.h>
+#include <libknot/descriptor.h>
+#include <libknot/packet/wire.h>
+#include <libknot/rdataset.h>
+#include <libknot/rrset.h>
+#include <libknot/rrtype/dnskey.h>
+#include <libknot/rrtype/nsec.h>
+#include <libknot/rrtype/rrsig.h>
+#include <contrib/wire.h>
+
+#include "lib/defines.h"
+#include "lib/dnssec/nsec.h"
+#include "lib/dnssec/nsec3.h"
+#include "lib/dnssec/signature.h"
+#include "lib/dnssec.h"
+#include "lib/resolve.h"
+
+/* forward */
+static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
+ const knot_rrset_t *covered, size_t key_pos, const struct dseckey *key);
+
+void kr_crypto_init(void)
+{
+ dnssec_crypto_init();
+}
+
+void kr_crypto_cleanup(void)
+{
+ dnssec_crypto_cleanup();
+}
+
+void kr_crypto_reinit(void)
+{
+ dnssec_crypto_reinit();
+}
+
+#define FLG_WILDCARD_EXPANSION 0x01 /**< Possibly generated by using wildcard expansion. */
+
+/**
+ * Check the RRSIG RR validity according to RFC4035 5.3.1 .
+ * @param flags The flags are going to be set according to validation result.
+ * @param cov_labels Covered RRSet owner label count.
+ * @param rrsigs rdata containing the signatures.
+ * @param key_owner Associated DNSKEY's owner.
+ * @param key_rdata Associated DNSKEY's rdata.
+ * @param keytag Used key tag.
+ * @param zone_name The name of the zone cut.
+ * @param timestamp Validation time.
+ */
+static int validate_rrsig_rr(int *flags, int cov_labels,
+ const knot_rdata_t *rrsigs,
+ const knot_dname_t *key_owner, const knot_rdata_t *key_rdata,
+ uint16_t keytag,
+ const knot_dname_t *zone_name, uint32_t timestamp,
+ kr_rrset_validation_ctx_t *vctx)
+{
+ if (!flags || !rrsigs || !key_owner || !key_rdata || !zone_name) {
+ return kr_error(EINVAL);
+ }
+ /* bullet 5 */
+ if (knot_rrsig_sig_expiration(rrsigs) < timestamp) {
+ vctx->rrs_counters.expired++;
+ return kr_error(EINVAL);
+ }
+ /* bullet 6 */
+ if (knot_rrsig_sig_inception(rrsigs) > timestamp) {
+ vctx->rrs_counters.notyet++;
+ return kr_error(EINVAL);
+ }
+ /* bullet 2 */
+ const knot_dname_t *signer_name = knot_rrsig_signer_name(rrsigs);
+ if (!signer_name || !knot_dname_is_equal(signer_name, zone_name)) {
+ vctx->rrs_counters.signer_invalid++;
+ return kr_error(EAGAIN);
+ }
+ /* bullet 4 */
+ {
+ int rrsig_labels = knot_rrsig_labels(rrsigs);
+ if (rrsig_labels > cov_labels) {
+ vctx->rrs_counters.labels_invalid++;
+ return kr_error(EINVAL);
+ }
+ if (rrsig_labels < cov_labels) {
+ *flags |= FLG_WILDCARD_EXPANSION;
+ }
+ }
+
+ /* bullet 7 */
+ if ((!knot_dname_is_equal(key_owner, signer_name)) ||
+ (knot_dnskey_alg(key_rdata) != knot_rrsig_alg(rrsigs)) ||
+ (keytag != knot_rrsig_key_tag(rrsigs))) {
+ vctx->rrs_counters.key_invalid++;
+ return kr_error(EINVAL);
+ }
+ /* bullet 8 */
+ /* Checked somewhere else. */
+ /* bullet 9 and 10 */
+ /* One of the requirements should be always fulfilled. */
+
+ return kr_ok();
+}
+
+/**
+ * Returns the number of labels that have been added by wildcard expansion.
+ * @param expanded Expanded wildcard.
+ * @param rrsigs RRSet containing the signatures.
+ * @param sig_pos Specifies the signature within the RRSIG RRSet.
+ * @return Number of added labels, -1 on error.
+ */
+static inline int wildcard_radix_len_diff(const knot_dname_t *expanded,
+ const knot_rdata_t *rrsig)
+{
+ if (!expanded || !rrsig) {
+ return -1;
+ }
+
+ return knot_dname_labels(expanded, NULL) - knot_rrsig_labels(rrsig);
+}
+
+int kr_rrset_validate(kr_rrset_validation_ctx_t *vctx, const knot_rrset_t *covered)
+{
+ if (!vctx) {
+ return kr_error(EINVAL);
+ }
+ if (!vctx->pkt || !covered || !vctx->keys || !vctx->zone_name) {
+ return kr_error(EINVAL);
+ }
+
+ memset(&vctx->rrs_counters, 0, sizeof(vctx->rrs_counters));
+ for (unsigned i = 0; i < vctx->keys->rrs.count; ++i) {
+ int ret = kr_rrset_validate_with_key(vctx, covered, i, NULL);
+ if (ret == 0) {
+ return ret;
+ }
+ }
+
+ return kr_error(ENOENT);
+}
+
+/**
+ * Validate RRSet using a specific key.
+ * @param vctx Pointer to validation context.
+ * @param covered RRSet covered by a signature. It must be in canonical format.
+ * @param key_pos Position of the key to be validated with.
+ * @param key Key to be used to validate.
+ * If NULL, then key from DNSKEY RRSet is used.
+ * @return 0 or error code, same as vctx->result.
+ */
+static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
+ const knot_rrset_t *covered,
+ size_t key_pos, const struct dseckey *key)
+{
+ const knot_pkt_t *pkt = vctx->pkt;
+ const knot_rrset_t *keys = vctx->keys;
+ const knot_dname_t *zone_name = vctx->zone_name;
+ uint32_t timestamp = vctx->timestamp;
+ bool has_nsec3 = vctx->has_nsec3;
+ struct dseckey *created_key = NULL;
+
+ /* It's just caller's approximation that the RR is in that particular zone.
+ * We MUST guard against attempts of zones signing out-of-bailiwick records. */
+ if (knot_dname_in_bailiwick(covered->owner, zone_name) < 0) {
+ vctx->result = kr_error(ENOENT);
+ return vctx->result;
+ }
+
+ const knot_rdata_t *key_rdata = knot_rdataset_at(&keys->rrs, key_pos);
+ if (key == NULL) {
+ int ret = kr_dnssec_key_from_rdata(&created_key, keys->owner,
+ key_rdata->data, key_rdata->len);
+ if (ret != 0) {
+ vctx->result = ret;
+ return vctx->result;
+ }
+ key = created_key;
+ }
+ uint16_t keytag = dnssec_key_get_keytag((dnssec_key_t *)key);
+ int covered_labels = knot_dname_labels(covered->owner, NULL);
+ if (knot_dname_is_wildcard(covered->owner)) {
+ /* The asterisk does not count, RFC4034 3.1.3, paragraph 3. */
+ --covered_labels;
+ }
+
+ for (uint16_t i = 0; i < vctx->rrs->len; ++i) {
+ /* Consider every RRSIG that matches owner and covers the class/type. */
+ const knot_rrset_t *rrsig = vctx->rrs->at[i]->rr;
+ if (rrsig->type != KNOT_RRTYPE_RRSIG) {
+ continue;
+ }
+ if ((covered->rclass != rrsig->rclass) || !knot_dname_is_equal(covered->owner, rrsig->owner)) {
+ continue;
+ }
+ knot_rdata_t *rdata_j = rrsig->rrs.rdata;
+ for (uint16_t j = 0; j < rrsig->rrs.count; ++j, rdata_j = knot_rdataset_next(rdata_j)) {
+ int val_flgs = 0;
+ int trim_labels = 0;
+ if (knot_rrsig_type_covered(rdata_j) != covered->type) {
+ continue;
+ }
+ vctx->rrs_counters.matching_name_type++;
+ int retv = validate_rrsig_rr(&val_flgs, covered_labels, rdata_j,
+ keys->owner, key_rdata, keytag,
+ zone_name, timestamp, vctx);
+ if (retv == kr_error(EAGAIN)) {
+ kr_dnssec_key_free(&created_key);
+ vctx->result = retv;
+ return retv;
+ } else if (retv != 0) {
+ continue;
+ }
+ if (val_flgs & FLG_WILDCARD_EXPANSION) {
+ trim_labels = wildcard_radix_len_diff(covered->owner, rdata_j);
+ if (trim_labels < 0) {
+ break;
+ }
+ }
+ if (kr_check_signature(rdata_j, (dnssec_key_t *) key, covered, trim_labels) != 0) {
+ vctx->rrs_counters.crypto_invalid++;
+ continue;
+ }
+ if (val_flgs & FLG_WILDCARD_EXPANSION) {
+ int ret = 0;
+ if (!has_nsec3) {
+ ret = kr_nsec_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner);
+ } else {
+ ret = kr_nsec3_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner, trim_labels - 1);
+ if (ret == kr_error(KNOT_ERANGE)) {
+ ret = 0;
+ vctx->flags |= KR_DNSSEC_VFLG_OPTOUT;
+ }
+ }
+ if (ret != 0) {
+ vctx->rrs_counters.nsec_invalid++;
+ continue;
+ }
+ vctx->flags |= KR_DNSSEC_VFLG_WEXPAND;
+ }
+ /* Validated with current key, OK */
+ kr_dnssec_key_free(&created_key);
+ vctx->result = kr_ok();
+ return vctx->result;
+ }
+ }
+ /* No applicable key found, cannot be validated. */
+ kr_dnssec_key_free(&created_key);
+ vctx->result = kr_error(ENOENT);
+ return vctx->result;
+}
+
+static bool kr_ds_algo_support(const knot_rrset_t *ta)
+{
+ knot_rdata_t *rdata_i = ta->rrs.rdata;
+ for (uint16_t i = 0; i < ta->rrs.count;
+ ++i, rdata_i = knot_rdataset_next(rdata_i)) {
+ if (dnssec_algorithm_digest_support(knot_ds_digest_type(rdata_i))
+ && dnssec_algorithm_key_support(knot_ds_alg(rdata_i))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rrset_t *ta)
+{
+ const knot_pkt_t *pkt = vctx->pkt;
+ const knot_rrset_t *keys = vctx->keys;
+
+ const bool ok = pkt && keys && ta && ta->rrs.count && ta->rrs.rdata
+ && ta->type == KNOT_RRTYPE_DS;
+ if (!ok) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+
+ /* Check if at least one DS has a usable algorithm pair. */
+ if (!kr_ds_algo_support(ta)) {
+ /* See RFC6840 5.2. */
+ return vctx->result = kr_error(DNSSEC_INVALID_DS_ALGORITHM);
+ }
+
+ /* RFC4035 5.2, bullet 1
+ * The supplied DS record has been authenticated.
+ * It has been validated or is part of a configured trust anchor.
+ */
+ memset(&vctx->rrs_counters, 0, sizeof(vctx->rrs_counters));
+ for (uint16_t i = 0; i < keys->rrs.count; ++i) {
+ /* RFC4035 5.3.1, bullet 8 */ /* ZSK */
+ /* LATER(optim.): more efficient way to iterate than _at() */
+ const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, i);
+ if (!kr_dnssec_key_zsk(krr->data) || kr_dnssec_key_revoked(krr->data)) {
+ continue;
+ }
+
+ struct dseckey *key = NULL;
+ if (kr_dnssec_key_from_rdata(&key, keys->owner, krr->data, krr->len) != 0) {
+ continue;
+ }
+ if (kr_authenticate_referral(ta, (dnssec_key_t *) key) != 0) {
+ kr_dnssec_key_free(&key);
+ continue;
+ }
+ if (kr_rrset_validate_with_key(vctx, keys, i, key) != 0) {
+ kr_dnssec_key_free(&key);
+ continue;
+ }
+ kr_dnssec_key_free(&key);
+ assert (vctx->result == 0);
+ return vctx->result;
+ }
+
+ /* No useable key found */
+ vctx->result = kr_error(ENOENT);
+ return vctx->result;
+}
+
+bool kr_dnssec_key_zsk(const uint8_t *dnskey_rdata)
+{
+ return wire_read_u16(dnskey_rdata) & 0x0100;
+}
+
+bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata)
+{
+ return wire_read_u16(dnskey_rdata) & 0x0001;
+}
+
+/** Return true if the DNSKEY is revoked. */
+bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata)
+{
+ return wire_read_u16(dnskey_rdata) & 0x0080;
+}
+
+int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen)
+{
+ if (!rdata || rdlen == 0 || (rrtype != KNOT_RRTYPE_DS && rrtype != KNOT_RRTYPE_DNSKEY)) {
+ return kr_error(EINVAL);
+ }
+ if (rrtype == KNOT_RRTYPE_DS) {
+ return wire_read_u16(rdata);
+ } else if (rrtype == KNOT_RRTYPE_DNSKEY) {
+ struct dseckey *key = NULL;
+ int ret = kr_dnssec_key_from_rdata(&key, NULL, rdata, rdlen);
+ if (ret != 0) {
+ return ret;
+ }
+ uint16_t keytag = dnssec_key_get_keytag((dnssec_key_t *)key);
+ kr_dnssec_key_free(&key);
+ return keytag;
+ } else {
+ return kr_error(EINVAL);
+ }
+}
+
+int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
+ const uint8_t *key_b_rdata, size_t key_b_rdlen)
+{
+ dnssec_key_t *key_a = NULL, *key_b = NULL;
+ int ret = kr_dnssec_key_from_rdata((struct dseckey **)&key_a, NULL, key_a_rdata, key_a_rdlen);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = kr_dnssec_key_from_rdata((struct dseckey **)&key_b, NULL, key_b_rdata, key_b_rdlen);
+ if (ret != 0) {
+ dnssec_key_free(key_a);
+ return ret;
+ }
+ /* If the algorithm and the public key match, we can be sure
+ * that they are the same key. */
+ ret = kr_error(ENOENT);
+ dnssec_binary_t pk_a, pk_b;
+ if (dnssec_key_get_algorithm(key_a) == dnssec_key_get_algorithm(key_b) &&
+ dnssec_key_get_pubkey(key_a, &pk_a) == DNSSEC_EOK &&
+ dnssec_key_get_pubkey(key_b, &pk_b) == DNSSEC_EOK) {
+ if (pk_a.size == pk_b.size && memcmp(pk_a.data, pk_b.data, pk_a.size) == 0) {
+ ret = 0;
+ }
+ }
+ dnssec_key_free(key_a);
+ dnssec_key_free(key_b);
+ return ret;
+}
+
+int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen)
+{
+ if (!key || !rdata || rdlen == 0) {
+ return kr_error(EINVAL);
+ }
+
+ dnssec_key_t *new_key = NULL;
+ const dnssec_binary_t binary_key = {
+ .size = rdlen,
+ .data = (uint8_t *)rdata
+ };
+
+ int ret = dnssec_key_new(&new_key);
+ if (ret != DNSSEC_EOK) {
+ return kr_error(ENOMEM);
+ }
+ ret = dnssec_key_set_rdata(new_key, &binary_key);
+ if (ret != DNSSEC_EOK) {
+ dnssec_key_free(new_key);
+ return kr_error(ret);
+ }
+ if (kown) {
+ ret = dnssec_key_set_dname(new_key, kown);
+ if (ret != DNSSEC_EOK) {
+ dnssec_key_free(new_key);
+ return kr_error(ENOMEM);
+ }
+ }
+
+ *key = (struct dseckey *) new_key;
+ return kr_ok();
+}
+
+void kr_dnssec_key_free(struct dseckey **key)
+{
+ assert(key);
+
+ dnssec_key_free((dnssec_key_t *) *key);
+ *key = NULL;
+}
+
+int kr_dnssec_matches_name_and_type(const ranked_rr_array_t *rrs, uint32_t qry_uid,
+ const knot_dname_t *name, uint16_t type)
+{
+ int ret = kr_error(ENOENT);
+ for (size_t i = 0; i < rrs->len; ++i) {
+ const ranked_rr_array_entry_t *entry = rrs->at[i];
+ const knot_rrset_t *nsec = entry->rr;
+ if (entry->qry_uid != qry_uid || entry->yielded) {
+ continue;
+ }
+ if (nsec->type != KNOT_RRTYPE_NSEC &&
+ nsec->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ if (!kr_rank_test(entry->rank, KR_RANK_SECURE)) {
+ continue;
+ }
+ if (nsec->type == KNOT_RRTYPE_NSEC) {
+ ret = kr_nsec_matches_name_and_type(nsec, name, type);
+ } else {
+ ret = kr_nsec3_matches_name_and_type(nsec, name, type);
+ }
+ if (ret == kr_ok()) {
+ return kr_ok();
+ } else if (ret != kr_error(ENOENT)) {
+ return ret;
+ }
+ }
+ return ret;
+}
diff --git a/lib/dnssec.h b/lib/dnssec.h
new file mode 100644
index 0000000..b54908c
--- /dev/null
+++ b/lib/dnssec.h
@@ -0,0 +1,152 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include <libknot/packet/pkt.h>
+
+/**
+ * Initialise cryptographic back-end.
+ */
+KR_EXPORT
+void kr_crypto_init(void);
+
+/**
+ * De-initialise cryptographic back-end.
+ */
+KR_EXPORT
+void kr_crypto_cleanup(void);
+
+/**
+ * Re-initialise cryptographic back-end.
+ * @note Must be called after fork() in the child.
+ */
+KR_EXPORT
+void kr_crypto_reinit(void);
+
+/** Opaque DNSSEC key pointer. */
+struct dseckey;
+
+#define KR_DNSSEC_VFLG_WEXPAND 0x01
+#define KR_DNSSEC_VFLG_OPTOUT 0x02
+
+/** DNSSEC validation context. */
+struct kr_rrset_validation_ctx {
+ const knot_pkt_t *pkt; /*!< Packet to be validated. */
+ ranked_rr_array_t *rrs; /*!< List of preselected RRs to be validated. */
+ knot_section_t section_id; /*!< Section to work with. */
+ const knot_rrset_t *keys; /*!< DNSKEY RRSet. */
+ const knot_dname_t *zone_name; /*!< Name of the zone containing the RRSIG RRSet. */
+ uint32_t timestamp; /*!< Validation time. */
+ bool has_nsec3; /*!< Whether to use NSEC3 validation. */
+ uint32_t qry_uid; /*!< Current query uid. */
+ uint32_t flags; /*!< Output - Flags. */
+ uint32_t err_cnt; /*!< Output - Number of validation failures. */
+ int result; /*!< Output - 0 or error code. */
+ struct {
+ unsigned int matching_name_type; /*!< Name + type matches */
+ unsigned int expired;
+ unsigned int notyet;
+ unsigned int signer_invalid; /*!< Signer is not zone apex */
+ unsigned int labels_invalid; /*!< Number of labels in RRSIG */
+ unsigned int key_invalid; /*!< Algorithm/keytag/key owner */
+ unsigned int crypto_invalid;
+ unsigned int nsec_invalid;
+ } rrs_counters; /*!< Error counters for single RRset validation. */
+};
+
+typedef struct kr_rrset_validation_ctx kr_rrset_validation_ctx_t;
+
+/**
+ * Validate RRSet.
+ * @param vctx Pointer to validation context.
+ * @param covered RRSet covered by a signature. It must be in canonical format.
+ * @return 0 or error code, same as vctx->result.
+ */
+int kr_rrset_validate(kr_rrset_validation_ctx_t *vctx,
+ const knot_rrset_t *covered);
+
+/**
+ * Check whether the DNSKEY rrset matches the supplied trust anchor RRSet.
+ * @param vctx Pointer to validation context.
+ * @param ta Trust anchor RRSet against which to validate the DNSKEY RRSet.
+ * @return 0 or error code, same as vctx->result. In particular,
+ * DNSSEC_INVALID_DS_ALGORITHM if *each* DS records is unusable
+ * due to unimplemented DNSKEY or DS algorithm.
+ */
+int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rrset_t *ta);
+
+/** Return true if the DNSKEY can be used as a ZSK. */
+KR_EXPORT KR_PURE
+bool kr_dnssec_key_zsk(const uint8_t *dnskey_rdata);
+
+/** Return true if the DNSKEY indicates being KSK (=> has SEP). */
+KR_EXPORT KR_PURE
+bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata);
+
+/** Return true if the DNSKEY is revoked. */
+KR_EXPORT KR_PURE
+bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata);
+
+/** Return DNSKEY tag.
+ * @param rrtype RR type (either DS or DNSKEY are supported)
+ * @param rdata Key/digest RDATA.
+ * @param rdlen RDATA length.
+ * @return Key tag (positive number), or an error code
+ */
+KR_EXPORT KR_PURE
+int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen);
+
+/** Return 0 if the two keys are identical.
+ * @note This compares RDATA only, algorithm and public key must match.
+ * @param key_a_rdata First key RDATA
+ * @param key_a_rdlen First key RDATA length
+ * @param key_b_rdata Second key RDATA
+ * @param key_b_rdlen Second key RDATA length
+ * @return 0 if they match or an error code
+ */
+KR_EXPORT KR_PURE
+int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
+ const uint8_t *key_b_rdata, size_t key_b_rdlen);
+
+/**
+ * Construct a DNSSEC key.
+ * @param key Pointer to be set to newly created DNSSEC key.
+ * @param kown DNSKEY owner name.
+ * @param rdata DNSKEY RDATA
+ * @param rdlen DNSKEY RDATA length
+ * @return 0 or error code; in particular: DNSSEC_INVALID_KEY_ALGORITHM
+ */
+int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen);
+
+/**
+ * Frees the DNSSEC key.
+ * @param key Pointer to freed key.
+ */
+void kr_dnssec_key_free(struct dseckey **key);
+
+/**
+ * Checks whether NSEC/NSEC3 RR selected by iterator matches the supplied name and type.
+ * @param rrs Records selected by iterator.
+ * @param qry_uid Query unique identifier where NSEC/NSEC3 belongs to.
+ * @param name Name to be checked.
+ * @param type Type to be checked.
+ * @return 0 or error code.
+ */
+int kr_dnssec_matches_name_and_type(const ranked_rr_array_t *rrs, uint32_t qry_uid,
+ const knot_dname_t *name, uint16_t type);
diff --git a/lib/dnssec/nsec.c b/lib/dnssec/nsec.c
new file mode 100644
index 0000000..4ae13b2
--- /dev/null
+++ b/lib/dnssec/nsec.c
@@ -0,0 +1,540 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <libknot/descriptor.h>
+#include <libknot/dname.h>
+#include <libknot/packet/wire.h>
+#include <libknot/rrset.h>
+#include <libknot/rrtype/nsec.h>
+#include <libknot/rrtype/rrsig.h>
+#include <libdnssec/error.h>
+#include <libdnssec/nsec.h>
+
+#include "lib/defines.h"
+#include "lib/dnssec/nsec.h"
+
+
+int kr_nsec_children_in_zone_check(const uint8_t *bm, uint16_t bm_size)
+{
+ if (!bm) {
+ return kr_error(EINVAL);
+ }
+ const bool parent_side =
+ dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_DNAME)
+ || (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS)
+ && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)
+ );
+ return parent_side ? abs(ENOENT) : kr_ok();
+ /* LATER: after refactoring, probably also check if signer name equals owner,
+ * but even without that it's not possible to attack *correctly* signed zones.
+ */
+}
+
+/**
+ * Check whether the NSEC RR proves that there is no closer match for <SNAME, SCLASS>.
+ * @param nsec NSEC RRSet.
+ * @param sname Searched name.
+ * @return 0 if proves, >0 if not (abs(ENOENT)), or error code (<0).
+ */
+static int nsec_covers(const knot_rrset_t *nsec, const knot_dname_t *sname)
+{
+ assert(nsec && sname);
+ if (knot_dname_cmp(sname, nsec->owner) <= 0) {
+ return abs(ENOENT); /* 'sname' before 'owner', so can't be covered */
+ }
+
+ /* If NSEC 'owner' >= 'next', it means that there is nothing after 'owner' */
+ /* We have to lower-case it with libknot >= 2.7; see also RFC 6840 5.1. */
+ knot_dname_t next[KNOT_DNAME_MAXLEN];
+ int ret = knot_dname_to_wire(next, knot_nsec_next(nsec->rrs.rdata), sizeof(next));
+ if (ret < 0) {
+ assert(!ret);
+ return kr_error(ret);
+ }
+ knot_dname_to_lower(next);
+
+ const bool is_last_nsec = knot_dname_cmp(nsec->owner, next) >= 0;
+ const bool in_range = is_last_nsec || knot_dname_cmp(sname, next) < 0;
+ if (!in_range) {
+ return abs(ENOENT);
+ }
+ /* Before returning kr_ok(), we have to check a special case:
+ * sname might be under delegation from owner and thus
+ * not in the zone of this NSEC at all.
+ */
+ if (knot_dname_in_bailiwick(sname, nsec->owner) <= 0) {
+ return kr_ok();
+ }
+ const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
+
+ return kr_nsec_children_in_zone_check(bm, bm_size);
+}
+
+#define FLG_NOEXIST_RRTYPE (1 << 0) /**< <SNAME, SCLASS> exists, <SNAME, SCLASS, STYPE> does not exist. */
+#define FLG_NOEXIST_RRSET (1 << 1) /**< <SNAME, SCLASS> does not exist. */
+#define FLG_NOEXIST_WILDCARD (1 << 2) /**< No wildcard covering <SNAME, SCLASS> exists. */
+#define FLG_NOEXIST_CLOSER (1 << 3) /**< Wildcard covering <SNAME, SCLASS> exists, but doesn't match STYPE. */
+
+
+/**
+ * According to set flags determine whether NSEC proving
+ * RRset or RRType non-existense has been found.
+ * @param f Flags to inspect.
+ * @return True if required NSEC exists.
+ */
+#define kr_nsec_rrset_noexist(f) \
+ ((f) & (FLG_NOEXIST_RRTYPE | FLG_NOEXIST_RRSET))
+/**
+ * According to set flags determine whether wildcard non-existense
+ * has been proven.
+ * @param f Flags to inspect.
+ * @return True if wildcard not exists.
+ */
+#define kr_nsec_wcard_noexist(f) ((f) & FLG_NOEXIST_WILDCARD)
+
+/**
+ * According to set flags determine whether authenticated denial of existence has been proven.
+ * @param f Flags to inspect.
+ * @return True if denial of existence proven.
+ */
+#define kr_nsec_existence_denied(f) \
+ ((kr_nsec_rrset_noexist(f)) && (kr_nsec_wcard_noexist(f)))
+
+/**
+ * Name error response check (RFC4035 3.1.3.2; RFC4035 5.4, bullet 2).
+ * @note Returned flags must be checked in order to prove denial.
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec NSEC RR.
+ * @param name Name to be checked.
+ * @param pool
+ * @return 0 or error code.
+ */
+static int name_error_response_check_rr(int *flags, const knot_rrset_t *nsec,
+ const knot_dname_t *name)
+{
+ assert(flags && nsec && name);
+
+ if (nsec_covers(nsec, name) == 0) {
+ *flags |= FLG_NOEXIST_RRSET;
+ }
+
+ /* Try to find parent wildcard that is proved by this NSEC. */
+ uint8_t namebuf[KNOT_DNAME_MAXLEN];
+ int ret = knot_dname_to_wire(namebuf, name, sizeof(namebuf));
+ if (ret < 0)
+ return ret;
+ knot_dname_t *ptr = namebuf;
+ while (ptr[0]) {
+ /* Remove leftmost label and replace it with '\1*'. */
+ ptr = (uint8_t *) knot_wire_next_label(ptr, NULL);
+ if (!ptr) {
+ return kr_error(EINVAL);
+ }
+ *(--ptr) = '*';
+ *(--ptr) = 1;
+ /* True if this wildcard provably doesn't exist. */
+ if (nsec_covers(nsec, ptr) == 0) {
+ *flags |= FLG_NOEXIST_WILDCARD;
+ break;
+ }
+ /* Remove added leftmost asterisk. */
+ ptr += 2;
+ }
+
+ return kr_ok();
+}
+
+int kr_nsec_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ int ret = name_error_response_check_rr(&flags, rrset, sname);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ return kr_nsec_existence_denied(flags) ? kr_ok() : kr_error(ENOENT);
+}
+
+/**
+ * Returns the labels from the covering RRSIG RRs.
+ * @note The number must be the same in all covering RRSIGs.
+ * @param nsec NSEC RR.
+ * @param sec Packet section.
+ * @param Number of labels or (negative) error code.
+ */
+static int coverign_rrsig_labels(const knot_rrset_t *nsec, const knot_pktsection_t *sec)
+{
+ assert(nsec && sec);
+
+ int ret = kr_error(ENOENT);
+
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if ((rrset->type != KNOT_RRTYPE_RRSIG) ||
+ (!knot_dname_is_equal(rrset->owner, nsec->owner))) {
+ continue;
+ }
+
+ knot_rdata_t *rdata_j = rrset->rrs.rdata;
+ for (uint16_t j = 0; j < rrset->rrs.count;
+ ++j, rdata_j = knot_rdataset_next(rdata_j)) {
+ if (knot_rrsig_type_covered(rdata_j) != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+
+ if (ret < 0) {
+ ret = knot_rrsig_labels(rdata_j);
+ } else {
+ if (ret != knot_rrsig_labels(rdata_j)) {
+ return kr_error(EINVAL);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t type, const knot_dname_t *owner)
+{
+ const int NO_PROOF = abs(ENOENT);
+ if (!bm || !owner) {
+ return kr_error(EINVAL);
+ }
+ if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) {
+ return NO_PROOF;
+ }
+
+ if (type != KNOT_RRTYPE_CNAME
+ && dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_CNAME)) {
+ return NO_PROOF;
+ }
+ /* Special behavior around zone cuts. */
+ switch (type) {
+ case KNOT_RRTYPE_DS:
+ /* Security feature: in case of DS also check for SOA
+ * non-existence to be more certain that we don't hold
+ * a child-side NSEC by some mistake (e.g. when forwarding).
+ * See RFC4035 5.2, next-to-last paragraph.
+ * This doesn't apply for root DS as it doesn't exist in DNS hierarchy.
+ */
+ if (owner[0] != '\0' && dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)) {
+ return NO_PROOF;
+ }
+ break;
+ case KNOT_RRTYPE_CNAME:
+ /* Exception from the `default` rule. It's perhaps disputable,
+ * but existence of CNAME at zone apex is not allowed, so we
+ * consider a parent-side record to be enough to prove non-existence. */
+ break;
+ default:
+ /* Parent-side delegation record isn't authoritative for non-DS;
+ * see RFC6840 4.1. */
+ if (dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_NS)
+ && !dnssec_nsec_bitmap_contains(bm, bm_size, KNOT_RRTYPE_SOA)) {
+ return NO_PROOF;
+ }
+ /* LATER(opt): perhaps short-circuit test if we repeat it here. */
+ }
+
+ return kr_ok();
+}
+
+/**
+ * Attempt to prove NODATA given a matching NSEC.
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec NSEC RR.
+ * @param type Type to be checked.
+ * @return 0 on success, abs(ENOENT) for no proof, or error code (<0).
+ * @note It's not a *full* proof, of course (wildcards, etc.)
+ * @TODO returning result via `flags` is just ugly.
+ */
+static int no_data_response_check_rrtype(int *flags, const knot_rrset_t *nsec,
+ uint16_t type)
+{
+ assert(flags && nsec);
+
+ const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
+ int ret = kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec->owner);
+ if (ret == kr_ok()) {
+ *flags |= FLG_NOEXIST_RRTYPE;
+ }
+ return ret <= 0 ? ret : kr_ok();
+}
+
+/**
+ * Perform check for RR type wildcard existence denial according to RFC4035 5.4, bullet 1.
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec NSEC RR.
+ * @param sec Packet section to work with.
+ * @return 0 or error code.
+ */
+static int no_data_wildcard_existence_check(int *flags, const knot_rrset_t *nsec,
+ const knot_pktsection_t *sec)
+{
+ assert(flags && nsec && sec);
+
+ int rrsig_labels = coverign_rrsig_labels(nsec, sec);
+ if (rrsig_labels < 0) {
+ return rrsig_labels;
+ }
+ int nsec_labels = knot_dname_labels(nsec->owner, NULL);
+ if (nsec_labels < 0) {
+ return nsec_labels;
+ }
+
+ if (rrsig_labels == nsec_labels) {
+ *flags |= FLG_NOEXIST_WILDCARD;
+ }
+
+ return kr_ok();
+}
+
+/**
+ * Perform check for NSEC wildcard existence that covers sname and
+ * have no stype bit set.
+ * @param pkt Packet structure to be processed.
+ * @param sec Packet section to work with.
+ * @param sname Queried domain name.
+ * @param stype Queried type.
+ * @return 0 or error code.
+ */
+static int wildcard_match_check(const knot_pkt_t *pkt, const knot_pktsection_t *sec,
+ const knot_dname_t *sname, uint16_t stype)
+{
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ if (!knot_dname_is_wildcard(rrset->owner)) {
+ continue;
+ }
+ if (!knot_dname_is_equal(rrset->owner, sname)) {
+ int wcard_labels = knot_dname_labels(rrset->owner, NULL);
+ int common_labels = knot_dname_matched_labels(rrset->owner, sname);
+ int rrsig_labels = coverign_rrsig_labels(rrset, sec);
+ if (wcard_labels < 1 ||
+ common_labels != wcard_labels - 1 ||
+ common_labels != rrsig_labels) {
+ continue;
+ }
+ }
+ int ret = no_data_response_check_rrtype(&flags, rrset, stype);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ return (flags & FLG_NOEXIST_RRTYPE) ? kr_ok() : kr_error(ENOENT);
+}
+
+int kr_nsec_no_data_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ if (knot_dname_is_equal(rrset->owner, sname)) {
+ int ret = no_data_response_check_rrtype(&flags, rrset, stype);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ }
+
+ return (flags & FLG_NOEXIST_RRTYPE) ? kr_ok() : kr_error(ENOENT);
+}
+
+int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ if (nsec_covers(rrset, sname) == 0) {
+ return kr_ok();
+ }
+ }
+
+ return kr_error(ENOENT);
+}
+
+int kr_nsec_existence_denial(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ /* NSEC proves that name exists, but has no data (RFC4035 4.9, 1) */
+ if (knot_dname_is_equal(rrset->owner, sname)) {
+ no_data_response_check_rrtype(&flags, rrset, stype);
+ } else {
+ /* NSEC proves that name doesn't exist (RFC4035, 4.9, 2) */
+ name_error_response_check_rr(&flags, rrset, sname);
+ }
+ no_data_wildcard_existence_check(&flags, rrset, sec);
+ }
+ if (kr_nsec_existence_denied(flags)) {
+ /* denial of existence proved accordignly to 4035 5.4 -
+ * NSEC proving either rrset non-existance or
+ * qtype non-existance has been found,
+ * and no wildcard expansion occurred.
+ */
+ return kr_ok();
+ } else if (kr_nsec_rrset_noexist(flags)) {
+ /* NSEC proving either rrset non-existance or
+ * qtype non-existance has been found,
+ * but wildcard expansion occurs.
+ * Try to find matching wildcard and check
+ * corresponding types.
+ */
+ return wildcard_match_check(pkt, sec, sname, stype);
+ }
+ return kr_error(ENOENT);
+}
+
+int kr_nsec_ref_to_unsigned(const knot_pkt_t *pkt)
+{
+ int nsec_found = 0;
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, KNOT_AUTHORITY);
+ if (!sec) {
+ return kr_error(EINVAL);
+ }
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *ns = knot_pkt_rr(sec, i);
+ if (ns->type == KNOT_RRTYPE_DS) {
+ return kr_error(EEXIST);
+ }
+ if (ns->type != KNOT_RRTYPE_NS) {
+ continue;
+ }
+ nsec_found = 0;
+ for (unsigned j = 0; j < sec->count; ++j) {
+ const knot_rrset_t *nsec = knot_pkt_rr(sec, j);
+ if (nsec->type == KNOT_RRTYPE_DS) {
+ return kr_error(EEXIST);
+ }
+ if (nsec->type != KNOT_RRTYPE_NSEC) {
+ continue;
+ }
+ /* nsec found
+ * check if owner name matches the delegation name
+ */
+ if (!knot_dname_is_equal(nsec->owner, ns->owner)) {
+ /* nsec does not match the delegation */
+ continue;
+ }
+ nsec_found = 1;
+ const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
+ if (!bm) {
+ return kr_error(EINVAL);
+ }
+ if (dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_NS) &&
+ !dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_DS) &&
+ !dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_SOA)) {
+ /* rfc4035, 5.2 */
+ return kr_ok();
+ }
+ }
+ if (nsec_found) {
+ /* nsec which owner matches
+ * the delegation name was found,
+ * but nsec type bitmap contains wrong types
+ */
+ return kr_error(EINVAL);
+ } else {
+ /* nsec that matches delegation was not found */
+ return kr_error(DNSSEC_NOT_FOUND);
+ }
+ }
+
+ return kr_error(EINVAL);
+}
+
+int kr_nsec_matches_name_and_type(const knot_rrset_t *nsec,
+ const knot_dname_t *name, uint16_t type)
+{
+ /* It's not secure enough to just check a single bit for (some) other types,
+ * but we don't (currently) only use this API for NS. See RFC 6840 sec. 4.
+ */
+ if (type != KNOT_RRTYPE_NS || !nsec || !name) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ if (!knot_dname_is_equal(nsec->owner, name)) {
+ return kr_error(ENOENT);
+ }
+ const uint8_t *bm = knot_nsec_bitmap(nsec->rrs.rdata);
+ uint16_t bm_size = knot_nsec_bitmap_len(nsec->rrs.rdata);
+ if (!bm) {
+ return kr_error(EINVAL);
+ }
+ if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) {
+ return kr_ok();
+ } else {
+ return kr_error(ENOENT);
+ }
+}
diff --git a/lib/dnssec/nsec.h b/lib/dnssec/nsec.h
new file mode 100644
index 0000000..9439a88
--- /dev/null
+++ b/lib/dnssec/nsec.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/packet/pkt.h>
+
+/**
+ * Check bitmap that child names are contained in the same zone.
+ * @note see RFC6840 4.1.
+ * @param bm Bitmap from NSEC or NSEC3.
+ * @param bm_size Bitmap size.
+ * @return 0 if they are, >0 if not (abs(ENOENT)), <0 on error.
+ */
+int kr_nsec_children_in_zone_check(const uint8_t *bm, uint16_t bm_size);
+
+/**
+ * Check an NSEC or NSEC3 bitmap for NODATA for a type.
+ * @param bm Bitmap.
+ * @param bm_size Bitmap size.
+ * @param type RR type to check.
+ * @param owner NSEC record owner.
+ * @note This includes special checks for zone cuts, e.g. from RFC 6840 sec. 4.
+ * @return 0, abs(ENOENT) (no proof), kr_error(EINVAL)
+ */
+int kr_nsec_bitmap_nodata_check(const uint8_t *bm, uint16_t bm_size, uint16_t type, const knot_dname_t *owner);
+
+/**
+ * Name error response check (RFC4035 3.1.3.2; RFC4035 5.4, bullet 2).
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @return 0 or error code.
+ */
+int kr_nsec_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname);
+
+/**
+ * No data response check (RFC4035 3.1.3.1; RFC4035 5.4, bullet 1).
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @param stype Type to be checked.
+ * @return 0 or error code.
+ */
+int kr_nsec_no_data_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype);
+
+/**
+ * Wildcard answer response check (RFC4035 3.1.3.3).
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @return 0 or error code.
+ */
+int kr_nsec_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname);
+
+/**
+ * Authenticated denial of existence according to RFC4035 5.4.
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Queried domain name.
+ * @param stype Queried type.
+ * @return 0 or error code.
+ */
+int kr_nsec_existence_denial(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype);
+
+/**
+ * Referral to unsigned subzone check (RFC4035 5.2).
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @return 0 or error code:
+ * DNSSEC_NOT_FOUND - neither ds nor nsec records
+ * were not found.
+ * EEXIST - ds record was found.
+ * EINVAL - bogus.
+ */
+int kr_nsec_ref_to_unsigned(const knot_pkt_t *pkt);
+
+/**
+ * Checks whether supplied NSEC RR matches the supplied name and type.
+ * @param nsec NSEC RR.
+ * @param name Name to be checked.
+ * @param type Type to be checked. Only use with NS! TODO (+copy&paste NSEC3)
+ * @return 0 or error code.
+ */
+int kr_nsec_matches_name_and_type(const knot_rrset_t *nsec,
+ const knot_dname_t *name, uint16_t type);
diff --git a/lib/dnssec/nsec3.c b/lib/dnssec/nsec3.c
new file mode 100644
index 0000000..4c2ef95
--- /dev/null
+++ b/lib/dnssec/nsec3.c
@@ -0,0 +1,776 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <libdnssec/binary.h>
+#include <libdnssec/error.h>
+#include <libdnssec/nsec.h>
+#include <libknot/descriptor.h>
+#include <contrib/base32hex.h>
+#include <libknot/rrset.h>
+#include <libknot/rrtype/nsec3.h>
+
+#include "lib/defines.h"
+#include "lib/dnssec/nsec.h"
+#include "lib/dnssec/nsec3.h"
+
+#define OPT_OUT_BIT 0x01
+
+//#define FLG_CLOSEST_ENCLOSER (1 << 0)
+#define FLG_CLOSEST_PROVABLE_ENCLOSER (1 << 1)
+#define FLG_NAME_COVERED (1 << 2)
+#define FLG_NAME_MATCHED (1 << 3)
+#define FLG_TYPE_BIT_MISSING (1 << 4)
+#define FLG_CNAME_BIT_MISSING (1 << 5)
+
+/**
+ * Obtains NSEC3 parameters from RR.
+ * @param params NSEC3 parameters structure to be set.
+ * @param nsec3 NSEC3 RR containing the parameters.
+ * @return 0 or error code.
+ */
+static int nsec3_parameters(dnssec_nsec3_params_t *params, const knot_rrset_t *nsec3)
+{
+ assert(params && nsec3);
+
+ const knot_rdata_t *rr = knot_rdataset_at(&nsec3->rrs, 0);
+ assert(rr);
+
+ /* Every NSEC3 RR contains data from NSEC3PARAMS. */
+ const size_t SALT_OFFSET = 5; /* First 5 octets contain { Alg, Flags, Iterations, Salt length } */
+ dnssec_binary_t rdata = {
+ .size = SALT_OFFSET + (size_t)knot_nsec3_salt_len(nsec3->rrs.rdata),
+ .data = /*const-cast*/(uint8_t *)rr->data,
+ };
+ if (rdata.size > rr->len)
+ return kr_error(EMSGSIZE);
+
+ int ret = dnssec_nsec3_params_from_rdata(params, &rdata);
+ if (ret != DNSSEC_EOK) {
+ return kr_error(EINVAL);
+ }
+
+ return kr_ok();
+}
+
+/**
+ * Computes a hash of a given domain name.
+ * @param hash Resulting hash, must be freed.
+ * @param params NSEC3 parameters.
+ * @param name Domain name to be hashed.
+ * @return 0 or error code.
+ */
+static int hash_name(dnssec_binary_t *hash, const dnssec_nsec3_params_t *params,
+ const knot_dname_t *name)
+{
+ assert(hash && params);
+ if (!name)
+ return kr_error(EINVAL);
+
+ dnssec_binary_t dname = {
+ .size = knot_dname_size(name),
+ .data = (uint8_t *) name,
+ };
+
+ int ret = dnssec_nsec3_hash(&dname, params, hash);
+ if (ret != DNSSEC_EOK) {
+ return kr_error(EINVAL);
+ }
+
+ return kr_ok();
+}
+
+/**
+ * Read hash from NSEC3 owner name and store its binary form.
+ * @param hash Buffer to be written.
+ * @param max_hash_size Maximal has size.
+ * @param nsec3 NSEC3 RR.
+ * @return 0 or error code.
+ */
+static int read_owner_hash(dnssec_binary_t *hash, size_t max_hash_size, const knot_rrset_t *nsec3)
+{
+ assert(hash && nsec3);
+ assert(hash->data);
+
+ int32_t ret = base32hex_decode(nsec3->owner + 1, nsec3->owner[0], hash->data, max_hash_size);
+ if (ret < 0) {
+ return kr_error(EILSEQ);
+ }
+ hash->size = ret;
+
+ return kr_ok();
+}
+
+#define MAX_HASH_BYTES 64
+/**
+ * Closest (provable) encloser match (RFC5155 7.2.1, bullet 1).
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec3 NSEC3 RR.
+ * @param name Name to be checked.
+ * @param skipped Number of skipped labels to find closest (provable) match.
+ * @return 0 or error code.
+ */
+static int closest_encloser_match(int *flags, const knot_rrset_t *nsec3,
+ const knot_dname_t *name, unsigned *skipped)
+{
+ assert(flags && nsec3 && name && skipped);
+
+ uint8_t hash_data[MAX_HASH_BYTES] = {0, };
+ dnssec_binary_t owner_hash = { 0, hash_data };
+ dnssec_nsec3_params_t params = { 0, };
+ dnssec_binary_t name_hash = { 0, };
+
+ int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = nsec3_parameters(&params, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ /* Root label has no encloser */
+ if (!name[0]) {
+ ret = kr_error(ENOENT);
+ goto fail;
+ }
+
+ const knot_dname_t *encloser = knot_wire_next_label(name, NULL);
+ *skipped = 1;
+
+ while(encloser) {
+ ret = hash_name(&name_hash, &params, encloser);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ if ((owner_hash.size == name_hash.size) &&
+ (memcmp(owner_hash.data, name_hash.data, owner_hash.size) == 0)) {
+ dnssec_binary_free(&name_hash);
+ *flags |= FLG_CLOSEST_PROVABLE_ENCLOSER;
+ break;
+ }
+
+ dnssec_binary_free(&name_hash);
+
+ if (!encloser[0])
+ break;
+ encloser = knot_wire_next_label(encloser, NULL);
+ ++(*skipped);
+ }
+
+ ret = kr_ok();
+
+fail:
+ if (params.salt.data) {
+ dnssec_nsec3_params_free(&params);
+ }
+ if (name_hash.data) {
+ dnssec_binary_free(&name_hash);
+ }
+ return ret;
+}
+
+/**
+ * Checks whether NSEC3 RR covers the supplied name (RFC5155 7.2.1, bullet 2).
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec3 NSEC3 RR.
+ * @param name Name to be checked.
+ * @return 0 or error code.
+ */
+static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t *name)
+{
+ assert(flags && nsec3 && name);
+
+ uint8_t hash_data[MAX_HASH_BYTES] = { 0, };
+ dnssec_binary_t owner_hash = { 0, hash_data };
+ dnssec_nsec3_params_t params = { 0, };
+ dnssec_binary_t name_hash = { 0, };
+
+ int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = nsec3_parameters(&params, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = hash_name(&name_hash, &params, name);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ uint8_t next_size = knot_nsec3_next_len(nsec3->rrs.rdata);
+ const uint8_t *next_hash = knot_nsec3_next(nsec3->rrs.rdata);
+
+ if ((next_size > 0) && (owner_hash.size == next_size) && (name_hash.size == next_size)) {
+ /* All hash lengths must be same. */
+ const uint8_t *ownrd = owner_hash.data;
+ const uint8_t *nextd = next_hash;
+ int covered = 0;
+ int greater_then_owner = (memcmp(ownrd, name_hash.data, next_size) < 0);
+ int less_then_next = (memcmp(name_hash.data, nextd, next_size) < 0);
+ if (memcmp(ownrd, nextd, next_size) < 0) {
+ /*
+ * 0 (...) owner ... next (...) MAX
+ * ^
+ * name
+ * ==>
+ * (owner < name) && (name < next)
+ */
+ covered = ((greater_then_owner) && (less_then_next));
+ } else {
+ /*
+ * owner ... MAX, 0 ... next
+ * ^ ^ ^
+ * name name name
+ * =>
+ * (owner < name) || (name < next)
+ */
+ covered = ((greater_then_owner) || (less_then_next));
+ }
+
+ if (covered) {
+ *flags |= FLG_NAME_COVERED;
+
+ uint8_t nsec3_flags = knot_nsec3_flags(nsec3->rrs.rdata);
+ if (nsec3_flags & ~OPT_OUT_BIT) {
+ /* RFC5155 3.1.2 */
+ ret = kr_error(EINVAL);
+ } else {
+ ret = kr_ok();
+ }
+ }
+ }
+
+fail:
+ if (params.salt.data) {
+ dnssec_nsec3_params_free(&params);
+ }
+ if (name_hash.data) {
+ dnssec_binary_free(&name_hash);
+ }
+ return ret;
+}
+
+/**
+ * Checks whether NSEC3 RR has the opt-out bit set.
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec3 NSEC3 RR.
+ * @param name Name to be checked.
+ * @return 0 or error code.
+ */
+static bool has_optout(const knot_rrset_t *nsec3)
+{
+ if (!nsec3) {
+ return false;
+ }
+
+ uint8_t nsec3_flags = knot_nsec3_flags(nsec3->rrs.rdata);
+ if (nsec3_flags & ~OPT_OUT_BIT) {
+ /* RFC5155 3.1.2 */
+ return false;
+ }
+
+ return nsec3_flags & OPT_OUT_BIT;
+}
+
+/**
+ * Checks whether NSEC3 RR matches the supplied name.
+ * @param flags Flags to be set according to check outcome.
+ * @param nsec3 NSEC3 RR.
+ * @param name Name to be checked.
+ * @return 0 if matching, >0 if not (abs(ENOENT)), or error code (<0).
+ */
+static int matches_name(const knot_rrset_t *nsec3, const knot_dname_t *name)
+{
+ assert(nsec3 && name);
+
+ uint8_t hash_data[MAX_HASH_BYTES] = { 0, };
+ dnssec_binary_t owner_hash = { 0, hash_data };
+ dnssec_nsec3_params_t params = { 0, };
+ dnssec_binary_t name_hash = { 0, };
+
+ int ret = read_owner_hash(&owner_hash, MAX_HASH_BYTES, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = nsec3_parameters(&params, nsec3);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ ret = hash_name(&name_hash, &params, name);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ if ((owner_hash.size == name_hash.size) &&
+ (memcmp(owner_hash.data, name_hash.data, owner_hash.size) == 0)) {
+ ret = kr_ok();
+ } else {
+ ret = abs(ENOENT);
+ }
+
+fail:
+ if (params.salt.data) {
+ dnssec_nsec3_params_free(&params);
+ }
+ if (name_hash.data) {
+ dnssec_binary_free(&name_hash);
+ }
+ return ret;
+}
+#undef MAX_HASH_BYTES
+
+/**
+ * Prepends an asterisk label to given name.
+ *
+ * @param tgt Target buffer to write domain name into.
+ * @param name Name to be added to the asterisk.
+ * @return Size of the resulting name or error code.
+ */
+static int prepend_asterisk(uint8_t *tgt, size_t maxlen, const knot_dname_t *name)
+{
+ assert(maxlen >= 3);
+ memcpy(tgt, "\1*", 3);
+ return knot_dname_to_wire(tgt + 2, name, maxlen - 2);
+}
+
+/**
+ * Closest encloser proof (RFC5155 7.2.1).
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @param encloser_name Returned matching encloser name, if found.
+ * @param matching_encloser_nsec3 Pointer to matching encloser NSEC RRSet.
+ * @param covering_next_nsec3 Pointer to covering next closer NSEC3 RRSet.
+ * @return 0 or error code.
+ */
+static int closest_encloser_proof(const knot_pkt_t *pkt,
+ knot_section_t section_id,
+ const knot_dname_t *sname,
+ const knot_dname_t **encloser_name,
+ const knot_rrset_t **matching_encloser_nsec3,
+ const knot_rrset_t **covering_next_nsec3)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ const knot_rrset_t *matching = NULL;
+ const knot_rrset_t *covering = NULL;
+
+ int flags = 0;
+ const knot_dname_t *next_closer = NULL;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ /* Also skip the NSEC3-to-match an ancestor of sname if it's
+ * a parent-side delegation, as that would mean the owner
+ * does not really exist (authoritatively in this zone,
+ * even in case of opt-out).
+ */
+ const uint8_t *bm = knot_nsec3_bitmap(rrset->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(rrset->rrs.rdata);
+ if (kr_nsec_children_in_zone_check(bm, bm_size) != 0) {
+ continue; /* no fatal errors from bad RRs */
+ }
+ /* Match the NSEC3 to sname or one of its ancestors. */
+ unsigned skipped = 0;
+ flags = 0;
+ int ret = closest_encloser_match(&flags, rrset, sname, &skipped);
+ if (ret != 0) {
+ return ret;
+ }
+ if (!(flags & FLG_CLOSEST_PROVABLE_ENCLOSER)) {
+ continue;
+ }
+ matching = rrset;
+ /* Construct the next closer name and try to cover it. */
+ --skipped;
+ next_closer = sname;
+ for (unsigned j = 0; j < skipped; ++j) {
+ assert(next_closer[0]);
+ next_closer = knot_wire_next_label(next_closer, NULL);
+ }
+ for (unsigned j = 0; j < sec->count; ++j) {
+ const knot_rrset_t *rrset_j = knot_pkt_rr(sec, j);
+ if (rrset_j->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ ret = covers_name(&flags, rrset_j, next_closer);
+ if (ret != 0) {
+ return ret;
+ }
+ if (flags & FLG_NAME_COVERED) {
+ covering = rrset_j;
+ break;
+ }
+ }
+ if (flags & FLG_NAME_COVERED) {
+ break;
+ }
+ flags = 0; //
+ }
+
+ if ((flags & FLG_CLOSEST_PROVABLE_ENCLOSER) && (flags & FLG_NAME_COVERED) && next_closer) {
+ if (encloser_name && next_closer[0]) {
+ *encloser_name = knot_wire_next_label(next_closer, NULL);
+ }
+ if (matching_encloser_nsec3) {
+ *matching_encloser_nsec3 = matching;
+ }
+ if (covering_next_nsec3) {
+ *covering_next_nsec3 = covering;
+ }
+ return kr_ok();
+ }
+
+ return kr_error(ENOENT);
+}
+
+/**
+ * Check whether any NSEC3 RR covers a wildcard RR at the closer encloser.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param encloser Closest (provable) encloser domain name.
+ * @return 0 or error code:
+ * KNOT_ERANGE - NSEC3 RR (that covers a wildcard)
+ * has been found, but has opt-out flag set;
+ * otherwise - error.
+ */
+static int covers_closest_encloser_wildcard(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *encloser)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !encloser) {
+ return kr_error(EINVAL);
+ }
+
+ uint8_t wildcard[KNOT_DNAME_MAXLEN];
+ wildcard[0] = 1;
+ wildcard[1] = '*';
+ int encloser_len = knot_dname_size(encloser);
+ if (encloser_len < 0) {
+ return encloser_len;
+ }
+ memcpy(wildcard + 2, encloser, encloser_len);
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ int ret = covers_name(&flags, rrset, wildcard);
+ if (ret != 0) {
+ return ret;
+ }
+ if (flags & FLG_NAME_COVERED) {
+ return has_optout(rrset) ?
+ kr_error(KNOT_ERANGE) : kr_ok();
+ }
+ }
+
+ return kr_error(ENOENT);
+}
+
+int kr_nsec3_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname)
+{
+ const knot_dname_t *encloser = NULL;
+ const knot_rrset_t *covering_next_nsec3 = NULL;
+ int ret = closest_encloser_proof(pkt, section_id, sname,
+ &encloser, NULL, &covering_next_nsec3);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = covers_closest_encloser_wildcard(pkt, section_id, encloser);
+ if (ret != 0) {
+ /* OK, but NSEC3 for wildcard at encloser has opt-out;
+ * or error */
+ return ret;
+ }
+ /* Closest encloser proof is OK and
+ * NSEC3 for wildcard has been found and optout flag is not set.
+ * Now check if NSEC3 that covers next closer name has opt-out. */
+ return has_optout(covering_next_nsec3) ?
+ kr_error(KNOT_ERANGE) : kr_ok();
+}
+
+/**
+ * Search the packet section for a matching NSEC3 with nodata-proving bitmap.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @param stype Type to be checked.
+ * @return 0 or error code.
+ * @note This does NOT check the opt-out case if type is DS;
+ * see RFC 5155 8.6.
+ */
+static int nodata_find(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *name, const uint16_t type)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !name) {
+ return kr_error(EINVAL);
+ }
+
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *nsec3 = knot_pkt_rr(sec, i);
+ /* Records causing any errors are simply skipped. */
+ if (nsec3->type != KNOT_RRTYPE_NSEC3
+ || matches_name(nsec3, name) != kr_ok()) {
+ continue;
+ /* LATER(optim.): we repeatedly recompute the hash of `name` */
+ }
+
+ const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata);
+ if (kr_nsec_bitmap_nodata_check(bm, bm_size, type, nsec3->owner) == kr_ok()) {
+ return kr_ok();
+ }
+ }
+
+ return kr_error(ENOENT);
+}
+
+/**
+ * Check whether NSEC3 RR matches a wildcard at the closest encloser and has given type bit missing.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param encloser Closest (provable) encloser domain name.
+ * @param stype Type to be checked.
+ * @return 0 or error code.
+ */
+static int matches_closest_encloser_wildcard(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *encloser, uint16_t stype)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !encloser) {
+ return kr_error(EINVAL);
+ }
+
+ uint8_t wildcard[KNOT_DNAME_MAXLEN]; /**< the source of synthesis */
+ int ret = prepend_asterisk(wildcard, sizeof(wildcard), encloser);
+ if (ret < 0) {
+ return ret;
+ }
+ assert(ret >= 3);
+ return nodata_find(pkt, section_id, wildcard, stype);
+}
+
+int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, int trim_to_next)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, section_id);
+ if (!sec || !sname) {
+ return kr_error(EINVAL);
+ }
+
+ /* Compute the next closer name. */
+ for (int i = 0; i < trim_to_next; ++i) {
+ assert(sname[0]);
+ sname = knot_wire_next_label(sname, NULL);
+ }
+
+ int flags = 0;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rrset = knot_pkt_rr(sec, i);
+ if (rrset->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ int ret = covers_name(&flags, rrset, sname);
+ if (ret != 0) {
+ return ret;
+ }
+ if (flags & FLG_NAME_COVERED) {
+ return has_optout(rrset) ?
+ kr_error(KNOT_ERANGE) : kr_ok();
+ }
+ }
+
+ return kr_error(ENOENT);
+}
+
+
+int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype)
+{
+ /* DS record may be also matched by an existing NSEC3 RR. */
+ int ret = nodata_find(pkt, section_id, sname, stype);
+ if (ret == 0) {
+ /* Satisfies RFC5155 8.5 and 8.6, both first paragraph. */
+ return ret;
+ }
+
+ /* Find closest provable encloser. */
+ const knot_dname_t *encloser_name = NULL;
+ const knot_rrset_t *covering_next_nsec3 = NULL;
+ ret = closest_encloser_proof(pkt, section_id, sname, &encloser_name,
+ NULL, &covering_next_nsec3);
+ if (ret != 0) {
+ return ret;
+ }
+
+ assert(encloser_name && covering_next_nsec3);
+ ret = matches_closest_encloser_wildcard(pkt, section_id,
+ encloser_name, stype);
+ if (ret == 0) {
+ /* Satisfies RFC5155 8.7 */
+ if (has_optout(covering_next_nsec3)) {
+ /* Opt-out is detected.
+ * Despite the fact that all records
+ * in the packet can be properly signed,
+ * AD bit must not be set due to rfc5155 9.2.
+ * Return appropriate code to the caller */
+ ret = kr_error(KNOT_ERANGE);
+ }
+ return ret;
+ }
+
+ if (!has_optout(covering_next_nsec3)) {
+ /* Bogus */
+ ret = kr_error(ENOENT);
+ } else {
+ /*
+ * Satisfies RFC5155 8.6 (QTYPE == DS), 2nd paragraph.
+ * Also satisfies ERRATA 3441 8.5 (QTYPE != DS), 3rd paragraph.
+ * - (wildcard) empty nonterminal
+ * derived from unsecure delegation.
+ * Denial of existence can not be proven.
+ * Set error code to proceed unsecure.
+ */
+ ret = kr_error(KNOT_ERANGE);
+ }
+
+ return ret;
+}
+
+int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt)
+{
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, KNOT_AUTHORITY);
+ if (!sec) {
+ return kr_error(EINVAL);
+ }
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *ns = knot_pkt_rr(sec, i);
+ if (ns->type == KNOT_RRTYPE_DS) {
+ return kr_error(EEXIST);
+ }
+ if (ns->type != KNOT_RRTYPE_NS) {
+ continue;
+ }
+
+ int flags = 0;
+ bool nsec3_found = false;
+ for (unsigned j = 0; j < sec->count; ++j) {
+ const knot_rrset_t *nsec3 = knot_pkt_rr(sec, j);
+ if (nsec3->type == KNOT_RRTYPE_DS) {
+ return kr_error(EEXIST);
+ }
+ if (nsec3->type != KNOT_RRTYPE_NSEC3) {
+ continue;
+ }
+ nsec3_found = true;
+ /* nsec3 found, check if owner name matches the delegation name.
+ * Just skip in case of *any* errors. */
+ if (matches_name(nsec3, ns->owner) != kr_ok()) {
+ continue;
+ }
+
+ const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata);
+ if (!bm) {
+ return kr_error(EINVAL);
+ }
+ if (dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_NS) &&
+ !dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_DS) &&
+ !dnssec_nsec_bitmap_contains(bm, bm_size,
+ KNOT_RRTYPE_SOA)) {
+ /* Satisfies rfc5155, 8.9. paragraph 2 */
+ return kr_ok();
+ }
+ }
+ if (!nsec3_found) {
+ return kr_error(DNSSEC_NOT_FOUND);
+ }
+ if (flags & FLG_NAME_MATCHED) {
+ /* nsec3 which owner matches
+ * the delegation name was found,
+ * but nsec3 type bitmap contains wrong types
+ */
+ return kr_error(EINVAL);
+ }
+ /* nsec3 that matches the delegation was not found.
+ * Check rfc5155, 8.9. paragraph 4.
+ * Find closest provable encloser.
+ */
+ const knot_dname_t *encloser_name = NULL;
+ const knot_rrset_t *covering_next_nsec3 = NULL;
+ int ret = closest_encloser_proof(pkt, KNOT_AUTHORITY, ns->owner,
+ &encloser_name, NULL, &covering_next_nsec3);
+ if (ret != 0) {
+ return kr_error(EINVAL);
+ }
+
+ if (has_optout(covering_next_nsec3)) {
+ return kr_error(KNOT_ERANGE);
+ } else {
+ return kr_error(EINVAL);
+ }
+ }
+ return kr_error(EINVAL);
+}
+
+int kr_nsec3_matches_name_and_type(const knot_rrset_t *nsec3,
+ const knot_dname_t *name, uint16_t type)
+{
+ /* It's not secure enough to just check a single bit for (some) other types,
+ * but we don't (currently) only use this API for NS. See RFC 6840 sec. 4.
+ */
+ if (type != KNOT_RRTYPE_NS) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ int ret = matches_name(nsec3, name);
+ if (ret) {
+ return kr_error(ret);
+ }
+ const uint8_t *bm = knot_nsec3_bitmap(nsec3->rrs.rdata);
+ uint16_t bm_size = knot_nsec3_bitmap_len(nsec3->rrs.rdata);
+ if (!bm) {
+ return kr_error(EINVAL);
+ }
+ if (dnssec_nsec_bitmap_contains(bm, bm_size, type)) {
+ return kr_ok();
+ } else {
+ return kr_error(ENOENT);
+ }
+}
diff --git a/lib/dnssec/nsec3.h b/lib/dnssec/nsec3.h
new file mode 100644
index 0000000..527ccce
--- /dev/null
+++ b/lib/dnssec/nsec3.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/packet/pkt.h>
+
+/**
+ * Name error response check (RFC5155 7.2.2).
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @return 0 or error code.
+ */
+int kr_nsec3_name_error_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname);
+
+/**
+ * Wildcard answer response check (RFC5155 7.2.6).
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Name to be checked.
+ * @param trim_to_next Number of labels to remove to obtain next closer name.
+ * @return 0 or error code:
+ * KNOT_ERANGE - NSEC3 RR that covers a wildcard
+ * has been found, but has opt-out flag set;
+ * otherwise - error.
+ */
+int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, int trim_to_next);
+
+/**
+ * Authenticated denial of existence according to RFC5155 8.5 and 8.7.
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @param section_id Packet section to be processed.
+ * @param sname Queried domain name.
+ * @param stype Queried type.
+ * @return 0 or error code:
+ * DNSSEC_NOT_FOUND - neither ds nor nsec records
+ * were not found.
+ * KNOT_ERANGE - denial of existence can't be proven
+ * due to opt-out, otherwise - bogus.
+ */
+int kr_nsec3_no_data(const knot_pkt_t *pkt, knot_section_t section_id,
+ const knot_dname_t *sname, uint16_t stype);
+
+/**
+ * Referral to unsigned subzone check (RFC5155 8.9).
+ * @note No RRSIGs are validated.
+ * @param pkt Packet structure to be processed.
+ * @return 0 or error code:
+ * KNOT_ERANGE - denial of existence can't be proven
+ * due to opt-out.
+ * EEXIST - ds record was found.
+ * EINVAL - bogus.
+ */
+int kr_nsec3_ref_to_unsigned(const knot_pkt_t *pkt);
+
+/**
+ * Checks whether supplied NSEC3 RR matches the supplied name and NS type.
+ * @param nsec3 NSEC3 RR.
+ * @param name Name to be checked.
+ * @param type Type to be checked. Only use with NS! TODO
+ * @return 0 or error code.
+ */
+int kr_nsec3_matches_name_and_type(const knot_rrset_t *nsec3,
+ const knot_dname_t *name, uint16_t type);
diff --git a/lib/dnssec/signature.c b/lib/dnssec/signature.c
new file mode 100644
index 0000000..356bf14
--- /dev/null
+++ b/lib/dnssec/signature.c
@@ -0,0 +1,307 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <string.h>
+
+#include <libdnssec/error.h>
+#include <libdnssec/key.h>
+#include <libdnssec/sign.h>
+#include <libknot/descriptor.h>
+#include <libknot/packet/rrset-wire.h>
+#include <libknot/packet/wire.h>
+#include <libknot/rrset.h>
+#include <libknot/rrtype/rrsig.h>
+#include <libknot/rrtype/ds.h>
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include "lib/dnssec/signature.h"
+
+#include "contrib/wire.h"
+
+static int authenticate_ds(const dnssec_key_t *key, dnssec_binary_t *ds_rdata, uint8_t digest_type)
+{
+ /* Compute DS RDATA from the DNSKEY. */
+ dnssec_binary_t computed_ds = { 0, };
+ int ret = dnssec_key_create_ds(key, digest_type, &computed_ds);
+ if (ret != DNSSEC_EOK) {
+ goto fail;
+ }
+
+ /* DS records contain algorithm, key tag and the digest.
+ * Therefore the comparison of the two DS is sufficient.
+ */
+ ret = (ds_rdata->size == computed_ds.size) &&
+ (memcmp(ds_rdata->data, computed_ds.data, ds_rdata->size) == 0);
+ ret = ret ? kr_ok() : kr_error(ENOENT);
+
+fail:
+ dnssec_binary_free(&computed_ds);
+ return kr_error(ret);
+}
+
+int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key)
+{
+ assert(ref && key);
+ if (ref->type != KNOT_RRTYPE_DS) {
+ return kr_error(EINVAL);
+ }
+
+ /* Try all possible DS records */
+ int ret = 0;
+ knot_rdata_t *rd = ref->rrs.rdata;
+ for (uint16_t i = 0; i < ref->rrs.count; ++i) {
+ dnssec_binary_t ds_rdata = {
+ .size = rd->len,
+ .data = rd->data
+ };
+ ret = authenticate_ds(key, &ds_rdata, knot_ds_digest_type(rd));
+ if (ret == 0) { /* Found a good DS */
+ return kr_ok();
+ }
+ rd = knot_rdataset_next(rd);
+ }
+
+ return kr_error(ret);
+}
+
+/**
+ * Adjust TTL in wire format.
+ * @param wire RR Set in wire format.
+ * @param wire_size Size of the wire data portion.
+ * @param new_ttl TTL value to be set for all RRs.
+ * @return 0 or error code.
+ */
+static int adjust_wire_ttl(uint8_t *wire, size_t wire_size, uint32_t new_ttl)
+{
+ assert(wire);
+ assert(sizeof(uint16_t) == 2);
+ assert(sizeof(uint32_t) == 4);
+ uint16_t rdlen;
+
+ int ret;
+
+ new_ttl = htonl(new_ttl);
+
+ size_t i = 0;
+ /* RR wire format in RFC1035 3.2.1 */
+ while(i < wire_size) {
+ ret = knot_dname_size(wire + i);
+ if (ret < 0) {
+ return ret;
+ }
+ i += ret + 4;
+ memcpy(wire + i, &new_ttl, sizeof(uint32_t));
+ i += sizeof(uint32_t);
+
+ memcpy(&rdlen, wire + i, sizeof(uint16_t));
+ rdlen = ntohs(rdlen);
+ i += sizeof(uint16_t) + rdlen;
+
+ assert(i <= wire_size);
+ }
+
+ return kr_ok();
+}
+
+/*!
+ * \brief Add RRSIG RDATA without signature to signing context.
+ *
+ * Requires signer name in RDATA in canonical form.
+ *
+ * \param ctx Signing context.
+ * \param rdata Pointer to RRSIG RDATA.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+#define RRSIG_RDATA_SIGNER_OFFSET 18
+static int sign_ctx_add_self(dnssec_sign_ctx_t *ctx, const uint8_t *rdata)
+{
+ assert(ctx);
+ assert(rdata);
+
+ int result;
+
+ // static header
+
+ dnssec_binary_t header = {
+ .data = (uint8_t *)rdata,
+ .size = RRSIG_RDATA_SIGNER_OFFSET,
+ };
+
+ result = dnssec_sign_add(ctx, &header);
+ if (result != DNSSEC_EOK) {
+ return result;
+ }
+
+ // signer name
+
+ const uint8_t *rdata_signer = rdata + RRSIG_RDATA_SIGNER_OFFSET;
+ dnssec_binary_t signer = { 0 };
+ signer.data = knot_dname_copy(rdata_signer, NULL);
+ signer.size = knot_dname_size(signer.data);
+
+ result = dnssec_sign_add(ctx, &signer);
+ free(signer.data);
+
+ return result;
+}
+#undef RRSIG_RDATA_SIGNER_OFFSET
+
+/*!
+ * \brief Add covered RRs to signing context.
+ *
+ * Requires all DNAMEs in canonical form and all RRs ordered canonically.
+ *
+ * \param ctx Signing context.
+ * \param covered Covered RRs.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int sign_ctx_add_records(dnssec_sign_ctx_t *ctx, const knot_rrset_t *covered,
+ uint32_t orig_ttl, int trim_labels)
+{
+ if (!ctx || !covered || trim_labels < 0) {
+ return kr_error(EINVAL);
+ }
+
+ // huge block of rrsets can be optionally created
+ static uint8_t wire_buffer[KNOT_WIRE_MAX_PKTSIZE];
+ int written = knot_rrset_to_wire(covered, wire_buffer, sizeof(wire_buffer), NULL);
+ if (written < 0) {
+ return written;
+ }
+
+ /* Set original ttl. */
+ int ret = adjust_wire_ttl(wire_buffer, written, orig_ttl);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (!trim_labels) {
+ const dnssec_binary_t wire_binary = {
+ .size = written,
+ .data = wire_buffer
+ };
+ return dnssec_sign_add(ctx, &wire_binary);
+ }
+
+ /* RFC4035 5.3.2
+ * Remove leftmost labels and replace them with '*.'
+ * for each RR in covered.
+ */
+ uint8_t *beginp = wire_buffer;
+ for (uint16_t i = 0; i < covered->rrs.count; ++i) {
+ /* RR(i) = name | type | class | OrigTTL | RDATA length | RDATA */
+ for (int j = 0; j < trim_labels; ++j) {
+ assert(beginp[0]);
+ beginp = (uint8_t *) knot_wire_next_label(beginp, NULL);
+ assert(beginp != NULL);
+ }
+ *(--beginp) = '*';
+ *(--beginp) = 1;
+ const size_t rdatalen_offset = knot_dname_size(beginp) + /* name */
+ sizeof(uint16_t) + /* type */
+ sizeof(uint16_t) + /* class */
+ sizeof(uint32_t); /* OrigTTL */
+ const uint8_t *rdatalen_ptr = beginp + rdatalen_offset;
+ const uint16_t rdata_size = wire_read_u16(rdatalen_ptr);
+ const size_t rr_size = rdatalen_offset +
+ sizeof(uint16_t) + /* RDATA length */
+ rdata_size; /* RDATA */
+ const dnssec_binary_t wire_binary = {
+ .size = rr_size,
+ .data = beginp
+ };
+ ret = dnssec_sign_add(ctx, &wire_binary);
+ if (ret != 0) {
+ break;
+ }
+ beginp += rr_size;
+ }
+ return ret;
+}
+
+/*!
+ * \brief Add all data covered by signature into signing context.
+ *
+ * RFC 4034: The signature covers RRSIG RDATA field (excluding the signature)
+ * and all matching RR records, which are ordered canonically.
+ *
+ * Requires all DNAMEs in canonical form and all RRs ordered canonically.
+ *
+ * \param ctx Signing context.
+ * \param rrsig_rdata RRSIG RDATA with populated fields except signature.
+ * \param covered Covered RRs.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+/* TODO -- Taken from knot/src/knot/dnssec/rrset-sign.c. Re-write for better fit needed. */
+static int sign_ctx_add_data(dnssec_sign_ctx_t *ctx, const uint8_t *rrsig_rdata,
+ const knot_rrset_t *covered, uint32_t orig_ttl, int trim_labels)
+{
+ int result = sign_ctx_add_self(ctx, rrsig_rdata);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ return sign_ctx_add_records(ctx, covered, orig_ttl, trim_labels);
+}
+
+int kr_check_signature(const knot_rdata_t *rrsig,
+ const dnssec_key_t *key, const knot_rrset_t *covered,
+ int trim_labels)
+{
+ if (!rrsig || !key || !dnssec_key_can_verify(key)) {
+ return kr_error(EINVAL);
+ }
+
+ int ret = 0;
+ dnssec_sign_ctx_t *sign_ctx = NULL;
+ dnssec_binary_t signature = {
+ .data = /*const-cast*/(uint8_t*)knot_rrsig_signature(rrsig),
+ .size = knot_rrsig_signature_len(rrsig),
+ };
+ if (!signature.data || !signature.size) {
+ ret = kr_error(EINVAL);
+ goto fail;
+ }
+
+ if (dnssec_sign_new(&sign_ctx, key) != 0) {
+ ret = kr_error(ENOMEM);
+ goto fail;
+ }
+
+ uint32_t orig_ttl = knot_rrsig_original_ttl(rrsig);
+
+ if (sign_ctx_add_data(sign_ctx, rrsig->data, covered, orig_ttl, trim_labels) != 0) {
+ ret = kr_error(ENOMEM);
+ goto fail;
+ }
+
+ if (dnssec_sign_verify(sign_ctx, &signature) != 0) {
+ ret = kr_error(EBADMSG);
+ goto fail;
+ }
+
+ ret = kr_ok();
+
+fail:
+ dnssec_sign_free(sign_ctx);
+ return ret;
+}
diff --git a/lib/dnssec/signature.h b/lib/dnssec/signature.h
new file mode 100644
index 0000000..b756483
--- /dev/null
+++ b/lib/dnssec/signature.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libdnssec/key.h>
+#include <libknot/rrset.h>
+
+/**
+ * Performs referral authentication according to RFC4035 5.2, bullet 2
+ * @param ref Referral RRSet. Currently only DS can be used.
+ * @param key Already parsed key.
+ * @return 0 or error code. In particular: DNSSEC_INVALID_DS_ALGORITHM
+ * in case *all* DSs in ref use an unimplemented algorithm.
+ */
+int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key);
+
+/**
+ * Check the signature of the supplied RRSet.
+ * @param rrsigs RRSet containing signatures.
+ * @param pos Index of the signature record in the signature RRSet.
+ * @param key Key to be used to validate the signature.
+ * @param covered The covered RRSet.
+ * @param trim_labels Number of the leftmost labels to be removed and replaced with '*.'.
+ * @return 0 if signature valid, error code else.
+ */
+int kr_check_signature(const knot_rdata_t *rrsig,
+ const dnssec_key_t *key, const knot_rrset_t *covered,
+ int trim_labels);
diff --git a/lib/dnssec/ta.c b/lib/dnssec/ta.c
new file mode 100644
index 0000000..12629c9
--- /dev/null
+++ b/lib/dnssec/ta.c
@@ -0,0 +1,185 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <contrib/cleanup.h>
+#include <libknot/descriptor.h>
+#include <libknot/rdataset.h>
+#include <libknot/rrset.h>
+#include <libknot/packet/wire.h>
+#include <libdnssec/key.h>
+#include <libdnssec/error.h>
+
+#include "lib/defines.h"
+#include "lib/dnssec.h"
+#include "lib/dnssec/ta.h"
+#include "lib/resolve.h"
+#include "lib/utils.h"
+
+knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name)
+{
+ return map_get(trust_anchors, (const char *)name);
+}
+
+const knot_dname_t *kr_ta_get_longest_name(map_t *trust_anchors, const knot_dname_t *name)
+{
+ while(name) {
+ if (kr_ta_get(trust_anchors, name)) {
+ return name;
+ }
+ if (name[0] == '\0') {
+ break;
+ }
+ name = knot_wire_next_label(name, NULL);
+ }
+ return NULL;
+}
+
+/* @internal Create DS from DNSKEY, caller MUST free dst if successful. */
+static int dnskey2ds(dnssec_binary_t *dst, const knot_dname_t *owner, const uint8_t *rdata, uint16_t rdlen)
+{
+ dnssec_key_t *key = NULL;
+ int ret = dnssec_key_new(&key);
+ if (ret) goto cleanup;
+ /* Create DS from DNSKEY and reinsert */
+ const dnssec_binary_t key_data = { .size = rdlen, .data = (uint8_t *)rdata };
+ ret = dnssec_key_set_rdata(key, &key_data);
+ if (ret) goto cleanup;
+ /* Accept only keys with Zone and SEP flags that aren't revoked,
+ * as a precaution. RFC 5011 also utilizes these flags.
+ * TODO: kr_dnssec_key_* names are confusing. */
+ const bool flags_ok = kr_dnssec_key_zsk(rdata) && !kr_dnssec_key_revoked(rdata);
+ if (!flags_ok) {
+ auto_free char *owner_str = kr_dname_text(owner);
+ kr_log_error("[ ta ] refusing to trust %s DNSKEY because of flags %d\n",
+ owner_str, dnssec_key_get_flags(key));
+ ret = kr_error(EILSEQ);
+ goto cleanup;
+ } else if (!kr_dnssec_key_ksk(rdata)) {
+ auto_free char *owner_str = kr_dname_text(owner);
+ int flags = dnssec_key_get_flags(key);
+ kr_log_info("[ ta ] warning: %s DNSKEY is missing the SEP bit; "
+ "flags %d instead of %d\n",
+ owner_str, flags, flags + 1/*a little ugly*/);
+ }
+ ret = dnssec_key_set_dname(key, owner);
+ if (ret) goto cleanup;
+ ret = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA256, dst);
+cleanup:
+ dnssec_key_free(key);
+ return kr_error(ret);
+}
+
+/* @internal Insert new TA to trust anchor set, rdata MUST be of DS type. */
+static int insert_ta(map_t *trust_anchors, const knot_dname_t *name,
+ uint32_t ttl, const uint8_t *rdata, uint16_t rdlen)
+{
+ bool is_new_key = false;
+ knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, name);
+ if (!ta_rr) {
+ ta_rr = knot_rrset_new(name, KNOT_RRTYPE_DS, KNOT_CLASS_IN, ttl, NULL);
+ is_new_key = true;
+ }
+ /* Merge-in new key data */
+ if (!ta_rr || (rdlen > 0 && knot_rrset_add_rdata(ta_rr, rdata, rdlen, NULL) != 0)) {
+ knot_rrset_free(ta_rr, NULL);
+ return kr_error(ENOMEM);
+ }
+ if (is_new_key) {
+ return map_set(trust_anchors, (const char *)name, ta_rr);
+ }
+ return kr_ok();
+}
+
+int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type,
+ uint32_t ttl, const uint8_t *rdata, uint16_t rdlen)
+{
+ if (!trust_anchors || !name) {
+ return kr_error(EINVAL);
+ }
+
+ /* DS/DNSEY types are accepted, for DNSKEY we
+ * need to compute a DS digest. */
+ if (type == KNOT_RRTYPE_DS) {
+ return insert_ta(trust_anchors, name, ttl, rdata, rdlen);
+ } else if (type == KNOT_RRTYPE_DNSKEY) {
+ dnssec_binary_t ds_rdata = { 0, };
+ int ret = dnskey2ds(&ds_rdata, name, rdata, rdlen);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = insert_ta(trust_anchors, name, ttl, ds_rdata.data, ds_rdata.size);
+ dnssec_binary_free(&ds_rdata);
+ return ret;
+ } else { /* Invalid type for TA */
+ return kr_error(EINVAL);
+ }
+}
+
+int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name)
+{
+ while(name) {
+ if (kr_ta_get(trust_anchors, name)) {
+ return true;
+ }
+ if (name[0] == '\0') {
+ return false;
+ }
+ name = knot_wire_next_label(name, NULL);
+ }
+ return false;
+}
+
+bool kr_ta_covers_qry(struct kr_context *ctx, const knot_dname_t *name,
+ const uint16_t type)
+{
+ assert(ctx && name);
+ if (type == KNOT_RRTYPE_DS && name[0] != '\0') {
+ /* DS is parent-side record, so the parent name needs to be covered. */
+ name = knot_wire_next_label(name, NULL);
+ if (!name) {
+ assert(false);
+ return false;
+ }
+ }
+ return kr_ta_covers(&ctx->trust_anchors, name)
+ && !kr_ta_covers(&ctx->negative_anchors, name);
+}
+
+/* Delete record data */
+static int del_record(const char *k, void *v, void *ext)
+{
+ knot_rrset_t *ta_rr = v;
+ if (ta_rr) {
+ knot_rrset_free(ta_rr, NULL);
+ }
+ return 0;
+}
+
+int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name)
+{
+ knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, name);
+ if (ta_rr) {
+ del_record(NULL, ta_rr, NULL);
+ map_del(trust_anchors, (const char *)name);
+ }
+ return kr_ok();
+}
+
+void kr_ta_clear(map_t *trust_anchors)
+{
+ map_walk(trust_anchors, del_record, NULL);
+ map_clear(trust_anchors);
+}
diff --git a/lib/dnssec/ta.h b/lib/dnssec/ta.h
new file mode 100644
index 0000000..dcc55e7
--- /dev/null
+++ b/lib/dnssec/ta.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/generic/map.h"
+#include <libknot/rrset.h>
+
+/**
+ * Find TA RRSet by name.
+ * @param trust_anchors trust store
+ * @param name name of the TA
+ * @return non-empty RRSet or NULL
+ */
+KR_EXPORT
+knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name);
+
+/**
+ * Add TA to trust store. DS or DNSKEY types are supported.
+ * @param trust_anchors trust store
+ * @param name name of the TA
+ * @param type RR type of the TA (DS or DNSKEY)
+ * @param ttl
+ * @param rdata
+ * @param rdlen
+ * @return 0 or an error
+ */
+KR_EXPORT
+int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type,
+ uint32_t ttl, const uint8_t *rdata, uint16_t rdlen);
+
+/**
+ * Return true if the name is below/at any TA in the store.
+ * This can be useful to check if it's possible to validate a name beforehand.
+ * @param trust_anchors trust store
+ * @param name name of the TA
+ * @return boolean
+ */
+KR_EXPORT KR_PURE
+int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name);
+
+struct kr_context;
+/**
+ * A wrapper around kr_ta_covers that is aware of negative TA and types.
+ */
+KR_EXPORT KR_PURE
+bool kr_ta_covers_qry(struct kr_context *ctx, const knot_dname_t *name,
+ const uint16_t type);
+
+/**
+ * Remove TA from trust store.
+ * @param trust_anchors trust store
+ * @param name name of the TA
+ * @return 0 or an error
+ */
+KR_EXPORT
+int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name);
+
+/**
+ * Clear trust store.
+ * @param trust_anchors trust store
+ */
+KR_EXPORT
+void kr_ta_clear(map_t *trust_anchors);
+
+/**
+ * Return TA with the longest name that covers given name.
+ * @param trust_anchors trust store
+ * @param name name of the TA
+ * @return pointer to name or NULL.
+ if not NULL, points inside the name parameter.
+ */
+KR_EXPORT
+const knot_dname_t *kr_ta_get_longest_name(map_t *trust_anchors, const knot_dname_t *name);
diff --git a/lib/generic/README.rst b/lib/generic/README.rst
new file mode 100644
index 0000000..7adff86
--- /dev/null
+++ b/lib/generic/README.rst
@@ -0,0 +1,60 @@
+Generics library
+----------------
+
+This small collection of "generics" was born out of frustration that I couldn't find no
+such thing for C. It's either bloated, has poor interface, null-checking is absent or
+doesn't allow custom allocation scheme. BSD-licensed (or compatible) code is allowed here,
+as long as it comes with a test case in `tests/test_generics.c`.
+
+* array_ - a set of simple macros to make working with dynamic arrays easier.
+* queue_ - a FIFO + LIFO queue.
+* map_ - a `Crit-bit tree`_ key-value map implementation (public domain) that comes with tests.
+* set_ - set abstraction implemented on top of ``map`` (unused now).
+* pack_ - length-prefixed list of objects (i.e. array-list).
+* lru_ - LRU-like hash table
+* trie_ - a trie-based key-value map, taken from knot-dns
+
+array
+~~~~~
+
+.. doxygenfile:: array.h
+ :project: libkres
+
+queue
+~~~~~
+
+.. doxygenfile:: queue.h
+ :project: libkres
+
+map
+~~~
+
+.. doxygenfile:: map.h
+ :project: libkres
+
+set
+~~~
+
+.. doxygenfile:: set.h
+ :project: libkres
+
+pack
+~~~~
+
+.. doxygenfile:: pack.h
+ :project: libkres
+
+lru
+~~~
+
+.. doxygenfile:: lru.h
+ :project: libkres
+
+trie
+~~~~
+
+.. doxygenfile:: trie.h
+ :project: libkres
+
+
+.. _`Crit-bit tree`: https://cr.yp.to/critbit.html
diff --git a/lib/generic/array.h b/lib/generic/array.h
new file mode 100644
index 0000000..ece4dd1
--- /dev/null
+++ b/lib/generic/array.h
@@ -0,0 +1,166 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ *
+ * @file array.h
+ * @brief A set of simple macros to make working with dynamic arrays easier.
+ *
+ * @note The C has no generics, so it is implemented mostly using macros.
+ * Be aware of that, as direct usage of the macros in the evaluating macros
+ * may lead to different expectations:
+ *
+ * @code{.c}
+ * MIN(array_push(arr, val), other)
+ * @endcode
+ *
+ * May evaluate the code twice, leading to unexpected behaviour.
+ * This is a price to pay for the absence of proper generics.
+ *
+ * # Example usage:
+ *
+ * @code{.c}
+ * array_t(const char*) arr;
+ * array_init(arr);
+ *
+ * // Reserve memory in advance
+ * if (array_reserve(arr, 2) < 0) {
+ * return ENOMEM;
+ * }
+ *
+ * // Already reserved, cannot fail
+ * array_push(arr, "princess");
+ * array_push(arr, "leia");
+ *
+ * // Not reserved, may fail
+ * if (array_push(arr, "han") < 0) {
+ * return ENOMEM;
+ * }
+ *
+ * // It does not hide what it really is
+ * for (size_t i = 0; i < arr.len; ++i) {
+ * printf("%s\n", arr.at[i]);
+ * }
+ *
+ * // Random delete
+ * array_del(arr, 0);
+ * @endcode
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+#include <stdlib.h>
+
+/** Simplified Qt containers growth strategy. */
+static inline size_t array_next_count(size_t want)
+{
+ if (want < 2048) {
+ return (want < 20) ? want + 4 : want * 2;
+ } else {
+ return want + 2048;
+ }
+}
+
+/** @internal Incremental memory reservation */
+static inline int array_std_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+{
+ if (*have >= want) {
+ return 0;
+ }
+ /* Simplified Qt containers growth strategy */
+ size_t next_size = array_next_count(want);
+ void *mem_new = realloc(*mem, next_size * elm_size);
+ if (mem_new != NULL) {
+ *mem = mem_new;
+ *have = next_size;
+ return 0;
+ }
+ return -1;
+}
+
+/** @internal Wrapper for stdlib free. */
+static inline void array_std_free(void *baton, void *p)
+{
+ free(p);
+}
+
+/** Declare an array structure. */
+#define array_t(type) struct {type * at; size_t len; size_t cap; }
+
+/** Zero-initialize the array. */
+#define array_init(array) ((array).at = NULL, (array).len = (array).cap = 0)
+
+/** Free and zero-initialize the array (plain malloc/free). */
+#define array_clear(array) \
+ array_clear_mm(array, array_std_free, NULL)
+
+/** Make the array empty and free pointed-to memory.
+ * Mempool usage: pass mm_free and a knot_mm_t* . */
+#define array_clear_mm(array, free, baton) \
+ (free)((baton), (array).at), array_init(array)
+
+/** Reserve capacity for at least n elements.
+ * @return 0 if success, <0 on failure */
+#define array_reserve(array, n) \
+ array_reserve_mm(array, n, array_std_reserve, NULL)
+
+/** Reserve capacity for at least n elements.
+ * Mempool usage: pass kr_memreserve and a knot_mm_t* .
+ * @return 0 if success, <0 on failure */
+#define array_reserve_mm(array, n, reserve, baton) \
+ (reserve)((baton), (char **) &(array).at, sizeof((array).at[0]), (n), &(array).cap)
+
+/**
+ * Push value at the end of the array, resize it if necessary.
+ * Mempool usage: pass kr_memreserve and a knot_mm_t* .
+ * @note May fail if the capacity is not reserved.
+ * @return element index on success, <0 on failure
+ */
+#define array_push_mm(array, val, reserve, baton) \
+ (int)((array).len < (array).cap ? ((array).at[(array).len] = val, (array).len++) \
+ : (array_reserve_mm(array, ((array).cap + 1), reserve, baton) < 0 ? -1 \
+ : ((array).at[(array).len] = val, (array).len++)))
+
+/**
+ * Push value at the end of the array, resize it if necessary (plain malloc/free).
+ * @note May fail if the capacity is not reserved.
+ * @return element index on success, <0 on failure
+ */
+#define array_push(array, val) \
+ array_push_mm(array, val, array_std_reserve, NULL)
+
+/**
+ * Pop value from the end of the array.
+ */
+#define array_pop(array) \
+ (array).len -= 1
+
+/**
+ * Remove value at given index.
+ * @return 0 on success, <0 on failure
+ */
+#define array_del(array, i) \
+ (int)((i) < (array).len ? ((array).len -= 1,(array).at[i] = (array).at[(array).len], 0) : -1)
+
+/**
+ * Return last element of the array.
+ * @warning Undefined if the array is empty.
+ */
+#define array_tail(array) \
+ (array).at[(array).len - 1]
+
+/** @} */
diff --git a/lib/generic/lru.c b/lib/generic/lru.c
new file mode 100644
index 0000000..12bba4e
--- /dev/null
+++ b/lib/generic/lru.c
@@ -0,0 +1,236 @@
+/* Copyright (C) 2016-2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/generic/lru.h"
+#include "contrib/murmurhash3/murmurhash3.h"
+
+typedef struct lru_group lru_group_t;
+
+struct lru_item {
+ uint16_t key_len, val_len; /**< Two bytes should be enough for our purposes. */
+ char data[];
+ /**< Place for both key and value.
+ *
+ * We use "char" to satisfy the C99+ aliasing rules.
+ * See C99 section 6.5 Expressions, paragraph 7.
+ * Any type can be accessed through char-pointer,
+ * so we can use a common struct definition
+ * for all types being held.
+ */
+};
+
+/** @internal Compute offset of value in struct lru_item. */
+static uint val_offset(uint key_len)
+{
+ uint key_end = offsetof(struct lru_item, data) + key_len;
+ // align it to the closest multiple of four
+ return round_power(key_end, 2);
+}
+
+/** @internal Return pointer to value in an item. */
+static void * item_val(struct lru_item *it)
+{
+ return it->data + val_offset(it->key_len) - offsetof(struct lru_item, data);
+}
+
+/** @internal Compute the size of an item. ATM we don't align/pad the end of it. */
+static uint item_size(uint key_len, uint val_len)
+{
+ return val_offset(key_len) + val_len;
+}
+
+/** @internal Free each item. */
+KR_EXPORT void lru_free_items_impl(struct lru *lru)
+{
+ assert(lru);
+ for (size_t i = 0; i < (1 << (size_t)lru->log_groups); ++i) {
+ lru_group_t *g = &lru->groups[i];
+ for (int j = 0; j < LRU_ASSOC; ++j)
+ mm_free(lru->mm, g->items[j]);
+ }
+}
+
+/** @internal See lru_apply. */
+KR_EXPORT void lru_apply_impl(struct lru *lru, lru_apply_fun f, void *baton)
+{
+ bool ok = lru && f;
+ if (!ok) {
+ assert(false);
+ return;
+ }
+ for (size_t i = 0; i < (1 << (size_t)lru->log_groups); ++i) {
+ lru_group_t *g = &lru->groups[i];
+ for (uint j = 0; j < LRU_ASSOC; ++j) {
+ struct lru_item *it = g->items[j];
+ if (!it)
+ continue;
+ enum lru_apply_do ret =
+ f(it->data, it->key_len, item_val(it), baton);
+ switch(ret) {
+ case LRU_APPLY_DO_EVICT: // evict
+ mm_free(lru->mm, it);
+ g->items[j] = NULL;
+ g->counts[j] = 0;
+ g->hashes[j] = 0;
+ break;
+ default:
+ assert(ret == LRU_APPLY_DO_NOTHING);
+ }
+ }
+ }
+}
+
+/** @internal See lru_create. */
+KR_EXPORT struct lru * lru_create_impl(uint max_slots, knot_mm_t *mm_array, knot_mm_t *mm)
+{
+ assert(max_slots);
+ if (!max_slots)
+ return NULL;
+ // let lru->log_groups = ceil(log2(max_slots / (float) assoc))
+ // without trying for efficiency
+ uint group_count = (max_slots - 1) / LRU_ASSOC + 1;
+ uint log_groups = 0;
+ for (uint s = group_count - 1; s; s /= 2)
+ ++log_groups;
+ group_count = 1 << log_groups;
+ assert(max_slots <= group_count * LRU_ASSOC && group_count * LRU_ASSOC < 2 * max_slots);
+
+ size_t size = offsetof(struct lru, groups[group_count]);
+ struct lru *lru = mm_alloc(mm_array, size);
+ if (unlikely(lru == NULL))
+ return NULL;
+ *lru = (struct lru){
+ .mm = mm,
+ .mm_array = mm_array,
+ .log_groups = log_groups,
+ };
+ // zeros are a good init
+ memset(lru->groups, 0, size - offsetof(struct lru, groups));
+ return lru;
+}
+
+/** @internal Decrement all counters within a group. */
+static void group_dec_counts(lru_group_t *g) {
+ g->counts[LRU_TRACKED] = LRU_TRACKED;
+ for (uint i = 0; i < LRU_TRACKED + 1; ++i)
+ if (likely(g->counts[i]))
+ --g->counts[i];
+}
+
+/** @internal Increment a counter within a group. */
+static void group_inc_count(lru_group_t *g, int i) {
+ if (likely(++(g->counts[i])))
+ return;
+ g->counts[i] = -1;
+ // We could've decreased or halved all of them, but let's keep the max.
+}
+
+/** @internal Implementation of both getting and insertion.
+ * Note: val_len is only meaningful if do_insert.
+ * *is_new is only meaningful when return value isn't NULL, contains
+ * true when returned lru entry has been allocated right now
+ * if return value is NULL, *is_new remains untouched.
+ */
+KR_EXPORT void * lru_get_impl(struct lru *lru, const char *key, uint key_len,
+ uint val_len, bool do_insert, bool *is_new)
+{
+ bool ok = lru && (key || !key_len) && key_len <= UINT16_MAX
+ && (!do_insert || val_len <= UINT16_MAX);
+ if (!ok) {
+ assert(false);
+ return NULL; // reasonable fallback when not debugging
+ }
+ bool is_new_entry = false;
+ // find the right group
+ uint32_t khash = hash(key, key_len);
+ uint16_t khash_top = khash >> 16;
+ lru_group_t *g = &lru->groups[khash & ((1 << lru->log_groups) - 1)];
+ struct lru_item *it = NULL;
+ uint i;
+ // scan the *stored* elements in the group
+ for (i = 0; i < LRU_ASSOC; ++i) {
+ if (g->hashes[i] == khash_top) {
+ it = g->items[i];
+ if (likely(it && it->key_len == key_len
+ && (key_len == 0 || memcmp(it->data, key, key_len) == 0))) {
+ /* Found a key, but trying to insert a value larger than available
+ * space in the allocated slot, so the entry must be resized to fit. */
+ if (unlikely(do_insert && val_len > it->val_len)) {
+ goto insert;
+ } else {
+ goto found; // to reduce huge nesting depth
+ }
+ }
+ }
+ }
+ // key not found; first try an empty/counted-out place to insert
+ if (do_insert)
+ for (i = 0; i < LRU_ASSOC; ++i)
+ if (g->items[i] == NULL || g->counts[i] == 0)
+ goto insert;
+ // check if we track key's count at least
+ for (i = LRU_ASSOC; i < LRU_TRACKED; ++i) {
+ if (g->hashes[i] == khash_top) {
+ group_inc_count(g, i);
+ if (!do_insert)
+ return NULL;
+ // check if we trumped some stored key
+ for (uint j = 0; j < LRU_ASSOC; ++j)
+ if (unlikely(g->counts[i] > g->counts[j])) {
+ // evict key j, i.e. swap with i
+ --g->counts[i]; // we increment it below
+ SWAP(g->counts[i], g->counts[j]);
+ SWAP(g->hashes[i], g->hashes[j]);
+ i = j;
+ goto insert;
+ }
+ return NULL;
+ }
+ }
+ // not found at all: decrement all counts but only on every LRU_TRACKED occasion
+ if (g->counts[LRU_TRACKED])
+ --g->counts[LRU_TRACKED];
+ else
+ group_dec_counts(g);
+ return NULL;
+insert: // insert into position i (incl. key)
+ assert(i < LRU_ASSOC);
+ g->hashes[i] = khash_top;
+ it = g->items[i];
+ uint new_size = item_size(key_len, val_len);
+ if (it == NULL || new_size != item_size(it->key_len, it->val_len)) {
+ // (re)allocate
+ mm_free(lru->mm, it);
+ it = g->items[i] = mm_alloc(lru->mm, new_size);
+ if (it == NULL)
+ return NULL;
+ }
+ it->key_len = key_len;
+ it->val_len = val_len;
+ if (key_len > 0) {
+ memcpy(it->data, key, key_len);
+ }
+ memset(item_val(it), 0, val_len); // clear the value
+ is_new_entry = true;
+found: // key and hash OK on g->items[i]; now update stamps
+ assert(i < LRU_ASSOC);
+ group_inc_count(g, i);
+ if (is_new) {
+ *is_new = is_new_entry;
+ }
+ return item_val(g->items[i]);
+}
+
diff --git a/lib/generic/lru.h b/lib/generic/lru.h
new file mode 100644
index 0000000..b5c9bcd
--- /dev/null
+++ b/lib/generic/lru.h
@@ -0,0 +1,249 @@
+/* Copyright (C) 2016-2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+/**
+ * @file lru.h
+ * @brief A lossy cache.
+ *
+ * @note The implementation tries to keep frequent keys and avoid others,
+ * even if "used recently", so it may refuse to store it on lru_get_new().
+ * It uses hashing to split the problem pseudo-randomly into smaller groups,
+ * and within each it tries to approximate relative usage counts of several
+ * most frequent keys/hashes. This tracking is done for *more* keys than
+ * those that are actually stored.
+ *
+ * Example usage:
+ * @code{.c}
+ * // Define new LRU type
+ * typedef lru_t(int) lru_int_t;
+ *
+ * // Create LRU
+ * lru_int_t *lru;
+ * lru_create(&lru, 5, NULL, NULL);
+ *
+ * // Insert some values
+ * int *pi = lru_get_new(lru, "luke", strlen("luke"), NULL);
+ * if (pi)
+ * *pi = 42;
+ * pi = lru_get_new(lru, "leia", strlen("leia"), NULL);
+ * if (pi)
+ * *pi = 24;
+ *
+ * // Retrieve values
+ * int *ret = lru_get_try(lru, "luke", strlen("luke"), NULL);
+ * if (!ret) printf("luke dropped out!\n");
+ * else printf("luke's number is %d\n", *ret);
+ *
+ * char *enemies[] = {"goro", "raiden", "subzero", "scorpion"};
+ * for (int i = 0; i < 4; ++i) {
+ * int *val = lru_get_new(lru, enemies[i], strlen(enemies[i]), NULL);
+ * if (val)
+ * *val = i;
+ * }
+ *
+ * // We're done
+ * lru_free(lru);
+ * @endcode
+ *
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+
+#include <assert.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "contrib/ucw/lib.h"
+#include "lib/utils.h"
+#include "libknot/mm_ctx.h"
+
+/* ================================ Interface ================================ */
+
+/** @brief The type for LRU, parametrized by value type. */
+#define lru_t(type) \
+ union { \
+ type *pdata_t; /* only the *type* information is used */ \
+ struct lru lru; \
+ }
+
+/**
+ * @brief Allocate and initialize an LRU with default associativity.
+ *
+ * The real limit on the number of slots can be a bit larger but less than double.
+ *
+ * @param ptable pointer to a pointer to the LRU
+ * @param max_slots number of slots
+ * @param mm_ctx_array memory context to use for the huge array, NULL for default
+ * @param mm_ctx memory context to use for individual key-value pairs, NULL for default
+ *
+ * @note The pointers to memory contexts need to remain valid
+ * during the whole life of the structure (or be NULL).
+ */
+#define lru_create(ptable, max_slots, mm_ctx_array, mm_ctx) do { \
+ (void)(((__typeof__((*(ptable))->pdata_t))0) == (void *)0); /* typecheck lru_t */ \
+ *(ptable) = (__typeof__(*(ptable))) \
+ lru_create_impl((max_slots), (mm_ctx_array), (mm_ctx)); \
+ } while (false)
+
+/** @brief Free an LRU created by lru_create (it can be NULL). */
+#define lru_free(table) \
+ lru_free_impl(&(table)->lru)
+
+/** @brief Reset an LRU to the empty state (but preserve any settings). */
+#define lru_reset(table) \
+ lru_reset_impl(&(table)->lru)
+
+/**
+ * @brief Find key in the LRU and return pointer to the corresponding value.
+ *
+ * @param table pointer to LRU
+ * @param key_ lookup key
+ * @param len_ key length
+ * @return pointer to data or NULL if not found
+ */
+#define lru_get_try(table, key_, len_) \
+ (__typeof__((table)->pdata_t)) \
+ lru_get_impl(&(table)->lru, (key_), (len_), -1, false, NULL)
+
+/**
+ * @brief Return pointer to value, inserting if needed (zeroed).
+ *
+ * @param table pointer to LRU
+ * @param key_ lookup key
+ * @param len_ key lengthkeys
+ * @param is_new pointer to bool to store result of operation
+ * (true if entry is newly added, false otherwise; can be NULL).
+ * @return pointer to data or NULL (can be even if memory could be allocated!)
+ */
+#define lru_get_new(table, key_, len_, is_new) \
+ (__typeof__((table)->pdata_t)) \
+ lru_get_impl(&(table)->lru, (key_), (len_), \
+ sizeof(*(table)->pdata_t), true, is_new)
+
+/**
+ * @brief Apply a function to every item in LRU.
+ *
+ * @param table pointer to LRU
+ * @param function enum lru_apply_do (*function)(const char *key, uint len, val_type *val, void *baton)
+ * See enum lru_apply_do for the return type meanings.
+ * @param baton extra pointer passed to each function invocation
+ */
+#define lru_apply(table, function, baton) do { \
+ lru_apply_fun_g(fun_dummy, __typeof__(*(table)->pdata_t)) = 0; \
+ (void)(fun_dummy == (function)); /* produce a warning with incompatible function type */ \
+ lru_apply_impl(&(table)->lru, (lru_apply_fun)(function), (baton)); \
+ } while (false)
+
+/** @brief Possible actions to do with an element. */
+enum lru_apply_do {
+ LRU_APPLY_DO_NOTHING,
+ LRU_APPLY_DO_EVICT,
+ /* maybe more in future*/
+};
+
+/**
+ * @brief Return the real capacity - maximum number of keys holdable within.
+ *
+ * @param table pointer to LRU
+ */
+#define lru_capacity(table) lru_capacity_impl(&(table)->lru)
+
+
+/** @brief Round the value up to a multiple of (1 << power). */
+static inline uint round_power(uint size, uint power)
+{
+ uint res = ((size - 1) & ~((1 << power) - 1)) + (1 << power);
+ assert(__builtin_ctz(res) >= power);
+ assert(size <= res && res < size + (1 << power));
+ return res;
+}
+
+
+/* ======================== Inlined part of implementation ======================== */
+/** @cond internal */
+
+#define lru_apply_fun_g(name, val_type) \
+ enum lru_apply_do (*(name))(const char *key, uint len, val_type *val, void *baton)
+typedef lru_apply_fun_g(lru_apply_fun, void);
+
+#if __GNUC__ >= 4
+ #define CACHE_ALIGNED __attribute__((aligned(64)))
+#else
+ #define CACHE_ALIGNED
+#endif
+
+struct lru;
+void lru_free_items_impl(struct lru *lru);
+struct lru * lru_create_impl(uint max_slots, knot_mm_t *mm_array, knot_mm_t *mm);
+void * lru_get_impl(struct lru *lru, const char *key, uint key_len,
+ uint val_len, bool do_insert, bool *is_new);
+void lru_apply_impl(struct lru *lru, lru_apply_fun f, void *baton);
+
+struct lru_item;
+
+#if SIZE_MAX > (1 << 32)
+ /** @internal The number of keys stored within each group. */
+ #define LRU_ASSOC 3
+#else
+ #define LRU_ASSOC 4
+#endif
+/** @internal The number of hashes tracked within each group: 10-1 or 12-1. */
+#define LRU_TRACKED ((64 - sizeof(size_t) * LRU_ASSOC) / 4 - 1)
+
+struct lru_group {
+ uint16_t counts[LRU_TRACKED+1]; /*!< Occurrence counters; the last one is special. */
+ uint16_t hashes[LRU_TRACKED+1]; /*!< Top halves of hashes; the last one is unused. */
+ struct lru_item *items[LRU_ASSOC]; /*!< The full items. */
+} CACHE_ALIGNED;
+
+/* The sizes are chosen so lru_group just fits into a single x86 cache line. */
+static_assert(64 == sizeof(struct lru_group)
+ && 64 == LRU_ASSOC * sizeof(void*) + (LRU_TRACKED+1) * 4,
+ "bad sizing for your sizeof(void*)");
+
+struct lru {
+ struct knot_mm *mm, /**< Memory context to use for keys. */
+ *mm_array; /**< Memory context to use for this structure itself. */
+ uint log_groups; /**< Logarithm of the number of LRU groups. */
+ struct lru_group groups[] CACHE_ALIGNED; /**< The groups of items. */
+};
+
+/** @internal See lru_free. */
+static inline void lru_free_impl(struct lru *lru)
+{
+ if (!lru)
+ return;
+ lru_free_items_impl(lru);
+ mm_free(lru->mm_array, lru);
+}
+
+/** @internal See lru_reset. */
+static inline void lru_reset_impl(struct lru *lru)
+{
+ lru_free_items_impl(lru);
+ memset(lru->groups, 0, sizeof(lru->groups[0]) * (1 << lru->log_groups));
+}
+
+/** @internal See lru_capacity. */
+static inline uint lru_capacity_impl(struct lru *lru)
+{
+ assert(lru);
+ return (1 << lru->log_groups) * LRU_ASSOC;
+}
+
+/** @endcond */
+/** @} (addtogroup generics) */
diff --git a/lib/generic/map.c b/lib/generic/map.c
new file mode 100644
index 0000000..3e06520
--- /dev/null
+++ b/lib/generic/map.c
@@ -0,0 +1,354 @@
+/*
+ * critbit89 - A crit-bit tree implementation for strings in C89
+ * Written by Jonas Gehring <jonas@jgehring.net>
+ * Implemented key-value storing by Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * The code makes the assumption that malloc returns pointers aligned at at
+ * least a two-byte boundary. Since the C standard requires that malloc return
+ * pointers that can store any type, there are no commonly-used toolchains for
+ * which this assumption is false.
+ *
+ * See https://github.com/agl/critbit/blob/master/critbit.pdf for reference.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "map.h"
+#include "lib/utils.h"
+
+ /* Exports */
+#if defined _WIN32 || defined __CYGWIN__
+ #define EXPORT __attribute__ ((dllexport))
+#else
+ #define EXPORT __attribute__ ((visibility ("default")))
+#endif
+
+#ifdef _MSC_VER /* MSVC */
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int32 uint32_t;
+ #ifdef _WIN64
+ typedef signed __int64 intptr_t;
+ #else
+ typedef _W64 signed int intptr_t;
+ #endif
+#else /* Not MSVC */
+ #include <stdint.h>
+#endif
+
+typedef struct {
+ void* value;
+ uint8_t key[];
+} cb_data_t;
+
+typedef struct {
+ void *child[2];
+ uint32_t byte;
+ uint8_t otherbits;
+} cb_node_t;
+
+/* Return true if ptr is internal node. */
+static inline int ref_is_internal(const uint8_t *p)
+{
+ return 1 & (intptr_t)p;
+}
+
+/* Get internal node. */
+static inline cb_node_t *ref_get_internal(uint8_t *p)
+{
+ return (cb_node_t *)(p - 1);
+}
+
+/* Static helper functions */
+static void cbt_traverse_delete(map_t *map, void *top)
+{
+ uint8_t *p = top;
+ if (ref_is_internal(p)) {
+ cb_node_t *q = ref_get_internal(p);
+ cbt_traverse_delete(map, q->child[0]);
+ cbt_traverse_delete(map, q->child[1]);
+ mm_free(map->pool, q);
+ } else {
+ mm_free(map->pool, p);
+ }
+}
+
+static int cbt_traverse_prefixed(void *top,
+ int (*callback)(const char *, void *, void *), void *baton)
+{
+ uint8_t *p = top;
+ cb_data_t *x = (cb_data_t *)top;
+
+ if (ref_is_internal(p)) {
+ cb_node_t *q = ref_get_internal(p);
+ int ret = 0;
+
+ ret = cbt_traverse_prefixed(q->child[0], callback, baton);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = cbt_traverse_prefixed(q->child[1], callback, baton);
+ if (ret != 0) {
+ return ret;
+ }
+ return 0;
+ }
+
+ return (callback)((const char *)x->key, x->value, baton);
+}
+
+static cb_data_t *cbt_make_data(map_t *map, const uint8_t *str, size_t len, void *value)
+{
+ cb_data_t *x = mm_alloc(map->pool, sizeof(cb_data_t) + len);
+ if (x != NULL) {
+ x->value = value;
+ memcpy(x->key, str, len);
+ }
+ return x;
+}
+
+/*! Like map_contains, but also set the value, if passed and found. */
+static int cbt_get(map_t *map, const char *str, void **value)
+{
+ const uint8_t *ubytes = (void *)str;
+ const size_t ulen = strlen(str);
+ uint8_t *p = map->root;
+ cb_data_t *x = NULL;
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ while (ref_is_internal(p)) {
+ cb_node_t *q = ref_get_internal(p);
+ uint8_t c = 0;
+ int direction;
+
+ if (q->byte < ulen) {
+ c = ubytes[q->byte];
+ }
+ direction = (1 + (q->otherbits | c)) >> 8;
+
+ p = q->child[direction];
+ }
+
+ x = (cb_data_t *)p;
+ if (strcmp(str, (const char *)x->key) == 0) {
+ if (value != NULL) {
+ *value = x->value;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+/*! Returns non-zero if map contains str */
+EXPORT int map_contains(map_t *map, const char *str)
+{
+ return cbt_get(map, str, NULL);
+}
+
+EXPORT void *map_get(map_t *map, const char *str)
+{
+ void *v = NULL;
+ cbt_get(map, str, &v);
+ return v;
+}
+
+EXPORT int map_set(map_t *map, const char *str, void *val)
+{
+ const uint8_t *const ubytes = (void *)str;
+ const size_t ulen = strlen(str);
+ uint8_t *p = map->root;
+ uint8_t c = 0, *x = NULL;
+ uint32_t newbyte = 0;
+ uint32_t newotherbits = 0;
+ int direction = 0, newdirection = 0;
+ cb_node_t *newnode = NULL;
+ cb_data_t *data = NULL;
+ void **wherep = NULL;
+
+ if (p == NULL) {
+ map->root = cbt_make_data(map, (const uint8_t *)str, ulen + 1, val);
+ if (map->root == NULL) {
+ return ENOMEM;
+ }
+ return 0;
+ }
+
+ while (ref_is_internal(p)) {
+ cb_node_t *q = ref_get_internal(p);
+ c = 0;
+ if (q->byte < ulen) {
+ c = ubytes[q->byte];
+ }
+ direction = (1 + (q->otherbits | c)) >> 8;
+
+ p = q->child[direction];
+ }
+
+ data = (cb_data_t *)p;
+ for (newbyte = 0; newbyte < ulen; ++newbyte) {
+ if (data->key[newbyte] != ubytes[newbyte]) {
+ newotherbits = data->key[newbyte] ^ ubytes[newbyte];
+ goto different_byte_found;
+ }
+ }
+
+ if (data->key[newbyte] != 0) {
+ newotherbits = data->key[newbyte];
+ goto different_byte_found;
+ }
+ data->value = val;
+ return 1;
+
+different_byte_found:
+ newotherbits |= newotherbits >> 1;
+ newotherbits |= newotherbits >> 2;
+ newotherbits |= newotherbits >> 4;
+ newotherbits = (newotherbits & ~(newotherbits >> 1)) ^ 255;
+ c = data->key[newbyte];
+ newdirection = (1 + (newotherbits | c)) >> 8;
+
+ newnode = mm_alloc(map->pool, sizeof(cb_node_t));
+ if (newnode == NULL) {
+ return ENOMEM;
+ }
+
+ x = (uint8_t *)cbt_make_data(map, ubytes, ulen + 1, val);
+ if (x == NULL) {
+ mm_free(map->pool, newnode);
+ return ENOMEM;
+ }
+
+ newnode->byte = newbyte;
+ newnode->otherbits = newotherbits;
+ newnode->child[1 - newdirection] = x;
+
+ /* Insert into map */
+ wherep = &map->root;
+ for (;;) {
+ cb_node_t *q;
+ p = *wherep;
+ if (!ref_is_internal(p)) {
+ break;
+ }
+
+ q = ref_get_internal(p);
+ if (q->byte > newbyte) {
+ break;
+ }
+ if (q->byte == newbyte && q->otherbits > newotherbits) {
+ break;
+ }
+
+ c = 0;
+ if (q->byte < ulen) {
+ c = ubytes[q->byte];
+ }
+ direction = (1 + (q->otherbits | c)) >> 8;
+ wherep = q->child + direction;
+ }
+
+ newnode->child[newdirection] = *wherep;
+ *wherep = (void *)(1 + (char *)newnode);
+ return 0;
+}
+
+/*! Deletes str from the map, returns 0 on success */
+EXPORT int map_del(map_t *map, const char *str)
+{
+ const uint8_t *ubytes = (void *)str;
+ const size_t ulen = strlen(str);
+ uint8_t *p = map->root;
+ void **wherep = NULL, **whereq = NULL;
+ cb_node_t *q = NULL;
+ cb_data_t *data = NULL;
+ int direction = 0;
+
+ if (map->root == NULL) {
+ return 1;
+ }
+ wherep = &map->root;
+
+ while (ref_is_internal(p)) {
+ uint8_t c = 0;
+ whereq = wherep;
+ q = ref_get_internal(p);
+
+ if (q->byte < ulen) {
+ c = ubytes[q->byte];
+ }
+ direction = (1 + (q->otherbits | c)) >> 8;
+ wherep = q->child + direction;
+ p = *wherep;
+ }
+
+ data = (cb_data_t *)p;
+ if (strcmp(str, (const char *)data->key) != 0) {
+ return 1;
+ }
+ mm_free(map->pool, p);
+
+ if (!whereq) {
+ map->root = NULL;
+ return 0;
+ }
+
+ *whereq = q->child[1 - direction];
+ mm_free(map->pool, q);
+ return 0;
+}
+
+/*! Clears the given map */
+EXPORT void map_clear(map_t *map)
+{
+ if (map->root) {
+ cbt_traverse_delete(map, map->root);
+ }
+ map->root = NULL;
+}
+
+/*! Calls callback for all strings in map with the given prefix */
+EXPORT int map_walk_prefixed(map_t *map, const char *prefix,
+ int (*callback)(const char *, void *, void *), void *baton)
+{
+ if (!map) {
+ return 0;
+ }
+
+ const uint8_t *ubytes = (void *)prefix;
+ const size_t ulen = strlen(prefix);
+ uint8_t *p = map->root;
+ uint8_t *top = p;
+ cb_data_t *data = NULL;
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ while (ref_is_internal(p)) {
+ cb_node_t *q = ref_get_internal(p);
+ uint8_t c = 0;
+ int direction;
+
+ if (q->byte < ulen) {
+ c = ubytes[q->byte];
+ }
+ direction = (1 + (q->otherbits | c)) >> 8;
+
+ p = q->child[direction];
+ if (q->byte < ulen) {
+ top = p;
+ }
+ }
+
+ data = (cb_data_t *)p;
+ if (strlen((const char *)data->key) < ulen || memcmp(data->key, prefix, ulen) != 0) {
+ return 0; /* No strings match */
+ }
+
+ return cbt_traverse_prefixed(top, callback, baton);
+}
diff --git a/lib/generic/map.h b/lib/generic/map.h
new file mode 100644
index 0000000..73ce4c0
--- /dev/null
+++ b/lib/generic/map.h
@@ -0,0 +1,115 @@
+/*
+ * critbit89 - A crit-bit map implementation for strings in C89
+ * Written by Jonas Gehring <jonas@jgehring.net>
+ */
+
+/**
+ * @file map.h
+ * @brief A Crit-bit tree key-value map implementation.
+ *
+ * @warning If the user provides a custom allocator, it must return addresses aligned to 2B boundary.
+ *
+ * # Example usage:
+ *
+ * @code{.c}
+ * map_t map = map_make(NULL);
+ *
+ * // Custom allocator (optional)
+ * map.malloc = &mymalloc;
+ * map.baton = &mymalloc_context;
+ *
+ * // Insert k-v pairs
+ * int values = { 42, 53, 64 };
+ * if (map_set(&map, "princess", &values[0]) != 0 ||
+ * map_set(&map, "prince", &values[1]) != 0 ||
+ * map_set(&map, "leia", &values[2]) != 0) {
+ * fail();
+ * }
+ *
+ * // Test membership
+ * if (map_contains(&map, "leia")) {
+ * success();
+ * }
+ *
+ * // Prefix search
+ * int i = 0;
+ * int count(const char *k, void *v, void *ext) { (*(int *)ext)++; return 0; }
+ * if (map_walk_prefixed(map, "princ", count, &i) == 0) {
+ * printf("%d matches\n", i);
+ * }
+ *
+ * // Delete
+ * if (map_del(&map, "badkey") != 0) {
+ * fail(); // No such key
+ * }
+ *
+ * // Clear the map
+ * map_clear(&map);
+ * @endcode
+ *
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct knot_mm; /* avoid the unnecessary include */
+
+/** Main data structure */
+typedef struct {
+ void *root;
+ struct knot_mm *pool;
+} map_t;
+
+/** Creates an new empty critbit map. Pass NULL for malloc+free. */
+static inline map_t map_make(struct knot_mm *pool)
+{
+ return (map_t){ .root = NULL, .pool = pool };
+}
+
+/** Returns non-zero if map contains str */
+int map_contains(map_t *map, const char *str);
+
+/** Returns value if map contains str. Note: NULL may mean two different things. */
+void *map_get(map_t *map, const char *str);
+
+/** Inserts str into map. Returns 0 if new, 1 if replaced, or ENOMEM. */
+int map_set(map_t *map, const char *str, void *val);
+
+/** Deletes str from the map, returns 0 on suceess */
+int map_del(map_t *map, const char *str);
+
+/** Clears the given map */
+void map_clear(map_t *map);
+
+/**
+ * Calls callback for all strings in map
+ * See @fn map_walk_prefixed() for documentation on parameters.
+ */
+#define map_walk(map, callback, baton) \
+ map_walk_prefixed((map), "", (callback), (baton))
+
+/**
+ * Calls callback for all strings in map with the given prefix.
+ * Returns value immediately if a callback returns nonzero.
+ *
+ * @param map
+ * @param prefix required string prefix (empty => all strings)
+ * @param callback callback parameters are (key, value, baton)
+ * @param baton passed uservalue
+ */
+int map_walk_prefixed(map_t *map, const char *prefix,
+ int (*callback)(const char *, void *, void *), void *baton);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
diff --git a/lib/generic/pack.h b/lib/generic/pack.h
new file mode 100644
index 0000000..dc7a975
--- /dev/null
+++ b/lib/generic/pack.h
@@ -0,0 +1,249 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file pack.h
+ * @brief A length-prefixed list of objects, also an array list.
+ *
+ * Each object is prefixed by item length, unlike array this structure
+ * permits variable-length data. It is also equivallent to forward-only list
+ * backed by an array.
+ *
+ * @note Maximum object size is 2^16 bytes, see ::pack_objlen_t
+ * @TODO If some mistake happens somewhere, the access may end up in an infinite loop.
+ * (equality comparison on pointers)
+ *
+ * # Example usage:
+ *
+ * @code{.c}
+ * pack_t pack;
+ * pack_init(pack);
+ *
+ * // Reserve 2 objects, 6 bytes total
+ * pack_reserve(pack, 2, 4 + 2);
+ *
+ * // Push 2 objects
+ * pack_obj_push(pack, U8("jedi"), 4)
+ * pack_obj_push(pack, U8("\xbe\xef"), 2);
+ *
+ * // Iterate length-value pairs
+ * uint8_t *it = pack_head(pack);
+ * while (it != pack_tail(pack)) {
+ * uint8_t *val = pack_obj_val(it);
+ * it = pack_obj_next(it);
+ * }
+ *
+ * // Remove object
+ * pack_obj_del(pack, U8("jedi"), 4);
+ *
+ * pack_clear(pack);
+ * @endcode
+ *
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h>
+#include "array.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Packed object length type. */
+typedef uint16_t pack_objlen_t;
+
+/** Pack is defined as an array of bytes */
+typedef array_t(uint8_t) pack_t;
+
+/** Zero-initialize the pack. */
+#define pack_init(pack) \
+ array_init(pack)
+
+/** Make the pack empty and free pointed-to memory (plain malloc/free). */
+#define pack_clear(pack) \
+ array_clear(pack)
+
+/** Make the pack empty and free pointed-to memory.
+ * Mempool usage: pass mm_free and a knot_mm_t* . */
+#define pack_clear_mm(pack, free, baton) \
+ array_clear_mm((pack), (free), (baton))
+
+/** Reserve space for *additional* objects in the pack (plain malloc/free).
+ * @return 0 if success, <0 on failure */
+#define pack_reserve(pack, objs_count, objs_len) \
+ pack_reserve_mm((pack), (objs_count), (objs_len), array_std_reserve, NULL)
+
+/** Reserve space for *additional* objects in the pack.
+ * Mempool usage: pass kr_memreserve and a knot_mm_t* .
+ * @return 0 if success, <0 on failure */
+#define pack_reserve_mm(pack, objs_count, objs_len, reserve, baton) \
+ array_reserve_mm((pack), (pack).len + (sizeof(pack_objlen_t)*(objs_count) + (objs_len)), (reserve), (baton))
+
+/** Return pointer to first packed object.
+ *
+ * Recommended way to iterate:
+ * for (uint8_t *it = pack_head(pack); it != pack_tail(pack); it = pack_obj_next(it))
+ */
+#define pack_head(pack) \
+ ((pack).len > 0 ? &((pack).at[0]) : NULL)
+
+/** Return pack end pointer. */
+#define pack_tail(pack) \
+ ((pack).len > 0 ? &((pack).at[(pack).len]) : NULL)
+
+/** Return packed object length. */
+static inline pack_objlen_t pack_obj_len(uint8_t *it)
+{
+ pack_objlen_t len = 0;
+ if (it != NULL)
+ memcpy(&len, it, sizeof(len));
+ return len;
+}
+
+/** Return packed object value. */
+static inline uint8_t *pack_obj_val(uint8_t *it)
+{
+ if (it == NULL) {
+ assert(it);
+ return NULL;
+ }
+ return it + sizeof(pack_objlen_t);
+}
+
+/** Return pointer to next packed object. */
+static inline uint8_t *pack_obj_next(uint8_t *it)
+{
+ if (it == NULL) {
+ assert(it);
+ return NULL;
+ }
+ return pack_obj_val(it) + pack_obj_len(it);
+}
+
+/** Return pointer to the last packed object. */
+static inline uint8_t *pack_last(pack_t pack)
+{
+ if (pack.len == 0) {
+ return NULL;
+ }
+ uint8_t *it = pack_head(pack);
+ uint8_t *tail = pack_tail(pack);
+ while (true) {
+ uint8_t *next = pack_obj_next(it);
+ if (next == tail) {
+ return it;
+ }
+ it = next;
+ }
+}
+
+/** Push object to the end of the pack
+ * @return 0 on success, negative number on failure
+ */
+static inline int pack_obj_push(pack_t *pack, const uint8_t *obj, pack_objlen_t len)
+{
+ if (pack == NULL || obj == NULL) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ size_t packed_len = len + sizeof(len);
+ if (pack->len + packed_len > pack->cap) {
+ return kr_error(ENOSPC);
+ }
+
+ uint8_t *endp = pack->at + pack->len;
+ memcpy(endp, (char *)&len, sizeof(len));
+ memcpy(endp + sizeof(len), obj, len);
+ pack->len += packed_len;
+ return 0;
+}
+
+/** Returns a pointer to packed object.
+ * @return pointer to packed object or NULL
+ */
+static inline uint8_t *pack_obj_find(pack_t *pack, const uint8_t *obj, pack_objlen_t len)
+{
+ if (pack == NULL || obj == NULL) {
+ assert(obj != NULL);
+ return NULL;
+ }
+ uint8_t *endp = pack_tail(*pack);
+ uint8_t *it = pack_head(*pack);
+ while (it != endp) {
+ uint8_t *val = pack_obj_val(it);
+ if (pack_obj_len(it) == len && memcmp(obj, val, len) == 0) {
+ return it;
+ }
+ it = pack_obj_next(it);
+ }
+ return NULL;
+}
+
+/** Delete object from the pack
+ * @return 0 on success, negative number on failure
+ */
+static inline int pack_obj_del(pack_t *pack, const uint8_t *obj, pack_objlen_t len)
+{
+ if (pack == NULL || obj == NULL) {
+ assert(obj != NULL);
+ return kr_error(EINVAL);
+ }
+ uint8_t *endp = pack_tail(*pack);
+ uint8_t *it = pack_obj_find(pack, obj, len);
+ if (it) {
+ size_t packed_len = len + sizeof(len);
+ memmove(it, it + packed_len, endp - it - packed_len);
+ pack->len -= packed_len;
+ return 0;
+ }
+ return -1;
+}
+
+/** Clone a pack, replacing destination pack; (*dst == NULL) is valid input.
+ * @return kr_error(ENOMEM) on allocation failure. */
+static inline int pack_clone(pack_t **dst, const pack_t *src, knot_mm_t *pool)
+{
+ if (!dst || !src) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ /* Get a valid pack_t. */
+ if (!*dst) {
+ *dst = mm_alloc(pool, sizeof(pack_t));
+ if (!*dst) return kr_error(ENOMEM);
+ pack_init(**dst);
+ /* Clone data only if needed */
+ if (src->len == 0) return kr_ok();
+ }
+ /* Replace the contents of the pack_t. */
+ int ret = array_reserve_mm(**dst, src->len, kr_memreserve, pool);
+ if (ret < 0) {
+ return kr_error(ENOMEM);
+ }
+ memcpy((*dst)->at, src->at, src->len);
+ (*dst)->len = src->len;
+ return kr_ok();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
diff --git a/lib/generic/queue.c b/lib/generic/queue.c
new file mode 100644
index 0000000..45657c7
--- /dev/null
+++ b/lib/generic/queue.c
@@ -0,0 +1,124 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "lib/generic/queue.h"
+#include <string.h>
+
+KR_EXPORT void queue_init_impl(struct queue *q, size_t item_size)
+{
+ q->len = 0;
+ q->item_size = item_size;
+ q->head = q->tail = NULL;
+ /* Take 128 B (two x86 cache lines), except a small margin
+ * that the allocator can use for its overhead.
+ * Normally (64-bit pointers) this means 16 B header + 13*8 B data. */
+ q->chunk_cap = (128 - offsetof(struct queue_chunk, data)
+ - sizeof(size_t)
+ ) / item_size;
+ if (!q->chunk_cap) q->chunk_cap = 1; /* item_size big enough by itself */
+}
+
+KR_EXPORT void queue_deinit_impl(struct queue *q)
+{
+ assert(q);
+ struct queue_chunk *p = q->head;
+ while (p != NULL) {
+ struct queue_chunk *pf = p;
+ p = p->next;
+ free(pf);
+ }
+#ifndef NDEBUG
+ memset(q, 0, sizeof(*q));
+#endif
+}
+
+static struct queue_chunk * queue_chunk_new(const struct queue *q)
+{
+ struct queue_chunk *c = malloc(offsetof(struct queue_chunk, data)
+ + q->chunk_cap * q->item_size);
+ if (unlikely(!c)) abort(); // simplify stuff
+ memset(c, 0, offsetof(struct queue_chunk, data));
+ c->cap = q->chunk_cap;
+ /* ->begin and ->end are zero, i.e. we optimize for _push
+ * and not _push_head, by default. */
+ return c;
+}
+
+/* Return pointer to the space for the new element. */
+KR_EXPORT void * queue_push_impl(struct queue *q)
+{
+ assert(q);
+ struct queue_chunk *t = q->tail; // shorthand
+ if (unlikely(!t)) {
+ assert(!q->head && !q->len);
+ q->head = q->tail = t = queue_chunk_new(q);
+ } else
+ if (t->end == t->cap) {
+ if (t->begin * 2 >= t->cap) {
+ /* Utilization is below 50%, so let's shift (no overlap). */
+ memcpy(t->data, t->data + t->begin * q->item_size,
+ (t->end - t->begin) * q->item_size);
+ t->end -= t->begin;
+ t->begin = 0;
+ } else {
+ /* Let's grow the tail by another chunk. */
+ assert(!t->next);
+ t->next = queue_chunk_new(q);
+ t = q->tail = t->next;
+ }
+ }
+ assert(t->end < t->cap);
+ ++(q->len);
+ ++(t->end);
+ return t->data + q->item_size * (t->end - 1);
+}
+
+/* Return pointer to the space for the new element. */
+KR_EXPORT void * queue_push_head_impl(struct queue *q)
+{
+ /* When we have choice, we optimize for further _push_head,
+ * i.e. when shifting or allocating a chunk,
+ * we store items on the tail-end of the chunk. */
+ assert(q);
+ struct queue_chunk *h = q->head; // shorthand
+ if (unlikely(!h)) {
+ assert(!q->tail && !q->len);
+ h = q->head = q->tail = queue_chunk_new(q);
+ h->begin = h->end = h->cap;
+ } else
+ if (h->begin == 0) {
+ if (h->end * 2 <= h->cap) {
+ /* Utilization is below 50%, so let's shift (no overlap).
+ * Computations here are simplified due to h->begin == 0. */
+ const int cnt = h->end;
+ memcpy(h->data + (h->cap - cnt) * q->item_size, h->data,
+ cnt * q->item_size);
+ h->begin = h->cap - cnt;
+ h->end = h->cap;
+ } else {
+ /* Let's grow the head by another chunk. */
+ h = queue_chunk_new(q);
+ h->next = q->head;
+ q->head = h;
+ h->begin = h->end = h->cap;
+ }
+ }
+ assert(h->begin > 0);
+ --(h->begin);
+ ++(q->len);
+ return h->data + q->item_size * h->begin;
+}
+
diff --git a/lib/generic/queue.h b/lib/generic/queue.h
new file mode 100644
index 0000000..755e759
--- /dev/null
+++ b/lib/generic/queue.h
@@ -0,0 +1,260 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * @file queue.h
+ * @brief A queue, usable for FIFO and LIFO simultaneously.
+ *
+ * Both the head and tail of the queue can be accessed and pushed to,
+ * but only the head can be popped from.
+ *
+ * @note The implementation uses a singly linked list of blocks
+ * where each block stores an array of values (for better efficiency).
+ *
+ * Example usage:
+ * @code{.c}
+ // define new queue type, and init a new queue instance
+ typedef queue_t(int) queue_int_t;
+ queue_int_t q;
+ queue_init(q);
+ // do some operations
+ queue_push(q, 1);
+ queue_push(q, 2);
+ queue_push(q, 3);
+ queue_push(q, 4);
+ queue_pop(q);
+ assert(queue_head(q) == 2);
+ assert(queue_tail(q) == 4);
+
+ // you may iterate
+ typedef queue_it_t(int) queue_it_int_t;
+ for (queue_it_int_t it = queue_it_begin(q); !queue_it_finished(it);
+ queue_it_next(it)) {
+ ++queue_it_val(it);
+ }
+ assert(queue_tail(q) == 5);
+
+ queue_push_head(q, 0);
+ ++queue_tail(q);
+ assert(queue_tail(q) == 6);
+ // free it up
+ queue_deinit(q);
+
+ // you may use dynamic allocation for the type itself
+ queue_int_t *qm = malloc(sizeof(queue_int_t));
+ queue_init(*qm);
+ queue_deinit(*qm);
+ free(qm);
+ * @endcode
+ *
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+
+#include "lib/defines.h"
+#include "contrib/ucw/lib.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/** @brief The type for queue, parametrized by value type. */
+#define queue_t(type) \
+ union { \
+ type *pdata_t; /* only the *type* information is used */ \
+ struct queue queue; \
+ }
+
+/** @brief Initialize a queue. You can malloc() it the usual way. */
+#define queue_init(q) do { \
+ (void)(((__typeof__(((q).pdata_t)))0) == (void *)0); /* typecheck queue_t */ \
+ queue_init_impl(&(q).queue, sizeof(*(q).pdata_t)); \
+ } while (false)
+
+/** @brief De-initialize a queue: make it invalid and free any inner allocations. */
+#define queue_deinit(q) \
+ queue_deinit_impl(&(q).queue)
+
+/** @brief Push data to queue's tail. (Type-safe version; use _impl() otherwise.) */
+#define queue_push(q, data) \
+ *((__typeof__((q).pdata_t)) queue_push_impl(&(q).queue)) = data
+
+/** @brief Push data to queue's head. (Type-safe version; use _impl() otherwise.) */
+#define queue_push_head(q, data) \
+ *((__typeof__((q).pdata_t)) queue_push_head_impl(&(q).queue)) = data
+
+/** @brief Remove the element at the head.
+ * The queue must not be empty. */
+#define queue_pop(q) \
+ queue_pop_impl(&(q).queue)
+
+/** @brief Return a "reference" to the element at the head (it's an L-value).
+ * The queue must not be empty. */
+#define queue_head(q) \
+ ( *(__typeof__((q).pdata_t)) queue_head_impl(&(q).queue) )
+
+/** @brief Return a "reference" to the element at the tail (it's an L-value).
+ * The queue must not be empty. */
+#define queue_tail(q) \
+ ( *(__typeof__((q).pdata_t)) queue_tail_impl(&(q).queue) )
+
+/** @brief Return the number of elements in the queue (very efficient). */
+#define queue_len(q) \
+ ((const size_t)(q).queue.len)
+
+
+/** @brief Type for queue iterator, parametrized by value type.
+ * It's a simple structure that owns no other resources.
+ * You may NOT use it after doing any push or pop (without _begin again). */
+#define queue_it_t(type) \
+ union { \
+ type *pdata_t; /* only the *type* information is used */ \
+ struct queue_it iter; \
+ }
+
+/** @brief Initialize a queue iterator at the head of the queue.
+ * If you use this in assignment (instead of initialization),
+ * you will unfortunately need to add corresponding type-cast in front.
+ * Beware: there's no type-check between queue and iterator! */
+#define queue_it_begin(q) \
+ { .iter = queue_it_begin_impl(&(q).queue) }
+
+/** @brief Return a "reference" to the current element (it's an L-value) . */
+#define queue_it_val(it) \
+ ( *(__typeof__((it).pdata_t)) queue_it_val_impl(&(it).iter) )
+
+/** @brief Test if the iterator has gone past the last element.
+ * If it has, you may not use _val or _next. */
+#define queue_it_finished(it) \
+ queue_it_finished_impl(&(it).iter)
+
+/** @brief Advance the iterator to the next element. */
+#define queue_it_next(it) \
+ queue_it_next_impl(&(it).iter)
+
+
+
+/* ====================== Internal for the implementation ================== */
+/** @cond internal */
+
+struct queue;
+/* Non-inline functions are exported to be usable from daemon. */
+void queue_init_impl(struct queue *q, size_t item_size);
+void queue_deinit_impl(struct queue *q);
+void * queue_push_impl(struct queue *q);
+void * queue_push_head_impl(struct queue *q);
+
+struct queue_chunk;
+struct queue {
+ size_t len;
+ uint16_t chunk_cap, item_size;
+ struct queue_chunk *head, *tail;
+};
+
+struct queue_chunk {
+ struct queue_chunk *next; /*< head -> ... -> tail */
+ int16_t begin, end, cap, pad_; /*< indices: zero is closest to head */
+ /*< We could fit into uint8_t for example, but the choice of (3+1)*2 bytes
+ * is a compromise between wasting space and getting a good alignment.
+ * In particular, queue_t(type*) will store the pointers on addresses
+ * aligned to the pointer size, in both 64-bit and 32-bit platforms.
+ */
+ char data[];
+ /**< The item data. We use "char" to satisfy the C99+ aliasing rules.
+ * See C99 section 6.5 Expressions, paragraph 7.
+ * Any type can be accessed through char-pointer,
+ * so we can use a common struct definition
+ * for all types being held.
+ */
+};
+
+static inline void * queue_head_impl(const struct queue *q)
+{
+ assert(q);
+ struct queue_chunk *h = q->head;
+ if (unlikely(!h))
+ return NULL;
+ assert(h->end > h->begin);
+ return h->data + h->begin * q->item_size;
+}
+
+static inline void * queue_tail_impl(const struct queue *q)
+{
+ assert(q);
+ struct queue_chunk *t = q->tail;
+ if (unlikely(!t))
+ return NULL;
+ assert(t->end > t->begin);
+ return t->data + (t->end - 1) * q->item_size;
+}
+
+static inline void queue_pop_impl(struct queue *q)
+{
+ assert(q);
+ struct queue_chunk *h = q->head;
+ assert(h && h->end > h->begin);
+ if (h->end - h->begin == 1) {
+ /* removing the last element in the chunk */
+ q->head = h->next;
+ free(h);
+ } else {
+ ++(h->begin);
+ }
+ --(q->len);
+}
+
+
+struct queue_it {
+ struct queue_chunk *chunk;
+ int16_t pos, item_size;
+};
+
+static inline struct queue_it queue_it_begin_impl(struct queue *q)
+{
+ assert(q);
+ return (struct queue_it){
+ .chunk = q->head,
+ .pos = q->head ? q->head->begin : -1,
+ .item_size = q->item_size,
+ };
+}
+
+static inline bool queue_it_finished_impl(struct queue_it *it)
+{
+ return it->chunk == NULL || it->pos >= it->chunk->end;
+}
+
+static inline void * queue_it_val_impl(struct queue_it *it)
+{
+ assert(!queue_it_finished_impl(it));
+ return it->chunk->data + it->pos * it->item_size;
+}
+
+static inline void queue_it_next_impl(struct queue_it *it)
+{
+ assert(!queue_it_finished_impl(it));
+ ++(it->pos);
+ if (it->pos < it->chunk->end)
+ return;
+ it->chunk = it->chunk->next;
+ it->pos = it->chunk ? it->chunk->begin : -1;
+}
+
+/** @endcond (internal) */
+/** @} (addtogroup generics) */
+
diff --git a/lib/generic/set.h b/lib/generic/set.h
new file mode 100644
index 0000000..332c1aa
--- /dev/null
+++ b/lib/generic/set.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file set.h
+ * @brief A set abstraction implemented on top of map.
+ *
+ * @note The API is based on map.h, see it for more examples.
+ *
+ * # Example usage:
+ *
+ * @code{.c}
+ * set_t set = set_make(NULL);
+ *
+ * // Insert keys
+ * if (set_add(&set, "princess") != 0 ||
+ * set_add(&set, "prince") != 0 ||
+ * set_add(&set, "leia") != 0) {
+ * fail();
+ * }
+ *
+ * // Test membership
+ * if (set_contains(&set, "leia")) {
+ * success();
+ * }
+ *
+ * // Prefix search
+ * int i = 0;
+ * int count(const char *s, void *n) { (*(int *)n)++; return 0; }
+ * if (set_walk_prefixed(set, "princ", count, &i) == 0) {
+ * printf("%d matches\n", i);
+ * }
+ *
+ * // Delete
+ * if (set_del(&set, "badkey") != 0) {
+ * fail(); // No such key
+ * }
+ *
+ * // Clear the set
+ * set_clear(&set);
+ * @endcode
+ *
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include "map.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef map_t set_t;
+typedef int (set_walk_cb)(const char *, void *);
+
+/*! Creates an new, empty critbit set */
+#define set_make \
+ map_make
+
+/*! Returns non-zero if set contains str */
+#define set_contains(set, str) \
+ map_contains((set), (str))
+
+/*! Inserts str into set. Returns 0 if new, 1 if already present, or ENOMEM. */
+#define set_add(set, str) \
+ map_set((set), (str), (void *)1)
+
+/*! Deletes str from the set, returns 0 on suceess */
+#define set_del(set, str) \
+ map_del((set), (str))
+
+/*! Clears the given set */
+#define set_clear(set) \
+ map_clear(set)
+
+/*! Calls callback for all strings in map */
+#define set_walk(set, callback, baton) \
+ map_walk_prefixed((set), "", (callback), (baton))
+
+/*! Calls callback for all strings in set with the given prefix */
+#define set_walk_prefixed(set, prefix, callback, baton) \
+ map_walk_prefixed((set), (prefix), (callback), (baton))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
diff --git a/lib/generic/trie.c b/lib/generic/trie.c
new file mode 100644
index 0000000..0009eef
--- /dev/null
+++ b/lib/generic/trie.c
@@ -0,0 +1,912 @@
+/* Copyright (C) 2016-2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ The code originated from https://github.com/fanf2/qp/blob/master/qp.c
+ at revision 5f6d93753.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/generic/trie.h"
+#include "lib/utils.h"
+#include "contrib/ucw/lib.h"
+
+#if defined(__i386) || defined(__x86_64) || defined(_M_IX86) \
+ || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN) \
+ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+
+ /*!
+ * \brief Use a pointer alignment hack to save memory.
+ *
+ * When on, isbranch() relies on the fact that in leaf_t the first pointer
+ * is aligned on multiple of 4 bytes and that the flags bitfield is
+ * overlaid over the lowest two bits of that pointer.
+ * Neither is really guaranteed by the C standards; the second part should
+ * be OK with x86_64 ABI and most likely any other little-endian platform.
+ * It would be possible to manipulate the right bits portably, but it would
+ * complicate the code nontrivially. C++ doesn't even guarantee type-punning.
+ * In debug mode we check this works OK when creating a new trie instance.
+ */
+ #define FLAGS_HACK 1
+#else
+ #define FLAGS_HACK 0
+#endif
+
+typedef unsigned char byte;
+#ifndef uint
+typedef unsigned int uint;
+#define uint uint
+#endif
+typedef uint bitmap_t; /*! Bit-maps, using the range of 1<<0 to 1<<16 (inclusive). */
+
+typedef struct {
+ uint32_t len; // 32 bits are enough for key lengths; probably even 16 bits would be.
+ char chars[];
+} tkey_t;
+
+/*! \brief Leaf of trie. */
+typedef struct {
+ #if !FLAGS_HACK
+ byte flags;
+ #endif
+ tkey_t *key; /*!< The pointer must be aligned to 4-byte multiples! */
+ trie_val_t val;
+} leaf_t;
+
+/*! \brief A trie node is either leaf_t or branch_t. */
+typedef union node node_t;
+
+/*!
+ * \brief Branch node of trie.
+ *
+ * - The flags distinguish whether the node is a leaf_t (0), or a branch
+ * testing the more-important nibble (1) or the less-important one (2).
+ * - It stores the index of the byte that the node tests. The combined
+ * value (index*4 + flags) increases in branch nodes as you go deeper
+ * into the trie. All the keys below a branch are identical up to the
+ * nibble identified by the branch. Indices have to be stored because
+ * we skip any branch nodes that would have a single child.
+ * (Consequently, the skipped parts of key have to be validated in a leaf.)
+ * - The bitmap indicates which subtries are present. The present child nodes
+ * are stored in the twigs array (with no holes between them).
+ * - To simplify storing keys that are prefixes of each other, the end-of-string
+ * position is treated as another nibble value, ordered before all others.
+ * That affects the bitmap and twigs fields.
+ *
+ * \note The branch nodes are never allocated individually, but they are
+ * always part of either the root node or the twigs array of the parent.
+ */
+typedef struct {
+ #if FLAGS_HACK
+ uint32_t flags : 2,
+ bitmap : 17; /*!< The first bitmap bit is for end-of-string child. */
+ #else
+ byte flags;
+ uint32_t bitmap;
+ #endif
+ uint32_t index;
+ node_t *twigs;
+} branch_t;
+
+union node {
+ leaf_t leaf;
+ branch_t branch;
+};
+
+struct trie {
+ node_t root; // undefined when weight == 0, see empty_root()
+ size_t weight;
+ knot_mm_t mm;
+};
+
+/*! \brief Make the root node empty (debug-only). */
+static inline void empty_root(node_t *root) {
+#ifndef NDEBUG
+ *root = (node_t){ .branch = {
+ .flags = 3, // invalid value that fits
+ .bitmap = 0,
+ .index = -1,
+ .twigs = NULL
+ } };
+#endif
+}
+
+/*! \brief Check that unportable code works OK (debug-only). */
+static void assert_portability(void) {
+#if FLAGS_HACK
+ assert(((union node){ .leaf = {
+ .key = (tkey_t *)(((uint8_t *)NULL) + 1),
+ .val = NULL
+ } }).branch.flags == 1);
+#endif
+}
+
+/*! \brief Propagate error codes. */
+#define ERR_RETURN(x) \
+ do { \
+ int err_code_ = x; \
+ if (unlikely(err_code_ != KNOT_EOK)) \
+ return err_code_; \
+ } while (false)
+
+/*!
+ * \brief Count the number of set bits.
+ *
+ * \TODO This implementation may be relatively slow on some HW.
+ */
+static uint bitmap_weight(bitmap_t w)
+{
+ assert((w & ~((1 << 17) - 1)) == 0); // using the least-important 17 bits
+ return __builtin_popcount(w);
+}
+
+/*! \brief Only keep the lowest bit in the bitmap (least significant -> twigs[0]). */
+static bitmap_t bitmap_lowest_bit(bitmap_t w)
+{
+ assert((w & ~((1 << 17) - 1)) == 0); // using the least-important 17 bits
+ return 1 << __builtin_ctz(w);
+}
+
+/*! \brief Test flags to determine type of this node. */
+static bool isbranch(const node_t *t)
+{
+ uint f = t->branch.flags;
+ assert(f <= 2);
+ return f != 0;
+}
+
+/*! \brief Make a bitmask for testing a branch bitmap. */
+static bitmap_t nibbit(byte k, uint flags)
+{
+ uint shift = (2 - flags) << 2;
+ uint nibble = (k >> shift) & 0xf;
+ return 1 << (nibble + 1/*because of prefix keys*/);
+}
+
+/*! \brief Extract a nibble from a key and turn it into a bitmask. */
+static bitmap_t twigbit(const node_t *t, const char *key, uint32_t len)
+{
+ assert(isbranch(t));
+ uint i = t->branch.index;
+
+ if (i >= len)
+ return 1 << 0; // leaf position
+
+ return nibbit((byte)key[i], t->branch.flags);
+}
+
+/*! \brief Test if a branch node has a child indicated by a bitmask. */
+static bool hastwig(const node_t *t, bitmap_t bit)
+{
+ assert(isbranch(t));
+ return t->branch.bitmap & bit;
+}
+
+/*! \brief Compute offset of an existing child in a branch node. */
+static uint twigoff(const node_t *t, bitmap_t b)
+{
+ assert(isbranch(t));
+ return bitmap_weight(t->branch.bitmap & (b - 1));
+}
+
+/*! \brief Get pointer to a particular child of a branch node. */
+static node_t* twig(node_t *t, uint i)
+{
+ assert(isbranch(t));
+ return &t->branch.twigs[i];
+}
+
+/*!
+ * \brief For a branch nod, compute offset of a child and child count.
+ *
+ * Having this separate might be meaningful for performance optimization.
+ */
+#define TWIGOFFMAX(off, max, t, b) do { \
+ off = twigoff(t, b); \
+ max = bitmap_weight(t->branch.bitmap); \
+ } while(0)
+
+/*! \brief Simple string comparator. */
+static int key_cmp(const char *k1, uint32_t k1_len, const char *k2, uint32_t k2_len)
+{
+ int ret = memcmp(k1, k2, MIN(k1_len, k2_len));
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Key string is equal, compare lengths. */
+ if (k1_len == k2_len) {
+ return 0;
+ } else if (k1_len < k2_len) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+trie_t* trie_create(knot_mm_t *mm)
+{
+ assert_portability();
+ trie_t *trie = mm_alloc(mm, sizeof(trie_t));
+ if (trie != NULL) {
+ empty_root(&trie->root);
+ trie->weight = 0;
+ if (mm != NULL)
+ trie->mm = *mm;
+ else
+ mm_ctx_init(&trie->mm);
+ }
+ return trie;
+}
+
+/*! \brief Free anything under the trie node, except for the passed pointer itself. */
+static void clear_trie(node_t *trie, knot_mm_t *mm)
+{
+ if (!isbranch(trie)) {
+ mm_free(mm, trie->leaf.key);
+ } else {
+ branch_t *b = &trie->branch;
+ int len = bitmap_weight(b->bitmap);
+ for (int i = 0; i < len; ++i)
+ clear_trie(b->twigs + i, mm);
+ mm_free(mm, b->twigs);
+ }
+}
+
+void trie_free(trie_t *tbl)
+{
+ if (tbl == NULL)
+ return;
+ if (tbl->weight)
+ clear_trie(&tbl->root, &tbl->mm);
+ mm_free(&tbl->mm, tbl);
+}
+
+void trie_clear(trie_t *tbl)
+{
+ assert(tbl);
+ if (!tbl->weight)
+ return;
+ clear_trie(&tbl->root, &tbl->mm);
+ empty_root(&tbl->root);
+ tbl->weight = 0;
+}
+
+size_t trie_weight(const trie_t *tbl)
+{
+ assert(tbl);
+ return tbl->weight;
+}
+
+struct found {
+ leaf_t *l; /**< the found leaf (NULL if not found) */
+ branch_t *p; /**< the leaf's parent (if exists) */
+ bitmap_t b; /**< bit-mask with a single bit marking l under p */
+};
+/** Search trie for an item with the given key (equality only). */
+static struct found find_equal(trie_t *tbl, const char *key, uint32_t len)
+{
+ assert(tbl);
+ struct found ret0;
+ memset(&ret0, 0, sizeof(ret0));
+ if (!tbl->weight)
+ return ret0;
+ /* Current node and parent while descending (returned values basically). */
+ node_t *t = &tbl->root;
+ branch_t *p = NULL;
+ bitmap_t b = 0;
+ while (isbranch(t)) {
+ __builtin_prefetch(t->branch.twigs);
+ b = twigbit(t, key, len);
+ if (!hastwig(t, b))
+ return ret0;
+ p = &t->branch;
+ t = twig(t, twigoff(t, b));
+ }
+ if (key_cmp(key, len, t->leaf.key->chars, t->leaf.key->len) != 0)
+ return ret0;
+ return (struct found) {
+ .l = &t->leaf,
+ .p = p,
+ .b = b,
+ };
+}
+/** Find item with the first key (lexicographical order). */
+static struct found find_first(trie_t *tbl)
+{
+ assert(tbl);
+ if (!tbl->weight) {
+ struct found ret0;
+ memset(&ret0, 0, sizeof(ret0));
+ return ret0;
+ }
+ /* Current node and parent while descending (returned values basically). */
+ node_t *t = &tbl->root;
+ branch_t *p = NULL;
+ while (isbranch(t)) {
+ p = &t->branch;
+ t = &p->twigs[0];
+ }
+ return (struct found) {
+ .l = &t->leaf,
+ .p = p,
+ .b = p ? bitmap_lowest_bit(p->bitmap) : 0,
+ };
+}
+
+trie_val_t* trie_get_try(trie_t *tbl, const char *key, uint32_t len)
+{
+ struct found found = find_equal(tbl, key, len);
+ return found.l ? &found.l->val : NULL;
+}
+
+trie_val_t* trie_get_first(trie_t *tbl, char **key, uint32_t *len)
+{
+ struct found found = find_first(tbl);
+ if (!found.l)
+ return NULL;
+ if (key)
+ *key = found.l->key->chars;
+ if (len)
+ *len = found.l->key->len;
+ return &found.l->val;
+}
+
+/** Delete the found element (if any) and return value (unless NULL is passed) */
+static int del_found(trie_t *tbl, struct found found, trie_val_t *val)
+{
+ if (!found.l)
+ return KNOT_ENOENT;
+ mm_free(&tbl->mm, found.l->key);
+ if (val != NULL)
+ *val = found.l->val; // we return trie_val_t directly when deleting
+ --tbl->weight;
+ branch_t * const p = found.p; // short-hand
+ if (unlikely(!p)) { // whole trie was a single leaf
+ assert(tbl->weight == 0);
+ empty_root(&tbl->root);
+ return KNOT_EOK;
+ }
+ // remove leaf t as child of p; get child index via pointer arithmetic
+ int ci = ((union node *)found.l) - p->twigs,
+ cc = bitmap_weight(p->bitmap); // child count
+ assert(ci >= 0 && ci < cc);
+
+ if (cc == 2) { // collapse binary node p: move the other child to this node
+ node_t *twigs = p->twigs;
+ (*(union node *)p) = twigs[1 - ci]; // it might be a leaf or branch
+ mm_free(&tbl->mm, twigs);
+ return KNOT_EOK;
+ }
+ memmove(p->twigs + ci, p->twigs + ci + 1, sizeof(node_t) * (cc - ci - 1));
+ p->bitmap &= ~found.b;
+ node_t *twigs = mm_realloc(&tbl->mm, p->twigs, sizeof(node_t) * (cc - 1),
+ sizeof(node_t) * cc);
+ if (likely(twigs != NULL))
+ p->twigs = twigs;
+ /* We can ignore mm_realloc failure, only beware that next time
+ * the prev_size passed to it wouldn't be correct; TODO? */
+ return KNOT_EOK;
+}
+
+int trie_del(trie_t *tbl, const char *key, uint32_t len, trie_val_t *val)
+{
+ struct found found = find_equal(tbl, key, len);
+ return del_found(tbl, found, val);
+}
+
+int trie_del_first(trie_t *tbl, char *key, uint32_t *len, trie_val_t *val)
+{
+ struct found found = find_first(tbl);
+ if (!found.l)
+ return KNOT_ENOENT;
+ if (key) {
+ if (!len)
+ return KNOT_EINVAL;
+ if (*len < found.l->key->len)
+ return kr_error(ENOSPC);
+ memcpy(key, found.l->key->chars, found.l->key->len);
+ }
+ if (len) { // makes sense even with key == NULL
+ *len = found.l->key->len;
+ }
+ return del_found(tbl, found, val);
+}
+
+/*!
+ * \brief Stack of nodes, storing a path down a trie.
+ *
+ * The structure also serves directly as the public trie_it_t type,
+ * in which case it always points to the current leaf, unless we've finished
+ * (i.e. it->len == 0).
+ */
+typedef struct trie_it {
+ node_t* *stack; /*!< The stack; malloc is used directly instead of mm. */
+ uint32_t len; /*!< Current length of the stack. */
+ uint32_t alen; /*!< Allocated/available length of the stack. */
+ /*! \brief Initial storage for \a stack; it should fit in many use cases. */
+ node_t* stack_init[60];
+} nstack_t;
+
+/*! \brief Create a node stack containing just the root (or empty). */
+static void ns_init(nstack_t *ns, trie_t *tbl)
+{
+ assert(tbl);
+ ns->stack = ns->stack_init;
+ ns->alen = sizeof(ns->stack_init) / sizeof(ns->stack_init[0]);
+ if (tbl->weight) {
+ ns->len = 1;
+ ns->stack[0] = &tbl->root;
+ } else {
+ ns->len = 0;
+ }
+}
+
+/*! \brief Free inside of the stack, i.e. not the passed pointer itself. */
+static void ns_cleanup(nstack_t *ns)
+{
+ assert(ns && ns->stack);
+ if (likely(ns->stack == ns->stack_init))
+ return;
+ free(ns->stack);
+ #ifndef NDEBUG
+ ns->stack = NULL;
+ ns->alen = 0;
+ #endif
+}
+
+/*! \brief Allocate more space for the stack. */
+static int ns_longer_alloc(nstack_t *ns)
+{
+ ns->alen *= 2;
+ size_t new_size = sizeof(nstack_t) + ns->alen * sizeof(node_t *);
+ node_t **st;
+ if (ns->stack == ns->stack_init) {
+ st = malloc(new_size);
+ if (st != NULL)
+ memcpy(st, ns->stack, ns->len * sizeof(node_t *));
+ } else {
+ st = realloc(ns->stack, new_size);
+ }
+ if (st == NULL)
+ return KNOT_ENOMEM;
+ ns->stack = st;
+ return KNOT_EOK;
+}
+
+/*! \brief Ensure the node stack can be extended by one. */
+static inline int ns_longer(nstack_t *ns)
+{
+ // get a longer stack if needed
+ if (likely(ns->len < ns->alen))
+ return KNOT_EOK;
+ return ns_longer_alloc(ns); // hand-split the part suitable for inlining
+}
+
+/*!
+ * \brief Find the "branching point" as if searching for a key.
+ *
+ * The whole path to the point is kept on the passed stack;
+ * always at least the root will remain on the top of it.
+ * Beware: the precise semantics of this function is rather tricky.
+ * The top of the stack will contain: the corresponding leaf if exact match is found;
+ * or the immediate node below a branching-point-on-edge or the branching-point itself.
+ *
+ * \param info Set position of the point of first mismatch (in index and flags).
+ * \param first Set the value of the first non-matching character (from trie),
+ * optionally; end-of-string character has value -256 (that's why it's int).
+ * Note: the character is converted to *unsigned* char (i.e. 0..255),
+ * as that's the ordering used in the trie.
+ *
+ * \return KNOT_EOK or KNOT_ENOMEM.
+ */
+static int ns_find_branch(nstack_t *ns, const char *key, uint32_t len,
+ branch_t *info, int *first)
+{
+ assert(ns && ns->len && info);
+ // First find some leaf with longest matching prefix.
+ while (isbranch(ns->stack[ns->len - 1])) {
+ ERR_RETURN(ns_longer(ns));
+ node_t *t = ns->stack[ns->len - 1];
+ __builtin_prefetch(t->branch.twigs);
+ bitmap_t b = twigbit(t, key, len);
+ // Even if our key is missing from this branch we need to
+ // keep iterating down to a leaf. It doesn't matter which
+ // twig we choose since the keys are all the same up to this
+ // index. Note that blindly using twigoff(t, b) can cause
+ // an out-of-bounds index if it equals twigmax(t).
+ uint i = hastwig(t, b) ? twigoff(t, b) : 0;
+ ns->stack[ns->len++] = twig(t, i);
+ }
+ tkey_t *lkey = ns->stack[ns->len-1]->leaf.key;
+ // Find index of the first char that differs.
+ uint32_t index = 0;
+ while (index < MIN(len,lkey->len)) {
+ if (key[index] != lkey->chars[index])
+ break;
+ else
+ ++index;
+ }
+ info->index = index;
+ if (first)
+ *first = lkey->len > index ? (unsigned char)lkey->chars[index] : -256;
+ // Find flags: which half-byte has matched.
+ uint flags;
+ if (index == len && len == lkey->len) { // found equivalent key
+ info->flags = flags = 0;
+ goto success;
+ }
+ if (likely(index < MIN(len,lkey->len))) {
+ byte k2 = (byte)lkey->chars[index];
+ byte k1 = (byte)key[index];
+ flags = ((k1 ^ k2) & 0xf0) ? 1 : 2;
+ } else { // one is prefix of another
+ flags = 1;
+ }
+ info->flags = flags;
+ // now go up the trie from the current leaf
+ branch_t *t;
+ do {
+ if (unlikely(ns->len == 1))
+ goto success; // only the root stays on the stack
+ t = (branch_t*)ns->stack[ns->len - 2];
+ if (t->index < index || (t->index == index && t->flags < flags))
+ goto success;
+ --ns->len;
+ } while (true);
+success:
+ #ifndef NDEBUG // invariants on successful return
+ assert(ns->len);
+ if (isbranch(ns->stack[ns->len - 1])) {
+ t = &ns->stack[ns->len - 1]->branch;
+ assert(t->index > index || (t->index == index && t->flags >= flags));
+ }
+ if (ns->len > 1) {
+ t = &ns->stack[ns->len - 2]->branch;
+ assert(t->index < index || (t->index == index
+ && (t->flags < flags || (t->flags == 1 && flags == 0))));
+ }
+ #endif
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Advance the node stack to the last leaf in the subtree.
+ *
+ * \return KNOT_EOK or KNOT_ENOMEM.
+ */
+static int ns_last_leaf(nstack_t *ns)
+{
+ assert(ns);
+ do {
+ ERR_RETURN(ns_longer(ns));
+ node_t *t = ns->stack[ns->len - 1];
+ if (!isbranch(t))
+ return KNOT_EOK;
+ int lasti = bitmap_weight(t->branch.bitmap) - 1;
+ assert(lasti >= 0);
+ ns->stack[ns->len++] = twig(t, lasti);
+ } while (true);
+}
+
+/*!
+ * \brief Advance the node stack to the first leaf in the subtree.
+ *
+ * \return KNOT_EOK or KNOT_ENOMEM.
+ */
+static int ns_first_leaf(nstack_t *ns)
+{
+ assert(ns && ns->len);
+ do {
+ ERR_RETURN(ns_longer(ns));
+ node_t *t = ns->stack[ns->len - 1];
+ if (!isbranch(t))
+ return KNOT_EOK;
+ ns->stack[ns->len++] = twig(t, 0);
+ } while (true);
+}
+
+/*!
+ * \brief Advance the node stack to the leaf that is previous to the current node.
+ *
+ * \note Prefix leaf under the current node DOES count (if present; perhaps questionable).
+ * \return KNOT_EOK on success, KNOT_ENOENT on not-found, or possibly KNOT_ENOMEM.
+ */
+static int ns_prev_leaf(nstack_t *ns)
+{
+ assert(ns && ns->len > 0);
+
+ node_t *t = ns->stack[ns->len - 1];
+ if (hastwig(t, 1 << 0)) { // the prefix leaf
+ t = twig(t, 0);
+ ERR_RETURN(ns_longer(ns));
+ ns->stack[ns->len++] = t;
+ return KNOT_EOK;
+ }
+
+ do {
+ if (ns->len < 2)
+ return KNOT_ENOENT; // root without empty key has no previous leaf
+ t = ns->stack[ns->len - 1];
+ node_t *p = ns->stack[ns->len - 2];
+ int pindex = t - p->branch.twigs; // index in parent via pointer arithmetic
+ assert(pindex >= 0 && pindex <= 16);
+ if (pindex > 0) { // t isn't the first child -> go down the previous one
+ ns->stack[ns->len - 1] = twig(p, pindex - 1);
+ return ns_last_leaf(ns);
+ }
+ // we've got to go up again
+ --ns->len;
+ } while (true);
+}
+
+/*!
+ * \brief Advance the node stack to the leaf that is successor to the current node.
+ *
+ * \note Prefix leaf or anything else under the current node DOES count.
+ * \return KNOT_EOK on success, KNOT_ENOENT on not-found, or possibly KNOT_ENOMEM.
+ */
+static int ns_next_leaf(nstack_t *ns)
+{
+ assert(ns && ns->len > 0);
+
+ node_t *t = ns->stack[ns->len - 1];
+ if (isbranch(t))
+ return ns_first_leaf(ns);
+ do {
+ if (ns->len < 2)
+ return KNOT_ENOENT; // not found, as no more parent is available
+ t = ns->stack[ns->len - 1];
+ node_t *p = ns->stack[ns->len - 2];
+ int pindex = t - p->branch.twigs; // index in parent via pointer arithmetic
+ assert(pindex >= 0 && pindex <= 16);
+ int pcount = bitmap_weight(p->branch.bitmap);
+ if (pindex + 1 < pcount) { // t isn't the last child -> go down the next one
+ ns->stack[ns->len - 1] = twig(p, pindex + 1);
+ return ns_first_leaf(ns);
+ }
+ // we've got to go up again
+ --ns->len;
+ } while (true);
+}
+
+int trie_get_leq(trie_t *tbl, const char *key, uint32_t len, trie_val_t **val)
+{
+ assert(tbl && val);
+ *val = NULL; // so on failure we can just return;
+ if (tbl->weight == 0)
+ return KNOT_ENOENT;
+ { // Intentionally un-indented; until end of function, to bound cleanup attr.
+ // First find a key with longest-matching prefix
+ __attribute__((cleanup(ns_cleanup)))
+ nstack_t ns_local;
+ ns_init(&ns_local, tbl);
+ nstack_t *ns = &ns_local;
+ branch_t bp;
+ int un_leaf; // first unmatched character in the leaf
+ ERR_RETURN(ns_find_branch(ns, key, len, &bp, &un_leaf));
+ int un_key = bp.index < len ? (unsigned char)key[bp.index] : -256;
+ node_t *t = ns->stack[ns->len - 1];
+ if (bp.flags == 0) { // found exact match
+ *val = &t->leaf.val;
+ return KNOT_EOK;
+ }
+ // Get t: the last node on matching path
+ if (isbranch(t) && t->branch.index == bp.index && t->branch.flags == bp.flags) {
+ // t is OK
+ } else {
+ // the top of the stack was the first unmatched node -> step up
+ if (ns->len == 1) {
+ // root was unmatched already
+ if (un_key < un_leaf)
+ return KNOT_ENOENT;
+ ERR_RETURN(ns_last_leaf(ns));
+ goto success;
+ }
+ --ns->len;
+ t = ns->stack[ns->len - 1];
+ }
+ // Now we re-do the first "non-matching" step in the trie
+ // but try the previous child if key was less (it may not exist)
+ bitmap_t b = twigbit(t, key, len);
+ int i = hastwig(t, b)
+ ? twigoff(t, b) - (un_key < un_leaf)
+ : twigoff(t, b) - 1 /*twigoff returns successor when !hastwig*/;
+ if (i >= 0) {
+ ERR_RETURN(ns_longer(ns));
+ ns->stack[ns->len++] = twig(t, i);
+ ERR_RETURN(ns_last_leaf(ns));
+ } else {
+ ERR_RETURN(ns_prev_leaf(ns));
+ }
+success:
+ assert(!isbranch(ns->stack[ns->len - 1]));
+ *val = &ns->stack[ns->len - 1]->leaf.val;
+ return 1;
+ }
+}
+
+/*! \brief Initialize a new leaf, copying the key, and returning failure code. */
+static int mk_leaf(node_t *leaf, const char *key, uint32_t len, knot_mm_t *mm)
+{
+ tkey_t *k = mm_alloc(mm, sizeof(tkey_t) + len);
+ #if FLAGS_HACK
+ assert(((uintptr_t)k) % 4 == 0); // we need an aligned pointer
+ #endif
+ if (unlikely(!k))
+ return KNOT_ENOMEM;
+ k->len = len;
+ memcpy(k->chars, key, len);
+ leaf->leaf = (leaf_t){
+ #if !FLAGS_HACK
+ .flags = 0,
+ #endif
+ .val = NULL,
+ .key = k
+ };
+ return KNOT_EOK;
+}
+
+trie_val_t* trie_get_ins(trie_t *tbl, const char *key, uint32_t len)
+{
+ assert(tbl);
+ // First leaf in an empty tbl?
+ if (unlikely(!tbl->weight)) {
+ if (unlikely(mk_leaf(&tbl->root, key, len, &tbl->mm)))
+ return NULL;
+ ++tbl->weight;
+ return &tbl->root.leaf.val;
+ }
+ { // Intentionally un-indented; until end of function, to bound cleanup attr.
+ // Find the branching-point
+ __attribute__((cleanup(ns_cleanup)))
+ nstack_t ns_local;
+ ns_init(&ns_local, tbl);
+ nstack_t *ns = &ns_local;
+ branch_t bp; // branch-point: index and flags signifying the longest common prefix
+ int k2; // the first unmatched character in the leaf
+ if (unlikely(ns_find_branch(ns, key, len, &bp, &k2)))
+ return NULL;
+ node_t *t = ns->stack[ns->len - 1];
+ if (bp.flags == 0) // the same key was already present
+ return &t->leaf.val;
+ node_t leaf;
+ if (unlikely(mk_leaf(&leaf, key, len, &tbl->mm)))
+ return NULL;
+
+ if (isbranch(t) && bp.index == t->branch.index && bp.flags == t->branch.flags) {
+ // The node t needs a new leaf child.
+ bitmap_t b1 = twigbit(t, key, len);
+ assert(!hastwig(t, b1));
+ uint s, m; TWIGOFFMAX(s, m, t, b1); // new child position and original child count
+ node_t *twigs = mm_realloc(&tbl->mm, t->branch.twigs,
+ sizeof(node_t) * (m + 1), sizeof(node_t) * m);
+ if (unlikely(!twigs))
+ goto err_leaf;
+ memmove(twigs + s + 1, twigs + s, sizeof(node_t) * (m - s));
+ twigs[s] = leaf;
+ t->branch.twigs = twigs;
+ t->branch.bitmap |= b1;
+ ++tbl->weight;
+ return &twigs[s].leaf.val;
+ } else {
+ // We need to insert a new binary branch with leaf at *t.
+ // Note: it works the same for the case where we insert above root t.
+ #ifndef NDEBUG
+ if (ns->len > 1) {
+ node_t *pt = ns->stack[ns->len - 2];
+ assert(hastwig(pt, twigbit(pt, key, len)));
+ }
+ #endif
+ node_t *twigs = mm_alloc(&tbl->mm, sizeof(node_t) * 2);
+ if (unlikely(!twigs))
+ goto err_leaf;
+ node_t t2 = *t; // Save before overwriting t.
+ t->branch.flags = bp.flags;
+ t->branch.index = bp.index;
+ t->branch.twigs = twigs;
+ bitmap_t b1 = twigbit(t, key, len);
+ bitmap_t b2 = unlikely(k2 == -256) ? (1 << 0) : nibbit(k2, bp.flags);
+ t->branch.bitmap = b1 | b2;
+ *twig(t, twigoff(t, b1)) = leaf;
+ *twig(t, twigoff(t, b2)) = t2;
+ ++tbl->weight;
+ return &twig(t, twigoff(t, b1))->leaf.val;
+ };
+err_leaf:
+ mm_free(&tbl->mm, leaf.leaf.key);
+ return NULL;
+ }
+}
+
+/*! \brief Apply a function to every trie_val_t*, in order; a recursive solution. */
+static int apply_trie(node_t *t, int (*f)(trie_val_t *, void *), void *d)
+{
+ assert(t);
+ if (!isbranch(t))
+ return f(&t->leaf.val, d);
+ int child_count = bitmap_weight(t->branch.bitmap);
+ for (int i = 0; i < child_count; ++i)
+ ERR_RETURN(apply_trie(twig(t, i), f, d));
+ return KNOT_EOK;
+}
+
+int trie_apply(trie_t *tbl, int (*f)(trie_val_t *, void *), void *d)
+{
+ assert(tbl && f);
+ if (!tbl->weight)
+ return KNOT_EOK;
+ return apply_trie(&tbl->root, f, d);
+}
+
+/* These are all thin wrappers around static Tns* functions. */
+trie_it_t* trie_it_begin(trie_t *tbl)
+{
+ assert(tbl);
+ trie_it_t *it = malloc(sizeof(nstack_t));
+ if (!it)
+ return NULL;
+ ns_init(it, tbl);
+ if (it->len == 0) // empty tbl
+ return it;
+ if (ns_first_leaf(it)) {
+ ns_cleanup(it);
+ free(it);
+ return NULL;
+ }
+ return it;
+}
+
+void trie_it_next(trie_it_t *it)
+{
+ assert(it && it->len);
+ if (ns_next_leaf(it) != KNOT_EOK)
+ it->len = 0;
+}
+
+bool trie_it_finished(trie_it_t *it)
+{
+ assert(it);
+ return it->len == 0;
+}
+
+void trie_it_free(trie_it_t *it)
+{
+ if (!it)
+ return;
+ ns_cleanup(it);
+ free(it);
+}
+
+const char* trie_it_key(trie_it_t *it, size_t *len)
+{
+ assert(it && it->len);
+ node_t *t = it->stack[it->len - 1];
+ assert(!isbranch(t));
+ tkey_t *key = t->leaf.key;
+ if (len)
+ *len = key->len;
+ return key->chars;
+}
+
+trie_val_t* trie_it_val(trie_it_t *it)
+{
+ assert(it && it->len);
+ node_t *t = it->stack[it->len - 1];
+ assert(!isbranch(t));
+ return &t->leaf.val;
+}
diff --git a/lib/generic/trie.h b/lib/generic/trie.h
new file mode 100644
index 0000000..0550e95
--- /dev/null
+++ b/lib/generic/trie.h
@@ -0,0 +1,150 @@
+/* Copyright (C) 2017-2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <libknot/mm_ctx.h>
+#include "lib/defines.h"
+
+/*!
+ * \brief Native API of QP-tries:
+ *
+ * - keys are char strings, not necessarily zero-terminated,
+ * the structure copies the contents of the passed keys
+ * - values are void* pointers, typically you get an ephemeral pointer to it
+ * - key lengths are limited by 2^32-1 ATM
+ *
+ * XXX EDITORS: trie.{h,c} are synced from
+ * https://gitlab.labs.nic.cz/knot/knot-dns/tree/68352fc969/src/contrib/qp-trie
+ * only with tiny adjustments, mostly #includes and KR_EXPORT.
+ */
+
+/*! \brief Element value. */
+typedef void* trie_val_t;
+
+/*! \brief Opaque structure holding a QP-trie. */
+typedef struct trie trie_t;
+
+/*! \brief Opaque type for holding a QP-trie iterator. */
+typedef struct trie_it trie_it_t;
+
+/*! \brief Create a trie instance. Pass NULL to use malloc+free. */
+KR_EXPORT
+trie_t* trie_create(knot_mm_t *mm);
+
+/*! \brief Free a trie instance. */
+KR_EXPORT
+void trie_free(trie_t *tbl);
+
+/*! \brief Clear a trie instance (make it empty). */
+KR_EXPORT
+void trie_clear(trie_t *tbl);
+
+/*! \brief Return the number of keys in the trie. */
+KR_EXPORT
+size_t trie_weight(const trie_t *tbl);
+
+/*! \brief Search the trie, returning NULL on failure. */
+KR_EXPORT
+trie_val_t* trie_get_try(trie_t *tbl, const char *key, uint32_t len);
+
+/*!
+ * \brief Return pointer to the minimum. Optionally with key and its length. */
+KR_EXPORT
+trie_val_t* trie_get_first(trie_t *tbl, char **key, uint32_t *len);
+
+/*! \brief Search the trie, inserting NULL trie_val_t on failure. */
+KR_EXPORT
+trie_val_t* trie_get_ins(trie_t *tbl, const char *key, uint32_t len);
+
+/*!
+ * \brief Search for less-or-equal element.
+ *
+ * \param tbl Trie.
+ * \param key Searched key.
+ * \param len Key length.
+ * \param val Must be valid; it will be set to NULL if not found or errored.
+ * \return KNOT_EOK for exact match, 1 for previous, KNOT_ENOENT for not-found,
+ * or KNOT_E*.
+ */
+KR_EXPORT
+int trie_get_leq(trie_t *tbl, const char *key, uint32_t len, trie_val_t **val);
+
+/*!
+ * \brief Apply a function to every trie_val_t, in order.
+ *
+ * \param d Parameter passed as the second argument to f().
+ * \return First nonzero from f() or zero (i.e. KNOT_EOK).
+ */
+int trie_apply(trie_t *tbl, int (*f)(trie_val_t *, void *), void *d);
+
+/*!
+ * \brief Remove an item, returning KNOT_EOK if succeeded or KNOT_ENOENT if not found.
+ *
+ * If val!=NULL and deletion succeeded, the deleted value is set.
+ */
+KR_EXPORT
+int trie_del(trie_t *tbl, const char *key, uint32_t len, trie_val_t *val);
+
+/*!
+ * \brief Remove the first item, returning KNOT_EOK on success.
+ *
+ * You may optionally get the key and/or value.
+ * The key is copied, so you need to pass sufficient len,
+ * otherwise kr_error(ENOSPC) is returned.
+ */
+KR_EXPORT
+int trie_del_first(trie_t *tbl, char *key, uint32_t *len, trie_val_t *val);
+
+/*! \brief Create a new iterator pointing to the first element (if any). */
+KR_EXPORT
+trie_it_t* trie_it_begin(trie_t *tbl);
+
+/*!
+ * \brief Advance the iterator to the next element.
+ *
+ * Iteration is in ascending lexicographical order.
+ * In particular, the empty string would be considered as the very first.
+ *
+ * \note You may not use this function if the trie's key-set has been modified
+ * during the lifetime of the iterator (modifying values only is OK).
+ */
+KR_EXPORT
+void trie_it_next(trie_it_t *it);
+
+/*! \brief Test if the iterator has gone past the last element. */
+KR_EXPORT
+bool trie_it_finished(trie_it_t *it);
+
+/*! \brief Free any resources of the iterator. It's OK to call it on NULL. */
+KR_EXPORT
+void trie_it_free(trie_it_t *it);
+
+/*!
+ * \brief Return pointer to the key of the current element.
+ *
+ * \note The optional len is uint32_t internally but size_t is better for our usage,
+ * as it is without an additional type conversion.
+ */
+KR_EXPORT
+const char* trie_it_key(trie_it_t *it, size_t *len);
+
+/*! \brief Return pointer to the value of the current element (writable). */
+KR_EXPORT
+trie_val_t* trie_it_val(trie_it_t *it);
diff --git a/lib/layer.h b/lib/layer.h
new file mode 100644
index 0000000..0909cb7
--- /dev/null
+++ b/lib/layer.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+
+#ifdef NOVERBOSELOG
+ #define QRVERBOSE(query, cls, ...)
+#else
+ /** Print a debug message related to resolution.
+ * \param _query associated kr_query, may be NULL
+ * \param _cls identifying string, typically of length exactly four (padded)
+ * \param ... printf-compatible list of parameters
+ */
+ #define QRVERBOSE(_query, _cls, ...) do { \
+ const struct kr_query *_qry = (_query); \
+ if (kr_log_trace_enabled(_qry)) { \
+ kr_log_trace(_qry, (_cls), __VA_ARGS__); \
+ } else if (VERBOSE_STATUS) { \
+ kr_log_qverbose_impl(_qry, (_cls), __VA_ARGS__); \
+ } \
+ } while (false)
+#endif
+
+/** Layer processing states. Only one value at a time (but see TODO).
+ *
+ * Each state represents the state machine transition,
+ * and determines readiness for the next action.
+ * See struct kr_layer_api for the actions.
+ *
+ * TODO: the cookie module sometimes sets (_FAIL | _DONE) on purpose (!)
+ */
+enum kr_layer_state {
+ KR_STATE_CONSUME = 1 << 0, /*!< Consume data. */
+ KR_STATE_PRODUCE = 1 << 1, /*!< Produce data. */
+ KR_STATE_DONE = 1 << 2, /*!< Finished successfully. */
+ KR_STATE_FAIL = 1 << 3, /*!< Error. */
+ KR_STATE_YIELD = 1 << 4, /*!< Paused, waiting for a sub-query. */
+};
+
+/* Forward declarations. */
+struct kr_layer_api;
+
+/** Packet processing context. */
+typedef struct kr_layer {
+ int state; /*!< The current state; bitmap of enum kr_layer_state. */
+ struct kr_request *req; /*!< The corresponding request. */
+ const struct kr_layer_api *api;
+} kr_layer_t;
+
+/** Packet processing module API. All functions return the new kr_layer_state. */
+struct kr_layer_api {
+ /** Start of processing the DNS request. */
+ int (*begin)(kr_layer_t *ctx);
+
+ int (*reset)(kr_layer_t *ctx);
+
+ /** Paired to begin, called both on successes and failures. */
+ int (*finish)(kr_layer_t *ctx);
+
+ /** Processing an answer from upstream or the answer to the request. */
+ int (*consume)(kr_layer_t *ctx, knot_pkt_t *pkt);
+
+ /** Produce either an answer to the request or a query for upstream (or fail). */
+ int (*produce)(kr_layer_t *ctx, knot_pkt_t *pkt);
+
+ /** Finalises the outbound query packet with the knowledge of the IP addresses.
+ * The checkout layer doesn't persist the state, so canceled subrequests
+ * don't affect the resolution or rest of the processing. */
+ int (*checkout)(kr_layer_t *ctx, knot_pkt_t *packet, struct sockaddr *dst, int type);
+
+ /** Finalises the answer.
+ * Last chance to affect what will get into the answer, including EDNS.*/
+ int (*answer_finalize)(kr_layer_t *ctx);
+
+ /** The module can store anything in here. */
+ void *data;
+
+ /** Internal to ./daemon/ffimodule.c. */
+ int cb_slots[];
+};
+
+typedef struct kr_layer_api kr_layer_api_t;
+
+/** Pickled layer state (api, input, state). */
+struct kr_layer_pickle {
+ struct kr_layer_pickle *next;
+ const struct kr_layer_api *api;
+ knot_pkt_t *pkt;
+ unsigned state;
+};
+
diff --git a/lib/layer/cache.c b/lib/layer/cache.c
new file mode 100644
index 0000000..c7bbc1a
--- /dev/null
+++ b/lib/layer/cache.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/module.h"
+#include "lib/cache/api.h"
+
+/** Module implementation. */
+const kr_layer_api_t *cache_layer(struct kr_module *module)
+{
+ static const kr_layer_api_t _layer = {
+ .produce = &cache_peek,
+ .consume = &cache_stash,
+ };
+
+ return &_layer;
+}
+
+KR_MODULE_EXPORT(cache)
diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c
new file mode 100644
index 0000000..cf57cc5
--- /dev/null
+++ b/lib/layer/iterate.c
@@ -0,0 +1,1135 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file iterate.c
+ *
+ * This builtin module is mainly active in the consume phase.
+ * Primary responsibilities:
+ * - Classify the packet as auth/nonauth and change its AA flag accordingly.
+ * - Pick interesting RRs to kr_request::answ_selected and ::auth_selected,
+ * NEW: and classify their rank, except for validation status.
+ * - Update kr_query::zone_cut (in case of referral).
+ * - Interpret CNAMEs.
+ * - Prepare the followup query - either inline or as another kr_query
+ * (CNAME jumps create a new "sibling" query).
+ */
+
+#include <sys/time.h>
+#include <assert.h>
+#include <arpa/inet.h>
+
+#include <contrib/cleanup.h>
+#include <libknot/descriptor.h>
+#include <libknot/rrtype/rdname.h>
+#include <libknot/rrtype/rrsig.h>
+
+#include "lib/layer/iterate.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+#include "lib/defines.h"
+#include "lib/nsrep.h"
+#include "lib/module.h"
+#include "lib/dnssec/ta.h"
+
+#define VERBOSE_MSG(...) QRVERBOSE(req->current_query, "iter", __VA_ARGS__)
+#define QVERBOSE_MSG(qry, ...) QRVERBOSE(qry, "iter", __VA_ARGS__)
+
+/* Iterator often walks through packet section, this is an abstraction. */
+typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_request *);
+
+/** Return minimized QNAME/QTYPE for current zone cut. */
+static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qtype)
+{
+ /* Minimization disabled. */
+ const knot_dname_t *qname = query->sname;
+ if (qname[0] == '\0' || query->flags.NO_MINIMIZE || query->flags.STUB) {
+ return qname;
+ }
+
+ /* Minimize name to contain current zone cut + 1 label. */
+ int cut_labels = knot_dname_labels(query->zone_cut.name, NULL);
+ int qname_labels = knot_dname_labels(qname, NULL);
+ while(qname[0] && qname_labels > cut_labels + 1) {
+ qname = knot_wire_next_label(qname, NULL);
+ qname_labels -= 1;
+ }
+
+ /* Hide QTYPE if minimized. */
+ if (qname != query->sname) {
+ *qtype = KNOT_RRTYPE_NS;
+ }
+
+ return qname;
+}
+
+/** Answer is paired to query. */
+static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
+{
+ uint16_t qtype = query->stype;
+ const knot_dname_t *qname = minimized_qname(query, &qtype);
+
+ return query->id == knot_wire_get_id(answer->wire) &&
+ knot_wire_get_qdcount(answer->wire) > 0 &&
+ query->sclass == knot_pkt_qclass(answer) &&
+ qtype == knot_pkt_qtype(answer) &&
+ knot_dname_is_equal(qname, knot_pkt_qname(answer));
+}
+
+/** Relaxed rule for AA, either AA=1 or SOA matching zone cut is required. */
+static bool is_authoritative(const knot_pkt_t *answer, struct kr_query *query)
+{
+ if (knot_wire_get_aa(answer->wire)) {
+ return true;
+ }
+
+ const knot_pktsection_t *ns = knot_pkt_section(answer, KNOT_AUTHORITY);
+ for (unsigned i = 0; i < ns->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(ns, i);
+ if (rr->type == KNOT_RRTYPE_SOA
+ && knot_dname_in_bailiwick(rr->owner, query->zone_cut.name) >= 0) {
+ return true;
+ }
+ }
+
+#ifndef STRICT_MODE
+ /* Last resort to work around broken auths, if the zone cut is at/parent of the QNAME. */
+ if (knot_dname_is_equal(query->zone_cut.name, knot_pkt_qname(answer))) {
+ return true;
+ }
+#endif
+
+ /* Some authoritative servers are hopelessly broken, allow lame answers in permissive mode. */
+ if (query->flags.PERMISSIVE) {
+ return true;
+ }
+
+ return false;
+}
+
+int kr_response_classify(const knot_pkt_t *pkt)
+{
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ switch (knot_wire_get_rcode(pkt->wire)) {
+ case KNOT_RCODE_NOERROR:
+ return (an->count == 0) ? PKT_NODATA : PKT_NOERROR;
+ case KNOT_RCODE_NXDOMAIN:
+ return PKT_NXDOMAIN;
+ case KNOT_RCODE_REFUSED:
+ return PKT_REFUSED;
+ default:
+ return PKT_ERROR;
+ }
+}
+
+/** @internal Filter ANY or loopback addresses. */
+static bool is_valid_addr(const uint8_t *addr, size_t len)
+{
+ if (len == sizeof(struct in_addr)) {
+ /* Filter ANY and 127.0.0.0/8 */
+ uint32_t ip_host = ntohl(*(const uint32_t *)(addr));
+ if (ip_host == 0 || (ip_host & 0xff000000) == 0x7f000000) {
+ return false;
+ }
+ } else if (len == sizeof(struct in6_addr)) {
+ struct in6_addr ip6_mask;
+ memset(&ip6_mask, 0, sizeof(ip6_mask));
+ /* All except last byte are zeroed, last byte defines ANY/::1 */
+ if (memcmp(addr, ip6_mask.s6_addr, sizeof(ip6_mask.s6_addr) - 1) == 0) {
+ return (addr[len - 1] > 1);
+ }
+ }
+ return true;
+}
+
+/** @internal Update NS address from record \a rr. Return _FAIL on error. */
+static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query, int *glue_cnt)
+{
+ if (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA) {
+ const knot_rdata_t *rdata = rr->rrs.rdata;
+ const int a_len = rr->type == KNOT_RRTYPE_A
+ ? sizeof(struct in_addr) : sizeof(struct in6_addr);
+ if (a_len != rdata->len) {
+ QVERBOSE_MSG(query, "<= ignoring invalid glue, length %d != %d\n",
+ (int)rdata->len, a_len);
+ return KR_STATE_FAIL;
+ }
+ char name_str[KR_DNAME_STR_MAXLEN];
+ char addr_str[INET6_ADDRSTRLEN];
+ WITH_VERBOSE(query) {
+ const int af = (rr->type == KNOT_RRTYPE_A) ? AF_INET : AF_INET6;
+ knot_dname_to_str(name_str, rr->owner, sizeof(name_str));
+ name_str[sizeof(name_str) - 1] = 0;
+ inet_ntop(af, rdata->data, addr_str, sizeof(addr_str));
+ }
+ if (!(query->flags.ALLOW_LOCAL) &&
+ !is_valid_addr(rdata->data, rdata->len)) {
+ QVERBOSE_MSG(query, "<= ignoring invalid glue for "
+ "'%s': '%s'\n", name_str, addr_str);
+ return KR_STATE_CONSUME; /* Ignore invalid addresses */
+ }
+ int ret = kr_zonecut_add(&query->zone_cut, rr->owner, rdata->data, rdata->len);
+ if (ret != 0) {
+ return KR_STATE_FAIL;
+ }
+
+ ++*glue_cnt; /* reduced verbosity */
+ /* QVERBOSE_MSG(query, "<= using glue for "
+ "'%s': '%s'\n", name_str, addr_str);
+ */
+ }
+ return KR_STATE_CONSUME;
+}
+
+/** @internal From \a pkt, fetch glue records for name \a ns, and update the cut etc.
+ *
+ * \param glue_cnt the number of accepted addresses (to be incremented)
+ */
+static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, bool in_bailiwick,
+ struct kr_request *req, const struct kr_query *qry, int *glue_cnt)
+{
+ ranked_rr_array_t *selected[] = kr_request_selected(req);
+ for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
+ for (unsigned k = 0; k < sec->count; ++k) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, k);
+ if (!knot_dname_is_equal(ns, rr->owner)) {
+ continue;
+ }
+ if ((rr->type != KNOT_RRTYPE_A) &&
+ (rr->type != KNOT_RRTYPE_AAAA)) {
+ continue;
+ }
+
+ uint8_t rank = (in_bailiwick && i == KNOT_ANSWER)
+ ? (KR_RANK_INITIAL | KR_RANK_AUTH) : KR_RANK_OMIT;
+ (void) kr_ranked_rrarray_add(selected[i], rr, rank,
+ false, qry->uid, &req->pool);
+
+ if ((rr->type == KNOT_RRTYPE_A) &&
+ (req->ctx->options.NO_IPV4)) {
+ continue;
+ }
+ if ((rr->type == KNOT_RRTYPE_AAAA) &&
+ (req->ctx->options.NO_IPV6)) {
+ continue;
+ }
+ (void) update_nsaddr(rr, req->current_query, glue_cnt);
+ }
+ }
+}
+
+/** Attempt to find glue for given nameserver name (best effort). */
+static bool has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
+{
+ for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
+ for (unsigned k = 0; k < sec->count; ++k) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, k);
+ if (knot_dname_is_equal(ns, rr->owner) &&
+ (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/** @internal Update the cut with another NS(+glue) record.
+ * @param current_cut is cut name before this packet.
+ * @return _DONE if cut->name changes, _FAIL on error, and _CONSUME otherwise. */
+static int update_cut(knot_pkt_t *pkt, const knot_rrset_t *rr,
+ struct kr_request *req, const knot_dname_t *current_cut,
+ int *glue_cnt)
+{
+ struct kr_query *qry = req->current_query;
+ struct kr_zonecut *cut = &qry->zone_cut;
+ int state = KR_STATE_CONSUME;
+
+ /* New authority MUST be at/below the authority of the current cut;
+ * also qname must be below new authority;
+ * otherwise it's a possible cache injection attempt. */
+ const bool ok = knot_dname_in_bailiwick(rr->owner, current_cut) >= 0
+ && knot_dname_in_bailiwick(qry->sname, rr->owner) >= 0;
+ if (!ok) {
+ VERBOSE_MSG("<= authority: ns outside bailiwick\n");
+#ifdef STRICT_MODE
+ return KR_STATE_FAIL;
+#else
+ /* Workaround: ignore out-of-bailiwick NSs for authoritative answers,
+ * but fail for referrals. This is important to detect lame answers. */
+ if (knot_pkt_section(pkt, KNOT_ANSWER)->count == 0) {
+ state = KR_STATE_FAIL;
+ }
+ return state;
+#endif
+ }
+
+ /* Update zone cut name */
+ if (!knot_dname_is_equal(rr->owner, cut->name)) {
+ /* Remember parent cut and descend to new (keep keys and TA). */
+ struct kr_zonecut *parent = mm_alloc(&req->pool, sizeof(*parent));
+ if (parent) {
+ memcpy(parent, cut, sizeof(*parent));
+ kr_zonecut_init(cut, rr->owner, &req->pool);
+ cut->key = parent->key;
+ cut->trust_anchor = parent->trust_anchor;
+ cut->parent = parent;
+ } else {
+ kr_zonecut_set(cut, rr->owner);
+ }
+ state = KR_STATE_DONE;
+ }
+
+ /* Fetch glue for each NS */
+ knot_rdata_t *rdata_i = rr->rrs.rdata;
+ for (unsigned i = 0; i < rr->rrs.count;
+ ++i, rdata_i = knot_rdataset_next(rdata_i)) {
+ const knot_dname_t *ns_name = knot_ns_name(rdata_i);
+ /* Glue is mandatory for NS below zone */
+ if (knot_dname_in_bailiwick(ns_name, rr->owner) >= 0
+ && !has_glue(pkt, ns_name)) {
+ const char *msg =
+ "<= authority: missing mandatory glue, skipping NS";
+ WITH_VERBOSE(qry) {
+ auto_free char *ns_str = kr_dname_text(ns_name);
+ VERBOSE_MSG("%s %s\n", msg, ns_str);
+ }
+ continue;
+ }
+ int ret = kr_zonecut_add(cut, ns_name, NULL, 0);
+ assert(!ret); (void)ret;
+
+ /* Choose when to use glue records. */
+ const bool in_bailiwick =
+ knot_dname_in_bailiwick(ns_name, current_cut) >= 0;
+ bool do_fetch;
+ if (qry->flags.PERMISSIVE) {
+ do_fetch = true;
+ } else if (qry->flags.STRICT) {
+ /* Strict mode uses only mandatory glue. */
+ do_fetch = knot_dname_in_bailiwick(ns_name, cut->name) >= 0;
+ } else {
+ /* Normal mode uses in-bailiwick glue. */
+ do_fetch = in_bailiwick;
+ }
+ if (do_fetch) {
+ fetch_glue(pkt, ns_name, in_bailiwick, req, qry, glue_cnt);
+ }
+ }
+
+ return state;
+}
+
+/** Compute rank appropriate for RRs present in the packet.
+ * @param answer whether the RR is from answer or authority section
+ * @param is_nonauth: from referral or forwarding (etc.) */
+static uint8_t get_initial_rank(const knot_rrset_t *rr, const struct kr_query *qry,
+ const bool answer, const bool is_nonauth)
+{
+ /* For RRSIGs, ensure the KR_RANK_AUTH flag corresponds to the signed RR. */
+ uint16_t type = kr_rrset_type_maysig(rr);
+
+ if (qry->flags.CACHED) {
+ return rr->additional ? *(uint8_t *)rr->additional : KR_RANK_OMIT;
+ /* ^^ Current use case for "cached" RRs without rank: hints module. */
+ }
+ if (answer || type == KNOT_RRTYPE_DS
+ || type == KNOT_RRTYPE_SOA /* needed for aggressive negative caching */
+ || type == KNOT_RRTYPE_NSEC || type == KNOT_RRTYPE_NSEC3) {
+ /* We almost always want these validated, and it should be possible. */
+ return KR_RANK_INITIAL | KR_RANK_AUTH;
+ }
+ /* Be aggressive: try to validate anything else (almost never extra latency). */
+ return KR_RANK_TRY;
+ /* TODO: this classifier of authoritativity may not be perfect yet. */
+}
+
+static int pick_authority(knot_pkt_t *pkt, struct kr_request *req, bool to_wire)
+{
+ struct kr_query *qry = req->current_query;
+ const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
+
+ const knot_dname_t *zonecut_name = qry->zone_cut.name;
+ bool referral = !knot_wire_get_aa(pkt->wire);
+ if (referral) {
+ /* zone cut already updated by process_authority()
+ * use parent zonecut name */
+ zonecut_name = qry->zone_cut.parent ? qry->zone_cut.parent->name : qry->zone_cut.name;
+ to_wire = false;
+ }
+
+ for (unsigned i = 0; i < ns->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(ns, i);
+ if (rr->rclass != KNOT_CLASS_IN
+ || knot_dname_in_bailiwick(rr->owner, zonecut_name) < 0) {
+ continue;
+ }
+ uint8_t rank = get_initial_rank(rr, qry, false,
+ qry->flags.FORWARD || referral);
+ int ret = kr_ranked_rrarray_add(&req->auth_selected, rr,
+ rank, to_wire, qry->uid, &req->pool);
+ if (ret != kr_ok()) {
+ return ret;
+ }
+ }
+
+ return kr_ok();
+}
+
+static int process_authority(knot_pkt_t *pkt, struct kr_request *req)
+{
+ struct kr_query *qry = req->current_query;
+ assert(!(qry->flags.STUB));
+
+ int result = KR_STATE_CONSUME;
+ if (qry->flags.FORWARD) {
+ return result;
+ }
+
+ const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+
+#ifdef STRICT_MODE
+ /* AA, terminate resolution chain. */
+ if (knot_wire_get_aa(pkt->wire)) {
+ return KR_STATE_CONSUME;
+ }
+#else
+ /* Work around servers sending back CNAME with different delegation and no AA. */
+ if (an->count > 0 && ns->count > 0) {
+ const knot_rrset_t *rr = knot_pkt_rr(an, 0);
+ if (rr->type == KNOT_RRTYPE_CNAME) {
+ return KR_STATE_CONSUME;
+ }
+ /* Work around for these NSs which are authoritative both for
+ * parent and child and mixes data from both zones in single answer */
+ if (knot_wire_get_aa(pkt->wire) &&
+ (rr->type == qry->stype) &&
+ (knot_dname_is_equal(rr->owner, qry->sname))) {
+ return KR_STATE_CONSUME;
+ }
+ }
+#endif
+ /* Remember current bailiwick for NS processing. */
+ const knot_dname_t *current_zone_cut = qry->zone_cut.name;
+ bool ns_record_exists = false;
+ int glue_cnt = 0;
+ /* Update zone cut information. */
+ for (unsigned i = 0; i < ns->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(ns, i);
+ if (rr->type == KNOT_RRTYPE_NS) {
+ ns_record_exists = true;
+ int state = update_cut(pkt, rr, req, current_zone_cut, &glue_cnt);
+ switch(state) {
+ case KR_STATE_DONE: result = state; break;
+ case KR_STATE_FAIL: return state; break;
+ default: /* continue */ break;
+ }
+ } else if (rr->type == KNOT_RRTYPE_SOA
+ && knot_dname_in_bailiwick(rr->owner, qry->zone_cut.name) > 0) {
+ /* SOA below cut in authority indicates different authority,
+ * but same NS set. */
+ qry->zone_cut.name = knot_dname_copy(rr->owner, &req->pool);
+ }
+ }
+
+ /* Nameserver is authoritative for both parent side and the child side of the
+ * delegation may respond with an NS record in the answer section, and still update
+ * the zone cut (e.g. what a.gtld-servers.net would respond for `com NS`) */
+ if (!ns_record_exists && knot_wire_get_aa(pkt->wire)) {
+ for (unsigned i = 0; i < an->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(an, i);
+ if (rr->type == KNOT_RRTYPE_NS
+ && knot_dname_in_bailiwick(rr->owner, qry->zone_cut.name) > 0) {
+ /* NS below cut in authority indicates different authority,
+ * but same NS set. */
+ qry->zone_cut.name = knot_dname_copy(rr->owner, &req->pool);
+ }
+ }
+ }
+
+ if (glue_cnt) {
+ VERBOSE_MSG("<= loaded %d glue addresses\n", glue_cnt);
+ }
+
+
+ if ((qry->flags.DNSSEC_WANT) && (result == KR_STATE_CONSUME)) {
+ if (knot_wire_get_aa(pkt->wire) == 0 &&
+ knot_wire_get_ancount(pkt->wire) == 0 &&
+ ns_record_exists) {
+ /* Unhelpful referral
+ Prevent from validating as an authoritative answer */
+ result = KR_STATE_DONE;
+ }
+ }
+
+ /* CONSUME => Unhelpful referral.
+ * DONE => Zone cut updated. */
+ return result;
+}
+
+static void finalize_answer(knot_pkt_t *pkt, struct kr_query *qry, struct kr_request *req)
+{
+ /* Finalize header */
+ knot_pkt_t *answer = req->answer;
+ knot_wire_set_rcode(answer->wire, knot_wire_get_rcode(pkt->wire));
+}
+
+static int unroll_cname(knot_pkt_t *pkt, struct kr_request *req, bool referral, const knot_dname_t **cname_ret)
+{
+ struct kr_query *query = req->current_query;
+ assert(!(query->flags.STUB));
+ /* Process answer type */
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ const knot_dname_t *cname = NULL;
+ const knot_dname_t *pending_cname = query->sname;
+ unsigned cname_chain_len = 0;
+ bool is_final = (query->parent == NULL);
+ uint32_t iter_count = 0;
+ bool strict_mode = (query->flags.STRICT);
+ do {
+ /* CNAME was found at previous iteration, but records may not follow the correct order.
+ * Try to find records for pending_cname owner from section start. */
+ cname = pending_cname;
+ pending_cname = NULL;
+ const int cname_labels = knot_dname_labels(cname, NULL);
+ for (unsigned i = 0; i < an->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(an, i);
+
+ /* Skip the RR if its owner+type doesn't interest us. */
+ const uint16_t type = kr_rrset_type_maysig(rr);
+ const bool type_OK = rr->type == query->stype || type == query->stype
+ || type == KNOT_RRTYPE_CNAME || type == KNOT_RRTYPE_DNAME;
+ /* TODO: actually handle DNAMEs */
+ if (rr->rclass != KNOT_CLASS_IN || !type_OK
+ || !knot_dname_is_equal(rr->owner, cname)
+ || knot_dname_in_bailiwick(rr->owner, query->zone_cut.name) < 0) {
+ continue;
+ }
+
+ if (rr->type == KNOT_RRTYPE_RRSIG) {
+ int rrsig_labels = knot_rrsig_labels(rr->rrs.rdata);
+ if (rrsig_labels > cname_labels) {
+ /* clearly wrong RRSIG, don't pick it.
+ * don't fail immediately,
+ * let validator work. */
+ continue;
+ }
+ if (rrsig_labels < cname_labels) {
+ query->flags.DNSSEC_WEXPAND = true;
+ }
+ }
+
+ /* Process records matching current SNAME */
+ int state = KR_STATE_FAIL;
+ bool to_wire = false;
+ if (is_final) {
+ /* if not referral, mark record to be written to final answer */
+ to_wire = !referral;
+ } else {
+ int cnt_ = 0;
+ state = update_nsaddr(rr, query->parent, &cnt_);
+ if (state == KR_STATE_FAIL) {
+ return state;
+ }
+ }
+ uint8_t rank = get_initial_rank(rr, query, true,
+ query->flags.FORWARD || referral);
+ state = kr_ranked_rrarray_add(&req->answ_selected, rr,
+ rank, to_wire, query->uid, &req->pool);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ /* Jump to next CNAME target */
+ if ((query->stype == KNOT_RRTYPE_CNAME) || (rr->type != KNOT_RRTYPE_CNAME)) {
+ continue;
+ }
+ cname_chain_len += 1;
+ pending_cname = knot_cname_name(rr->rrs.rdata);
+ if (!pending_cname) {
+ break;
+ }
+ if (cname_chain_len > an->count || cname_chain_len > KR_CNAME_CHAIN_LIMIT) {
+ VERBOSE_MSG("<= too long cname chain\n");
+ return KR_STATE_FAIL;
+ }
+ /* Don't use pending_cname immediately.
+ * There are can be records for "old" cname. */
+ }
+ if (!pending_cname) {
+ break;
+ }
+ if (knot_dname_is_equal(cname, pending_cname)) {
+ VERBOSE_MSG("<= cname chain loop\n");
+ return KR_STATE_FAIL;
+ }
+ /* In strict mode, explicitly fetch each CNAME target. */
+ if (strict_mode) {
+ cname = pending_cname;
+ break;
+ }
+ /* Information outside bailiwick is not trusted. */
+ if (knot_dname_in_bailiwick(pending_cname, query->zone_cut.name) < 0) {
+ cname = pending_cname;
+ break;
+ }
+ /* The validator still can't handle multiple zones in one answer,
+ * so we only follow if a single label is replaced.
+ * TODO: this still isn't 100%, as the target might have a NS+DS,
+ * possibly leading to a SERVFAIL for the in-bailiwick name. */
+ const int pending_labels = knot_dname_labels(pending_cname, NULL);
+ if (pending_labels != cname_labels) {
+ cname = pending_cname;
+ break;
+ }
+ if (knot_dname_matched_labels(pending_cname, cname) !=
+ (cname_labels - 1)) {
+ cname = pending_cname;
+ break;
+ }
+ } while (++iter_count < KR_CNAME_CHAIN_LIMIT);
+ if (iter_count >= KR_CNAME_CHAIN_LIMIT) {
+ VERBOSE_MSG("<= too long cname chain\n");
+ return KR_STATE_FAIL;
+ }
+ *cname_ret = cname;
+ return kr_ok();
+}
+
+static int process_referral_answer(knot_pkt_t *pkt, struct kr_request *req)
+{
+ const knot_dname_t *cname = NULL;
+ int state = unroll_cname(pkt, req, true, &cname);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ struct kr_query *query = req->current_query;
+ if (!(query->flags.CACHED)) {
+ /* If not cached (i.e. got from upstream)
+ * make sure that this is not an authoritative answer
+ * (even with AA=1) for other layers.
+ * There can be answers with AA=1,
+ * empty answer section and NS in authority.
+ * Clearing of AA prevents them from
+ * caching in the packet cache.
+ * If packet already cached, don't touch him. */
+ knot_wire_clear_aa(pkt->wire);
+ }
+ state = pick_authority(pkt, req, false);
+ return state == kr_ok() ? KR_STATE_DONE : KR_STATE_FAIL;
+}
+
+static int process_final(knot_pkt_t *pkt, struct kr_request *req,
+ const knot_dname_t *cname)
+{
+ const int pkt_class = kr_response_classify(pkt);
+ struct kr_query *query = req->current_query;
+ ranked_rr_array_t *array = &req->answ_selected;
+ for (size_t i = 0; i < array->len; ++i) {
+ const knot_rrset_t *rr = array->at[i]->rr;
+ if (!knot_dname_is_equal(rr->owner, cname)) {
+ continue;
+ }
+ if ((rr->rclass != query->sclass) ||
+ (rr->type != query->stype)) {
+ continue;
+ }
+ const bool to_wire = ((pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) != 0);
+ const int state = pick_authority(pkt, req, to_wire);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ if (!array->at[i]->to_wire) {
+ const size_t last_idx = array->len - 1;
+ size_t j = i;
+ ranked_rr_array_entry_t *entry = array->at[i];
+ /* Relocate record to the end, after current cname */
+ while (j < last_idx) {
+ array->at[j] = array->at[j + 1];
+ ++j;
+ }
+ array->at[last_idx] = entry;
+ entry->to_wire = true;
+ }
+ finalize_answer(pkt, query, req);
+ return KR_STATE_DONE;
+ }
+ return kr_ok();
+}
+
+static int process_answer(knot_pkt_t *pkt, struct kr_request *req)
+{
+ struct kr_query *query = req->current_query;
+
+ /* Response for minimized QNAME. Note that current iterator's minimization
+ * is only able ask one label below a zone cut.
+ * NODATA => may be empty non-terminal, retry (found zone cut)
+ * NOERROR => found zone cut, retry, except the case described below
+ * NXDOMAIN => parent is zone cut, retry as a workaround for bad authoritatives
+ */
+ const bool is_final = (query->parent == NULL);
+ const int pkt_class = kr_response_classify(pkt);
+ const knot_dname_t * pkt_qname = knot_pkt_qname(pkt);
+ if (!knot_dname_is_equal(pkt_qname, query->sname) &&
+ (pkt_class & (PKT_NOERROR|PKT_NXDOMAIN|PKT_REFUSED|PKT_NODATA))) {
+ /* Check for parent server that is authoritative for child zone,
+ * several CCTLDs where the SLD and TLD have the same name servers */
+ const knot_pktsection_t *ans = knot_pkt_section(pkt, KNOT_ANSWER);
+ if ((pkt_class & (PKT_NOERROR)) && ans->count > 0 &&
+ knot_dname_is_equal(pkt_qname, query->zone_cut.name)) {
+ VERBOSE_MSG("<= continuing with qname minimization\n");
+ } else {
+ /* fall back to disabling minimization */
+ VERBOSE_MSG("<= retrying with non-minimized name\n");
+ query->flags.NO_MINIMIZE = true;
+ }
+ return KR_STATE_CONSUME;
+ }
+
+ /* This answer didn't improve resolution chain, therefore must be authoritative (relaxed to negative). */
+ if (!is_authoritative(pkt, query)) {
+ if (!(query->flags.FORWARD) &&
+ pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) {
+ VERBOSE_MSG("<= lame response: non-auth sent negative response\n");
+ return KR_STATE_FAIL;
+ }
+ }
+
+ const knot_dname_t *cname = NULL;
+ /* Process answer type */
+ int state = unroll_cname(pkt, req, false, &cname);
+ if (state != kr_ok()) {
+ return state;
+ }
+ /* Make sure that this is an authoritative answer (even with AA=0) for other layers */
+ knot_wire_set_aa(pkt->wire);
+ /* Either way it resolves current query. */
+ query->flags.RESOLVED = true;
+ /* Follow canonical name as next SNAME. */
+ if (!knot_dname_is_equal(cname, query->sname)) {
+ /* Check if target record has been already copied */
+ query->flags.CNAME = true;
+ if (is_final) {
+ state = process_final(pkt, req, cname);
+ if (state != kr_ok()) {
+ return state;
+ }
+ } else if ((query->flags.FORWARD) &&
+ ((query->stype == KNOT_RRTYPE_DS) ||
+ (query->stype == KNOT_RRTYPE_NS))) {
+ /* CNAME'ed answer for DS or NS subquery.
+ * Treat it as proof of zonecut nonexistance. */
+ return KR_STATE_DONE;
+ }
+ VERBOSE_MSG("<= cname chain, following\n");
+ /* Check if the same query was followed in the same CNAME chain. */
+ for (const struct kr_query *q = query->cname_parent; q != NULL;
+ q = q->cname_parent) {
+ if (q->sclass == query->sclass &&
+ q->stype == query->stype &&
+ knot_dname_is_equal(q->sname, cname)) {
+ VERBOSE_MSG("<= cname chain loop\n");
+ return KR_STATE_FAIL;
+ }
+ }
+ struct kr_query *next = kr_rplan_push(&req->rplan, query->parent, cname, query->sclass, query->stype);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ next->flags.AWAIT_CUT = true;
+
+ /* Copy transitive flags from original query to CNAME followup. */
+ next->flags.TRACE = query->flags.TRACE;
+ next->flags.ALWAYS_CUT = query->flags.ALWAYS_CUT;
+ next->flags.NO_MINIMIZE = query->flags.NO_MINIMIZE;
+ next->flags.NO_THROTTLE = query->flags.NO_THROTTLE;
+
+ if (query->flags.FORWARD) {
+ next->forward_flags.CNAME = true;
+ if (query->parent == NULL) {
+ state = kr_nsrep_copy_set(&next->ns, &query->ns);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ }
+ }
+ next->cname_parent = query;
+ /* Want DNSSEC if and only if it's posible to secure
+ * this name (i.e. iff it is covered by a TA) */
+ if (kr_ta_covers_qry(req->ctx, cname, query->stype)) {
+ next->flags.DNSSEC_WANT = true;
+ } else {
+ next->flags.DNSSEC_WANT = false;
+ }
+ if (!(query->flags.FORWARD) ||
+ (query->flags.DNSSEC_WEXPAND)) {
+ state = pick_authority(pkt, req, false);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ }
+ } else if (!query->parent) {
+ /* Answer for initial query */
+ const bool to_wire = ((pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) != 0);
+ state = pick_authority(pkt, req, to_wire);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ finalize_answer(pkt, query, req);
+ } else {
+ /* Answer for sub-query; DS, IP for NS etc.
+ * It may contains NSEC \ NSEC3 records for
+ * data non-existence or wc expansion proving.
+ * If yes, they must be validated by validator.
+ * If no, authority section is unuseful.
+ * dnssec\nsec.c & dnssec\nsec3.c use
+ * rrsets from incoming packet.
+ * validator uses answer_selected & auth_selected.
+ * So, if nsec\nsec3 records are present in authority,
+ * pick_authority() must be called.
+ * TODO refactor nsec\nsec3 modules to work with
+ * answer_selected & auth_selected instead of incoming pkt. */
+ bool auth_is_unuseful = true;
+ const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
+ for (unsigned i = 0; i < ns->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(ns, i);
+ if (rr->type == KNOT_RRTYPE_NSEC ||
+ rr->type == KNOT_RRTYPE_NSEC3) {
+ auth_is_unuseful = false;
+ break;
+ }
+ }
+ if (!auth_is_unuseful) {
+ state = pick_authority(pkt, req, false);
+ if (state != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ }
+ }
+ return KR_STATE_DONE;
+}
+
+/** @internal like process_answer() but for the STUB mode. */
+static int process_stub(knot_pkt_t *pkt, struct kr_request *req)
+{
+ struct kr_query *query = req->current_query;
+ assert(query->flags.STUB);
+ /* Pick all answer RRs. */
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ for (unsigned i = 0; i < an->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(an, i);
+ int err = kr_ranked_rrarray_add(&req->answ_selected, rr,
+ KR_RANK_OMIT | KR_RANK_AUTH, true, query->uid, &req->pool);
+ /* KR_RANK_AUTH: we don't have the records directly from
+ * an authoritative source, but we do trust the server and it's
+ * supposed to only send us authoritative records. */
+ if (err != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+ }
+
+ knot_wire_set_aa(pkt->wire);
+ query->flags.RESOLVED = true;
+ /* Pick authority RRs. */
+ int pkt_class = kr_response_classify(pkt);
+ const bool to_wire = ((pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) != 0);
+ int err = pick_authority(pkt, req, to_wire);
+ if (err != kr_ok()) {
+ return KR_STATE_FAIL;
+ }
+
+ finalize_answer(pkt, query, req);
+ return KR_STATE_DONE;
+}
+
+
+/** Error handling, RFC1034 5.3.3, 4d. */
+static int resolve_error(knot_pkt_t *pkt, struct kr_request *req)
+{
+ return KR_STATE_FAIL;
+}
+
+/* State-less single resolution iteration step, not needed. */
+static int reset(kr_layer_t *ctx) { return KR_STATE_PRODUCE; }
+
+/* Set resolution context and parameters. */
+static int begin(kr_layer_t *ctx)
+{
+ if (ctx->state & (KR_STATE_DONE|KR_STATE_FAIL)) {
+ return ctx->state;
+ }
+ /*
+ * RFC7873 5.4 extends the QUERY operation code behaviour in order to
+ * be able to generate requests for server cookies. Such requests have
+ * QDCOUNT equal to zero and must contain a cookie option.
+ * Server cookie queries must be handled by the cookie module/layer
+ * before this layer.
+ */
+ const knot_pkt_t *pkt = ctx->req->qsource.packet;
+ if (!pkt || knot_wire_get_qdcount(pkt->wire) == 0) {
+ return KR_STATE_FAIL;
+ }
+
+ struct kr_query *qry = ctx->req->current_query;
+ /* Avoid any other classes, and avoid any meta-types ~~except for ANY~~. */
+ if (qry->sclass != KNOT_CLASS_IN
+ || (knot_rrtype_is_metatype(qry->stype)
+ /* && qry->stype != KNOT_RRTYPE_ANY hmm ANY seems broken ATM */)) {
+ knot_wire_set_rcode(ctx->req->answer->wire, KNOT_RCODE_NOTIMPL);
+ return KR_STATE_FAIL;
+ }
+
+ return reset(ctx);
+}
+
+int kr_make_query(struct kr_query *query, knot_pkt_t *pkt)
+{
+ /* Minimize QNAME (if possible). */
+ uint16_t qtype = query->stype;
+ const knot_dname_t *qname = minimized_qname(query, &qtype);
+
+ /* Form a query for the authoritative. */
+ knot_pkt_clear(pkt);
+ int ret = knot_pkt_put_question(pkt, qname, query->sclass, qtype);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ /* Query built, expect answer. */
+ query->id = kr_rand_bytes(2);
+ /* We must respect https://tools.ietf.org/html/rfc7766#section-6.2.1
+ * - When sending multiple queries over a TCP connection, clients MUST NOT
+ * reuse the DNS Message ID of an in-flight query on that connection.
+ *
+ * So, if query is going to be sent over TCP connection
+ * this id can be changed to avoid duplication with query that already was sent
+ * but didn't receive answer yet.
+ */
+ knot_wire_set_id(pkt->wire, query->id);
+ pkt->parsed = pkt->size;
+
+ return kr_ok();
+}
+
+static int prepare_query(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ assert(pkt && ctx);
+ struct kr_request *req = ctx->req;
+ struct kr_query *query = req->current_query;
+ if (!query || ctx->state & (KR_STATE_DONE|KR_STATE_FAIL)) {
+ return ctx->state;
+ }
+
+ /* Make query */
+ int ret = kr_make_query(query, pkt);
+ if (ret != 0) {
+ return KR_STATE_FAIL;
+ }
+
+ WITH_VERBOSE(query) {
+ KR_DNAME_GET_STR(name_str, query->sname);
+ KR_RRTYPE_GET_STR(type_str, query->stype);
+ QVERBOSE_MSG(query, "'%s' type '%s' new uid was assigned .%02u, parent uid .%02u\n",
+ name_str, type_str, req->rplan.next_uid,
+ query->parent ? query->parent->uid : 0);
+ }
+
+ query->uid = req->rplan.next_uid;
+ req->rplan.next_uid += 1;
+
+ return KR_STATE_CONSUME;
+}
+
+static int resolve_badmsg(knot_pkt_t *pkt, struct kr_request *req, struct kr_query *query)
+{
+
+#ifndef STRICT_MODE
+ /* Work around broken auths/load balancers */
+ if (query->flags.SAFEMODE) {
+ return resolve_error(pkt, req);
+ } else if (query->flags.NO_MINIMIZE) {
+ query->flags.SAFEMODE = true;
+ return KR_STATE_DONE;
+ } else {
+ query->flags.NO_MINIMIZE = true;
+ return KR_STATE_DONE;
+ }
+#else
+ return resolve_error(pkt, req);
+#endif
+}
+
+static int resolve_notimpl(knot_pkt_t *pkt, struct kr_request *req, struct kr_query *qry)
+{
+ if (qry->stype == KNOT_RRTYPE_RRSIG && qry->parent != NULL) {
+ /* RRSIG subquery have got NOTIMPL.
+ * Possible scenario - same NS is autoritative for child and parent,
+ * but child isn't signed.
+ * We got delegation to parent,
+ * then NS responded as NS for child zone.
+ * Answer contained record been requested, but no RRSIGs,
+ * Validator issued RRSIG query then. If qname is zone name,
+ * we can get NOTIMPL. Ask for DS to find out security status.
+ * TODO - maybe it would be better to do this in validator, when
+ * RRSIG revalidation occurs.
+ */
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *next = kr_rplan_push(rplan, qry->parent, qry->sname,
+ qry->sclass, KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ kr_zonecut_set(&next->zone_cut, qry->parent->zone_cut.name);
+ kr_zonecut_copy(&next->zone_cut, &qry->parent->zone_cut);
+ kr_zonecut_copy_trust(&next->zone_cut, &qry->parent->zone_cut);
+ next->flags.DNSSEC_WANT = true;
+ qry->flags.RESOLVED = true;
+ return KR_STATE_DONE;
+ }
+ return resolve_badmsg(pkt, req, qry);
+}
+
+/** Resolve input query or continue resolution with followups.
+ *
+ * This roughly corresponds to RFC1034, 5.3.3 4a-d.
+ */
+static int resolve(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ assert(pkt && ctx);
+ struct kr_request *req = ctx->req;
+ struct kr_query *query = req->current_query;
+ if (!query) {
+ return ctx->state;
+ }
+
+ WITH_VERBOSE(query) {
+ if (query->flags.TRACE) {
+ auto_free char *pkt_text = kr_pkt_text(pkt);
+ VERBOSE_MSG("<= answer received: \n%s\n", pkt_text);
+ }
+ }
+
+ if (query->flags.RESOLVED || query->flags.BADCOOKIE_AGAIN) {
+ return ctx->state;
+ }
+
+ /* Check for packet processing errors first.
+ * Note - we *MUST* check if it has at least a QUESTION,
+ * otherwise it would crash on accessing QNAME. */
+#ifdef STRICT_MODE
+ if (pkt->parsed < pkt->size) {
+ VERBOSE_MSG("<= pkt contains excessive data\n");
+ return resolve_badmsg(pkt, req, query);
+ } else
+#endif
+ if (pkt->parsed <= KNOT_WIRE_HEADER_SIZE) {
+ VERBOSE_MSG("<= malformed response\n");
+ return resolve_badmsg(pkt, req, query);
+ } else if (!is_paired_to_query(pkt, query)) {
+ VERBOSE_MSG("<= ignoring mismatching response\n");
+ /* Force TCP, to work around authoritatives messing up question
+ * without yielding to spoofed responses. */
+ query->flags.TCP = true;
+ return resolve_badmsg(pkt, req, query);
+ } else if (knot_wire_get_tc(pkt->wire)) {
+ VERBOSE_MSG("<= truncated response, failover to TCP\n");
+ if (query) {
+ /* Fail if already on TCP. */
+ if (query->flags.TCP) {
+ VERBOSE_MSG("<= TC=1 with TCP, bailing out\n");
+ return resolve_error(pkt, req);
+ }
+ query->flags.TCP = true;
+ }
+ return KR_STATE_CONSUME;
+ }
+
+#ifndef NOVERBOSELOG
+ const knot_lookup_t *rcode = knot_lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire));
+#endif
+
+ /* Check response code. */
+ switch(knot_wire_get_rcode(pkt->wire)) {
+ case KNOT_RCODE_NOERROR:
+ case KNOT_RCODE_NXDOMAIN:
+ break; /* OK */
+ case KNOT_RCODE_REFUSED:
+ case KNOT_RCODE_SERVFAIL: {
+ if (query->flags.STUB) {
+ /* Pass through in stub mode */
+ break;
+ }
+ VERBOSE_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ query->fails += 1;
+ if (query->fails >= KR_QUERY_NSRETRY_LIMIT) {
+ query->fails = 0; /* Reset per-query counter. */
+ return resolve_error(pkt, req);
+ } else {
+ if (!query->flags.FORWARD) {
+ query->flags.NO_MINIMIZE = true; /* Drop minimisation as a safe-guard. */
+ }
+ return KR_STATE_CONSUME;
+ }
+ }
+ case KNOT_RCODE_FORMERR:
+ VERBOSE_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ return resolve_badmsg(pkt, req, query);
+ case KNOT_RCODE_NOTIMPL:
+ VERBOSE_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ return resolve_notimpl(pkt, req, query);
+ default:
+ VERBOSE_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ return resolve_error(pkt, req);
+ }
+
+ /* Forwarding/stub mode is special. */
+ if (query->flags.STUB) {
+ return process_stub(pkt, req);
+ }
+
+ /* Resolve authority to see if it's referral or authoritative. */
+ int state = process_authority(pkt, req);
+ switch(state) {
+ case KR_STATE_CONSUME: /* Not referral, process answer. */
+ VERBOSE_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ state = process_answer(pkt, req);
+ break;
+ case KR_STATE_DONE: /* Referral */
+ state = process_referral_answer(pkt,req);
+ VERBOSE_MSG("<= referral response, follow\n");
+ break;
+ default:
+ break;
+ }
+
+ return state;
+}
+
+/** Module implementation. */
+const kr_layer_api_t *iterate_layer(struct kr_module *module)
+{
+ static const kr_layer_api_t _layer = {
+ .begin = &begin,
+ .reset = &reset,
+ .consume = &resolve,
+ .produce = &prepare_query
+ };
+ return &_layer;
+}
+
+KR_MODULE_EXPORT(iterate)
+
+#undef VERBOSE_MSG
diff --git a/lib/layer/iterate.h b/lib/layer/iterate.h
new file mode 100644
index 0000000..a9395bf
--- /dev/null
+++ b/lib/layer/iterate.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/layer.h"
+#include "lib/rplan.h"
+
+/* Packet classification. */
+enum {
+ PKT_NOERROR = 1 << 0, /* Positive response */
+ PKT_NODATA = 1 << 1, /* No data response */
+ PKT_NXDOMAIN = 1 << 2, /* Negative response */
+ PKT_REFUSED = 1 << 3, /* Refused response */
+ PKT_ERROR = 1 << 4 /* Bad message */
+};
+
+/** Classify response by type. */
+int kr_response_classify(const knot_pkt_t *pkt);
+
+/** Make next iterative query. */
+KR_EXPORT
+int kr_make_query(struct kr_query *query, knot_pkt_t *pkt);
diff --git a/lib/layer/validate.c b/lib/layer/validate.c
new file mode 100644
index 0000000..55c3ad7
--- /dev/null
+++ b/lib/layer/validate.c
@@ -0,0 +1,1133 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <contrib/cleanup.h>
+#include <libknot/packet/wire.h>
+#include <libknot/rrtype/rdname.h>
+#include <libknot/rrtype/rrsig.h>
+#include <libdnssec/error.h>
+
+#include "lib/dnssec/nsec.h"
+#include "lib/dnssec/nsec3.h"
+#include "lib/dnssec.h"
+#include "lib/layer.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+#include "lib/utils.h"
+#include "lib/defines.h"
+#include "lib/module.h"
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "vldr", __VA_ARGS__)
+
+#define MAX_REVALIDATION_CNT 2
+
+/**
+ * Search in section for given type.
+ * @param sec Packet section.
+ * @param type Type to search for.
+ * @return True if found.
+ */
+static bool section_has_type(const knot_pktsection_t *sec, uint16_t type)
+{
+ if (!sec) {
+ return false;
+ }
+
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, i);
+ if (rr->type == type) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool pkt_has_type(const knot_pkt_t *pkt, uint16_t type)
+{
+ if (!pkt) {
+ return false;
+ }
+
+ if (section_has_type(knot_pkt_section(pkt, KNOT_ANSWER), type)) {
+ return true;
+ }
+ if (section_has_type(knot_pkt_section(pkt, KNOT_AUTHORITY), type)) {
+ return true;
+ }
+ return section_has_type(knot_pkt_section(pkt, KNOT_ADDITIONAL), type);
+}
+
+static void log_bogus_rrsig(kr_rrset_validation_ctx_t *vctx, const struct kr_query *qry,
+ const knot_rrset_t *rr, const char *msg) {
+ WITH_VERBOSE(qry) {
+ auto_free char *name_text = kr_dname_text(rr->owner);
+ auto_free char *type_text = kr_rrtype_text(rr->type);
+ VERBOSE_MSG(qry, ">< %s: %s %s "
+ "(%u matching RRSIGs, %u expired, %u not yet valid, "
+ "%u invalid signer, %u invalid label count, %u invalid key, "
+ "%u invalid crypto, %u invalid NSEC)\n",
+ msg, name_text, type_text, vctx->rrs_counters.matching_name_type,
+ vctx->rrs_counters.expired, vctx->rrs_counters.notyet,
+ vctx->rrs_counters.signer_invalid, vctx->rrs_counters.labels_invalid,
+ vctx->rrs_counters.key_invalid, vctx->rrs_counters.crypto_invalid,
+ vctx->rrs_counters.nsec_invalid);
+ }
+}
+
+static int validate_section(kr_rrset_validation_ctx_t *vctx, const struct kr_query *qry,
+ knot_mm_t *pool)
+{
+ if (!vctx) {
+ return kr_error(EINVAL);
+ }
+
+ /* Can't use qry->zone_cut.name directly, as this name can
+ * change when updating cut information before validation.
+ */
+ vctx->zone_name = vctx->keys ? vctx->keys->owner : NULL;
+
+ int validation_result = 0;
+ for (ssize_t i = 0; i < vctx->rrs->len; ++i) {
+ ranked_rr_array_entry_t *entry = vctx->rrs->at[i];
+ const knot_rrset_t *rr = entry->rr;
+
+ if (entry->yielded || vctx->qry_uid != entry->qry_uid) {
+ continue;
+ }
+
+ if (kr_rank_test(entry->rank, KR_RANK_OMIT)
+ || kr_rank_test(entry->rank, KR_RANK_SECURE)) {
+ continue; /* these are already OK */
+ }
+
+ if (rr->type == KNOT_RRTYPE_RRSIG) {
+ const knot_dname_t *signer_name = knot_rrsig_signer_name(rr->rrs.rdata);
+ if (!knot_dname_is_equal(vctx->zone_name, signer_name)) {
+ kr_rank_set(&entry->rank, KR_RANK_MISMATCH);
+ vctx->err_cnt += 1;
+ break;
+ }
+ kr_rank_set(&entry->rank, KR_RANK_OMIT);
+ continue;
+ }
+
+ uint8_t rank_orig = entry->rank;
+ validation_result = kr_rrset_validate(vctx, rr);
+ if (validation_result == kr_ok()) {
+ kr_rank_set(&entry->rank, KR_RANK_SECURE);
+
+ } else if (kr_rank_test(rank_orig, KR_RANK_TRY)) {
+ log_bogus_rrsig(vctx, qry, rr,
+ "failed to validate non-authoritative data but continuing");
+ vctx->result = kr_ok();
+ kr_rank_set(&entry->rank, KR_RANK_TRY);
+ /* ^^ BOGUS would be more accurate, but it might change
+ * to MISMATCH on revalidation, e.g. in test val_referral_nods :-/
+ */
+
+ } else if (validation_result == kr_error(ENOENT)) {
+ /* no RRSIGs found */
+ kr_rank_set(&entry->rank, KR_RANK_MISSING);
+ vctx->err_cnt += 1;
+ log_bogus_rrsig(vctx, qry, rr, "no valid RRSIGs found");
+ } else {
+ kr_rank_set(&entry->rank, KR_RANK_BOGUS);
+ vctx->err_cnt += 1;
+ log_bogus_rrsig(vctx, qry, rr, "bogus signatures");
+ }
+ }
+ return kr_ok();
+}
+
+static int validate_records(struct kr_request *req, knot_pkt_t *answer, knot_mm_t *pool, bool has_nsec3)
+{
+ struct kr_query *qry = req->current_query;
+ if (!qry->zone_cut.key) {
+ VERBOSE_MSG(qry, "<= no DNSKEY, can't validate\n");
+ return kr_error(EBADMSG);
+ }
+
+ kr_rrset_validation_ctx_t vctx = {
+ .pkt = answer,
+ .rrs = &req->answ_selected,
+ .section_id = KNOT_ANSWER,
+ .keys = qry->zone_cut.key,
+ .zone_name = qry->zone_cut.name,
+ .timestamp = qry->timestamp.tv_sec,
+ .qry_uid = qry->uid,
+ .has_nsec3 = has_nsec3,
+ .flags = 0,
+ .err_cnt = 0,
+ .result = 0
+ };
+
+ int ret = validate_section(&vctx, qry, pool);
+ req->answ_validated = (vctx.err_cnt == 0);
+ if (ret != kr_ok()) {
+ return ret;
+ }
+
+ uint32_t an_flags = vctx.flags;
+ vctx.rrs = &req->auth_selected;
+ vctx.section_id = KNOT_AUTHORITY;
+ vctx.flags = 0;
+ vctx.err_cnt = 0;
+ vctx.result = 0;
+
+ ret = validate_section(&vctx, qry, pool);
+ req->auth_validated = (vctx.err_cnt == 0);
+ if (ret != kr_ok()) {
+ return ret;
+ }
+
+ /* Records were validated.
+ * If there is wildcard expansion in answer,
+ * or optout - flag the query.
+ */
+ if (an_flags & KR_DNSSEC_VFLG_WEXPAND) {
+ qry->flags.DNSSEC_WEXPAND = true;
+ }
+ if (an_flags & KR_DNSSEC_VFLG_OPTOUT) {
+ qry->flags.DNSSEC_OPTOUT = true;
+ }
+
+ return ret;
+}
+
+static int validate_keyset(struct kr_request *req, knot_pkt_t *answer, bool has_nsec3)
+{
+ /* Merge DNSKEY records from answer that are below/at current cut. */
+ struct kr_query *qry = req->current_query;
+ bool updated_key = false;
+ const knot_pktsection_t *an = knot_pkt_section(answer, KNOT_ANSWER);
+ for (unsigned i = 0; i < an->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(an, i);
+ if (rr->type != KNOT_RRTYPE_DNSKEY
+ || knot_dname_in_bailiwick(rr->owner, qry->zone_cut.name) < 0) {
+ continue;
+ }
+ /* Merge with zone cut (or replace ancestor key). */
+ if (!qry->zone_cut.key || !knot_dname_is_equal(qry->zone_cut.key->owner, rr->owner)) {
+ qry->zone_cut.key = knot_rrset_copy(rr, qry->zone_cut.pool);
+ if (!qry->zone_cut.key) {
+ return kr_error(ENOMEM);
+ }
+ updated_key = true;
+ } else {
+ int ret = knot_rdataset_merge(&qry->zone_cut.key->rrs,
+ &rr->rrs, qry->zone_cut.pool);
+ if (ret != 0) {
+ knot_rrset_free(qry->zone_cut.key, qry->zone_cut.pool);
+ qry->zone_cut.key = NULL;
+ return ret;
+ }
+ updated_key = true;
+ }
+ }
+
+ /* Check if there's a key for current TA. */
+ if (updated_key && !(qry->flags.CACHED)) {
+
+ kr_rrset_validation_ctx_t vctx = {
+ .pkt = answer,
+ .rrs = &req->answ_selected,
+ .section_id = KNOT_ANSWER,
+ .keys = qry->zone_cut.key,
+ .zone_name = qry->zone_cut.name,
+ .timestamp = qry->timestamp.tv_sec,
+ .qry_uid = qry->uid,
+ .has_nsec3 = has_nsec3,
+ .flags = 0,
+ .result = 0
+ };
+ int ret = kr_dnskeys_trusted(&vctx, qry->zone_cut.trust_anchor);
+ if (ret != 0) {
+ if (ret != kr_error(DNSSEC_INVALID_DS_ALGORITHM) &&
+ ret != kr_error(EAGAIN)) {
+ log_bogus_rrsig(&vctx, qry, qry->zone_cut.key, "bogus key");
+ }
+ knot_rrset_free(qry->zone_cut.key, qry->zone_cut.pool);
+ qry->zone_cut.key = NULL;
+ return ret;
+ }
+
+ if (vctx.flags & KR_DNSSEC_VFLG_WEXPAND) {
+ qry->flags.DNSSEC_WEXPAND = true;
+ }
+ if (vctx.flags & KR_DNSSEC_VFLG_OPTOUT) {
+ qry->flags.DNSSEC_OPTOUT = true;
+ }
+
+ }
+ return kr_ok();
+}
+
+static knot_rrset_t *update_ds(struct kr_zonecut *cut, const knot_pktsection_t *sec)
+{
+ /* Aggregate DS records (if using multiple keys) */
+ knot_rrset_t *new_ds = NULL;
+ for (unsigned i = 0; i < sec->count; ++i) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, i);
+ if (rr->type != KNOT_RRTYPE_DS) {
+ continue;
+ }
+ int ret = 0;
+ if (new_ds) {
+ ret = knot_rdataset_merge(&new_ds->rrs, &rr->rrs, cut->pool);
+ } else {
+ new_ds = knot_rrset_copy(rr, cut->pool);
+ if (!new_ds) {
+ return NULL;
+ }
+ }
+ if (ret != 0) {
+ knot_rrset_free(new_ds, cut->pool);
+ return NULL;
+ }
+ }
+ return new_ds;
+}
+
+static void mark_insecure_parents(const struct kr_query *qry)
+{
+ /* If there is a chain of DS queries mark all of them,
+ * then mark first non-DS parent.
+ * Stop if parent is waiting for ns address.
+ * NS can be located at unsigned zone, but still will return
+ * valid DNSSEC records for initial query. */
+ struct kr_query *parent = qry->parent;
+ while (parent && !parent->flags.AWAIT_IPV4 && !parent->flags.AWAIT_IPV6) {
+ parent->flags.DNSSEC_WANT = false;
+ parent->flags.DNSSEC_INSECURE = true;
+ if (parent->stype != KNOT_RRTYPE_DS &&
+ parent->stype != KNOT_RRTYPE_RRSIG) {
+ break;
+ }
+ parent = parent->parent;
+ }
+}
+
+static int update_parent_keys(struct kr_request *req, uint16_t answer_type)
+{
+ struct kr_query *qry = req->current_query;
+ struct kr_query *parent = qry->parent;
+ assert(parent);
+ switch(answer_type) {
+ case KNOT_RRTYPE_DNSKEY:
+ VERBOSE_MSG(qry, "<= parent: updating DNSKEY\n");
+ parent->zone_cut.key = knot_rrset_copy(qry->zone_cut.key, parent->zone_cut.pool);
+ if (!parent->zone_cut.key) {
+ return KR_STATE_FAIL;
+ }
+ break;
+ case KNOT_RRTYPE_DS:
+ VERBOSE_MSG(qry, "<= parent: updating DS\n");
+ if (qry->flags.DNSSEC_INSECURE) { /* DS non-existence proven. */
+ mark_insecure_parents(qry);
+ } else if (qry->flags.DNSSEC_NODS && !qry->flags.FORWARD) {
+ if (qry->flags.DNSSEC_OPTOUT) {
+ mark_insecure_parents(qry);
+ } else {
+ int ret = kr_dnssec_matches_name_and_type(&req->auth_selected, qry->uid,
+ qry->sname, KNOT_RRTYPE_NS);
+ if (ret == kr_ok()) {
+ mark_insecure_parents(qry);
+ }
+ }
+ } else if (qry->flags.DNSSEC_NODS && qry->flags.FORWARD) {
+ int ret = kr_dnssec_matches_name_and_type(&req->auth_selected, qry->uid,
+ qry->sname, KNOT_RRTYPE_NS);
+ if (ret == kr_ok()) {
+ mark_insecure_parents(qry);
+ }
+ } else { /* DS existence proven. */
+ parent->zone_cut.trust_anchor = knot_rrset_copy(qry->zone_cut.trust_anchor, parent->zone_cut.pool);
+ if (!parent->zone_cut.trust_anchor) {
+ return KR_STATE_FAIL;
+ }
+ }
+ break;
+ default: break;
+ }
+ return kr_ok();
+}
+
+static int update_delegation(struct kr_request *req, struct kr_query *qry, knot_pkt_t *answer, bool has_nsec3)
+{
+ struct kr_zonecut *cut = &qry->zone_cut;
+
+ /* RFC4035 3.1.4. authoritative must send either DS or proof of non-existence.
+ * If it contains neither, resolver must query the parent for the DS (RFC4035 5.2.).
+ * If DS exists, the referral is OK,
+ * otherwise referral is bogus (or an attempted downgrade attack).
+ */
+
+
+ unsigned section = KNOT_ANSWER;
+ const bool referral = !knot_wire_get_aa(answer->wire);
+ if (referral) {
+ section = KNOT_AUTHORITY;
+ } else if (knot_pkt_qtype(answer) == KNOT_RRTYPE_DS &&
+ !(qry->flags.CNAME) &&
+ (knot_wire_get_rcode(answer->wire) != KNOT_RCODE_NXDOMAIN)) {
+ section = KNOT_ANSWER;
+ } else { /* N/A */
+ return kr_ok();
+ }
+
+ int ret = 0;
+ const knot_dname_t *proved_name = knot_pkt_qname(answer);
+ /* Aggregate DS records (if using multiple keys) */
+ knot_rrset_t *new_ds = update_ds(cut, knot_pkt_section(answer, section));
+ if (!new_ds) {
+ /* No DS provided, check for proof of non-existence. */
+ if (!has_nsec3) {
+ if (referral) {
+ /* Check if it is referral to unsigned, rfc4035 5.2 */
+ ret = kr_nsec_ref_to_unsigned(answer);
+ } else {
+ /* No-data answer */
+ ret = kr_nsec_existence_denial(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
+ }
+ } else {
+ if (referral) {
+ /* Check if it is referral to unsigned, rfc5155 8.9 */
+ ret = kr_nsec3_ref_to_unsigned(answer);
+ } else {
+ /* No-data answer, QTYPE is DS, rfc5155 8.6 */
+ ret = kr_nsec3_no_data(answer, KNOT_AUTHORITY, proved_name, KNOT_RRTYPE_DS);
+ }
+ if (ret == kr_error(KNOT_ERANGE)) {
+ /* Not bogus, going insecure due to optout */
+ ret = 0;
+ }
+ }
+
+ if (referral && qry->stype != KNOT_RRTYPE_DS &&
+ ret == DNSSEC_NOT_FOUND) {
+ /* referral,
+ * qtype is not KNOT_RRTYPE_DS, NSEC\NSEC3 were not found.
+ * Check if DS already was fetched. */
+ knot_rrset_t *ta = cut->trust_anchor;
+ if (knot_dname_is_equal(cut->name, ta->owner)) {
+ /* DS is OK */
+ ret = 0;
+ }
+ } else if (ret != 0) {
+ VERBOSE_MSG(qry, "<= bogus proof of DS non-existence\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ } else if (proved_name[0] != '\0') { /* don't go to insecure for . DS */
+ VERBOSE_MSG(qry, "<= DS doesn't exist, going insecure\n");
+ qry->flags.DNSSEC_NODS = true;
+ /* Rank the corresponding nonauth NS as insecure. */
+ for (int i = 0; i < req->auth_selected.len; ++i) {
+ ranked_rr_array_entry_t *ns = req->auth_selected.at[i];
+ if (ns->qry_uid != qry->uid
+ || !ns->rr
+ || ns->rr->type != KNOT_RRTYPE_NS) {
+ continue;
+ }
+ if (!referral && !knot_dname_is_equal(qry->sname, ns->rr->owner)) {
+ continue;
+ }
+ /* Found the record. Note: this is slightly fragile
+ * in case there were more NS records in the packet.
+ * As it is now for referrals, kr_nsec*_ref_to_unsigned consider
+ * (only) the first NS record in the packet. */
+ if (!kr_rank_test(ns->rank, KR_RANK_AUTH)) { /* sanity */
+ ns->rank = KR_RANK_INSECURE;
+ }
+ break;
+ }
+ }
+ return ret;
+ } else if (qry->flags.FORWARD && qry->parent) {
+ struct kr_query *parent = qry->parent;
+ parent->zone_cut.name = knot_dname_copy(qry->sname, parent->zone_cut.pool);
+ }
+
+ /* Extend trust anchor */
+ VERBOSE_MSG(qry, "<= DS: OK\n");
+ cut->trust_anchor = new_ds;
+ return ret;
+}
+
+static const knot_dname_t *find_first_signer(ranked_rr_array_t *arr)
+{
+ for (size_t i = 0; i < arr->len; ++i) {
+ ranked_rr_array_entry_t *entry = arr->at[i];
+ const knot_rrset_t *rr = entry->rr;
+ if (entry->yielded ||
+ (!kr_rank_test(entry->rank, KR_RANK_INITIAL) &&
+ !kr_rank_test(entry->rank, KR_RANK_TRY) &&
+ !kr_rank_test(entry->rank, KR_RANK_MISMATCH))) {
+ continue;
+ }
+ if (rr->type == KNOT_RRTYPE_RRSIG) {
+ return knot_rrsig_signer_name(rr->rrs.rdata);
+ }
+ }
+ return NULL;
+}
+
+static const knot_dname_t *signature_authority(struct kr_request *req)
+{
+ const knot_dname_t *signer_name = find_first_signer(&req->answ_selected);
+ if (!signer_name) {
+ signer_name = find_first_signer(&req->auth_selected);
+ }
+ return signer_name;
+}
+
+static int rrsig_not_found(kr_layer_t *ctx, const knot_rrset_t *rr)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ /* Parent-side record, so don't ask for RRSIG.
+ * We won't receive it anyway. */
+ if (qry->stype == KNOT_RRTYPE_DS) {
+ return KR_STATE_FAIL;
+ }
+
+ struct kr_zonecut *cut = &qry->zone_cut;
+ const knot_dname_t *cut_name_start = qry->zone_cut.name;
+ bool use_cut = true;
+ if (knot_dname_in_bailiwick(rr->owner, cut_name_start) < 0) {
+ int zone_labels = knot_dname_labels(qry->zone_cut.name, NULL);
+ int matched_labels = knot_dname_matched_labels(qry->zone_cut.name, rr->owner);
+ int skip_labels = zone_labels - matched_labels;
+ while (skip_labels--) {
+ cut_name_start = knot_wire_next_label(cut_name_start, NULL);
+ }
+ /* try to find the name wanted among ancestors */
+ use_cut = false;
+ while (cut->parent) {
+ cut = cut->parent;
+ if (knot_dname_is_equal(cut_name_start, cut->name)) {
+ use_cut = true;
+ break;
+ }
+ };
+ }
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *next = kr_rplan_push(rplan, qry, rr->owner, rr->rclass, KNOT_RRTYPE_RRSIG);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ kr_zonecut_init(&next->zone_cut, cut_name_start, &req->pool);
+ if (use_cut) {
+ kr_zonecut_copy(&next->zone_cut, cut);
+ kr_zonecut_copy_trust(&next->zone_cut, cut);
+ } else {
+ next->flags.AWAIT_CUT = true;
+ }
+ if (qry->flags.FORWARD) {
+ next->flags.AWAIT_CUT = false;
+ }
+ next->flags.DNSSEC_WANT = true;
+ return KR_STATE_YIELD;
+}
+
+static int check_validation_result(kr_layer_t *ctx, ranked_rr_array_t *arr)
+{
+ int ret = KR_STATE_DONE;
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ ranked_rr_array_entry_t *invalid_entry = NULL;
+ for (size_t i = 0; i < arr->len; ++i) {
+ ranked_rr_array_entry_t *entry = arr->at[i];
+ if (entry->yielded || entry->qry_uid != qry->uid) {
+ continue;
+ }
+ if (kr_rank_test(entry->rank, KR_RANK_MISMATCH)) {
+ invalid_entry = entry;
+ break;
+ } else if (kr_rank_test(entry->rank, KR_RANK_MISSING) &&
+ !invalid_entry) {
+ invalid_entry = entry;
+ } else if (kr_rank_test(entry->rank, KR_RANK_OMIT)) {
+ continue;
+ } else if (!kr_rank_test(entry->rank, KR_RANK_SECURE) &&
+ !invalid_entry) {
+ invalid_entry = entry;
+ }
+ }
+
+ if (!invalid_entry) {
+ return ret;
+ }
+
+ if (!kr_rank_test(invalid_entry->rank, KR_RANK_SECURE) &&
+ (++(invalid_entry->revalidation_cnt) > MAX_REVALIDATION_CNT)) {
+ VERBOSE_MSG(qry, "<= continuous revalidation, fails\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+
+ const knot_rrset_t *rr = invalid_entry->rr;
+ if (kr_rank_test(invalid_entry->rank, KR_RANK_MISMATCH)) {
+ const knot_dname_t *signer_name = knot_rrsig_signer_name(rr->rrs.rdata);
+ if (knot_dname_in_bailiwick(signer_name, qry->zone_cut.name) > 0) {
+ qry->zone_cut.name = knot_dname_copy(signer_name, &req->pool);
+ qry->flags.AWAIT_CUT = true;
+ } else if (!knot_dname_is_equal(signer_name, qry->zone_cut.name)) {
+ if (qry->zone_cut.parent) {
+ memcpy(&qry->zone_cut, qry->zone_cut.parent, sizeof(qry->zone_cut));
+ } else {
+ qry->flags.AWAIT_CUT = true;
+ }
+ qry->zone_cut.name = knot_dname_copy(signer_name, &req->pool);
+ }
+ VERBOSE_MSG(qry, ">< cut changed (new signer), needs revalidation\n");
+ ret = KR_STATE_YIELD;
+ } else if (kr_rank_test(invalid_entry->rank, KR_RANK_MISSING)) {
+ ret = rrsig_not_found(ctx, rr);
+ } else if (!kr_rank_test(invalid_entry->rank, KR_RANK_SECURE)) {
+ qry->flags.DNSSEC_BOGUS = true;
+ ret = KR_STATE_FAIL;
+ }
+
+ return ret;
+}
+
+static bool check_empty_answer(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ ranked_rr_array_t *arr = &req->answ_selected;
+ size_t num_entries = 0;
+ for (size_t i = 0; i < arr->len; ++i) {
+ ranked_rr_array_entry_t *entry = arr->at[i];
+ const knot_rrset_t *rr = entry->rr;
+ if (rr->type == KNOT_RRTYPE_RRSIG && qry->stype != KNOT_RRTYPE_RRSIG) {
+ continue;
+ }
+ if (entry->qry_uid == qry->uid) {
+ ++num_entries;
+ }
+ }
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ return ((an->count != 0) && (num_entries == 0)) ? false : true;
+}
+
+static int unsigned_forward(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ const uint16_t qtype = knot_pkt_qtype(pkt);
+ const uint8_t pkt_rcode = knot_wire_get_rcode(pkt->wire);
+ bool nods = false;
+ bool ns_exist = true;
+ for (int i = 0; i < req->rplan.resolved.len; ++i) {
+ struct kr_query *q = req->rplan.resolved.at[i];
+ if (q->sclass == qry->sclass &&
+ q->stype == KNOT_RRTYPE_DS &&
+ knot_dname_is_equal(q->sname, qry->sname)) {
+ nods = true;
+ if (!(q->flags.DNSSEC_OPTOUT)) {
+ int ret = kr_dnssec_matches_name_and_type(&req->auth_selected, q->uid,
+ qry->sname, KNOT_RRTYPE_NS);
+ ns_exist = (ret == kr_ok());
+ }
+ }
+ }
+
+ if (nods && ns_exist && qtype == KNOT_RRTYPE_NS) {
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ if (qry->forward_flags.CNAME) {
+ assert(qry->cname_parent);
+ qry->cname_parent->flags.DNSSEC_WANT = false;
+ qry->cname_parent->flags.DNSSEC_INSECURE = true;
+ } else if (pkt_rcode == KNOT_RCODE_NOERROR && qry->parent != NULL) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, KNOT_ANSWER);
+ const knot_rrset_t *rr = knot_pkt_rr(sec, 0);
+ if (rr->type == KNOT_RRTYPE_NS) {
+ qry->parent->zone_cut.name = knot_dname_copy(rr->owner, &req->pool);
+ qry->parent->flags.DNSSEC_WANT = false;
+ qry->parent->flags.DNSSEC_INSECURE = true;
+ }
+ }
+ while (qry->parent) {
+ qry = qry->parent;
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ if (qry->forward_flags.CNAME) {
+ assert(qry->cname_parent);
+ qry->cname_parent->flags.DNSSEC_WANT = false;
+ qry->cname_parent->flags.DNSSEC_INSECURE = true;
+ }
+ }
+ return KR_STATE_DONE;
+ }
+
+ if (ctx->state == KR_STATE_YIELD) {
+ return KR_STATE_DONE;
+ }
+
+ if (!nods && qtype != KNOT_RRTYPE_DS) {
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *next = kr_rplan_push(rplan, qry, qry->sname, qry->sclass, KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ kr_zonecut_set(&next->zone_cut, qry->zone_cut.name);
+ kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+ next->flags.DNSSEC_WANT = true;
+ }
+
+ return KR_STATE_YIELD;
+}
+
+static int check_signer(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ const knot_dname_t *ta_name = qry->zone_cut.trust_anchor ? qry->zone_cut.trust_anchor->owner : NULL;
+ const knot_dname_t *signer = signature_authority(req);
+ if (ta_name && (!signer || !knot_dname_is_equal(ta_name, signer))) {
+ /* check all newly added RRSIGs */
+ if (!signer) {
+ if (qry->flags.FORWARD) {
+ return unsigned_forward(ctx, pkt);
+ }
+ /* Not a DNSSEC-signed response. */
+ if (ctx->state == KR_STATE_YIELD) {
+ /* Already yielded for revalidation.
+ * It means that trust chain is OK and
+ * transition to INSECURE hasn't occurred.
+ * Let the validation logic ask about RRSIG. */
+ return KR_STATE_DONE;
+ }
+ /* Ask parent for DS
+ * to prove transition to INSECURE. */
+ const uint16_t qtype = knot_pkt_qtype(pkt);
+ const knot_dname_t *qname = knot_pkt_qname(pkt);
+ if (qtype == KNOT_RRTYPE_NS &&
+ knot_dname_in_bailiwick(qname, qry->zone_cut.name) > 0) {
+ /* Server is authoritative
+ * for both parent and child,
+ * and child zone is not signed. */
+ qry->zone_cut.name = knot_dname_copy(qname, &req->pool);
+ }
+ } else if (knot_dname_in_bailiwick(signer, qry->zone_cut.name) > 0) {
+ if (!(qry->flags.FORWARD)) {
+ /* Key signer is below current cut, advance and refetch keys. */
+ qry->zone_cut.name = knot_dname_copy(signer, &req->pool);
+ } else {
+ /* Check if DS does not exist. */
+ struct kr_query *q = kr_rplan_find_resolved(&req->rplan, NULL,
+ signer, qry->sclass, KNOT_RRTYPE_DS);
+ if (q && q->flags.DNSSEC_NODS) {
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ if (qry->parent) {
+ qry->parent->flags.DNSSEC_WANT = false;
+ qry->parent->flags.DNSSEC_INSECURE = true;
+ }
+ } else if (qry->stype != KNOT_RRTYPE_DS) {
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *next = kr_rplan_push(rplan, qry, qry->sname,
+ qry->sclass, KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ kr_zonecut_set(&next->zone_cut, qry->zone_cut.name);
+ kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+ next->flags.DNSSEC_WANT = true;
+ }
+ }
+ } else if (!knot_dname_is_equal(signer, qry->zone_cut.name)) {
+ /* Key signer is above the current cut, so we can't validate it. This happens when
+ a server is authoritative for both grandparent, parent and child zone.
+ Ascend to parent cut, and refetch authority for signer. */
+ if (qry->zone_cut.parent) {
+ memcpy(&qry->zone_cut, qry->zone_cut.parent, sizeof(qry->zone_cut));
+ } else {
+ qry->flags.AWAIT_CUT = true;
+ }
+ qry->zone_cut.name = knot_dname_copy(signer, &req->pool);
+ }
+
+ /* zone cut matches, but DS/DNSKEY doesn't => refetch. */
+ VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n");
+ if ((qry->flags.FORWARD) && qry->stype != KNOT_RRTYPE_DS) {
+ struct kr_rplan *rplan = &req->rplan;
+ struct kr_query *next = kr_rplan_push(rplan, qry, signer,
+ qry->sclass, KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ kr_zonecut_set(&next->zone_cut, qry->zone_cut.name);
+ kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+ next->flags.DNSSEC_WANT = true;
+ return KR_STATE_YIELD;
+ }
+ if (!(qry->flags.FORWARD)) {
+ return KR_STATE_YIELD;
+ }
+ }
+ return KR_STATE_DONE;
+}
+
+/** Change ranks of RRs from this single iteration:
+ * _INITIAL or _TRY or _MISSING -> rank_to_set.
+ *
+ * Optionally do this only in a `bailiwick` (if not NULL).
+ * Iterator shouldn't have selected such records, but we check to be sure. */
+static void rank_records(kr_layer_t *ctx, enum kr_rank rank_to_set,
+ const knot_dname_t *bailiwick)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ ranked_rr_array_t *ptrs[2] = { &req->answ_selected, &req->auth_selected };
+ for (size_t i = 0; i < 2; ++i) {
+ ranked_rr_array_t *arr = ptrs[i];
+ for (size_t j = 0; j < arr->len; ++j) {
+ ranked_rr_array_entry_t *entry = arr->at[j];
+ if (entry->qry_uid != qry->uid) {
+ continue;
+ }
+ if (bailiwick && knot_dname_in_bailiwick(entry->rr->owner,
+ bailiwick) < 0) {
+ continue;
+ }
+ if (kr_rank_test(entry->rank, KR_RANK_INITIAL)
+ || kr_rank_test(entry->rank, KR_RANK_TRY)
+ || kr_rank_test(entry->rank, KR_RANK_MISSING)) {
+ kr_rank_set(&entry->rank, rank_to_set);
+ }
+ }
+ }
+}
+
+static void check_wildcard(kr_layer_t *ctx)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ ranked_rr_array_t *ptrs[2] = { &req->answ_selected, &req->auth_selected };
+
+ for (int i = 0; i < 2; ++i) {
+ ranked_rr_array_t *arr = ptrs[i];
+ for (ssize_t j = 0; j < arr->len; ++j) {
+ ranked_rr_array_entry_t *entry = arr->at[j];
+ const knot_rrset_t *rrsigs = entry->rr;
+
+ if (qry->uid != entry->qry_uid) {
+ continue;
+ }
+
+ if (rrsigs->type != KNOT_RRTYPE_RRSIG) {
+ continue;
+ }
+
+ int owner_labels = knot_dname_labels(rrsigs->owner, NULL);
+
+ knot_rdata_t *rdata_k = rrsigs->rrs.rdata;
+ for (int k = 0; k < rrsigs->rrs.count;
+ ++k, rdata_k = knot_rdataset_next(rdata_k)) {
+ if (knot_rrsig_labels(rdata_k) != owner_labels) {
+ qry->flags.DNSSEC_WEXPAND = true;
+ }
+ }
+ }
+ }
+}
+
+/** Just for wildcard_adjust_to_wire() */
+static bool rr_is_for_wildcard(const ranked_rr_array_entry_t *entry)
+{
+ switch (kr_rrset_type_maysig(entry->rr)) {
+ case KNOT_RRTYPE_NSEC:
+ case KNOT_RRTYPE_NSEC3:
+ return true;
+ default:
+ return false;
+ }
+}
+/** In case of wildcard expansion, mark required authority RRs by to_wire. */
+static int wildcard_adjust_to_wire(struct kr_request *req, const struct kr_query *qry)
+{
+ if (!qry->parent && qry->flags.DNSSEC_WEXPAND) {
+ return kr_ranked_rrarray_set_wire(&req->auth_selected, true,
+ qry->uid, true, &rr_is_for_wildcard);
+ }
+ return kr_ok();
+}
+
+static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ int ret = 0;
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+
+ /* Ignore faulty or unprocessed responses. */
+ if (ctx->state & (KR_STATE_FAIL|KR_STATE_CONSUME)) {
+ return ctx->state;
+ }
+
+ /* Pass-through if user doesn't want secure answer or stub. */
+ /* @todo: Validating stub resolver mode. */
+ if (qry->flags.STUB) {
+ rank_records(ctx, KR_RANK_OMIT, NULL);
+ return ctx->state;
+ }
+ uint8_t pkt_rcode = knot_wire_get_rcode(pkt->wire);
+ if ((qry->flags.FORWARD) &&
+ pkt_rcode != KNOT_RCODE_NOERROR &&
+ pkt_rcode != KNOT_RCODE_NXDOMAIN) {
+ do {
+ qry->flags.DNSSEC_BOGUS = true;
+ if (qry->cname_parent) {
+ qry->cname_parent->flags.DNSSEC_BOGUS = true;
+ }
+ qry = qry->parent;
+ } while (qry);
+ ctx->state = KR_STATE_DONE;
+ return ctx->state;
+ }
+
+ if (!(qry->flags.DNSSEC_WANT)) {
+ const bool is_insec = qry->flags.CACHED && qry->flags.DNSSEC_INSECURE;
+ if ((qry->flags.DNSSEC_INSECURE)) {
+ rank_records(ctx, KR_RANK_INSECURE, qry->zone_cut.name);
+ }
+ if (is_insec && qry->parent != NULL) {
+ /* We have got insecure answer from cache.
+ * Mark parent(s) as insecure. */
+ mark_insecure_parents(qry);
+ VERBOSE_MSG(qry, "<= cached insecure response, going insecure\n");
+ ctx->state = KR_STATE_DONE;
+ } else if (ctx->state == KR_STATE_YIELD) {
+ /* Transition to unsecure state
+ occurred during revalidation.
+ if state remains YIELD, answer will not be cached.
+ Let cache layers to work. */
+ ctx->state = KR_STATE_DONE;
+ }
+ return ctx->state;
+ }
+
+ /* Pass-through if CD bit is set. */
+ if (knot_wire_get_cd(req->qsource.packet->wire)) {
+ check_wildcard(ctx);
+ wildcard_adjust_to_wire(req, qry);
+ rank_records(ctx, KR_RANK_OMIT, NULL);
+ return ctx->state;
+ }
+ /* Answer for RRSIG may not set DO=1, but all records MUST still validate. */
+ bool use_signatures = (knot_pkt_qtype(pkt) != KNOT_RRTYPE_RRSIG);
+ if (!(qry->flags.CACHED) && !knot_pkt_has_dnssec(pkt) && !use_signatures) {
+ VERBOSE_MSG(qry, "<= got insecure response\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+
+ /* Check if this is a DNSKEY answer, check trust chain and store. */
+ uint16_t qtype = knot_pkt_qtype(pkt);
+ bool has_nsec3 = pkt_has_type(pkt, KNOT_RRTYPE_NSEC3);
+ const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
+ const bool referral = (an->count == 0 && !knot_wire_get_aa(pkt->wire));
+
+ if (!(qry->flags.CACHED) && knot_wire_get_aa(pkt->wire)) {
+ /* Check if answer if not empty,
+ * but iterator has not selected any records. */
+ if (!check_empty_answer(ctx, pkt)) {
+ VERBOSE_MSG(qry, "<= no useful RR in authoritative answer\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+ /* Track difference between current TA and signer name.
+ * This indicates that the NS is auth for both parent-child,
+ * and we must update DS/DNSKEY to validate it.
+ */
+ ret = check_signer(ctx, pkt);
+ if (ret != KR_STATE_DONE) {
+ return ret;
+ }
+ if (qry->flags.FORWARD && qry->flags.DNSSEC_INSECURE) {
+ return KR_STATE_DONE;
+ }
+ }
+
+ if (knot_wire_get_aa(pkt->wire) && qtype == KNOT_RRTYPE_DNSKEY) {
+ ret = validate_keyset(req, pkt, has_nsec3);
+ if (ret == kr_error(EAGAIN)) {
+ VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n");
+ return KR_STATE_YIELD;
+ } else if (ret == kr_error(DNSSEC_INVALID_DS_ALGORITHM)) {
+ VERBOSE_MSG(qry, ">< all DS entries use unsupported algorithm pairs, going insecure\n");
+ /* ^ the message is a bit imprecise to avoid being too verbose */
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ rank_records(ctx, KR_RANK_INSECURE, qry->zone_cut.name);
+ mark_insecure_parents(qry);
+ return KR_STATE_DONE;
+ } else if (ret != 0) {
+ VERBOSE_MSG(qry, "<= bad keys, broken trust chain\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+ }
+
+ /* Validate non-existence proof if not positive answer.
+ * In case of CNAME, iterator scheduled a sibling query for the target,
+ * so we just drop the negative piece of information and don't try to prove it.
+ * TODO: not ideal; with aggressive cache we'll at least avoid the extra packet. */
+ if (!qry->flags.CACHED && pkt_rcode == KNOT_RCODE_NXDOMAIN && !qry->flags.CNAME) {
+ /* @todo If knot_pkt_qname(pkt) is used instead of qry->sname then the tests crash. */
+ if (!has_nsec3) {
+ ret = kr_nsec_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname);
+ } else {
+ ret = kr_nsec3_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname);
+ }
+ if (has_nsec3 && (ret == kr_error(KNOT_ERANGE))) {
+ /* NXDOMAIN proof is OK,
+ * but NSEC3 that covers next closer name
+ * (or wildcard at next closer name) has opt-out flag.
+ * RFC5155 9.2; AD flag can not be set */
+ qry->flags.DNSSEC_OPTOUT = true;
+ VERBOSE_MSG(qry, "<= can't prove NXDOMAIN due to optout, going insecure\n");
+ } else if (ret != 0) {
+ VERBOSE_MSG(qry, "<= bad NXDOMAIN proof\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+ }
+
+ /* @todo WTH, this needs API that just tries to find a proof and the caller
+ * doesn't have to worry about NSEC/NSEC3
+ * @todo rework this
+ * CNAME: same as the NXDOMAIN case above */
+ if (!qry->flags.CACHED && pkt_rcode == KNOT_RCODE_NOERROR && !qry->flags.CNAME) {
+ bool no_data = (an->count == 0 && knot_wire_get_aa(pkt->wire));
+ if (no_data) {
+ /* @todo
+ * ? quick mechanism to determine which check to preform first
+ * ? merge the functionality together to share code/resources
+ */
+ if (!has_nsec3) {
+ ret = kr_nsec_existence_denial(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
+ } else {
+ ret = kr_nsec3_no_data(pkt, KNOT_AUTHORITY, knot_pkt_qname(pkt), knot_pkt_qtype(pkt));
+ }
+ if (ret != 0) {
+ if (has_nsec3 && (ret == kr_error(KNOT_ERANGE))) {
+ VERBOSE_MSG(qry, "<= can't prove NODATA due to optout, going insecure\n");
+ qry->flags.DNSSEC_OPTOUT = true;
+ /* Could not return from here,
+ * we must continue, validate NSEC\NSEC3 and
+ * call update_parent_keys() to mark
+ * parent queries as insecured */
+ } else {
+ VERBOSE_MSG(qry, "<= bad NODATA proof\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+ }
+ }
+ }
+
+ /* Validate all records, fail as bogus if it doesn't match.
+ * Do not revalidate data from cache, as it's already trusted. */
+ if (!(qry->flags.CACHED)) {
+ ret = validate_records(req, pkt, req->rplan.pool, has_nsec3);
+ if (ret != 0) {
+ /* something exceptional - no DNS key, empty pointers etc
+ * normally it shoudn't happen */
+ VERBOSE_MSG(qry, "<= couldn't validate RRSIGs\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ }
+ /* check validation state and spawn subrequests */
+ if (!req->answ_validated) {
+ ret = check_validation_result(ctx, &req->answ_selected);
+ if (ret != KR_STATE_DONE) {
+ return ret;
+ }
+ }
+ if (!req->auth_validated) {
+ ret = check_validation_result(ctx, &req->auth_selected);
+ if (ret != KR_STATE_DONE) {
+ return ret;
+ }
+ }
+ }
+
+ wildcard_adjust_to_wire(req, qry);
+
+ /* Check and update current delegation point security status. */
+ ret = update_delegation(req, qry, pkt, has_nsec3);
+ if (ret == DNSSEC_NOT_FOUND && qry->stype != KNOT_RRTYPE_DS) {
+ if (ctx->state == KR_STATE_YIELD) {
+ VERBOSE_MSG(qry, "<= can't validate referral\n");
+ qry->flags.DNSSEC_BOGUS = true;
+ return KR_STATE_FAIL;
+ } else {
+ /* Check the trust chain and query DS\DNSKEY if needed. */
+ VERBOSE_MSG(qry, "<= DS\\NSEC was not found, querying for DS\n");
+ return KR_STATE_YIELD;
+ }
+ } else if (ret != 0) {
+ return KR_STATE_FAIL;
+ } else if (pkt_rcode == KNOT_RCODE_NOERROR &&
+ referral &&
+ ((!qry->flags.DNSSEC_WANT && qry->flags.DNSSEC_INSECURE) ||
+ (qry->flags.DNSSEC_NODS))) {
+ /* referral with proven DS non-existance */
+ qtype = KNOT_RRTYPE_DS;
+ }
+ /* Update parent query zone cut */
+ if (qry->parent) {
+ if (update_parent_keys(req, qtype) != 0) {
+ return KR_STATE_FAIL;
+ }
+ }
+
+ if (qry->flags.FORWARD && qry->parent) {
+ if (pkt_rcode == KNOT_RCODE_NXDOMAIN) {
+ qry->parent->forward_flags.NO_MINIMIZE = true;
+ }
+ }
+ VERBOSE_MSG(qry, "<= answer valid, OK\n");
+ return KR_STATE_DONE;
+}
+/** Module implementation. */
+const kr_layer_api_t *validate_layer(struct kr_module *module)
+{
+ static const kr_layer_api_t _layer = {
+ .consume = &validate,
+ };
+ /* Store module reference */
+ return &_layer;
+}
+
+int validate_init(struct kr_module *module)
+{
+ return kr_ok();
+}
+
+KR_MODULE_EXPORT(validate)
+
+#undef VERBOSE_MSG
diff --git a/lib/lib.mk b/lib/lib.mk
new file mode 100644
index 0000000..8ac4e91
--- /dev/null
+++ b/lib/lib.mk
@@ -0,0 +1,110 @@
+libkres_SOURCES := \
+ lib/cache/api.c \
+ lib/cache/cdb_lmdb.c \
+ lib/cache/entry_list.c \
+ lib/cache/entry_pkt.c \
+ lib/cache/entry_rr.c \
+ lib/cache/knot_pkt.c \
+ lib/cache/nsec1.c \
+ lib/cache/nsec3.c \
+ lib/cache/peek.c \
+ lib/dnssec.c \
+ lib/dnssec/nsec.c \
+ lib/dnssec/nsec3.c \
+ lib/dnssec/signature.c \
+ lib/dnssec/ta.c \
+ lib/generic/lru.c \
+ lib/generic/map.c \
+ lib/generic/queue.c \
+ lib/generic/trie.c \
+ lib/layer/cache.c \
+ lib/layer/iterate.c \
+ lib/layer/validate.c \
+ lib/module.c \
+ lib/nsrep.c \
+ lib/resolve.c \
+ lib/rplan.c \
+ lib/utils.c \
+ lib/zonecut.c
+
+libkres_HEADERS := \
+ lib/cache/api.h \
+ lib/cache/cdb_api.h \
+ lib/cache/cdb_lmdb.h \
+ lib/cache/impl.h \
+ lib/defines.h \
+ lib/dnssec.h \
+ lib/dnssec/nsec.h \
+ lib/dnssec/nsec3.h \
+ lib/dnssec/signature.h \
+ lib/dnssec/ta.h \
+ lib/generic/array.h \
+ lib/generic/lru.h \
+ lib/generic/map.h \
+ lib/generic/pack.h \
+ lib/generic/queue.h \
+ lib/generic/trie.h \
+ lib/layer.h \
+ lib/layer/iterate.h \
+ lib/module.h \
+ lib/nsrep.h \
+ lib/resolve.h \
+ lib/rplan.h \
+ lib/utils.h \
+ lib/zonecut.h
+
+# Dependencies
+libkres_DEPEND := $(contrib)
+libkres_CFLAGS := -fPIC $(lmdb_CFLAGS)
+libkres_LIBS := $(contrib_TARGET) $(libknot_LIBS) $(libdnssec_LIBS) $(lmdb_LIBS) \
+ $(libuv_LIBS) $(gnutls_LIBS)
+libkres_TARGET := -L$(abspath lib) -lkres
+
+ifeq ($(ENABLE_COOKIES),yes)
+libkres_SOURCES += \
+ lib/cookies/alg_containers.c \
+ lib/cookies/alg_sha.c \
+ lib/cookies/helper.c \
+ lib/cookies/lru_cache.c \
+ lib/cookies/nonce.c
+
+libkres_HEADERS += \
+ lib/cookies/alg_containers.h \
+ lib/cookies/alg_sha.h \
+ lib/cookies/control.h \
+ lib/cookies/helper.h \
+ lib/cookies/lru_cache.h \
+ lib/cookies/nonce.h
+
+libkres_LIBS += $(nettle_LIBS)
+endif
+
+# Make library
+ifeq ($(BUILDMODE), static)
+$(eval $(call make_static,libkres,lib,yes))
+else
+$(eval $(call make_lib,libkres,lib,yes,$(ABIVER)))
+endif
+
+# Generate pkg-config file
+libkres.pc:
+ @echo 'prefix='$(PREFIX) > $@
+ @echo 'exec_prefix=$${prefix}' >> $@
+ @echo 'libdir='$(LIBDIR) >> $@
+ @echo 'includedir='$(INCLUDEDIR) >> $@
+ @echo 'Name: libkres' >> $@
+ @echo 'Description: Knot Resolver library' >> $@
+ @echo 'URL: https://www.knot-resolver.cz' >> $@
+ @echo 'Version: $(VERSION)' >> $@
+ @echo 'Libs: -L$${libdir} -lkres' >> $@
+ @echo 'Cflags: -I$${includedir}' >> $@
+libkres-pcinstall: libkres.pc libkres-install
+ $(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)
+ $(INSTALL) -m 644 $< $(DESTDIR)$(PKGCONFIGDIR)
+
+# Targets
+lib: $(libkres)
+lib-install: libkres-install libkres-pcinstall
+lib-clean: libkres-clean
+
+.PHONY: lib lib-install lib-clean libkres.pc
diff --git a/lib/module.c b/lib/module.c
new file mode 100644
index 0000000..68abc84
--- /dev/null
+++ b/lib/module.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <contrib/cleanup.h>
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include "lib/module.h"
+
+/* List of embedded modules */
+const kr_layer_api_t *iterate_layer(struct kr_module *module);
+const kr_layer_api_t *validate_layer(struct kr_module *module);
+const kr_layer_api_t *cache_layer(struct kr_module *module);
+static const struct kr_module embedded_modules[] = {
+ { "iterate", NULL, NULL, NULL, iterate_layer, NULL, NULL, NULL },
+ { "validate", NULL, NULL, NULL, validate_layer, NULL, NULL, NULL },
+ { "cache", NULL, NULL, NULL, cache_layer, NULL, NULL, NULL },
+};
+
+/** Library extension. */
+#if defined(__APPLE__)
+ #define LIBEXT ".dylib"
+#elif _WIN32
+ #define LIBEXT ".dll"
+#else
+ #define LIBEXT ".so"
+#endif
+
+
+/** Load prefixed symbol. */
+static void *load_symbol(void *lib, const char *prefix, const char *name)
+{
+ auto_free char *symbol = kr_strcatdup(2, prefix, name);
+ return dlsym(lib, symbol);
+}
+
+static int load_library(struct kr_module *module, const char *name, const char *path)
+{
+ assert(module && name && path);
+ /* Absolute or relative path (then only library search path is used). */
+ auto_free char *lib_path = kr_strcatdup(4, path, "/", name, LIBEXT);
+ if (lib_path == NULL) {
+ return kr_error(ENOMEM);
+ }
+
+ /* Workaround for buggy _fini/__attribute__((destructor)) and dlclose(),
+ * this keeps the library mapped until the program finishes though. */
+ module->lib = dlopen(lib_path, RTLD_NOW | RTLD_NODELETE);
+ if (module->lib) {
+ return kr_ok();
+ }
+
+ return kr_error(ENOENT);
+}
+
+const struct kr_module * kr_module_embedded(const char *name)
+{
+ for (unsigned i = 0; i < sizeof(embedded_modules)/sizeof(embedded_modules[0]); ++i) {
+ if (strcmp(name, embedded_modules[i].name) == 0)
+ return embedded_modules + i;
+ }
+ return NULL;
+}
+
+/** Load C module symbols. */
+static int load_sym_c(struct kr_module *module, uint32_t api_required)
+{
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic" /* casts after load_symbol() */
+ /* Check if it's embedded first */
+ const struct kr_module *embedded = kr_module_embedded(module->name);
+ if (embedded) {
+ module->init = embedded->init;
+ module->deinit = embedded->deinit;
+ module->config = embedded->config;
+ module->layer = embedded->layer;
+ module->props = embedded->props;
+ return kr_ok();
+ }
+ /* Load dynamic library module */
+ auto_free char *m_prefix = kr_strcatdup(2, module->name, "_");
+
+ /* Check ABI version, return error on mismatch. */
+ module_api_cb *api = load_symbol(module->lib, m_prefix, "api");
+ if (api == NULL) {
+ return kr_error(ENOENT);
+ }
+ if (api() != api_required) {
+ return kr_error(ENOTSUP);
+ }
+
+ /* Load ABI by symbol names. */
+ #define ML(symname) module->symname = \
+ load_symbol(module->lib, m_prefix, #symname)
+ ML(init);
+ ML(deinit);
+ ML(config);
+ ML(layer);
+ ML(props);
+ #undef ML
+
+ return kr_ok();
+ #pragma GCC diagnostic pop
+}
+
+int kr_module_load(struct kr_module *module, const char *name, const char *path)
+{
+ if (module == NULL || name == NULL) {
+ return kr_error(EINVAL);
+ }
+
+ /* Initialize, keep userdata */
+ void *data = module->data;
+ memset(module, 0, sizeof(struct kr_module));
+ module->data = data;
+ module->name = strdup(name);
+ if (module->name == NULL) {
+ return kr_error(ENOMEM);
+ }
+
+ /* Search for module library. */
+ if (!path || load_library(module, name, path) != 0) {
+ module->lib = RTLD_DEFAULT;
+ }
+
+ /* Try to load module ABI. */
+ int ret = load_sym_c(module, KR_MODULE_API);
+ if (ret == 0 && module->init) {
+ ret = module->init(module);
+ }
+ if (ret != 0) {
+ kr_module_unload(module);
+ }
+
+ return ret;
+}
+
+void kr_module_unload(struct kr_module *module)
+{
+ if (module == NULL) {
+ return;
+ }
+
+ if (module->deinit) {
+ module->deinit(module);
+ }
+
+ if (module->lib && module->lib != RTLD_DEFAULT) {
+ dlclose(module->lib);
+ }
+
+ free(module->name);
+ memset(module, 0, sizeof(struct kr_module));
+}
diff --git a/lib/module.h b/lib/module.h
new file mode 100644
index 0000000..295c1f9
--- /dev/null
+++ b/lib/module.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Module API definition and functions for (un)loading modules.
+ */
+
+#pragma once
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include "lib/layer.h"
+
+struct kr_module;
+struct kr_prop;
+
+
+/**
+ * Export module API version (place this at the end of your module).
+ *
+ * @param module module name (f.e. hints)
+ */
+#define KR_MODULE_EXPORT(module) \
+ KR_EXPORT uint32_t module ## _api() { return KR_MODULE_API; }
+#define KR_MODULE_API ((uint32_t) 0x20180401)
+
+typedef uint32_t (module_api_cb)(void);
+
+
+/**
+ * Module representation.
+ *
+ * The five symbols (init, ...) may be defined by the module as name_init(), etc;
+ * all are optional and missing symbols are represented as NULLs;
+ */
+struct kr_module {
+ char *name;
+
+ /** Constructor. Called after loading the module. @return error code. */
+ int (*init)(struct kr_module *self);
+ /** Destructor. Called before unloading the module. @return error code. */
+ int (*deinit)(struct kr_module *self);
+ /** Configure with encoded JSON (NULL if missing). @return error code. */
+ int (*config)(struct kr_module *self, const char *input);
+ /** Get a pointer to packet processing API specs. See docs on that type. */
+ const kr_layer_api_t * (*layer)(struct kr_module *self);
+ /** Get a pointer to list of properties, terminated by { NULL, NULL, NULL }. */
+ const struct kr_prop * (*props)(void);
+
+ void *lib; /**< Shared library handle or RTLD_DEFAULT */
+ void *data; /**< Custom data context. */
+};
+
+/**
+ * Module property callback. Input and output is passed via a JSON encoded in a string.
+ *
+ * @param env pointer to the lua engine, i.e. struct engine *env (TODO: explicit type)
+ * @param input parameter (NULL if missing/nil on lua level)
+ * @return a free-form JSON output (malloc-ated)
+ * @note see l_trampoline() implementation for details about the input/output conversion.
+ */
+typedef char *(kr_prop_cb)(void *env, struct kr_module *self, const char *input);
+
+/**
+ * Module property (named callable).
+ */
+struct kr_prop {
+ kr_prop_cb *cb;
+ const char *name;
+ const char *info;
+};
+
+
+/**
+ * Load a C module instance into memory.
+ *
+ * @param module module structure
+ * @param name module name
+ * @param path module search path
+ * @return 0 or an error
+ */
+KR_EXPORT
+int kr_module_load(struct kr_module *module, const char *name, const char *path);
+
+/**
+ * Unload module instance.
+ *
+ * @param module module structure
+ */
+KR_EXPORT
+void kr_module_unload(struct kr_module *module);
+
+/**
+ * Get embedded module prototype by name (or NULL).
+ */
+KR_EXPORT
+const struct kr_module * kr_module_embedded(const char *name);
+
diff --git a/lib/nsrep.c b/lib/nsrep.c
new file mode 100644
index 0000000..2af12f2
--- /dev/null
+++ b/lib/nsrep.c
@@ -0,0 +1,563 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <arpa/inet.h>
+
+#include "lib/nsrep.h"
+#include "lib/rplan.h"
+#include "lib/resolve.h"
+#include "lib/defines.h"
+#include "lib/generic/pack.h"
+#include "contrib/ucw/lib.h"
+
+/** Some built-in unfairness ... */
+#ifndef FAVOUR_IPV6
+#define FAVOUR_IPV6 20 /* 20ms bonus for v6 */
+#endif
+
+/** @internal Macro to set address structure. */
+#define ADDR_SET(sa, family, addr, len, port) do {\
+ memcpy(&sa ## _addr, (addr), (len)); \
+ sa ## _family = (family); \
+ sa ## _port = htons(port); \
+} while (0)
+
+/** Update nameserver representation with current name/address pair. */
+static void update_nsrep(struct kr_nsrep *ns, size_t pos, uint8_t *addr, size_t addr_len, int port)
+{
+ if (addr == NULL) {
+ ns->addr[pos].ip.sa_family = AF_UNSPEC;
+ return;
+ }
+
+ /* Rotate previous addresses to the right. */
+ memmove(ns->addr + pos + 1, ns->addr + pos, (KR_NSREP_MAXADDR - pos - 1) * sizeof(ns->addr[0]));
+
+ switch(addr_len) {
+ case sizeof(struct in_addr):
+ ADDR_SET(ns->addr[pos].ip4.sin, AF_INET, addr, addr_len, port); break;
+ case sizeof(struct in6_addr):
+ ADDR_SET(ns->addr[pos].ip6.sin6, AF_INET6, addr, addr_len, port); break;
+ default: assert(0); break;
+ }
+}
+
+static void update_nsrep_set(struct kr_nsrep *ns, const knot_dname_t *name, uint8_t *addr[], unsigned score)
+{
+ /* NSLIST is not empty, empty NS cannot be a leader. */
+ if (!addr[0] && ns->addr[0].ip.sa_family != AF_UNSPEC) {
+ return;
+ }
+ /* Set new NS leader */
+ ns->name = name;
+ ns->score = score;
+ for (size_t i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ if (addr[i]) {
+ void *addr_val = pack_obj_val(addr[i]);
+ size_t len = pack_obj_len(addr[i]);
+ update_nsrep(ns, i, addr_val, len, KR_DNS_PORT);
+ } else {
+ break;
+ }
+ }
+}
+
+#undef ADDR_SET
+
+/**
+ * \param addr_set pack with one IP address per element */
+static unsigned eval_addr_set(const pack_t *addr_set, struct kr_context *ctx,
+ struct kr_qflags opts, unsigned score, uint8_t *addr[])
+{
+ kr_nsrep_rtt_lru_t *rtt_cache = ctx->cache_rtt;
+ kr_nsrep_rtt_lru_entry_t *rtt_cache_entry_ptr[KR_NSREP_MAXADDR] = { NULL, };
+ assert (KR_NSREP_MAXADDR >= 2);
+ unsigned rtt_cache_entry_score[KR_NSREP_MAXADDR] = { score, KR_NS_MAX_SCORE + 1, };
+ uint64_t now = kr_now();
+
+ /* Name server is better candidate if it has address record. */
+ for (uint8_t *it = pack_head(*addr_set); it != pack_tail(*addr_set);
+ it = pack_obj_next(it)) {
+ void *val = pack_obj_val(it);
+ size_t len = pack_obj_len(it);
+ unsigned favour = 0;
+ bool is_valid = false;
+ /* Check if the address isn't disabled. */
+ if (len == sizeof(struct in6_addr)) {
+ is_valid = !(opts.NO_IPV6);
+ favour = FAVOUR_IPV6;
+ } else if (len == sizeof(struct in_addr)) {
+ is_valid = !(opts.NO_IPV4);
+ } else {
+ assert(!EINVAL);
+ is_valid = false;
+ }
+
+ if (!is_valid) {
+ continue;
+ }
+
+ /* Get score for the current address. */
+ kr_nsrep_rtt_lru_entry_t *cached = rtt_cache ?
+ lru_get_try(rtt_cache, val, len) :
+ NULL;
+ unsigned cur_addr_score = KR_NS_GLUED;
+ if (cached) {
+ cur_addr_score = cached->score;
+ if (cached->score >= KR_NS_TIMEOUT) {
+ /* If NS once was marked as "timeouted",
+ * it won't participate in NS elections
+ * at least ctx->cache_rtt_tout_retry_interval milliseconds. */
+ uint64_t elapsed = now - cached->tout_timestamp;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+ if (elapsed > ctx->cache_rtt_tout_retry_interval) {
+ /* Select this NS for probing in this particular query,
+ * but don't change the cached score.
+ * For other queries this NS will remain "timeouted". */
+ cur_addr_score = KR_NS_LONG - 1;
+ }
+ }
+ }
+
+ for (size_t i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ if (cur_addr_score >= KR_NS_TIMEOUT) {
+ /* We can't use favour here.
+ * If all of the conditions below are true
+ *
+ * rtt_cache_entry_score[i] < KR_NS_TIMEOUT
+ * rtt_cache_entry_score[i] + favour > KR_NS_TIMEOUT
+ * cur_addr_score < rtt_cache_entry_score[i] + favour
+ *
+ * we will prefer "certainly dead" cur_addr_score
+ * instead of "almost dead, but alive" rtt_cache_entry_score[i]
+ */
+ if (cur_addr_score >= rtt_cache_entry_score[i]) {
+ continue;
+ }
+ }
+ if (cur_addr_score >= KR_NS_TIMEOUT
+ || cur_addr_score < rtt_cache_entry_score[i] + favour) {
+ /* Shake down previous contenders */
+ for (size_t j = KR_NSREP_MAXADDR - 1; j > i; --j) {
+ addr[j] = addr[j - 1];
+ rtt_cache_entry_ptr[j] = rtt_cache_entry_ptr[j - 1];
+ rtt_cache_entry_score[j] = rtt_cache_entry_score[j - 1];
+ }
+ addr[i] = it;
+ rtt_cache_entry_score[i] = cur_addr_score;
+ rtt_cache_entry_ptr[i] = cached;
+ break;
+ }
+ }
+ }
+
+ /* At this point, rtt_cache_entry_ptr contains up to KR_NSREP_MAXADDR
+ * pointers to the rtt cache entries with the best scores for the given addr_set.
+ * Check if there are timeouted NS. */
+
+ for (size_t i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ if (rtt_cache_entry_ptr[i] == NULL)
+ continue;
+ if (rtt_cache_entry_ptr[i]->score < KR_NS_TIMEOUT)
+ continue;
+
+ uint64_t elapsed = now - rtt_cache_entry_ptr[i]->tout_timestamp;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+ if (elapsed <= ctx->cache_rtt_tout_retry_interval)
+ continue;
+
+ /* rtt_cache_entry_ptr[i] points to "timeouted" rtt cache entry.
+ * The period of the ban on participation in elections has expired. */
+
+ if (VERBOSE_STATUS) {
+ void *val = pack_obj_val(addr[i]);
+ size_t len = pack_obj_len(addr[i]);
+ char sa_str[INET6_ADDRSTRLEN];
+ int af = (len == sizeof(struct in6_addr)) ? AF_INET6 : AF_INET;
+ inet_ntop(af, val, sa_str, sizeof(sa_str));
+ kr_log_verbose("[ ][nsre] probing timeouted NS: %s, score %i\n",
+ sa_str, rtt_cache_entry_ptr[i]->score);
+ }
+
+ rtt_cache_entry_ptr[i]->tout_timestamp = now;
+ }
+
+ return rtt_cache_entry_score[0];
+}
+
+static int eval_nsrep(const knot_dname_t *owner, const pack_t *addr_set, struct kr_query *qry)
+{
+ struct kr_nsrep *ns = &qry->ns;
+ struct kr_context *ctx = ns->ctx;
+ unsigned score = KR_NS_MAX_SCORE;
+ unsigned reputation = 0;
+ uint8_t *addr_choice[KR_NSREP_MAXADDR] = { NULL, };
+
+ /* Fetch NS reputation */
+ if (ctx->cache_rep) {
+ unsigned *cached = lru_get_try(ctx->cache_rep, (const char *)owner,
+ knot_dname_size(owner));
+ if (cached) {
+ reputation = *cached;
+ }
+ }
+
+ /* Favour nameservers with unknown addresses to probe them,
+ * otherwise discover the current best address for the NS. */
+ if (addr_set->len == 0) {
+ score = KR_NS_UNKNOWN;
+ /* If the server doesn't have IPv6, give it disadvantage. */
+ if (reputation & KR_NS_NOIP6) {
+ score += FAVOUR_IPV6;
+ /* If the server is unknown but has rep record, treat it as timeouted */
+ if (reputation & KR_NS_NOIP4) {
+ score = KR_NS_UNKNOWN;
+ /* Try to start with clean slate */
+ if (!(qry->flags.NO_IPV6)) {
+ reputation &= ~KR_NS_NOIP6;
+ }
+ if (!(qry->flags.NO_IPV4)) {
+ reputation &= ~KR_NS_NOIP4;
+ }
+ }
+ }
+ } else {
+ score = eval_addr_set(addr_set, ctx, qry->flags, score, addr_choice);
+ }
+
+ /* Probabilistic bee foraging strategy (naive).
+ * The fastest NS is preferred by workers until it is depleted (timeouts or degrades),
+ * at the same time long distance scouts probe other sources (low probability).
+ * Servers on TIMEOUT will not have probed at all.
+ * Servers with score above KR_NS_LONG will have periodically removed from
+ * reputation cache, so that kresd can reprobe them. */
+ if (score >= KR_NS_TIMEOUT) {
+ return kr_ok();
+ } else if (score <= ns->score &&
+ (score < KR_NS_LONG || qry->flags.NO_THROTTLE)) {
+ update_nsrep_set(ns, owner, addr_choice, score);
+ ns->reputation = reputation;
+ } else if (kr_rand_coin(1, 10) &&
+ !kr_rand_coin(score, KR_NS_MAX_SCORE)) {
+ /* With 10% chance probe server with a probability
+ * given by its RTT / MAX_RTT. */
+ update_nsrep_set(ns, owner, addr_choice, score);
+ ns->reputation = reputation;
+ return 1; /* Stop evaluation */
+ } else if (ns->score > KR_NS_MAX_SCORE) {
+ /* Check if any server was already selected.
+ * If no, pick current server and continue evaluation. */
+ update_nsrep_set(ns, owner, addr_choice, score);
+ ns->reputation = reputation;
+ }
+
+ return kr_ok();
+}
+
+int kr_nsrep_set(struct kr_query *qry, size_t index, const struct sockaddr *sock)
+{
+ if (!qry) {
+ return kr_error(EINVAL);
+ }
+ if (index >= KR_NSREP_MAXADDR) {
+ return kr_error(ENOSPC);
+ }
+
+ if (!sock) {
+ qry->ns.name = (const uint8_t *)"";
+ qry->ns.addr[index].ip.sa_family = AF_UNSPEC;
+ return kr_ok();
+ }
+
+ switch (sock->sa_family) {
+ case AF_INET:
+ if (qry->flags.NO_IPV4) {
+ return kr_error(ENOENT);
+ }
+ qry->ns.addr[index].ip4 = *(const struct sockaddr_in *)sock;
+ break;
+ case AF_INET6:
+ if (qry->flags.NO_IPV6) {
+ return kr_error(ENOENT);
+ }
+ qry->ns.addr[index].ip6 = *(const struct sockaddr_in6 *)sock;
+ break;
+ default:
+ qry->ns.addr[index].ip.sa_family = AF_UNSPEC;
+ return kr_error(EINVAL);
+ }
+
+ qry->ns.name = (const uint8_t *)"";
+ /* Reset score on first entry */
+ if (index == 0) {
+ qry->ns.score = KR_NS_UNKNOWN;
+ qry->ns.reputation = 0;
+ }
+
+ /* Retrieve RTT from cache */
+ struct kr_context *ctx = qry->ns.ctx;
+ kr_nsrep_rtt_lru_entry_t *rtt_cache_entry = ctx
+ ? lru_get_try(ctx->cache_rtt, kr_inaddr(sock), kr_family_len(sock->sa_family))
+ : NULL;
+ if (rtt_cache_entry) {
+ qry->ns.score = MIN(qry->ns.score, rtt_cache_entry->score);
+ }
+
+ return kr_ok();
+}
+
+#define ELECT_INIT(ns, ctx_) do { \
+ (ns)->ctx = (ctx_); \
+ (ns)->addr[0].ip.sa_family = AF_UNSPEC; \
+ (ns)->reputation = 0; \
+ (ns)->score = KR_NS_MAX_SCORE + 1; \
+} while (0)
+
+int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx)
+{
+ if (!qry || !ctx) {
+ //assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ struct kr_nsrep *ns = &qry->ns;
+ ELECT_INIT(ns, ctx);
+
+ int ret = kr_ok();
+ trie_it_t *it;
+ for (it = trie_it_begin(qry->zone_cut.nsset); !trie_it_finished(it);
+ trie_it_next(it)) {
+ ret = eval_nsrep(/* we trust it's a correct dname */
+ (const knot_dname_t *)trie_it_key(it, NULL),
+ (const pack_t *)*trie_it_val(it), qry);
+ if (ret) break;
+ }
+ trie_it_free(it);
+
+ if (qry->ns.score <= KR_NS_MAX_SCORE && qry->ns.score >= KR_NS_LONG) {
+ /* This is a low-reliability probe,
+ * go with TCP to get ICMP reachability check. */
+ qry->flags.TCP = true;
+ }
+ return ret;
+}
+
+int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx)
+{
+ if (!qry || !ctx) {
+ //assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ /* Get address list for this NS */
+ struct kr_nsrep *ns = &qry->ns;
+ ELECT_INIT(ns, ctx);
+ pack_t *addr_set = kr_zonecut_find(&qry->zone_cut, ns->name);
+ if (!addr_set) {
+ return kr_error(ENOENT);
+ }
+ /* Evaluate addr list */
+ uint8_t *addr_choice[KR_NSREP_MAXADDR] = { NULL, };
+ unsigned score = eval_addr_set(addr_set, ctx, qry->flags, ns->score, addr_choice);
+ update_nsrep_set(ns, ns->name, addr_choice, score);
+ return kr_ok();
+}
+
+#undef ELECT_INIT
+
+int kr_nsrep_update_rtt(struct kr_nsrep *ns, const struct sockaddr *addr,
+ unsigned score, kr_nsrep_rtt_lru_t *cache, int umode)
+{
+ if (!cache || umode > KR_NS_MAX || umode < 0) {
+ return kr_error(EINVAL);
+ }
+
+ /* Get `addr`, and later its raw string. */
+ if (addr) {
+ /* Caller provided specific address, OK. */
+ } else if (ns != NULL) {
+ addr = &ns->addr[0].ip;
+ } else {
+ assert(false && "kr_nsrep_update_rtt: don't know what address to update");
+ return kr_error(EINVAL);
+ }
+ const char *addr_in = kr_inaddr(addr);
+ size_t addr_len = kr_inaddr_len(addr);
+ if (!addr_in || addr_len <= 0) {
+ assert(false && "kr_nsrep_update_rtt: incorrect address");
+ return kr_error(EINVAL);
+ }
+
+ bool is_new_entry = false;
+ kr_nsrep_rtt_lru_entry_t *cur = lru_get_new(cache, addr_in, addr_len,
+ (&is_new_entry));
+ if (!cur) {
+ return kr_ok();
+ }
+ if (score <= KR_NS_GLUED) {
+ score = KR_NS_GLUED + 1;
+ }
+ /* If there's nothing to update, we reset it unless KR_NS_UPDATE_NORESET
+ * mode was requested. New items are zeroed by LRU automatically. */
+ if (is_new_entry && umode != KR_NS_UPDATE_NORESET) {
+ umode = KR_NS_RESET;
+ }
+ unsigned new_score = 0;
+ /* Update score, by default smooth over last two measurements. */
+ switch (umode) {
+ case KR_NS_UPDATE:
+ case KR_NS_UPDATE_NORESET:
+ new_score = (cur->score + score) / 2; break;
+ case KR_NS_RESET: new_score = score; break;
+ case KR_NS_ADD: new_score = MIN(KR_NS_MAX_SCORE - 1, cur->score + score); break;
+ case KR_NS_MAX: new_score = MAX(cur->score, score); break;
+ default: return kr_error(EINVAL);
+ }
+ /* Score limits */
+ if (new_score > KR_NS_MAX_SCORE) {
+ new_score = KR_NS_MAX_SCORE;
+ }
+ if (new_score >= KR_NS_TIMEOUT && cur->score < KR_NS_TIMEOUT) {
+ /* Set the timestamp only when NS became "timeouted" */
+ cur->tout_timestamp = kr_now();
+ }
+ cur->score = new_score;
+ return kr_ok();
+}
+
+int kr_nsrep_update_rep(struct kr_nsrep *ns, unsigned reputation, kr_nsrep_lru_t *cache)
+{
+ if (!ns || !cache ) {
+ return kr_error(EINVAL);
+ }
+
+ /* Store in the struct */
+ ns->reputation = reputation;
+ /* Store reputation in the LRU cache */
+ unsigned *cur = lru_get_new(cache, (const char *)ns->name,
+ knot_dname_size(ns->name), NULL);
+ if (cur) {
+ *cur = reputation;
+ }
+ return kr_ok();
+}
+
+int kr_nsrep_copy_set(struct kr_nsrep *dst, const struct kr_nsrep *src)
+{
+ if (!dst || !src ) {
+ return kr_error(EINVAL);
+ }
+
+ memcpy(dst, src, sizeof(struct kr_nsrep));
+ dst->name = (const uint8_t *)"";
+ dst->score = KR_NS_UNKNOWN;
+ dst->reputation = 0;
+
+ return kr_ok();
+}
+
+int kr_nsrep_sort(struct kr_nsrep *ns, struct kr_context *ctx)
+{
+ if (!ns || !ctx) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+
+ kr_nsrep_rtt_lru_t *rtt_cache = ctx->cache_rtt;
+
+ ns->reputation = 0;
+ ns->score = KR_NS_MAX_SCORE + 1;
+
+ if (ns->addr[0].ip.sa_family == AF_UNSPEC) {
+ return kr_error(EINVAL);
+ }
+
+ /* Compute the scores. Unfortunately there's no space for scores
+ * along the addresses. */
+ unsigned scores[KR_NSREP_MAXADDR];
+ int i;
+ bool timeouted_address_is_already_selected = false;
+ for (i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ const struct sockaddr *sa = &ns->addr[i].ip;
+ if (sa->sa_family == AF_UNSPEC) {
+ break;
+ }
+ kr_nsrep_rtt_lru_entry_t *rtt_cache_entry = lru_get_try(rtt_cache,
+ kr_inaddr(sa),
+ kr_family_len(sa->sa_family));
+ if (!rtt_cache_entry) {
+ scores[i] = 1; /* prefer unknown to probe RTT */
+ } else if (rtt_cache_entry->score < KR_NS_FWD_TIMEOUT) {
+ /* some probability to bump bad ones up for re-probe */
+ scores[i] = rtt_cache_entry->score;
+ /* The lower the rtt, the more likely it will be selected. */
+ if (!kr_rand_coin(rtt_cache_entry->score, KR_NS_FWD_TIMEOUT)) {
+ scores[i] = 1;
+ }
+ } else {
+ uint64_t now = kr_now();
+ uint64_t elapsed = now - rtt_cache_entry->tout_timestamp;
+ scores[i] = KR_NS_MAX_SCORE + 1;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+ if (elapsed > ctx->cache_rtt_tout_retry_interval &&
+ !timeouted_address_is_already_selected) {
+ scores[i] = 1;
+ rtt_cache_entry->tout_timestamp = now;
+ timeouted_address_is_already_selected = true;
+ }
+ }
+
+ /* Give advantage to IPv6. */
+ if (scores[i] <= KR_NS_MAX_SCORE && sa->sa_family == AF_INET) {
+ scores[i] += FAVOUR_IPV6;
+ }
+
+ if (VERBOSE_STATUS) {
+ kr_log_verbose("[ ][nsre] score %d for %s;\t cached RTT: %d\n",
+ scores[i], kr_straddr(sa),
+ rtt_cache_entry ? rtt_cache_entry->score : -1);
+ }
+ }
+
+ /* Select-sort the addresses. */
+ const int count = i;
+ for (i = 0; i < count - 1; ++i) {
+ /* find min from i onwards */
+ int min_i = i;
+ for (int j = i + 1; j < count; ++j) {
+ if (scores[j] < scores[min_i]) {
+ min_i = j;
+ }
+ }
+ /* swap the indices */
+ if (min_i != i) {
+ SWAP(scores[min_i], scores[i]);
+ SWAP(ns->addr[min_i], ns->addr[i]);
+ }
+ }
+
+ if (count > 0) {
+ ns->score = scores[0];
+ ns->reputation = 0;
+ }
+
+ return kr_ok();
+}
diff --git a/lib/nsrep.h b/lib/nsrep.h
new file mode 100644
index 0000000..cc35ca4
--- /dev/null
+++ b/lib/nsrep.h
@@ -0,0 +1,188 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <libknot/dname.h>
+#include <limits.h>
+
+#include "lib/defines.h"
+#include "lib/generic/lru.h"
+
+struct kr_query;
+
+/**
+ * NS RTT score (special values).
+ * @note RTT is measured in milliseconds.
+ */
+enum kr_ns_score {
+ KR_NS_MAX_SCORE = 20 * KR_CONN_RTT_MAX, /* max possible value */
+ KR_NS_FWD_TIMEOUT = (95 * 10000) / 100, /* timeout for upstream recursor,
+ * 95 percents from max resolution time */
+ KR_NS_TIMEOUT = (95 * KR_CONN_RTT_MAX) / 100, /* timeout for upstream auth */
+ KR_NS_LONG = (3 * KR_NS_TIMEOUT) / 4,
+ KR_NS_UNKNOWN = KR_NS_TIMEOUT / 2,
+ KR_NS_PENALTY = 100,
+ KR_NS_GLUED = 10
+};
+
+/**
+ * See kr_nsrep_update_rtt()
+ */
+#define KR_NS_DEAD (((KR_NS_TIMEOUT * 4) + 3) / 3)
+#define KR_NS_FWD_DEAD (((KR_NS_FWD_TIMEOUT * 4) + 3) / 3)
+
+/** If once NS was marked as "timeouted", it won't participate in NS elections
+ * at least KR_NS_TIMEOUT_RETRY_INTERVAL milliseconds (now: one second). */
+#define KR_NS_TIMEOUT_RETRY_INTERVAL 1000
+
+/**
+ * NS QoS flags.
+ */
+enum kr_ns_rep {
+ KR_NS_NOIP4 = 1 << 0, /**< NS has no IPv4 */
+ KR_NS_NOIP6 = 1 << 1, /**< NS has no IPv6 */
+ KR_NS_NOEDNS = 1 << 2 /**< NS has no EDNS support */
+};
+
+/**
+ * NS RTT update modes.
+ * First update is always KR_NS_RESET unless
+ * KR_NS_UPDATE_NORESET mode had choosen.
+ */
+enum kr_ns_update_mode {
+ KR_NS_UPDATE = 0, /**< Update as smooth over last two measurements */
+ KR_NS_UPDATE_NORESET, /**< Same as KR_NS_UPDATE, but disable fallback to
+ * KR_NS_RESET on newly added entries.
+ * Zero is used as initial value. */
+ KR_NS_RESET, /**< Set to given value */
+ KR_NS_ADD, /**< Increment current value */
+ KR_NS_MAX /**< Set to maximum of current/proposed value. */
+};
+
+struct kr_nsrep_rtt_lru_entry {
+ unsigned score; /* combined rtt */
+ uint64_t tout_timestamp; /* The time when score became
+ * greater or equal then KR_NS_TIMEOUT.
+ * Is meaningful only when score >= KR_NS_TIMEOUT */
+};
+
+typedef struct kr_nsrep_rtt_lru_entry kr_nsrep_rtt_lru_entry_t;
+
+/**
+ * NS QoS tracking.
+ */
+typedef lru_t(kr_nsrep_rtt_lru_entry_t) kr_nsrep_rtt_lru_t;
+
+/**
+ * NS reputation tracking.
+ */
+typedef lru_t(unsigned) kr_nsrep_lru_t;
+
+/* Maximum count of addresses probed in one go (last is left empty) */
+#define KR_NSREP_MAXADDR 4
+
+/**
+ * Name server representation.
+ * Contains extra information about the name server, e.g. score
+ * or other metadata.
+ */
+struct kr_nsrep
+{
+ unsigned score; /**< NS score */
+ unsigned reputation; /**< NS reputation */
+ const knot_dname_t *name; /**< NS name */
+ struct kr_context *ctx; /**< Resolution context */
+ union inaddr addr[KR_NSREP_MAXADDR]; /**< NS address(es) */
+};
+
+/**
+ * Set given NS address. (Very low-level access to the list.)
+ * @param qry updated query
+ * @param index index of the updated target
+ * @param sock socket address to use (sockaddr_in or sockaddr_in6 or NULL)
+ * @return 0 or an error code, in particular kr_error(ENOENT) for net.ipvX
+ */
+KR_EXPORT
+int kr_nsrep_set(struct kr_query *qry, size_t index, const struct sockaddr *sock);
+
+/**
+ * Elect best nameserver/address pair from the nsset.
+ * @param qry updated query
+ * @param ctx resolution context
+ * @return 0 or an error code
+ */
+KR_EXPORT
+int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx);
+
+/**
+ * Elect best nameserver/address pair from the nsset.
+ * @param qry updated query
+ * @param ctx resolution context
+ * @return 0 or an error code
+ */
+KR_EXPORT
+int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx);
+
+/**
+ * Update NS address RTT information.
+ *
+ * @brief In KR_NS_UPDATE mode reputation is smoothed over last N measurements.
+ *
+ * @param ns updated NS representation
+ * @param addr chosen address (NULL for first)
+ * @param score new score (i.e. RTT), see enum kr_ns_score
+ * @param cache RTT LRU cache
+ * @param umode update mode (KR_NS_UPDATE or KR_NS_RESET or KR_NS_ADD)
+ * @return 0 on success, error code on failure
+ */
+KR_EXPORT
+int kr_nsrep_update_rtt(struct kr_nsrep *ns, const struct sockaddr *addr,
+ unsigned score, kr_nsrep_rtt_lru_t *cache, int umode);
+
+/**
+ * Update NSSET reputation information.
+ *
+ * @param ns updated NS representation
+ * @param reputation combined reputation flags, see enum kr_ns_rep
+ * @param cache LRU cache
+ * @return 0 on success, error code on failure
+ */
+KR_EXPORT
+int kr_nsrep_update_rep(struct kr_nsrep *ns, unsigned reputation, kr_nsrep_lru_t *cache);
+/**
+ * Copy NSSET reputation information and resets score.
+ *
+ * @param dst updated NS representation
+ * @param src source NS representation
+ * @return 0 on success, error code on failure
+ */
+int kr_nsrep_copy_set(struct kr_nsrep *dst, const struct kr_nsrep *src);
+
+/**
+ * Sort addresses in the query nsrep list by cached RTT.
+ * if RTT is greater then KR_NS_TIMEOUT, address will placed at the beginning of the
+ * nsrep list once in cache.ns_tout() milliseconds. Otherwise it will be sorted
+ * as if it has cached RTT equal to KR_NS_MAX_SCORE + 1.
+ * @param ns updated kr_nsrep
+ * @param ctx name resolution context.
+ * @return 0 or an error code
+ * @note ns reputation is zeroed and score is set to KR_NS_MAX_SCORE + 1.
+ */
+KR_EXPORT
+int kr_nsrep_sort(struct kr_nsrep *ns, struct kr_context *ctx);
diff --git a/lib/resolve.c b/lib/resolve.c
new file mode 100644
index 0000000..8718f25
--- /dev/null
+++ b/lib/resolve.c
@@ -0,0 +1,1648 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include <libknot/rrtype/rdname.h>
+#include <libknot/descriptor.h>
+#include <ucw/mempool.h>
+#include "lib/resolve.h"
+#include "lib/layer.h"
+#include "lib/rplan.h"
+#include "lib/layer/iterate.h"
+#include "lib/dnssec/ta.h"
+#include "lib/dnssec.h"
+#if defined(ENABLE_COOKIES)
+#include "lib/cookies/control.h"
+#include "lib/cookies/helper.h"
+#include "lib/cookies/nonce.h"
+#else /* Define compatibility macros */
+#define KNOT_EDNS_OPTION_COOKIE 10
+#endif /* defined(ENABLE_COOKIES) */
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE((qry), "resl", __VA_ARGS__)
+
+bool kr_rank_check(uint8_t rank)
+{
+ switch (rank & ~KR_RANK_AUTH) {
+ case KR_RANK_INITIAL:
+ case KR_RANK_OMIT:
+ case KR_RANK_TRY:
+ case KR_RANK_INDET:
+ case KR_RANK_BOGUS:
+ case KR_RANK_MISMATCH:
+ case KR_RANK_MISSING:
+ case KR_RANK_INSECURE:
+ case KR_RANK_SECURE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/** @internal Set @a yielded to all RRs with matching @a qry_uid. */
+static void set_yield(ranked_rr_array_t *array, const uint32_t qry_uid, const bool yielded)
+{
+ for (unsigned i = 0; i < array->len; ++i) {
+ ranked_rr_array_entry_t *entry = array->at[i];
+ if (entry->qry_uid == qry_uid) {
+ entry->yielded = yielded;
+ }
+ }
+}
+
+/**
+ * @internal Defer execution of current query.
+ * The current layer state and input will be pushed to a stack and resumed on next iteration.
+ */
+static int consume_yield(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ size_t pkt_size = pkt->size;
+ if (knot_pkt_has_tsig(pkt)) {
+ pkt_size += pkt->tsig_wire.len;
+ }
+ knot_pkt_t *pkt_copy = knot_pkt_new(NULL, pkt_size, &req->pool);
+ struct kr_layer_pickle *pickle = mm_alloc(&req->pool, sizeof(*pickle));
+ if (pickle && pkt_copy && knot_pkt_copy(pkt_copy, pkt) == 0) {
+ struct kr_query *qry = req->current_query;
+ pickle->api = ctx->api;
+ pickle->state = ctx->state;
+ pickle->pkt = pkt_copy;
+ pickle->next = qry->deferred;
+ qry->deferred = pickle;
+ set_yield(&req->answ_selected, qry->uid, true);
+ set_yield(&req->auth_selected, qry->uid, true);
+ return kr_ok();
+ }
+ return kr_error(ENOMEM);
+}
+static int begin_yield(kr_layer_t *ctx) { return kr_ok(); }
+static int reset_yield(kr_layer_t *ctx) { return kr_ok(); }
+static int finish_yield(kr_layer_t *ctx) { return kr_ok(); }
+static int produce_yield(kr_layer_t *ctx, knot_pkt_t *pkt) { return kr_ok(); }
+static int checkout_yield(kr_layer_t *ctx, knot_pkt_t *packet, struct sockaddr *dst, int type) { return kr_ok(); }
+static int answer_finalize_yield(kr_layer_t *ctx) { return kr_ok(); }
+
+/** @internal Macro for iterating module layers. */
+#define RESUME_LAYERS(from, r, qry, func, ...) \
+ (r)->current_query = (qry); \
+ for (size_t i = (from); i < (r)->ctx->modules->len; ++i) { \
+ struct kr_module *mod = (r)->ctx->modules->at[i]; \
+ if (mod->layer) { \
+ struct kr_layer layer = {.state = (r)->state, .api = mod->layer(mod), .req = (r)}; \
+ if (layer.api && layer.api->func) { \
+ (r)->state = layer.api->func(&layer, ##__VA_ARGS__); \
+ if ((r)->state == KR_STATE_YIELD) { \
+ func ## _yield(&layer, ##__VA_ARGS__); \
+ break; \
+ } \
+ } \
+ } \
+ } /* Invalidate current query. */ \
+ (r)->current_query = NULL
+
+/** @internal Macro for starting module iteration. */
+#define ITERATE_LAYERS(req, qry, func, ...) RESUME_LAYERS(0, req, qry, func, ##__VA_ARGS__)
+
+/** @internal Find layer id matching API. */
+static inline size_t layer_id(struct kr_request *req, const struct kr_layer_api *api) {
+ module_array_t *modules = req->ctx->modules;
+ for (size_t i = 0; i < modules->len; ++i) {
+ struct kr_module *mod = modules->at[i];
+ if (mod->layer && mod->layer(mod) == api) {
+ return i;
+ }
+ }
+ return 0; /* Not found, try all. */
+}
+
+/* @internal We don't need to deal with locale here */
+KR_CONST static inline bool isletter(unsigned chr)
+{ return (chr | 0x20 /* tolower */) - 'a' <= 'z' - 'a'; }
+
+/* Randomize QNAME letter case.
+ * This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
+ * https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
+ */
+static void randomized_qname_case(knot_dname_t * restrict qname, uint32_t secret)
+{
+ if (secret == 0) {
+ return;
+ }
+ assert(qname);
+ const int len = knot_dname_size(qname) - 2; /* Skip first, last label. */
+ for (int i = 0; i < len; ++i) {
+ if (isletter(*++qname)) {
+ *qname ^= ((secret >> (i & 31)) & 1) * 0x20;
+ }
+ }
+}
+
+/** Invalidate current NS/addr pair. */
+static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
+{
+ if (qry->ns.addr[0].ip.sa_family != AF_UNSPEC) {
+ const char *addr = kr_inaddr(&qry->ns.addr[0].ip);
+ int addr_len = kr_inaddr_len(&qry->ns.addr[0].ip);
+ return kr_zonecut_del(&qry->zone_cut, qry->ns.name, addr, addr_len);
+ } else {
+ return kr_zonecut_del_all(&qry->zone_cut, qry->ns.name);
+ }
+}
+
+/** This turns of QNAME minimisation if there is a non-terminal between current zone cut, and name target.
+ * It save several minimization steps, as the zone cut is likely final one.
+ */
+static void check_empty_nonterms(struct kr_query *qry, knot_pkt_t *pkt, struct kr_cache *cache, uint32_t timestamp)
+{
+ // FIXME cleanup, etc.
+#if 0
+ if (qry->flags.NO_MINIMIZE) {
+ return;
+ }
+
+ const knot_dname_t *target = qry->sname;
+ const knot_dname_t *cut_name = qry->zone_cut.name;
+ if (!target || !cut_name)
+ return;
+
+ struct kr_cache_entry *entry = NULL;
+ /* @note: The non-terminal must be direct child of zone cut (e.g. label distance <= 2),
+ * otherwise this would risk leaking information to parent if the NODATA TTD > zone cut TTD. */
+ int labels = knot_dname_labels(target, NULL) - knot_dname_labels(cut_name, NULL);
+ while (target[0] && labels > 2) {
+ target = knot_wire_next_label(target, NULL);
+ --labels;
+ }
+ for (int i = 0; i < labels; ++i) {
+ int ret = kr_cache_peek(cache, KR_CACHE_PKT, target, KNOT_RRTYPE_NS, &entry, &timestamp);
+ if (ret == 0) { /* Either NXDOMAIN or NODATA, start here. */
+ /* @todo We could stop resolution here for NXDOMAIN, but we can't because of broken CDNs */
+ qry->flags.NO_MINIMIZE = true;
+ kr_make_query(qry, pkt);
+ break;
+ }
+ assert(target[0]);
+ target = knot_wire_next_label(target, NULL);
+ }
+ kr_cache_sync(cache);
+#endif
+}
+
+static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name,
+ struct kr_request *req, knot_pkt_t *pkt)
+{
+ /* It can occur that here parent query already have
+ * provably insecured zonecut which not in the cache yet. */
+ struct kr_qflags pflags;
+ if (qry->parent) {
+ pflags = qry->parent->flags;
+ }
+ const bool is_insecured = qry->parent != NULL
+ && !(pflags.AWAIT_IPV4 || pflags.AWAIT_IPV6)
+ && (pflags.DNSSEC_INSECURE || pflags.DNSSEC_NODS);
+
+ /* Want DNSSEC if it's possible to secure this name
+ * (e.g. is covered by any TA) */
+ if (is_insecured) {
+ /* If parent is unsecured we don't want DNSSEC
+ * even if cut name is covered by TA. */
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ VERBOSE_MSG(qry, "=> going insecure because parent query is insecure\n");
+ } else if (kr_ta_covers_qry(req->ctx, qry->zone_cut.name, KNOT_RRTYPE_NS)) {
+ qry->flags.DNSSEC_WANT = true;
+ } else {
+ qry->flags.DNSSEC_WANT = false;
+ VERBOSE_MSG(qry, "=> going insecure because there's no covering TA\n");
+ }
+
+ struct kr_zonecut cut_found;
+ kr_zonecut_init(&cut_found, requested_name, req->rplan.pool);
+ /* Cut that has been found can differs from cut that has been requested.
+ * So if not already insecured,
+ * try to fetch ta & keys even if initial cut name not covered by TA */
+ bool secured = !is_insecured;
+ int ret = kr_zonecut_find_cached(req->ctx, &cut_found, requested_name,
+ qry, &secured);
+ if (ret == kr_error(ENOENT)) {
+ /* No cached cut found, start from SBELT
+ * and issue priming query. */
+ kr_zonecut_deinit(&cut_found);
+ ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
+ if (ret != 0) {
+ return KR_STATE_FAIL;
+ }
+ VERBOSE_MSG(qry, "=> using root hints\n");
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_DONE;
+ } else if (ret != kr_ok()) {
+ kr_zonecut_deinit(&cut_found);
+ return KR_STATE_FAIL;
+ }
+
+ /* Find out security status.
+ * Go insecure if the zone cut is provably insecure */
+ if ((qry->flags.DNSSEC_WANT) && !secured) {
+ VERBOSE_MSG(qry, "=> NS is provably without DS, going insecure\n");
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ }
+ /* Zonecut name can change, check it again
+ * to prevent unnecessary DS & DNSKEY queries */
+ if (!(qry->flags.DNSSEC_INSECURE) &&
+ kr_ta_covers_qry(req->ctx, cut_found.name, KNOT_RRTYPE_NS)) {
+ qry->flags.DNSSEC_WANT = true;
+ } else {
+ qry->flags.DNSSEC_WANT = false;
+ }
+ /* Check if any DNSKEY found for cached cut */
+ if (qry->flags.DNSSEC_WANT && cut_found.key == NULL &&
+ kr_zonecut_is_empty(&cut_found)) {
+ /* Cut found and there are no proofs of zone insecurity.
+ * But no DNSKEY found and no glue fetched.
+ * We have got circular dependency - must fetch A\AAAA
+ * from authoritative, but we have no key to verify it. */
+ kr_zonecut_deinit(&cut_found);
+ if (requested_name[0] != '\0' ) {
+ /* If not root - try next label */
+ return KR_STATE_CONSUME;
+ }
+ /* No cached cut & keys found, start from SBELT */
+ ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
+ if (ret != 0) {
+ return KR_STATE_FAIL;
+ }
+ VERBOSE_MSG(qry, "=> using root hints\n");
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_DONE;
+ }
+ /* Use the found zone cut. */
+ kr_zonecut_move(&qry->zone_cut, &cut_found);
+ /* Check if there's a non-terminal between target and current cut. */
+ struct kr_cache *cache = &req->ctx->cache;
+ check_empty_nonterms(qry, pkt, cache, qry->timestamp.tv_sec);
+ /* Cut found */
+ return KR_STATE_PRODUCE;
+}
+
+static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
+{
+ struct kr_rplan *rplan = &param->rplan;
+ struct kr_context *ctx = param->ctx;
+
+
+ /* Start NS queries from root, to avoid certain cases
+ * where a NS drops out of cache and the rest is unavailable,
+ * this would lead to dependency loop in current zone cut.
+ * Prefer IPv6 and continue with IPv4 if not available.
+ */
+ uint16_t next_type = 0;
+ if (!(qry->flags.AWAIT_IPV6) &&
+ !(ctx->options.NO_IPV6)) {
+ next_type = KNOT_RRTYPE_AAAA;
+ qry->flags.AWAIT_IPV6 = true;
+ } else if (!(qry->flags.AWAIT_IPV4) &&
+ !(ctx->options.NO_IPV4)) {
+ next_type = KNOT_RRTYPE_A;
+ qry->flags.AWAIT_IPV4 = true;
+ /* Hmm, no useable IPv6 then. */
+ qry->ns.reputation |= KR_NS_NOIP6;
+ kr_nsrep_update_rep(&qry->ns, qry->ns.reputation, ctx->cache_rep);
+ }
+ /* Bail out if the query is already pending or dependency loop. */
+ if (!next_type || kr_rplan_satisfies(qry->parent, qry->ns.name, KNOT_CLASS_IN, next_type)) {
+ /* Fall back to SBELT if root server query fails. */
+ if (!next_type && qry->zone_cut.name[0] == '\0') {
+ VERBOSE_MSG(qry, "=> fallback to root hints\n");
+ kr_zonecut_set_sbelt(ctx, &qry->zone_cut);
+ qry->flags.NO_THROTTLE = true; /* Pick even bad SBELT servers */
+ return kr_error(EAGAIN);
+ }
+ /* No IPv4 nor IPv6, flag server as unusable. */
+ VERBOSE_MSG(qry, "=> unresolvable NS address, bailing out\n");
+ qry->ns.reputation |= KR_NS_NOIP4 | KR_NS_NOIP6;
+ kr_nsrep_update_rep(&qry->ns, qry->ns.reputation, ctx->cache_rep);
+ invalidate_ns(rplan, qry);
+ return kr_error(EHOSTUNREACH);
+ }
+ /* Push new query to the resolution plan */
+ struct kr_query *next =
+ kr_rplan_push(rplan, qry, qry->ns.name, KNOT_CLASS_IN, next_type);
+ if (!next) {
+ return kr_error(ENOMEM);
+ }
+ next->flags.NONAUTH = true;
+
+ /* At the root level with no NS addresses, add SBELT subrequest. */
+ int ret = 0;
+ if (qry->zone_cut.name[0] == '\0') {
+ ret = kr_zonecut_set_sbelt(ctx, &next->zone_cut);
+ if (ret == 0) { /* Copy TA and key since it's the same cut to avoid lookup. */
+ kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+ kr_zonecut_set_sbelt(ctx, &qry->zone_cut); /* Add SBELT to parent in case query fails. */
+ qry->flags.NO_THROTTLE = true; /* Pick even bad SBELT servers */
+ }
+ } else {
+ next->flags.AWAIT_CUT = true;
+ }
+ return ret;
+}
+
+static int edns_put(knot_pkt_t *pkt, bool reclaim)
+{
+ if (!pkt->opt_rr) {
+ return kr_ok();
+ }
+ if (reclaim) {
+ /* Reclaim reserved size. */
+ int ret = knot_pkt_reclaim(pkt, knot_edns_wire_size(pkt->opt_rr));
+ if (ret != 0) {
+ return ret;
+ }
+ }
+ /* Write to packet. */
+ assert(pkt->current == KNOT_ADDITIONAL);
+ return knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE);
+}
+
+/** Removes last EDNS OPT RR written to the packet. */
+static int edns_erase_and_reserve(knot_pkt_t *pkt)
+{
+ /* Nothing to be done. */
+ if (!pkt || !pkt->opt_rr) {
+ return 0;
+ }
+
+ /* Fail if the data are located elsewhere than at the end of packet. */
+ if (pkt->current != KNOT_ADDITIONAL ||
+ pkt->opt_rr != &pkt->rr[pkt->rrset_count - 1]) {
+ return -1;
+ }
+
+ size_t len = knot_rrset_size(pkt->opt_rr);
+ int16_t rr_removed = pkt->opt_rr->rrs.count;
+ /* Decrease rrset counters. */
+ pkt->rrset_count -= 1;
+ pkt->sections[pkt->current].count -= 1;
+ pkt->size -= len;
+ knot_wire_add_arcount(pkt->wire, -rr_removed); /* ADDITIONAL */
+
+ pkt->opt_rr = NULL;
+
+ /* Reserve the freed space. */
+ return knot_pkt_reserve(pkt, len);
+}
+
+static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request *req)
+{
+ pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm);
+ size_t wire_size = knot_edns_wire_size(pkt->opt_rr);
+#if defined(ENABLE_COOKIES)
+ if (req->ctx->cookie_ctx.clnt.enabled ||
+ req->ctx->cookie_ctx.srvr.enabled) {
+ wire_size += KR_COOKIE_OPT_MAX_LEN;
+ }
+#endif /* defined(ENABLE_COOKIES) */
+ if (req->qsource.flags.tls) {
+ if (req->ctx->tls_padding == -1)
+ /* FIXME: we do not know how to reserve space for the
+ * default padding policy, since we can't predict what
+ * it will select. So i'm just guessing :/ */
+ wire_size += KNOT_EDNS_OPTION_HDRLEN + 512;
+ if (req->ctx->tls_padding >= 2)
+ wire_size += KNOT_EDNS_OPTION_HDRLEN + req->ctx->tls_padding;
+ }
+ return knot_pkt_reserve(pkt, wire_size);
+}
+
+static int answer_prepare(struct kr_request *req, knot_pkt_t *query)
+{
+ knot_pkt_t *answer = req->answer;
+ if (knot_pkt_init_response(answer, query) != 0) {
+ return kr_error(ENOMEM); /* Failed to initialize answer */
+ }
+ /* Handle EDNS in the query */
+ if (knot_pkt_has_edns(query)) {
+ answer->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &answer->mm);
+ if (answer->opt_rr == NULL){
+ return kr_error(ENOMEM);
+ }
+ /* Set DO bit if set (DNSSEC requested). */
+ if (knot_pkt_has_dnssec(query)) {
+ knot_edns_set_do(answer->opt_rr);
+ }
+ }
+ return kr_ok();
+}
+
+/** @return error code, ignoring if forced to truncate the packet. */
+static int write_extra_records(const rr_array_t *arr, uint16_t reorder, knot_pkt_t *answer)
+{
+ for (size_t i = 0; i < arr->len; ++i) {
+ int err = knot_pkt_put_rotate(answer, 0, arr->at[i], reorder, 0);
+ if (err != KNOT_EOK) {
+ return err == KNOT_ESPACE ? kr_ok() : kr_error(err);
+ }
+ }
+ return kr_ok();
+}
+
+/**
+ * @param all_secure optionally &&-combine security of written RRs into its value.
+ * (i.e. if you pass a pointer to false, it will always remain)
+ * @param all_cname optionally output if all written RRs are CNAMEs and RRSIGs of CNAMEs
+ * @return error code, ignoring if forced to truncate the packet.
+ */
+static int write_extra_ranked_records(const ranked_rr_array_t *arr, uint16_t reorder,
+ knot_pkt_t *answer, bool *all_secure, bool *all_cname)
+{
+ const bool has_dnssec = knot_pkt_has_dnssec(answer);
+ bool all_sec = true;
+ bool all_cn = (all_cname != NULL); /* optim.: init as false if not needed */
+ int err = kr_ok();
+
+ for (size_t i = 0; i < arr->len; ++i) {
+ ranked_rr_array_entry_t * entry = arr->at[i];
+ if (!entry->to_wire) {
+ continue;
+ }
+ knot_rrset_t *rr = entry->rr;
+ if (!has_dnssec) {
+ if (rr->type != knot_pkt_qtype(answer) && knot_rrtype_is_dnssec(rr->type)) {
+ continue;
+ }
+ }
+ err = knot_pkt_put_rotate(answer, 0, rr, reorder, 0);
+ if (err != KNOT_EOK) {
+ if (err == KNOT_ESPACE) {
+ err = kr_ok();
+ }
+ break;
+ }
+
+ if (rr->type != KNOT_RRTYPE_RRSIG) {
+ all_sec = all_sec && kr_rank_test(entry->rank, KR_RANK_SECURE);
+ }
+ all_cn = all_cn && kr_rrset_type_maysig(entry->rr) == KNOT_RRTYPE_CNAME;
+ }
+
+ if (all_secure) {
+ *all_secure = *all_secure && all_sec;
+ }
+ if (all_cname) {
+ *all_cname = all_cn;
+ }
+ return err;
+}
+
+/** @internal Add an EDNS padding RR into the answer if requested and required. */
+static int answer_padding(struct kr_request *request)
+{
+ if (!request || !request->answer || !request->ctx) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ int32_t padding = request->ctx->tls_padding;
+ knot_pkt_t *answer = request->answer;
+ knot_rrset_t *opt_rr = answer->opt_rr;
+ int32_t pad_bytes = -1;
+
+ if (padding == -1) { /* use the default padding policy from libknot */
+ pad_bytes = knot_pkt_default_padding_size(answer, opt_rr);
+ }
+ if (padding >= 2) {
+ int32_t max_pad_bytes = knot_edns_get_payload(opt_rr) - (answer->size + knot_rrset_size(opt_rr));
+ pad_bytes = MIN(knot_edns_alignment_size(answer->size, knot_rrset_size(opt_rr), padding),
+ max_pad_bytes);
+ }
+
+ if (pad_bytes >= 0) {
+ uint8_t zeros[MAX(1, pad_bytes)];
+ memset(zeros, 0, sizeof(zeros));
+ int r = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_PADDING,
+ pad_bytes, zeros, &answer->mm);
+ if (r != KNOT_EOK) {
+ knot_rrset_clear(opt_rr, &answer->mm);
+ return kr_error(r);
+ }
+ }
+ return kr_ok();
+}
+
+static int answer_fail(struct kr_request *request)
+{
+ knot_pkt_t *answer = request->answer;
+ int ret = kr_pkt_clear_payload(answer);
+ knot_wire_clear_ad(answer->wire);
+ knot_wire_clear_aa(answer->wire);
+ knot_wire_set_rcode(answer->wire, KNOT_RCODE_SERVFAIL);
+ if (ret == 0 && answer->opt_rr) {
+ /* OPT in SERVFAIL response is still useful for cookies/additional info. */
+ knot_pkt_begin(answer, KNOT_ADDITIONAL);
+ answer_padding(request); /* Ignore failed padding in SERVFAIL answer. */
+ ret = edns_put(answer, false);
+ }
+ return ret;
+}
+
+static int answer_finalize(struct kr_request *request, int state)
+{
+ struct kr_rplan *rplan = &request->rplan;
+ knot_pkt_t *answer = request->answer;
+
+ /* Always set SERVFAIL for bogus answers. */
+ if (state == KR_STATE_FAIL && rplan->pending.len > 0) {
+ struct kr_query *last = array_tail(rplan->pending);
+ if ((last->flags.DNSSEC_WANT) && (last->flags.DNSSEC_BOGUS)) {
+ return answer_fail(request);
+ }
+ }
+
+ struct kr_query *last = rplan->resolved.len > 0 ? array_tail(rplan->resolved) : NULL;
+ /* TODO ^^^^ this is slightly fragile */
+
+ /* AD flag. We can only change `secure` from true to false.
+ * Be conservative. Primary approach: check ranks of all RRs in wire.
+ * Only "negative answers" need special handling. */
+ bool secure = last != NULL && state == KR_STATE_DONE /*< suspicious otherwise */
+ && knot_pkt_qtype(answer) != KNOT_RRTYPE_RRSIG;
+ if (last && (last->flags.STUB)) {
+ secure = false; /* don't trust forwarding for now */
+ }
+ if (last && (last->flags.DNSSEC_OPTOUT)) {
+ VERBOSE_MSG(NULL, "AD: opt-out\n");
+ secure = false; /* the last answer is insecure due to opt-out */
+ }
+
+ const uint16_t reorder = last ? last->reorder : 0;
+ bool answ_all_cnames = false/*arbitrary*/;
+ if (request->answ_selected.len > 0) {
+ assert(answer->current <= KNOT_ANSWER);
+ /* Write answer records. */
+ if (answer->current < KNOT_ANSWER) {
+ knot_pkt_begin(answer, KNOT_ANSWER);
+ }
+ if (write_extra_ranked_records(&request->answ_selected, reorder,
+ answer, &secure, &answ_all_cnames))
+ {
+ return answer_fail(request);
+ }
+ }
+
+ /* Write authority records. */
+ if (answer->current < KNOT_AUTHORITY) {
+ knot_pkt_begin(answer, KNOT_AUTHORITY);
+ }
+ if (write_extra_ranked_records(&request->auth_selected, reorder,
+ answer, &secure, NULL)) {
+ return answer_fail(request);
+ }
+ /* Write additional records. */
+ knot_pkt_begin(answer, KNOT_ADDITIONAL);
+ if (write_extra_records(&request->additional, reorder, answer)) {
+ return answer_fail(request);
+ }
+ /* Write EDNS information */
+ if (answer->opt_rr) {
+ if (request->qsource.flags.tls) {
+ if (answer_padding(request) != kr_ok()) {
+ return answer_fail(request);
+ }
+ }
+ knot_pkt_begin(answer, KNOT_ADDITIONAL);
+ int ret = knot_pkt_put(answer, KNOT_COMPR_HINT_NONE,
+ answer->opt_rr, KNOT_PF_FREE);
+ if (ret != KNOT_EOK) {
+ return answer_fail(request);
+ }
+ }
+
+ if (!last) secure = false; /*< should be no-op, mostly documentation */
+ /* AD: "negative answers" need more handling. */
+ if (kr_response_classify(answer) != PKT_NOERROR
+ /* Additionally check for CNAME chains that "end in NODATA",
+ * as those would also be PKT_NOERROR. */
+ || (answ_all_cnames && knot_pkt_qtype(answer) != KNOT_RRTYPE_CNAME)) {
+
+ secure = secure && last->flags.DNSSEC_WANT
+ && !last->flags.DNSSEC_BOGUS && !last->flags.DNSSEC_INSECURE;
+ }
+
+ if (secure) {
+ struct kr_query *cname_parent = last->cname_parent;
+ while (cname_parent != NULL) {
+ if (cname_parent->flags.DNSSEC_OPTOUT) {
+ secure = false;
+ break;
+ }
+ cname_parent = cname_parent->cname_parent;
+ }
+ }
+
+ /* No detailed analysis ATM, just _SECURE or not.
+ * LATER: request->rank might better be computed in validator's finish phase. */
+ VERBOSE_MSG(last, "AD: request%s classified as SECURE\n", secure ? "" : " NOT");
+ request->rank = secure ? KR_RANK_SECURE : KR_RANK_INITIAL;
+
+ /* Clear AD if not secure. ATM answer has AD=1 if requested secured answer. */
+ if (!secure) {
+ knot_wire_clear_ad(answer->wire);
+ }
+
+ return kr_ok();
+}
+
+static int query_finalize(struct kr_request *request, struct kr_query *qry, knot_pkt_t *pkt)
+{
+ int ret = 0;
+ knot_pkt_begin(pkt, KNOT_ADDITIONAL);
+ if (!(qry->flags.SAFEMODE)) {
+ /* Remove any EDNS records from any previous iteration. */
+ ret = edns_erase_and_reserve(pkt);
+ if (ret == 0) {
+ ret = edns_create(pkt, request->answer, request);
+ }
+ if (ret == 0) {
+ /* Stub resolution (ask for +rd and +do) */
+ if (qry->flags.STUB) {
+ knot_wire_set_rd(pkt->wire);
+ if (knot_pkt_has_dnssec(request->qsource.packet)) {
+ knot_edns_set_do(pkt->opt_rr);
+ }
+ if (knot_wire_get_cd(request->qsource.packet->wire)) {
+ knot_wire_set_cd(pkt->wire);
+ }
+ /* Full resolution (ask for +cd and +do) */
+ } else if (qry->flags.FORWARD) {
+ knot_wire_set_rd(pkt->wire);
+ knot_edns_set_do(pkt->opt_rr);
+ knot_wire_set_cd(pkt->wire);
+ } else if (qry->flags.DNSSEC_WANT) {
+ knot_edns_set_do(pkt->opt_rr);
+ knot_wire_set_cd(pkt->wire);
+ }
+ }
+ }
+ return ret;
+}
+
+int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer)
+{
+ /* Initialize request */
+ request->ctx = ctx;
+ request->answer = answer;
+ request->options = ctx->options;
+ request->state = KR_STATE_CONSUME;
+ request->current_query = NULL;
+ array_init(request->additional);
+ array_init(request->answ_selected);
+ array_init(request->auth_selected);
+ array_init(request->add_selected);
+ request->answ_validated = false;
+ request->auth_validated = false;
+ request->rank = KR_RANK_INITIAL;
+ request->trace_log = NULL;
+ request->trace_finish = NULL;
+
+ /* Expect first query */
+ kr_rplan_init(&request->rplan, request, &request->pool);
+ return KR_STATE_CONSUME;
+}
+
+static int resolve_query(struct kr_request *request, const knot_pkt_t *packet)
+{
+ struct kr_rplan *rplan = &request->rplan;
+ const knot_dname_t *qname = knot_pkt_qname(packet);
+ uint16_t qclass = knot_pkt_qclass(packet);
+ uint16_t qtype = knot_pkt_qtype(packet);
+ struct kr_query *qry = NULL;
+ struct kr_context *ctx = request->ctx;
+ struct kr_cookie_ctx *cookie_ctx = ctx ? &ctx->cookie_ctx : NULL;
+
+ if (qname != NULL) {
+ qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype);
+ } else if (cookie_ctx && cookie_ctx->srvr.enabled &&
+ knot_wire_get_qdcount(packet->wire) == 0 &&
+ knot_pkt_has_edns(packet) &&
+ knot_pkt_edns_option(packet, KNOT_EDNS_OPTION_COOKIE)) {
+ /* Plan empty query only for cookies. */
+ qry = kr_rplan_push_empty(rplan, NULL);
+ }
+ if (!qry) {
+ return KR_STATE_FAIL;
+ }
+
+ if (qname != NULL) {
+ /* Deferred zone cut lookup for this query. */
+ qry->flags.AWAIT_CUT = true;
+ /* Want DNSSEC if it's posible to secure this name (e.g. is covered by any TA) */
+ if ((knot_wire_get_ad(packet->wire) || knot_pkt_has_dnssec(packet)) &&
+ kr_ta_covers_qry(request->ctx, qname, qtype)) {
+ qry->flags.DNSSEC_WANT = true;
+ }
+ }
+
+ /* Initialize answer packet */
+ knot_pkt_t *answer = request->answer;
+ knot_wire_set_qr(answer->wire);
+ knot_wire_clear_aa(answer->wire);
+ knot_wire_set_ra(answer->wire);
+ knot_wire_set_rcode(answer->wire, KNOT_RCODE_NOERROR);
+
+ assert(request->qsource.packet);
+ if (knot_wire_get_cd(request->qsource.packet->wire)) {
+ knot_wire_set_cd(answer->wire);
+ } else if (qry->flags.DNSSEC_WANT) {
+ knot_wire_set_ad(answer->wire);
+ }
+
+ /* Expect answer, pop if satisfied immediately */
+ ITERATE_LAYERS(request, qry, begin);
+ if ((request->state & KR_STATE_DONE) != 0) {
+ kr_rplan_pop(rplan, qry);
+ } else if (qname == NULL) {
+ /* it is an empty query which must be resolved by
+ `begin` layer of cookie module.
+ If query isn't resolved, fail. */
+ request->state = KR_STATE_FAIL;
+ }
+ return request->state;
+}
+
+KR_PURE static bool kr_inaddr_equal(const struct sockaddr *a, const struct sockaddr *b)
+{
+ const int a_len = kr_inaddr_len(a);
+ const int b_len = kr_inaddr_len(b);
+ return a_len == b_len && memcmp(kr_inaddr(a), kr_inaddr(b), a_len) == 0;
+}
+
+static void update_nslist_rtt(struct kr_context *ctx, struct kr_query *qry, const struct sockaddr *src)
+{
+ /* Do not track in safe mode. */
+ if (qry->flags.SAFEMODE) {
+ return;
+ }
+
+ /* Calculate total resolution time from the time the query was generated. */
+ uint64_t elapsed = kr_now() - qry->timestamp_mono;
+ elapsed = elapsed > UINT_MAX ? UINT_MAX : elapsed;
+
+ /* NSs in the preference list prior to the one who responded will be penalised
+ * with the RETRY timer interval. This is because we know they didn't respond
+ * for N retries, so their RTT must be at least N * RETRY.
+ * The NS in the preference list that responded will have RTT relative to the
+ * time when the query was sent out, not when it was originated.
+ */
+ for (size_t i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ const struct sockaddr *addr = &qry->ns.addr[i].ip;
+ if (addr->sa_family == AF_UNSPEC) {
+ break;
+ }
+ /* If this address is the source of the answer, update its RTT */
+ if (kr_inaddr_equal(src, addr)) {
+ kr_nsrep_update_rtt(&qry->ns, addr, elapsed, ctx->cache_rtt, KR_NS_UPDATE);
+ WITH_VERBOSE(qry) {
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop(addr->sa_family, kr_inaddr(addr), addr_str, sizeof(addr_str));
+ VERBOSE_MSG(qry, "<= server: '%s' rtt: %"PRIu64" ms\n",
+ addr_str, elapsed);
+ }
+ } else {
+ /* Response didn't come from this IP, but we know the RTT must be at least
+ * several RETRY timer tries, e.g. if we have addresses [a, b, c] and we have
+ * tried [a, b] when the answer from 'a' came after 350ms, then we know
+ * that 'b' didn't respond for at least 350 - (1 * 300) ms. We can't say that
+ * its RTT is 50ms, but we can say that its score shouldn't be less than 50. */
+ kr_nsrep_update_rtt(&qry->ns, addr, elapsed, ctx->cache_rtt, KR_NS_MAX);
+ WITH_VERBOSE(qry) {
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop(addr->sa_family, kr_inaddr(addr), addr_str, sizeof(addr_str));
+ VERBOSE_MSG(qry, "<= server: '%s' rtt: >= %"PRIu64" ms\n",
+ addr_str, elapsed);
+ }
+ }
+ /* Subtract query start time from elapsed time */
+ if (elapsed < KR_CONN_RETRY) {
+ break;
+ }
+ elapsed = elapsed - KR_CONN_RETRY;
+ }
+}
+
+static void update_nslist_score(struct kr_request *request, struct kr_query *qry, const struct sockaddr *src, knot_pkt_t *packet)
+{
+ struct kr_context *ctx = request->ctx;
+ /* On successful answer, update preference list RTT and penalise timer */
+ if (request->state != KR_STATE_FAIL) {
+ /* Update RTT information for preference list */
+ update_nslist_rtt(ctx, qry, src);
+ /* Do not complete NS address resolution on soft-fail. */
+ const int rcode = packet ? knot_wire_get_rcode(packet->wire) : 0;
+ if (rcode != KNOT_RCODE_SERVFAIL && rcode != KNOT_RCODE_REFUSED) {
+ qry->flags.AWAIT_IPV6 = false;
+ qry->flags.AWAIT_IPV4 = false;
+ } else { /* Penalize SERVFAILs. */
+ kr_nsrep_update_rtt(&qry->ns, src, KR_NS_PENALTY, ctx->cache_rtt, KR_NS_ADD);
+ }
+ }
+}
+
+static bool resolution_time_exceeded(struct kr_query *qry, uint64_t now)
+{
+ uint64_t resolving_time = now - qry->creation_time_mono;
+ if (resolving_time > KR_RESOLVE_TIME_LIMIT) {
+ WITH_VERBOSE(qry) {
+ VERBOSE_MSG(qry, "query resolution time limit exceeded\n");
+ }
+ return true;
+ }
+ return false;
+}
+
+int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, knot_pkt_t *packet)
+{
+ struct kr_rplan *rplan = &request->rplan;
+
+ /* Empty resolution plan, push packet as the new query */
+ if (packet && kr_rplan_empty(rplan)) {
+ if (answer_prepare(request, packet) != 0) {
+ return KR_STATE_FAIL;
+ }
+ return resolve_query(request, packet);
+ }
+
+ /* Different processing for network error */
+ struct kr_query *qry = array_tail(rplan->pending);
+ /* Check overall resolution time */
+ if (resolution_time_exceeded(qry, kr_now())) {
+ return KR_STATE_FAIL;
+ }
+ bool tried_tcp = (qry->flags.TCP);
+ if (!packet || packet->size == 0) {
+ if (tried_tcp) {
+ request->state = KR_STATE_FAIL;
+ } else {
+ qry->flags.TCP = true;
+ }
+ } else {
+ /* Packet cleared, derandomize QNAME. */
+ knot_dname_t *qname_raw = knot_pkt_qname(packet);
+ if (qname_raw && qry->secret != 0) {
+ randomized_qname_case(qname_raw, qry->secret);
+ }
+ request->state = KR_STATE_CONSUME;
+ if (qry->flags.CACHED) {
+ ITERATE_LAYERS(request, qry, consume, packet);
+ } else {
+ /* Fill in source and latency information. */
+ request->upstream.rtt = kr_now() - qry->timestamp_mono;
+ request->upstream.addr = src;
+ ITERATE_LAYERS(request, qry, consume, packet);
+ /* Clear temporary information */
+ request->upstream.addr = NULL;
+ request->upstream.rtt = 0;
+ }
+ }
+
+ /* Track RTT for iterative answers */
+ if (src && !(qry->flags.CACHED)) {
+ update_nslist_score(request, qry, src, packet);
+ }
+ /* Resolution failed, invalidate current NS. */
+ if (request->state == KR_STATE_FAIL) {
+ invalidate_ns(rplan, qry);
+ qry->flags.RESOLVED = false;
+ }
+
+ /* Pop query if resolved. */
+ if (request->state == KR_STATE_YIELD) {
+ return KR_STATE_PRODUCE; /* Requery */
+ } else if (qry->flags.RESOLVED) {
+ kr_rplan_pop(rplan, qry);
+ } else if (!tried_tcp && (qry->flags.TCP)) {
+ return KR_STATE_PRODUCE; /* Requery over TCP */
+ } else { /* Clear query flags for next attempt */
+ qry->flags.CACHED = false;
+ if (!request->options.TCP) {
+ qry->flags.TCP = false;
+ }
+ }
+
+ ITERATE_LAYERS(request, qry, reset);
+
+ /* Do not finish with bogus answer. */
+ if (qry->flags.DNSSEC_BOGUS) {
+ return KR_STATE_FAIL;
+ }
+
+ return kr_rplan_empty(&request->rplan) ? KR_STATE_DONE : KR_STATE_PRODUCE;
+}
+
+/** @internal Spawn subrequest in current zone cut (no minimization or lookup). */
+static struct kr_query *zone_cut_subreq(struct kr_rplan *rplan, struct kr_query *parent,
+ const knot_dname_t *qname, uint16_t qtype)
+{
+ struct kr_query *next = kr_rplan_push(rplan, parent, qname, parent->sclass, qtype);
+ if (!next) {
+ return NULL;
+ }
+ kr_zonecut_set(&next->zone_cut, parent->zone_cut.name);
+ if (kr_zonecut_copy(&next->zone_cut, &parent->zone_cut) != 0 ||
+ kr_zonecut_copy_trust(&next->zone_cut, &parent->zone_cut) != 0) {
+ return NULL;
+ }
+ next->flags.NO_MINIMIZE = true;
+ if (parent->flags.DNSSEC_WANT) {
+ next->flags.DNSSEC_WANT = true;
+ }
+ return next;
+}
+
+static int forward_trust_chain_check(struct kr_request *request, struct kr_query *qry, bool resume)
+{
+ struct kr_rplan *rplan = &request->rplan;
+ map_t *trust_anchors = &request->ctx->trust_anchors;
+ map_t *negative_anchors = &request->ctx->negative_anchors;
+
+ if (qry->parent != NULL &&
+ !(qry->forward_flags.CNAME) &&
+ !(qry->flags.DNS64_MARK) &&
+ knot_dname_in_bailiwick(qry->zone_cut.name, qry->parent->zone_cut.name) >= 0) {
+ return KR_STATE_PRODUCE;
+ }
+
+ assert(qry->flags.FORWARD);
+
+ if (!trust_anchors) {
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_PRODUCE;
+ }
+
+ if (qry->flags.DNSSEC_INSECURE) {
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_PRODUCE;
+ }
+
+ if (qry->forward_flags.NO_MINIMIZE) {
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_PRODUCE;
+ }
+
+ const knot_dname_t *start_name = qry->sname;
+ if ((qry->flags.AWAIT_CUT) && !resume) {
+ qry->flags.AWAIT_CUT = false;
+ const knot_dname_t *longest_ta = kr_ta_get_longest_name(trust_anchors, qry->sname);
+ if (longest_ta) {
+ start_name = longest_ta;
+ qry->zone_cut.name = knot_dname_copy(start_name, qry->zone_cut.pool);
+ qry->flags.DNSSEC_WANT = true;
+ } else {
+ qry->flags.DNSSEC_WANT = false;
+ return KR_STATE_PRODUCE;
+ }
+ }
+
+ bool has_ta = (qry->zone_cut.trust_anchor != NULL);
+ knot_dname_t *ta_name = (has_ta ? qry->zone_cut.trust_anchor->owner : NULL);
+ bool refetch_ta = (!has_ta || !knot_dname_is_equal(qry->zone_cut.name, ta_name));
+ bool is_dnskey_subreq = kr_rplan_satisfies(qry, ta_name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
+ bool refetch_key = has_ta && (!qry->zone_cut.key || !knot_dname_is_equal(ta_name, qry->zone_cut.key->owner));
+ if (refetch_key && !is_dnskey_subreq) {
+ struct kr_query *next = zone_cut_subreq(rplan, qry, ta_name, KNOT_RRTYPE_DNSKEY);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ return KR_STATE_DONE;
+ }
+
+ int name_offset = 1;
+ const knot_dname_t *wanted_name;
+ bool nods, ds_req, ns_req, minimized, ns_exist;
+ do {
+ wanted_name = start_name;
+ ds_req = false;
+ ns_req = false;
+ ns_exist = true;
+
+ int cut_labels = knot_dname_labels(qry->zone_cut.name, NULL);
+ int wanted_name_labels = knot_dname_labels(wanted_name, NULL);
+ while (wanted_name[0] && wanted_name_labels > cut_labels + name_offset) {
+ wanted_name = knot_wire_next_label(wanted_name, NULL);
+ wanted_name_labels -= 1;
+ }
+ minimized = (wanted_name != qry->sname);
+
+ for (int i = 0; i < request->rplan.resolved.len; ++i) {
+ struct kr_query *q = request->rplan.resolved.at[i];
+ if (q->parent == qry &&
+ q->sclass == qry->sclass &&
+ (q->stype == KNOT_RRTYPE_DS || q->stype == KNOT_RRTYPE_NS) &&
+ knot_dname_is_equal(q->sname, wanted_name)) {
+ if (q->stype == KNOT_RRTYPE_DS) {
+ ds_req = true;
+ if (q->flags.CNAME) {
+ ns_exist = false;
+ } else if (!(q->flags.DNSSEC_OPTOUT)) {
+ int ret = kr_dnssec_matches_name_and_type(&request->auth_selected, q->uid,
+ wanted_name, KNOT_RRTYPE_NS);
+ ns_exist = (ret == kr_ok());
+ }
+ } else {
+ if (q->flags.CNAME) {
+ ns_exist = false;
+ }
+ ns_req = true;
+ }
+ }
+ }
+
+ if (ds_req && ns_exist && !ns_req && (minimized || resume)) {
+ struct kr_query *next = zone_cut_subreq(rplan, qry, wanted_name,
+ KNOT_RRTYPE_NS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ return KR_STATE_DONE;
+ }
+
+ if (qry->parent == NULL && (qry->flags.CNAME) &&
+ ds_req && ns_req) {
+ return KR_STATE_PRODUCE;
+ }
+
+ /* set `nods` */
+ if ((qry->stype == KNOT_RRTYPE_DS) &&
+ knot_dname_is_equal(wanted_name, qry->sname)) {
+ nods = true;
+ } else if (resume && !ds_req) {
+ nods = false;
+ } else if (!minimized && qry->stype != KNOT_RRTYPE_DNSKEY) {
+ nods = true;
+ } else {
+ nods = ds_req;
+ }
+ name_offset += 1;
+ } while (ds_req && (ns_req || !ns_exist) && minimized);
+
+ /* Disable DNSSEC if it enters NTA. */
+ if (kr_ta_get(negative_anchors, wanted_name)){
+ VERBOSE_MSG(qry, ">< negative TA, going insecure\n");
+ qry->flags.DNSSEC_WANT = false;
+ }
+
+ /* Enable DNSSEC if enters a new island of trust. */
+ bool want_secured = (qry->flags.DNSSEC_WANT) &&
+ !knot_wire_get_cd(request->qsource.packet->wire);
+ if (!(qry->flags.DNSSEC_WANT) &&
+ !knot_wire_get_cd(request->qsource.packet->wire) &&
+ kr_ta_get(trust_anchors, wanted_name)) {
+ qry->flags.DNSSEC_WANT = true;
+ want_secured = true;
+ WITH_VERBOSE(qry) {
+ KR_DNAME_GET_STR(qname_str, wanted_name);
+ VERBOSE_MSG(qry, ">< TA: '%s'\n", qname_str);
+ }
+ }
+
+ if (want_secured && !qry->zone_cut.trust_anchor) {
+ knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, wanted_name);
+ if (!ta_rr) {
+ char name[] = "\0";
+ ta_rr = kr_ta_get(trust_anchors, (knot_dname_t*)name);
+ }
+ if (ta_rr) {
+ qry->zone_cut.trust_anchor = knot_rrset_copy(ta_rr, qry->zone_cut.pool);
+ }
+ }
+
+ has_ta = (qry->zone_cut.trust_anchor != NULL);
+ ta_name = (has_ta ? qry->zone_cut.trust_anchor->owner : NULL);
+ refetch_ta = (!has_ta || !knot_dname_is_equal(wanted_name, ta_name));
+ if (!nods && want_secured && refetch_ta) {
+ struct kr_query *next = zone_cut_subreq(rplan, qry, wanted_name,
+ KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ return KR_STATE_DONE;
+ }
+
+ /* Try to fetch missing DNSKEY.
+ * Do not fetch if this is a DNSKEY subrequest to avoid circular dependency. */
+ is_dnskey_subreq = kr_rplan_satisfies(qry, ta_name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
+ refetch_key = has_ta && (!qry->zone_cut.key || !knot_dname_is_equal(ta_name, qry->zone_cut.key->owner));
+ if (want_secured && refetch_key && !is_dnskey_subreq) {
+ struct kr_query *next = zone_cut_subreq(rplan, qry, ta_name, KNOT_RRTYPE_DNSKEY);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ return KR_STATE_DONE;
+ }
+
+ return KR_STATE_PRODUCE;
+}
+
+/* @todo: Validator refactoring, keep this in driver for now. */
+static int trust_chain_check(struct kr_request *request, struct kr_query *qry)
+{
+ struct kr_rplan *rplan = &request->rplan;
+ map_t *trust_anchors = &request->ctx->trust_anchors;
+ map_t *negative_anchors = &request->ctx->negative_anchors;
+
+ /* Disable DNSSEC if it enters NTA. */
+ if (kr_ta_get(negative_anchors, qry->zone_cut.name)){
+ VERBOSE_MSG(qry, ">< negative TA, going insecure\n");
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ }
+ if (qry->flags.DNSSEC_NODS) {
+ /* This is the next query iteration with minimized qname.
+ * At previous iteration DS non-existance has been proven */
+ qry->flags.DNSSEC_NODS = false;
+ qry->flags.DNSSEC_WANT = false;
+ qry->flags.DNSSEC_INSECURE = true;
+ }
+ /* Enable DNSSEC if entering a new (or different) island of trust,
+ * and update the TA RRset if required. */
+ bool want_secured = (qry->flags.DNSSEC_WANT) &&
+ !knot_wire_get_cd(request->qsource.packet->wire);
+ knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, qry->zone_cut.name);
+ if (!knot_wire_get_cd(request->qsource.packet->wire) && ta_rr) {
+ qry->flags.DNSSEC_WANT = true;
+ want_secured = true;
+
+ if (qry->zone_cut.trust_anchor == NULL
+ || !knot_dname_is_equal(qry->zone_cut.trust_anchor->owner, qry->zone_cut.name)) {
+ mm_free(qry->zone_cut.pool, qry->zone_cut.trust_anchor);
+ qry->zone_cut.trust_anchor = knot_rrset_copy(ta_rr, qry->zone_cut.pool);
+
+ WITH_VERBOSE(qry) {
+ KR_DNAME_GET_STR(qname_str, ta_rr->owner);
+ VERBOSE_MSG(qry, ">< TA: '%s'\n", qname_str);
+ }
+ }
+ }
+
+ /* Try to fetch missing DS (from above the cut). */
+ const bool has_ta = (qry->zone_cut.trust_anchor != NULL);
+ const knot_dname_t *ta_name = (has_ta ? qry->zone_cut.trust_anchor->owner : NULL);
+ const bool refetch_ta = !has_ta || !knot_dname_is_equal(qry->zone_cut.name, ta_name);
+ if (want_secured && refetch_ta) {
+ /* @todo we could fetch the information from the parent cut, but we don't remember that now */
+ struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, qry->sclass, KNOT_RRTYPE_DS);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ next->flags.AWAIT_CUT = true;
+ next->flags.DNSSEC_WANT = true;
+ return KR_STATE_DONE;
+ }
+ /* Try to fetch missing DNSKEY (either missing or above current cut).
+ * Do not fetch if this is a DNSKEY subrequest to avoid circular dependency. */
+ const bool is_dnskey_subreq = kr_rplan_satisfies(qry, ta_name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
+ const bool refetch_key = has_ta && (!qry->zone_cut.key || !knot_dname_is_equal(ta_name, qry->zone_cut.key->owner));
+ if (want_secured && refetch_key && !is_dnskey_subreq) {
+ struct kr_query *next = zone_cut_subreq(rplan, qry, ta_name, KNOT_RRTYPE_DNSKEY);
+ if (!next) {
+ return KR_STATE_FAIL;
+ }
+ return KR_STATE_DONE;
+ }
+
+ return KR_STATE_PRODUCE;
+}
+
+/** @internal Check current zone cut status and credibility, spawn subrequests if needed. */
+static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot_pkt_t *packet)
+/* TODO: using cache on this point in this way just isn't nice; remove in time */
+{
+ /* Stub mode, just forward and do not solve cut. */
+ if (qry->flags.STUB) {
+ return KR_STATE_PRODUCE;
+ }
+
+ /* Forwarding to upstream resolver mode.
+ * Since forwarding targets already are in qry->ns -
+ * cut fetching is not needed. */
+ if (qry->flags.FORWARD) {
+ return forward_trust_chain_check(request, qry, false);
+ }
+ if (!(qry->flags.AWAIT_CUT)) {
+ /* The query was resolved from cache.
+ * Spawn DS \ DNSKEY requests if needed and exit */
+ return trust_chain_check(request, qry);
+ }
+
+ /* The query wasn't resolved from cache,
+ * now it's the time to look up closest zone cut from cache. */
+ struct kr_cache *cache = &request->ctx->cache;
+ if (!kr_cache_is_open(cache)) {
+ int ret = kr_zonecut_set_sbelt(request->ctx, &qry->zone_cut);
+ if (ret != 0) {
+ return KR_STATE_FAIL;
+ }
+ VERBOSE_MSG(qry, "=> no cache open, using root hints\n");
+ qry->flags.AWAIT_CUT = false;
+ return KR_STATE_DONE;
+ }
+
+ const knot_dname_t *requested_name = qry->sname;
+ /* If at/subdomain of parent zone cut, start from its encloser.
+ * This is for case when we get to a dead end
+ * (and need glue from parent), or DS refetch. */
+ if (qry->parent) {
+ const knot_dname_t *parent = qry->parent->zone_cut.name;
+ if (parent[0] != '\0'
+ && knot_dname_in_bailiwick(qry->sname, parent) >= 0) {
+ requested_name = knot_wire_next_label(parent, NULL);
+ }
+ } else if ((qry->stype == KNOT_RRTYPE_DS) && (qry->sname[0] != '\0')) {
+ /* If this is explicit DS query, start from encloser too. */
+ requested_name = knot_wire_next_label(requested_name, NULL);
+ }
+
+ int state = KR_STATE_FAIL;
+ do {
+ state = ns_fetch_cut(qry, requested_name, request, packet);
+ if (state == KR_STATE_DONE || state == KR_STATE_FAIL) {
+ return state;
+ } else if (state == KR_STATE_CONSUME) {
+ requested_name = knot_wire_next_label(requested_name, NULL);
+ }
+ } while (state == KR_STATE_CONSUME);
+
+ /* Update minimized QNAME if zone cut changed */
+ if (qry->zone_cut.name && qry->zone_cut.name[0] != '\0' && !(qry->flags.NO_MINIMIZE)) {
+ if (kr_make_query(qry, packet) != 0) {
+ return KR_STATE_FAIL;
+ }
+ }
+ qry->flags.AWAIT_CUT = false;
+
+ /* Check trust chain */
+ return trust_chain_check(request, qry);
+}
+
+int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet)
+{
+ struct kr_rplan *rplan = &request->rplan;
+ unsigned ns_election_iter = 0;
+
+ /* No query left for resolution */
+ if (kr_rplan_empty(rplan)) {
+ return KR_STATE_FAIL;
+ }
+ /* If we have deferred answers, resume them. */
+ struct kr_query *qry = array_tail(rplan->pending);
+ if (qry->deferred != NULL) {
+ /* @todo: Refactoring validator, check trust chain before resuming. */
+ int state = 0;
+ if (((qry->flags.FORWARD) == 0) ||
+ ((qry->stype == KNOT_RRTYPE_DS) && (qry->flags.CNAME))) {
+ state = trust_chain_check(request, qry);
+ } else {
+ state = forward_trust_chain_check(request, qry, true);
+ }
+
+ switch(state) {
+ case KR_STATE_FAIL: return KR_STATE_FAIL;
+ case KR_STATE_DONE: return KR_STATE_PRODUCE;
+ default: break;
+ }
+ VERBOSE_MSG(qry, "=> resuming yielded answer\n");
+ struct kr_layer_pickle *pickle = qry->deferred;
+ request->state = KR_STATE_YIELD;
+ set_yield(&request->answ_selected, qry->uid, false);
+ set_yield(&request->auth_selected, qry->uid, false);
+ RESUME_LAYERS(layer_id(request, pickle->api), request, qry, consume, pickle->pkt);
+ if (request->state != KR_STATE_YIELD) {
+ /* No new deferred answers, take the next */
+ qry->deferred = pickle->next;
+ }
+ } else {
+ /* Caller is interested in always tracking a zone cut, even if the answer is cached
+ * this is normally not required, and incurrs another cache lookups for cached answer. */
+ if (qry->flags.ALWAYS_CUT) {
+ if (!(qry->flags.STUB)) {
+ switch(zone_cut_check(request, qry, packet)) {
+ case KR_STATE_FAIL: return KR_STATE_FAIL;
+ case KR_STATE_DONE: return KR_STATE_PRODUCE;
+ default: break;
+ }
+ }
+ }
+ /* Resolve current query and produce dependent or finish */
+ request->state = KR_STATE_PRODUCE;
+ ITERATE_LAYERS(request, qry, produce, packet);
+ if (request->state != KR_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
+ /* Produced an answer from cache, consume it. */
+ qry->secret = 0;
+ request->state = KR_STATE_CONSUME;
+ ITERATE_LAYERS(request, qry, consume, packet);
+ }
+ }
+ switch(request->state) {
+ case KR_STATE_FAIL: return request->state;
+ case KR_STATE_CONSUME: break;
+ case KR_STATE_DONE:
+ default: /* Current query is done */
+ if (qry->flags.RESOLVED && request->state != KR_STATE_YIELD) {
+ kr_rplan_pop(rplan, qry);
+ }
+ ITERATE_LAYERS(request, qry, reset);
+ return kr_rplan_empty(rplan) ? KR_STATE_DONE : KR_STATE_PRODUCE;
+ }
+
+
+ /* This query has RD=0 or is ANY, stop here. */
+ if (qry->stype == KNOT_RRTYPE_ANY ||
+ !knot_wire_get_rd(request->qsource.packet->wire)) {
+ VERBOSE_MSG(qry, "=> qtype is ANY or RD=0, bail out\n");
+ return KR_STATE_FAIL;
+ }
+
+ /* Update zone cut, spawn new subrequests. */
+ if (!(qry->flags.STUB)) {
+ int state = zone_cut_check(request, qry, packet);
+ switch(state) {
+ case KR_STATE_FAIL: return KR_STATE_FAIL;
+ case KR_STATE_DONE: return KR_STATE_PRODUCE;
+ default: break;
+ }
+ }
+
+ns_election:
+
+ /* If the query has already selected a NS and is waiting for IPv4/IPv6 record,
+ * elect best address only, otherwise elect a completely new NS.
+ */
+ if(++ns_election_iter >= KR_ITER_LIMIT) {
+ VERBOSE_MSG(qry, "=> couldn't converge NS selection, bail out\n");
+ return KR_STATE_FAIL;
+ }
+
+ const struct kr_qflags qflg = qry->flags;
+ const bool retry = qflg.TCP || qflg.BADCOOKIE_AGAIN;
+ if (qflg.AWAIT_IPV4 || qflg.AWAIT_IPV6) {
+ kr_nsrep_elect_addr(qry, request->ctx);
+ } else if (qflg.FORWARD || qflg.STUB) {
+ kr_nsrep_sort(&qry->ns, request->ctx);
+ if (qry->ns.score > KR_NS_MAX_SCORE) {
+ /* At the moment all NS have bad reputation.
+ * But there can be existing connections*/
+ VERBOSE_MSG(qry, "=> no valid NS left\n");
+ return KR_STATE_FAIL;
+ }
+ } else if (!qry->ns.name || !retry) { /* Keep NS when requerying/stub/badcookie. */
+ /* Root DNSKEY must be fetched from the hints to avoid chicken and egg problem. */
+ if (qry->sname[0] == '\0' && qry->stype == KNOT_RRTYPE_DNSKEY) {
+ kr_zonecut_set_sbelt(request->ctx, &qry->zone_cut);
+ qry->flags.NO_THROTTLE = true; /* Pick even bad SBELT servers */
+ }
+ kr_nsrep_elect(qry, request->ctx);
+ if (qry->ns.score > KR_NS_MAX_SCORE) {
+ if (kr_zonecut_is_empty(&qry->zone_cut)) {
+ VERBOSE_MSG(qry, "=> no NS with an address\n");
+ } else {
+ VERBOSE_MSG(qry, "=> no valid NS left\n");
+ }
+ if (!qry->flags.NO_NS_FOUND) {
+ qry->flags.NO_NS_FOUND = true;
+ } else {
+ ITERATE_LAYERS(request, qry, reset);
+ kr_rplan_pop(rplan, qry);
+ }
+ return KR_STATE_PRODUCE;
+ }
+ }
+
+ /* Resolve address records */
+ if (qry->ns.addr[0].ip.sa_family == AF_UNSPEC) {
+ int ret = ns_resolve_addr(qry, request);
+ if (ret != 0) {
+ qry->flags.AWAIT_IPV6 = false;
+ qry->flags.AWAIT_IPV4 = false;
+ qry->flags.TCP = false;
+ qry->ns.name = NULL;
+ goto ns_election; /* Must try different NS */
+ }
+ ITERATE_LAYERS(request, qry, reset);
+ return KR_STATE_PRODUCE;
+ }
+
+ /* Randomize query case (if not in safe mode or turned off) */
+ qry->secret = (qry->flags.SAFEMODE || qry->flags.NO_0X20)
+ ? 0 : kr_rand_bytes(sizeof(qry->secret));
+ knot_dname_t *qname_raw = knot_pkt_qname(packet);
+ randomized_qname_case(qname_raw, qry->secret);
+
+ /*
+ * Additional query is going to be finalized when calling
+ * kr_resolve_checkout().
+ */
+ qry->timestamp_mono = kr_now();
+ *dst = &qry->ns.addr[0].ip;
+ *type = (qry->flags.TCP) ? SOCK_STREAM : SOCK_DGRAM;
+ return request->state;
+}
+
+#if defined(ENABLE_COOKIES)
+/** Update DNS cookie data in packet. */
+static bool outbound_request_update_cookies(struct kr_request *req,
+ const struct sockaddr *src,
+ const struct sockaddr *dst)
+{
+ assert(req);
+
+ /* RFC7873 4.1 strongly requires server address. */
+ if (!dst) {
+ return false;
+ }
+
+ struct kr_cookie_settings *clnt_sett = &req->ctx->cookie_ctx.clnt;
+
+ /* Cookies disabled or packet has no EDNS section. */
+ if (!clnt_sett->enabled) {
+ return true;
+ }
+
+ /*
+ * RFC7873 4.1 recommends using also the client address. The matter is
+ * also discussed in section 6.
+ */
+
+ kr_request_put_cookie(&clnt_sett->current, req->ctx->cache_cookie,
+ src, dst, req);
+
+ return true;
+}
+#endif /* defined(ENABLE_COOKIES) */
+
+int kr_resolve_checkout(struct kr_request *request, const struct sockaddr *src,
+ struct sockaddr *dst, int type, knot_pkt_t *packet)
+{
+ /* @todo: Update documentation if this function becomes approved. */
+
+ struct kr_rplan *rplan = &request->rplan;
+
+ if (knot_wire_get_qr(packet->wire) != 0) {
+ return kr_ok();
+ }
+
+ /* No query left for resolution */
+ if (kr_rplan_empty(rplan)) {
+ return kr_error(EINVAL);
+ }
+ struct kr_query *qry = array_tail(rplan->pending);
+
+#if defined(ENABLE_COOKIES)
+ /* Update DNS cookies in request. */
+ if (type == SOCK_DGRAM) { /* @todo: Add cookies also over TCP? */
+ /*
+ * The actual server IP address is needed before generating the
+ * actual cookie. If we don't know the server address then we
+ * also don't know the actual cookie size.
+ */
+ if (!outbound_request_update_cookies(request, src, dst)) {
+ return kr_error(EINVAL);
+ }
+ }
+#endif /* defined(ENABLE_COOKIES) */
+
+ int ret = query_finalize(request, qry, packet);
+ if (ret != 0) {
+ return kr_error(EINVAL);
+ }
+
+ /* Track changes in minimization secret to enable/disable minimization */
+ uint32_t old_minimization_secret = qry->secret;
+
+ /* Run the checkout layers and cancel on failure.
+ * The checkout layer doesn't persist the state, so canceled subrequests
+ * don't affect the resolution or rest of the processing. */
+ int state = request->state;
+ ITERATE_LAYERS(request, qry, checkout, packet, dst, type);
+ if (request->state == KR_STATE_FAIL) {
+ request->state = state; /* Restore */
+ return kr_error(ECANCELED);
+ }
+
+ /* Randomize query case (if secret changed) */
+ knot_dname_t *qname = (knot_dname_t *)knot_pkt_qname(packet);
+ if (qry->secret != old_minimization_secret) {
+ randomized_qname_case(qname, qry->secret);
+ }
+
+ /* Write down OPT unless in safemode */
+ if (!(qry->flags.SAFEMODE)) {
+ ret = edns_put(packet, true);
+ if (ret != 0) {
+ return kr_error(EINVAL);
+ }
+ }
+
+ WITH_VERBOSE(qry) {
+
+ KR_DNAME_GET_STR(qname_str, knot_pkt_qname(packet));
+ KR_DNAME_GET_STR(zonecut_str, qry->zone_cut.name);
+ KR_RRTYPE_GET_STR(type_str, knot_pkt_qtype(packet));
+
+ for (size_t i = 0; i < KR_NSREP_MAXADDR; ++i) {
+ struct sockaddr *addr = &qry->ns.addr[i].ip;
+ if (addr->sa_family == AF_UNSPEC) {
+ break;
+ }
+ if (!kr_inaddr_equal(dst, addr)) {
+ continue;
+ }
+ const char *ns_str = kr_straddr(addr);
+ VERBOSE_MSG(qry,
+ "=> id: '%05u' querying: '%s' score: %u zone cut: '%s' "
+ "qname: '%s' qtype: '%s' proto: '%s'\n",
+ qry->id, ns_str ? ns_str : "", qry->ns.score, zonecut_str,
+ qname_str, type_str, (qry->flags.TCP) ? "tcp" : "udp");
+
+ break;
+ }}
+
+ return kr_ok();
+}
+
+int kr_resolve_finish(struct kr_request *request, int state)
+{
+ /* Finalize answer and construct wire-buffer. */
+ ITERATE_LAYERS(request, NULL, answer_finalize);
+ if (request->state == KR_STATE_FAIL) {
+ state = KR_STATE_FAIL;
+ } else if (answer_finalize(request, state) != 0) {
+ state = KR_STATE_FAIL;
+ }
+
+ /* Error during processing, internal failure */
+ if (state != KR_STATE_DONE) {
+ knot_pkt_t *answer = request->answer;
+ if (knot_wire_get_rcode(answer->wire) == KNOT_RCODE_NOERROR) {
+ knot_wire_clear_ad(answer->wire);
+ knot_wire_clear_aa(answer->wire);
+ knot_wire_set_rcode(answer->wire, KNOT_RCODE_SERVFAIL);
+ }
+ }
+
+ request->state = state;
+ ITERATE_LAYERS(request, NULL, finish);
+
+#ifndef NOVERBOSELOG
+ struct kr_rplan *rplan = &request->rplan;
+ struct kr_query *last = kr_rplan_last(rplan);
+ VERBOSE_MSG(last, "finished: %d, queries: %zu, mempool: %zu B\n",
+ request->state, rplan->resolved.len, (size_t) mp_total_size(request->pool.ctx));
+#endif
+
+ /* Trace request finish */
+ if (request->trace_finish) {
+ request->trace_finish(request);
+ }
+
+ /* Uninstall all tracepoints */
+ request->trace_finish = NULL;
+ request->trace_log = NULL;
+
+ return KR_STATE_DONE;
+}
+
+struct kr_rplan *kr_resolve_plan(struct kr_request *request)
+{
+ if (request) {
+ return &request->rplan;
+ }
+ return NULL;
+}
+
+knot_mm_t *kr_resolve_pool(struct kr_request *request)
+{
+ if (request) {
+ return &request->pool;
+ }
+ return NULL;
+}
+
+#undef VERBOSE_MSG
diff --git a/lib/resolve.h b/lib/resolve.h
new file mode 100644
index 0000000..60d80bb
--- /dev/null
+++ b/lib/resolve.h
@@ -0,0 +1,332 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <libknot/packet/pkt.h>
+
+#include "lib/cookies/control.h"
+#include "lib/cookies/lru_cache.h"
+#include "lib/layer.h"
+#include "lib/generic/map.h"
+#include "lib/generic/array.h"
+#include "lib/nsrep.h"
+#include "lib/rplan.h"
+#include "lib/module.h"
+#include "lib/cache/api.h"
+
+/**
+ * @file resolve.h
+ * @brief The API provides an API providing a "consumer-producer"-like interface to enable
+ * user to plug it into existing event loop or I/O code.
+ *
+ * # Example usage of the iterative API:
+ *
+ * @code{.c}
+ *
+ * // Create request and its memory pool
+ * struct kr_request req = {
+ * .pool = {
+ * .ctx = mp_new (4096),
+ * .alloc = (mm_alloc_t) mp_alloc
+ * }
+ * };
+ *
+ * // Setup and provide input query
+ * int state = kr_resolve_begin(&req, ctx, final_answer);
+ * state = kr_resolve_consume(&req, query);
+ *
+ * // Generate answer
+ * while (state == KR_STATE_PRODUCE) {
+ *
+ * // Additional query generate, do the I/O and pass back answer
+ * state = kr_resolve_produce(&req, &addr, &type, query);
+ * while (state == KR_STATE_CONSUME) {
+ * int ret = sendrecv(addr, proto, query, resp);
+ *
+ * // If I/O fails, make "resp" empty
+ * state = kr_resolve_consume(&request, addr, resp);
+ * knot_pkt_clear(resp);
+ * }
+ * knot_pkt_clear(query);
+ * }
+ *
+ * // "state" is either DONE or FAIL
+ * kr_resolve_finish(&request, state);
+ *
+ * @endcode
+ */
+
+
+/**
+ * RRset rank - for cache and ranked_rr_*.
+ *
+ * The rank meaning consists of one independent flag - KR_RANK_AUTH,
+ * and the rest have meaning of values where only one can hold at any time.
+ * You can use one of the enums as a safe initial value, optionally | KR_RANK_AUTH;
+ * otherwise it's best to manipulate ranks via the kr_rank_* functions.
+ *
+ * @note The representation is complicated by restrictions on integer comparison:
+ * - AUTH must be > than !AUTH
+ * - AUTH INSECURE must be > than AUTH (because it attempted validation)
+ * - !AUTH SECURE must be > than AUTH (because it's valid)
+ *
+ * See also:
+ * https://tools.ietf.org/html/rfc2181#section-5.4.1
+ * https://tools.ietf.org/html/rfc4035#section-4.3
+ */
+enum kr_rank {
+ /* Initial-like states. No validation has been attempted (yet). */
+ KR_RANK_INITIAL = 0, /**< Did not attempt to validate. It's assumed
+ compulsory to validate (or prove insecure). */
+ KR_RANK_OMIT, /**< Do not attempt to validate.
+ (And don't consider it a validation failure.) */
+ KR_RANK_TRY, /**< Attempt to validate, but failures are non-fatal. */
+
+ /* Failure states. These have higher value because they have more information. */
+ KR_RANK_INDET = 4, /**< Unable to determine whether it should be secure. */
+ KR_RANK_BOGUS, /**< Ought to be secure but isn't. */
+ KR_RANK_MISMATCH,
+ KR_RANK_MISSING, /**< Unable to obtain a good signature. */
+
+ /** Proven to be insecure, i.e. we have a chain of trust from TAs
+ * that cryptographically denies the possibility of existence
+ * of a positive chain of trust from the TAs to the record. */
+ KR_RANK_INSECURE = 8,
+
+ /** Authoritative data flag; the chain of authority was "verified".
+ * Even if not set, only in-bailiwick stuff is acceptable,
+ * i.e. almost authoritative (example: mandatory glue and its NS RR). */
+ KR_RANK_AUTH = 16,
+
+ KR_RANK_SECURE = 32, /**< Verified whole chain of trust from the closest TA. */
+ /* @note Rank must not exceed 6 bits */
+};
+
+/** Check that a rank value is valid. Meant for assertions. */
+bool kr_rank_check(uint8_t rank) KR_PURE;
+
+/** Test the presence of any flag/state in a rank, i.e. including KR_RANK_AUTH. */
+static inline bool kr_rank_test(uint8_t rank, uint8_t kr_flag)
+{
+ assert(kr_rank_check(rank) && kr_rank_check(kr_flag));
+ if (kr_flag == KR_RANK_AUTH) {
+ return rank & KR_RANK_AUTH;
+ }
+ assert(!(kr_flag & KR_RANK_AUTH));
+ /* The rest are exclusive values - exactly one has to be set. */
+ return (rank & ~KR_RANK_AUTH) == kr_flag;
+}
+
+/** Set the rank state. The _AUTH flag is kept as it was. */
+static inline void kr_rank_set(uint8_t *rank, uint8_t kr_flag)
+{
+ assert(rank && kr_rank_check(*rank));
+ assert(kr_rank_check(kr_flag) && !(kr_flag & KR_RANK_AUTH));
+ *rank = kr_flag | (*rank & KR_RANK_AUTH);
+}
+
+
+/** @cond internal Array of modules. */
+typedef array_t(struct kr_module *) module_array_t;
+/* @endcond */
+
+/**
+ * Name resolution context.
+ *
+ * Resolution context provides basic services like cache, configuration and options.
+ *
+ * @note This structure is persistent between name resolutions and may
+ * be shared between threads.
+ */
+struct kr_context
+{
+ struct kr_qflags options;
+ knot_rrset_t *opt_rr;
+ map_t trust_anchors;
+ map_t negative_anchors;
+ struct kr_zonecut root_hints;
+ struct kr_cache cache;
+ kr_nsrep_rtt_lru_t *cache_rtt;
+ unsigned cache_rtt_tout_retry_interval;
+ kr_nsrep_lru_t *cache_rep;
+ module_array_t *modules;
+ /* The cookie context structure should not be held within the cookies
+ * module because of better access. */
+ struct kr_cookie_ctx cookie_ctx;
+ kr_cookie_lru_t *cache_cookie;
+ int32_t tls_padding; /**< See net.tls_padding in ../daemon/README.rst -- -1 is "true" (default policy), 0 is "false" (no padding) */
+ knot_mm_t *pool;
+};
+
+/* Kept outside, because kres-gen.lua can't handle this depth
+ * (and lines here were too long anyway). */
+struct kr_request_qsource_flags {
+ bool tcp:1; /**< true if the request is on TCP (or TLS); only meaningful if (dst_addr). */
+ bool tls:1; /**< true if the request is on TLS; only meaningful if (dst_addr). */
+};
+
+/**
+ * Name resolution request.
+ *
+ * Keeps information about current query processing between calls to
+ * processing APIs, i.e. current resolved query, resolution plan, ...
+ * Use this instead of the simple interface if you want to implement
+ * multiplexing or custom I/O.
+ *
+ * @note All data for this request must be allocated from the given pool.
+ */
+struct kr_request {
+ struct kr_context *ctx;
+ knot_pkt_t *answer;
+ struct kr_query *current_query; /**< Current evaluated query. */
+ struct {
+ /** Address that originated the request. NULL for internal origin. */
+ const struct sockaddr *addr;
+ /** Address that accepted the request. NULL for internal origin. */
+ const struct sockaddr *dst_addr;
+ const knot_pkt_t *packet;
+ struct kr_request_qsource_flags flags; /**< See definition above. */
+ size_t size; /**< query packet size */
+ } qsource;
+ struct {
+ unsigned rtt; /**< Current upstream RTT */
+ const struct sockaddr *addr; /**< Current upstream address */
+ } upstream; /**< Upstream information, valid only in consume() phase */
+ struct kr_qflags options;
+ int state;
+ ranked_rr_array_t answ_selected;
+ ranked_rr_array_t auth_selected;
+ ranked_rr_array_t add_selected;
+ rr_array_t additional;
+ bool answ_validated; /**< internal to validator; beware of caching, etc. */
+ bool auth_validated; /**< see answ_validated ^^ ; TODO */
+
+ /** Overall rank for the request.
+ *
+ * Values from kr_rank, currently just KR_RANK_SECURE and _INITIAL.
+ * Only read this in finish phase and after validator, please.
+ * Meaning of _SECURE: all RRs in answer+authority are _SECURE,
+ * including any negative results implied (NXDOMAIN, NODATA).
+ */
+ uint8_t rank;
+
+ struct kr_rplan rplan;
+ trace_log_f trace_log; /**< Logging tracepoint */
+ trace_callback_f trace_finish; /**< Request finish tracepoint */
+ int vars_ref; /**< Reference to per-request variable table. LUA_NOREF if not set. */
+ knot_mm_t pool;
+ unsigned int uid; /** for logging purposes only */
+ void *daemon_context; /** pointer to worker from daemon. Can be used in modules. */
+};
+
+/** Initializer for an array of *_selected. */
+#define kr_request_selected(req) { \
+ [KNOT_ANSWER] = &(req)->answ_selected, \
+ [KNOT_AUTHORITY] = &(req)->auth_selected, \
+ [KNOT_ADDITIONAL] = &(req)->add_selected, \
+ }
+
+/**
+ * Begin name resolution.
+ *
+ * @note Expects a request to have an initialized mempool, the "answer" packet will
+ * be kept during the resolution and will contain the final answer at the end.
+ *
+ * @param request request state with initialized mempool
+ * @param ctx resolution context
+ * @param answer allocated packet for final answer
+ * @return CONSUME (expecting query)
+ */
+KR_EXPORT
+int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pkt_t *answer);
+
+/**
+ * Consume input packet (may be either first query or answer to query originated from kr_resolve_produce())
+ *
+ * @note If the I/O fails, provide an empty or NULL packet, this will make iterator recognize nameserver failure.
+ *
+ * @param request request state (awaiting input)
+ * @param src [in] packet source address
+ * @param packet [in] input packet
+ * @return any state
+ */
+KR_EXPORT
+int kr_resolve_consume(struct kr_request *request, const struct sockaddr *src, knot_pkt_t *packet);
+
+/**
+ * Produce either next additional query or finish.
+ *
+ * If the CONSUME is returned then dst, type and packet will be filled with
+ * appropriate values and caller is responsible to send them and receive answer.
+ * If it returns any other state, then content of the variables is undefined.
+ *
+ * @param request request state (in PRODUCE state)
+ * @param dst [out] possible address of the next nameserver
+ * @param type [out] possible used socket type (SOCK_STREAM, SOCK_DGRAM)
+ * @param packet [out] packet to be filled with additional query
+ * @return any state
+ */
+KR_EXPORT
+int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *type, knot_pkt_t *packet);
+
+/**
+ * Finalises the outbound query packet with the knowledge of the IP addresses.
+ *
+ * @note The function must be called before actual sending of the request packet.
+ *
+ * @param request request state (in PRODUCE state)
+ * @param src address from which the query is going to be sent
+ * @param dst address of the name server
+ * @param type used socket type (SOCK_STREAM, SOCK_DGRAM)
+ * @param packet [in,out] query packet to be finalised
+ * @return kr_ok() or error code
+ */
+KR_EXPORT
+int kr_resolve_checkout(struct kr_request *request, const struct sockaddr *src,
+ struct sockaddr *dst, int type, knot_pkt_t *packet);
+
+/**
+ * Finish resolution and commit results if the state is DONE.
+ *
+ * @note The structures will be deinitialized, but the assigned memory pool is not going to
+ * be destroyed, as it's owned by caller.
+ *
+ * @param request request state
+ * @param state either DONE or FAIL state
+ * @return DONE
+ */
+KR_EXPORT
+int kr_resolve_finish(struct kr_request *request, int state);
+
+/**
+ * Return resolution plan.
+ * @param request request state
+ * @return pointer to rplan
+ */
+KR_EXPORT KR_PURE
+struct kr_rplan *kr_resolve_plan(struct kr_request *request);
+
+/**
+ * Return memory pool associated with request.
+ * @param request request state
+ * @return mempool
+ */
+KR_EXPORT KR_PURE
+knot_mm_t *kr_resolve_pool(struct kr_request *request);
+
diff --git a/lib/rplan.c b/lib/rplan.c
new file mode 100644
index 0000000..6ed8e4e
--- /dev/null
+++ b/lib/rplan.c
@@ -0,0 +1,308 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <libknot/descriptor.h>
+#include <libknot/errcode.h>
+
+#include "lib/rplan.h"
+#include "lib/resolve.h"
+#include "lib/cache/api.h"
+#include "lib/defines.h"
+#include "lib/layer.h"
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "plan", __VA_ARGS__)
+#define QUERY_PROVIDES(q, name, cls, type) \
+ ((q)->sclass == (cls) && (q)->stype == type && knot_dname_is_equal((q)->sname, name))
+
+inline static unsigned char chars_or(const unsigned char a, const unsigned char b)
+{
+ return a | b;
+}
+
+/** Bits set to 1 in variable b will be set to zero in variable a. */
+inline static unsigned char chars_mask(const unsigned char a, const unsigned char b)
+{
+ return a & ~b;
+}
+
+/** Apply mod(a, b) to every byte a, b from fl1, fl2 and return result in fl1. */
+inline static void kr_qflags_mod(struct kr_qflags *fl1, struct kr_qflags fl2,
+ unsigned char mod(const unsigned char a, const unsigned char b))
+{
+ if (!fl1) abort();
+ union {
+ struct kr_qflags flags;
+ /* C99 section 6.5.3.4: sizeof(char) == 1 */
+ unsigned char chars[sizeof(struct kr_qflags)];
+ } tmp1, tmp2;
+ /* The compiler should be able to optimize all this into simple ORs. */
+ tmp1.flags = *fl1;
+ tmp2.flags = fl2;
+ for (size_t i = 0; i < sizeof(struct kr_qflags); ++i) {
+ tmp1.chars[i] = mod(tmp1.chars[i], tmp2.chars[i]);
+ }
+ *fl1 = tmp1.flags;
+}
+
+/**
+ * Set bits from variable fl2 in variable fl1.
+ * Bits which are not set in fl2 are not modified in fl1.
+ *
+ * @param[in,out] fl1
+ * @param[in] fl2
+ */
+void kr_qflags_set(struct kr_qflags *fl1, struct kr_qflags fl2)
+{
+ kr_qflags_mod(fl1, fl2, chars_or);
+}
+
+/**
+ * Clear bits from variable fl2 in variable fl1.
+ * Bits which are not set in fl2 are not modified in fl1.
+ *
+ * @param[in,out] fl1
+ * @param[in] fl2
+ */
+void kr_qflags_clear(struct kr_qflags *fl1, struct kr_qflags fl2)
+{
+ kr_qflags_mod(fl1, fl2, chars_mask);
+}
+
+static struct kr_query *query_create(knot_mm_t *pool, const knot_dname_t *name, uint32_t uid)
+{
+ struct kr_query *qry = mm_alloc(pool, sizeof(struct kr_query));
+ if (qry == NULL) {
+ return NULL;
+ }
+
+ memset(qry, 0, sizeof(struct kr_query));
+ if (name != NULL) {
+ qry->sname = knot_dname_copy(name, pool);
+ if (qry->sname == NULL) {
+ mm_free(pool, qry);
+ return NULL;
+ }
+ }
+
+ knot_dname_to_lower(qry->sname);
+ qry->uid = uid;
+ return qry;
+}
+
+static void query_free(knot_mm_t *pool, struct kr_query *qry)
+{
+ kr_zonecut_deinit(&qry->zone_cut);
+ mm_free(pool, qry->sname);
+ mm_free(pool, qry);
+}
+
+int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, knot_mm_t *pool)
+{
+ if (rplan == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ memset(rplan, 0, sizeof(struct kr_rplan));
+
+ rplan->pool = pool;
+ rplan->request = request;
+ array_init(rplan->pending);
+ array_init(rplan->resolved);
+ rplan->next_uid = 0;
+ return KNOT_EOK;
+}
+
+void kr_rplan_deinit(struct kr_rplan *rplan)
+{
+ if (rplan == NULL) {
+ return;
+ }
+
+ for (size_t i = 0; i < rplan->pending.len; ++i) {
+ query_free(rplan->pool, rplan->pending.at[i]);
+ }
+ for (size_t i = 0; i < rplan->resolved.len; ++i) {
+ query_free(rplan->pool, rplan->resolved.at[i]);
+ }
+ array_clear_mm(rplan->pending, mm_free, rplan->pool);
+ array_clear_mm(rplan->resolved, mm_free, rplan->pool);
+}
+
+bool kr_rplan_empty(struct kr_rplan *rplan)
+{
+ if (rplan == NULL) {
+ return true;
+ }
+
+ return rplan->pending.len == 0;
+}
+
+static struct kr_query *kr_rplan_push_query(struct kr_rplan *rplan,
+ struct kr_query *parent,
+ const knot_dname_t *name)
+{
+ if (rplan == NULL) {
+ return NULL;
+ }
+
+ /* Make sure there's enough space */
+ int ret = array_reserve_mm(rplan->pending, rplan->pending.len + 1, kr_memreserve, rplan->pool);
+ if (ret != 0) {
+ return NULL;
+ }
+
+ struct kr_query *qry = query_create(rplan->pool, name, rplan->next_uid);
+ if (qry == NULL) {
+ return NULL;
+ }
+ rplan->next_uid += 1;
+ /* Class and type must be set outside this function. */
+ qry->flags = rplan->request->options;
+ qry->parent = parent;
+ qry->request = rplan->request;
+ qry->ns.ctx = rplan->request->ctx;
+ qry->ns.addr[0].ip.sa_family = AF_UNSPEC;
+ gettimeofday(&qry->timestamp, NULL);
+ qry->timestamp_mono = kr_now();
+ qry->creation_time_mono = parent ? parent->creation_time_mono : qry->timestamp_mono;
+ kr_zonecut_init(&qry->zone_cut, (const uint8_t *)"", rplan->pool);
+ qry->reorder = qry->flags.REORDER_RR ? kr_rand_bytes(sizeof(qry->reorder)) : 0;
+
+ /* When forwarding, keep the nameserver addresses. */
+ if (parent && parent->flags.FORWARD && qry->flags.FORWARD) {
+ ret = kr_nsrep_copy_set(&qry->ns, &parent->ns);
+ if (ret) {
+ query_free(rplan->pool, qry);
+ return NULL;
+ }
+ }
+
+ array_push(rplan->pending, qry);
+
+ return qry;
+}
+
+struct kr_query *kr_rplan_push_empty(struct kr_rplan *rplan, struct kr_query *parent)
+{
+ if (rplan == NULL) {
+ return NULL;
+ }
+
+ struct kr_query *qry = kr_rplan_push_query(rplan, parent, NULL);
+ if (qry == NULL) {
+ return NULL;
+ }
+
+ WITH_VERBOSE(qry) {
+ VERBOSE_MSG(qry, "plan '%s' type '%s' uid [%05u.%02u]\n", "", "",
+ qry->request ? qry->request->uid : 0, qry->uid);
+ }
+ return qry;
+}
+
+struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
+ const knot_dname_t *name, uint16_t cls, uint16_t type)
+{
+ if (rplan == NULL || name == NULL) {
+ return NULL;
+ }
+
+ struct kr_query *qry = kr_rplan_push_query(rplan, parent, name);
+ if (qry == NULL) {
+ return NULL;
+ }
+
+ qry->sclass = cls;
+ qry->stype = type;
+
+ WITH_VERBOSE(qry) {
+ KR_DNAME_GET_STR(name_str, name);
+ KR_RRTYPE_GET_STR(type_str, type);
+ VERBOSE_MSG(parent, "plan '%s' type '%s' uid [%05u.%02u]\n",
+ name_str, type_str,
+ qry->request ? qry->request->uid : 0, qry->uid);
+ }
+ return qry;
+}
+
+int kr_rplan_pop(struct kr_rplan *rplan, struct kr_query *qry)
+{
+ if (rplan == NULL || qry == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ /* Make sure there's enough space */
+ int ret = array_reserve_mm(rplan->resolved, rplan->resolved.len + 1, kr_memreserve, rplan->pool);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Find the query, it will likely be on top */
+ for (size_t i = rplan->pending.len; i > 0; i--) {
+ if (rplan->pending.at[i - 1] == qry) {
+ array_del(rplan->pending, i - 1);
+ array_push(rplan->resolved, qry);
+ break;
+ }
+ }
+ return KNOT_EOK;
+}
+
+bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type)
+{
+ while (name && closure) {
+ if (QUERY_PROVIDES(closure, name, cls, type)) {
+ return true;
+ }
+ closure = closure->parent;
+ }
+ return false;
+}
+
+struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan)
+{
+ if (rplan->resolved.len == 0) {
+ return NULL;
+ }
+ return array_tail(rplan->resolved);
+}
+
+struct kr_query *kr_rplan_last(struct kr_rplan *rplan)
+{
+ if (!kr_rplan_empty(rplan)) {
+ return array_tail(rplan->pending);
+ }
+
+ return kr_rplan_resolved(rplan);
+}
+
+struct kr_query *kr_rplan_find_resolved(struct kr_rplan *rplan, struct kr_query *parent,
+ const knot_dname_t *name, uint16_t cls, uint16_t type)
+{
+ struct kr_query *ret = NULL;
+ for (int i = 0; i < rplan->resolved.len; ++i) {
+ struct kr_query *q = rplan->resolved.at[i];
+ if (q->stype == type && q->sclass == cls &&
+ (parent == NULL || q->parent == parent) &&
+ knot_dname_is_equal(q->sname, name)) {
+ ret = q;
+ break;
+ }
+ }
+ return ret;
+}
+
+#undef VERBOSE_MSG
diff --git a/lib/rplan.h b/lib/rplan.h
new file mode 100644
index 0000000..21b0b0b
--- /dev/null
+++ b/lib/rplan.h
@@ -0,0 +1,221 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <sys/time.h>
+#include <libknot/dname.h>
+#include <libknot/codes.h>
+
+#include "lib/cache/api.h"
+#include "lib/zonecut.h"
+#include "lib/nsrep.h"
+
+/** Query flags */
+struct kr_qflags {
+ bool NO_MINIMIZE : 1; /**< Don't minimize QNAME. */
+ bool NO_THROTTLE : 1; /**< No query/slow NS throttling. */
+ bool NO_IPV6 : 1; /**< Disable IPv6 */
+ bool NO_IPV4 : 1; /**< Disable IPv4 */
+ bool TCP : 1; /**< Use TCP for this query. */
+ bool RESOLVED : 1; /**< Query is resolved. Note that kr_query gets
+ * RESOLVED before following a CNAME chain; see .CNAME. */
+ bool AWAIT_IPV4 : 1; /**< Query is waiting for A address. */
+ bool AWAIT_IPV6 : 1; /**< Query is waiting for AAAA address. */
+ bool AWAIT_CUT : 1; /**< Query is waiting for zone cut lookup */
+ bool SAFEMODE : 1; /**< Don't use fancy stuff (EDNS, 0x20, ...) */
+ bool CACHED : 1; /**< Query response is cached. */
+ bool NO_CACHE : 1; /**< No cache for lookup; exception: finding NSs and subqueries. */
+ bool EXPIRING : 1; /**< Query response is cached, but expiring. */
+ bool ALLOW_LOCAL : 1; /**< Allow queries to local or private address ranges. */
+ bool DNSSEC_WANT : 1; /**< Want DNSSEC secured answer; exception: +cd,
+ * i.e. knot_wire_set_cd(request->answer->wire). */
+ bool DNSSEC_BOGUS : 1; /**< Query response is DNSSEC bogus. */
+ bool DNSSEC_INSECURE : 1;/**< Query response is DNSSEC insecure. */
+ bool DNSSEC_CD : 1; /**< Instruction to set CD bit in request. */
+ bool STUB : 1; /**< Stub resolution, accept received answer as solved. */
+ bool ALWAYS_CUT : 1; /**< Always recover zone cut (even if cached). */
+ bool DNSSEC_WEXPAND : 1; /**< Query response has wildcard expansion. */
+ bool PERMISSIVE : 1; /**< Permissive resolver mode. */
+ bool STRICT : 1; /**< Strict resolver mode. */
+ bool BADCOOKIE_AGAIN : 1;/**< Query again because bad cookie returned. */
+ bool CNAME : 1; /**< Query response contains CNAME in answer section. */
+ bool REORDER_RR : 1; /**< Reorder cached RRs. */
+ bool TRACE : 1; /**< Also log answers if --verbose. */
+ bool NO_0X20 : 1; /**< Disable query case randomization . */
+ bool DNSSEC_NODS : 1; /**< DS non-existance is proven */
+ bool DNSSEC_OPTOUT : 1; /**< Closest encloser proof has optout */
+ bool NONAUTH : 1; /**< Non-authoritative in-bailiwick records are enough.
+ * TODO: utilize this also outside cache. */
+ bool FORWARD : 1; /**< Forward all queries to upstream; validate answers. */
+ bool DNS64_MARK : 1; /**< Internal mark for dns64 module. */
+ bool CACHE_TRIED : 1; /**< Internal to cache module. */
+ bool NO_NS_FOUND : 1; /**< No valid NS found during last PRODUCE stage. */
+};
+
+/** Combine flags together. This means set union for simple flags. */
+KR_EXPORT
+void kr_qflags_set(struct kr_qflags *fl1, struct kr_qflags fl2);
+
+/** Remove flags. This means set-theoretic difference. */
+KR_EXPORT
+void kr_qflags_clear(struct kr_qflags *fl1, struct kr_qflags fl2);
+
+/** Callback for serve-stale decisions.
+ * @param ttl the expired TTL (i.e. it's < 0)
+ * @return the adjusted TTL (typically 1) or < 0.
+ */
+typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
+ const struct kr_query *qry);
+
+/**
+ * Single query representation.
+ */
+struct kr_query {
+ struct kr_query *parent;
+ knot_dname_t *sname; /**< The name to resolve - lower-cased, uncompressed. */
+ uint16_t stype;
+ uint16_t sclass;
+ uint16_t id;
+ struct kr_qflags flags, forward_flags;
+ uint32_t secret;
+ uint16_t fails;
+ uint16_t reorder; /**< Seed to reorder (cached) RRs in answer or zero. */
+ uint64_t creation_time_mono; /* The time of query's creation (milliseconds).
+ * Or time of creation of an oldest
+ * ancestor if it is a subquery. */
+ uint64_t timestamp_mono; /**< Time of query created or time of
+ * query to upstream resolver (milliseconds). */
+ struct timeval timestamp; /**< Real time for TTL+DNSSEC checks (.tv_sec only). */
+ struct kr_zonecut zone_cut;
+ struct kr_layer_pickle *deferred;
+ uint32_t uid; /**< Query iteration number, unique within the kr_rplan. */
+ /** Pointer to the query that originated this one because of following a CNAME (or NULL). */
+ struct kr_query *cname_parent;
+ struct kr_request *request; /**< Parent resolution request. */
+ kr_stale_cb stale_cb; /**< See the type */
+ /* Beware: this must remain the last, because of lua bindings. */
+ struct kr_nsrep ns;
+};
+
+/** @cond internal Array of queries. */
+typedef array_t(struct kr_query *) kr_qarray_t;
+/* @endcond */
+
+/**
+ * Query resolution plan structure.
+ *
+ * The structure most importantly holds the original query, answer and the
+ * list of pending queries required to resolve the original query.
+ * It also keeps a notion of current zone cut.
+ */
+struct kr_rplan {
+ kr_qarray_t pending; /**< List of pending queries. */
+ kr_qarray_t resolved; /**< List of resolved queries. */
+ struct kr_request *request; /**< Parent resolution request. */
+ knot_mm_t *pool; /**< Temporary memory pool. */
+ uint32_t next_uid; /**< Next value for kr_query::uid (incremental). */
+};
+
+/**
+ * Initialize resolution plan (empty).
+ * @param rplan plan instance
+ * @param request resolution request
+ * @param pool ephemeral memory pool for whole resolution
+ */
+KR_EXPORT
+int kr_rplan_init(struct kr_rplan *rplan, struct kr_request *request, knot_mm_t *pool);
+
+/**
+ * Deinitialize resolution plan, aborting any uncommited transactions.
+ * @param rplan plan instance
+ */
+KR_EXPORT
+void kr_rplan_deinit(struct kr_rplan *rplan);
+
+/**
+ * Return true if the resolution plan is empty (i.e. finished or initialized)
+ * @param rplan plan instance
+ * @return true or false
+ */
+KR_EXPORT KR_PURE
+bool kr_rplan_empty(struct kr_rplan *rplan);
+
+/**
+ * Push empty query to the top of the resolution plan.
+ * @note This query serves as a cookie query only.
+ * @param rplan plan instance
+ * @param parent query parent (or NULL)
+ * @return query instance or NULL
+ */
+KR_EXPORT
+struct kr_query *kr_rplan_push_empty(struct kr_rplan *rplan,
+ struct kr_query *parent);
+
+/**
+ * Push a query to the top of the resolution plan.
+ * @note This means that this query takes precedence before all pending queries.
+ * @param rplan plan instance
+ * @param parent query parent (or NULL)
+ * @param name resolved name
+ * @param cls resolved class
+ * @param type resolved type
+ * @return query instance or NULL
+ */
+KR_EXPORT
+struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
+ const knot_dname_t *name, uint16_t cls, uint16_t type);
+
+/**
+ * Pop existing query from the resolution plan.
+ * @note Popped queries are not discarded, but moved to the resolved list.
+ * @param rplan plan instance
+ * @param qry resolved query
+ * @return 0 or an error
+ */
+KR_EXPORT
+int kr_rplan_pop(struct kr_rplan *rplan, struct kr_query *qry);
+
+/**
+ * Return true if resolution chain satisfies given query.
+ */
+KR_EXPORT KR_PURE
+bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type);
+
+/** Return last resolved query. */
+KR_EXPORT KR_PURE
+struct kr_query *kr_rplan_resolved(struct kr_rplan *rplan);
+
+/**
+ * Return last query (either currently being solved or last resolved).
+ * This is necessary to retrieve the last query in case of resolution failures (e.g. time limit reached).
+ */
+KR_EXPORT KR_PURE
+struct kr_query *kr_rplan_last(struct kr_rplan *rplan);
+
+
+/**
+ * Check if a given query already resolved.
+ * @param rplan plan instance
+ * @param parent query parent (or NULL)
+ * @param name resolved name
+ * @param cls resolved class
+ * @param type resolved type
+ * @return query instance or NULL
+ */
+KR_EXPORT KR_PURE
+struct kr_query *kr_rplan_find_resolved(struct kr_rplan *rplan, struct kr_query *parent,
+ const knot_dname_t *name, uint16_t cls, uint16_t type);
diff --git a/lib/utils.c b/lib/utils.c
new file mode 100644
index 0000000..fe9ab03
--- /dev/null
+++ b/lib/utils.c
@@ -0,0 +1,1084 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <contrib/cleanup.h>
+#include <contrib/ccan/asprintf/asprintf.h>
+#include <ucw/mempool.h>
+#include <gnutls/gnutls.h>
+#include <libknot/descriptor.h>
+#include <libknot/dname.h>
+#include <libknot/rrtype/rrsig.h>
+#include <libknot/rrset-dump.h>
+#include <libknot/version.h>
+#include <uv.h>
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include "lib/generic/array.h"
+#include "lib/nsrep.h"
+#include "lib/module.h"
+#include "lib/resolve.h"
+
+
+/* Always compile-in log symbols, even if disabled. */
+#undef kr_verbose_status
+#undef kr_verbose_set
+#undef kr_log_verbose
+
+/* Logging & debugging */
+bool kr_verbose_status = false;
+
+void *mm_realloc(knot_mm_t *mm, void *what, size_t size, size_t prev_size)
+{
+ if (mm) {
+ void *p = mm->alloc(mm->ctx, size);
+ if (p == NULL) {
+ return NULL;
+ } else {
+ if (what) {
+ memcpy(p, what,
+ prev_size < size ? prev_size : size);
+ }
+ mm_free(mm, what);
+ return p;
+ }
+ } else {
+ return realloc(what, size);
+ }
+}
+
+void *mm_malloc(void *ctx, size_t n)
+{
+ (void)ctx;
+ return malloc(n);
+}
+
+/*
+ * Macros.
+ */
+#define strlen_safe(x) ((x) ? strlen(x) : 0)
+
+/**
+ * @internal Convert 16bit unsigned to string, keeps leading spaces.
+ * @note Always fills dst length = 5
+ * Credit: http://computer-programming-forum.com/46-asm/7aa4b50bce8dd985.htm
+ */
+static inline int u16tostr(uint8_t *dst, uint16_t num)
+{
+ uint32_t tmp = num * (((1 << 28) / 10000) + 1) - (num / 4);
+ for(size_t i = 0; i < 5; i++) {
+ dst[i] = '0' + (char) (tmp >> 28);
+ tmp = (tmp & 0x0fffffff) * 10;
+ }
+ return 5;
+}
+
+/*
+ * Cleanup callbacks.
+ */
+
+static void kres_gnutls_log(int level, const char *message)
+{
+ kr_log_verbose("[gnutls] (%d) %s", level, message);
+}
+
+bool kr_verbose_set(bool status)
+{
+#ifndef NOVERBOSELOG
+ kr_verbose_status = status;
+
+ /* gnutls logs messages related to our TLS and also libdnssec,
+ * and the logging is set up in a global way only */
+ if (status) {
+ gnutls_global_set_log_function(kres_gnutls_log);
+ }
+ gnutls_global_set_log_level(status ? 5 : 0);
+#endif
+ return kr_verbose_status;
+}
+
+void kr_log_verbose(const char *fmt, ...)
+{
+ if (kr_verbose_status) {
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ fflush(stdout);
+ }
+}
+
+void kr_log_qverbose_impl(const struct kr_query *qry, const char *cls, const char *fmt, ...)
+{
+ unsigned ind = 0;
+ for (const struct kr_query *q = qry; q; q = q->parent)
+ ind += 2;
+ uint32_t qry_uid = qry ? qry->uid : 0;
+ uint32_t req_uid = qry && qry->request ? qry->request->uid : 0;
+ /* Simplified kr_log_verbose() calls, first prefix then passed fmt...
+ * Calling it would take about the same amount of code. */
+ printf("[%05u.%02u][%s] %*s", req_uid, qry_uid, cls, ind, "");
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ fflush(stdout);
+}
+
+bool kr_log_trace(const struct kr_query *query, const char *source, const char *fmt, ...)
+{
+ if (!kr_log_trace_enabled(query)) {
+ return false;
+ }
+
+ auto_free char *msg = NULL;
+
+ va_list args;
+ va_start(args, fmt);
+ int len = vasprintf(&msg, fmt, args);
+ va_end(args);
+
+ /* Check formatting result before logging */
+ if (len < 0) {
+ return false;
+ }
+
+ query->request->trace_log(query, source, msg);
+ return true;
+}
+
+char* kr_strcatdup(unsigned n, ...)
+{
+ if (n < 1) {
+ return NULL;
+ }
+
+ /* Calculate total length */
+ size_t total_len = 0;
+ va_list vl;
+ va_start(vl, n);
+ for (unsigned i = 0; i < n; ++i) {
+ char *item = va_arg(vl, char *);
+ const size_t new_len = total_len + strlen_safe(item);
+ if (unlikely(new_len < total_len)) {
+ va_end(vl);
+ return NULL;
+ }
+ total_len = new_len;
+ }
+ va_end(vl);
+
+ /* Allocate result and fill */
+ char *result = NULL;
+ if (total_len > 0) {
+ if (unlikely(total_len + 1 == 0)) return NULL;
+ result = malloc(total_len + 1);
+ }
+ if (result) {
+ char *stream = result;
+ va_start(vl, n);
+ for (unsigned i = 0; i < n; ++i) {
+ char *item = va_arg(vl, char *);
+ if (item) {
+ size_t len = strlen(item);
+ memcpy(stream, item, len + 1);
+ stream += len;
+ }
+ }
+ va_end(vl);
+ }
+
+ return result;
+}
+
+int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+{
+ if (*have >= want) {
+ return 0;
+ } else {
+ knot_mm_t *pool = baton;
+ size_t next_size = array_next_count(want);
+ void *mem_new = mm_alloc(pool, next_size * elm_size);
+ if (mem_new != NULL) {
+ memcpy(mem_new, *mem, (*have)*(elm_size));
+ mm_free(pool, *mem);
+ *mem = mem_new;
+ *have = next_size;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int pkt_recycle(knot_pkt_t *pkt, bool keep_question)
+{
+ /* The maximum size of a header + query name + (class, type) */
+ uint8_t buf[KNOT_WIRE_HEADER_SIZE + KNOT_DNAME_MAXLEN + 2 * sizeof(uint16_t)];
+
+ /* Save header and the question section */
+ size_t base_size = KNOT_WIRE_HEADER_SIZE;
+ if (keep_question) {
+ base_size += knot_pkt_question_size(pkt);
+ }
+ assert(base_size <= sizeof(buf));
+ memcpy(buf, pkt->wire, base_size);
+
+ /* Clear the packet and its auxiliary structures */
+ knot_pkt_clear(pkt);
+
+ /* Restore header and question section and clear counters */
+ pkt->size = base_size;
+ memcpy(pkt->wire, buf, base_size);
+ knot_wire_set_qdcount(pkt->wire, keep_question);
+ knot_wire_set_ancount(pkt->wire, 0);
+ knot_wire_set_nscount(pkt->wire, 0);
+ knot_wire_set_arcount(pkt->wire, 0);
+
+ /* Reparse question */
+ knot_pkt_begin(pkt, KNOT_ANSWER);
+ return knot_pkt_parse_question(pkt);
+}
+
+int kr_pkt_recycle(knot_pkt_t *pkt)
+{
+ return pkt_recycle(pkt, false);
+}
+
+int kr_pkt_clear_payload(knot_pkt_t *pkt)
+{
+ return pkt_recycle(pkt, knot_wire_get_qdcount(pkt->wire));
+}
+
+int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl,
+ uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen)
+{
+ /* LATER(opt.): there's relatively lots of copying, but ATM kr_pkt_put()
+ * isn't considered to be used in any performance-critical parts (just lua). */
+ if (!pkt || !name) {
+ return kr_error(EINVAL);
+ }
+ /* Create empty RR */
+ knot_rrset_t rr;
+ knot_rrset_init(&rr, knot_dname_copy(name, &pkt->mm), rtype, rclass, ttl);
+ /* Create RDATA */
+ knot_rdata_t *rdata_tmp = mm_alloc(&pkt->mm, offsetof(knot_rdata_t, data) + rdlen);
+ knot_rdata_init(rdata_tmp, rdlen, rdata);
+ knot_rdataset_add(&rr.rrs, rdata_tmp, &pkt->mm);
+ mm_free(&pkt->mm, rdata_tmp); /* we're always on mempool for now, but whatever */
+ /* Append RR */
+ return knot_pkt_put(pkt, 0, &rr, KNOT_PF_FREE);
+}
+
+void kr_pkt_make_auth_header(knot_pkt_t *pkt)
+{
+ assert(pkt && pkt->wire);
+ knot_wire_clear_ad(pkt->wire);
+ knot_wire_set_aa(pkt->wire);
+}
+
+const char *kr_inaddr(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return NULL;
+ }
+ switch (addr->sa_family) {
+ case AF_INET: return (const char *)&(((const struct sockaddr_in *)addr)->sin_addr);
+ case AF_INET6: return (const char *)&(((const struct sockaddr_in6 *)addr)->sin6_addr);
+ default: return NULL;
+ }
+}
+
+int kr_inaddr_family(const struct sockaddr *addr)
+{
+ if (!addr)
+ return AF_UNSPEC;
+ return addr->sa_family;
+}
+
+int kr_inaddr_len(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return kr_error(EINVAL);
+ }
+ return kr_family_len(addr->sa_family);
+}
+
+int kr_sockaddr_len(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return kr_error(EINVAL);
+ }
+ switch (addr->sa_family) {
+ case AF_INET: return sizeof(struct sockaddr_in);
+ case AF_INET6: return sizeof(struct sockaddr_in6);
+ default: return kr_error(EINVAL);
+ }
+}
+
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right)
+{
+ if (!left || !right) {
+ return kr_error(EINVAL);
+ }
+ if (left->sa_family != right->sa_family) {
+ return kr_error(EFAULT);
+ }
+ if (left->sa_family == AF_INET) {
+ struct sockaddr_in *left_in = (struct sockaddr_in *)left;
+ struct sockaddr_in *right_in = (struct sockaddr_in *)right;
+ if (left_in->sin_addr.s_addr != right_in->sin_addr.s_addr) {
+ return kr_error(EFAULT);
+ }
+ if (left_in->sin_port != right_in->sin_port) {
+ return kr_error(EFAULT);
+ }
+ } else if (left->sa_family == AF_INET6) {
+ struct sockaddr_in6 *left_in6 = (struct sockaddr_in6 *)left;
+ struct sockaddr_in6 *right_in6 = (struct sockaddr_in6 *)right;
+ if (memcmp(&left_in6->sin6_addr, &right_in6->sin6_addr,
+ sizeof(struct in6_addr)) != 0) {
+ return kr_error(EFAULT);
+ }
+ if (left_in6->sin6_port != right_in6->sin6_port) {
+ return kr_error(EFAULT);
+ }
+ } else {
+ return kr_error(ENOENT);
+ }
+ return kr_ok();
+}
+
+uint16_t kr_inaddr_port(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return 0;
+ }
+ switch (addr->sa_family) {
+ case AF_INET: return ntohs(((const struct sockaddr_in *)addr)->sin_port);
+ case AF_INET6: return ntohs(((const struct sockaddr_in6 *)addr)->sin6_port);
+ default: return 0;
+ }
+}
+
+void kr_inaddr_set_port(struct sockaddr *addr, uint16_t port)
+{
+ if (!addr) {
+ return;
+ }
+ switch (addr->sa_family) {
+ case AF_INET: ((struct sockaddr_in *)addr)->sin_port = htons(port);
+ case AF_INET6: ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
+ default: break;
+ }
+}
+
+int kr_inaddr_str(const struct sockaddr *addr, char *buf, size_t *buflen)
+{
+ if (!addr || !buf || !buflen) {
+ return kr_error(EINVAL);
+ }
+
+ if (!inet_ntop(addr->sa_family, kr_inaddr(addr), buf, *buflen)) {
+ return kr_error(errno);
+ }
+ const int len = strlen(buf);
+ const int len_need = len + 1 + 5 + 1;
+ if (len_need > *buflen) {
+ *buflen = len_need;
+ return kr_error(ENOSPC);
+ }
+ *buflen = len_need;
+ buf[len] = '#';
+ u16tostr((uint8_t *)&buf[len + 1], kr_inaddr_port(addr));
+ buf[len_need - 1] = 0;
+ return kr_ok();
+}
+
+int kr_straddr_family(const char *addr)
+{
+ if (!addr) {
+ return kr_error(EINVAL);
+ }
+ if (strchr(addr, ':')) {
+ return AF_INET6;
+ }
+ return AF_INET;
+}
+
+int kr_family_len(int family)
+{
+ switch (family) {
+ case AF_INET: return sizeof(struct in_addr);
+ case AF_INET6: return sizeof(struct in6_addr);
+ default: return kr_error(EINVAL);
+ }
+}
+
+struct sockaddr * kr_straddr_socket(const char *addr, int port)
+{
+ switch (kr_straddr_family(addr)) {
+ case AF_INET: {
+ struct sockaddr_in *res = malloc(sizeof(*res));
+ if (uv_ip4_addr(addr, port, res) >= 0) {
+ return (struct sockaddr *)res;
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *res = malloc(sizeof(*res));
+ if (uv_ip6_addr(addr, port, res) >= 0) {
+ return (struct sockaddr *)res;
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+ default:
+ return NULL;
+ }
+}
+
+int kr_straddr_subnet(void *dst, const char *addr)
+{
+ if (!dst || !addr) {
+ return kr_error(EINVAL);
+ }
+ /* Parse subnet */
+ int bit_len = 0;
+ int family = kr_straddr_family(addr);
+ auto_free char *addr_str = strdup(addr);
+ char *subnet = strchr(addr_str, '/');
+ if (subnet) {
+ *subnet = '\0';
+ subnet += 1;
+ bit_len = strtol(subnet, NULL, 10);
+ /* Check client subnet length */
+ const int max_len = (family == AF_INET6) ? 128 : 32;
+ if (bit_len < 0 || bit_len > max_len) {
+ return kr_error(ERANGE);
+ }
+ } else {
+ /* No subnet, use maximal subnet length. */
+ bit_len = (family == AF_INET6) ? 128 : 32;
+ }
+ /* Parse address */
+ int ret = inet_pton(family, addr_str, dst);
+ if (ret < 0) {
+ return kr_error(EILSEQ);
+ }
+
+ return bit_len;
+}
+
+int kr_straddr_split(const char *addr, char *buf, size_t buflen, uint16_t *port)
+{
+ const int base = 10;
+ long p = 0;
+ size_t addrlen = strlen(addr);
+ char *p_start = strchr(addr, '@');
+ char *p_end;
+
+ if (!p_start) {
+ p_start = strchr(addr, '#');
+ }
+
+ if (p_start) {
+ if (p_start[1] != '\0'){
+ p = strtol(p_start + 1, &p_end, base);
+ if (*p_end != '\0' || p <= 0 || p > UINT16_MAX) {
+ return kr_error(EINVAL);
+ }
+ }
+ addrlen = p_start - addr;
+ }
+
+ /* Check if address is valid. */
+ if (addrlen >= INET6_ADDRSTRLEN) {
+ return kr_error(EINVAL);
+ }
+
+ char str[INET6_ADDRSTRLEN];
+ struct sockaddr_storage ss;
+
+ memcpy(str, addr, addrlen); str[addrlen] = '\0';
+
+ int family = kr_straddr_family(str);
+ if (family == kr_error(EINVAL) || !inet_pton(family, str, &ss)) {
+ return kr_error(EINVAL);
+ }
+
+ /* Address and port contains valid values, return it to caller */
+ if (buf) {
+ if (addrlen >= buflen) {
+ return kr_error(ENOSPC);
+ }
+ memcpy(buf, addr, addrlen); buf[addrlen] = '\0';
+ }
+ if (port) {
+ *port = (uint16_t)p;
+ }
+
+ return kr_ok();
+}
+
+int kr_straddr_join(const char *addr, uint16_t port, char *buf, size_t *buflen)
+{
+ if (!addr || !buf || !buflen) {
+ return kr_error(EINVAL);
+ }
+
+ struct sockaddr_storage ss;
+ int family = kr_straddr_family(addr);
+ if (family == kr_error(EINVAL) || !inet_pton(family, addr, &ss)) {
+ return kr_error(EINVAL);
+ }
+
+ int len = strlen(addr);
+ if (len + 6 >= *buflen) {
+ return kr_error(ENOSPC);
+ }
+
+ memcpy(buf, addr, len + 1);
+ buf[len] = '#';
+ u16tostr((uint8_t *)&buf[len + 1], port);
+ len += 6;
+ buf[len] = 0;
+ *buflen = len;
+
+ return kr_ok();
+}
+
+int kr_bitcmp(const char *a, const char *b, int bits)
+{
+ /* We're using the function from lua directly, so at least for now
+ * we avoid crashing on bogus inputs. Meaning: NULL is ordered before
+ * anything else, and negative length is the same as zero.
+ * TODO: review the call sites and probably remove the checks. */
+ if (bits <= 0 || (!a && !b)) {
+ return 0;
+ } else if (!a) {
+ return -1;
+ } else if (!b) {
+ return 1;
+ }
+
+ assert((a && b && bits >= 0) || bits == 0);
+ /* Compare part byte-divisible part. */
+ const size_t chunk = bits / 8;
+ int ret = memcmp(a, b, chunk);
+ if (ret != 0) {
+ return ret;
+ }
+ a += chunk;
+ b += chunk;
+ bits -= chunk * 8;
+ /* Compare last partial byte address block. */
+ if (bits > 0) {
+ const size_t shift = (8 - bits);
+ ret = ((uint8_t)(*a >> shift) - (uint8_t)(*b >> shift));
+ }
+ return ret;
+}
+
+int kr_rrkey(char *key, uint16_t class, const knot_dname_t *owner,
+ uint16_t type, uint16_t additional)
+{
+ if (!key || !owner) {
+ return kr_error(EINVAL);
+ }
+ uint8_t *key_buf = (uint8_t *)key;
+ int ret = u16tostr(key_buf, class);
+ if (ret <= 0) {
+ return ret;
+ }
+ key_buf += ret;
+ ret = knot_dname_to_wire(key_buf, owner, KNOT_DNAME_MAXLEN);
+ if (ret <= 0) {
+ return ret;
+ }
+ knot_dname_to_lower(key_buf);
+ key_buf += ret - 1;
+ ret = u16tostr(key_buf, type);
+ if (ret <= 0) {
+ return ret;
+ }
+ key_buf += ret;
+ ret = u16tostr(key_buf, additional);
+ if (ret <= 0) {
+ return ret;
+ }
+ key_buf[ret] = '\0';
+ return (char *)&key_buf[ret] - key;
+}
+
+/** Return whether two RRsets match, i.e. would form the same set; see ranked_rr_array_t */
+static inline bool rrsets_match(const knot_rrset_t *rr1, const knot_rrset_t *rr2)
+{
+ bool match = rr1->type == rr2->type && rr1->rclass == rr2->rclass;
+ if (match && rr2->type == KNOT_RRTYPE_RRSIG) {
+ match = match && knot_rrsig_type_covered(rr1->rrs.rdata)
+ == knot_rrsig_type_covered(rr2->rrs.rdata);
+ }
+ match = match && knot_dname_is_equal(rr1->owner, rr2->owner);
+ return match;
+}
+
+/** Ensure that an index in a ranked array won't cause "duplicate" RRsets on wire.
+ *
+ * Other entries that would form the same RRset get to_wire = false.
+ * See also rrsets_match.
+ */
+static int to_wire_ensure_unique(ranked_rr_array_t *array, size_t index)
+{
+ bool ok = array && index < array->len;
+ if (!ok) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+
+ const struct ranked_rr_array_entry *e0 = array->at[index];
+ if (!e0->to_wire) {
+ return kr_ok();
+ }
+
+ for (ssize_t i = array->len - 1; i >= 0; --i) {
+ /* ^ iterate backwards, as the end is more likely in CPU caches */
+ struct ranked_rr_array_entry *ei = array->at[i];
+ if (ei->qry_uid == e0->qry_uid /* assumption: no duplicates within qry */
+ || !ei->to_wire /* no use for complex comparison if @to_wire */
+ ) {
+ continue;
+ }
+ if (rrsets_match(ei->rr, e0->rr)) {
+ ei->to_wire = false;
+ }
+ }
+ return kr_ok();
+}
+
+int kr_ranked_rrarray_add(ranked_rr_array_t *array, const knot_rrset_t *rr,
+ uint8_t rank, bool to_wire, uint32_t qry_uid, knot_mm_t *pool)
+{
+ /* rr always has one record per rrset
+ * check if another rrset with the same
+ * rclass/type/owner combination exists within current query
+ * and merge if needed */
+ for (ssize_t i = array->len - 1; i >= 0; --i) {
+ ranked_rr_array_entry_t *stashed = array->at[i];
+ if (stashed->yielded) {
+ break;
+ }
+ if (stashed->qry_uid != qry_uid) {
+ break;
+ }
+ if (!rrsets_match(stashed->rr, rr)) {
+ continue;
+ }
+ /* Found the entry to merge with. Check consistency and merge. */
+ bool ok = stashed->rank == rank && !stashed->cached;
+ if (!ok) {
+ assert(false);
+ return kr_error(EEXIST);
+ }
+ /* It may happen that an RRset is first considered useful
+ * (to_wire = false, e.g. due to being part of glue),
+ * and later we may find we also want it in the answer. */
+ stashed->to_wire = stashed->to_wire || to_wire;
+
+ return knot_rdataset_merge(&stashed->rr->rrs, &rr->rrs, pool);
+ }
+
+ /* No stashed rrset found, add */
+ int ret = array_reserve_mm(*array, array->len + 1, kr_memreserve, pool);
+ if (ret != 0) {
+ return kr_error(ENOMEM);
+ }
+
+ ranked_rr_array_entry_t *entry = mm_alloc(pool, sizeof(ranked_rr_array_entry_t));
+ if (!entry) {
+ return kr_error(ENOMEM);
+ }
+ knot_rrset_t *copy = knot_rrset_copy(rr, pool);
+ if (!copy) {
+ mm_free(pool, entry);
+ return kr_error(ENOMEM);
+ }
+
+ entry->qry_uid = qry_uid;
+ entry->rr = copy;
+ entry->rank = rank;
+ entry->revalidation_cnt = 0;
+ entry->cached = false;
+ entry->yielded = false;
+ entry->to_wire = to_wire;
+ if (array_push(*array, entry) < 0) {
+ /* Silence coverity. It shouldn't be possible to happen,
+ * due to the array_reserve_mm call above. */
+ mm_free(pool, entry);
+ return kr_error(ENOMEM);
+ }
+
+ return to_wire_ensure_unique(array, array->len - 1);
+}
+
+int kr_ranked_rrarray_set_wire(ranked_rr_array_t *array, bool to_wire,
+ uint32_t qry_uid, bool check_dups,
+ bool (*extraCheck)(const ranked_rr_array_entry_t *))
+{
+ for (size_t i = 0; i < array->len; ++i) {
+ ranked_rr_array_entry_t *entry = array->at[i];
+ if (entry->qry_uid != qry_uid) {
+ continue;
+ }
+ if (extraCheck != NULL && !extraCheck(entry)) {
+ continue;
+ }
+ entry->to_wire = to_wire;
+ if (check_dups) {
+ int ret = to_wire_ensure_unique(array, i);
+ if (ret) return ret;
+ }
+ }
+ return kr_ok();
+}
+
+
+static char *callprop(struct kr_module *module, const char *prop, const char *input, void *env)
+{
+ if (!module || !module->props || !prop) {
+ return NULL;
+ }
+ for (const struct kr_prop *p = module->props(); p && p->name; ++p) {
+ if (p->cb != NULL && strcmp(p->name, prop) == 0) {
+ return p->cb(env, module, input);
+ }
+ }
+ return NULL;
+}
+
+char *kr_module_call(struct kr_context *ctx, const char *module, const char *prop, const char *input)
+{
+ if (!ctx || !ctx->modules || !module || !prop) {
+ return NULL;
+ }
+ module_array_t *mod_list = ctx->modules;
+ for (size_t i = 0; i < mod_list->len; ++i) {
+ struct kr_module *mod = mod_list->at[i];
+ if (strcmp(mod->name, module) == 0) {
+ return callprop(mod, prop, input, ctx);
+ }
+ }
+ return NULL;
+}
+
+static void flags_to_str(char *dst, const knot_pkt_t *pkt, size_t maxlen)
+{
+ int offset = 0;
+ int ret = 0;
+ struct {
+ uint8_t (*get) (const uint8_t *packet);
+ char name[3];
+ } flag[7] = {
+ {knot_wire_get_qr, "qr"},
+ {knot_wire_get_aa, "aa"},
+ {knot_wire_get_rd, "rd"},
+ {knot_wire_get_ra, "ra"},
+ {knot_wire_get_tc, "tc"},
+ {knot_wire_get_ad, "ad"},
+ {knot_wire_get_cd, "cd"}
+ };
+ for (int i = 0; i < 7; ++i) {
+ if (!flag[i].get(pkt->wire)) {
+ continue;
+ }
+ ret = snprintf(dst + offset, maxlen, "%s ", flag[i].name);
+ if (ret <= 0 || ret >= maxlen) {
+ dst[0] = 0;
+ return;
+ }
+ offset += ret;
+ maxlen -= ret;
+ }
+ dst[offset] = 0;
+}
+
+static char *print_section_opt(struct mempool *mp, char *endp, const knot_rrset_t *rr, const uint8_t rcode)
+{
+ uint8_t ercode = knot_edns_get_ext_rcode(rr);
+ uint16_t ext_rcode_id = knot_edns_whole_rcode(ercode, rcode);
+ const char *ext_rcode_str = "Unused";
+ const knot_lookup_t *ext_rcode;
+
+ if (ercode > 0) {
+ ext_rcode = knot_lookup_by_id(knot_rcode_names, ext_rcode_id);
+ if (ext_rcode != NULL) {
+ ext_rcode_str = ext_rcode->name;
+ } else {
+ ext_rcode_str = "Unknown";
+ }
+ }
+
+ return mp_printf_append(mp, endp,
+ ";; EDNS PSEUDOSECTION:\n;; "
+ "Version: %u; flags: %s; UDP size: %u B; ext-rcode: %s\n\n",
+ knot_edns_get_version(rr),
+ (knot_edns_do(rr) != 0) ? "do" : "",
+ knot_edns_get_payload(rr),
+ ext_rcode_str);
+
+}
+
+char *kr_pkt_text(const knot_pkt_t *pkt)
+{
+ if (!pkt) {
+ return NULL;
+ }
+
+ struct mempool *mp = mp_new(512);
+
+ static const char * snames[] = {
+ ";; ANSWER SECTION", ";; AUTHORITY SECTION", ";; ADDITIONAL SECTION"
+ };
+ char flags[32];
+ uint8_t pkt_rcode = knot_wire_get_rcode(pkt->wire);
+ uint8_t pkt_opcode = knot_wire_get_opcode(pkt->wire);
+ const char *rcode_str = "Unknown";
+ const char *opcode_str = "Unknown";
+ const knot_lookup_t *rcode = knot_lookup_by_id(knot_rcode_names, pkt_rcode);
+ const knot_lookup_t *opcode = knot_lookup_by_id(knot_opcode_names, pkt_opcode);
+ uint16_t qry_id = knot_wire_get_id(pkt->wire);
+ uint16_t qdcount = knot_wire_get_qdcount(pkt->wire);
+
+ if (rcode != NULL) {
+ rcode_str = rcode->name;
+ }
+ if (opcode != NULL) {
+ opcode_str = opcode->name;
+ }
+ flags_to_str(flags, pkt, sizeof(flags));
+
+ char *ptr = mp_printf(mp,
+ ";; ->>HEADER<<- opcode: %s; status: %s; id: %hu\n"
+ ";; Flags: %s QUERY: %hu; ANSWER: %hu; "
+ "AUTHORITY: %hu; ADDITIONAL: %hu\n\n",
+ opcode_str, rcode_str, qry_id,
+ flags,
+ qdcount,
+ knot_wire_get_ancount(pkt->wire),
+ knot_wire_get_nscount(pkt->wire),
+ knot_wire_get_arcount(pkt->wire));
+
+ if (knot_pkt_has_edns(pkt)) {
+ ptr = print_section_opt(mp, ptr, pkt->opt_rr, knot_wire_get_rcode(pkt->wire));
+ }
+
+ if (qdcount == 1) {
+ KR_DNAME_GET_STR(qname, knot_pkt_qname(pkt));
+ KR_RRTYPE_GET_STR(rrtype, knot_pkt_qtype(pkt));
+ ptr = mp_printf_append(mp, ptr, ";; QUESTION SECTION\n%s\t\t%s\n", qname, rrtype);
+ } else if (qdcount > 1) {
+ ptr = mp_printf_append(mp, ptr, ";; Warning: unsupported QDCOUNT %hu\n", qdcount);
+ }
+
+ for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
+ const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
+ if (sec->count == 0 || knot_pkt_rr(sec, 0)->type == KNOT_RRTYPE_OPT) {
+ /* OPT RRs are _supposed_ to be the last ^^, if they appear */
+ continue;
+ }
+
+ ptr = mp_printf_append(mp, ptr, "\n%s\n", snames[i - KNOT_ANSWER]);
+ for (unsigned k = 0; k < sec->count; ++k) {
+ const knot_rrset_t *rr = knot_pkt_rr(sec, k);
+ if (rr->type == KNOT_RRTYPE_OPT) {
+ continue;
+ }
+ auto_free char *rr_text = kr_rrset_text(rr);
+ ptr = mp_printf_append(mp, ptr, "%s", rr_text);
+ }
+ }
+
+ /* Close growing buffer and duplicate result before deleting */
+ char *result = strdup(ptr);
+ mp_delete(mp);
+ return result;
+}
+
+char *kr_rrset_text(const knot_rrset_t *rr)
+{
+ if (!rr) {
+ return NULL;
+ }
+
+ /* Note: knot_rrset_txt_dump will double the size until the rrset fits */
+ size_t bufsize = 128;
+ char *buf = malloc(bufsize);
+ int ret = knot_rrset_txt_dump(rr, &buf, &bufsize, &KNOT_DUMP_STYLE_DEFAULT);
+ if (ret < 0) {
+ free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+uint64_t kr_now()
+{
+ return uv_now(uv_default_loop());
+}
+
+const char *kr_strptime_diff(const char *format, const char *time1_str,
+ const char *time0_str, double *diff) {
+ assert(format != NULL);
+ assert(time1_str != NULL);
+ assert(time0_str != NULL);
+ assert(diff != NULL);
+
+ struct tm time1_tm;
+ time_t time1_u;
+ struct tm time0_tm;
+ time_t time0_u;
+
+ char *err = strptime(time1_str, format, &time1_tm);
+ if (err == NULL || err != time1_str + strlen(time1_str))
+ return "strptime failed for time1";
+ time1_tm.tm_isdst = -1; /* determine if DST is active or not */
+ time1_u = mktime(&time1_tm);
+ if (time1_u == (time_t)-1)
+ return "mktime failed for time1";
+
+ err = strptime(time0_str, format, &time0_tm);
+ if (err == NULL || err != time0_str + strlen(time0_str))
+ return "strptime failed for time0";
+ time0_tm.tm_isdst = -1; /* determine if DST is active or not */
+ time0_u = mktime(&time0_tm);
+ if (time0_u == (time_t)-1)
+ return "mktime failed for time0";
+ *diff = difftime(time1_u, time0_u);
+
+ return NULL;
+}
+
+int knot_dname_lf2wire(knot_dname_t * const dst, uint8_t len, const uint8_t *lf)
+{
+ knot_dname_t *d = dst; /* moving "cursor" as we write it out */
+ bool ok = d && (len == 0 || lf);
+ if (!ok) {
+ assert(false);
+ return kr_error(EINVAL);
+ }
+ /* we allow the final zero byte to be omitted */
+ if (!len) {
+ goto finish;
+ }
+ if (lf[len - 1]) {
+ ++len;
+ }
+ /* convert the name, one label at a time */
+ int label_end = len - 1; /* index of the zero byte after the current label */
+ while (label_end >= 0) {
+ /* find label_start */
+ int i = label_end - 1;
+ while (i >= 0 && lf[i])
+ --i;
+ const int label_start = i + 1; /* index of the first byte of the current label */
+ const int label_len = label_end - label_start;
+ assert(label_len >= 0);
+ if (label_len > 63 || label_len <= 0)
+ return kr_error(EILSEQ);
+ /* write the label */
+ *d = label_len;
+ ++d;
+ memcpy(d, lf + label_start, label_len);
+ d += label_len;
+ /* next label */
+ label_end = label_start - 1;
+ }
+finish:
+ *d = 0; /* the final zero */
+ ++d;
+ return d - dst;
+}
+
+static void rnd_noerror(void *data, uint size)
+{
+ int ret = gnutls_rnd(GNUTLS_RND_NONCE, data, size);
+ if (ret) {
+ kr_log_error("gnutls_rnd(): %s\n", gnutls_strerror(ret));
+ abort();
+ }
+}
+void kr_rnd_buffered(void *data, uint size)
+{
+ /* static circular buffer, from index _begin (inclusive) to _end (exclusive) */
+ static uint8_t buf[512/8]; /* gnutls_rnd() works on blocks of 512 bits (chacha) */
+ static uint buf_begin = sizeof(buf);
+
+ if (unlikely(size > sizeof(buf))) {
+ rnd_noerror(data, size);
+ return;
+ }
+ /* Start with contiguous chunk, possibly until the end of buffer. */
+ const uint size1 = MIN(size, sizeof(buf) - buf_begin);
+ uint8_t *d = data;
+ memcpy(d, buf + buf_begin, size1);
+ if (size1 == size) {
+ buf_begin += size1;
+ return;
+ }
+ d += size1;
+ size -= size1;
+ /* Refill the whole buffer, and finish by another contiguous chunk. */
+ rnd_noerror(buf, sizeof(buf));
+ memcpy(d, buf, size);
+ buf_begin = size;
+}
+
+void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
+ uint16_t type, uint16_t rclass, uint32_t ttl)
+{
+ assert(rrset);
+ knot_rrset_init(rrset, owner, type, rclass, ttl);
+}
+uint16_t kr_pkt_qclass(const knot_pkt_t *pkt)
+{
+ return knot_pkt_qclass(pkt);
+}
+uint16_t kr_pkt_qtype(const knot_pkt_t *pkt)
+{
+ return knot_pkt_qtype(pkt);
+}
+uint32_t kr_rrsig_sig_inception(const knot_rdata_t *rdata)
+{
+ return knot_rrsig_sig_inception(rdata);
+}
+uint32_t kr_rrsig_sig_expiration(const knot_rdata_t *rdata)
+{
+ return knot_rrsig_sig_expiration(rdata);
+}
+uint16_t kr_rrsig_type_covered(const knot_rdata_t *rdata)
+{
+ return knot_rrsig_type_covered(rdata);
+}
+
diff --git a/lib/utils.h b/lib/utils.h
new file mode 100644
index 0000000..21eabac
--- /dev/null
+++ b/lib/utils.h
@@ -0,0 +1,495 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <lua.h>
+
+#include <libknot/libknot.h>
+#include <libknot/packet/pkt.h>
+#include <libknot/rrset.h>
+#include <libknot/rrtype/rrsig.h>
+
+#include "lib/generic/array.h"
+#include "lib/defines.h"
+
+struct kr_query;
+struct kr_request;
+
+/*
+ * Logging and debugging.
+ */
+
+/** @brief Callback for request events. */
+typedef void (*trace_callback_f)(struct kr_request *request);
+/** @brief Callback for request logging handler. */
+typedef void (*trace_log_f)(const struct kr_query *query, const char *source, const char *msg);
+
+#define kr_log_info(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0)
+#define kr_log_error(...) fprintf(stderr, ## __VA_ARGS__)
+
+/* Always export these, but override direct calls by macros conditionally. */
+/** Whether in --verbose mode. Only use this for reading. */
+KR_EXPORT extern bool kr_verbose_status;
+
+/** Set --verbose mode. Not available if compiled with -DNOVERBOSELOG. */
+KR_EXPORT bool kr_verbose_set(bool status);
+
+/** Log a message if in --verbose mode. */
+KR_EXPORT KR_PRINTF(1)
+void kr_log_verbose(const char *fmt, ...);
+
+/** Utility for QRVERBOSE - use that instead. */
+KR_EXPORT KR_PRINTF(3)
+void kr_log_qverbose_impl(const struct kr_query *qry, const char *cls, const char *fmt, ...);
+
+/**
+ * @brief Return true if the query has request log handler installed.
+ */
+#define kr_log_trace_enabled(query) (__builtin_expect( \
+ (query) && (query)->request && (query)->request->trace_log, \
+ false))
+
+/**
+ * Log a message through the request log handler.
+ * @param query current query
+ * @param source message source
+ * @param fmt message format
+ * @return true if the message was logged
+ */
+KR_EXPORT KR_PRINTF(3)
+bool kr_log_trace(const struct kr_query *query, const char *source, const char *fmt, ...);
+
+#ifdef NOVERBOSELOG
+/* Efficient compile-time disabling of verbose messages. */
+#define kr_verbose_status false
+#define kr_verbose_set(x)
+#endif
+
+/** Block run in --verbose mode; optimized when not run. */
+#define VERBOSE_STATUS __builtin_expect(kr_verbose_status, false)
+#define WITH_VERBOSE(query) if(__builtin_expect(kr_verbose_status || kr_log_trace_enabled(query), false))
+#define kr_log_verbose if(VERBOSE_STATUS) kr_log_verbose
+
+#define KR_DNAME_GET_STR(dname_str, dname) \
+ char dname_str[KR_DNAME_STR_MAXLEN]; \
+ knot_dname_to_str(dname_str, (dname), sizeof(dname_str)); \
+ dname_str[sizeof(dname_str) - 1] = 0;
+
+#define KR_RRTYPE_GET_STR(rrtype_str, rrtype) \
+ char rrtype_str[KR_RRTYPE_STR_MAXLEN]; \
+ knot_rrtype_to_string((rrtype), rrtype_str, sizeof(rrtype_str)); \
+ rrtype_str[sizeof(rrtype_str) - 1] = 0;
+
+/* C11 compatibility, but without any implementation so far. */
+#ifndef static_assert
+#define static_assert(cond, msg)
+#endif
+
+/** @cond Memory alloc routines */
+static inline void *mm_alloc(knot_mm_t *mm, size_t size)
+{
+ if (mm) return mm->alloc(mm->ctx, size);
+ else return malloc(size);
+}
+static inline void mm_free(knot_mm_t *mm, const void *what)
+{
+ if (mm) {
+ if (mm->free)
+ mm->free((void *)what);
+ }
+ else free((void *)what);
+}
+
+/** Realloc implementation using memory context. */
+KR_EXPORT
+void *mm_realloc(knot_mm_t *mm, void *what, size_t size, size_t prev_size);
+
+/** Trivial malloc() wrapper. */
+void *mm_malloc(void *ctx, size_t n);
+
+/** Initialize mm with standard malloc+free. */
+static inline void mm_ctx_init(knot_mm_t *mm)
+{
+ mm->ctx = NULL;
+ mm->alloc = mm_malloc;
+ mm->free = free;
+}
+/* @endcond */
+
+/** Return time difference in miliseconds.
+ * @note based on the _BSD_SOURCE timersub() macro */
+static inline long time_diff(struct timeval *begin, struct timeval *end) {
+ struct timeval res = {
+ .tv_sec = end->tv_sec - begin->tv_sec,
+ .tv_usec = end->tv_usec - begin->tv_usec
+ };
+ if (res.tv_usec < 0) {
+ --res.tv_sec;
+ res.tv_usec += 1000000;
+ }
+ return res.tv_sec * 1000 + res.tv_usec / 1000;
+}
+
+/** @cond internal Array types */
+struct kr_context;
+
+typedef array_t(knot_rrset_t *) rr_array_t;
+struct ranked_rr_array_entry {
+ uint32_t qry_uid;
+ uint8_t rank; /**< enum kr_rank */
+ uint8_t revalidation_cnt;
+ bool cached : 1; /**< Set to true if the entry was written into cache */
+ bool yielded : 1;
+ bool to_wire : 1; /**< whether to be put into the answer */
+ bool expiring : 1; /**< low remaining TTL; see is_expiring; only used in cache ATM */
+ knot_rrset_t *rr;
+};
+typedef struct ranked_rr_array_entry ranked_rr_array_entry_t;
+
+/** Array of RRsets coming from multiple queries; for struct kr_request.
+ *
+ * Notes:
+ * - RRSIGs are only considered to form an RRset when the types covered match;
+ * cache-related code relies on that!
+ * - RRsets from the same packet (qry_uid) get merged.
+ */
+typedef array_t(ranked_rr_array_entry_t *) ranked_rr_array_t;
+/* @endcond */
+
+/** Concatenate N strings. */
+KR_EXPORT
+char* kr_strcatdup(unsigned n, ...);
+
+/** You probably want kr_rand_* convenience functions instead.
+ * This is a buffered version of gnutls_rnd(GNUTLS_RND_NONCE, ..) */
+KR_EXPORT
+void kr_rnd_buffered(void *data, unsigned int size);
+
+/** Return a few random bytes. */
+static inline uint64_t kr_rand_bytes(unsigned int size)
+{
+ uint64_t result;
+ if (size <= 0 || size > sizeof(result)) {
+ kr_log_error("kr_rand_bytes(): EINVAL\n");
+ abort();
+ }
+ uint8_t data[sizeof(result)];
+ kr_rnd_buffered(data, size);
+ /* I would have liked to dump the random data into a size_t directly,
+ * but that would work well only on little-endian machines,
+ * so intsead I hope that the compiler will optimize this out.
+ * (Tested via reading assembly from usual gcc -O2 setup.)
+ * Alternatively we could waste more rnd bytes, but that seemed worse. */
+ result = 0;
+ for (unsigned int i = 0; i < size; ++ i) {
+ result |= ((size_t)data[i]) << (i * 8);
+ }
+ return result;
+}
+
+/** Throw a pseudo-random coin, succeeding approximately with probability nomin/denomin.
+ * - low precision, only one byte of randomness (or none with extreme parameters)
+ * - tip: use !kr_rand_coin() to get the complementary probability
+ */
+static inline bool kr_rand_coin(unsigned int nomin, unsigned int denomin)
+{
+ /* This function might be called with non-constant values
+ * so we try to handle odd corner cases instead of crash. */
+ if (nomin >= denomin)
+ return true;
+ else if (nomin <= 0)
+ return false;
+
+ /* threshold = how many parts from 256 are a success */
+ unsigned int threshold = (nomin * 256 + /*rounding*/ denomin / 2) / denomin;
+ if (threshold == 0) threshold = 1;
+ if (threshold == 256) threshold = 255;
+ return (kr_rand_bytes(1) < threshold);
+}
+
+/** Memory reservation routine for knot_mm_t */
+KR_EXPORT
+int kr_memreserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have);
+
+/** @internal Fast packet reset. */
+KR_EXPORT
+int kr_pkt_recycle(knot_pkt_t *pkt);
+
+/** @internal Clear packet payload. */
+KR_EXPORT
+int kr_pkt_clear_payload(knot_pkt_t *pkt);
+
+/** Construct and put record to packet. */
+KR_EXPORT
+int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl,
+ uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen);
+
+/** Set packet header suitable for authoritative answer. (for policy module) */
+KR_EXPORT
+void kr_pkt_make_auth_header(knot_pkt_t *pkt);
+
+/** Simple storage for IPx address or AF_UNSPEC. */
+union inaddr {
+ struct sockaddr ip;
+ struct sockaddr_in ip4;
+ struct sockaddr_in6 ip6;
+};
+
+/** Address bytes for given family. */
+KR_EXPORT KR_PURE
+const char *kr_inaddr(const struct sockaddr *addr);
+/** Address family. */
+KR_EXPORT KR_PURE
+int kr_inaddr_family(const struct sockaddr *addr);
+/** Address length for given family, i.e. sizeof(struct in*_addr). */
+KR_EXPORT KR_PURE
+int kr_inaddr_len(const struct sockaddr *addr);
+/** Sockaddr length for given family, i.e. sizeof(struct sockaddr_in*). */
+KR_EXPORT KR_PURE
+int kr_sockaddr_len(const struct sockaddr *addr);
+/** Compare two given sockaddr.
+ * return 0 - addresses are equal, error code otherwise.
+ */
+KR_EXPORT KR_PURE
+int kr_sockaddr_cmp(const struct sockaddr *left, const struct sockaddr *right);
+/** Port. */
+KR_EXPORT KR_PURE
+uint16_t kr_inaddr_port(const struct sockaddr *addr);
+/** Set port. */
+KR_EXPORT
+void kr_inaddr_set_port(struct sockaddr *addr, uint16_t port);
+
+/** Write string representation for given address as "<addr>#<port>".
+ * \param[in] addr the raw address
+ * \param[out] buf the buffer for output string
+ * \param[in,out] buflen the available(in) and utilized(out) length, including \0 */
+KR_EXPORT
+int kr_inaddr_str(const struct sockaddr *addr, char *buf, size_t *buflen);
+
+/** Return address type for string. */
+KR_EXPORT KR_PURE
+int kr_straddr_family(const char *addr);
+/** Return address length in given family (struct in*_addr). */
+KR_EXPORT KR_CONST
+int kr_family_len(int family);
+/** Create a sockaddr* from string+port representation (also accepts IPv6 link-local). */
+KR_EXPORT
+struct sockaddr * kr_straddr_socket(const char *addr, int port);
+/** Parse address and return subnet length (bits).
+ * @warning 'dst' must be at least `sizeof(struct in6_addr)` long. */
+KR_EXPORT
+int kr_straddr_subnet(void *dst, const char *addr);
+
+/** Splits ip address specified as "addr@port" or "addr#port" into addr and port
+ * and performs validation.
+ * @note if #port part isn't present, then port will be set to 0.
+ * buf and\or port can be set to NULL.
+ * @return kr_error(EINVAL) - addr part doesn't contains valid ip address or
+ * #port part is out-of-range (either < 0 either > UINT16_MAX)
+ * kr_error(ENOSP) - buflen is too small
+ */
+KR_EXPORT
+int kr_straddr_split(const char *addr, char *buf, size_t buflen, uint16_t *port);
+/** Formats ip address and port in "addr#port" format.
+ * and performs validation.
+ * @note Port always formatted as five-character string with leading zeros.
+ * @return kr_error(EINVAL) - addr or buf is NULL or buflen is 0 or
+ * addr doesn't contain a valid ip address
+ * kr_error(ENOSP) - buflen is too small
+ */
+KR_EXPORT
+int kr_straddr_join(const char *addr, uint16_t port, char *buf, size_t *buflen);
+
+/** Compare memory bitwise. The semantics is "the same" as for memcmp().
+ * The partial byte is considered with more-significant bits first,
+ * so this is e.g. suitable for comparing IP prefixes. */
+KR_EXPORT KR_PURE
+int kr_bitcmp(const char *a, const char *b, int bits);
+
+/** @internal RR map flags. */
+static const uint8_t KEY_FLAG_RRSIG = 0x02;
+static inline uint8_t KEY_FLAG_RANK(const char *key)
+ { return ((uint8_t)(key[0])) >> 2; }
+static inline bool KEY_COVERING_RRSIG(const char *key)
+ { return ((uint8_t)(key[0])) & KEY_FLAG_RRSIG; }
+
+/* Stash key = {[5] class, [1-255] owner, [5] type, [5] additional, [1] \x00 } */
+#define KR_RRKEY_LEN (16 + KNOT_DNAME_MAXLEN)
+/** Create unique null-terminated string key for RR.
+ * @param key Destination buffer for key size, MUST be KR_RRKEY_LEN or larger.
+ * @param class RR class.
+ * @param owner RR owner name.
+ * @param type RR type.
+ * @param additional flags (for instance can be used for storing covered type
+ * when RR type is RRSIG).
+ * @return key length if successful or an error
+ * */
+KR_EXPORT
+int kr_rrkey(char *key, uint16_t class, const knot_dname_t *owner,
+ uint16_t type, uint16_t additional);
+
+/** @internal Add RRSet copy to ranked RR array. */
+KR_EXPORT
+int kr_ranked_rrarray_add(ranked_rr_array_t *array, const knot_rrset_t *rr,
+ uint8_t rank, bool to_wire, uint32_t qry_uid, knot_mm_t *pool);
+
+/** @internal Mark the RRSets from particular query as
+ * "have (not) to be recorded in the final answer".
+ * @param array RRSet array.
+ * @param to_wire Records must be\must not be recorded in final answer.
+ * @param qry_uid Query uid.
+ * @param check_dups When to_wire is true, try to avoid duplicate RRSets.
+ * @param extraCheck optional function checking whether to consider the record
+ * @return 0 or an error
+ */
+int kr_ranked_rrarray_set_wire(ranked_rr_array_t *array, bool to_wire,
+ uint32_t qry_uid, bool check_dups,
+ bool (*extraCheck)(const ranked_rr_array_entry_t *));
+
+KR_PURE
+char *kr_pkt_text(const knot_pkt_t *pkt);
+
+KR_PURE
+char *kr_rrset_text(const knot_rrset_t *rr);
+
+KR_PURE
+static inline char *kr_dname_text(const knot_dname_t *name) {
+ return knot_dname_to_str_alloc(name);
+}
+
+KR_CONST
+static inline char *kr_rrtype_text(const uint16_t rrtype) {
+ char type_str[32] = {0};
+ knot_rrtype_to_string(rrtype, type_str, sizeof(type_str));
+ return strdup(type_str);
+}
+
+/**
+ * Call module property.
+ */
+KR_EXPORT
+char *kr_module_call(struct kr_context *ctx, const char *module, const char *prop, const char *input);
+
+/** Swap two places. Note: the parameters need to be without side effects. */
+#define SWAP(x, y) do { /* http://stackoverflow.com/a/3982430/587396 */ \
+ unsigned char swap_temp[sizeof(x) == sizeof(y) ? (ssize_t)sizeof(x) : -1]; \
+ memcpy(swap_temp, &y, sizeof(x)); \
+ memcpy(&y, &x, sizeof(x)); \
+ memcpy(&x, swap_temp, sizeof(x)); \
+ } while(0)
+
+/** Return the (covered) type of an nonempty RRset. */
+static inline uint16_t kr_rrset_type_maysig(const knot_rrset_t *rr)
+{
+ assert(rr && rr->rrs.count && rr->rrs.rdata);
+ uint16_t type = rr->type;
+ if (type == KNOT_RRTYPE_RRSIG)
+ type = knot_rrsig_type_covered(rr->rrs.rdata);
+ return type;
+}
+
+/** Printf onto the lua stack, avoiding additional copy (thin wrapper). */
+KR_PRINTF(2)
+static inline const char *lua_push_printf(lua_State *L, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ const char *ret = lua_pushvfstring(L, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+/** @internal Return string representation of addr.
+ * @note return pointer to static string
+ */
+static inline char *kr_straddr(const struct sockaddr *addr)
+{
+ assert(addr != NULL);
+ /* We are the sinle-threaded application */
+ static char str[INET6_ADDRSTRLEN + 1 + 5 + 1];
+ size_t len = sizeof(str);
+ int ret = kr_inaddr_str(addr, str, &len);
+ return ret != kr_ok() || len == 0 ? NULL : str;
+}
+
+/** The current time in monotonic milliseconds.
+ *
+ * \note it may be outdated in case of long callbacks; see uv_now().
+ */
+KR_EXPORT
+uint64_t kr_now();
+
+/** Convert name from lookup format to wire. See knot_dname_lf
+ *
+ * \note len bytes are read and len+1 are written with *normal* LF,
+ * but it's also allowed that the final zero byte is omitted in LF.
+ * \return the number of bytes written (>0) or error code (<0)
+ */
+int knot_dname_lf2wire(knot_dname_t *dst, uint8_t len, const uint8_t *lf);
+
+/** Patched knot_dname_lf. LF for "." has length zero instead of one, for consistency.
+ * (TODO: consistency?)
+ * \param add_wildcard append the wildcard label
+ * \note packet is always NULL
+ */
+static inline int kr_dname_lf(uint8_t *dst, const knot_dname_t *src, bool add_wildcard)
+{
+ knot_dname_storage_t right_aligned_dst;
+ uint8_t *right_aligned_dname_start = knot_dname_lf(src, right_aligned_dst);
+ if (!right_aligned_dname_start) {
+ return kr_error(EINVAL);
+ }
+ int len = right_aligned_dname_start[0];
+ assert(right_aligned_dname_start + 1 + len - KNOT_DNAME_MAXLEN == right_aligned_dst);
+ memcpy(dst + 1, right_aligned_dname_start + 1, len);
+ if (add_wildcard) {
+ if (len + 2 > KNOT_DNAME_MAXLEN)
+ return kr_error(ENOSPC);
+ dst[len + 1] = '*';
+ dst[len + 2] = '\0';
+ len += 2;
+ }
+ dst[0] = len;
+ return KNOT_EOK;
+}
+
+/**
+ * Difference between two calendar times specified as strings.
+ * \param format[in] format for strptime
+ * \param diff[out] result from C difftime(time1, time0)
+ */
+KR_EXPORT
+const char *kr_strptime_diff(const char *format, const char *time1_str,
+ const char *time0_str, double *diff);
+
+/* Trivial non-inline wrappers, to be used in lua. */
+KR_EXPORT void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
+ uint16_t type, uint16_t rclass, uint32_t ttl);
+KR_EXPORT uint16_t kr_pkt_qclass(const knot_pkt_t *pkt);
+KR_EXPORT uint16_t kr_pkt_qtype(const knot_pkt_t *pkt);
+KR_EXPORT uint32_t kr_rrsig_sig_inception(const knot_rdata_t *rdata);
+KR_EXPORT uint32_t kr_rrsig_sig_expiration(const knot_rdata_t *rdata);
+KR_EXPORT uint16_t kr_rrsig_type_covered(const knot_rdata_t *rdata);
diff --git a/lib/zonecut.c b/lib/zonecut.c
new file mode 100644
index 0000000..5e54d97
--- /dev/null
+++ b/lib/zonecut.c
@@ -0,0 +1,597 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/zonecut.h"
+
+#include "contrib/cleanup.h"
+#include "lib/defines.h"
+#include "lib/generic/pack.h"
+#include "lib/layer.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+
+#include <libknot/descriptor.h>
+#include <libknot/packet/wire.h>
+#include <libknot/rrtype/rdname.h>
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "zcut", __VA_ARGS__)
+
+/** Information for one NS name + address type. */
+typedef enum {
+ AI_UNINITED = 0,
+ AI_REPUT, /**< Don't use this addrset, due to: cache_rep, NO_IPV6, ...
+ * cache_rep approximates various problems when fetching the RRset. */
+ AI_CYCLED, /**< Skipped due to cycle detection; see implementation for details. */
+ AI_LAST_BAD = AI_CYCLED, /** bad states: <= AI_LAST_BAD */
+ AI_UNKNOWN, /**< Don't know status of this RRset; various reasons. */
+ AI_EMPTY, /**< No usable address (may mean e.g. just NODATA). */
+ AI_OK, /**< At least one usable address.
+ * LATER: we might be interested whether it's only glue. */
+} addrset_info_t;
+
+
+static void update_cut_name(struct kr_zonecut *cut, const knot_dname_t *name)
+{
+ if (knot_dname_is_equal(name, cut->name)) {
+ return;
+ }
+ knot_dname_t *next_name = knot_dname_copy(name, cut->pool);
+ mm_free(cut->pool, cut->name);
+ cut->name = next_name;
+}
+
+int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t *pool)
+{
+ if (!cut || !name) {
+ return kr_error(EINVAL);
+ }
+
+ memset(cut, 0, sizeof(*cut));
+ cut->name = knot_dname_copy(name, pool);
+ cut->pool = pool;
+ cut->nsset = trie_create(pool);
+ return cut->name && cut->nsset ? kr_ok() : kr_error(ENOMEM);
+}
+
+/** Completely free a pack_t. */
+static inline void free_addr_set(pack_t *pack, knot_mm_t *pool)
+{
+ if (unlikely(!pack)) {
+ /* promised we don't store NULL packs */
+ assert(false);
+ return;
+ }
+ pack_clear_mm(*pack, mm_free, pool);
+ mm_free(pool, pack);
+}
+/** Trivial wrapper for use in trie_apply, due to ugly casting. */
+static int free_addr_set_cb(trie_val_t *v, void *pool)
+{
+ free_addr_set(*v, pool);
+ return kr_ok();
+}
+
+void kr_zonecut_deinit(struct kr_zonecut *cut)
+{
+ if (!cut) {
+ return;
+ }
+ mm_free(cut->pool, cut->name);
+ if (cut->nsset) {
+ trie_apply(cut->nsset, free_addr_set_cb, cut->pool);
+ trie_free(cut->nsset);
+ }
+ knot_rrset_free(cut->key, cut->pool);
+ knot_rrset_free(cut->trust_anchor, cut->pool);
+}
+
+void kr_zonecut_move(struct kr_zonecut *to, const struct kr_zonecut *from)
+{
+ if (!to || !from) abort();
+ kr_zonecut_deinit(to);
+ memcpy(to, from, sizeof(*to));
+}
+
+void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name)
+{
+ if (!cut || !name) {
+ return;
+ }
+ knot_rrset_t *key, *ta;
+ key = cut->key; cut->key = NULL;
+ ta = cut->trust_anchor; cut->trust_anchor = NULL;
+ kr_zonecut_deinit(cut);
+ kr_zonecut_init(cut, name, cut->pool);
+ cut->key = key;
+ cut->trust_anchor = ta;
+}
+
+int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src)
+{
+ if (!dst || !src) {
+ return kr_error(EINVAL);
+ }
+ if (!dst->nsset) {
+ dst->nsset = trie_create(dst->pool);
+ }
+ /* Copy the contents, one by one. */
+ int ret = kr_ok();
+ trie_it_t *it;
+ for (it = trie_it_begin(src->nsset); !trie_it_finished(it); trie_it_next(it)) {
+ size_t klen;
+ const char * const k = trie_it_key(it, &klen);
+ pack_t **new_pack = (pack_t **)trie_get_ins(dst->nsset, k, klen);
+ if (!new_pack) {
+ ret = kr_error(ENOMEM);
+ break;
+ }
+ const pack_t *old_pack = *trie_it_val(it);
+ ret = pack_clone(new_pack, old_pack, dst->pool);
+ if (ret) break;
+ }
+ trie_it_free(it);
+ return ret;
+}
+
+int kr_zonecut_copy_trust(struct kr_zonecut *dst, const struct kr_zonecut *src)
+{
+ knot_rrset_t *key_copy = NULL;
+ knot_rrset_t *ta_copy = NULL;
+
+ if (src->key) {
+ key_copy = knot_rrset_copy(src->key, dst->pool);
+ if (!key_copy) {
+ return kr_error(ENOMEM);
+ }
+ }
+
+ if (src->trust_anchor) {
+ ta_copy = knot_rrset_copy(src->trust_anchor, dst->pool);
+ if (!ta_copy) {
+ knot_rrset_free(key_copy, dst->pool);
+ return kr_error(ENOMEM);
+ }
+ }
+
+ knot_rrset_free(dst->key, dst->pool);
+ dst->key = key_copy;
+ knot_rrset_free(dst->trust_anchor, dst->pool);
+ dst->trust_anchor = ta_copy;
+
+ return kr_ok();
+}
+
+int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const void *data, int len)
+{
+ if (!cut || !ns || !cut->nsset || (data && len <= 0)) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ /* Disabled; add_reverse_pair() misuses this for domain name in rdata. */
+ if (false && data && len != sizeof(struct in_addr)
+ && len != sizeof(struct in6_addr)) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+
+ /* Get a pack_t for the ns. */
+ pack_t **pack = (pack_t **)trie_get_ins(cut->nsset, (const char *)ns, knot_dname_size(ns));
+ if (!pack) return kr_error(ENOMEM);
+ if (*pack == NULL) {
+ *pack = mm_alloc(cut->pool, sizeof(pack_t));
+ if (*pack == NULL) return kr_error(ENOMEM);
+ pack_init(**pack);
+ }
+ /* Insert data (if has any) */
+ if (data == NULL) {
+ return kr_ok();
+ }
+ /* Check for duplicates */
+ if (pack_obj_find(*pack, data, len)) {
+ return kr_ok();
+ }
+ /* Push new address */
+ int ret = pack_reserve_mm(**pack, 1, len, kr_memreserve, cut->pool);
+ if (ret != 0) {
+ return kr_error(ENOMEM);
+ }
+ return pack_obj_push(*pack, data, len);
+}
+
+int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const void *data, int len)
+{
+ if (!cut || !ns || (data && len <= 0)) {
+ return kr_error(EINVAL);
+ }
+
+ /* Find the address list. */
+ int ret = kr_ok();
+ pack_t *pack = kr_zonecut_find(cut, ns);
+ if (pack == NULL) {
+ return kr_error(ENOENT);
+ }
+ /* Remove address from the pack. */
+ if (data) {
+ ret = pack_obj_del(pack, data, len);
+ }
+ /* No servers left, remove NS from the set. */
+ if (pack->len == 0) {
+ free_addr_set(pack, cut->pool);
+ ret = trie_del(cut->nsset, (const char *)ns, knot_dname_size(ns), NULL);
+ assert(ret == 0); /* only KNOT_ENOENT and that *can't* happen */
+ return (ret == 0) ? kr_ok() : kr_error(ret);
+ }
+
+ return ret;
+}
+
+int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns)
+{
+ if (!cut || !ns) {
+ return kr_error(EINVAL);
+ }
+
+ /* Find the address list; then free and remove it. */
+ pack_t *pack;
+ int ret = trie_del(cut->nsset, (const char *)ns, knot_dname_size(ns),
+ (trie_val_t *)&pack);
+ if (ret) { /* deletion failed */
+ assert(ret == KNOT_ENOENT);
+ return kr_error(ENOENT);
+ }
+ free_addr_set(pack, cut->pool);
+ return kr_ok();
+}
+
+pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
+{
+ if (!cut || !ns) {
+ return NULL;
+ }
+ trie_val_t *val = trie_get_try(cut->nsset, (const char *)ns, knot_dname_size(ns));
+ /* we get pointer to the pack_t pointer */
+ return val ? (pack_t *)*val : NULL;
+}
+
+static int has_address(trie_val_t *v, void *baton_)
+{
+ const pack_t *pack = *v;
+ const bool found = pack != NULL && pack->len != 0;
+ return found;
+}
+
+bool kr_zonecut_is_empty(struct kr_zonecut *cut)
+{
+ if (!cut || !cut->nsset) {
+ assert(false);
+ return true;
+ }
+ return !trie_apply(cut->nsset, has_address, NULL);
+}
+
+int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut)
+{
+ if (!ctx || !cut || !ctx->root_hints.nsset) {
+ return kr_error(EINVAL);
+ }
+
+ trie_apply(cut->nsset, free_addr_set_cb, cut->pool);
+ trie_clear(cut->nsset);
+
+ const uint8_t *const dname_root = (const uint8_t *)/*sign-cast*/("");
+ update_cut_name(cut, dname_root);
+ /* Copy root hints from resolution context. */
+ return kr_zonecut_copy(cut, &ctx->root_hints);
+}
+
+/** Fetch address for zone cut. Any rank is accepted (i.e. glue as well). */
+static addrset_info_t fetch_addr(pack_t *addrs, const knot_dname_t *ns, uint16_t rrtype,
+ knot_mm_t *mm_pool, const struct kr_query *qry)
+// LATER(optim.): excessive data copying
+{
+ int rdlen;
+ switch (rrtype) {
+ case KNOT_RRTYPE_A:
+ rdlen = 4;
+ break;
+ case KNOT_RRTYPE_AAAA:
+ rdlen = 16;
+ break;
+ default:
+ assert(!EINVAL);
+ return AI_UNKNOWN;
+ }
+
+ struct kr_context *ctx = qry->request->ctx;
+ struct kr_cache_p peek;
+ if (kr_cache_peek_exact(&ctx->cache, ns, rrtype, &peek) != 0) {
+ return AI_UNKNOWN;
+ }
+ int32_t new_ttl = kr_cache_ttl(&peek, qry, ns, rrtype);
+ if (new_ttl < 0) {
+ return AI_UNKNOWN;
+ }
+
+ knot_rrset_t cached_rr;
+ knot_rrset_init(&cached_rr, /*const-cast*/(knot_dname_t *)ns, rrtype,
+ KNOT_CLASS_IN, new_ttl);
+ if (kr_cache_materialize(&cached_rr.rrs, &peek, mm_pool) < 0) {
+ return AI_UNKNOWN;
+ }
+
+ /* Reserve memory in *addrs. Implementation detail:
+ * pack_t cares for lengths, so we don't store those in the data. */
+ const size_t pack_extra_size = knot_rdataset_size(&cached_rr.rrs)
+ - cached_rr.rrs.count * offsetof(knot_rdata_t, len);
+ int ret = pack_reserve_mm(*addrs, cached_rr.rrs.count, pack_extra_size,
+ kr_memreserve, mm_pool);
+ if (ret) abort(); /* ENOMEM "probably" */
+
+ int usable_cnt = 0;
+ addrset_info_t result = AI_EMPTY;
+ knot_rdata_t *rd = cached_rr.rrs.rdata;
+ for (uint16_t i = 0; i < cached_rr.rrs.count; ++i, rd = knot_rdataset_next(rd)) {
+ if (unlikely(rd->len != rdlen)) {
+ VERBOSE_MSG(qry, "bad NS address length %d for rrtype %d, skipping\n",
+ (int)rd->len, (int)rrtype);
+ continue;
+ }
+ /* Check RTT cache - whether the IP is usable or not. */
+ kr_nsrep_rtt_lru_entry_t *rtt_e = ctx->cache_rtt
+ ? lru_get_try(ctx->cache_rtt, (const char *)rd->data, rd->len)
+ : NULL;
+ const bool unusable = rtt_e && rtt_e->score >= KR_NS_TIMEOUT
+ && qry->creation_time_mono
+ < rtt_e->tout_timestamp + ctx->cache_rtt_tout_retry_interval;
+ if (!unusable) {
+ result = AI_OK;
+ ++usable_cnt;
+ }
+
+ ret = pack_obj_push(addrs, rd->data, rd->len);
+ assert(!ret); /* didn't fit because of incorrectly reserved memory */
+ /* LATER: for now we lose quite some information here,
+ * as keeping it would need substantial changes on other places,
+ * and it turned out to be premature optimization (most likely).
+ * We might e.g. skip adding unusable addresses,
+ * and either keep some rtt information associated
+ * or even finish up choosing the set to send packets to.
+ * Overall there's some overlap with nsrep.c functionality.
+ */
+ }
+ if (usable_cnt != cached_rr.rrs.count) {
+ VERBOSE_MSG(qry, "usable NS addresses: %d/%d\n",
+ usable_cnt, cached_rr.rrs.count);
+ }
+ return result;
+}
+
+/** Fetch best NS for zone cut. */
+static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut,
+ const knot_dname_t *name, const struct kr_query *qry,
+ uint8_t * restrict rank)
+{
+ struct kr_cache_p peek;
+ int ret = kr_cache_peek_exact(&ctx->cache, name, KNOT_RRTYPE_NS, &peek);
+ if (ret != 0) {
+ return ret;
+ }
+ /* Note: we accept *any* rank from the cache. We assume that nothing
+ * completely untrustworthy could get into the cache, e.g out-of-bailiwick
+ * records that weren't validated.
+ */
+ *rank = peek.rank;
+
+ int32_t new_ttl = kr_cache_ttl(&peek, qry, name, KNOT_RRTYPE_NS);
+ if (new_ttl < 0) {
+ return kr_error(ESTALE);
+ }
+ /* Materialize the rdataset temporarily, for simplicity. */
+ knot_rdataset_t ns_rds = { 0, NULL };
+ ret = kr_cache_materialize(&ns_rds, &peek, cut->pool);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Insert name servers for this zone cut, addresses will be looked up
+ * on-demand (either from cache or iteratively) */
+ bool all_bad = true; /**< All NSs (seen so far) are in a bad state. */
+ knot_rdata_t *rdata_i = ns_rds.rdata;
+ for (unsigned i = 0; i < ns_rds.count;
+ ++i, rdata_i = knot_rdataset_next(rdata_i)) {
+ const knot_dname_t *ns_name = knot_ns_name(rdata_i);
+ const size_t ns_size = knot_dname_size(ns_name);
+
+ /* Get a new pack within the nsset. */
+ pack_t **pack = (pack_t **)trie_get_ins(cut->nsset,
+ (const char *)ns_name, ns_size);
+ if (!pack) return kr_error(ENOMEM);
+ assert(!*pack); /* not critical, really */
+ *pack = mm_alloc(cut->pool, sizeof(pack_t));
+ if (!*pack) return kr_error(ENOMEM);
+ pack_init(**pack);
+
+ addrset_info_t infos[2];
+ /* Fetch NS reputation and decide whether to prefetch A/AAAA records. */
+ unsigned *cached = lru_get_try(ctx->cache_rep,
+ (const char *)ns_name, ns_size);
+ unsigned reputation = (cached) ? *cached : 0;
+ infos[0] = (reputation & KR_NS_NOIP4) || qry->flags.NO_IPV4
+ ? AI_REPUT
+ : fetch_addr(*pack, ns_name, KNOT_RRTYPE_A, cut->pool, qry);
+ infos[1] = (reputation & KR_NS_NOIP6) || qry->flags.NO_IPV6
+ ? AI_REPUT
+ : fetch_addr(*pack, ns_name, KNOT_RRTYPE_AAAA, cut->pool, qry);
+
+ #if 0 /* rather unlikely to be useful unless changing some zcut code */
+ WITH_VERBOSE(qry) {
+ auto_free char *ns_name_txt = kr_dname_text(ns_name);
+ VERBOSE_MSG(qry, "NS %s infos: %d, %d\n",
+ ns_name_txt, (int)infos[0], (int)infos[1]);
+ }
+ #endif
+
+ /* AI_CYCLED checks.
+ * If an ancestor query has its zone cut in the state that
+ * it's looking for name or address(es) of some NS(s),
+ * we want to avoid doing so with a NS that lies under its cut.
+ * Instead we need to consider such names unusable in the cut (for now). */
+ if (infos[0] != AI_UNKNOWN && infos[1] != AI_UNKNOWN) {
+ /* Optimization: the following loop would be pointless. */
+ all_bad = false;
+ continue;
+ }
+ for (const struct kr_query *aq = qry; aq->parent; aq = aq->parent) {
+ const struct kr_qflags *aqpf = &aq->parent->flags;
+ if ( (aqpf->AWAIT_CUT && aq->stype == KNOT_RRTYPE_NS)
+ || (aqpf->AWAIT_IPV4 && aq->stype == KNOT_RRTYPE_A)
+ || (aqpf->AWAIT_IPV6 && aq->stype == KNOT_RRTYPE_AAAA)) {
+ if (knot_dname_in_bailiwick(ns_name,
+ aq->parent->zone_cut.name)) {
+ for (int j = 0; j < 2; ++j)
+ if (infos[j] == AI_UNKNOWN)
+ infos[j] = AI_CYCLED;
+ break;
+ }
+ } else {
+ /* This ancestor waits for other reason that
+ * NS name or address, so we're out of a direct cycle. */
+ break;
+ }
+ }
+ all_bad = all_bad && infos[0] <= AI_LAST_BAD && infos[1] <= AI_LAST_BAD;
+ }
+
+ if (all_bad) { WITH_VERBOSE(qry) {
+ auto_free char *name_txt = kr_dname_text(name);
+ VERBOSE_MSG(qry, "cut %s: all NSs bad, count = %d\n",
+ name_txt, (int)ns_rds.count);
+ } }
+ knot_rdataset_clear(&ns_rds, cut->pool);
+ return all_bad ? ELOOP : kr_ok();
+}
+
+/**
+ * Fetch secure RRSet of given type.
+ */
+static int fetch_secure_rrset(knot_rrset_t **rr, struct kr_cache *cache,
+ const knot_dname_t *owner, uint16_t type, knot_mm_t *pool,
+ const struct kr_query *qry)
+{
+ if (!rr) {
+ assert(!EINVAL);
+ return kr_error(EINVAL);
+ }
+ /* peek, check rank and TTL */
+ struct kr_cache_p peek;
+ int ret = kr_cache_peek_exact(cache, owner, type, &peek);
+ if (ret != 0) {
+ return ret;
+ }
+ if (!kr_rank_test(peek.rank, KR_RANK_SECURE)) {
+ return kr_error(ENOENT);
+ }
+ int32_t new_ttl = kr_cache_ttl(&peek, qry, owner, type);
+ if (new_ttl < 0) {
+ return kr_error(ESTALE);
+ }
+ /* materialize a new RRset */
+ knot_rrset_free(*rr, pool);
+ *rr = mm_alloc(pool, sizeof(knot_rrset_t));
+ if (*rr == NULL) {
+ return kr_error(ENOMEM);
+ }
+ owner = knot_dname_copy(/*const-cast*/(knot_dname_t *)owner, pool);
+ if (!owner) {
+ mm_free(pool, *rr);
+ *rr = NULL;
+ return kr_error(ENOMEM);
+ }
+ knot_rrset_init(*rr, /*const-cast*/(knot_dname_t *)owner, type,
+ KNOT_CLASS_IN, new_ttl);
+ ret = kr_cache_materialize(&(*rr)->rrs, &peek, pool);
+ if (ret < 0) {
+ knot_rrset_free(*rr, pool);
+ *rr = NULL;
+ return ret;
+ }
+
+ return kr_ok();
+}
+
+int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut,
+ const knot_dname_t *name, const struct kr_query *qry,
+ bool * restrict secured)
+{
+ if (!ctx || !cut || !name) {
+ //assert(false);
+ return kr_error(EINVAL);
+ }
+ /* I'm not sure whether the caller always passes a clean state;
+ * mixing doesn't seem to make sense in any case, so let's clear it.
+ * We don't bother freeing the packs, as they're on mempool. */
+ trie_clear(cut->nsset);
+ /* Copy name as it may overlap with cut name that is to be replaced. */
+ knot_dname_t *qname = knot_dname_copy(name, cut->pool);
+ if (!qname) {
+ return kr_error(ENOMEM);
+ }
+ /* Start at QNAME. */
+ int ret;
+ const knot_dname_t *label = qname;
+ while (true) {
+ /* Fetch NS first and see if it's insecure. */
+ uint8_t rank = 0;
+ const bool is_root = (label[0] == '\0');
+ ret = fetch_ns(ctx, cut, label, qry, &rank);
+ if (ret == 0) {
+ /* Flag as insecure if cached as this */
+ if (kr_rank_test(rank, KR_RANK_INSECURE)) {
+ *secured = false;
+ }
+ /* Fetch DS and DNSKEY if caller wants secure zone cut */
+ int ret_ds = 1, ret_dnskey = 1;
+ if (*secured || is_root) {
+ ret_ds = fetch_secure_rrset(&cut->trust_anchor, &ctx->cache,
+ label, KNOT_RRTYPE_DS, cut->pool, qry);
+ ret_dnskey = fetch_secure_rrset(&cut->key, &ctx->cache,
+ label, KNOT_RRTYPE_DNSKEY, cut->pool, qry);
+ }
+ update_cut_name(cut, label);
+ WITH_VERBOSE(qry) {
+ auto_free char *label_str = kr_dname_text(label);
+ VERBOSE_MSG(qry,
+ "found cut: %s (rank 0%.2o return codes: DS %d, DNSKEY %d)\n",
+ label_str, rank, ret_ds, ret_dnskey);
+ }
+ ret = kr_ok();
+ break;
+ } /* else */
+
+ trie_clear(cut->nsset);
+ /* Subtract label from QNAME. */
+ if (!is_root) {
+ label = knot_wire_next_label(label, NULL);
+ } else {
+ ret = kr_error(ENOENT);
+ break;
+ }
+ }
+
+ kr_cache_sync(&ctx->cache);
+ mm_free(cut->pool, qname);
+ return ret;
+}
diff --git a/lib/zonecut.h b/lib/zonecut.h
new file mode 100644
index 0000000..2808c66
--- /dev/null
+++ b/lib/zonecut.h
@@ -0,0 +1,173 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/cache/api.h"
+#include "lib/defines.h"
+#include "lib/generic/pack.h"
+#include "lib/generic/trie.h"
+
+struct kr_rplan;
+struct kr_context;
+
+/**
+ * Current zone cut representation.
+*/
+struct kr_zonecut {
+ knot_dname_t *name; /**< Zone cut name. */
+ knot_rrset_t* key; /**< Zone cut DNSKEY. */
+ knot_rrset_t* trust_anchor; /**< Current trust anchor. */
+ struct kr_zonecut *parent; /**< Parent zone cut. */
+ trie_t *nsset; /**< Map of nameserver => address_set (pack_t). */
+ knot_mm_t *pool; /**< Memory pool. */
+};
+
+/**
+ * Populate root zone cut with SBELT.
+ * @param cut zone cut
+ * @param name
+ * @param pool
+ * @return 0 or error code
+ */
+KR_EXPORT
+int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t *pool);
+
+/**
+ * Clear the structure and free the address set.
+ * @param cut zone cut
+ */
+KR_EXPORT
+void kr_zonecut_deinit(struct kr_zonecut *cut);
+
+/**
+ * Move a zonecut, transferring ownership of any pointed-to memory.
+ * @param to the target - it gets deinit-ed
+ * @param from the source - not modified, but shouldn't be used afterward
+ */
+KR_EXPORT
+void kr_zonecut_move(struct kr_zonecut *to, const struct kr_zonecut *from);
+
+/**
+ * Reset zone cut to given name and clear address list.
+ * @note This clears the address list even if the name doesn't change. TA and DNSKEY don't change.
+ * @param cut zone cut to be set
+ * @param name new zone cut name
+ */
+KR_EXPORT
+void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name);
+
+/**
+ * Copy zone cut, including all data. Does not copy keys and trust anchor.
+ * @param dst destination zone cut
+ * @param src source zone cut
+ * @return 0 or an error code; If it fails with kr_error(ENOMEM),
+ * it may be in a half-filled state, but it's safe to deinit...
+ * @note addresses for names in `src` get replaced and others are left as they were.
+ */
+KR_EXPORT
+int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src);
+
+/**
+ * Copy zone trust anchor and keys.
+ * @param dst destination zone cut
+ * @param src source zone cut
+ * @return 0 or an error code
+ */
+KR_EXPORT
+int kr_zonecut_copy_trust(struct kr_zonecut *dst, const struct kr_zonecut *src);
+
+/**
+ * Add address record to the zone cut.
+ *
+ * The record will be merged with existing data,
+ * it may be either A/AAAA type.
+ *
+ * @param cut zone cut to be populated
+ * @param ns nameserver name
+ * @param data typically knot_rdata_t::data
+ * @param len typically knot_rdata_t::len
+ * @return 0 or error code
+ */
+KR_EXPORT
+int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const void *data, int len);
+
+/**
+ * Delete nameserver/address pair from the zone cut.
+ * @param cut
+ * @param ns name server name
+ * @param data typically knot_rdata_t::data
+ * @param len typically knot_rdata_t::len
+ * @return 0 or error code
+ */
+KR_EXPORT
+int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const void *data, int len);
+
+/**
+ * Delete all addresses associated with the given name.
+ * @param cut
+ * @param ns name server name
+ * @return 0 or error code
+ */
+KR_EXPORT
+int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns);
+
+/**
+ * Find nameserver address list in the zone cut.
+ *
+ * @note This can be used for membership test, a non-null pack is returned
+ * if the nameserver name exists.
+ *
+ * @param cut
+ * @param ns name server name
+ * @return pack of addresses or NULL
+ */
+KR_EXPORT KR_PURE
+pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns);
+
+/**
+ * Populate zone cut with a root zone using SBELT :rfc:`1034`
+ *
+ * @param ctx resolution context (to fetch root hints)
+ * @param cut zone cut to be populated
+ * @return 0 or error code
+ */
+KR_EXPORT
+int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut);
+
+/**
+ * Populate zone cut address set from cache.
+ *
+ * @param ctx resolution context (to fetch data from LRU caches)
+ * @param cut zone cut to be populated
+ * @param name QNAME to start finding zone cut for
+ * @param qry query for timestamp and stale-serving decisions
+ * @param secured set to true if want secured zone cut, will return false if it is provably insecure
+ * @return 0 or error code (ENOENT if it doesn't find anything)
+ */
+KR_EXPORT
+int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut,
+ const knot_dname_t *name, const struct kr_query *qry,
+ bool * restrict secured);
+/**
+ * Check if any address is present in the zone cut.
+ *
+ * @param cut zone cut to check
+ * @return true/false
+ */
+KR_EXPORT
+bool kr_zonecut_is_empty(struct kr_zonecut *cut);
+
diff --git a/modules/README.rst b/modules/README.rst
new file mode 100644
index 0000000..5d38f0f
--- /dev/null
+++ b/modules/README.rst
@@ -0,0 +1,331 @@
+.. _modules-api:
+
+*********************
+Modules API reference
+*********************
+
+.. contents::
+ :depth: 1
+ :local:
+
+Supported languages
+===================
+
+Currently modules written in C and LuaJIT are supported.
+There is also a support for writing modules in Go 1.5+ |---| the library has no native Go bindings, library is accessible using CGO_.
+
+The anatomy of an extension
+===========================
+
+A module is a shared object or script defining specific functions, here's an overview.
+
+*Note* |---| the :ref:`Modules <lib_api_modules>` header documents the module loading and API.
+
+.. csv-table::
+ :header: "C/Go", "Lua", "Params", "Comment"
+
+ "``X_api()`` [#]_", "", "", "API version"
+ "``X_init()``", "``X.init()``", "``module``", "Constructor"
+ "``X_deinit()``", "``X.deinit()``", "``module, key``", "Destructor"
+ "``X_config()``", "``X.config()``", "``module``", "Configuration"
+ "``X_layer()``", "``X.layer``", "``module``", ":ref:`Module layer <lib-layers>`"
+ "``X_props()``", "", "", "List of properties"
+
+.. [#] Mandatory symbol.
+
+The ``X`` corresponds to the module name, if the module name is ``hints``, then the prefix for constructor would be ``hints_init()``.
+This doesn't apply for Go, as it for now always implements `main` and requires capitalized first letter in order to export its symbol.
+
+.. note::
+ The resolution context :c:type:`struct kr_context` holds loaded modules for current context. A module can be registered with :c:func:`kr_context_register`, which triggers module constructor *immediately* after the load. Module destructor is automatically called when the resolution context closes.
+
+ If the module exports a layer implementation, it is automatically discovered by :c:func:`kr_resolver` on resolution init and plugged in. The order in which the modules are registered corresponds to the call order of layers.
+
+Writing a module in Lua
+=======================
+
+The probably most convenient way of writing modules is Lua since you can use already installed modules
+from system and have first-class access to the scripting engine. You can also tap to all the events, that
+the C API has access to, but keep in mind that transitioning from the C to Lua function is slower than
+the other way round.
+
+.. note:: The Lua functions retrieve an additional first parameter compared to the C counterparts - a "state".
+ There is no Lua wrapper for C structures used in the resolution context, until they're implemented
+ you can inspect the structures using the `ffi <http://luajit.org/ext_ffi.html>`_ library.
+
+The modules follow the `Lua way <http://lua-users.org/wiki/ModuleDefinition>`_, where the module interface is returned in a named table.
+
+.. code-block:: lua
+
+ --- @module Count incoming queries
+ local counter = {}
+
+ function counter.init(module)
+ counter.total = 0
+ counter.last = 0
+ counter.failed = 0
+ end
+
+ function counter.deinit(module)
+ print('counted', counter.total, 'queries')
+ end
+
+ -- @function Run the q/s counter with given interval.
+ function counter.config(conf)
+ -- We can use the scripting facilities here
+ if counter.ev then event.cancel(counter.ev)
+ event.recurrent(conf.interval, function ()
+ print(counter.total - counter.last, 'q/s')
+ counter.last = counter.total
+ end)
+ end
+
+ return counter
+
+.. tip:: The API functions may return an integer value just like in other languages, but they may also return a coroutine that will be continued asynchronously. A good use case for this approach is is a deferred initialization, e.g. loading a chunks of data or waiting for I/O.
+
+.. code-block:: lua
+
+ function counter.init(module)
+ counter.total = 0
+ counter.last = 0
+ counter.failed = 0
+ return coroutine.create(function ()
+ for line in io.lines('/etc/hosts') do
+ load(module, line)
+ coroutine.yield()
+ end
+ end)
+ end
+
+The created module can be then loaded just like any other module, except it isn't very useful since it
+doesn't provide any layer to capture events. The Lua module can however provide a processing layer, just
+:ref:`like its C counterpart <lib-layers>`.
+
+.. code-block:: lua
+
+ -- Notice it isn't a function, but a table of functions
+ counter.layer = {
+ begin = function (state, data)
+ counter.total = counter.total + 1
+ return state
+ end,
+ finish = function (state, req, answer)
+ if state == kres.FAIL then
+ counter.failed = counter.failed + 1
+ end
+ return state
+ end
+ }
+
+There is currently an additional "feature" in comparison to C layer functions:
+the ``consume``, ``produce`` and ``checkout`` functions do not get called at all
+if ``state == kres.FAIL``;
+note that ``answer_finalize`` and ``finish`` get called nevertheless.
+
+Since the modules are like any other Lua modules, you can interact with them through the CLI and and any interface.
+
+.. tip:: The module can be placed anywhere in the Lua search path, in the working directory or in the MODULESDIR.
+
+Writing a module in C
+=====================
+
+As almost all the functions are optional, the minimal module looks like this:
+
+.. code-block:: c
+
+ #include "lib/module.h"
+ /* Convenience macro to declare module API. */
+ KR_MODULE_EXPORT(mymodule)
+
+
+Let's define an observer thread for the module as well. It's going to be stub for the sake of brevity,
+but you can for example create a condition, and notify the thread from query processing by declaring
+module layer (see the :ref:`Writing layers <lib-layers>`).
+
+.. code-block:: c
+
+ static void* observe(void *arg)
+ {
+ /* ... do some observing ... */
+ }
+
+ int mymodule_init(struct kr_module *module)
+ {
+ /* Create a thread and start it in the background. */
+ pthread_t thr_id;
+ int ret = pthread_create(&thr_id, NULL, &observe, NULL);
+ if (ret != 0) {
+ return kr_error(errno);
+ }
+
+ /* Keep it in the thread */
+ module->data = thr_id;
+ return kr_ok();
+ }
+
+ int mymodule_deinit(struct kr_module *module)
+ {
+ /* ... signalize cancellation ... */
+ void *res = NULL;
+ pthread_t thr_id = (pthread_t) module->data;
+ int ret = pthread_join(thr_id, res);
+ if (ret != 0) {
+ return kr_error(errno);
+ }
+
+ return kr_ok();
+ }
+
+This example shows how a module can run in the background, this enables you to, for example, observe
+and publish data about query resolution.
+
+Writing a module in Go
+======================
+
+The Go modules use CGO_ to interface C resolver library, there are no native bindings yet. Second issue is that layers are declared as a structure of function pointers, which are `not present in Go`_, the workaround is to declare them in CGO_ header. Each module must be the ``main`` package, here's a minimal example:
+
+.. code-block:: go
+
+ package main
+
+ /*
+ #include "lib/module.h"
+ */
+ import "C"
+ import "unsafe"
+
+ /* Mandatory functions */
+
+ //export mymodule_api
+ func mymodule_api() C.uint32_t {
+ return C.KR_MODULE_API
+ }
+ func main() {}
+
+.. warning:: Do not forget to prefix function declarations with ``//export symbol_name``, as only these will be exported in module.
+
+In order to integrate with query processing, you have to declare a helper function with function pointers to the
+the layer implementation. Since the code prefacing ``import "C"`` is expanded in headers, you need the `static inline` trick
+to avoid multiple declarations. Here's how the preface looks like:
+
+.. code-block:: go
+
+ /*
+ #include "lib/layer.h"
+ #include "lib/module.h"
+ // Need a forward declaration of the function signature
+ int finish(kr_layer_t *);
+ // Workaround for layers composition
+ static inline const kr_layer_api_t *_layer(void)
+ {
+ static const kr_layer_api_t api = {
+ .finish = &finish
+ };
+ return &api;
+ }
+ */
+ import "C"
+ import "unsafe"
+
+Now we can add the implementations for the ``finish`` layer and finalize the module:
+
+.. code-block:: go
+
+ //export finish
+ func finish(ctx *C.kr_layer_t) C.int {
+ // Since the context is unsafe.Pointer, we need to cast it
+ var param *C.struct_kr_request = (*C.struct_kr_request)(ctx.data)
+ // Now we can use the C API as well
+ fmt.Printf("[go] resolved %d queries\n", C.list_size(&param.rplan.resolved))
+ return 0
+ }
+
+ //export mymodule_layer
+ func mymodule_layer(module *C.struct_kr_module) *C.kr_layer_api_t {
+ // Wrapping the inline trampoline function
+ return C._layer()
+ }
+
+See the CGO_ for more information about type conversions and interoperability between the C/Go.
+
+Gotchas
+-------
+
+* ``main()`` function is mandatory in each module, otherwise it won't compile.
+* Module layer function implementation must be done in C during ``import "C"``, as Go doesn't support pointers to functions.
+* The library doesn't have a Go-ified bindings yet, so interacting with it requires CGO shims, namely structure traversal and type conversions (strings, numbers).
+* Other modules can be called through C call ``C.kr_module_call(kr_context, module_name, module_propery, input)``
+
+Configuring modules
+===================
+
+There is a callback ``X_config()`` that you can implement, see hints module.
+
+.. _mod-properties:
+
+Exposing C/Go module properties
+===============================
+
+A module can offer NULL-terminated list of *properties*, each property is essentially a callable with free-form JSON input/output.
+JSON was chosen as an interchangeable format that doesn't require any schema beforehand, so you can do two things - query the module properties
+from external applications or between modules (i.e. `statistics` module can query `cache` module for memory usage).
+JSON was chosen not because it's the most efficient protocol, but because it's easy to read and write and interface to outside world.
+
+.. note:: The ``void *env`` is a generic module interface. Since we're implementing daemon modules, the pointer can be cast to ``struct engine*``.
+ This is guaranteed by the implemented API version (see `Writing a module in C`_).
+
+Here's an example how a module can expose its property:
+
+.. code-block:: c
+
+ char* get_size(void *env, struct kr_module *m,
+ const char *args)
+ {
+ /* Get cache from engine. */
+ struct engine *engine = env;
+ struct kr_cache *cache = &engine->resolver.cache;
+ /* Read item count */
+ int count = (cache->api)->count(cache->db);
+ char *result = NULL;
+ asprintf(&result, "{ \"result\": %d }", count);
+
+ return result;
+ }
+
+ struct kr_prop *cache_props(void)
+ {
+ static struct kr_prop prop_list[] = {
+ /* Callback, Name, Description */
+ {&get_size, "get_size", "Return number of records."},
+ {NULL, NULL, NULL}
+ };
+ return prop_list;
+ }
+
+ KR_MODULE_EXPORT(cache)
+
+Once you load the module, you can call the module property from the interactive console.
+*Note* |---| the JSON output will be transparently converted to Lua tables.
+
+.. code-block:: bash
+
+ $ kresd
+ ...
+ [system] started in interactive mode, type 'help()'
+ > modules.load('cached')
+ > cached.get_size()
+ [size] => 53
+
+*Note* |---| this relies on function pointers, so the same ``static inline`` trick as for the ``Layer()`` is required for C/Go.
+
+Special properties
+------------------
+
+If the module declares properties ``get`` or ``set``, they can be used in the Lua interpreter as
+regular tables.
+
+.. _`not present in Go`: http://blog.golang.org/gos-declaration-syntax
+.. _CGO: http://golang.org/cmd/cgo/
+
+.. |---| unicode:: U+02014 .. em dash
diff --git a/modules/bogus_log/README.rst b/modules/bogus_log/README.rst
new file mode 100644
index 0000000..0b93e82
--- /dev/null
+++ b/modules/bogus_log/README.rst
@@ -0,0 +1,41 @@
+.. _mod-bogus_log:
+
+DNSSEC validation failure logging
+---------------------------------
+
+This module adds error message for each DNSSEC validation failure.
+It is meant to provide hint to operators which queries should be
+investigated using diagnostic tools like DNSViz_.
+
+Add following line to your configuration file to enable it:
+
+.. code-block:: lua
+
+ modules.load('bogus_log')
+
+Example of error message logged by this module:
+
+.. code-block:: none
+
+ DNSSEC validation failure dnssec-failed.org. DNSKEY
+
+.. _DNSViz: http://dnsviz.net/
+
+List of most frequent queries which fail as DNSSEC bogus can be obtained at run-time:
+
+.. code-block:: lua
+
+ > bogus_log.frequent()
+ [1] => {
+ [type] => DNSKEY
+ [count] => 1
+ [name] => dnssec-failed.org.
+ }
+ [2] => {
+ [type] => DNSKEY
+ [count] => 13
+ [name] => rhybar.cz.
+ }
+
+Please note that in future this module might be replaced
+with some other way to log this information.
diff --git a/modules/bogus_log/bogus_log.c b/modules/bogus_log/bogus_log.c
new file mode 100644
index 0000000..98c0fc9
--- /dev/null
+++ b/modules/bogus_log/bogus_log.c
@@ -0,0 +1,150 @@
+/* Copyright (C) Knot Resolver contributors. Licensed under GNU GPLv3 or
+ * (at your option) any later version. See COPYING for text of the license.
+ *
+ * This module logs (query name, type) pairs which failed DNSSEC validation. */
+
+#include <libknot/packet/pkt.h>
+#include <libknot/dname.h>
+#include <ccan/json/json.h>
+#include <contrib/cleanup.h>
+
+#include "daemon/engine.h"
+#include "lib/layer.h"
+#include "lib/generic/lru.h"
+
+/** @internal Compatibility wrapper for Lua < 5.2 */
+#if LUA_VERSION_NUM < 502
+#define lua_rawlen(L, obj) lua_objlen((L), (obj))
+#endif
+
+#ifdef LRU_REP_SIZE
+ #define FREQUENT_COUNT LRU_REP_SIZE /* Size of frequent tables */
+#else
+ #define FREQUENT_COUNT 5000 /* Size of frequent tables */
+#endif
+
+/** @internal LRU hash of most frequent names. */
+typedef lru_t(unsigned) namehash_t;
+
+/** @internal Stats data structure. */
+struct stat_data {
+ namehash_t *frequent;
+};
+
+static int consume(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ if (!(ctx->state & KR_STATE_FAIL)
+ || !ctx->req
+ || !ctx->req->current_query
+ || !ctx->req->current_query->flags.DNSSEC_BOGUS
+ || knot_wire_get_qdcount(pkt->wire) != 1)
+ return ctx->state;
+
+ auto_free char *qname_text = kr_dname_text(knot_pkt_qname(pkt));
+ auto_free char *qtype_text = kr_rrtype_text(knot_pkt_qtype(pkt));
+
+ kr_log_error("DNSSEC validation failure %s %s\n", qname_text, qtype_text);
+
+ /* log of most frequent bogus queries */
+ uint16_t type = knot_pkt_qtype(pkt);
+ char key[sizeof(type) + KNOT_DNAME_MAXLEN];
+ memcpy(key, &type, sizeof(type));
+ int key_len = knot_dname_to_wire((uint8_t *)key + sizeof(type), knot_pkt_qname(pkt), KNOT_DNAME_MAXLEN);
+ if (key_len >= 0) {
+ struct kr_module *module = ctx->api->data;
+ struct stat_data *data = module->data;
+ unsigned *count = lru_get_new(data->frequent, key, key_len+sizeof(type), NULL);
+ if (count)
+ *count += 1;
+ }
+
+ return ctx->state;
+}
+
+/** @internal Helper for dump_list: add a single namehash_t item to JSON. */
+static enum lru_apply_do dump_value(const char *key, uint len, unsigned *val, void *baton)
+{
+ uint16_t key_type = 0;
+ /* Extract query name, type and counter */
+ memcpy(&key_type, key, sizeof(key_type));
+ KR_DNAME_GET_STR(key_name, (uint8_t *)key + sizeof(key_type));
+ KR_RRTYPE_GET_STR(type_str, key_type);
+
+ /* Convert to JSON object */
+ JsonNode *json_val = json_mkobject();
+ json_append_member(json_val, "count", json_mknumber(*val));
+ json_append_member(json_val, "name", json_mkstring(key_name));
+ json_append_member(json_val, "type", json_mkstring(type_str));
+ json_append_element((JsonNode *)baton, json_val);
+ return LRU_APPLY_DO_NOTHING; // keep the item
+}
+
+/**
+ * List frequent names.
+ *
+ * Output: [{ count: <counter>, name: <qname>, type: <qtype>}, ... ]
+ */
+static char* dump_list(void *env, struct kr_module *module, const char *args, namehash_t *table)
+{
+ if (!table) {
+ return NULL;
+ }
+ JsonNode *root = json_mkarray();
+ lru_apply(table, dump_value, root);
+ char *ret = json_encode(root);
+ json_delete(root);
+ return ret;
+}
+
+static char* dump_frequent(void *env, struct kr_module *module, const char *args)
+{
+ struct stat_data *data = module->data;
+ return dump_list(env, module, args, data->frequent);
+}
+
+KR_EXPORT
+int bogus_log_init(struct kr_module *module)
+{
+ struct stat_data *data = malloc(sizeof(*data));
+ if (!data) {
+ return kr_error(ENOMEM);
+ }
+ memset(data, 0, sizeof(*data));
+ module->data = data;
+ lru_create(&data->frequent, FREQUENT_COUNT, NULL, NULL);
+ return kr_ok();
+}
+
+KR_EXPORT
+int bogus_log_deinit(struct kr_module *module)
+{
+ struct stat_data *data = module->data;
+ if (data) {
+ lru_free(data->frequent);
+ free(data);
+ }
+ return kr_ok();
+}
+
+
+KR_EXPORT
+const kr_layer_api_t *bogus_log_layer(struct kr_module *module)
+{
+ static kr_layer_api_t _layer = {
+ .consume = &consume,
+ };
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_EXPORT
+struct kr_prop *bogus_log_props(void)
+{
+ static struct kr_prop prop_list[] = {
+ { &dump_frequent, "frequent", "List most frequent queries.", },
+ { NULL, NULL, NULL }
+ };
+ return prop_list;
+}
+
+KR_MODULE_EXPORT(bogus_log)
diff --git a/modules/bogus_log/bogus_log.mk b/modules/bogus_log/bogus_log.mk
new file mode 100644
index 0000000..7431b19
--- /dev/null
+++ b/modules/bogus_log/bogus_log.mk
@@ -0,0 +1,8 @@
+bogus_log_CFLAGS := -fPIC
+# We use a symbol that's not in libkres but the daemon.
+# On darwin this isn't accepted by default.
+bogus_log_LDFLAGS := -Wl,-undefined -Wl,dynamic_lookup
+bogus_log_SOURCES := modules/bogus_log/bogus_log.c
+bogus_log_DEPEND := $(libkres)
+bogus_log_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS)
+$(call make_c_module,bogus_log)
diff --git a/modules/bogus_log/test.integr/deckard.yaml b/modules/bogus_log/test.integr/deckard.yaml
new file mode 100644
index 0000000..a8c8700
--- /dev/null
+++ b/modules/bogus_log/test.integr/deckard.yaml
@@ -0,0 +1,13 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/bogus_log/test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
+noclean: True
diff --git a/modules/bogus_log/test.integr/kresd_config.j2 b/modules/bogus_log/test.integr/kresd_config.j2
new file mode 100644
index 0000000..6e3dc09
--- /dev/null
+++ b/modules/bogus_log/test.integr/kresd_config.j2
@@ -0,0 +1,82 @@
+{% for TAF in TRUST_ANCHOR_FILES %}
+trust_anchors.add_file('{{TAF}}')
+{% endfor %}
+
+{% raw %}
+modules.load('bogus_log')
+
+function check_stats(got)
+ log('checking if bogus_log.frequent values match expected values:')
+ local expected = {
+ [1] = {
+ ['type'] = 'DNSKEY',
+ ['count'] = 2,
+ ['name'] = '.',
+ }
+ }
+ print(table_print(expected))
+
+ if table_print(expected) == table_print(got) then
+ log('no problem found')
+ return policy.DENY_MSG('Ok')
+ else
+ log('mismatch!')
+ return policy.DENY_MSG('bogus_log.frequent mismatch, see logs')
+ end
+end
+
+function reply_result(state, req)
+ local got = bogus_log.frequent()
+ log('current bogus_log.frequent() values:')
+ print(table_print(got))
+ local result = check_stats(got)
+ return result(state, req)
+end
+policy.add(policy.pattern(reply_result, 'bogus_log.test.'))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/bogus_log/test.integr/val_minimal_expiredsignature.rpl b/modules/bogus_log/test.integr/val_minimal_expiredsignature.rpl
new file mode 100644
index 0000000..d0a616b
--- /dev/null
+++ b/modules/bogus_log/test.integr/val_minimal_expiredsignature.rpl
@@ -0,0 +1,124 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170410000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Date after expiration of signatures.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+bogus_log.test. IN TXT
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NXDOMAIN
+SECTION QUESTION
+bogus_log.test. IN TXT
+SECTION AUTHORITY
+bogus_log.test. 10800 IN SOA bogus_log.test. nobody.invalid. 1 3600 1200 604800 10800
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "Ok"
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/cookies/README.rst b/modules/cookies/README.rst
new file mode 100644
index 0000000..5db476c
--- /dev/null
+++ b/modules/cookies/README.rst
@@ -0,0 +1,54 @@
+.. _mod-cookies:
+
+DNS Cookies
+-----------
+
+The module performs most of the :rfc:`7873` DNS cookies functionality. Its main purpose is to check the cookies of inbound queries and responses. It is also used to alter the behaviour of the cookie functionality.
+
+Example Configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ -- Load the module before the 'iterate' layer.
+ modules = {
+ 'cookies < iterate'
+ }
+
+ -- Configure the client part of the resolver. Set 8 bytes of the client
+ -- secret and choose the hashing algorithm to be used.
+ -- Use a string composed of hexadecimal digits to set the secret.
+ cookies.config { client_secret = '0123456789ABCDEF',
+ client_cookie_alg = 'FNV-64' }
+
+ -- Configure the server part of the resolver.
+ cookies.config { server_secret = 'FEDCBA9876543210',
+ server_cookie_alg = 'FNV-64' }
+
+ -- Enable client cookie functionality. (Add cookies into outbound
+ -- queries.)
+ cookies.config { client_enabled = true }
+
+ -- Enable server cookie functionality. (Handle cookies in inbound
+ -- requests.)
+ cookies.config { server_enabled = true }
+
+.. tip:: If you want to change several parameters regarding the client or server configuration then do it within a single ``cookies.config()`` invocation.
+
+.. warning:: The module must be loaded before any other module that has direct influence on query processing and response generation. The module must be able to intercept an incoming query before the processing of the actual query starts. It must also be able to check the cookies of inbound responses and eventually discard them before they are handled by other functional units.
+
+Properties
+^^^^^^^^^^
+
+.. function:: cookies.config(configuration)
+
+ :param table configuration: part of cookie configuration to be changed, may be called without parameter
+ :return: JSON dictionary containing current configuration
+
+ The function may be called without any parameter. In such case it only returns current configuration. The returned JSON also contains available algorithm choices.
+
+Dependencies
+^^^^^^^^^^^^
+
+* `Nettle <https://www.lysator.liu.se/~nisse/nettle/>`_ required for HMAC-SHA256
+
diff --git a/modules/cookies/cookiectl.c b/modules/cookies/cookiectl.c
new file mode 100644
index 0000000..1af508b
--- /dev/null
+++ b/modules/cookies/cookiectl.c
@@ -0,0 +1,684 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <ccan/json/json.h>
+#include <ctype.h>
+#include <libknot/rrtype/opt-cookie.h>
+#include <libknot/db/db_lmdb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/cookies/alg_containers.h"
+#include "modules/cookies/cookiectl.h"
+
+#define NAME_CLIENT_ENABLED "client_enabled"
+#define NAME_CLIENT_SECRET "client_secret"
+#define NAME_CLIENT_COOKIE_ALG "client_cookie_alg"
+#define NAME_AVAILABLE_CLIENT_COOKIE_ALGS "available_client_cookie_algs"
+
+#define NAME_SERVER_ENABLED "server_enabled"
+#define NAME_SERVER_SECRET "server_secret"
+#define NAME_SERVER_COOKIE_ALG "server_cookie_alg"
+#define NAME_AVAILABLE_SERVER_COOKIE_ALGS "available_server_cookie_algs"
+
+/**
+ * @brief Initialises cookie control context.
+ * @param ctx cookie control context
+ */
+static void kr_cookie_ctx_init(struct kr_cookie_ctx *ctx)
+{
+ if (!ctx) {
+ return;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->clnt.current.alg_id = ctx->clnt.recent.alg_id = -1;
+ ctx->srvr.current.alg_id = ctx->srvr.recent.alg_id = -1;
+}
+
+/**
+ * @brief Check whether node holds proper 'enabled' value.
+ * @patam node JSON node holding the value
+ * @return true if value OK
+ */
+static bool enabled_ok(const JsonNode *node)
+{
+ assert(node);
+
+ return node->tag == JSON_BOOL;
+}
+
+/**
+ * @brief Check whether node holds proper 'secret' value.
+ * @patam node JSON node holding the value
+ * @return true if value OK
+ */
+static bool secret_ok(const JsonNode *node)
+{
+ assert(node);
+
+ if (node->tag != JSON_STRING) {
+ return false;
+ }
+
+ const char *hexstr = node->string_;
+
+ size_t len = strlen(hexstr);
+ if ((len % 2) != 0) {
+ return false;
+ }
+ /* A check for minimal required length could also be performed. */
+
+ for (size_t i = 0; i < len; ++i) {
+ if (!isxdigit(tolower(hexstr[i]))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @brief Find hash function with given name.
+ * @param node JSON node holding the value
+ * @param table lookup table with algorithm names
+ * @return pointer to table entry or NULL on error if does not exist
+ */
+static const knot_lookup_t *hash_func_lookup(const JsonNode *node,
+ const knot_lookup_t table[])
+{
+ if (!node || node->tag != JSON_STRING) {
+ return NULL;
+ }
+
+ return knot_lookup_by_name(table, node->string_);
+}
+
+/**
+ * @brief Creates a cookie secret structure.
+ * @param size size of the actual secret
+ * @param zero set to true if value should be cleared
+ * @return pointer to new structure, NULL on failure or if @size is zero
+ */
+static struct kr_cookie_secret *new_cookie_secret(size_t size, bool zero)
+{
+ if (size == 0) {
+ return NULL;
+ }
+
+ struct kr_cookie_secret *sq = malloc(sizeof(*sq) + size);
+ if (!sq) {
+ return NULL;
+ }
+
+ sq->size = size;
+ if (zero) {
+ memset(sq->data, 0, size);
+ }
+ return sq;
+}
+
+/**
+ * @brief Clone a cookie secret.
+ * @param sec secret to be cloned
+ * @return pointer to new structure, NULL on failure or if @size is zero
+ */
+static struct kr_cookie_secret *clone_cookie_secret(const struct kr_cookie_secret *sec)
+{
+ if (!sec || sec->size == 0) {
+ return NULL;
+ }
+
+ struct kr_cookie_secret *sq = malloc(sizeof(*sq) + sec->size);
+ if (!sq) {
+ return NULL;
+ }
+
+ sq->size = sec->size;
+ memcpy(sq->data, sec->data, sq->size);
+ return sq;
+}
+
+static int hexchar2val(int d)
+{
+ if (('0' <= d) && (d <= '9')) {
+ return d - '0';
+ } else if (('a' <= d) && (d <= 'f')) {
+ return d - 'a' + 0x0a;
+ } else {
+ return -1;
+ }
+}
+
+static int hexval2char(int i)
+{
+ if ((0 <= i) && (i <= 9)) {
+ return i + '0';
+ } else if ((0x0a <= i) && (i <= 0x0f)) {
+ return i - 0x0a + 'A';
+ } else {
+ return -1;
+ }
+}
+
+/**
+ * @brief Converts string containing two-digit hexadecimal number into int.
+ * @param hexstr hexadecimal string
+ * @return -1 on error, value from 0 to 255 else.
+ */
+static int hexbyte2int(const char *hexstr)
+{
+ if (!hexstr) {
+ return -1;
+ }
+
+ int dhi = tolower(hexstr[0]);
+ if (!isxdigit(dhi)) {
+ /* Exit also on empty string. */
+ return -1;
+ }
+ int dlo = tolower(hexstr[1]);
+ if (!isxdigit(dlo)) {
+ return -1;
+ }
+
+ dhi = hexchar2val(dhi);
+ assert(dhi != -1);
+ dlo = hexchar2val(dlo);
+ assert(dlo != -1);
+
+ return (dhi << 4) | dlo;
+}
+
+/**
+ * @brief Writes two hexadecimal digits (two byes) into given memory location.
+ * @param tgt target location
+ * @param i number from 0 to 255
+ * @return 0 on success, -1 on failure
+ */
+static int int2hexbyte(char *tgt, int i)
+{
+ if (!tgt || i < 0x00 || i > 0xff) {
+ return -1;
+ }
+
+ int ilo = hexval2char(i & 0x0f);
+ assert(ilo != -1);
+ int ihi = hexval2char((i >> 4) & 0x0f);
+ assert(ihi != -1);
+
+ tgt[0] = ihi;
+ tgt[1] = ilo;
+
+ return 0;
+}
+
+/**
+ * @brief Reads a string containing hexadecimal values.
+ * @note String must consist of hexadecimal digits only and must have even
+ * non-zero length.
+ */
+static struct kr_cookie_secret *new_sq_from_hexstr(const char *hexstr)
+{
+ if (!hexstr) {
+ return NULL;
+ }
+
+ size_t len = strlen(hexstr);
+ if ((len % 2) != 0) {
+ return NULL;
+ }
+
+ struct kr_cookie_secret *sq = new_cookie_secret(len / 2, false);
+ if (!sq) {
+ return NULL;
+ }
+
+ uint8_t *data = sq->data;
+ for (size_t i = 0; i < len; i += 2) {
+ int num = hexbyte2int(hexstr + i);
+ if (num == -1) {
+ free(sq);
+ return NULL;
+ }
+ assert(0x00 <= num && num <= 0xff);
+ *data = num;
+ ++data;
+ }
+
+ return sq;
+}
+
+/**
+ * @brief Creates new secret.
+ * @patam node JSON node holding the secret value
+ * @return pointer to newly allocated secret, NULL on error
+ */
+static struct kr_cookie_secret *create_secret(const JsonNode *node)
+{
+ if (!node) {
+ return NULL;
+ }
+
+ if (node->tag != JSON_STRING) {
+ return NULL;
+ }
+
+ return new_sq_from_hexstr(node->string_);
+}
+
+/**
+ * @brief Check whether configuration node contains valid values.
+ */
+static bool configuration_node_ok(const JsonNode *node)
+{
+ assert(node);
+
+ if (!node->key) {
+ /* All top most nodes must have names. */
+ return false;
+ }
+
+ if (strcmp(node->key, NAME_CLIENT_ENABLED) == 0) {
+ return enabled_ok(node);
+ } else if (strcmp(node->key, NAME_CLIENT_SECRET) == 0) {
+ return secret_ok(node);
+ } else if (strcmp(node->key, NAME_CLIENT_COOKIE_ALG) == 0) {
+ return hash_func_lookup(node, kr_cc_alg_names) != NULL;
+ } else if (strcmp(node->key, NAME_SERVER_ENABLED) == 0) {
+ return enabled_ok(node);
+ } else if (strcmp(node->key, NAME_SERVER_SECRET) == 0) {
+ return secret_ok(node);
+ } else if (strcmp(node->key, NAME_SERVER_COOKIE_ALG) == 0) {
+ return hash_func_lookup(node, kr_sc_alg_names) != NULL;
+ }
+
+ return false;
+}
+
+/**
+ * @brief Creates a new string from secret quantity.
+ * @param sq secret quantity
+ * @return newly allocated string or NULL on error
+ */
+static char *new_hexstr_from_sq(const struct kr_cookie_secret *sq)
+{
+ if (!sq) {
+ return NULL;
+ }
+
+ char *new_str = malloc((sq->size * 2) + 1);
+ if (!new_str) {
+ return NULL;
+ }
+
+ char *tgt = new_str;
+ for (size_t i = 0; i < sq->size; ++i) {
+ if (0 != int2hexbyte(tgt, sq->data[i])) {
+ free(new_str);
+ return NULL;
+ }
+ tgt += 2;
+ }
+
+ *tgt = '\0';
+ return new_str;
+}
+
+static bool read_secret(JsonNode *root, const char *node_name,
+ const struct kr_cookie_secret *secret)
+{
+ assert(root && node_name && secret);
+
+ char *secret_str = new_hexstr_from_sq(secret);
+ if (!secret_str) {
+ return false;
+ }
+
+ JsonNode *str_node = json_mkstring(secret_str);
+ if (!str_node) {
+ free(secret_str);
+ return false;
+ }
+
+ json_append_member(root, node_name, str_node);
+
+ free(secret_str);
+ return true;
+}
+
+static bool read_available_hashes(JsonNode *root, const char *root_name,
+ const knot_lookup_t table[])
+{
+ assert(root && root_name && table);
+
+ JsonNode *array = json_mkarray();
+ if (!array) {
+ return false;
+ }
+
+ const knot_lookup_t *aux_ptr = table;
+ while (aux_ptr && (aux_ptr->id >= 0) && aux_ptr->name) {
+ JsonNode *element = json_mkstring(aux_ptr->name);
+ if (!element) {
+ goto fail;
+ }
+ json_append_element(array, element);
+ ++aux_ptr;
+ }
+
+ json_append_member(root, root_name, array);
+
+ return true;
+
+fail:
+ if (array) {
+ json_delete(array);
+ }
+ return false;
+}
+
+/**
+ * @brief Check whether new settings are different from the old ones.
+ */
+static bool is_modified(const struct kr_cookie_comp *running,
+ struct kr_cookie_secret *secr,
+ const knot_lookup_t *alg_lookup)
+{
+ assert(running);
+
+ if (alg_lookup && alg_lookup->id >= 0) {
+ if (running->alg_id != alg_lookup->id) {
+ return true;
+ }
+ }
+
+ if (secr) {
+ assert(secr->size > 0);
+ if (running->secr->size != secr->size ||
+ 0 != memcmp(running->secr->data, secr->data,
+ running->secr->size)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @brief Returns newly allocated secret via pointer argument.
+ */
+static bool obtain_secret(JsonNode *root_node, struct kr_cookie_secret **secret,
+ const char *name)
+{
+ assert(secret && name);
+
+ const JsonNode *node;
+ if ((node = json_find_member(root_node, name)) != NULL) {
+ *secret = create_secret(node);
+ if (!*secret) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @brief Updates the current configuration and moves current to recent.
+ */
+static void update_running(struct kr_cookie_settings *running,
+ struct kr_cookie_secret **secret,
+ const knot_lookup_t *alg_lookup)
+{
+ assert(running && secret);
+ assert(*secret || alg_lookup);
+
+ running->recent.alg_id = -1;
+ free(running->recent.secr);
+ running->recent.secr = NULL;
+
+ running->recent.alg_id = running->current.alg_id;
+ if (alg_lookup) {
+ assert(alg_lookup->id >= 0);
+ running->current.alg_id = alg_lookup->id;
+ }
+
+ if (*secret) {
+ running->recent.secr = running->current.secr;
+ running->current.secr = *secret;
+ *secret = NULL;
+ } else {
+ running->recent.secr = clone_cookie_secret(running->current.secr);
+ }
+}
+
+/**
+ * @brief Applies modification onto client/server running configuration.
+ * @note The @a secret is going to be consumed.
+ * @param secret pointer to new secret
+ * @param alg_lookup new algorithm
+ * @param enabled JSON node holding boolean value
+ */
+static void apply_changes(struct kr_cookie_settings *running,
+ struct kr_cookie_secret **secret,
+ const knot_lookup_t *alg_lookup,
+ const JsonNode *enabled)
+{
+ assert(running && secret);
+
+ if (is_modified(&running->current, *secret, alg_lookup)) {
+ update_running(running, secret, alg_lookup);
+ }
+
+ if (enabled) {
+ assert(enabled->tag == JSON_BOOL);
+ running->enabled = enabled->bool_;
+ }
+}
+
+/**
+ * @brief Applies configuration.
+ *
+ * @note The function must be called after the input values have been checked
+ * for validity. Only first found values are applied.
+ *
+ * @param ctx cookie configuration context
+ * @param root_node JSON root node
+ * @return true if changes were applied
+ */
+static bool config_apply_json(struct kr_cookie_ctx *ctx, JsonNode *root_node)
+{
+ assert(ctx && root_node);
+
+ /*
+ * These must be allocated before actual change. Allocation failure
+ * should not leave configuration in inconsistent state.
+ */
+ struct kr_cookie_secret *new_clnt_secret = NULL;
+ struct kr_cookie_secret *new_srvr_secret = NULL;
+ if (!obtain_secret(root_node, &new_clnt_secret, NAME_CLIENT_SECRET)) {
+ return false;
+ }
+ if (!obtain_secret(root_node, &new_srvr_secret, NAME_SERVER_SECRET)) {
+ free(new_clnt_secret);
+ return false;
+ }
+
+ /* Algorithm pointers. */
+ const knot_lookup_t *clnt_lookup = hash_func_lookup(json_find_member(root_node, NAME_CLIENT_COOKIE_ALG), kr_cc_alg_names);
+ const knot_lookup_t *srvr_lookup = hash_func_lookup(json_find_member(root_node, NAME_SERVER_COOKIE_ALG), kr_sc_alg_names);
+
+ const JsonNode *clnt_enabled_node = json_find_member(root_node, NAME_CLIENT_ENABLED);
+ const JsonNode *srvr_enabled_node = json_find_member(root_node, NAME_SERVER_ENABLED);
+
+ apply_changes(&ctx->clnt, &new_clnt_secret, clnt_lookup, clnt_enabled_node);
+ apply_changes(&ctx->srvr, &new_srvr_secret, srvr_lookup, srvr_enabled_node);
+
+ /*
+ * Allocated secrets should be already consumed. There is no need to
+ * free them.
+ */
+
+ return true;
+}
+
+bool config_apply(struct kr_cookie_ctx *ctx, const char *args)
+{
+ if (!ctx) {
+ return false;
+ }
+
+ if (!args || !strlen(args)) {
+ return true;
+ }
+
+ if (!args || !strlen(args)) {
+ return true;
+ }
+
+ bool success = false;
+
+ /* Check whether all supplied data are valid. */
+ JsonNode *root_node = json_decode(args);
+ if (!root_node) {
+ return false;
+ }
+ JsonNode *node;
+ json_foreach (node, root_node) {
+ success = configuration_node_ok(node);
+ if (!success) {
+ break;
+ }
+ }
+
+ /* Apply configuration if values seem to be OK. */
+ if (success) {
+ success = config_apply_json(ctx, root_node);
+ }
+
+ json_delete(root_node);
+
+ return success;
+}
+
+char *config_read(struct kr_cookie_ctx *ctx)
+{
+ if (!ctx) {
+ return NULL;
+ }
+
+ const knot_lookup_t *lookup;
+ char *result;
+ JsonNode *root_node = json_mkobject();
+ if (!root_node) {
+ return NULL;
+ }
+
+ json_append_member(root_node, NAME_CLIENT_ENABLED,
+ json_mkbool(ctx->clnt.enabled));
+
+ read_secret(root_node, NAME_CLIENT_SECRET, ctx->clnt.current.secr);
+
+ lookup = knot_lookup_by_id(kr_cc_alg_names, ctx->clnt.current.alg_id);
+ if (lookup) {
+ json_append_member(root_node, NAME_CLIENT_COOKIE_ALG,
+ json_mkstring(lookup->name));
+ }
+
+ read_available_hashes(root_node, NAME_AVAILABLE_CLIENT_COOKIE_ALGS,
+ kr_cc_alg_names);
+
+ json_append_member(root_node, NAME_SERVER_ENABLED,
+ json_mkbool(ctx->srvr.enabled));
+
+ read_secret(root_node, NAME_SERVER_SECRET, ctx->srvr.current.secr);
+
+ lookup = knot_lookup_by_id(kr_sc_alg_names, ctx->srvr.current.alg_id);
+ if (lookup) {
+ json_append_member(root_node, NAME_SERVER_COOKIE_ALG,
+ json_mkstring(lookup->name));
+ }
+
+ read_available_hashes(root_node, NAME_AVAILABLE_SERVER_COOKIE_ALGS,
+ kr_sc_alg_names);
+
+ result = json_encode(root_node);
+ json_delete(root_node);
+ return result;
+}
+
+int config_init(struct kr_cookie_ctx *ctx)
+{
+ if (!ctx) {
+ return kr_error(EINVAL);
+ }
+
+ kr_cookie_ctx_init(ctx);
+
+ struct kr_cookie_secret *cs = new_cookie_secret(KNOT_OPT_COOKIE_CLNT,
+ true);
+ struct kr_cookie_secret *ss = new_cookie_secret(KNOT_OPT_COOKIE_CLNT,
+ true);
+ if (!cs || !ss) {
+ free(cs);
+ free(ss);
+ return kr_error(ENOMEM);
+ }
+
+ const knot_lookup_t *clookup = knot_lookup_by_name(kr_cc_alg_names,
+ "FNV-64");
+ const knot_lookup_t *slookup = knot_lookup_by_name(kr_sc_alg_names,
+ "FNV-64");
+ if (!clookup || !slookup) {
+ free(cs);
+ free(ss);
+ return kr_error(ENOENT);
+ }
+
+ ctx->clnt.current.secr = cs;
+ ctx->clnt.current.alg_id = clookup->id;
+
+ ctx->srvr.current.secr = ss;
+ ctx->srvr.current.alg_id = slookup->id;
+
+ return kr_ok();
+}
+
+void config_deinit(struct kr_cookie_ctx *ctx)
+{
+ if (!ctx) {
+ return;
+ }
+
+ ctx->clnt.enabled = false;
+
+ free(ctx->clnt.recent.secr);
+ ctx->clnt.recent.secr = NULL;
+
+ free(ctx->clnt.current.secr);
+ ctx->clnt.current.secr = NULL;
+
+ ctx->srvr.enabled = false;
+
+ free(ctx->srvr.recent.secr);
+ ctx->srvr.recent.secr = NULL;
+
+ free(ctx->srvr.current.secr);
+ ctx->srvr.current.secr = NULL;
+}
diff --git a/modules/cookies/cookiectl.h b/modules/cookies/cookiectl.h
new file mode 100644
index 0000000..48a379d
--- /dev/null
+++ b/modules/cookies/cookiectl.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "lib/cookies/control.h"
+
+/**
+ * @brief Sets cookie control context structure.
+ * @param ctx cookie control context
+ * @param args JSON string describing configuration changes
+ * @return true if changes successfully applied
+ */
+bool config_apply(struct kr_cookie_ctx *ctx, const char *args);
+
+/**
+ * @brief Reads cookie control context structure.
+ * @param ctx cookie control context
+ * @return JSON string or NULL on error
+ */
+char *config_read(struct kr_cookie_ctx *ctx);
+
+/**
+ * @brief Initialises cookie control context to default values.
+ * @param ctx cookie control context
+ * @return kr_ok() or error code
+ */
+int config_init(struct kr_cookie_ctx *ctx);
+
+/**
+ * @brief Clears the cookie control context.
+ * @param ctx cookie control context
+ */
+void config_deinit(struct kr_cookie_ctx *ctx);
diff --git a/modules/cookies/cookiemonster.c b/modules/cookies/cookiemonster.c
new file mode 100644
index 0000000..7af7afa
--- /dev/null
+++ b/modules/cookies/cookiemonster.c
@@ -0,0 +1,469 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <ccan/json/json.h>
+#include <libknot/db/db_lmdb.h>
+#include <libknot/error.h>
+#include <libknot/mm_ctx.h>
+#include <libknot/rrtype/opt-cookie.h>
+#include <libknot/version.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lib/cookies/alg_containers.h"
+#include "lib/cookies/control.h"
+#include "lib/cookies/helper.h"
+#include "lib/cookies/lru_cache.h"
+#include "lib/cookies/nonce.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+#include "modules/cookies/cookiemonster.h"
+
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "cookies", __VA_ARGS__)
+
+/**
+ * Obtain address from query/response context if if can be obtained.
+ * @param req resolution context
+ * @return pointer to where the server socket address, NULL if not provided within context
+ */
+static const struct sockaddr *passed_server_sockaddr(const struct kr_request *req)
+{
+ if (!req || !req->upstream.addr) {
+ return NULL;
+ }
+
+ if (req->upstream.addr->sa_family == AF_INET ||
+ req->upstream.addr->sa_family == AF_INET6) {
+ return req->upstream.addr;
+ }
+
+ return NULL;
+}
+
+/**
+ * Obtain pointer to server socket address that matches obtained cookie.
+ * @param srvr_sa server socket address
+ * @param cc client cookie from the response
+ * @param cc_len client cookie size
+ * @param clnt_sett client cookie settings structure
+ * @retval 1 if cookie matches current settings
+ * @retval 0 if cookie matches recent settings
+ * @return -1 if cookie does not match
+ * @return -2 on any error
+ */
+static int srvr_sockaddr_cc_check(const struct sockaddr *srvr_sa,
+ const uint8_t *cc, uint16_t cc_len,
+ const struct kr_cookie_settings *clnt_sett)
+{
+ assert(cc && cc_len > 0 && clnt_sett);
+
+ if (!srvr_sa) {
+ return -2;
+ }
+
+ assert(clnt_sett->current.secr);
+
+ /* The address must correspond with the client cookie. */
+ struct knot_cc_input input = {
+ .clnt_sockaddr = NULL, /* Not supported yet. */
+ .srvr_sockaddr = srvr_sa,
+ .secret_data = clnt_sett->current.secr->data,
+ .secret_len = clnt_sett->current.secr->size
+ };
+
+ const struct knot_cc_alg *cc_alg = kr_cc_alg_get(clnt_sett->current.alg_id);
+ if (!cc_alg) {
+ return -2;
+ }
+ int comp_ret = -1; /* Cookie does not match. */
+ int ret = knot_cc_check(cc, cc_len, &input, cc_alg);
+ if (ret == KNOT_EOK) {
+ comp_ret = 1;
+ } else {
+ cc_alg = kr_cc_alg_get(clnt_sett->recent.alg_id);
+ if (clnt_sett->recent.secr && cc_alg) {
+ input.secret_data = clnt_sett->recent.secr->data;
+ input.secret_len = clnt_sett->recent.secr->size;
+ ret = knot_cc_check(cc, cc_len, &input, cc_alg);
+ if (ret == KNOT_EOK) {
+ comp_ret = 0;
+ }
+ }
+ }
+
+ return comp_ret;
+}
+
+/**
+ * Obtain cookie from cache.
+ * @note Cookies with invalid length are ignored.
+ * @param cache cache context
+ * @param sa key value
+ * @param cookie_opt entire EDNS cookie option (including header)
+ * @return true if a cookie exists in cache
+ */
+static const uint8_t *get_cookie_opt(kr_cookie_lru_t *cache,
+ const struct sockaddr *sa)
+{
+ assert(cache && sa);
+
+ const uint8_t *cached_cookie_opt = kr_cookie_lru_get(cache, sa);
+ if (!cached_cookie_opt) {
+ return NULL;
+ }
+
+ size_t cookie_opt_size = KNOT_EDNS_OPTION_HDRLEN +
+ knot_edns_opt_get_length(cached_cookie_opt);
+ if (cookie_opt_size > KR_COOKIE_OPT_MAX_LEN) {
+ return NULL;
+ }
+
+ return cached_cookie_opt;
+}
+
+/**
+ * Check whether the supplied cookie is cached under the given key.
+ * @param cache cache context
+ * @param sa key value
+ * @param cookie_opt cookie option to search for
+ */
+static bool is_cookie_cached(kr_cookie_lru_t *cache, const struct sockaddr *sa,
+ const uint8_t *cookie_opt)
+{
+ assert(cache && sa && cookie_opt);
+
+ const uint8_t *cached_opt = get_cookie_opt(cache, sa);
+ if (!cached_opt) {
+ return false;
+ }
+
+ uint16_t cookie_opt_size = KNOT_EDNS_OPTION_HDRLEN +
+ knot_edns_opt_get_length(cookie_opt);
+ uint16_t cached_opt_size = KNOT_EDNS_OPTION_HDRLEN +
+ knot_edns_opt_get_length(cached_opt);
+
+ if (cookie_opt_size != cached_opt_size) {
+ return false;
+ }
+
+ return memcmp(cookie_opt, cached_opt, cookie_opt_size) == 0;
+}
+
+/**
+ * Check cookie content and store it to cache.
+ */
+static bool check_cookie_content_and_cache(const struct kr_cookie_settings *clnt_sett,
+ struct kr_request *req,
+ uint8_t *pkt_cookie_opt,
+ kr_cookie_lru_t *cache)
+{
+ assert(clnt_sett && req && pkt_cookie_opt && cache);
+
+ const uint8_t *pkt_cookie_data = knot_edns_opt_get_data(pkt_cookie_opt);
+ uint16_t pkt_cookie_len = knot_edns_opt_get_length(pkt_cookie_opt);
+ /* knot_edns_opt_cookie_parse() returns error on invalid data. */
+
+ const uint8_t *pkt_cc = NULL, *pkt_sc = NULL;
+ uint16_t pkt_cc_len = 0, pkt_sc_len = 0;
+
+ int ret = knot_edns_opt_cookie_parse(pkt_cookie_data, pkt_cookie_len,
+ &pkt_cc, &pkt_cc_len,
+ &pkt_sc, &pkt_sc_len);
+ if (ret != KNOT_EOK || !pkt_sc) {
+ VERBOSE_MSG(NULL, "%s\n",
+ "got malformed DNS cookie or server cookie missing");
+ return false;
+ }
+ assert(pkt_cc_len == KNOT_OPT_COOKIE_CLNT);
+
+ /* Check server address against received client cookie. */
+ const struct sockaddr *srvr_sockaddr = passed_server_sockaddr(req);
+ ret = srvr_sockaddr_cc_check(srvr_sockaddr, pkt_cc, pkt_cc_len,
+ clnt_sett);
+ if (ret < 0) {
+ VERBOSE_MSG(NULL, "%s\n", "could not match received cookie");
+ return false;
+ }
+ assert(srvr_sockaddr);
+
+ /* Don't cache received cookies that don't match the current secret. */
+ if ((ret == 1) &&
+ !is_cookie_cached(cache, srvr_sockaddr, pkt_cookie_opt)) {
+ ret = kr_cookie_lru_set(cache, srvr_sockaddr, pkt_cookie_opt);
+ if (ret != kr_ok()) {
+ VERBOSE_MSG(NULL, "%s\n", "failed caching cookie");
+ } else {
+ VERBOSE_MSG(NULL, "%s\n", "cookie cached");
+ }
+ }
+
+ return true;
+}
+
+/** Process incoming response. */
+int check_response(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ struct kr_cookie_ctx *cookie_ctx = &req->ctx->cookie_ctx;
+
+ if (ctx->state & (KR_STATE_DONE | KR_STATE_FAIL)) {
+ return ctx->state;
+ }
+
+ if (!cookie_ctx->clnt.enabled || (qry->flags.TCP)) {
+ return ctx->state;
+ }
+
+ /* Obtain cookie if present in response. Don't check actual content. */
+ uint8_t *pkt_cookie_opt = NULL;
+ if (knot_pkt_has_edns(pkt)) {
+ pkt_cookie_opt = knot_edns_get_option(pkt->opt_rr,
+ KNOT_EDNS_OPTION_COOKIE);
+ }
+
+ kr_cookie_lru_t *cookie_cache = req->ctx->cache_cookie;
+
+ const struct sockaddr *srvr_sockaddr = passed_server_sockaddr(req);
+
+ if (!pkt_cookie_opt && srvr_sockaddr &&
+ get_cookie_opt(cookie_cache, srvr_sockaddr)) {
+ /* We haven't received any cookies although we should. */
+ VERBOSE_MSG(NULL, "%s\n",
+ "expected to receive a cookie but none received");
+ return KR_STATE_FAIL;
+ }
+
+ if (!pkt_cookie_opt) {
+ /* Don't do anything if no cookies expected and received. */
+ return ctx->state;
+ }
+
+ if (!check_cookie_content_and_cache(&cookie_ctx->clnt, req,
+ pkt_cookie_opt, cookie_cache)) {
+ return KR_STATE_FAIL;
+ }
+
+ uint16_t rcode = knot_pkt_ext_rcode(pkt);
+ if (rcode == KNOT_RCODE_BADCOOKIE) {
+ struct kr_query *next = NULL;
+ if (!(qry->flags.BADCOOKIE_AGAIN)) {
+ /* Received first BADCOOKIE, regenerate query. */
+ next = kr_rplan_push(&req->rplan, qry->parent,
+ qry->sname, qry->sclass,
+ qry->stype);
+ }
+
+ if (next) {
+ VERBOSE_MSG(NULL, "%s\n", "BADCOOKIE querying again");
+ qry->flags.BADCOOKIE_AGAIN = true;
+ } else {
+ /*
+ * Either the planning of the second request failed or
+ * BADCOOKIE received for the second time.
+ *
+ * RFC7873 5.3 says that TCP should be used. Currently
+ * we always expect that the server doesn't support TCP.
+ */
+ qry->flags.BADCOOKIE_AGAIN = false;
+ return KR_STATE_FAIL;
+ }
+
+ return KR_STATE_CONSUME;
+ }
+
+ return ctx->state;
+}
+
+static inline uint8_t *req_cookie_option(struct kr_request *req)
+{
+ if (!req || !req->qsource.opt) {
+ return NULL;
+ }
+
+ return knot_edns_get_option(req->qsource.opt, KNOT_EDNS_OPTION_COOKIE);
+}
+
+/**
+ * @brief Returns resolver state and sets answer RCODE on missing or invalid
+ * server cookie.
+ *
+ * @note Caller should exit when only KR_STATE_FAIL is returned.
+ *
+ * @param state original resolver state
+ * @param sc_present true if server cookie is present
+ * @param ignore_badcookie true if bad cookies should be treated as good ones
+ * @param req request context
+ * @return new resolver state
+ */
+static int invalid_sc_status(int state, bool sc_present, bool ignore_badcookie,
+ const struct kr_request *req, knot_pkt_t *answer)
+{
+ assert(req && answer);
+
+ const knot_pkt_t *pkt = req->qsource.packet;
+
+ if (!pkt) {
+ return KR_STATE_FAIL;
+ }
+
+ if (knot_wire_get_qdcount(pkt->wire) == 0) {
+ /* RFC7873 5.4 */
+ state = KR_STATE_DONE;
+ if (sc_present) {
+ kr_pkt_set_ext_rcode(answer, KNOT_RCODE_BADCOOKIE);
+ state |= KR_STATE_FAIL;
+ }
+ } else if (!ignore_badcookie) {
+ /* Generate BADCOOKIE response. */
+ VERBOSE_MSG(NULL, "%s\n",
+ !sc_present ? "request is missing server cookie" :
+ "request has invalid server cookie");
+ if (!knot_pkt_has_edns(answer)) {
+ VERBOSE_MSG(NULL, "%s\n",
+ "missing EDNS section in prepared answer");
+ /* Caller should exit on this (and only this) state. */
+ return KR_STATE_FAIL;
+ }
+ kr_pkt_set_ext_rcode(answer, KNOT_RCODE_BADCOOKIE);
+ state = KR_STATE_FAIL | KR_STATE_DONE;
+ }
+
+ return state;
+}
+
+int check_request(kr_layer_t *ctx)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_cookie_settings *srvr_sett = &req->ctx->cookie_ctx.srvr;
+
+ if (!srvr_sett->enabled) {
+ return ctx->state;
+ }
+
+ knot_pkt_t *answer = req->answer;
+
+ if (ctx->state & (KR_STATE_DONE | KR_STATE_FAIL)) {
+ return ctx->state;
+ }
+
+ if (!srvr_sett->enabled) {
+ if (knot_pkt_has_edns(answer)) {
+ /* Delete any cookies. */
+ knot_edns_remove_options(answer->opt_rr,
+ KNOT_EDNS_OPTION_COOKIE);
+ }
+ return ctx->state;
+ }
+
+ uint8_t *req_cookie_opt = req_cookie_option(req);
+ if (!req_cookie_opt) {
+ return ctx->state; /* Don't do anything without cookies. */
+ }
+
+ struct knot_dns_cookies cookies;
+ memset(&cookies, 0, sizeof(cookies));
+ int ret = kr_parse_cookie_opt(req_cookie_opt, &cookies);
+ if (ret != kr_ok()) {
+ /* FORMERR -- malformed cookies. */
+ VERBOSE_MSG(NULL, "%s\n", "request with malformed cookie");
+ knot_wire_set_rcode(answer->wire, KNOT_RCODE_FORMERR);
+ return KR_STATE_FAIL | KR_STATE_DONE;
+ }
+
+ /*
+ * RFC7873 5.2.3 and 5.2.4 suggest that queries with invalid or
+ * missing server cookies can be treated like normal.
+ * Right now bad cookies are always ignored (i.e. treated as valid).
+ */
+ bool ignore_badcookie = true;
+
+ const struct knot_sc_alg *current_sc_alg = kr_sc_alg_get(srvr_sett->current.alg_id);
+
+ if (!req->qsource.addr || !srvr_sett->current.secr || !current_sc_alg) {
+ VERBOSE_MSG(NULL, "%s\n", "missing valid server cookie context");
+ return KR_STATE_FAIL;
+ }
+
+ int return_state = ctx->state;
+
+ struct knot_sc_private srvr_data = {
+ .clnt_sockaddr = req->qsource.addr,
+ .secret_data = srvr_sett->current.secr->data,
+ .secret_len = srvr_sett->current.secr->size
+ };
+
+ struct knot_sc_input sc_input = {
+ .cc = cookies.cc,
+ .cc_len = cookies.cc_len,
+ /* Don't set nonce here. */
+ .srvr_data = &srvr_data
+ };
+
+ struct kr_nonce_input nonce = {
+ .rand = kr_rand_bytes(sizeof(nonce.rand)),
+ .time = req->current_query->timestamp.tv_sec
+ };
+
+ if (!cookies.sc) {
+ /* Request has no server cookie. */
+ return_state = invalid_sc_status(return_state, false,
+ ignore_badcookie, req, answer);
+ if (return_state == KR_STATE_FAIL) {
+ return return_state;
+ }
+ goto answer_add_cookies;
+ }
+
+ /* Check server cookie obtained in request. */
+
+ ret = knot_sc_check(KR_NONCE_LEN, &cookies, &srvr_data, current_sc_alg);
+ if (ret == KNOT_EINVAL && srvr_sett->recent.secr) {
+ const struct knot_sc_alg *recent_sc_alg = kr_sc_alg_get(srvr_sett->recent.alg_id);
+ if (recent_sc_alg) {
+ /* Try recent algorithm. */
+ struct knot_sc_private recent_srvr_data = {
+ .clnt_sockaddr = req->qsource.addr,
+ .secret_data = srvr_sett->recent.secr->data,
+ .secret_len = srvr_sett->recent.secr->size
+ };
+ ret = knot_sc_check(KR_NONCE_LEN, &cookies,
+ &recent_srvr_data, recent_sc_alg);
+ }
+ }
+ if (ret != KNOT_EOK) {
+ /* Invalid server cookie. */
+ return_state = invalid_sc_status(return_state, true,
+ ignore_badcookie, req, answer);
+ if (return_state == KR_STATE_FAIL) {
+ return return_state;
+ }
+ goto answer_add_cookies;
+ }
+
+ /* Server cookie is OK. */
+
+answer_add_cookies:
+ /* Add server cookie into response. */
+ ret = kr_answer_write_cookie(&sc_input, &nonce, current_sc_alg, answer);
+ if (ret != kr_ok()) {
+ return_state = KR_STATE_FAIL;
+ }
+ return return_state;
+}
+
+#undef VERBOSE_MSG
diff --git a/modules/cookies/cookiemonster.h b/modules/cookies/cookiemonster.h
new file mode 100644
index 0000000..ef269e7
--- /dev/null
+++ b/modules/cookies/cookiemonster.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <libknot/packet/pkt.h>
+
+#include "lib/layer.h"
+
+/** Checks cookies of inbound requests. It's for kr_layer_api_t::begin. */
+int check_request(kr_layer_t *ctx);
+
+/** Checks cookies of received responses. It's for kr_layer_api_t::consume. */
+int check_response(kr_layer_t *ctx, knot_pkt_t *pkt);
diff --git a/modules/cookies/cookies.c b/modules/cookies/cookies.c
new file mode 100644
index 0000000..6a1db4f
--- /dev/null
+++ b/modules/cookies/cookies.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2016-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+
+#include "daemon/engine.h"
+#include "lib/layer.h"
+#include "modules/cookies/cookiectl.h"
+#include "modules/cookies/cookiemonster.h"
+
+/**
+ * Get/set DNS cookie related stuff.
+ *
+ * Input: { name: value, ... }
+ * Output: current configuration
+ */
+static char *cookies_config(void *env, struct kr_module *module,
+ const char *args)
+{
+ struct kr_cookie_ctx *cookie_ctx = module->data;
+ assert(cookie_ctx);
+
+ /* Apply configuration, if any. */
+ config_apply(cookie_ctx, args);
+
+ /* Return current configuration. */
+ return config_read(cookie_ctx);
+}
+
+/*
+ * Module implementation.
+ */
+
+KR_EXPORT
+int cookies_init(struct kr_module *module)
+{
+ struct engine *engine = module->data;
+
+ struct kr_cookie_ctx *cookie_ctx = &engine->resolver.cookie_ctx;
+
+ int ret = config_init(cookie_ctx);
+ if (ret != kr_ok()) {
+ return ret;
+ }
+
+ /* Replace engine pointer. */
+ module->data = cookie_ctx;
+
+ return kr_ok();
+}
+
+KR_EXPORT
+int cookies_deinit(struct kr_module *module)
+{
+ struct kr_cookie_ctx *cookie_ctx = module->data;
+
+ config_deinit(cookie_ctx);
+
+ return kr_ok();
+}
+
+KR_EXPORT
+const kr_layer_api_t *cookies_layer(struct kr_module *module)
+{
+ /* The function answer_finalize() in resolver is called before any
+ * .finish callback. Therefore this layer does not use it. */
+
+ static kr_layer_api_t _layer = {
+ .begin = &check_request,
+ .consume = &check_response
+ };
+ /* Store module reference */
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_EXPORT
+struct kr_prop *cookies_props(void)
+{
+ static struct kr_prop prop_list[] = {
+ { &cookies_config, "config", "Empty value to return current configuration.", },
+ { NULL, NULL, NULL }
+ };
+ return prop_list;
+}
+
+KR_MODULE_EXPORT(cookies)
diff --git a/modules/cookies/cookies.mk b/modules/cookies/cookies.mk
new file mode 100644
index 0000000..31d2120
--- /dev/null
+++ b/modules/cookies/cookies.mk
@@ -0,0 +1,8 @@
+cookies_CFLAGS := -fPIC
+cookies_SOURCES := \
+ modules/cookies/cookiectl.c \
+ modules/cookies/cookiemonster.c \
+ modules/cookies/cookies.c
+cookies_DEPEND := $(libkres)
+cookies_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS)
+$(call make_c_module,cookies)
diff --git a/modules/daf/README.rst b/modules/daf/README.rst
new file mode 100644
index 0000000..24ca504
--- /dev/null
+++ b/modules/daf/README.rst
@@ -0,0 +1,137 @@
+.. _mod-daf:
+
+DNS Application Firewall
+------------------------
+
+This module is a high-level interface for other powerful filtering modules and DNS views. It provides an easy interface to apply and monitor DNS filtering rules and a persistent memory for them. It also provides a restful service interface and an HTTP interface.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+Firewall rules are declarative and consist of filters and actions. Filters have ``field operator operand`` notation (e.g. ``qname = example.com``), and may be chained using AND/OR keywords. Actions may or may not have parameters after the action name.
+
+.. code-block:: lua
+
+ -- Let's write some daft rules!
+ modules = { 'daf' }
+
+ -- Block all queries with QNAME = example.com
+ daf.add 'qname = example.com deny'
+
+ -- Filters can be combined using AND/OR...
+ -- Block all queries with QNAME match regex and coming from given subnet
+ daf.add 'qname ~ %w+.example.com AND src = 192.0.2.0/24 deny'
+
+ -- We also can reroute addresses in response to alternate target
+ -- This reroutes 1.2.3.4 to localhost
+ daf.add 'src = 127.0.0.0/8 reroute 192.0.2.1-127.0.0.1'
+
+ -- Subnets work too, this reroutes a whole subnet
+ -- e.g. 192.0.2.55 to 127.0.0.55
+ daf.add 'src = 127.0.0.0/8 reroute 192.0.2.0/24-127.0.0.0'
+
+ -- This rewrites all A answers for 'example.com' from
+ -- whatever the original address was to 127.0.0.2
+ daf.add 'src = 127.0.0.0/8 rewrite example.com A 127.0.0.2'
+
+ -- Mirror queries matching given name to DNS logger
+ daf.add 'qname ~ %w+.example.com mirror 127.0.0.2'
+ daf.add 'qname ~ example-%d.com mirror 127.0.0.3@5353'
+
+ -- Forward queries from subnet
+ daf.add 'src = 127.0.0.1/8 forward 127.0.0.1@5353'
+ -- Forward to multiple targets
+ daf.add 'src = 127.0.0.1/8 forward 127.0.0.1@5353,127.0.0.2@5353'
+
+ -- Truncate queries based on destination IPs
+ daf.add 'dst = 192.0.2.51 truncate'
+
+ -- Disable a rule
+ daf.disable 2
+ -- Enable a rule
+ daf.enable 2
+ -- Delete a rule
+ daf.del 2
+
+If you're not sure what firewall rules are in effect, see ``daf.rules``:
+
+.. code-block:: text
+
+ -- Show active rules
+ > daf.rules
+ [1] => {
+ [rule] => {
+ [count] => 42
+ [id] => 1
+ [cb] => function: 0x1a3eda38
+ }
+ [info] => qname = example.com AND src = 127.0.0.1/8 deny
+ [policy] => function: 0x1a3eda38
+ }
+ [2] => {
+ [rule] => {
+ [suspended] => true
+ [count] => 123522
+ [id] => 2
+ [cb] => function: 0x1a3ede88
+ }
+ [info] => qname ~ %w+.facebook.com AND src = 127.0.0.1/8 deny...
+ [policy] => function: 0x1a3ede88
+ }
+
+Web interface
+^^^^^^^^^^^^^
+
+If you have :ref:`HTTP/2 <mod-http>` loaded, the firewall automatically loads as a snippet.
+You can create, track, suspend and remove firewall rules from the web interface.
+If you load both modules, you have to load `daf` after `http`.
+
+RESTful interface
+^^^^^^^^^^^^^^^^^
+
+The module also exports a RESTful API for operations over rule chains.
+
+
+.. csv-table::
+ :header: "URL", "HTTP Verb", "Action"
+
+ "/daf", "GET", "Return JSON list of active rules."
+ "/daf", "POST", "Insert new rule, rule string is expected in body. Returns rule information in JSON."
+ "/daf/<id>", "GET", "Retrieve a rule matching given ID."
+ "/daf/<id>", "DELETE", "Delete a rule matching given ID."
+ "/daf/<id>/<prop>/<val>", "PATCH", "Modify given rule, for example /daf/3/active/false suspends rule 3."
+
+This interface is used by the web interface for all operations, but you can also use it directly
+for testing.
+
+.. code-block:: bash
+
+ # Get current rule set
+ $ curl -s -X GET http://localhost:8053/daf | jq .
+ {}
+
+ # Create new rule
+ $ curl -s -X POST -d "src = 127.0.0.1 pass" http://localhost:8053/daf | jq .
+ {
+ "count": 0,
+ "active": true,
+ "info": "src = 127.0.0.1 pass",
+ "id": 1
+ }
+
+ # Disable rule
+ $ curl -s -X PATCH http://localhost:8053/daf/1/active/false | jq .
+ true
+
+ # Retrieve a rule information
+ $ curl -s -X GET http://localhost:8053/daf/1 | jq .
+ {
+ "count": 4,
+ "active": true,
+ "info": "src = 127.0.0.1 pass",
+ "id": 1
+ }
+
+ # Delete a rule
+ $ curl -s -X DELETE http://localhost:8053/daf/1 | jq .
+ true
diff --git a/modules/daf/daf.js b/modules/daf/daf.js
new file mode 100644
index 0000000..a614118
--- /dev/null
+++ b/modules/daf/daf.js
@@ -0,0 +1,294 @@
+/* Filter grammar */
+const dafg = {
+ key: {'qname': true, 'src': true, 'dst': true},
+ op: {'=': true, '~': true},
+ conj: {'and': true, 'or': true},
+ action: {'pass': true, 'deny': true, 'drop': true, 'truncate': true, 'forward': true, 'reroute': true, 'rewrite': true, 'mirror': true},
+ suggest: [
+ 'QNAME = example.com',
+ 'QNAME ~ %d+.example.com',
+ 'SRC = 127.0.0.1',
+ 'SRC = 127.0.0.1/8',
+ 'DST = 127.0.0.1',
+ 'DST = 127.0.0.1/8',
+ /* Action examples */
+ 'PASS', 'DENY', 'DROP', 'TRUNCATE',
+ 'FORWARD 127.0.0.1',
+ 'MIRROR 127.0.0.1',
+ 'REROUTE 127.0.0.1-192.168.1.1',
+ 'REROUTE 127.0.0.1/24-192.168.1.0',
+ 'REWRITE example.com A 127.0.0.1',
+ 'REWRITE example.com AAAA ::1',
+ ]
+};
+
+function setValidateHint(cls) {
+ var builderForm = $('#daf-builder-form');
+ builderForm.removeClass('has-error has-warning has-success');
+ if (cls) {
+ builderForm.addClass(cls);
+ }
+}
+
+function validateToken(tok, tbl) {
+ if (tok.length > 0 && tok[0].length > 0) {
+ if (tbl[tok[0].toLowerCase()]) {
+ setValidateHint('has-success');
+ return true;
+ } else { setValidateHint('has-error'); }
+ } else { setValidateHint('has-warning'); }
+ return false;
+}
+
+function parseOption(tok) {
+ var key = tok.shift().toLowerCase();
+ var op = null;
+ if (dafg.key[key]) {
+ op = tok.shift();
+ if (op) {
+ op = op.toLowerCase();
+ }
+ }
+ const item = {
+ text: key.toUpperCase() + ' ' + (op ? op.toUpperCase() : '') + ' ' + tok.join(' '),
+ };
+ if (dafg.key[key]) {
+ item.class = 'tag-default';
+ } else if (dafg.action[key]) {
+ item.class = 'tag-warning';
+ } else if (dafg.conj[key]) {
+ item.class = 'tag-success';
+ }
+ return item;
+}
+
+function createOption(input) {
+ const item = parseOption(input.split(' '));
+ item.value = input;
+ return item;
+}
+
+function dafComplete(form) {
+ const items = form.items;
+ for (var i in items) {
+ const tok = items[i].split(' ')[0].toLowerCase();
+ if (dafg.action[tok]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function formatRule(input) {
+ const tok = input.split(' ');
+ var res = [];
+ while (tok.length > 0) {
+ const key = tok.shift().toLowerCase();
+ if (dafg.key[key]) {
+ var item = parseOption([key, tok.shift(), tok.shift()]);
+ res.push('<span class="label tag '+item.class+'">'+item.text+'</span>');
+ } else if (dafg.action[key]) {
+ var item = parseOption([key].concat(tok));
+ res.push('<span class="label tag '+item.class+'">'+item.text+'</span>');
+ tok.splice(0, tok.length);
+ } else if (dafg.conj[key]) {
+ var item = parseOption([key]);
+ res.push('<span class="label tag '+item.class+'">'+item.text+'</span>');
+ }
+ }
+ return res.join('');
+}
+
+function toggleRule(row, span, enabled) {
+ if (!enabled) {
+ span.removeClass('glyphicon-pause');
+ span.addClass('glyphicon-play');
+ row.addClass('warning');
+ } else {
+ span.removeClass('glyphicon-play');
+ span.addClass('glyphicon-pause');
+ row.removeClass('warning');
+ }
+}
+
+function ruleControl(cell, type, url, action) {
+ const row = cell.parent();
+ $.ajax({
+ url: 'daf/' + row.data('rule-id') + url,
+ type: type,
+ success: action,
+ fail: function (data) {
+ row.show();
+ const reason = data.responseText.length > 0 ? data.responseText : 'internal error';
+ cell.find('.alert').remove();
+ cell.append(
+ '<div class="alert alert-danger" role="alert">'+
+ 'Failed (code: '+data.status+', reason: '+reason+').'+
+ '</div>'
+ );
+ },
+ });
+}
+
+function bindRuleControl(cell) {
+ const row = cell.parent();
+ cell.find('.daf-remove').click(function() {
+ row.hide();
+ ruleControl(cell, 'DELETE', '', function (data) {
+ cell.parent().remove();
+ });
+ });
+ cell.find('.daf-suspend').click(function() {
+ const span = $(this).find('span');
+ ruleControl(cell, 'PATCH', span.hasClass('glyphicon-pause') ? '/active/false' : '/active/true');
+ toggleRule(row, span, span.hasClass('glyphicon-play'));
+ });
+}
+
+function loadRule(rule, tbl) {
+ const row = $('<tr data-rule-id="'+rule.id+'" />');
+ row.append('<td class="daf-rule">' + formatRule(rule.info) + '</td>');
+ row.append('<td class="daf-count">' + rule.count + '</td>');
+ row.append('<td class="daf-rate"><span class="badge"></span></td>');
+ row.append('<td class="daf-ctl text-right">' +
+ '<div class="btn-group btn-group-xs">' +
+ '<button class="btn btn-default daf-suspend"><span class="glyphicon" aria="hidden" /></button>' +
+ '<button class="btn btn-default daf-remove"><span class="glyphicon glyphicon-remove" aria="hidden" /></button>' +
+ '</div></td>');
+ tbl.append(row);
+ /* Bind rule controls */
+ bindRuleControl(row.find('.daf-ctl'));
+ toggleRule(row, row.find('.daf-suspend span'), rule.active);
+}
+
+/* Load the filter table from JSON */
+function loadTable(resp) {
+ const tbl = $('#daf-rules')
+ tbl.children().remove();
+ tbl.append('<tr><th>Rule</th><th>Matches</th><th>Rate</th><th></th></tr>')
+ for (var i in resp) {
+ loadRule(resp[i], tbl);
+ }
+}
+
+$(function() {
+ /* Load the filter table. */
+ $.ajax({
+ url: 'daf',
+ type: 'get',
+ dataType: 'json',
+ success: loadTable
+ });
+ /* Listen for counter updates */
+ const wsStats = (secure ? 'wss://' : 'ws://') + location.host + '/daf';
+ const ws = new Socket(wsStats);
+ var lastRateUpdate = Date.now();
+ ws.onmessage = function(evt) {
+ var data = JSON.parse(evt.data);
+ /* Update heartbeat clock */
+ var now = Date.now();
+ var dt = now - lastRateUpdate;
+ lastRateUpdate = now;
+ /* Update match counts and rates */
+ $('#daf-rules .daf-rate span').text('');
+ for (var key in data) {
+ const row = $('tr[data-rule-id="'+key+'"]');
+ if (row) {
+ const cell = row.find('.daf-count');
+ const diff = data[key] - parseInt(cell.text());
+ cell.text(data[key]);
+ const badge = row.find('.daf-rate span');
+ if (diff > 0) {
+ /* Normalize difference to heartbeat (in msecs) */
+ const rate = Math.ceil((1000 * diff) / dt);
+ badge.text(rate + ' pps');
+ }
+ }
+ }
+ };
+ /* Rule builder UI */
+ $('#daf-builder').selectize({
+ delimiter: ',',
+ persist: true,
+ highlight: true,
+ closeAfterSelect: true,
+ onItemAdd: function (input, item) {
+ setValidateHint();
+ /* Prevent new rules when action is specified */
+ const tok = input.split(' ');
+ if (dafg.action[tok[0].toLowerCase()]) {
+ $('#daf-add').focus();
+ } else if(dafComplete(this)) {
+ /* No more rules after query is complete. */
+ item.remove();
+ }
+ },
+ createFilter: function (input) {
+ const tok = input.split(' ');
+ var key, op, expr;
+ /* If there are already filters, allow conjunctions. */
+ if (tok.length > 0 && this.items.length > 0 && dafg.conj[tok[0]]) {
+ setValidateHint();
+ return true;
+ }
+ /* First token is expected to be filter key,
+ * or any postrule with a parameter */
+ if (validateToken(tok, dafg.key)) {
+ key = tok.shift();
+ } else if (tok.length > 1 && validateToken(tok, dafg.action)) {
+ setValidateHint();
+ return true;
+ } else {
+ return false;
+ }
+ /* Input is a filter - second token must be operator */
+ if (validateToken(tok, dafg.op)) {
+ op = tok.shift();
+ } else {
+ return false;
+ }
+ /* Input is a filter - the rest of the tokens are RHS arguments. */
+ if (tok.length > 0 && tok[0].length > 0) {
+ expr = tok.join(' ');
+ } else {
+ setValidateHint('has-warning');
+ return false;
+ }
+ setValidateHint('has-success');
+ return true;
+ },
+ create: createOption,
+ render: {
+ item: function(item, escape) {
+ return '<div class="name '+item.class+'">' + escape(item.text) + '</span>';
+ },
+ },
+ });
+ /* Add default suggestions. */
+ const dafBuilder = $('#daf-builder')[0].selectize;
+ for (var i in dafg.suggest) {
+ dafBuilder.addOption(createOption(dafg.suggest[i]));
+ }
+ /* Rule builder submit */
+ $('#daf-add').click(function () {
+ const form = $('#daf-builder-form').parent();
+ if (dafBuilder.items.length == 0 || form.hasClass('has-error')) {
+ return;
+ }
+ /* Clear previous errors and resubmit. */
+ form.parent().find('.alert').remove();
+ $.post('daf', dafBuilder.items.join(' '))
+ .done(function (data) {
+ dafBuilder.clear();
+ loadRule(data, $('#daf-rules'));
+ })
+ .fail(function (data) {
+ const reason = data.responseText.length > 0 ? data.responseText : 'internal error';
+ form.after(
+ '<div class="alert alert-danger" role="alert">'+
+ 'Couldn\'t add rule (code: '+data.status+', reason: '+reason+').'+
+ '</div>'
+ );
+ });
+ });
+}); \ No newline at end of file
diff --git a/modules/daf/daf.lua b/modules/daf/daf.lua
new file mode 100644
index 0000000..28b6342
--- /dev/null
+++ b/modules/daf/daf.lua
@@ -0,0 +1,353 @@
+-- Load dependent modules
+if not view then modules.load('view') end
+if not policy then modules.load('policy') end
+
+-- Actions
+local actions = {
+ pass = 1, deny = 2, drop = 3, tc = 4, truncate = 4,
+ forward = function (g)
+ local addrs = {}
+ local tok = g()
+ for addr in string.gmatch(tok, '[^,]+') do
+ table.insert(addrs, addr)
+ end
+ return policy.FORWARD(addrs)
+ end,
+ mirror = function (g)
+ return policy.MIRROR(g())
+ end,
+ reroute = function (g)
+ local rules = {}
+ local tok = g()
+ while tok do
+ local from, to = tok:match '([^-]+)-(%S+)'
+ rules[from] = to
+ tok = g()
+ end
+ return policy.REROUTE(rules)
+ end,
+ rewrite = function (g)
+ local rules = {}
+ local tok = g()
+ while tok do
+ -- This is currently limited to A/AAAA rewriting
+ -- in fixed format '<owner> <type> <addr>'
+ local _, to = g(), g()
+ rules[tok] = to
+ tok = g()
+ end
+ return policy.REROUTE(rules, true)
+ end,
+}
+
+-- Filter rules per column
+local filters = {
+ -- Filter on QNAME (either pattern or suffix match)
+ qname = function (g)
+ local op, val = g(), todname(g())
+ if op == '~' then return policy.pattern(true, val:sub(2)) -- Skip leading label length
+ elseif op == '=' then return policy.suffix(true, {val})
+ else error(string.format('invalid operator "%s" on qname', op)) end
+ end,
+ -- Filter on source address
+ src = function (g)
+ local op = g()
+ if op ~= '=' then error('address supports only "=" operator') end
+ return view.rule_src(true, g())
+ end,
+ -- Filter on destination address
+ dst = function (g)
+ local op = g()
+ if op ~= '=' then error('address supports only "=" operator') end
+ return view.rule_dst(true, g())
+ end,
+}
+
+local function parse_filter(tok, g, prev)
+ if not tok then error(string.format('expected filter after "%s"', prev)) end
+ local filter = filters[tok:lower()]
+ if not filter then error(string.format('invalid filter "%s"', tok)) end
+ return filter(g)
+end
+
+local function parse_rule(g)
+ -- Allow action without filter
+ local tok = g()
+ if not filters[tok:lower()] then
+ return tok, nil
+ end
+ local f = parse_filter(tok, g)
+ -- Compose filter functions on conjunctions
+ -- or terminate filter chain and return
+ tok = g()
+ while tok do
+ if tok:lower() == 'and' then
+ local fa, fb = f, parse_filter(g(), g, tok)
+ f = function (req, qry) return fa(req, qry) and fb(req, qry) end
+ elseif tok:lower() == 'or' then
+ local fa, fb = f, parse_filter(g(), g, tok)
+ f = function (req, qry) return fa(req, qry) or fb(req, qry) end
+ else
+ break
+ end
+ tok = g()
+ end
+ return tok, f
+end
+
+local function parse_query(g)
+ local ok, actid, filter = pcall(parse_rule, g)
+ if not ok then return nil, actid end
+ actid = actid:lower()
+ if not actions[actid] then return nil, string.format('invalid action "%s"', actid) end
+ -- Parse and interpret action
+ local action = actions[actid]
+ if type(action) == 'function' then
+ action = action(g)
+ end
+ return actid, action, filter
+end
+
+-- Compile a rule described by query language
+-- The query language is modelled by iptables/nftables
+-- conj = AND | OR
+-- op = IS | NOT | LIKE | IN
+-- filter = <key> <op> <expr>
+-- rule = <filter> | <filter> <conj> <rule>
+-- action = PASS | DENY | DROP | TC | FORWARD
+-- query = <rule> <action>
+local function compile(query)
+ local g = string.gmatch(query, '%S+')
+ return parse_query(g)
+end
+
+-- @function Describe given rule for presentation
+local function rule_info(r)
+ return {info=r.info, id=r.rule.id, active=(r.rule.suspended ~= true), count=r.rule.count}
+end
+
+-- Module declaration
+local M = {
+ rules = {}
+}
+
+-- @function Remove a rule
+
+-- @function Cleanup module
+function M.deinit()
+ if http and http.endpoints then
+ http.endpoints['/daf'] = nil
+ http.endpoints['/daf.js'] = nil
+ http.snippets['/daf'] = nil
+ end
+end
+
+-- @function Add rule
+function M.add(rule)
+ -- Ignore duplicates
+ for _, r in ipairs(M.rules) do
+ if r.info == rule then return r end
+ end
+ local id, action, filter = compile(rule)
+ if not id then error(action) end
+ -- Combine filter and action into policy
+ local p
+ if filter then
+ p = function (req, qry)
+ return filter(req, qry) and action
+ end
+ else
+ p = function ()
+ return action
+ end
+ end
+ local desc = {info=rule, policy=p}
+ -- Enforce in policy module, special actions are postrules
+ if id == 'reroute' or id == 'rewrite' then
+ desc.rule = policy.add(p, true)
+ else
+ desc.rule = policy.add(p)
+ end
+ table.insert(M.rules, desc)
+ return desc
+end
+
+-- @function Remove a rule
+function M.del(id)
+ for _, r in ipairs(M.rules) do
+ if r.rule.id == id then
+ policy.del(id)
+ table.remove(M.rules, id)
+ return true
+ end
+ end
+end
+
+-- @function Find a rule
+function M.get(id)
+ for _, r in ipairs(M.rules) do
+ if r.rule.id == id then
+ return r
+ end
+ end
+end
+
+-- @function Enable/disable a rule
+function M.toggle(id, val)
+ for _, r in ipairs(M.rules) do
+ if r.rule.id == id then
+ r.rule.suspended = not val
+ return true
+ end
+ end
+end
+
+-- @function Enable/disable a rule
+function M.disable(id)
+ return M.toggle(id, false)
+end
+function M.enable(id)
+ return M.toggle(id, true)
+end
+
+local function consensus(op, ...)
+ local ret = true
+ local results = map(string.format(op, ...))
+ for _, r in ipairs(results) do
+ ret = ret and r
+ end
+ return ret
+end
+
+-- @function Public-facing API
+local function api(h, stream)
+ local m = h:get(':method')
+ -- GET method
+ if m == 'GET' then
+ local path = h:get(':path')
+ local id = tonumber(path:match '/([^/]*)$')
+ if id then
+ local r = M.get(id)
+ if r then
+ return rule_info(r)
+ end
+ return 404, '"No such rule"' -- Not found
+ else
+ local ret = {}
+ for _, r in ipairs(M.rules) do
+ table.insert(ret, rule_info(r))
+ end
+ return ret
+ end
+ -- DELETE method
+ elseif m == 'DELETE' then
+ local path = h:get(':path')
+ local id = tonumber(path:match '/([^/]*)$')
+ if id then
+ if consensus('daf.del "%s"', id) then
+ return tojson(true)
+ end
+ return 404, '"No such rule"' -- Not found
+ end
+ return 400 -- Request doesn't have numeric id
+ -- POST method
+ elseif m == 'POST' then
+ local query = stream:get_body_as_string()
+ if query then
+ local ok, r = pcall(M.add, query)
+ if not ok then return 500, string.format('"%s"', r:match('/([^/]+)$')) end
+ -- Dispatch to all other workers
+ consensus('daf.add "%s"', query)
+ return rule_info(r)
+ end
+ return 400
+ -- PATCH method
+ elseif m == 'PATCH' then
+ local path = h:get(':path')
+ local id, action, val = path:match '(%d+)/([^/]*)/([^/]*)$'
+ id = tonumber(id)
+ if not id or not action or not val then
+ return 400 -- Request not well formatted
+ end
+ -- We do not support more actions
+ if action == 'active' then
+ if consensus('daf.toggle(%d, %s)', id, val == 'true' or 'false') then
+ return tojson(true)
+ else
+ return 404, '"No such rule"'
+ end
+ else
+ return 501, '"Action not implemented"'
+ end
+ end
+end
+
+local function getmatches()
+ local update = {}
+ for _, rules in ipairs(map 'daf.rules') do
+ for _, r in ipairs(rules) do
+ local id = tostring(r.rule.id)
+ -- Must have string keys for JSON object and not an array
+ update[id] = (update[id] or 0) + r.rule.count
+ end
+ end
+ return update
+end
+
+-- @function Publish DAF statistics
+local function publish(_, ws)
+ local ok, last = true, nil
+ while ok do
+ -- Check if we have new rule matches
+ local diff = {}
+ local has_update, update = pcall(getmatches)
+ if has_update then
+ if last then
+ for id, count in pairs(update) do
+ if not last[id] or last[id] < count then
+ diff[id] = count
+ end
+ end
+ end
+ last = update
+ end
+ -- Update counters when there is a new data
+ if next(diff) ~= nil then
+ ok = ws:send(tojson(diff))
+ else
+ ok = ws:send_ping()
+ end
+ worker.sleep(1)
+ end
+end
+
+-- @function Configure module
+function M.config()
+ if not http or not http.endpoints then return end
+ -- Export API and data publisher
+ http.endpoints['/daf.js'] = http.page('daf.js', 'daf')
+ http.endpoints['/daf'] = {'application/json', api, publish}
+ -- Export snippet
+ http.snippets['/daf'] = {'Application Firewall', [[
+ <script type="text/javascript" src="daf.js"></script>
+ <div class="row" style="margin-bottom: 5px">
+ <form id="daf-builder-form">
+ <div class="col-md-11">
+ <input type="text" id="daf-builder" class="form-control" aria-label="..." />
+ </div>
+ <div class="col-md-1">
+ <button type="button" id="daf-add" class="btn btn-default btn-sm">Add</button>
+ </div>
+ </form>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <table id="daf-rules" class="table table-striped table-responsive">
+ <th><td>No rules here yet.</td></th>
+ </table>
+ </div>
+ </div>
+ ]]}
+end
+
+return M \ No newline at end of file
diff --git a/modules/daf/daf.mk b/modules/daf/daf.mk
new file mode 100644
index 0000000..0f02675
--- /dev/null
+++ b/modules/daf/daf.mk
@@ -0,0 +1,3 @@
+daf_SOURCES := daf.lua
+daf_INSTALL := modules/daf/daf.js
+$(call make_lua_module,daf)
diff --git a/modules/detect_time_jump/README.rst b/modules/detect_time_jump/README.rst
new file mode 100644
index 0000000..240907f
--- /dev/null
+++ b/modules/detect_time_jump/README.rst
@@ -0,0 +1,20 @@
+.. _mod-detect_time_jump:
+
+Detect discontinuous jumps in the system time
+---------------------------------------------
+
+This module detect discontinuous jumps in the system time when resolver
+is running. It clears cache when a significant backward time jumps occurs.
+
+Time jumps are usually created by NTP time change or by admin intervention.
+These change can affect cache records as they store timestamp and TTL in real
+time.
+
+If you want to preserve cache during time travel you should disable
+this module by ``modules.unload('detect_time_jump')``.
+
+Due to the way monotonic system time works on typical systems,
+suspend-resume cycles will be perceived as forward time jumps,
+but this direction of shift does not have the risk of using records
+beyond their intended TTL, so forward jumps do not cause erasing the cache.
+
diff --git a/modules/detect_time_jump/detect_time_jump.lua b/modules/detect_time_jump/detect_time_jump.lua
new file mode 100644
index 0000000..65ae060
--- /dev/null
+++ b/modules/detect_time_jump/detect_time_jump.lua
@@ -0,0 +1,44 @@
+-- Module interface
+local ffi = require('ffi')
+
+local mod = {}
+mod.threshold = 10 * min
+local event_id = nil
+
+-- Get time of last cache clear. Compute difference between realtime
+-- and monotonic time. Compute difference of actual realtime and monotonic
+-- time. In ideal case these differences should be almost same.
+-- If they differ more than mod.threshold value then clear cache.
+local function check_time()
+ local checkpoint = cache.checkpoint()
+ local cache_timeshift = checkpoint.walltime.sec * 1000 - checkpoint.monotime
+ local actual_timeshift = os.time() * 1000 - tonumber(ffi.C.kr_now())
+ local jump_backward = cache_timeshift - actual_timeshift
+ if jump_backward > mod.threshold then
+ log("Detected backwards time jump, clearing cache.\n" ..
+ "But what does that mean? It means your future hasn't been written yet."
+ )
+ cache.clear()
+ elseif -jump_backward > mod.threshold then
+ -- On Linux 4.17+ this shouldn't happen anymore: https://lwn.net/Articles/751482/
+ log("Detected forward time jump. (Suspend-resume, possibly.)")
+ cache.checkpoint(true)
+ end
+end
+
+function mod.init()
+ if event_id then
+ error("Module is already loaded.")
+ else
+ event_id = event.recurrent(1 * min , check_time)
+ end
+end
+
+function mod.deinit()
+ if event_id then
+ event.cancel(event_id)
+ event_id = nil
+ end
+end
+
+return mod
diff --git a/modules/detect_time_jump/detect_time_jump.mk b/modules/detect_time_jump/detect_time_jump.mk
new file mode 100644
index 0000000..04df607
--- /dev/null
+++ b/modules/detect_time_jump/detect_time_jump.mk
@@ -0,0 +1,2 @@
+detect_time_jump_SOURCES := detect_time_jump.lua
+$(call make_lua_module,detect_time_jump)
diff --git a/modules/detect_time_skew/README.rst b/modules/detect_time_skew/README.rst
new file mode 100644
index 0000000..8eeb2eb
--- /dev/null
+++ b/modules/detect_time_skew/README.rst
@@ -0,0 +1,21 @@
+.. _mod-detect_time_skew:
+
+System time skew detector
+-------------------------
+
+This module compares local system time with inception and expiration time
+bounds in DNSSEC signatures for ``. NS`` records. If the local system time is
+outside of these bounds, it is likely a misconfiguration which will cause
+all DNSSEC validation (and resolution) to fail.
+
+In case of mismatch, a warning message will be logged to help with
+further diagnostics.
+
+.. warning:: Information printed by this module can be forged by a network attacker!
+ System administrator MUST verify values printed by this module and
+ fix local system time using a trusted source.
+
+This module is useful for debugging purposes. It runs only once during resolver
+start does not anything after that. It is enabled by default.
+You may disable the module by appending
+``modules.unload('detect_time_skew')`` to your configuration.
diff --git a/modules/detect_time_skew/detect_time_skew.lua b/modules/detect_time_skew/detect_time_skew.lua
new file mode 100644
index 0000000..9f04c3e
--- /dev/null
+++ b/modules/detect_time_skew/detect_time_skew.lua
@@ -0,0 +1,85 @@
+-- Module interface
+local ffi = require('ffi')
+
+local mod = {}
+local event_id = nil
+
+-- Resolve callback
+-- Check time validity of RRSIGs in priming query
+-- luacheck: no unused args
+local function check_time_callback(pkt, req)
+ pkt = kres.pkt_t(pkt)
+ if pkt:rcode() ~= kres.rcode.NOERROR then
+ warn("[detect_time_skew] cannot resolve '.' NS")
+ return nil
+ end
+ local seen_rrsigs = 0
+ local valid_rrsigs = 0
+ local section = pkt:rrsets(kres.section.ANSWER)
+ local now = os.time()
+ local time_diff = 0
+ local inception = 0
+ local expiration = 0
+ for i = 1, #section do
+ local rr = section[i]
+ assert(rr.type)
+ if rr.type == kres.type.RRSIG then
+ for k = 0, rr.rrs.count - 1 do
+ seen_rrsigs = seen_rrsigs + 1
+ local rdata = rr:rdata_pt(k)
+ inception = ffi.C.kr_rrsig_sig_inception(rdata)
+ expiration = ffi.C.kr_rrsig_sig_expiration(rdata)
+ if now > expiration then
+ -- possitive value = in the future
+ time_diff = now - expiration
+ elseif now < inception then
+ -- negative value = in the past
+ time_diff = now - inception
+ else
+ valid_rrsigs = valid_rrsigs + 1
+ end
+ end
+ end
+ end
+ if seen_rrsigs == 0 then
+ if verbose() then
+ log("[detect_time_skew] No RRSIGs received! "..
+ "You really should configure DNSSEC trust anchor for the root.")
+ end
+ elseif valid_rrsigs == 0 then
+ warn("[detect_time_skew] Local system time %q seems to be at "..
+ "least %u seconds in the %s. DNSSEC signatures for '.' NS "..
+ "are not valid %s. Please check your system clock!",
+ os.date("%c", now),
+ math.abs(time_diff),
+ time_diff > 0 and "future" or "past",
+ time_diff > 0 and "yet" or "anymore")
+ elseif verbose() then
+ log("[detect_time_skew] Local system time %q is within "..
+ "RRSIG validity interval <%q,%q>.", os.date("%c", now),
+ os.date("%c", inception), os.date("%c", expiration))
+ end
+end
+
+-- Make priming query and check time validty of RRSIGs.
+local function check_time()
+ resolve(".", kres.type.NS, kres.class.IN, {"DNSSEC_WANT", "DNSSEC_CD"},
+ check_time_callback)
+end
+
+function mod.init()
+ if event_id then
+ error("Module is already loaded.")
+ else
+ event_id = event.after(0 , check_time)
+ end
+end
+
+function mod.deinit()
+ if event_id then
+ event.cancel(event_id)
+ event_id = nil
+ end
+end
+
+return mod
diff --git a/modules/detect_time_skew/detect_time_skew.mk b/modules/detect_time_skew/detect_time_skew.mk
new file mode 100644
index 0000000..bc29deb
--- /dev/null
+++ b/modules/detect_time_skew/detect_time_skew.mk
@@ -0,0 +1,2 @@
+detect_time_skew_SOURCES := detect_time_skew.lua
+$(call make_lua_module,detect_time_skew)
diff --git a/modules/dns64/README.rst b/modules/dns64/README.rst
new file mode 100644
index 0000000..047443f
--- /dev/null
+++ b/modules/dns64/README.rst
@@ -0,0 +1,26 @@
+.. _mod-dns64:
+
+DNS64
+-----
+
+The module for :rfc:`6147` DNS64 AAAA-from-A record synthesis, it is used to enable client-server communication between an IPv6-only client and an IPv4-only server. See the well written `introduction`_ in the PowerDNS documentation.
+If no address is passed (i.e. ``nil``), the well-known prefix ``64:ff9b::`` is used.
+
+.. warning:: The module currently won't work well with :ref:`policy.STUB <mod-policy>`.
+ Also, the IPv6 passed in configuration is assumed to be ``/96``, and
+ PTR synthesis and "exclusion prefixes" aren't implemented.
+
+.. tip:: The A record sub-requests will be DNSSEC secured, but the synthetic AAAA records can't be. Make sure the last mile between stub and resolver is secure to avoid spoofing.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ -- Load the module with a NAT64 address
+ modules = { dns64 = 'fe80::21b:77ff:0:0' }
+ -- Reconfigure later
+ dns64.config('fe80::21b:aabb:0:0')
+
+
+.. _introduction: https://doc.powerdns.com/md/recursor/dns64
diff --git a/modules/dns64/dns64.lua b/modules/dns64/dns64.lua
new file mode 100644
index 0000000..8e3eaa0
--- /dev/null
+++ b/modules/dns64/dns64.lua
@@ -0,0 +1,103 @@
+-- Module interface
+local ffi = require('ffi')
+local M = {}
+local addr_buf = ffi.new('char[16]')
+
+--[[
+Missing parts of the RFC:
+ > The implementation SHOULD support mapping of separate IPv4 address
+ > ranges to separate IPv6 prefixes for AAAA record synthesis. This
+ > allows handling of special use IPv4 addresses [RFC5735].
+
+ Also the exclusion prefixes are not implemented, sec. 5.1.4 (MUST).
+
+ TODO: support different prefix lengths, defaulting to /96 if not specified
+ https://tools.ietf.org/html/rfc6052#section-2.2
+
+ PTR queries aren't supported (MUST), sec. 5.3.1.2
+]]
+
+-- Config
+function M.config (confstr)
+ M.proxy = kres.str2ip(confstr or '64:ff9b::')
+ if M.proxy == nil then error('[dns64] "'..confstr..'" is not a valid address') end
+end
+
+-- Layers
+M.layer = { }
+function M.layer.consume(state, req, pkt)
+ if state == kres.FAIL then return state end
+ pkt = kres.pkt_t(pkt)
+ req = kres.request_t(req)
+ local qry = req:current()
+ -- Observe only final answers in IN class where request has no CD flag.
+ if M.proxy == nil or not qry.flags.RESOLVED
+ or pkt:qclass() ~= kres.class.IN or req.answer:cd() then
+ return state
+ end
+ -- Synthetic AAAA from marked A responses
+ local answer = pkt:section(kres.section.ANSWER)
+
+ -- Observe final AAAA NODATA responses to the current SNAME.
+ local is_nodata = pkt:rcode() == kres.rcode.NOERROR and #answer == 0
+ if pkt:qtype() == kres.type.AAAA and is_nodata and pkt:qname() == qry:name()
+ and qry.flags.RESOLVED and not qry.flags.CNAME and qry.parent == nil then
+ -- Start a *marked* corresponding A sub-query.
+ local extraFlags = kres.mk_qflags({})
+ extraFlags.DNSSEC_WANT = qry.flags.DNSSEC_WANT
+ extraFlags.AWAIT_CUT = true
+ extraFlags.DNS64_MARK = true
+ req:push(pkt:qname(), kres.type.A, kres.class.IN, extraFlags, qry)
+ return state
+ end
+
+
+ -- Observe answer to the marked sub-query, and convert all A records in ANSWER
+ -- to corresponding AAAA records to be put into the request's answer.
+ if not qry.flags.DNS64_MARK then return state end
+ -- Find rank for the NODATA answer.
+ -- That will result into corresponding AD flag. See RFC 6147 5.5.2.
+ local neg_rank
+ if qry.parent.flags.DNSSEC_WANT and not qry.parent.flags.DNSSEC_INSECURE
+ then neg_rank = ffi.C.KR_RANK_SECURE
+ else neg_rank = ffi.C.KR_RANK_INSECURE
+ end
+ -- Find TTL bound from SOA, according to RFC 6147 5.1.7.4.
+ local max_ttl = 600
+ for i = 1, tonumber(req.auth_selected.len) do
+ local entry = req.auth_selected.at[i - 1]
+ if entry.qry_uid == qry.parent.uid and entry.rr
+ and entry.rr.type == kres.type.SOA
+ and entry.rr.rclass == kres.class.IN then
+ max_ttl = entry.rr:ttl()
+ end
+ end
+ -- Find the As and do the conversion itself.
+ for i = 1, tonumber(req.answ_selected.len) do
+ local orig = req.answ_selected.at[i - 1]
+ if orig.qry_uid == qry.uid and orig.rr.type == kres.type.A then
+ local rank = neg_rank
+ if orig.rank < rank then rank = orig.rank end
+ -- Disable GC, as this object doesn't own owner or RDATA, it's just a reference
+ local ttl = orig.rr:ttl()
+ if ttl > max_ttl then ttl = max_ttl end
+ local rrs = ffi.gc(kres.rrset(nil, kres.type.AAAA, orig.rr.rclass, ttl), nil)
+ rrs._owner = orig.rr._owner
+ for k = 1, orig.rr.rrs.count do
+ local rdata = orig.rr:rdata( k - 1 )
+ ffi.copy(addr_buf, M.proxy, 12)
+ ffi.copy(addr_buf + 12, rdata, 4)
+ ffi.C.knot_rrset_add_rdata(rrs, ffi.string(addr_buf, 16), 16, req.pool)
+ end
+ ffi.C.kr_ranked_rrarray_add(
+ req.answ_selected,
+ rrs,
+ rank,
+ true,
+ qry.uid,
+ req.pool)
+ end
+ end
+end
+
+return M
diff --git a/modules/dns64/dns64.mk b/modules/dns64/dns64.mk
new file mode 100644
index 0000000..948188c
--- /dev/null
+++ b/modules/dns64/dns64.mk
@@ -0,0 +1,2 @@
+dns64_SOURCES := dns64.lua
+$(call make_lua_module,dns64)
diff --git a/modules/dns64/dns64.test.lua b/modules/dns64/dns64.test.lua
new file mode 100644
index 0000000..1798ccd
--- /dev/null
+++ b/modules/dns64/dns64.test.lua
@@ -0,0 +1,52 @@
+local condition = require('cqueues.condition')
+
+-- setup resolver
+modules = { 'hints', 'dns64' }
+hints['dns64.example'] = '192.168.1.1'
+hints.use_nodata(true) -- Respond NODATA to AAAA query
+dns64.config('fe80::21b:77ff:0:0')
+
+-- helper to wait for query resolution
+local function wait_resolve(qname, qtype)
+ local waiting, done, cond = false, false, condition.new()
+ local rcode, answers = kres.rcode.SERVFAIL, {}
+ resolve {
+ name = qname,
+ type = qtype,
+ finish = function (answer, _)
+ answer = kres.pkt_t(answer)
+ rcode = answer:rcode()
+ answers = answer:section(kres.section.ANSWER)
+ -- Signal as completed
+ if waiting then
+ cond:signal()
+ end
+ done = true
+ end,
+ }
+ -- Wait if it didn't finish immediately
+ if not done then
+ waiting = true
+ cond:wait()
+ end
+ return rcode, answers
+end
+
+-- test builtin rules
+local function test_builtin_rules()
+ local rcode, answers = wait_resolve('dns64.example', kres.type.AAAA)
+ same(rcode, kres.rcode.NOERROR, 'dns64.example returns NOERROR')
+ same(#answers, 1, 'dns64.example synthesised answer')
+ local expect = {'dns64.example.', '0', 'AAAA', 'fe80::21b:77ff:c0a8:101'}
+ if #answers > 0 then
+ local rr = {kres.rr2str(answers[1]):match('(%S+)%s+(%S+)%s+(%S+)%s+(%S+)')}
+ same(rr, expect, 'dns64.example synthesised correct AAAA record')
+ end
+end
+
+-- plan tests
+local tests = {
+ test_builtin_rules,
+}
+
+return tests \ No newline at end of file
diff --git a/modules/dnstap/README.rst b/modules/dnstap/README.rst
new file mode 100644
index 0000000..442b4cf
--- /dev/null
+++ b/modules/dnstap/README.rst
@@ -0,0 +1,24 @@
+.. _mod-dnstap:
+
+Dnstap
+------
+
+Dnstap module currently supports logging dns responses to a unix socket
+in dnstap format using fstrm framing library. The unix socket and the
+socket reader should be present before starting kresd.
+
+Configuration
+^^^^^^^^^^^^^
+Tunables:
+
+* ``socket_path``: the the unix socket file where dnstap messages will be sent
+* ``log_responses``: if true responses in wire format will be logged
+
+.. code-block:: lua
+
+ modules = {
+ dnstap = {
+ socket_path = "/tmp/dnstap.sock",
+ log_responses = true
+ }
+ }
diff --git a/modules/dnstap/dnstap.c b/modules/dnstap/dnstap.c
new file mode 100644
index 0000000..0918426
--- /dev/null
+++ b/modules/dnstap/dnstap.c
@@ -0,0 +1,382 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * @file dnstap.c
+ * @brief dnstap based query logging support
+ *
+ */
+
+#include "lib/module.h"
+#include "lib/layer.h"
+#include "lib/resolve.h"
+#include "modules/dnstap/dnstap.pb-c.h"
+#include <ccan/json/json.h>
+#include <fstrm.h>
+#include "contrib/cleanup.h"
+
+#define DEBUG_MSG(fmt, ...) kr_log_verbose("[dnstap] " fmt, ##__VA_ARGS__);
+#define CFG_SOCK_PATH "socket_path"
+#define CFG_LOG_RESP_PKT "log_responses"
+#define DEFAULT_SOCK_PATH "/tmp/dnstap.sock"
+#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap"
+#define DNSTAP_INITIAL_BUF_SIZE 256
+
+#define auto_destroy_uopts __attribute__((cleanup(fstrm_unix_writer_options_destroy)))
+#define auto_destroy_wopts __attribute__((cleanup(fstrm_writer_options_destroy)))
+
+/* Internal data structure */
+struct dnstap_data {
+ bool log_resp_pkt;
+ struct fstrm_iothr *iothread;
+ struct fstrm_iothr_queue *ioq;
+};
+
+/*
+ * dt_pack packs the dnstap message for transport
+ * https://gitlab.labs.nic.cz/knot/knot-dns/blob/master/src/contrib/dnstap/dnstap.c#L24
+ * */
+uint8_t* dt_pack(const Dnstap__Dnstap *d, uint8_t **buf, size_t *sz)
+{
+ ProtobufCBufferSimple sbuf = { { NULL } };
+
+ sbuf.base.append = protobuf_c_buffer_simple_append;
+ sbuf.len = 0;
+ sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE;
+ sbuf.data = malloc(sbuf.alloced);
+ if (sbuf.data == NULL) {
+ return NULL;
+ }
+ sbuf.must_free_data = true;
+
+ *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf);
+ *buf = sbuf.data;
+ return *buf;
+}
+
+/* set_address fills in address detail in dnstap_message
+ * https://gitlab.labs.nic.cz/knot/knot-dns/blob/master/src/contrib/dnstap/message.c#L28
+ */
+static void set_address(const struct sockaddr *sockaddr,
+ ProtobufCBinaryData *addr,
+ protobuf_c_boolean *has_addr,
+ uint32_t *port,
+ protobuf_c_boolean *has_port) {
+ const char *saddr = kr_inaddr(sockaddr);
+ if (saddr == NULL) {
+ *has_addr = false;
+ *has_port = false;
+ return;
+ }
+
+ addr->data = (uint8_t *)(saddr);
+ addr->len = kr_inaddr_len(sockaddr);
+ *has_addr = true;
+ *port = kr_inaddr_port(sockaddr);
+ *has_port = true;
+}
+
+/* dnstap_log prepares dnstap message and sent it to fstrm */
+static int dnstap_log(kr_layer_t *ctx) {
+ const struct kr_request *req = ctx->req;
+ const struct kr_module *module = ctx->api->data;
+ const struct kr_rplan *rplan = &req->rplan;
+ const struct dnstap_data *dnstap_dt = module->data;
+
+ /* check if we have a valid iothread */
+ if (!dnstap_dt->iothread || !dnstap_dt->ioq) {
+ DEBUG_MSG("dnstap_dt->iothread or dnstap_dt->ioq is NULL\n");
+ return kr_error(EFAULT);
+ }
+
+ /* current time */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ /* Create dnstap message */
+ Dnstap__Message m;
+
+ memset(&m, 0, sizeof(m));
+
+ m.base.descriptor = &dnstap__message__descriptor;
+ /* Only handling response */
+ m.type = DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE;
+
+ if (req->qsource.addr) {
+ set_address(req->qsource.addr,
+ &m.query_address,
+ &m.has_query_address,
+ &m.query_port,
+ &m.has_query_port);
+ }
+
+ if (req->qsource.dst_addr) {
+ if (req->qsource.flags.tcp) {
+ m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
+ } else {
+ m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
+ }
+ m.has_socket_protocol = true;
+
+ set_address(req->qsource.dst_addr,
+ &m.response_address,
+ &m.has_response_address,
+ &m.response_port,
+ &m.has_response_port);
+ switch (req->qsource.dst_addr->sa_family) {
+ case AF_INET:
+ m.socket_family = DNSTAP__SOCKET_FAMILY__INET;
+ m.has_socket_family = true;
+ break;
+ case AF_INET6:
+ m.socket_family = DNSTAP__SOCKET_FAMILY__INET6;
+ m.has_socket_family = true;
+ break;
+ }
+ }
+
+ if (dnstap_dt->log_resp_pkt) {
+ const knot_pkt_t *rpkt = req->answer;
+ m.response_message.len = rpkt->size;
+ m.response_message.data = (uint8_t *)rpkt->wire;
+ m.has_response_message = true;
+ }
+
+ /* set query time to the timestamp of the first kr_query
+ * set response time to now
+ */
+ if (rplan->resolved.len > 0) {
+ struct kr_query *first = rplan->resolved.at[0];
+
+ m.query_time_sec = first->timestamp.tv_sec;
+ m.has_query_time_sec = true;
+ m.query_time_nsec = first->timestamp.tv_usec * 1000;
+ m.has_query_time_nsec = true;
+ }
+
+ /* Response time */
+ m.response_time_sec = now.tv_sec;
+ m.has_response_time_sec = true;
+ m.response_time_nsec = now.tv_usec * 1000;
+ m.has_response_time_nsec = true;
+
+ /* Query Zone */
+ if (rplan->resolved.len > 0) {
+ struct kr_query *last = array_tail(rplan->resolved);
+ /* Only add query_zone when not answered from cache */
+ if (!(last->flags.CACHED)) {
+ const knot_dname_t *zone_cut_name = last->zone_cut.name;
+ if (zone_cut_name != NULL) {
+ m.query_zone.data = (uint8_t *)zone_cut_name;
+ m.query_zone.len = knot_dname_size(zone_cut_name);
+ m.has_query_zone = true;
+ }
+ }
+ }
+
+ /* Create a dnstap Message */
+ Dnstap__Dnstap dnstap = DNSTAP__DNSTAP__INIT;
+ dnstap.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
+ dnstap.message = (Dnstap__Message *)&m;
+
+ /* Pack the message */
+ uint8_t *frame = NULL;
+ size_t size = 0;
+ dt_pack(&dnstap, &frame, &size);
+ if (!frame) {
+ return kr_error(ENOMEM);
+ }
+
+ /* Submit a request to send message to fstrm_iothr*/
+ fstrm_res res = fstrm_iothr_submit(dnstap_dt->iothread, dnstap_dt->ioq, frame, size,
+ fstrm_free_wrapper, NULL);
+ if (res != fstrm_res_success) {
+ DEBUG_MSG("Error submitting dnstap message to iothr\n");
+ free(frame);
+ return kr_error(EBUSY);
+ }
+
+ return ctx->state;
+}
+
+KR_EXPORT
+int dnstap_init(struct kr_module *module) {
+ /* allocated memory for internal data */
+ struct dnstap_data *data = malloc(sizeof(*data));
+ if (!data) {
+ return kr_error(ENOMEM);
+ }
+ memset(data, 0, sizeof(*data));
+
+ /* save pointer to internal struct in module for future reference */
+ module->data = data;
+ return kr_ok();
+}
+
+KR_EXPORT
+int dnstap_deinit(struct kr_module *module) {
+ struct dnstap_data *data = module->data;
+ /* Free allocated memory */
+ if (data) {
+ fstrm_iothr_destroy(&data->iothread);
+ DEBUG_MSG("fstrm iothread destroyed\n");
+ free(data);
+ }
+ return kr_ok();
+}
+
+/* dnstap_unix_writer returns a unix fstream writer
+ * https://gitlab.labs.nic.cz/knot/knot-dns/blob/master/src/knot/modules/dnstap.c#L159
+ */
+static struct fstrm_writer* dnstap_unix_writer(const char *path) {
+
+ auto_destroy_uopts struct fstrm_unix_writer_options *opt = fstrm_unix_writer_options_init();
+ if (!opt) {
+ return NULL;
+ }
+ fstrm_unix_writer_options_set_socket_path(opt, path);
+
+ auto_destroy_wopts struct fstrm_writer_options *wopt = fstrm_writer_options_init();
+ if (!wopt) {
+ fstrm_unix_writer_options_destroy(&opt);
+ return NULL;
+ }
+ fstrm_writer_options_add_content_type(wopt, DNSTAP_CONTENT_TYPE,
+ strlen(DNSTAP_CONTENT_TYPE));
+
+ struct fstrm_writer *writer = fstrm_unix_writer_init(opt, wopt);
+ fstrm_unix_writer_options_destroy(&opt);
+ fstrm_writer_options_destroy(&wopt);
+ if (!writer) {
+ return NULL;
+ }
+
+ fstrm_res res = fstrm_writer_open(writer);
+ if (res != fstrm_res_success) {
+ DEBUG_MSG("fstrm_writer_open returned %d\n", res);
+ fstrm_writer_destroy(&writer);
+ return NULL;
+ }
+
+ return writer;
+}
+
+/* find_string
+ * create a new string from json
+ * *var is set to pointer of new string
+ * node must of type JSON_STRING
+ * new string can be at most len bytes
+ */
+static int find_string(const JsonNode *node, char **val, size_t len) {
+ if (!node || !node->key) {
+ return kr_error(EINVAL);
+ }
+ assert(node->tag == JSON_STRING);
+ *val = strndup(node->string_, len);
+ assert(*val != NULL);
+ return kr_ok();
+}
+
+/* find_bool returns bool from json */
+static bool find_bool(const JsonNode *node) {
+ if (!node || !node->key) {
+ return false;
+ }
+ assert(node->tag == JSON_BOOL);
+ return node->bool_;
+}
+
+/* parse config */
+KR_EXPORT
+int dnstap_config(struct kr_module *module, const char *conf) {
+ struct dnstap_data *data = module->data;
+ auto_free char *sock_path = NULL;
+
+ /* Empty conf passed, set default */
+ if (!conf || strlen(conf) < 1) {
+ sock_path = strndup(DEFAULT_SOCK_PATH, PATH_MAX);
+ } else {
+
+ JsonNode *root_node = json_decode(conf);
+ if (!root_node) {
+ DEBUG_MSG("error parsing json\n");
+ return kr_error(EINVAL);
+ }
+
+ JsonNode *node;
+ /* dnstapPath key */
+ node = json_find_member(root_node, CFG_SOCK_PATH);
+ if (!node || find_string(node, &sock_path, PATH_MAX) != kr_ok()) {
+ sock_path = strndup(DEFAULT_SOCK_PATH, PATH_MAX);
+ }
+
+ /* logRespPkt key */
+ node = json_find_member(root_node, CFG_LOG_RESP_PKT);
+ if (node) {
+ data->log_resp_pkt = find_bool(node);
+ } else {
+ data->log_resp_pkt = false;
+ }
+
+ /* clean up json, we don't need it no more */
+ json_delete(root_node);
+ }
+
+ DEBUG_MSG("opening sock file %s\n",sock_path);
+ struct fstrm_writer *writer = dnstap_unix_writer(sock_path);
+ if (!writer) {
+ DEBUG_MSG("can't create unix writer\n");
+ return kr_error(EINVAL);
+ }
+
+ struct fstrm_iothr_options *opt = fstrm_iothr_options_init();
+ if (!opt) {
+ DEBUG_MSG("can't init fstrm options\n");
+ fstrm_writer_destroy(&writer);
+ return kr_error(EINVAL);
+ }
+
+ /* Create the I/O thread. */
+ data->iothread = fstrm_iothr_init(opt, &writer);
+ fstrm_iothr_options_destroy(&opt);
+ if (!data->iothread) {
+ DEBUG_MSG("can't init fstrm_iothr\n");
+ fstrm_writer_destroy(&writer);
+ return kr_error(ENOMEM);
+ }
+
+ /* Get fstrm thread handle
+ * We only have one input queue, hence idx=0
+ */
+ data->ioq = fstrm_iothr_get_input_queue_idx(data->iothread, 0);
+ if (!data->ioq) {
+ fstrm_iothr_destroy(&data->iothread);
+ DEBUG_MSG("can't get fstrm queue\n");
+ return kr_error(EBUSY);
+ }
+
+ return kr_ok();
+}
+
+KR_EXPORT
+const kr_layer_api_t *dnstap_layer(struct kr_module *module) {
+ static kr_layer_api_t _layer = {
+ .finish = &dnstap_log,
+ };
+ /* Store module reference */
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_MODULE_EXPORT(dnstap)
+
diff --git a/modules/dnstap/dnstap.mk b/modules/dnstap/dnstap.mk
new file mode 100644
index 0000000..9a44dc2
--- /dev/null
+++ b/modules/dnstap/dnstap.mk
@@ -0,0 +1,8 @@
+dnstap_CFLAGS := -fPIC
+dnstap_SOURCES := modules/dnstap/dnstap.pb-c.c modules/dnstap/dnstap.c
+dnstap_DEPEND := $(libkres) modules/dnstap/dnstap.pb-c.c # because of generated *.h
+dnstap_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS) $(libprotobuf-c_LIBS) $(libfstrm_LIBS)
+$(call make_c_module,dnstap)
+
+modules/dnstap/dnstap.pb-c.c: modules/dnstap/dnstap.proto
+ protoc-c $< --c_out=.
diff --git a/modules/dnstap/dnstap.pb-c.c b/modules/dnstap/dnstap.pb-c.c
new file mode 100644
index 0000000..94d11c3
--- /dev/null
+++ b/modules/dnstap/dnstap.pb-c.c
@@ -0,0 +1,523 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: modules/dnstap/dnstap.proto */
+
+/* Do not generate deprecated warnings for self */
+#ifndef PROTOBUF_C__NO_DEPRECATED
+#define PROTOBUF_C__NO_DEPRECATED
+#endif
+
+#include "modules/dnstap/dnstap.pb-c.h"
+void dnstap__dnstap__init
+ (Dnstap__Dnstap *message)
+{
+ static Dnstap__Dnstap init_value = DNSTAP__DNSTAP__INIT;
+ *message = init_value;
+}
+size_t dnstap__dnstap__get_packed_size
+ (const Dnstap__Dnstap *message)
+{
+ assert(message->base.descriptor == &dnstap__dnstap__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t dnstap__dnstap__pack
+ (const Dnstap__Dnstap *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &dnstap__dnstap__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t dnstap__dnstap__pack_to_buffer
+ (const Dnstap__Dnstap *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &dnstap__dnstap__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+Dnstap__Dnstap *
+ dnstap__dnstap__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (Dnstap__Dnstap *)
+ protobuf_c_message_unpack (&dnstap__dnstap__descriptor,
+ allocator, len, data);
+}
+void dnstap__dnstap__free_unpacked
+ (Dnstap__Dnstap *message,
+ ProtobufCAllocator *allocator)
+{
+ assert(message->base.descriptor == &dnstap__dnstap__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void dnstap__message__init
+ (Dnstap__Message *message)
+{
+ static Dnstap__Message init_value = DNSTAP__MESSAGE__INIT;
+ *message = init_value;
+}
+size_t dnstap__message__get_packed_size
+ (const Dnstap__Message *message)
+{
+ assert(message->base.descriptor == &dnstap__message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t dnstap__message__pack
+ (const Dnstap__Message *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &dnstap__message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t dnstap__message__pack_to_buffer
+ (const Dnstap__Message *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &dnstap__message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+Dnstap__Message *
+ dnstap__message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (Dnstap__Message *)
+ protobuf_c_message_unpack (&dnstap__message__descriptor,
+ allocator, len, data);
+}
+void dnstap__message__free_unpacked
+ (Dnstap__Message *message,
+ ProtobufCAllocator *allocator)
+{
+ assert(message->base.descriptor == &dnstap__message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCEnumValue dnstap__dnstap__type__enum_values_by_number[1] =
+{
+ { "MESSAGE", "DNSTAP__DNSTAP__TYPE__MESSAGE", 1 },
+};
+static const ProtobufCIntRange dnstap__dnstap__type__value_ranges[] = {
+{1, 0},{0, 1}
+};
+static const ProtobufCEnumValueIndex dnstap__dnstap__type__enum_values_by_name[1] =
+{
+ { "MESSAGE", 0 },
+};
+const ProtobufCEnumDescriptor dnstap__dnstap__type__descriptor =
+{
+ PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
+ "dnstap.Dnstap.Type",
+ "Type",
+ "Dnstap__Dnstap__Type",
+ "dnstap",
+ 1,
+ dnstap__dnstap__type__enum_values_by_number,
+ 1,
+ dnstap__dnstap__type__enum_values_by_name,
+ 1,
+ dnstap__dnstap__type__value_ranges,
+ NULL,NULL,NULL,NULL /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor dnstap__dnstap__field_descriptors[5] =
+{
+ {
+ "identity",
+ 1,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Dnstap, has_identity),
+ offsetof(Dnstap__Dnstap, identity),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "version",
+ 2,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Dnstap, has_version),
+ offsetof(Dnstap__Dnstap, version),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "extra",
+ 3,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Dnstap, has_extra),
+ offsetof(Dnstap__Dnstap, extra),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "message",
+ 14,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(Dnstap__Dnstap, message),
+ &dnstap__message__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "type",
+ 15,
+ PROTOBUF_C_LABEL_REQUIRED,
+ PROTOBUF_C_TYPE_ENUM,
+ 0, /* quantifier_offset */
+ offsetof(Dnstap__Dnstap, type),
+ &dnstap__dnstap__type__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned dnstap__dnstap__field_indices_by_name[] = {
+ 2, /* field[2] = extra */
+ 0, /* field[0] = identity */
+ 3, /* field[3] = message */
+ 4, /* field[4] = type */
+ 1, /* field[1] = version */
+};
+static const ProtobufCIntRange dnstap__dnstap__number_ranges[2 + 1] =
+{
+ { 1, 0 },
+ { 14, 3 },
+ { 0, 5 }
+};
+const ProtobufCMessageDescriptor dnstap__dnstap__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "dnstap.Dnstap",
+ "Dnstap",
+ "Dnstap__Dnstap",
+ "dnstap",
+ sizeof(Dnstap__Dnstap),
+ 5,
+ dnstap__dnstap__field_descriptors,
+ dnstap__dnstap__field_indices_by_name,
+ 2, dnstap__dnstap__number_ranges,
+ (ProtobufCMessageInit) dnstap__dnstap__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCEnumValue dnstap__message__type__enum_values_by_number[12] =
+{
+ { "AUTH_QUERY", "DNSTAP__MESSAGE__TYPE__AUTH_QUERY", 1 },
+ { "AUTH_RESPONSE", "DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE", 2 },
+ { "RESOLVER_QUERY", "DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY", 3 },
+ { "RESOLVER_RESPONSE", "DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE", 4 },
+ { "CLIENT_QUERY", "DNSTAP__MESSAGE__TYPE__CLIENT_QUERY", 5 },
+ { "CLIENT_RESPONSE", "DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE", 6 },
+ { "FORWARDER_QUERY", "DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY", 7 },
+ { "FORWARDER_RESPONSE", "DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE", 8 },
+ { "STUB_QUERY", "DNSTAP__MESSAGE__TYPE__STUB_QUERY", 9 },
+ { "STUB_RESPONSE", "DNSTAP__MESSAGE__TYPE__STUB_RESPONSE", 10 },
+ { "TOOL_QUERY", "DNSTAP__MESSAGE__TYPE__TOOL_QUERY", 11 },
+ { "TOOL_RESPONSE", "DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE", 12 },
+};
+static const ProtobufCIntRange dnstap__message__type__value_ranges[] = {
+{1, 0},{0, 12}
+};
+static const ProtobufCEnumValueIndex dnstap__message__type__enum_values_by_name[12] =
+{
+ { "AUTH_QUERY", 0 },
+ { "AUTH_RESPONSE", 1 },
+ { "CLIENT_QUERY", 4 },
+ { "CLIENT_RESPONSE", 5 },
+ { "FORWARDER_QUERY", 6 },
+ { "FORWARDER_RESPONSE", 7 },
+ { "RESOLVER_QUERY", 2 },
+ { "RESOLVER_RESPONSE", 3 },
+ { "STUB_QUERY", 8 },
+ { "STUB_RESPONSE", 9 },
+ { "TOOL_QUERY", 10 },
+ { "TOOL_RESPONSE", 11 },
+};
+const ProtobufCEnumDescriptor dnstap__message__type__descriptor =
+{
+ PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
+ "dnstap.Message.Type",
+ "Type",
+ "Dnstap__Message__Type",
+ "dnstap",
+ 12,
+ dnstap__message__type__enum_values_by_number,
+ 12,
+ dnstap__message__type__enum_values_by_name,
+ 1,
+ dnstap__message__type__value_ranges,
+ NULL,NULL,NULL,NULL /* reserved[1234] */
+};
+static const ProtobufCFieldDescriptor dnstap__message__field_descriptors[14] =
+{
+ {
+ "type",
+ 1,
+ PROTOBUF_C_LABEL_REQUIRED,
+ PROTOBUF_C_TYPE_ENUM,
+ 0, /* quantifier_offset */
+ offsetof(Dnstap__Message, type),
+ &dnstap__message__type__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "socket_family",
+ 2,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_ENUM,
+ offsetof(Dnstap__Message, has_socket_family),
+ offsetof(Dnstap__Message, socket_family),
+ &dnstap__socket_family__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "socket_protocol",
+ 3,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_ENUM,
+ offsetof(Dnstap__Message, has_socket_protocol),
+ offsetof(Dnstap__Message, socket_protocol),
+ &dnstap__socket_protocol__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_address",
+ 4,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Message, has_query_address),
+ offsetof(Dnstap__Message, query_address),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "response_address",
+ 5,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Message, has_response_address),
+ offsetof(Dnstap__Message, response_address),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_port",
+ 6,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_UINT32,
+ offsetof(Dnstap__Message, has_query_port),
+ offsetof(Dnstap__Message, query_port),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "response_port",
+ 7,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_UINT32,
+ offsetof(Dnstap__Message, has_response_port),
+ offsetof(Dnstap__Message, response_port),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_time_sec",
+ 8,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_UINT64,
+ offsetof(Dnstap__Message, has_query_time_sec),
+ offsetof(Dnstap__Message, query_time_sec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_time_nsec",
+ 9,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_FIXED32,
+ offsetof(Dnstap__Message, has_query_time_nsec),
+ offsetof(Dnstap__Message, query_time_nsec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_message",
+ 10,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Message, has_query_message),
+ offsetof(Dnstap__Message, query_message),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "query_zone",
+ 11,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Message, has_query_zone),
+ offsetof(Dnstap__Message, query_zone),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "response_time_sec",
+ 12,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_UINT64,
+ offsetof(Dnstap__Message, has_response_time_sec),
+ offsetof(Dnstap__Message, response_time_sec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "response_time_nsec",
+ 13,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_FIXED32,
+ offsetof(Dnstap__Message, has_response_time_nsec),
+ offsetof(Dnstap__Message, response_time_nsec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "response_message",
+ 14,
+ PROTOBUF_C_LABEL_OPTIONAL,
+ PROTOBUF_C_TYPE_BYTES,
+ offsetof(Dnstap__Message, has_response_message),
+ offsetof(Dnstap__Message, response_message),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned dnstap__message__field_indices_by_name[] = {
+ 3, /* field[3] = query_address */
+ 9, /* field[9] = query_message */
+ 5, /* field[5] = query_port */
+ 8, /* field[8] = query_time_nsec */
+ 7, /* field[7] = query_time_sec */
+ 10, /* field[10] = query_zone */
+ 4, /* field[4] = response_address */
+ 13, /* field[13] = response_message */
+ 6, /* field[6] = response_port */
+ 12, /* field[12] = response_time_nsec */
+ 11, /* field[11] = response_time_sec */
+ 1, /* field[1] = socket_family */
+ 2, /* field[2] = socket_protocol */
+ 0, /* field[0] = type */
+};
+static const ProtobufCIntRange dnstap__message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 14 }
+};
+const ProtobufCMessageDescriptor dnstap__message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "dnstap.Message",
+ "Message",
+ "Dnstap__Message",
+ "dnstap",
+ sizeof(Dnstap__Message),
+ 14,
+ dnstap__message__field_descriptors,
+ dnstap__message__field_indices_by_name,
+ 1, dnstap__message__number_ranges,
+ (ProtobufCMessageInit) dnstap__message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCEnumValue dnstap__socket_family__enum_values_by_number[2] =
+{
+ { "INET", "DNSTAP__SOCKET_FAMILY__INET", 1 },
+ { "INET6", "DNSTAP__SOCKET_FAMILY__INET6", 2 },
+};
+static const ProtobufCIntRange dnstap__socket_family__value_ranges[] = {
+{1, 0},{0, 2}
+};
+static const ProtobufCEnumValueIndex dnstap__socket_family__enum_values_by_name[2] =
+{
+ { "INET", 0 },
+ { "INET6", 1 },
+};
+const ProtobufCEnumDescriptor dnstap__socket_family__descriptor =
+{
+ PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
+ "dnstap.SocketFamily",
+ "SocketFamily",
+ "Dnstap__SocketFamily",
+ "dnstap",
+ 2,
+ dnstap__socket_family__enum_values_by_number,
+ 2,
+ dnstap__socket_family__enum_values_by_name,
+ 1,
+ dnstap__socket_family__value_ranges,
+ NULL,NULL,NULL,NULL /* reserved[1234] */
+};
+static const ProtobufCEnumValue dnstap__socket_protocol__enum_values_by_number[2] =
+{
+ { "UDP", "DNSTAP__SOCKET_PROTOCOL__UDP", 1 },
+ { "TCP", "DNSTAP__SOCKET_PROTOCOL__TCP", 2 },
+};
+static const ProtobufCIntRange dnstap__socket_protocol__value_ranges[] = {
+{1, 0},{0, 2}
+};
+static const ProtobufCEnumValueIndex dnstap__socket_protocol__enum_values_by_name[2] =
+{
+ { "TCP", 1 },
+ { "UDP", 0 },
+};
+const ProtobufCEnumDescriptor dnstap__socket_protocol__descriptor =
+{
+ PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
+ "dnstap.SocketProtocol",
+ "SocketProtocol",
+ "Dnstap__SocketProtocol",
+ "dnstap",
+ 2,
+ dnstap__socket_protocol__enum_values_by_number,
+ 2,
+ dnstap__socket_protocol__enum_values_by_name,
+ 1,
+ dnstap__socket_protocol__value_ranges,
+ NULL,NULL,NULL,NULL /* reserved[1234] */
+};
diff --git a/modules/dnstap/dnstap.pb-c.h b/modules/dnstap/dnstap.pb-c.h
new file mode 100644
index 0000000..51d5fee
--- /dev/null
+++ b/modules/dnstap/dnstap.pb-c.h
@@ -0,0 +1,343 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: modules/dnstap/dnstap.proto */
+
+#ifndef PROTOBUF_C_modules_2fdnstap_2fdnstap_2eproto__INCLUDED
+#define PROTOBUF_C_modules_2fdnstap_2fdnstap_2eproto__INCLUDED
+
+#include <protobuf-c/protobuf-c.h>
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if PROTOBUF_C_VERSION_NUMBER < 1000000
+# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
+#elif 1002001 < PROTOBUF_C_MIN_COMPILER_VERSION
+# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
+#endif
+
+
+typedef struct _Dnstap__Dnstap Dnstap__Dnstap;
+typedef struct _Dnstap__Message Dnstap__Message;
+
+
+/* --- enums --- */
+
+/*
+ * Identifies which field below is filled in.
+ */
+typedef enum _Dnstap__Dnstap__Type {
+ DNSTAP__DNSTAP__TYPE__MESSAGE = 1
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(DNSTAP__DNSTAP__TYPE)
+} Dnstap__Dnstap__Type;
+typedef enum _Dnstap__Message__Type {
+ /*
+ * AUTH_QUERY is a DNS query message received from a resolver by an
+ * authoritative name server, from the perspective of the authoritative
+ * name server.
+ */
+ DNSTAP__MESSAGE__TYPE__AUTH_QUERY = 1,
+ /*
+ * AUTH_RESPONSE is a DNS response message sent from an authoritative
+ * name server to a resolver, from the perspective of the authoritative
+ * name server.
+ */
+ DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE = 2,
+ /*
+ * RESOLVER_QUERY is a DNS query message sent from a resolver to an
+ * authoritative name server, from the perspective of the resolver.
+ * Resolvers typically clear the RD (recursion desired) bit when
+ * sending queries.
+ */
+ DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY = 3,
+ /*
+ * RESOLVER_RESPONSE is a DNS response message received from an
+ * authoritative name server by a resolver, from the perspective of
+ * the resolver.
+ */
+ DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE = 4,
+ /*
+ * CLIENT_QUERY is a DNS query message sent from a client to a DNS
+ * server which is expected to perform further recursion, from the
+ * perspective of the DNS server. The client may be a stub resolver or
+ * forwarder or some other type of software which typically sets the RD
+ * (recursion desired) bit when querying the DNS server. The DNS server
+ * may be a simple forwarding proxy or it may be a full recursive
+ * resolver.
+ */
+ DNSTAP__MESSAGE__TYPE__CLIENT_QUERY = 5,
+ /*
+ * CLIENT_RESPONSE is a DNS response message sent from a DNS server to
+ * a client, from the perspective of the DNS server. The DNS server
+ * typically sets the RA (recursion available) bit when responding.
+ */
+ DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE = 6,
+ /*
+ * FORWARDER_QUERY is a DNS query message sent from a downstream DNS
+ * server to an upstream DNS server which is expected to perform
+ * further recursion, from the perspective of the downstream DNS
+ * server.
+ */
+ DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY = 7,
+ /*
+ * FORWARDER_RESPONSE is a DNS response message sent from an upstream
+ * DNS server performing recursion to a downstream DNS server, from the
+ * perspective of the downstream DNS server.
+ */
+ DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE = 8,
+ /*
+ * STUB_QUERY is a DNS query message sent from a stub resolver to a DNS
+ * server, from the perspective of the stub resolver.
+ */
+ DNSTAP__MESSAGE__TYPE__STUB_QUERY = 9,
+ /*
+ * STUB_RESPONSE is a DNS response message sent from a DNS server to a
+ * stub resolver, from the perspective of the stub resolver.
+ */
+ DNSTAP__MESSAGE__TYPE__STUB_RESPONSE = 10,
+ /*
+ * TOOL_QUERY is a DNS query message sent from a DNS software tool to a
+ * DNS server, from the perspective of the tool.
+ */
+ DNSTAP__MESSAGE__TYPE__TOOL_QUERY = 11,
+ /*
+ * TOOL_RESPONSE is a DNS response message received by a DNS software
+ * tool from a DNS server, from the perspective of the tool.
+ */
+ DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE = 12
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(DNSTAP__MESSAGE__TYPE)
+} Dnstap__Message__Type;
+/*
+ * SocketFamily: the network protocol family of a socket. This specifies how
+ * to interpret "network address" fields.
+ */
+typedef enum _Dnstap__SocketFamily {
+ /*
+ * IPv4 (RFC 791)
+ */
+ DNSTAP__SOCKET_FAMILY__INET = 1,
+ /*
+ * IPv6 (RFC 2460)
+ */
+ DNSTAP__SOCKET_FAMILY__INET6 = 2
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(DNSTAP__SOCKET_FAMILY)
+} Dnstap__SocketFamily;
+/*
+ * SocketProtocol: the transport protocol of a socket. This specifies how to
+ * interpret "transport port" fields.
+ */
+typedef enum _Dnstap__SocketProtocol {
+ /*
+ * User Datagram Protocol (RFC 768)
+ */
+ DNSTAP__SOCKET_PROTOCOL__UDP = 1,
+ /*
+ * Transmission Control Protocol (RFC 793)
+ */
+ DNSTAP__SOCKET_PROTOCOL__TCP = 2
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(DNSTAP__SOCKET_PROTOCOL)
+} Dnstap__SocketProtocol;
+
+/* --- messages --- */
+
+/*
+ * "Dnstap": this is the top-level dnstap type, which is a "union" type that
+ * contains other kinds of dnstap payloads, although currently only one type
+ * of dnstap payload is defined.
+ * See: https://developers.google.com/protocol-buffers/docs/techniques#union
+ */
+struct _Dnstap__Dnstap
+{
+ ProtobufCMessage base;
+ /*
+ * DNS server identity.
+ * If enabled, this is the identity string of the DNS server which generated
+ * this message. Typically this would be the same string as returned by an
+ * "NSID" (RFC 5001) query.
+ */
+ protobuf_c_boolean has_identity;
+ ProtobufCBinaryData identity;
+ /*
+ * DNS server version.
+ * If enabled, this is the version string of the DNS server which generated
+ * this message. Typically this would be the same string as returned by a
+ * "version.bind" query.
+ */
+ protobuf_c_boolean has_version;
+ ProtobufCBinaryData version;
+ /*
+ * Extra data for this payload.
+ * This field can be used for adding an arbitrary byte-string annotation to
+ * the payload. No encoding or interpretation is applied or enforced.
+ */
+ protobuf_c_boolean has_extra;
+ ProtobufCBinaryData extra;
+ Dnstap__Dnstap__Type type;
+ /*
+ * One of the following will be filled in.
+ */
+ Dnstap__Message *message;
+};
+#define DNSTAP__DNSTAP__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&dnstap__dnstap__descriptor) \
+ , 0,{0,NULL}, 0,{0,NULL}, 0,{0,NULL}, 0, NULL }
+
+
+/*
+ * Message: a wire-format (RFC 1035 section 4) DNS message and associated
+ * metadata. Applications generating "Message" payloads should follow
+ * certain requirements based on the MessageType, see below.
+ */
+struct _Dnstap__Message
+{
+ ProtobufCMessage base;
+ /*
+ * One of the Type values described above.
+ */
+ Dnstap__Message__Type type;
+ /*
+ * One of the SocketFamily values described above.
+ */
+ protobuf_c_boolean has_socket_family;
+ Dnstap__SocketFamily socket_family;
+ /*
+ * One of the SocketProtocol values described above.
+ */
+ protobuf_c_boolean has_socket_protocol;
+ Dnstap__SocketProtocol socket_protocol;
+ /*
+ * The network address of the message initiator.
+ * For SocketFamily INET, this field is 4 octets (IPv4 address).
+ * For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ */
+ protobuf_c_boolean has_query_address;
+ ProtobufCBinaryData query_address;
+ /*
+ * The network address of the message responder.
+ * For SocketFamily INET, this field is 4 octets (IPv4 address).
+ * For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ */
+ protobuf_c_boolean has_response_address;
+ ProtobufCBinaryData response_address;
+ /*
+ * The transport port of the message initiator.
+ * This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ */
+ protobuf_c_boolean has_query_port;
+ uint32_t query_port;
+ /*
+ * The transport port of the message responder.
+ * This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ */
+ protobuf_c_boolean has_response_port;
+ uint32_t response_port;
+ /*
+ * The time at which the DNS query message was sent or received, depending
+ * on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY.
+ * This is the number of seconds since the UNIX epoch.
+ */
+ protobuf_c_boolean has_query_time_sec;
+ uint64_t query_time_sec;
+ /*
+ * The time at which the DNS query message was sent or received.
+ * This is the seconds fraction, expressed as a count of nanoseconds.
+ */
+ protobuf_c_boolean has_query_time_nsec;
+ uint32_t query_time_nsec;
+ /*
+ * The initiator's original wire-format DNS query message, verbatim.
+ */
+ protobuf_c_boolean has_query_message;
+ ProtobufCBinaryData query_message;
+ /*
+ * The "zone" or "bailiwick" pertaining to the DNS query message.
+ * This is a wire-format DNS domain name.
+ */
+ protobuf_c_boolean has_query_zone;
+ ProtobufCBinaryData query_zone;
+ /*
+ * The time at which the DNS response message was sent or received,
+ * depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or
+ * CLIENT_RESPONSE.
+ * This is the number of seconds since the UNIX epoch.
+ */
+ protobuf_c_boolean has_response_time_sec;
+ uint64_t response_time_sec;
+ /*
+ * The time at which the DNS response message was sent or received.
+ * This is the seconds fraction, expressed as a count of nanoseconds.
+ */
+ protobuf_c_boolean has_response_time_nsec;
+ uint32_t response_time_nsec;
+ /*
+ * The responder's original wire-format DNS response message, verbatim.
+ */
+ protobuf_c_boolean has_response_message;
+ ProtobufCBinaryData response_message;
+};
+#define DNSTAP__MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&dnstap__message__descriptor) \
+ , 0, 0,0, 0,0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,0, 0,0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,{0,NULL} }
+
+
+/* Dnstap__Dnstap methods */
+void dnstap__dnstap__init
+ (Dnstap__Dnstap *message);
+size_t dnstap__dnstap__get_packed_size
+ (const Dnstap__Dnstap *message);
+size_t dnstap__dnstap__pack
+ (const Dnstap__Dnstap *message,
+ uint8_t *out);
+size_t dnstap__dnstap__pack_to_buffer
+ (const Dnstap__Dnstap *message,
+ ProtobufCBuffer *buffer);
+Dnstap__Dnstap *
+ dnstap__dnstap__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void dnstap__dnstap__free_unpacked
+ (Dnstap__Dnstap *message,
+ ProtobufCAllocator *allocator);
+/* Dnstap__Message methods */
+void dnstap__message__init
+ (Dnstap__Message *message);
+size_t dnstap__message__get_packed_size
+ (const Dnstap__Message *message);
+size_t dnstap__message__pack
+ (const Dnstap__Message *message,
+ uint8_t *out);
+size_t dnstap__message__pack_to_buffer
+ (const Dnstap__Message *message,
+ ProtobufCBuffer *buffer);
+Dnstap__Message *
+ dnstap__message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void dnstap__message__free_unpacked
+ (Dnstap__Message *message,
+ ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*Dnstap__Dnstap_Closure)
+ (const Dnstap__Dnstap *message,
+ void *closure_data);
+typedef void (*Dnstap__Message_Closure)
+ (const Dnstap__Message *message,
+ void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCEnumDescriptor dnstap__socket_family__descriptor;
+extern const ProtobufCEnumDescriptor dnstap__socket_protocol__descriptor;
+extern const ProtobufCMessageDescriptor dnstap__dnstap__descriptor;
+extern const ProtobufCEnumDescriptor dnstap__dnstap__type__descriptor;
+extern const ProtobufCMessageDescriptor dnstap__message__descriptor;
+extern const ProtobufCEnumDescriptor dnstap__message__type__descriptor;
+
+PROTOBUF_C__END_DECLS
+
+
+#endif /* PROTOBUF_C_modules_2fdnstap_2fdnstap_2eproto__INCLUDED */
diff --git a/modules/dnstap/dnstap.proto b/modules/dnstap/dnstap.proto
new file mode 100644
index 0000000..ed87c65
--- /dev/null
+++ b/modules/dnstap/dnstap.proto
@@ -0,0 +1,269 @@
+// dnstap: flexible, structured event replication format for DNS software
+//
+// This file contains the protobuf schemas for the "dnstap" structured event
+// replication format for DNS software.
+
+// Written in 2013-2014 by Farsight Security, Inc.
+//
+// To the extent possible under law, the author(s) have dedicated all
+// copyright and related and neighboring rights to this file to the public
+// domain worldwide. This file is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this file. If not, see:
+//
+// <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+syntax = "proto2";
+package dnstap;
+
+// "Dnstap": this is the top-level dnstap type, which is a "union" type that
+// contains other kinds of dnstap payloads, although currently only one type
+// of dnstap payload is defined.
+// See: https://developers.google.com/protocol-buffers/docs/techniques#union
+message Dnstap {
+ // DNS server identity.
+ // If enabled, this is the identity string of the DNS server which generated
+ // this message. Typically this would be the same string as returned by an
+ // "NSID" (RFC 5001) query.
+ optional bytes identity = 1;
+
+ // DNS server version.
+ // If enabled, this is the version string of the DNS server which generated
+ // this message. Typically this would be the same string as returned by a
+ // "version.bind" query.
+ optional bytes version = 2;
+
+ // Extra data for this payload.
+ // This field can be used for adding an arbitrary byte-string annotation to
+ // the payload. No encoding or interpretation is applied or enforced.
+ optional bytes extra = 3;
+
+ // Identifies which field below is filled in.
+ enum Type {
+ MESSAGE = 1;
+ }
+ required Type type = 15;
+
+ // One of the following will be filled in.
+ optional Message message = 14;
+}
+
+// SocketFamily: the network protocol family of a socket. This specifies how
+// to interpret "network address" fields.
+enum SocketFamily {
+ INET = 1; // IPv4 (RFC 791)
+ INET6 = 2; // IPv6 (RFC 2460)
+}
+
+// SocketProtocol: the transport protocol of a socket. This specifies how to
+// interpret "transport port" fields.
+enum SocketProtocol {
+ UDP = 1; // User Datagram Protocol (RFC 768)
+ TCP = 2; // Transmission Control Protocol (RFC 793)
+}
+
+// Message: a wire-format (RFC 1035 section 4) DNS message and associated
+// metadata. Applications generating "Message" payloads should follow
+// certain requirements based on the MessageType, see below.
+message Message {
+
+ // There are eight types of "Message" defined that correspond to the
+ // four arrows in the following diagram, slightly modified from RFC 1035
+ // section 2:
+
+ // +---------+ +----------+ +--------+
+ // | | query | | query | |
+ // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. |
+ // | Resolver| | Server | | Name |
+ // | |<-SR--------CR-| |<-RR----AR-| Server |
+ // +---------+ response | | response | |
+ // +----------+ +--------+
+
+ // Each arrow has two Type values each, one for each "end" of each arrow,
+ // because these are considered to be distinct events. Each end of each
+ // arrow on the diagram above has been marked with a two-letter Type
+ // mnemonic. Clockwise from upper left, these mnemonic values are:
+ //
+ // SQ: STUB_QUERY
+ // CQ: CLIENT_QUERY
+ // RQ: RESOLVER_QUERY
+ // AQ: AUTH_QUERY
+ // AR: AUTH_RESPONSE
+ // RR: RESOLVER_RESPONSE
+ // CR: CLIENT_RESPONSE
+ // SR: STUB_RESPONSE
+
+ // Two additional types of "Message" have been defined for the
+ // "forwarding" case where an upstream DNS server is responsible for
+ // further recursion. These are not shown on the diagram above, but have
+ // the following mnemonic values:
+
+ // FQ: FORWARDER_QUERY
+ // FR: FORWARDER_RESPONSE
+
+ // The "Message" Type values are defined below.
+
+ enum Type {
+ // AUTH_QUERY is a DNS query message received from a resolver by an
+ // authoritative name server, from the perspective of the authoritative
+ // name server.
+ AUTH_QUERY = 1;
+
+ // AUTH_RESPONSE is a DNS response message sent from an authoritative
+ // name server to a resolver, from the perspective of the authoritative
+ // name server.
+ AUTH_RESPONSE = 2;
+
+ // RESOLVER_QUERY is a DNS query message sent from a resolver to an
+ // authoritative name server, from the perspective of the resolver.
+ // Resolvers typically clear the RD (recursion desired) bit when
+ // sending queries.
+ RESOLVER_QUERY = 3;
+
+ // RESOLVER_RESPONSE is a DNS response message received from an
+ // authoritative name server by a resolver, from the perspective of
+ // the resolver.
+ RESOLVER_RESPONSE = 4;
+
+ // CLIENT_QUERY is a DNS query message sent from a client to a DNS
+ // server which is expected to perform further recursion, from the
+ // perspective of the DNS server. The client may be a stub resolver or
+ // forwarder or some other type of software which typically sets the RD
+ // (recursion desired) bit when querying the DNS server. The DNS server
+ // may be a simple forwarding proxy or it may be a full recursive
+ // resolver.
+ CLIENT_QUERY = 5;
+
+ // CLIENT_RESPONSE is a DNS response message sent from a DNS server to
+ // a client, from the perspective of the DNS server. The DNS server
+ // typically sets the RA (recursion available) bit when responding.
+ CLIENT_RESPONSE = 6;
+
+ // FORWARDER_QUERY is a DNS query message sent from a downstream DNS
+ // server to an upstream DNS server which is expected to perform
+ // further recursion, from the perspective of the downstream DNS
+ // server.
+ FORWARDER_QUERY = 7;
+
+ // FORWARDER_RESPONSE is a DNS response message sent from an upstream
+ // DNS server performing recursion to a downstream DNS server, from the
+ // perspective of the downstream DNS server.
+ FORWARDER_RESPONSE = 8;
+
+ // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS
+ // server, from the perspective of the stub resolver.
+ STUB_QUERY = 9;
+
+ // STUB_RESPONSE is a DNS response message sent from a DNS server to a
+ // stub resolver, from the perspective of the stub resolver.
+ STUB_RESPONSE = 10;
+
+ // TOOL_QUERY is a DNS query message sent from a DNS software tool to a
+ // DNS server, from the perspective of the tool.
+ TOOL_QUERY = 11;
+
+ // TOOL_RESPONSE is a DNS response message received by a DNS software
+ // tool from a DNS server, from the perspective of the tool.
+ TOOL_RESPONSE = 12;
+ }
+
+ // One of the Type values described above.
+ required Type type = 1;
+
+ // One of the SocketFamily values described above.
+ optional SocketFamily socket_family = 2;
+
+ // One of the SocketProtocol values described above.
+ optional SocketProtocol socket_protocol = 3;
+
+ // The network address of the message initiator.
+ // For SocketFamily INET, this field is 4 octets (IPv4 address).
+ // For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ optional bytes query_address = 4;
+
+ // The network address of the message responder.
+ // For SocketFamily INET, this field is 4 octets (IPv4 address).
+ // For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ optional bytes response_address = 5;
+
+ // The transport port of the message initiator.
+ // This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ optional uint32 query_port = 6;
+
+ // The transport port of the message responder.
+ // This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ optional uint32 response_port = 7;
+
+ // The time at which the DNS query message was sent or received, depending
+ // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY.
+ // This is the number of seconds since the UNIX epoch.
+ optional uint64 query_time_sec = 8;
+
+ // The time at which the DNS query message was sent or received.
+ // This is the seconds fraction, expressed as a count of nanoseconds.
+ optional fixed32 query_time_nsec = 9;
+
+ // The initiator's original wire-format DNS query message, verbatim.
+ optional bytes query_message = 10;
+
+ // The "zone" or "bailiwick" pertaining to the DNS query message.
+ // This is a wire-format DNS domain name.
+ optional bytes query_zone = 11;
+
+ // The time at which the DNS response message was sent or received,
+ // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or
+ // CLIENT_RESPONSE.
+ // This is the number of seconds since the UNIX epoch.
+ optional uint64 response_time_sec = 12;
+
+ // The time at which the DNS response message was sent or received.
+ // This is the seconds fraction, expressed as a count of nanoseconds.
+ optional fixed32 response_time_nsec = 13;
+
+ // The responder's original wire-format DNS response message, verbatim.
+ optional bytes response_message = 14;
+}
+
+// All fields except for 'type' in the Message schema are optional.
+// It is recommended that at least the following fields be filled in for
+// particular types of Messages.
+
+// AUTH_QUERY:
+// socket_family, socket_protocol
+// query_address, query_port
+// query_message
+// query_time_sec, query_time_nsec
+
+// AUTH_RESPONSE:
+// socket_family, socket_protocol
+// query_address, query_port
+// query_time_sec, query_time_nsec
+// response_message
+// response_time_sec, response_time_nsec
+
+// RESOLVER_QUERY:
+// socket_family, socket_protocol
+// query_message
+// query_time_sec, query_time_nsec
+// query_zone
+// response_address, response_port
+
+// RESOLVER_RESPONSE:
+// socket_family, socket_protocol
+// query_time_sec, query_time_nsec
+// query_zone
+// response_address, response_port
+// response_message
+// response_time_sec, response_time_nsec
+
+// CLIENT_QUERY:
+// socket_family, socket_protocol
+// query_message
+// query_time_sec, query_time_nsec
+
+// CLIENT_RESPONSE:
+// socket_family, socket_protocol
+// query_time_sec, query_time_nsec
+// response_message
+// response_time_sec, response_time_nsec
diff --git a/modules/edns_keepalive/README.rst b/modules/edns_keepalive/README.rst
new file mode 100644
index 0000000..7938632
--- /dev/null
+++ b/modules/edns_keepalive/README.rst
@@ -0,0 +1,12 @@
+.. _mod-edns_keepalive:
+
+EDNS keepalive
+--------------
+
+The ``edns_keepalive`` module implements :rfc:`7828` for *clients* connecting to Knot Resolver via TCP and TLS.
+Note that client connections are timed-out the same way *regardless* of them sending the EDNS option;
+the module just allows clients to discover the timeout.
+
+When connecting to servers, Knot Resolver does not send this EDNS option.
+It still attempts to reuse established connections intelligently.
+
diff --git a/modules/edns_keepalive/edns_keepalive.c b/modules/edns_keepalive/edns_keepalive.c
new file mode 100644
index 0000000..99c0d96
--- /dev/null
+++ b/modules/edns_keepalive/edns_keepalive.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file edns_keepalive.c
+ * @brief Minimalistic EDNS keepalive implementation on server side.
+ * If keepalive option is present in query,
+ * always reply with constant timeout value.
+ *
+ */
+#include <libknot/packet/pkt.h>
+#include "daemon/worker.h"
+#include "lib/module.h"
+#include "lib/layer.h"
+
+static int edns_keepalive_finalize(kr_layer_t *ctx)
+{
+ struct kr_request *req = ctx->req;
+ knot_pkt_t *answer = req->answer;
+ const knot_rrset_t *src_opt = req->qsource.packet->opt_rr;
+ knot_rrset_t *answ_opt = answer->opt_rr;
+
+ const bool ka_want =
+ req->qsource.flags.tcp &&
+ src_opt != NULL &&
+ knot_edns_get_option(src_opt, KNOT_EDNS_OPTION_TCP_KEEPALIVE) &&
+ answ_opt != NULL;
+ if (!ka_want) {
+ return ctx->state;
+ }
+ const struct worker_ctx *worker = (const struct worker_ctx *)req->daemon_context;
+ assert(worker);
+ const struct network *net = &worker->engine->net;
+ uint64_t timeout = net->tcp.in_idle_timeout / 100;
+ if (timeout > UINT16_MAX) {
+ timeout = UINT16_MAX;
+ }
+ knot_mm_t *pool = &answer->mm;
+ uint16_t ka_size = knot_edns_keepalive_size(timeout);
+ uint8_t ka_buf[ka_size];
+ int ret = knot_edns_keepalive_write(ka_buf, ka_size, timeout);
+ if (ret == KNOT_EOK) {
+ ret = knot_edns_add_option(answ_opt, KNOT_EDNS_OPTION_TCP_KEEPALIVE,
+ ka_size, ka_buf, pool);
+ }
+ if (ret != KNOT_EOK) {
+ ctx->state = KR_STATE_FAIL;
+ }
+ return ctx->state;
+}
+
+KR_EXPORT
+const kr_layer_api_t *edns_keepalive_layer(struct kr_module *module)
+{
+ static kr_layer_api_t _layer = {
+ .answer_finalize = &edns_keepalive_finalize,
+ };
+ /* Store module reference */
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_MODULE_EXPORT(edns_keepalive)
+
diff --git a/modules/edns_keepalive/edns_keepalive.mk b/modules/edns_keepalive/edns_keepalive.mk
new file mode 100644
index 0000000..4ce2bd9
--- /dev/null
+++ b/modules/edns_keepalive/edns_keepalive.mk
@@ -0,0 +1,5 @@
+edns_keepalive_CFLAGS := -fPIC
+edns_keepalive_LDFLAGS := -Wl,-undefined -Wl,dynamic_lookup
+edns_keepalive_SOURCES := modules/edns_keepalive/edns_keepalive.c
+$(call make_c_module,edns_keepalive)
+
diff --git a/modules/etcd/README.rst b/modules/etcd/README.rst
new file mode 100644
index 0000000..5de55c2
--- /dev/null
+++ b/modules/etcd/README.rst
@@ -0,0 +1,44 @@
+.. _mod-etcd:
+
+Etcd module
+-----------
+
+The module connects to Etcd peers and watches for configuration change.
+By default, the module looks for the subtree under ``/knot-resolver`` directory,
+but you can change this `in the configuration <https://github.com/mah0x211/lua-etcd#cli-err--etcdnew-optiontable->`_.
+
+The subtree structure corresponds to the configuration variables in the declarative style.
+
+.. code-block:: bash
+
+ $ etcdctl set /knot-resolvevr/net/127.0.0.1 53
+ $ etcdctl set /knot-resolver/cache/size 10000000
+
+Configures all listening nodes to following configuration:
+
+.. code-block:: lua
+
+ net = { '127.0.0.1' }
+ cache.size = 10000000
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ modules = {
+ etcd = {
+ prefix = '/knot-resolver',
+ peer = 'http://127.0.0.1:7001'
+ }
+ }
+
+.. warning:: Work in progress!
+
+Dependencies
+^^^^^^^^^^^^
+
+* `lua-etcd <https://github.com/mah0x211/lua-etcd>`_ available in LuaRocks
+
+ ``$ luarocks install etcd --from=https://mah0x211.github.io/rocks/``
+
diff --git a/modules/etcd/etcd.lua b/modules/etcd/etcd.lua
new file mode 100644
index 0000000..4d4bbfb
--- /dev/null
+++ b/modules/etcd/etcd.lua
@@ -0,0 +1,55 @@
+--- @module etcd
+local etcd = {}
+
+-- @function update subtree configuration
+local function update_subtree(tree)
+ if not tree then return end
+ for _, k in pairs(tree) do
+ if k.dir then
+ update_subtree(k.nodes)
+ else
+ local key,opt = k.key:gmatch('([^/]+)/([^/]+)$')()
+ if _G[key][opt] ~= k.value then
+ _G[key][opt] = k.value
+ end
+ end
+ end
+end
+
+-- @function reload whole configuration
+function etcd.reload()
+ local res, err = etcd.cli:readdir('/', true)
+ if err then
+ error(err)
+ end
+ update_subtree(res.body.node.nodes)
+end
+
+function etcd.init()
+ etcd.Etcd = require('etcd.luasocket')
+ etcd.defaults = { prefix = '/knot-resolver' }
+end
+
+function etcd.deinit()
+ if etcd.ev then event.cancel(etcd.ev) end
+end
+
+function etcd.config(conf)
+ local options = etcd.defaults
+ if type(conf) == 'table' then
+ for k,v in pairs(conf) do options[k] = v end
+ end
+ -- create connection
+ local cli, err = etcd.Etcd.new(options)
+ if err then
+ error(err)
+ end
+ etcd.cli = cli
+ -- schedule recurrent polling
+ -- @todo: the etcd has watch() API, but this requires
+ -- coroutines on socket operations
+ if etcd.ev then event.cancel(etcd.ev) end
+ etcd.ev = event.recurrent(5 * sec, etcd.reload)
+end
+
+return etcd
diff --git a/modules/etcd/etcd.mk b/modules/etcd/etcd.mk
new file mode 100644
index 0000000..0b8d244
--- /dev/null
+++ b/modules/etcd/etcd.mk
@@ -0,0 +1,2 @@
+etcd_SOURCES := etcd.lua
+$(call make_lua_module,etcd)
diff --git a/modules/experimental_dot_auth/README.rst b/modules/experimental_dot_auth/README.rst
new file mode 100644
index 0000000..79c963b
--- /dev/null
+++ b/modules/experimental_dot_auth/README.rst
@@ -0,0 +1,84 @@
+.. _mod-experimental_dot_auth:
+
+Experimental DNS-over-TLS Auto-discovery
+----------------------------------------
+
+This experimental module provides automatic discovery of authoritative servers' supporting DNS-over-TLS.
+The module uses magic NS names to detect SPKI_ fingerprint which is very similar to `dnscurve`_ mechanism.
+
+.. warning:: This protocol and module is experimental and can be changed or removed at any time. Use at own risk, security properties were not analyzed!
+
+How it works
+^^^^^^^^^^^^
+
+The module will look for NS target names formatted as:
+``dot-{base32(sha256(SPKI))}....``
+
+For instance, Knot Resolver will detect NS names formatted like this
+
+.. code-block:: none
+
+ example.com NS dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.example.com
+
+and automatically discover that example.com NS supports DoT with the base64-encoded SPKI digest of ``m+12GgMFIiheEhKvUcOynjbn3WYQUp5tVGDh7Snwj/Q=``
+and will associate it with the IPs of ``dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.example.com``.
+
+In that example, the base32 encoded (no padding) version of the sha256 PIN is ``tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a``, which when
+converted to base64 translates to ``m+12GgMFIiheEhKvUcOynjbn3WYQUp5tVGDh7Snwj/Q=``.
+
+Generating NS target names
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To generate the NS target name, use the following command to generate the base32 encoded string of the SPKI fingerprint:
+
+.. code-block:: bash
+
+ openssl x509 -in /path/to/cert.pem -pubkey -noout | \
+ openssl pkey -pubin -outform der | \
+ openssl dgst -sha256 -binary | \
+ base32 | tr -d '=' | tr '[:upper:]' '[:lower:]'
+ tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a
+
+Then add a target to your NS with: ``dot-${b32}.a.example.com``
+
+Finally, map ``dot-${b32}.a.example.com`` to the right set of IPs.
+
+.. code-block:: bash
+
+ ...
+ ...
+ ;; QUESTION SECTION:
+ ;example.com. IN NS
+
+ ;; AUTHORITY SECTION:
+ example.com. 3600 IN NS dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.a.example.com.
+ example.com. 3600 IN NS dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.b.example.com.
+
+ ;; ADDITIONAL SECTION:
+ dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.a.example.com. 3600 IN A 192.0.2.1
+ dot-tpwxmgqdaurcqxqsckxvdq5sty3opxlgcbjj43kumdq62kpqr72a.b.example.com. 3600 IN AAAA 2001:DB8::1
+ ...
+ ...
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+To enable the module, add this snippet to your config:
+
+.. code-block:: lua
+
+ -- Start an experiment, use with caution
+ modules.load('experimental_dot_auth')
+
+This module requires standard ``basexx`` Lua library which is typically provided by ``lua-basexx`` package.
+
+Caveats
+^^^^^^^
+
+The module relies on seeing the reply of the NS query and as such will not work
+if Knot Resolver uses data from its cache. You may need to delete the cache before starting ``kresd`` to work around this.
+
+The module also assumes that the NS query answer will return both the NS targets in the Authority section as well as the glue records in the Additional section.
+
+.. _dnscurve: https://dnscurve.org/
+.. _SPKI: https://en.wikipedia.org/wiki/Simple_public-key_infrastructure
diff --git a/modules/experimental_dot_auth/basexx.lua b/modules/experimental_dot_auth/basexx.lua
new file mode 100644
index 0000000..86ac996
--- /dev/null
+++ b/modules/experimental_dot_auth/basexx.lua
@@ -0,0 +1,320 @@
+-- The MIT License (MIT)
+--
+-- Copyright (c) 2013 aiq
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy of
+-- this software and associated documentation files (the "Software"), to deal in
+-- the Software without restriction, including without limitation the rights to
+-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+-- the Software, and to permit persons to whom the Software is furnished to do so,
+-- subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in all
+-- copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+-- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+-- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+-- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--
+--
+--
+--------------------------------------------------------------------------------
+-- util functions
+--------------------------------------------------------------------------------
+
+local function divide_string( str, max )
+ local result = {}
+
+ local start = 1
+ for i = 1, #str do
+ if i % max == 0 then
+ table.insert( result, str:sub( start, i ) )
+ start = i + 1
+ elseif i == #str then
+ table.insert( result, str:sub( start, i ) )
+ end
+ end
+
+ return result
+end
+
+local function number_to_bit( num, length )
+ local bits = {}
+
+ while num > 0 do
+ local rest = math.floor( math.fmod( num, 2 ) )
+ table.insert( bits, rest )
+ num = ( num - rest ) / 2
+ end
+
+ while #bits < length do
+ table.insert( bits, "0" )
+ end
+
+ return string.reverse( table.concat( bits ) )
+end
+
+local function ignore_set( str, set )
+ if set then
+ str = str:gsub( "["..set.."]", "" )
+ end
+ return str
+end
+
+local function pure_from_bit( str )
+ return ( str:gsub( '........', function ( cc )
+ return string.char( tonumber( cc, 2 ) )
+ end ) )
+end
+
+local function unexpected_char_error( str, pos )
+ local c = string.sub( str, pos, pos )
+ return string.format( "unexpected character at position %d: '%s'", pos, c )
+end
+
+--------------------------------------------------------------------------------
+
+local basexx = {}
+
+--------------------------------------------------------------------------------
+-- base2(bitfield) decode and encode function
+--------------------------------------------------------------------------------
+
+local bitMap = { o = "0", i = "1", l = "1" }
+
+function basexx.from_bit( str, ignore )
+ str = ignore_set( str, ignore )
+ str = string.lower( str )
+ str = str:gsub( '[ilo]', function( c ) return bitMap[ c ] end )
+ local pos = string.find( str, "[^01]" )
+ if pos then return nil, unexpected_char_error( str, pos ) end
+
+ return pure_from_bit( str )
+end
+
+function basexx.to_bit( str )
+ return ( str:gsub( '.', function ( c )
+ local byte = string.byte( c )
+ local bits = {}
+ for _ = 1,8 do
+ table.insert( bits, byte % 2 )
+ byte = math.floor( byte / 2 )
+ end
+ return table.concat( bits ):reverse()
+ end ) )
+end
+
+--------------------------------------------------------------------------------
+-- base16(hex) decode and encode function
+--------------------------------------------------------------------------------
+
+function basexx.from_hex( str, ignore )
+ str = ignore_set( str, ignore )
+ local pos = string.find( str, "[^%x]" )
+ if pos then return nil, unexpected_char_error( str, pos ) end
+
+ return ( str:gsub( '..', function ( cc )
+ return string.char( tonumber( cc, 16 ) )
+ end ) )
+end
+
+function basexx.to_hex( str )
+ return ( str:gsub( '.', function ( c )
+ return string.format('%02X', string.byte( c ) )
+ end ) )
+end
+
+--------------------------------------------------------------------------------
+-- generic function to decode and encode base32/base64
+--------------------------------------------------------------------------------
+
+local function from_basexx( str, alphabet, bits )
+ local result = {}
+ for i = 1, #str do
+ local c = string.sub( str, i, i )
+ if c ~= '=' then
+ local index = string.find( alphabet, c, 1, true )
+ if not index then
+ return nil, unexpected_char_error( str, i )
+ end
+ table.insert( result, number_to_bit( index - 1, bits ) )
+ end
+ end
+
+ local value = table.concat( result )
+ local pad = #value % 8
+ return pure_from_bit( string.sub( value, 1, #value - pad ) )
+end
+
+local function to_basexx( str, alphabet, bits, pad )
+ local bitString = basexx.to_bit( str )
+
+ local chunks = divide_string( bitString, bits )
+ local result = {}
+ for _,value in ipairs( chunks ) do
+ if ( #value < bits ) then
+ value = value .. string.rep( '0', bits - #value )
+ end
+ local pos = tonumber( value, 2 ) + 1
+ table.insert( result, alphabet:sub( pos, pos ) )
+ end
+
+ table.insert( result, pad )
+ return table.concat( result )
+end
+
+--------------------------------------------------------------------------------
+-- rfc 3548: http://www.rfc-editor.org/rfc/rfc3548.txt
+--------------------------------------------------------------------------------
+
+local base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
+local base32PadMap = { "", "======", "====", "===", "=" }
+
+function basexx.from_base32( str, ignore )
+ str = ignore_set( str, ignore )
+ return from_basexx( string.upper( str ), base32Alphabet, 5 )
+end
+
+function basexx.to_base32( str )
+ return to_basexx( str, base32Alphabet, 5, base32PadMap[ #str % 5 + 1 ] )
+end
+
+--------------------------------------------------------------------------------
+-- crockford: http://www.crockford.com/wrmg/base32.html
+--------------------------------------------------------------------------------
+
+local crockfordAlphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+local crockfordMap = { O = "0", I = "1", L = "1" }
+
+function basexx.from_crockford( str, ignore )
+ str = ignore_set( str, ignore )
+ str = string.upper( str )
+ str = str:gsub( '[ILOU]', function( c ) return crockfordMap[ c ] end )
+ return from_basexx( str, crockfordAlphabet, 5 )
+end
+
+function basexx.to_crockford( str )
+ return to_basexx( str, crockfordAlphabet, 5, "" )
+end
+
+--------------------------------------------------------------------------------
+-- base64 decode and encode function
+--------------------------------------------------------------------------------
+
+local base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"..
+ "abcdefghijklmnopqrstuvwxyz"..
+ "0123456789+/"
+local base64PadMap = { "", "==", "=" }
+
+function basexx.from_base64( str, ignore )
+ str = ignore_set( str, ignore )
+ return from_basexx( str, base64Alphabet, 6 )
+end
+
+function basexx.to_base64( str )
+ return to_basexx( str, base64Alphabet, 6, base64PadMap[ #str % 3 + 1 ] )
+end
+
+--------------------------------------------------------------------------------
+-- URL safe base64 decode and encode function
+--------------------------------------------------------------------------------
+
+local url64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"..
+ "abcdefghijklmnopqrstuvwxyz"..
+ "0123456789-_"
+
+function basexx.from_url64( str, ignore )
+ str = ignore_set( str, ignore )
+ return from_basexx( str, url64Alphabet, 6 )
+end
+
+function basexx.to_url64( str )
+ return to_basexx( str, url64Alphabet, 6, "" )
+end
+
+--------------------------------------------------------------------------------
+--
+--------------------------------------------------------------------------------
+
+local function length_error( len, d )
+ return string.format( "invalid length: %d - must be a multiple of %d", len, d )
+end
+
+local z85Decoder = { 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
+ 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
+ 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+ 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
+ 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
+ 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 }
+
+function basexx.from_z85( str, ignore )
+ str = ignore_set( str, ignore )
+ if ( #str % 5 ) ~= 0 then
+ return nil, length_error( #str, 5 )
+ end
+
+ local result = {}
+
+ local value = 0
+ for i = 1, #str do
+ local index = string.byte( str, i ) - 31
+ if index < 1 or index >= #z85Decoder then
+ return nil, unexpected_char_error( str, i )
+ end
+ value = ( value * 85 ) + z85Decoder[ index ]
+ if ( i % 5 ) == 0 then
+ local divisor = 256 * 256 * 256
+ while divisor ~= 0 do
+ local b = math.floor( value / divisor ) % 256
+ table.insert( result, string.char( b ) )
+ divisor = math.floor( divisor / 256 )
+ end
+ value = 0
+ end
+ end
+
+ return table.concat( result )
+end
+
+local z85Encoder = "0123456789"..
+ "abcdefghijklmnopqrstuvwxyz"..
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"..
+ ".-:+=^!/*?&<>()[]{}@%$#"
+
+function basexx.to_z85( str )
+ if ( #str % 4 ) ~= 0 then
+ return nil, length_error( #str, 4 )
+ end
+
+ local result = {}
+
+ local value = 0
+ for i = 1, #str do
+ local b = string.byte( str, i )
+ value = ( value * 256 ) + b
+ if ( i % 4 ) == 0 then
+ local divisor = 85 * 85 * 85 * 85
+ while divisor ~= 0 do
+ local index = ( math.floor( value / divisor ) % 85 ) + 1
+ table.insert( result, z85Encoder:sub( index, index ) )
+ divisor = math.floor( divisor / 85 )
+ end
+ value = 0
+ end
+ end
+
+ return table.concat( result )
+end
+
+--------------------------------------------------------------------------------
+
+return basexx
diff --git a/modules/experimental_dot_auth/experimental_dot_auth.lua b/modules/experimental_dot_auth/experimental_dot_auth.lua
new file mode 100644
index 0000000..f5ab6be
--- /dev/null
+++ b/modules/experimental_dot_auth/experimental_dot_auth.lua
@@ -0,0 +1,122 @@
+-- Module interface
+
+local ffi = require('ffi')
+local basexx = require('basexx')
+local C = ffi.C
+
+-- Export module interface
+local M = {}
+M.layer = {}
+local base32 = {}
+local str = {}
+local AF_INET = 2
+local AF_INET6 = 10
+local INET_ADDRSTRLEN = 16
+local INET6_ADDRSTRLEN = 46
+
+ffi.cdef[[
+/*
+ * Data structures
+ */
+typedef int socklen_t;
+ struct sockaddr_storage{
+ unsigned short int ss_family;
+ unsigned long int __ss_align;
+ char __ss_padding[128 - (2 *sizeof(unsigned long int))];
+ };
+ struct in_addr{
+ unsigned char s_addr[4];
+ };
+ struct in6_addr{
+ unsigned char s6_addr[16];
+ };
+ struct sockaddr_in{
+ short sin_family;
+ unsigned short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+ } __attribute__ ((__packed__));
+ struct sockaddr_in6{
+ unsigned short sin6_family;
+ unsigned short sin6_port;
+ unsigned int sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ unsigned int sin6_scope_id;
+ };
+ typedef unsigned short sa_family_t;
+ struct sockaddr_un {
+ sa_family_t sun_family;
+ char sun_path[108];
+ };
+ const char *inet_ntop(
+ int af,
+ const void *cp,
+ char *buf,
+ socklen_t len);
+]]
+
+function base32.pad(b32)
+ local m = #b32 % 8
+ if m ~= 0 then
+ b32 = b32 .. string.rep("=", 8 - m)
+ end
+ return b32
+end
+
+function str.starts(String,Start)
+ return string.sub(String,1,string.len(Start))==Start
+end
+
+-- Handle DoT signalling NS domains.
+function M.layer.consume(state, _, pkt)
+ if state == kres.FAIL then return state end
+ -- Only successful answers
+ pkt = kres.pkt_t(pkt)
+ -- log("%s", pkt:tostring())
+ local authority = pkt:section(kres.section.AUTHORITY)
+ local additional = pkt:section(kres.section.ADDITIONAL)
+ for _, rr in ipairs(authority) do
+ --log("%d %s", rr.type, kres.dname2str(rr.rdata))
+ if rr.type == kres.type.NS then
+ local name = kres.dname2str(rr.rdata):upper()
+ -- log("NS %d", name:len())
+ if name:len() > 56 and str.starts(name, "DOT-") then
+ local k = basexx.to_base64(
+ basexx.from_base32(
+ base32.pad(string.sub(name, 5, string.find(name, '[.]') - 1))
+ )
+ )
+ for _, rr_add in ipairs(additional) do
+ if rr_add.type == kres.type.A or rr_add.type == kres.type.AAAA then
+ local name_add = kres.dname2str(rr_add.owner):upper()
+ if name == name_add then
+ local addrbuf
+ if rr_add.type == kres.type.A then
+ local ns_addr = ffi.new("struct sockaddr_in")
+ ns_addr.sin_family = AF_INET
+
+ ns_addr.sin_addr.s_addr = rr_add.rdata
+ addrbuf = ffi.new("char[?]", INET_ADDRSTRLEN)
+ C.inet_ntop(AF_INET, ns_addr.sin_addr, addrbuf, INET_ADDRSTRLEN)
+ else
+ local ns_addr = ffi.new("struct sockaddr_in6")
+ ns_addr.sin6_family = AF_INET6
+
+ ns_addr.sin6_addr.s6_addr = rr_add.rdata
+ addrbuf = ffi.new("char[?]", INET6_ADDRSTRLEN)
+ C.inet_ntop(AF_INET6, ns_addr.sin6_addr, addrbuf, INET6_ADDRSTRLEN)
+ end
+ net.tls_client(ffi.string(addrbuf).."@853", {k})
+ log("Adding %s IP %s %s", name_add, ffi.string(addrbuf).."@853", k)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ return state
+
+end
+
+return M
diff --git a/modules/experimental_dot_auth/experimental_dot_auth.mk b/modules/experimental_dot_auth/experimental_dot_auth.mk
new file mode 100644
index 0000000..6f93fcd
--- /dev/null
+++ b/modules/experimental_dot_auth/experimental_dot_auth.mk
@@ -0,0 +1,2 @@
+experimental_dot_auth_SOURCES := experimental_dot_auth.lua basexx.lua
+$(call make_lua_module,experimental_dot_auth)
diff --git a/modules/graphite/README.rst b/modules/graphite/README.rst
new file mode 100644
index 0000000..06efd82
--- /dev/null
+++ b/modules/graphite/README.rst
@@ -0,0 +1,49 @@
+.. _mod-graphite:
+
+Graphite module
+---------------
+
+The module sends statistics over the Graphite_ protocol to either Graphite_, Metronome_, InfluxDB_ or any compatible storage. This allows powerful visualization over metrics collected by Knot Resolver.
+
+.. tip:: The Graphite server is challenging to get up and running, InfluxDB_ combined with Grafana_ are much easier, and provide richer set of options and available front-ends. Metronome_ by PowerDNS alternatively provides a mini-graphite server for much simpler setups.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+Only the ``host`` parameter is mandatory.
+
+By default the module uses UDP so it doesn't guarantee the delivery, set ``tcp = true`` to enable Graphite over TCP. If the TCP consumer goes down or the connection with Graphite is lost, resolver will periodically attempt to reconnect with it.
+
+.. code-block:: lua
+
+ modules = {
+ graphite = {
+ prefix = hostname(), -- optional metric prefix
+ host = '127.0.0.1', -- graphite server address
+ port = 2003, -- graphite server port
+ interval = 5 * sec, -- publish interval
+ tcp = false -- set to true if want TCP mode
+ }
+ }
+
+The module supports sending data to multiple servers at once.
+
+.. code-block:: lua
+
+ modules = {
+ graphite = {
+ host = { '127.0.0.1', '1.2.3.4', '::1' },
+ }
+ }
+
+Dependencies
+^^^^^^^^^^^^
+
+* `luasocket <http://w3.impa.br/~diego/software/luasocket/>`_ available in LuaRocks
+
+ ``$ luarocks install luasocket``
+
+.. _Graphite: https://graphite.readthedocs.io/en/latest/feeding-carbon.html
+.. _InfluxDB: https://influxdb.com/
+.. _Metronome: https://github.com/ahuPowerDNS/metronome
+.. _Grafana: http://grafana.org/
diff --git a/modules/graphite/graphite.lua b/modules/graphite/graphite.lua
new file mode 100644
index 0000000..bbf735a
--- /dev/null
+++ b/modules/graphite/graphite.lua
@@ -0,0 +1,141 @@
+-- Load dependent modules
+if not stats then modules.load('stats') end
+
+-- This is leader-only module
+if worker.id > 0 then return {} end
+local M = {}
+local socket = require('socket')
+
+-- Create connected UDP socket
+local function make_udp(host, port)
+ local s, err, status
+ if host:find(':') then
+ s, err = socket.udp6()
+ else
+ s, err = socket.udp()
+ end
+ if not s then
+ return nil, err
+ end
+ status, err = s:setpeername(host, port)
+ if not status then
+ return nil, err
+ end
+ return s
+end
+
+-- Create connected TCP socket
+local function make_tcp(host, port)
+ local s, err, status
+ if host:find(':') then
+ s, err = socket.tcp6()
+ else
+ s, err = socket.tcp()
+ end
+ if not s then
+ return nil, err
+ end
+ status, err = s:connect(host, port)
+ if not status then
+ return s, err
+ end
+ return s
+end
+
+local function merge(results)
+ local t = {}
+ for _, result in ipairs(results) do
+ for k, v in pairs(result) do
+ t[k] = (t[k] or 0) + v
+ end
+ end
+ return t
+end
+
+-- Send the metrics in a table to multiple Graphite consumers
+local function publish_table(metrics, prefix, now)
+ for key,val in pairs(metrics) do
+ local msg = key..' '..val..' '..now..'\n'
+ if prefix then
+ msg = prefix..'.'..msg
+ end
+ for i in ipairs(M.cli) do
+ local ok, err = M.cli[i]:send(msg)
+ if not ok then
+ -- Best-effort reconnect once per two tries
+ local tcp = M.cli[i]['connect'] ~= nil
+ local host = M.info[i]
+ if tcp and host.seen + 2 * M.interval / 1000 <= now then
+ print(string.format('[graphite] reconnecting: %s@%d reason: %s',
+ host.addr, host.port, err))
+ M.cli[i] = make_tcp(host.addr, host.port)
+ host.seen = now
+ end
+ end
+ end
+ end
+end
+
+function M.init()
+ M.ev = nil
+ M.cli = {}
+ M.info = {}
+ M.interval = 5 * sec
+ M.prefix = 'kresd.' .. hostname()
+ return 0
+end
+
+function M.deinit()
+ if M.ev then event.cancel(M.ev) end
+ return 0
+end
+
+-- @function Publish results to the Graphite server(s)
+function M.publish()
+ local now = os.time()
+ -- Publish built-in statistics
+ if not M.cli then error("no graphite server configured") end
+ publish_table(merge(map 'cache.stats()'), M.prefix..'.cache', now)
+ publish_table(merge(map 'worker.stats()'), M.prefix..'.worker', now)
+ -- Publish extended statistics if available
+ publish_table(merge(map 'stats.list()'), M.prefix, now)
+ return 0
+end
+
+-- @function Make connection to Graphite server.
+function M.add_server(_, host, port, tcp)
+ local s, err
+ if tcp then
+ s, err = make_tcp(host, port)
+ else
+ s, err = make_udp(host, port)
+ end
+ if not s then
+ error(err)
+ end
+ table.insert(M.cli, s)
+ table.insert(M.info, {addr = host, port = port, seen = 0})
+ return 0
+end
+
+function M.config(conf)
+ -- config defaults
+ if not conf then return 0 end
+ if not conf.port then conf.port = 2003 end
+ if conf.interval then M.interval = conf.interval end
+ if conf.prefix then M.prefix = conf.prefix end
+ -- connect to host(s)
+ if type(conf.host) == 'table' then
+ for _, val in pairs(conf.host) do
+ M:add_server(val, conf.port, conf.tcp)
+ end
+ else
+ M:add_server(conf.host, conf.port, conf.tcp)
+ end
+ -- start publishing stats
+ if M.ev then event.cancel(M.ev) end
+ M.ev = event.recurrent(M.interval, M.publish)
+ return 0
+end
+
+return M
diff --git a/modules/graphite/graphite.mk b/modules/graphite/graphite.mk
new file mode 100644
index 0000000..615f8be
--- /dev/null
+++ b/modules/graphite/graphite.mk
@@ -0,0 +1,2 @@
+graphite_SOURCES := graphite.lua
+$(call make_lua_module,graphite)
diff --git a/modules/hints/README.rst b/modules/hints/README.rst
new file mode 100644
index 0000000..a42d19c
--- /dev/null
+++ b/modules/hints/README.rst
@@ -0,0 +1,113 @@
+.. _mod-hints:
+
+Static hints
+------------
+
+This is a module providing static hints for forward records (A/AAAA) and reverse records (PTR).
+The records can be loaded from ``/etc/hosts``-like files and/or added directly.
+
+You can also use the module to change the root hints; they are used as a safety belt or if the root NS
+drops out of cache.
+
+Examples
+^^^^^^^^
+
+.. code-block:: lua
+
+ -- Load hints after iterator (so hints take precedence before caches)
+ modules = { 'hints > iterate' }
+ -- Add a custom hosts file
+ hints.add_hosts('hosts.custom')
+ -- Override the root hints
+ hints.root({
+ ['j.root-servers.net.'] = { '2001:503:c27::2:30', '192.58.128.30' }
+ })
+ -- Add a custom hint
+ hints['foo.bar'] = '127.0.0.1'
+
+.. note:: The :ref:`policy <mod-policy>` module applies before hints, meaning e.g. that hints for special names (:rfc:`6761#section-6`) like ``localhost`` or ``test`` will get shadowed by policy rules by default.
+ That can be worked around e.g. by explicit ``policy.PASS`` action.
+
+Properties
+^^^^^^^^^^
+
+.. function:: hints.config([path])
+
+ :param string path: path to hosts-like file, default: no file
+ :return: ``{ result: bool }``
+
+ Clear any configured hints, and optionally load a hosts-like file as in ``hints.add_hosts(path)``.
+ (Root hints are not touched.)
+
+.. function:: hints.add_hosts([path])
+
+ :param string path: path to hosts-like file, default: ``/etc/hosts``
+
+ Add hints from a host-like file.
+
+.. function:: hints.get(hostname)
+
+ :param string hostname: i.e. ``"localhost"``
+ :return: ``{ result: [address1, address2, ...] }``
+
+ Return list of address record matching given name.
+ If no hostname is specified, all hints are returned in the table format used by ``hints.root()``.
+
+.. function:: hints.set(pair)
+
+ :param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``
+ :return: ``{ result: bool }``
+
+ Add a hostname--address pair hint.
+
+ .. note::
+
+ If multiple addresses have been added for a name (in separate ``hints.set()`` commands),
+ all are returned in a forward query.
+ If multiple names have been added to an address, the last one defined is returned
+ in a corresponding PTR query.
+
+.. function:: hints.del(pair)
+
+ :param string pair: ``hostname address`` i.e. ``"localhost 127.0.0.1"``, or just ``hostname``
+ :return: ``{ result: bool }``
+
+ Remove a hostname - address pair hint. If address is omitted, all addresses for the given name are deleted.
+
+.. function:: hints.root_file(path)
+
+ Replace current root hints from a zonefile. If the path is omitted, the compiled-in path is used, i.e. the root hints are reset to the default.
+
+.. function:: hints.root(root_hints)
+
+ :param table root_hints: new set of root hints i.e. ``{['name'] = 'addr', ...}``
+ :return: ``{ ['a.root-servers.net.'] = { '1.2.3.4', '5.6.7.8', ...}, ... }``
+
+ Replace current root hints and return the current table of root hints.
+
+ .. tip:: If no parameters are passed, it only returns current root hints set without changing anything.
+
+ Example:
+
+ .. code-block:: lua
+
+ > hints.root({
+ ['l.root-servers.net.'] = '199.7.83.42',
+ ['m.root-servers.net.'] = '202.12.27.33'
+ })
+ [l.root-servers.net.] => {
+ [1] => 199.7.83.42
+ }
+ [m.root-servers.net.] => {
+ [1] => 202.12.27.33
+ }
+
+ .. tip:: A good rule of thumb is to select only a few fastest root hints. The server learns RTT and NS quality over time, and thus tries all servers available. You can help it by preselecting the candidates.
+
+.. function:: hints.use_nodata(toggle)
+
+ :param bool toggle: true if enabling NODATA synthesis, false if disabling
+ :return: ``{ result: bool }``
+
+ If set to true (the default), NODATA will be synthesised for matching hint name, but mismatching type (e.g. AAAA query when only A hint exists).
+
diff --git a/modules/hints/hints.c b/modules/hints/hints.c
new file mode 100644
index 0000000..84e2e99
--- /dev/null
+++ b/modules/hints/hints.c
@@ -0,0 +1,668 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file hints.c
+ * @brief Constructed zone cut from the hosts-like file, see @zonecut.h
+ *
+ * The module provides an override for queried address records.
+ */
+
+#include <libknot/packet/pkt.h>
+#include <libknot/descriptor.h>
+#include <ccan/json/json.h>
+#include <ucw/mempool.h>
+#include <contrib/cleanup.h>
+#include <lauxlib.h>
+
+#include "daemon/engine.h"
+#include "lib/zonecut.h"
+#include "lib/module.h"
+#include "lib/layer.h"
+
+/* Defaults */
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "hint", __VA_ARGS__)
+#define ERR_MSG(...) kr_log_error("[ ][hint] " __VA_ARGS__)
+
+struct hints_data {
+ struct kr_zonecut hints;
+ struct kr_zonecut reverse_hints;
+ bool use_nodata; /**< See hint_use_nodata() description, exposed via lua. */
+};
+
+/** Useful for returning from module properties. */
+static char * bool2jsonstr(bool val)
+{
+ char *result = NULL;
+ if (-1 == asprintf(&result, "{ \"result\": %s }", val ? "true" : "false"))
+ result = NULL;
+ return result;
+}
+
+static int put_answer(knot_pkt_t *pkt, struct kr_query *qry, knot_rrset_t *rr, bool use_nodata)
+{
+ int ret = 0;
+ if (!knot_rrset_empty(rr) || use_nodata) {
+ /* Update packet question */
+ if (!knot_dname_is_equal(knot_pkt_qname(pkt), rr->owner)) {
+ kr_pkt_recycle(pkt);
+ knot_pkt_put_question(pkt, qry->sname, qry->sclass, qry->stype);
+ }
+ if (!knot_rrset_empty(rr)) {
+ /* Append to packet */
+ ret = knot_pkt_put_rotate(pkt, KNOT_COMPR_HINT_QNAME, rr,
+ qry->reorder, KNOT_PF_FREE);
+ } else {
+ /* Return empty answer if name exists, but type doesn't match */
+ knot_wire_set_aa(pkt->wire);
+ }
+ } else {
+ ret = kr_error(ENOENT);
+ }
+ /* Clear RR if failed */
+ if (ret != 0) {
+ knot_rrset_clear(rr, &pkt->mm);
+ }
+ return ret;
+}
+
+static int satisfy_reverse(struct kr_zonecut *hints, knot_pkt_t *pkt, struct kr_query *qry, bool use_nodata)
+{
+ /* Find a matching name */
+ pack_t *addr_set = kr_zonecut_find(hints, qry->sname);
+ if (!addr_set || addr_set->len == 0) {
+ return kr_error(ENOENT);
+ }
+ knot_dname_t *qname = knot_dname_copy(qry->sname, &pkt->mm);
+ knot_rrset_t rr;
+ knot_rrset_init(&rr, qname, KNOT_RRTYPE_PTR, KNOT_CLASS_IN, 0);
+
+ /* Append address records from hints */
+ uint8_t *addr = pack_last(*addr_set);
+ if (addr != NULL) {
+ size_t len = pack_obj_len(addr);
+ void *addr_val = pack_obj_val(addr);
+ knot_rrset_add_rdata(&rr, addr_val, len, &pkt->mm);
+ }
+
+ return put_answer(pkt, qry, &rr, use_nodata);
+}
+
+static int satisfy_forward(struct kr_zonecut *hints, knot_pkt_t *pkt, struct kr_query *qry, bool use_nodata)
+{
+ /* Find a matching name */
+ pack_t *addr_set = kr_zonecut_find(hints, qry->sname);
+ if (!addr_set || addr_set->len == 0) {
+ return kr_error(ENOENT);
+ }
+ knot_dname_t *qname = knot_dname_copy(qry->sname, &pkt->mm);
+ knot_rrset_t rr;
+ knot_rrset_init(&rr, qname, qry->stype, qry->sclass, 0);
+ size_t family_len = sizeof(struct in_addr);
+ if (rr.type == KNOT_RRTYPE_AAAA) {
+ family_len = sizeof(struct in6_addr);
+ }
+
+ /* Append address records from hints */
+ uint8_t *addr = pack_head(*addr_set);
+ while (addr != pack_tail(*addr_set)) {
+ size_t len = pack_obj_len(addr);
+ void *addr_val = pack_obj_val(addr);
+ if (len == family_len) {
+ knot_rrset_add_rdata(&rr, addr_val, len, &pkt->mm);
+ }
+ addr = pack_obj_next(addr);
+ }
+
+ return put_answer(pkt, qry, &rr, use_nodata);
+}
+
+static int query(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_query *qry = ctx->req->current_query;
+ if (!qry || ctx->state & (KR_STATE_FAIL)) {
+ return ctx->state;
+ }
+
+ struct kr_module *module = ctx->api->data;
+ struct hints_data *data = module->data;
+ if (!data) { /* No valid file. */
+ return ctx->state;
+ }
+ /* FIXME: putting directly into packet breaks ordering in case the hint
+ * is applied after a CNAME jump. */
+ switch(qry->stype) {
+ case KNOT_RRTYPE_A:
+ case KNOT_RRTYPE_AAAA: /* Find forward record hints */
+ if (satisfy_forward(&data->hints, pkt, qry, data->use_nodata) != 0)
+ return ctx->state;
+ break;
+ case KNOT_RRTYPE_PTR: /* Find PTR record */
+ if (satisfy_reverse(&data->reverse_hints, pkt, qry, data->use_nodata) != 0)
+ return ctx->state;
+ break;
+ default:
+ return ctx->state; /* Ignore */
+ }
+
+ VERBOSE_MSG(qry, "<= answered from hints\n");
+ qry->flags.DNSSEC_WANT = false; /* Never authenticated */
+ qry->flags.CACHED = true;
+ qry->flags.NO_MINIMIZE = true;
+ pkt->parsed = pkt->size;
+ knot_wire_set_qr(pkt->wire);
+ return KR_STATE_DONE;
+}
+
+static int parse_addr_str(union inaddr *sa, const char *addr)
+{
+ int family = strchr(addr, ':') ? AF_INET6 : AF_INET;
+ memset(sa, 0, sizeof(*sa));
+ sa->ip.sa_family = family;
+ char *addr_bytes = (/*const*/char *)kr_inaddr(&sa->ip);
+ if (inet_pton(family, addr, addr_bytes) < 1) {
+ return kr_error(EILSEQ);
+ }
+ return 0;
+}
+
+/** @warning _NOT_ thread-safe; returns a pointer to static data! */
+static const knot_dname_t * raw_addr2reverse(const uint8_t *raw_addr, int family)
+{
+ #define REV_MAXLEN (4*16 + 16 /* the suffix, terminator, etc. */)
+ char reverse_addr[REV_MAXLEN];
+ static knot_dname_t dname[REV_MAXLEN];
+ #undef REV_MAXLEN
+
+ if (family == AF_INET) {
+ snprintf(reverse_addr, sizeof(reverse_addr),
+ "%d.%d.%d.%d.in-addr.arpa.",
+ raw_addr[3], raw_addr[2], raw_addr[1], raw_addr[0]);
+ } else if (family == AF_INET6) {
+ char *ra_it = reverse_addr;
+ for (int i = 15; i >= 0; --i) {
+ ssize_t free_space = reverse_addr + sizeof(reverse_addr) - ra_it;
+ int written = snprintf(ra_it, free_space, "%x.%x.",
+ raw_addr[i] & 0x0f, raw_addr[i] >> 4);
+ if (written >= free_space) {
+ assert(false);
+ return NULL;
+ }
+ ra_it += written;
+ }
+ ssize_t free_space = reverse_addr + sizeof(reverse_addr) - ra_it;
+ if (snprintf(ra_it, free_space, "ip6.arpa.") >= free_space) {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+
+ if (!knot_dname_from_str(dname, reverse_addr, sizeof(dname))) {
+ return NULL;
+ }
+ return dname;
+}
+
+static const knot_dname_t * addr2reverse(const char *addr)
+{
+ /* Parse address string */
+ union inaddr ia;
+ if (parse_addr_str(&ia, addr) != 0) {
+ return NULL;
+ }
+ return raw_addr2reverse((const /*sign*/uint8_t *)kr_inaddr(&ia.ip),
+ kr_inaddr_family(&ia.ip));
+}
+
+static int add_pair(struct kr_zonecut *hints, const char *name, const char *addr)
+{
+ /* Build key */
+ knot_dname_t key[KNOT_DNAME_MAXLEN];
+ if (!knot_dname_from_str(key, name, sizeof(key))) {
+ return kr_error(EINVAL);
+ }
+ knot_dname_to_lower(key);
+
+ union inaddr ia;
+ if (parse_addr_str(&ia, addr) != 0) {
+ return kr_error(EINVAL);
+ }
+
+ return kr_zonecut_add(hints, key, kr_inaddr(&ia.ip), kr_inaddr_len(&ia.ip));
+}
+
+static int add_reverse_pair(struct kr_zonecut *hints, const char *name, const char *addr)
+{
+ const knot_dname_t *key = addr2reverse(addr);
+
+ if (key == NULL) {
+ return kr_error(EINVAL);
+ }
+
+ knot_dname_t ptr_name[KNOT_DNAME_MAXLEN];
+ if (!knot_dname_from_str(ptr_name, name, sizeof(ptr_name))) {
+ return kr_error(EINVAL);
+ }
+
+ return kr_zonecut_add(hints, key, ptr_name, knot_dname_size(ptr_name));
+}
+
+/** For a given name, remove either one address or all of them (if == NULL).
+ *
+ * Also remove the corresponding reverse records.
+ */
+static int del_pair(struct hints_data *data, const char *name, const char *addr)
+{
+ /* Build key */
+ knot_dname_t key[KNOT_DNAME_MAXLEN];
+ if (!knot_dname_from_str(key, name, sizeof(key))) {
+ return kr_error(EINVAL);
+ }
+ int key_len = knot_dname_size(key);
+
+ if (addr) {
+ /* Remove the pair. */
+ union inaddr ia;
+ if (parse_addr_str(&ia, addr) != 0) {
+ return kr_error(EINVAL);
+ }
+
+ const knot_dname_t *reverse_key = addr2reverse(addr);
+ kr_zonecut_del(&data->reverse_hints, reverse_key, key, key_len);
+ return kr_zonecut_del(&data->hints, key,
+ kr_inaddr(&ia.ip), kr_inaddr_len(&ia.ip));
+ }
+ /* We're removing everything for the name;
+ * first find the name's pack */
+ pack_t *addr_set = kr_zonecut_find(&data->hints, key);
+ if (!addr_set || addr_set->len == 0) {
+ return kr_error(ENOENT);
+ }
+
+ /* Remove address records in hints from reverse_hints. */
+
+ for (uint8_t *a = pack_head(*addr_set); a != pack_tail(*addr_set);
+ a = pack_obj_next(a)) {
+ void *addr_val = pack_obj_val(a);
+ int family = pack_obj_len(a) == kr_family_len(AF_INET)
+ ? AF_INET : AF_INET6;
+ const knot_dname_t *reverse_key = raw_addr2reverse(addr_val, family);
+ if (reverse_key != NULL) {
+ kr_zonecut_del(&data->reverse_hints, reverse_key, key, key_len);
+ }
+ }
+
+ /* Remove the whole name. */
+ return kr_zonecut_del_all(&data->hints, key);
+}
+
+static int load_file(struct kr_module *module, const char *path)
+{
+ auto_fclose FILE *fp = fopen(path, "r");
+ if (fp == NULL) {
+ ERR_MSG("reading '%s' failed: %s\n", path, strerror(errno));
+ return kr_error(errno);
+ } else {
+ VERBOSE_MSG(NULL, "reading '%s'\n", path);
+ }
+
+ /* Load file to map */
+ struct hints_data *data = module->data;
+ size_t line_len = 0;
+ size_t count = 0;
+ size_t line_count = 0;
+ auto_free char *line = NULL;
+ int ret = kr_ok();
+
+ while (getline(&line, &line_len, fp) > 0) {
+ ++line_count;
+ char *saveptr = NULL;
+ const char *addr = strtok_r(line, " \t\n", &saveptr);
+ if (addr == NULL || strchr(addr, '#') || strlen(addr) == 0) {
+ continue;
+ }
+ const char *canonical_name = strtok_r(NULL, " \t\n", &saveptr);
+ if (canonical_name == NULL) {
+ ret = -1;
+ goto error;
+ }
+ /* Since the last added PTR records takes preference,
+ * we add canonical name as the last one. */
+ const char *name_tok;
+ while ((name_tok = strtok_r(NULL, " \t\n", &saveptr)) != NULL) {
+ ret = add_pair(&data->hints, name_tok, addr);
+ if (!ret) {
+ ret = add_reverse_pair(&data->reverse_hints, name_tok, addr);
+ }
+ if (ret) {
+ ret = -1;
+ goto error;
+ }
+ count += 1;
+ }
+ ret = add_pair(&data->hints, canonical_name, addr);
+ if (!ret) {
+ ret = add_reverse_pair(&data->reverse_hints, canonical_name, addr);
+ }
+ if (ret) {
+ ret = -1;
+ goto error;
+ }
+ count += 1;
+ }
+error:
+ if (ret) {
+ ret = kr_error(ret);
+ ERR_MSG("%s:%zu: invalid syntax\n", path, line_count);
+ }
+ VERBOSE_MSG(NULL, "loaded %zu hints\n", count);
+ return ret;
+}
+
+static char* hint_add_hosts(void *env, struct kr_module *module, const char *args)
+{
+ if (!args)
+ args = "/etc/hosts";
+ int err = load_file(module, args);
+ return bool2jsonstr(err == kr_ok());
+}
+
+/**
+ * Set name => address hint.
+ *
+ * Input: { name, address }
+ * Output: { result: bool }
+ *
+ */
+static char* hint_set(void *env, struct kr_module *module, const char *args)
+{
+ struct hints_data *data = module->data;
+ if (!args)
+ return NULL;
+ auto_free char *args_copy = strdup(args);
+ if (!args_copy)
+ return NULL;
+
+ int ret = -1;
+ char *addr = strchr(args_copy, ' ');
+ if (addr) {
+ *addr = '\0';
+ ++addr;
+ ret = add_reverse_pair(&data->reverse_hints, args_copy, addr);
+ if (ret) {
+ del_pair(data, args_copy, addr);
+ } else {
+ ret = add_pair(&data->hints, args_copy, addr);
+ }
+ }
+
+ return bool2jsonstr(ret == 0);
+}
+
+static char* hint_del(void *env, struct kr_module *module, const char *args)
+{
+ struct hints_data *data = module->data;
+ if (!args)
+ return NULL;
+ auto_free char *args_copy = strdup(args);
+ if (!args_copy)
+ return NULL;
+
+ int ret = -1;
+ char *addr = strchr(args_copy, ' ');
+ if (addr) {
+ *addr = '\0';
+ ++addr;
+ }
+ ret = del_pair(data, args_copy, addr);
+
+ return bool2jsonstr(ret == 0);
+}
+
+/** @internal Pack address list into JSON array. */
+static JsonNode *pack_addrs(pack_t *pack)
+{
+ char buf[INET6_ADDRSTRLEN];
+ JsonNode *root = json_mkarray();
+ uint8_t *addr = pack_head(*pack);
+ while (addr != pack_tail(*pack)) {
+ size_t len = pack_obj_len(addr);
+ int family = len == sizeof(struct in_addr) ? AF_INET : AF_INET6;
+ if (!inet_ntop(family, pack_obj_val(addr), buf, sizeof(buf))) {
+ break;
+ }
+ json_append_element(root, json_mkstring(buf));
+ addr = pack_obj_next(addr);
+ }
+ return root;
+}
+
+static char* pack_hints(struct kr_zonecut *hints);
+/**
+ * Retrieve address hints, either for given name or for all names.
+ *
+ * Input: name
+ * Output: NULL or "{ address1, address2, ... }"
+ */
+static char* hint_get(void *env, struct kr_module *module, const char *args)
+{
+ struct kr_zonecut *hints = &((struct hints_data *) module->data)->hints;
+ if (!hints) {
+ assert(false);
+ return NULL;
+ }
+
+ if (!args) {
+ return pack_hints(hints);
+ }
+
+ knot_dname_t key[KNOT_DNAME_MAXLEN];
+ pack_t *pack = NULL;
+ if (knot_dname_from_str(key, args, sizeof(key))) {
+ pack = kr_zonecut_find(hints, key);
+ }
+ if (!pack || pack->len == 0) {
+ return NULL;
+ }
+
+ char *result = NULL;
+ JsonNode *root = pack_addrs(pack);
+ if (root) {
+ result = json_encode(root);
+ json_delete(root);
+ }
+ return result;
+}
+
+/** @internal Pack all hints into serialized JSON. */
+static char* pack_hints(struct kr_zonecut *hints) {
+ char *result = NULL;
+ JsonNode *root_node = json_mkobject();
+ trie_it_t *it;
+ for (it = trie_it_begin(hints->nsset); !trie_it_finished(it); trie_it_next(it)) {
+ KR_DNAME_GET_STR(nsname_str, (const knot_dname_t *)trie_it_key(it, NULL));
+ JsonNode *addr_list = pack_addrs((pack_t *)*trie_it_val(it));
+ if (!addr_list) goto error;
+ json_append_member(root_node, nsname_str, addr_list);
+ }
+ result = json_encode(root_node);
+error:
+ trie_it_free(it);
+ json_delete(root_node);
+ return result;
+}
+
+static void unpack_hint(struct kr_zonecut *root_hints, JsonNode *table, const char *name)
+{
+ JsonNode *node = NULL;
+ json_foreach(node, table) {
+ switch(node->tag) {
+ case JSON_STRING: add_pair(root_hints, name ? name : node->key, node->string_); break;
+ case JSON_ARRAY: unpack_hint(root_hints, node, name ? name : node->key); break;
+ default: continue;
+ }
+ }
+}
+
+/**
+ * Get/set root hints set.
+ *
+ * Input: { name: [addr_list], ... }
+ * Output: current list
+ *
+ */
+static char* hint_root(void *env, struct kr_module *module, const char *args)
+{
+ struct engine *engine = env;
+ struct kr_context *ctx = &engine->resolver;
+ struct kr_zonecut *root_hints = &ctx->root_hints;
+ /* Replace root hints if parameter is set */
+ if (args && args[0] != '\0') {
+ JsonNode *root_node = json_decode(args);
+ kr_zonecut_set(root_hints, (const uint8_t *)"");
+ unpack_hint(root_hints, root_node, NULL);
+ json_delete(root_node);
+ }
+ /* Return current root hints */
+ return pack_hints(root_hints);
+}
+
+static char* hint_root_file(void *env, struct kr_module *module, const char *args)
+{
+ struct engine *engine = env;
+ struct kr_context *ctx = &engine->resolver;
+ const char *err_msg = engine_hint_root_file(ctx, args);
+ if (err_msg) {
+ luaL_error(engine->L, "error when opening '%s': %s", args, err_msg);
+ }
+ return strdup(err_msg ? err_msg : "");
+}
+
+static char* hint_use_nodata(void *env, struct kr_module *module, const char *args)
+{
+ struct hints_data *data = module->data;
+ if (!args) {
+ return NULL;
+ }
+
+ JsonNode *root_node = json_decode(args);
+ if (!root_node || root_node->tag != JSON_BOOL) {
+ json_delete(root_node);
+ return bool2jsonstr(false);
+ }
+
+ data->use_nodata = root_node->bool_;
+ json_delete(root_node);
+ return bool2jsonstr(true);
+}
+
+/*
+ * Module implementation.
+ */
+
+KR_EXPORT
+const kr_layer_api_t *hints_layer(struct kr_module *module)
+{
+ static kr_layer_api_t _layer = {
+ .produce = &query,
+ };
+ /* Store module reference */
+ _layer.data = module;
+ return &_layer;
+}
+
+
+/** Basic initialization: get a memory pool, etc. */
+KR_EXPORT
+int hints_init(struct kr_module *module)
+{
+ /* Create pool and copy itself */
+ knot_mm_t _pool = {
+ .ctx = mp_new(4096),
+ .alloc = (knot_mm_alloc_t) mp_alloc
+ };
+ knot_mm_t *pool = mm_alloc(&_pool, sizeof(*pool));
+ if (!pool) {
+ return kr_error(ENOMEM);
+ }
+ memcpy(pool, &_pool, sizeof(*pool));
+
+ struct hints_data *data = mm_alloc(pool, sizeof(struct hints_data));
+ if (!data) {
+ mp_delete(pool->ctx);
+ return kr_error(ENOMEM);
+ }
+ kr_zonecut_init(&data->hints, (const uint8_t *)(""), pool);
+ kr_zonecut_init(&data->reverse_hints, (const uint8_t *)(""), pool);
+ data->use_nodata = true;
+ module->data = data;
+
+ return kr_ok();
+}
+
+/** Release all resources. */
+KR_EXPORT
+int hints_deinit(struct kr_module *module)
+{
+ struct hints_data *data = module->data;
+ if (data) {
+ kr_zonecut_deinit(&data->hints);
+ kr_zonecut_deinit(&data->reverse_hints);
+ mp_delete(data->hints.pool->ctx);
+ module->data = NULL;
+ }
+ return kr_ok();
+}
+
+/** Drop all hints, and load a hosts file if any was specified.
+ *
+ * It seems slightly strange to drop all, but keep doing that for now.
+ */
+KR_EXPORT
+int hints_config(struct kr_module *module, const char *conf)
+{
+ hints_deinit(module);
+ int err = hints_init(module);
+ if (err != kr_ok()) {
+ return err;
+ }
+
+ if (conf && conf[0]) {
+ return load_file(module, conf);
+ }
+ return kr_ok();
+}
+
+KR_EXPORT
+struct kr_prop *hints_props(void)
+{
+ static struct kr_prop prop_list[] = {
+ { &hint_set, "set", "Set {name, address} hint.", },
+ { &hint_del, "del", "Delete one {name, address} hint or all addresses for the name.", },
+ { &hint_get, "get", "Retrieve hint for given name.", },
+ { &hint_add_hosts, "add_hosts", "Load a file with hosts-like formatting and add contents into hints.", },
+ { &hint_root, "root", "Replace root hints set (empty value to return current list).", },
+ { &hint_root_file, "root_file", "Replace root hints set from a zonefile.", },
+ { &hint_use_nodata, "use_nodata", "Synthesise NODATA if name matches, but type doesn't. True by default.", },
+ { NULL, NULL, NULL }
+ };
+ return prop_list;
+}
+
+KR_MODULE_EXPORT(hints)
+
+#undef VERBOSE_MSG
diff --git a/modules/hints/hints.mk b/modules/hints/hints.mk
new file mode 100644
index 0000000..7613c18
--- /dev/null
+++ b/modules/hints/hints.mk
@@ -0,0 +1,8 @@
+hints_CFLAGS := -fPIC
+# We use a symbol that's not in libkres but the daemon.
+# On darwin this isn't accepted by default.
+hints_LDFLAGS := -Wl,-undefined -Wl,dynamic_lookup
+hints_SOURCES := modules/hints/hints.c
+hints_DEPEND := $(libkres)
+hints_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS)
+$(call make_c_module,hints)
diff --git a/modules/hints/tests/hints.test.lua b/modules/hints/tests/hints.test.lua
new file mode 100644
index 0000000..b60d2a3
--- /dev/null
+++ b/modules/hints/tests/hints.test.lua
@@ -0,0 +1,36 @@
+local utils = require('test_utils')
+
+-- setup resolver
+modules = { 'hints' }
+
+-- test for default configuration
+local function test_default()
+ -- get loaded root hints and change names to lowercase
+ local hints_data = utils.table_keys_to_lower(hints.root())
+
+ -- root hints loaded from default location
+ -- check correct ip address of a.root-server.net
+ utils.contains(hints_data['a.root-servers.net.'], '198.41.0.4', 'has IP address for a.root-servers.net.')
+end
+
+-- test loading from config file
+local function test_custom()
+ -- load custom root hints file with fake ip address for a.root-server.net
+ local err_msg = hints.root_file(TEST_DIR .. 'hints_test.zone')
+ same(err_msg, '', 'load root hints from file')
+
+ -- get loaded root hints and change names to lowercase
+ local hints_data = utils.table_keys_to_lower(hints.root())
+ isnt(hints_data['a.root-servers.net.'], nil, 'can retrieve root hints')
+
+ -- check loaded ip address of a.root-server.net
+ utils.not_contains(hints_data['a.root-servers.net.'], '198.41.0.4',
+ 'real IP address for a.root-servers.net. is replaced')
+ utils.contains(hints_data['a.root-servers.net.'], '10.0.0.1',
+ 'real IP address for a.root-servers.net. is correct')
+end
+
+return {
+ test_default,
+ test_custom
+}
diff --git a/modules/hints/tests/hints_test.zone b/modules/hints/tests/hints_test.zone
new file mode 100644
index 0000000..f38ee77
--- /dev/null
+++ b/modules/hints/tests/hints_test.zone
@@ -0,0 +1 @@
+A.ROOT-SERVERS.NET. 3600000 A 10.0.0.1 \ No newline at end of file
diff --git a/modules/http/README.rst b/modules/http/README.rst
new file mode 100644
index 0000000..b4b9194
--- /dev/null
+++ b/modules/http/README.rst
@@ -0,0 +1,345 @@
+.. _mod-http:
+
+HTTP/2 services
+---------------
+
+This is a module that does the heavy lifting to provide an HTTP/2 enabled
+server that provides endpoint for other modules
+in order to enable them to export restful APIs and websocket streams.
+One example is statistics module that can stream live metrics on the website,
+or publish metrics on request for Prometheus scraper.
+
+The server allows other modules to either use default endpoint that provides
+built-in webpage, restful APIs and websocket streams, or create new endpoints.
+
+By default the server provides plain HTTP and TLS on the same port. See below
+if you want to use only one of these.
+
+.. warning:: This module provides access to various API endpoints
+ and must not be directly exposed to untrusted parties.
+ Use `reverse-proxy`_ like Apache_ or Nginx_ if you need to
+ authenticate API clients.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+By default, the web interface starts HTTPS/2 on port 8053 using an ephemeral
+certificate that is valid for 90 days and is automatically renewed. It is of
+course self-signed. Why not use something like
+`Let's Encrypt <https://letsencrypt.org>`_?
+
+.. code-block:: lua
+
+ -- Load HTTP module with defaults
+ modules = {
+ http = {
+ host = 'localhost', -- Default: 'localhost'
+ port = 8053, -- Default: 8053
+ geoip = 'GeoLite2-City.mmdb' -- Optional, see
+ -- e.g. https://dev.maxmind.com/geoip/geoip2/geolite2/
+ -- and install mmdblua library
+ endpoints = {},
+ }
+ }
+
+Now you can reach the web services and APIs, done!
+
+.. code-block:: bash
+
+ $ curl -k https://localhost:8053
+ $ curl -k https://localhost:8053/stats
+
+
+Configuring TLS
+^^^^^^^^^^^^^^^
+You can disable unecrypted HTTP and enforce HTTPS by passing
+``tls = true`` option.
+
+.. code-block:: lua
+
+ http = {
+ tls = true,
+ }
+
+If you want to provide your own certificate and key, you're welcome to do so:
+
+.. code-block:: lua
+
+ http = {
+ cert = 'mycert.crt',
+ key = 'mykey.key',
+ }
+
+The format of both certificate and key is expected to be PEM, e.g. equivalent to
+the outputs of following:
+
+.. code-block:: bash
+
+ openssl ecparam -genkey -name prime256v1 -out mykey.key
+ openssl req -new -key mykey.key -out csr.pem
+ openssl req -x509 -days 90 -key mykey.key -in csr.pem -out mycert.crt
+
+It is also possible to disable HTTPS altogether by passing ``tls = false`` option.
+Plain HTTP gets handy if you want to use `reverse-proxy`_ like Apache_ or Nginx_
+for authentication to API etc.
+(Unencrypted HTTP could be fine for localhost tests as, for example,
+Safari doesn't allow WebSockets over HTTPS with a self-signed certificate.
+Major drawback is that current browsers won't do HTTP/2 over insecure connection.)
+
+
+Built-in services
+^^^^^^^^^^^^^^^^^
+
+The HTTP module has several built-in services to use.
+
+.. csv-table::
+ :header: "Endpoint", "Service", "Description"
+
+ "``/stats``", "Statistics/metrics", "Exported metrics in JSON."
+ "``/metrics``", "Prometheus metrics", "Exported metrics for Prometheus_"
+ "``/trace/:name/:type``", "Tracking", "Trace resolution of the query and return the verbose logs."
+
+Enabling Prometheus metrics endpoint
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The module exposes ``/metrics`` endpoint that serves internal metrics in Prometheus_ text format.
+You can use it out of the box:
+
+.. code-block:: bash
+
+ $ curl -k https://localhost:8053/metrics | tail
+ # TYPE latency histogram
+ latency_bucket{le=10} 2.000000
+ latency_bucket{le=50} 2.000000
+ latency_bucket{le=100} 2.000000
+ latency_bucket{le=250} 2.000000
+ latency_bucket{le=500} 2.000000
+ latency_bucket{le=1000} 2.000000
+ latency_bucket{le=1500} 2.000000
+ latency_bucket{le=+Inf} 2.000000
+ latency_count 2.000000
+ latency_sum 11.000000
+
+You can namespace the metrics in configuration, using `http.prometheus.namespace` attribute:
+
+.. code-block:: lua
+
+ http = {
+ host = 'localhost',
+ }
+
+ -- Set Prometheus namespace
+ http.prometheus.namespace = 'resolver_'
+
+You can also add custom metrics or rewrite existing metrics before they are returned to Prometheus client.
+
+.. code-block:: lua
+
+ http = {
+ host = 'localhost',
+ }
+
+ -- Add an arbitrary metric to Prometheus
+ http.prometheus.finalize = function (metrics)
+ table.insert(metrics, 'build_info{version="1.2.3"} 1')
+ end
+
+Tracing requests
+^^^^^^^^^^^^^^^^
+
+With the ``/trace`` endpoint you can trace various aspects of the request execution.
+The basic mode allows you to resolve a query and trace verbose logs (and messages received):
+
+.. code-block:: bash
+
+ $ curl https://localhost:8053/trace/e.root-servers.net
+ [ 8138] [iter] 'e.root-servers.net.' type 'A' created outbound query, parent id 0
+ [ 8138] [ rc ] => rank: 020, lowest 020, e.root-servers.net. A
+ [ 8138] [ rc ] => satisfied from cache
+ [ 8138] [iter] <= answer received:
+ ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 8138
+ ;; Flags: qr aa QUERY: 1; ANSWER: 0; AUTHORITY: 0; ADDITIONAL: 0
+
+ ;; QUESTION SECTION
+ e.root-servers.net. A
+
+ ;; ANSWER SECTION
+ e.root-servers.net. 3556353 A 192.203.230.10
+
+ [ 8138] [iter] <= rcode: NOERROR
+ [ 8138] [resl] finished: 4, queries: 1, mempool: 81952 B
+
+How to expose services over HTTP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The module provides a table ``endpoints`` of already existing endpoints, it is free for reading and
+writing. It contains tables describing a triplet - ``{mime, on_serve, on_websocket}``.
+In order to register a new service, simply add it to the table:
+
+.. code-block:: lua
+
+ local on_health = {'application/json',
+ function (h, stream)
+ -- API call, return a JSON table
+ return {state = 'up', uptime = 0}
+ end,
+ function (h, ws)
+ -- Stream current status every second
+ local ok = true
+ while ok do
+ local push = tojson('up')
+ ok = ws:send(tojson({'up'}))
+ require('cqueues').sleep(1)
+ end
+ -- Finalize the WebSocket
+ ws:close()
+ end}
+ -- Load module
+ modules = {
+ http = {
+ endpoints = { ['/health'] = on_health }
+ }
+ }
+
+Then you can query the API endpoint, or tail the WebSocket using curl.
+
+.. code-block:: bash
+
+ $ curl -k https://localhost:8053/health
+ {"state":"up","uptime":0}
+ $ curl -k -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost:8053/health" -H "Sec-Websocket-Key: nope" -H "Sec-Websocket-Version: 13" https://localhost:8053/health
+ HTTP/1.1 101 Switching Protocols
+ upgrade: websocket
+ sec-websocket-accept: eg18mwU7CDRGUF1Q+EJwPM335eM=
+ connection: upgrade
+
+ ?["up"]?["up"]?["up"]
+
+Since the stream handlers are effectively coroutines, you are free to keep state and yield using cqueues.
+This is especially useful for WebSockets, as you can stream content in a simple loop instead of
+chains of callbacks.
+
+Last thing you can publish from modules are *"snippets"*. Snippets are plain pieces of HTML code that are rendered at the end of the built-in webpage. The snippets can be extended with JS code to talk to already
+exported restful APIs and subscribe to WebSockets.
+
+.. code-block:: lua
+
+ http.snippets['/health'] = {'Health service', '<p>UP!</p>'}
+
+How to expose RESTful services
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A RESTful service is likely to respond differently to different type of methods and requests,
+there are three things that you can do in a service handler to send back results.
+First is to just send whatever you want to send back, it has to respect MIME type that the service
+declared in the endpoint definition. The response code would then be ``200 OK``, any non-string
+responses will be packed to JSON. Alternatively, you can respond with a number corresponding to
+the HTTP response code or send headers and body yourself.
+
+.. code-block:: lua
+
+ -- Our upvalue
+ local value = 42
+
+ -- Expose the service
+ local service = {'application/json',
+ function (h, stream)
+ -- Get request method and deal with it properly
+ local m = h:get(':method')
+ local path = h:get(':path')
+ log('[service] method %s path %s', m, path)
+ -- Return table, response code will be '200 OK'
+ if m == 'GET' then
+ return {key = path, value = value}
+ -- Save body, perform check and either respond with 505 or 200 OK
+ elseif m == 'POST' then
+ local data = stream:get_body_as_string()
+ if not tonumber(data) then
+ return 500, 'Not a good request'
+ end
+ value = tonumber(data)
+ -- Unsupported method, return 405 Method not allowed
+ else
+ return 405, 'Cannot do that'
+ end
+ end}
+ -- Load the module
+ modules = {
+ http = {
+ endpoints = { ['/service'] = service }
+ }
+ }
+
+In some cases you might need to send back your own headers instead of default provided by HTTP handler,
+you can do this, but then you have to return ``false`` to notify handler that it shouldn't try to generate
+a response.
+
+.. code-block:: lua
+
+ local headers = require('http.headers')
+ function (h, stream)
+ -- Send back headers
+ local hsend = headers.new()
+ hsend:append(':status', '200')
+ hsend:append('content-type', 'binary/octet-stream')
+ assert(stream:write_headers(hsend, false))
+ -- Send back data
+ local data = 'binary-data'
+ assert(stream:write_chunk(data, true))
+ -- Disable default handler action
+ return false
+ end
+
+How to expose more interfaces
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Services exposed in the previous part share the same external interface. This means that it's either accessible to the outside world or internally, but not one or another. This is not always desired, i.e. you might want to offer DNS/HTTPS to everyone, but allow application firewall configuration only on localhost. ``http`` module allows you to create additional interfaces with custom endpoints for this purpose.
+
+.. code-block:: lua
+
+ http.add_interface {
+ endpoints = {
+ ['/conf'] = {
+ 'application/json', function (h, stream)
+ return 'configuration API\n'
+ end
+ },
+ },
+ -- Same options as the config() method
+ host = 'localhost',
+ port = '8054',
+ }
+
+This way you can have different internal-facing and external-facing services at the same time.
+
+Dependencies
+^^^^^^^^^^^^
+
+* `lua-http <https://github.com/daurnimator/lua-http>`_ (>= 0.1) available in LuaRocks
+
+ If you're installing via Homebrew on OS X, you need OpenSSL too.
+
+ .. code-block:: bash
+
+ $ brew update
+ $ brew install openssl
+ $ brew link openssl --force # Override system OpenSSL
+
+ Any other system can install from LuaRocks directly:
+
+ .. code-block:: bash
+
+ $ luarocks install http
+
+* `mmdblua <https://github.com/daurnimator/mmdblua>`_ available in LuaRocks
+
+ .. code-block:: bash
+
+ $ luarocks install --server=https://luarocks.org/dev mmdblua
+ $ curl -O https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
+ $ gzip -d GeoLite2-City.mmdb.gz
+
+.. _Prometheus: https://prometheus.io
+.. _reverse-proxy: https://en.wikipedia.org/wiki/Reverse_proxy
+.. _Apache: https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
+.. _Nginx: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
diff --git a/modules/http/http.lua b/modules/http/http.lua
new file mode 100644
index 0000000..f61102a
--- /dev/null
+++ b/modules/http/http.lua
@@ -0,0 +1,414 @@
+-- Load dependent modules
+if not stats then modules.load('stats') end
+if not bogus_log then modules.load('bogus_log') end
+
+-- This is a module that does the heavy lifting to provide an HTTP/2 enabled
+-- server that supports TLS by default and provides endpoint for other modules
+-- in order to enable them to export restful APIs and websocket streams.
+-- One example is statistics module that can stream live metrics on the website,
+-- or publish metrics on request for Prometheus scraper.
+local http_server = require('http.server')
+local http_headers = require('http.headers')
+local http_websocket = require('http.websocket')
+local http_util = require "http.util"
+local x509, pkey = require('openssl.x509'), require('openssl.pkey')
+local has_mmdb, mmdb = pcall(require, 'mmdb')
+
+-- Module declaration
+local M = {
+ servers = {},
+}
+
+-- Map extensions to MIME type
+local mime_types = {
+ js = 'application/javascript',
+ css = 'text/css',
+ tpl = 'text/html',
+ ico = 'image/x-icon'
+}
+
+-- Preload static contents, nothing on runtime will touch the disk
+local function pgload(relpath, modname)
+ if not modname then modname = 'http' end
+ local mdir = moduledir()
+ local fp, err = io.open(string.format('%s/%s/%s', mdir, modname, relpath), 'r')
+ if not fp then
+ fp, err = io.open(string.format('%s/%s/static/%s', mdir, modname, relpath), 'r')
+ end
+ if not fp then error(err) end
+ local data = fp:read('*all')
+ fp:close()
+ -- Guess content type
+ local ext = relpath:match('[^\\.]+$')
+ return {mime_types[ext] or 'text', data, nil, 86400}
+end
+M.page = pgload
+
+-- Preloaded static assets
+local pages = {
+ 'favicon.ico',
+ 'kresd.js',
+ 'kresd.css',
+ 'jquery.js',
+ 'd3.js',
+ 'topojson.js',
+ 'datamaps.world.min.js',
+ 'dygraph-combined.js',
+ 'selectize.min.js',
+ 'selectize.min.css',
+ 'selectize.bootstrap3.min.css',
+ 'bootstrap.min.js',
+ 'bootstrap.min.css',
+ 'bootstrap-theme.min.css',
+ 'glyphicons-halflings-regular.woff2',
+}
+
+-- Serve preloaded root page
+local function serve_root()
+ local data = pgload('main.tpl')[2]
+ data = data
+ :gsub('{{ title }}', M.title or ('kresd @ ' .. hostname()))
+ :gsub('{{ host }}', hostname())
+ return function (_, stream)
+ -- Render snippets
+ local rsnippets = {}
+ for _,v in pairs(M.snippets) do
+ local sid = string.lower(string.gsub(v[1], ' ', '-'))
+ table.insert(rsnippets, string.format('<section id="%s"><h2>%s</h2>\n%s</section>', sid, v[1], v[2]))
+ end
+ -- Return index page
+ return data
+ :gsub('{{ secure }}', stream:checktls() and 'true' or 'false')
+ :gsub('{{ snippets }}', table.concat(rsnippets, '\n'))
+ end
+end
+
+-- Export HTTP service endpoints
+M.endpoints = {
+ ['/'] = {'text/html', serve_root()},
+}
+
+-- Export static pages
+for _, pg in ipairs(pages) do
+ M.endpoints['/'..pg] = pgload(pg)
+end
+
+-- Export built-in prometheus interface
+local prometheus = require('prometheus')
+for k, v in pairs(prometheus.endpoints) do
+ M.endpoints[k] = v
+end
+M.prometheus = prometheus
+
+-- Export built-in trace interface
+local http_trace = require('http_trace')
+for k, v in pairs(http_trace.endpoints) do
+ M.endpoints[k] = v
+end
+M.trace = http_trace
+
+-- Export HTTP service page snippets
+M.snippets = {}
+
+-- Serve known requests, for methods other than GET
+-- the endpoint must be a closure and not a preloaded string
+local function serve(endpoints, h, stream)
+ local hsend = http_headers.new()
+ local path = h:get(':path')
+ local entry = endpoints[path]
+ if not entry then -- Accept top-level path match
+ entry = endpoints[path:match '^/[^/?]*']
+ end
+ -- Unpack MIME and data
+ local data, mime, ttl, err
+ if entry then
+ mime = entry[1]
+ data = entry[2]
+ ttl = entry[4]
+ end
+ -- Get string data out of service endpoint
+ if type(data) == 'function' then
+ local set_mime, set_ttl
+ data, err, set_mime, set_ttl = data(h, stream)
+ -- Override default endpoint mime/TTL
+ if set_mime then mime = set_mime end
+ if set_ttl then ttl = set_ttl end
+ -- Handler doesn't provide any data
+ if data == false then return end
+ if type(data) == 'number' then return tostring(data), err end
+ -- Methods other than GET require handler to be closure
+ elseif h:get(':method') ~= 'GET' then
+ return '501', ''
+ end
+ if type(data) == 'table' then data = tojson(data) end
+ if not mime or type(data) ~= 'string' then
+ return '404', ''
+ else
+ -- Serve content type appropriately
+ hsend:append(':status', '200')
+ hsend:append('content-type', mime)
+ hsend:append('content-length', tostring(#data))
+ if ttl then
+ hsend:append('cache-control', string.format('max-age=%d', ttl))
+ end
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(data, true))
+ end
+end
+
+-- Web server service closure
+local function route(endpoints)
+ return function (_, stream)
+ -- HTTP/2: We're only permitted to send in open/half-closed (remote)
+ local connection = stream.connection
+ if connection.version >= 2 then
+ if stream.state ~= 'open' and stream.state ~= 'half closed (remote)' then
+ return
+ end
+ end
+ -- Start reading headers
+ local h = assert(stream:get_headers())
+ local m = h:get(':method')
+ local path = h:get(':path')
+ -- Upgrade connection to WebSocket
+ local ws = http_websocket.new_from_stream(stream, h)
+ if ws then
+ assert(ws:accept { protocols = {'json'} })
+ -- Continue streaming results to client
+ local ep = endpoints[path]
+ local cb = ep[3]
+ if cb then
+ cb(h, ws)
+ end
+ ws:close()
+ return
+ else
+ local ok, err, reason = http_util.yieldable_pcall(serve, endpoints, h, stream)
+ if not ok or err then
+ if err ~= '404' and verbose() then
+ log('[http] %s %s: %s (%s)', m, path, err or '500', reason)
+ end
+ -- Method is not supported
+ local hsend = http_headers.new()
+ hsend:append(':status', err or '500')
+ if reason then
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(reason, true))
+ else
+ assert(stream:write_headers(hsend, true))
+ end
+ end
+ end
+ end
+end
+
+-- @function Create self-signed certificate
+local function ephemeralcert(host)
+ -- Import luaossl directly
+ local name = require('openssl.x509.name')
+ local altname = require('openssl.x509.altname')
+ local openssl_bignum = require('openssl.bignum')
+ local openssl_rand = require('openssl.rand')
+ -- Create self-signed certificate
+ host = host or hostname()
+ local crt = x509.new()
+ local now = os.time()
+ crt:setVersion(3)
+ -- serial needs to be unique or browsers will show uninformative error messages
+ crt:setSerial(openssl_bignum.fromBinary(openssl_rand.bytes(16)))
+ -- use the host we're listening on as canonical name
+ local dn = name.new()
+ dn:add("CN", host)
+ crt:setSubject(dn)
+ crt:setIssuer(dn) -- should match subject for a self-signed
+ local alt = altname.new()
+ alt:add("DNS", host)
+ crt:setSubjectAlt(alt)
+ -- Valid for 90 days
+ crt:setLifetime(now, now + 90*60*60*24)
+ -- Can't be used as a CA
+ crt:setBasicConstraints{CA=false}
+ crt:setBasicConstraintsCritical(true)
+ -- Create and set key (default: EC/P-256 as a most "interoperable")
+ local key = pkey.new {type = 'EC', curve = 'prime256v1'}
+ crt:setPublicKey(key)
+ crt:sign(key)
+ return crt, key
+end
+
+-- @function Prefer HTTP/2 or HTTP/1.1
+local function alpnselect(_, protos)
+ for _, proto in ipairs(protos) do
+ if proto == 'h2' or proto == 'http/1.1' then
+ return proto
+ end
+ end
+ return nil
+end
+
+-- @function Create TLS context
+local function tlscontext(crt, key)
+ local http_tls = require('http.tls')
+ local ctx = http_tls.new_server_context()
+ if ctx.setAlpnSelect then
+ ctx:setAlpnSelect(alpnselect)
+ end
+ assert(ctx:setPrivateKey(key))
+ assert(ctx:setCertificate(crt))
+ return ctx
+end
+
+-- @function Refresh self-signed certificates
+local function updatecert(crtfile, keyfile)
+ local f = assert(io.open(crtfile, 'w'), string.format('cannot open "%s" for writing', crtfile))
+ local crt, key = ephemeralcert()
+ -- Write back to file
+ f:write(tostring(crt))
+ f:close()
+ f = assert(io.open(keyfile, 'w'), string.format('cannot open "%s" for writing', keyfile))
+ local pub, priv = key:toPEM('public', 'private')
+ assert(f:write(pub..priv))
+ f:close()
+ return crt, key
+end
+
+-- @function Listen on given HTTP(s) host
+function M.add_interface(conf)
+ local crt, key, ephemeral
+ if conf.tls ~= false then
+ -- Check if a cert file was specified
+ if not conf.cert then
+ conf.cert = 'self.crt'
+ conf.key = 'self.key'
+ ephemeral = true
+ elseif not conf.key then
+ error('certificate provided, but missing key')
+ end
+ -- Read or create self-signed x509 certificate
+ local f = io.open(conf.cert, 'r')
+ if f then
+ crt = assert(x509.new(f:read('*all')))
+ f:close()
+ -- Continue reading key file
+ if crt then
+ f = io.open(conf.key, 'r')
+ key = assert(pkey.new(f:read('*all')))
+ f:close()
+ end
+ elseif ephemeral then
+ crt, key = updatecert(conf.cert, conf.key)
+ end
+ -- Check loaded certificate
+ if not crt or not key then
+ panic('failed to load certificate "%s"', conf.cert)
+ end
+ end
+ -- Compose server handler
+ local routes = route(conf.endpoints or M.endpoints)
+ -- Enable SO_REUSEPORT by default (unless explicitly turned off)
+ local reuseport = (conf.reuseport ~= nil) and conf.reuseport or true
+ if not reuseport and worker.id > 0 then
+ warn('[http] the "reuseport" option is disabled and multiple forks are used, ' ..
+ 'port binding will fail on some instances')
+ end
+ -- Check if UNIX socket path is used
+ local addr_str
+ if not conf.path then
+ conf.host = conf.host or 'localhost'
+ conf.port = conf.port or 8053
+ addr_str = string.format('%s@%d', conf.host, conf.port)
+ else
+ if conf.host or conf.port then
+ error('either "path", or "host" and "port" must be provided')
+ end
+ addr_str = conf.path
+ end
+ -- Create TLS context and start listening
+ local s, err = http_server.listen {
+ cq = worker.bg_worker.cq,
+ host = conf.host,
+ port = conf.port,
+ path = conf.path,
+ v6only = conf.v6only,
+ unlink = conf.unlink,
+ reuseaddr = conf.reuseaddr,
+ reuseport = reuseport,
+ client_timeout = conf.client_timeout or 5,
+ ctx = crt and tlscontext(crt, key),
+ tls = conf.tls,
+ onstream = routes,
+ -- Log errors, but do not throw
+ onerror = function(myserver, context, op, err, errno) -- luacheck: ignore 212
+ local msg = '[http] ' .. op .. ' on ' .. tostring(context) .. ' failed'
+ if err then
+ msg = msg .. ': ' .. tostring(err)
+ end
+ if verbose() then
+ log(msg)
+ end
+ end,
+ }
+ -- Manually call :listen() so that we are bound before calling :localname()
+ if s then
+ err = select(2, s:listen())
+ end
+ if err then
+ panic('failed to listen on %s: %s', addr_str, err)
+ end
+ table.insert(M.servers, s)
+ -- Create certificate renewal timer if ephemeral
+ if crt and ephemeral then
+ local _, expiry = crt:getLifetime()
+ expiry = math.max(0, expiry - (os.time() - 3 * 24 * 3600))
+ event.after(expiry, function ()
+ log('[http] refreshed ephemeral certificate')
+ crt, key = updatecert(conf.cert, conf.key)
+ s.ctx = tlscontext(crt, key)
+ end)
+ end
+end
+
+-- @function Listen on given HTTP(s) host (backwards compatible interface)
+function M.interface(host, port, endpoints, crtfile, keyfile)
+ return M.add_interface {
+ host = host,
+ port = port,
+ endpoints = endpoints,
+ cert = crtfile,
+ key = keyfile,
+ }
+end
+
+-- @function Init module
+function M.init()
+ -- collect and merge metrics only on leader
+ if worker.id == 0 then
+ worker.coroutine(prometheus.init)
+ end
+end
+
+-- @function Cleanup module
+function M.deinit()
+ for i, server in ipairs(M.servers) do
+ server:close()
+ M.servers[i] = nil
+ end
+ prometheus.deinit()
+end
+
+-- @function Configure module
+function M.config(conf)
+ if conf == true then conf = {} end
+ assert(type(conf) == 'table', 'config { host = "...", port = 443, cert = "...", key = "..." }')
+ -- Configure web interface for resolver
+ if conf.geoip then
+ if has_mmdb then
+ M.geoip = mmdb.open(conf.geoip)
+ else
+ error('[http] mmdblua library not found, please remove GeoIP configuration')
+ end
+ end
+ M.add_interface(conf)
+end
+
+return M
diff --git a/modules/http/http.mk b/modules/http/http.mk
new file mode 100644
index 0000000..9ce4f0d
--- /dev/null
+++ b/modules/http/http.mk
@@ -0,0 +1,3 @@
+http_SOURCES := http.lua prometheus.lua http_trace.lua
+http_INSTALL := $(wildcard modules/http/static/*)
+$(call make_lua_module,http)
diff --git a/modules/http/http.test.lua b/modules/http/http.test.lua
new file mode 100644
index 0000000..3d0ac14
--- /dev/null
+++ b/modules/http/http.test.lua
@@ -0,0 +1,89 @@
+-- check prerequisites
+local has_http = pcall(require, 'http') and pcall(require, 'http.request')
+if not has_http then
+ pass('skipping http module test because its not installed')
+ done()
+else
+ local request = require('http.request')
+ local endpoints = require('http').endpoints
+
+ -- custom endpoints
+ endpoints['/test'] = {'text/custom', function () return 'hello' end}
+
+ -- setup resolver
+ modules = {
+ http = {
+ port = 0, -- Select random port
+ cert = false,
+ endpoints = endpoints,
+ }
+ }
+
+ local server = http.servers[1]
+ ok(server ~= nil, 'creates server instance')
+ local _, host, port = server:localname()
+ ok(host and port, 'binds to an interface')
+
+ -- helper for returning useful values to test on
+ local function http_get(uri)
+ local headers, stream = assert(request.new_from_uri(uri .. '/'):go())
+ local body = assert(stream:get_body_as_string())
+ return tonumber(headers:get(':status')), body, headers:get('content-type')
+ end
+
+ -- test whether http interface responds and binds
+ local function test_builtin_pages()
+ local code, body, mime
+ local uri = string.format('http://%s:%d', host, port)
+ -- simple static page
+ code, body, mime = http_get(uri .. '/')
+ same(code, 200, 'static page return 200 OK')
+ ok(#body > 0, 'static page has non-empty body')
+ same(mime, 'text/html', 'static page has text/html content type')
+ -- custom endpoint
+ code, body, mime = http_get(uri .. '/test')
+ same(code, 200, 'custom page return 200 OK')
+ same(body, 'hello', 'custom page has non-empty body')
+ same(mime, 'text/custom', 'custom page has custom content type')
+ -- non-existent page
+ code = http_get(uri .. '/badpage')
+ same(code, 404, 'non-existent page returns 404')
+ -- /stats endpoint serves metrics
+ code, body, mime = http_get(uri .. '/stats')
+ same(code, 200, '/stats page return 200 OK')
+ ok(#body > 0, '/stats page has non-empty body')
+ same(mime, 'application/json', '/stats page has correct content type')
+ -- /metrics serves metrics
+ code, body, mime = http_get(uri .. '/metrics')
+ same(code, 200, '/metrics page return 200 OK')
+ ok(#body > 0, '/metrics page has non-empty body')
+ same(mime, 'text/plain; version=0.0.4', '/metrics page has correct content type')
+ -- /metrics serves frequent
+ code, body, mime = http_get(uri .. '/frequent')
+ same(code, 200, '/frequent page return 200 OK')
+ ok(#body > 0, '/frequent page has non-empty body')
+ same(mime, 'application/json', '/frequent page has correct content type')
+ -- /metrics serves bogus
+ code, body, mime = http_get(uri .. '/bogus')
+ same(code, 200, '/bogus page return 200 OK')
+ ok(#body > 0, '/bogus page has non-empty body')
+ same(mime, 'application/json', '/bogus page has correct content type')
+ -- /trace serves trace log for requests
+ code, body, mime = http_get(uri .. '/trace/localhost/A')
+ same(code, 200, '/trace page return 200 OK')
+ ok(#body > 0, '/trace page has non-empty body')
+ same(mime, 'text/plain', '/trace page has correct content type')
+ -- /trace checks variables
+ code = http_get(uri .. '/trace/localhost/BADTYPE')
+ same(code, 400, '/trace checks type')
+ code = http_get(uri .. '/trace/')
+ same(code, 400, '/trace requires name')
+ end
+
+ -- plan tests
+ local tests = {
+ test_builtin_pages,
+ }
+
+ return tests
+end
diff --git a/modules/http/http_trace.lua b/modules/http/http_trace.lua
new file mode 100644
index 0000000..9e4d466
--- /dev/null
+++ b/modules/http/http_trace.lua
@@ -0,0 +1,109 @@
+local ffi = require('ffi')
+local bit = require('bit')
+local condition = require('cqueues.condition')
+
+-- Buffer selected record information to a table
+local function add_selected_records(dst, records)
+ for _, rec in ipairs(records) do
+ local rank = rec.rank
+ -- Separate the referral chain verified flag
+ local verified = bit.band(rec.rank, kres.rank.AUTH)
+ if verified then
+ rank = bit.band(rank, bit.bnot(kres.rank.AUTH))
+ end
+ local rank_name = kres.tostring.rank[rank] or tostring(rank)
+ -- Write out each individual RR
+ for rr in tostring(rec.rr):gmatch('[^\n]+\n?') do
+ local row = string.format('cached: %s, rank: %s, record: %s',
+ rec.cached, rank_name:lower(), rr)
+ table.insert(dst, row)
+ end
+ end
+end
+
+local function format_selected_records(header, records)
+ if #records == 0 then return '' end
+ return string.format('%s\n%s\n', header, string.rep('-', #header))
+ .. table.concat(records, '') .. '\n'
+end
+
+-- Trace execution of DNS queries
+local function serve_trace(h, _)
+ local path = h:get(':path')
+ local qname, qtype_str = path:match('/trace/([^/]+)/?([^/]*)')
+ if not qname then
+ return 400, 'expected /trace/<query name>/<query type>'
+ end
+
+ -- Parse query type (or default to A)
+ if not qtype_str or #qtype_str == 0 then
+ qtype_str = 'A'
+ end
+
+ local qtype = kres.type[qtype_str]
+ if not qtype then
+ return 400, string.format('unexpected query type: %s', qtype_str)
+ end
+
+ -- Create logging handler callback
+ local buffer = {}
+ local buffer_log_cb = ffi.cast('trace_log_f', function (query, source, msg)
+ local message = string.format('[%5s] [%s] %s',
+ query.id, ffi.string(source), ffi.string(msg))
+ table.insert(buffer, message)
+ end)
+
+ -- Wait for the result of the query
+ -- Note: We can't do non-blocking write to stream directly from resolve callbacks
+ -- because they don't run inside cqueue.
+ local answers, authority = {}, {}
+ local cond = condition.new()
+ local waiting, done = false, false
+ local finish_cb = ffi.cast('trace_callback_f', function (req)
+ req = kres.request_t(req)
+ add_selected_records(answers, req.answ_selected)
+ add_selected_records(authority, req.auth_selected)
+ if waiting then
+ cond:signal()
+ end
+ done = true
+ end)
+
+ -- Resolve query and buffer logs into table
+ resolve {
+ name = qname,
+ type = qtype,
+ options = {'TRACE'},
+ init = function (req)
+ req = kres.request_t(req)
+ req.trace_log = buffer_log_cb
+ req.trace_finish = finish_cb
+ end
+ }
+
+ -- Wait for asynchronous query and free callbacks
+ if not done then
+ waiting = true
+ cond:wait()
+ end
+
+ buffer_log_cb:free()
+ finish_cb:free()
+
+ -- Build the result
+ local result = table.concat(buffer, '') .. '\n'
+ .. format_selected_records('Used records from answer:', answers)
+ .. format_selected_records('Used records from authority:', authority)
+ -- Return buffered data
+ if not done then
+ return 504, result
+ end
+ return result
+end
+
+-- Export endpoints
+return {
+ endpoints = {
+ ['/trace'] = {'text/plain', serve_trace},
+ }
+} \ No newline at end of file
diff --git a/modules/http/prometheus.lua b/modules/http/prometheus.lua
new file mode 100644
index 0000000..00d93de
--- /dev/null
+++ b/modules/http/prometheus.lua
@@ -0,0 +1,172 @@
+-- Module implementation
+local M = {
+ namespace = '',
+ finalize = function (_ --[[metrics]]) end,
+}
+
+local snapshots, snapshots_count = {}, 120
+
+-- Gauge metrics
+local gauges = {
+ ['worker.concurrent'] = true,
+ ['worker.rss'] = true,
+}
+
+local function merge(t, results, prefix)
+ for _, result in pairs(results) do
+ if type(result) == 'table' then
+ for k, v in pairs(result) do
+ local val = t[prefix..k]
+ t[prefix..k] = (val or 0) + v
+ end
+ end
+ end
+end
+
+local function getstats()
+ local t = {}
+ merge(t, map 'stats.list()', '')
+ merge(t, map 'cache.stats()', 'cache.')
+ merge(t, map 'worker.stats()', 'worker.')
+ return t
+end
+
+local function snapshot_end()
+ snapshots_count = false
+end
+
+-- Function to sort frequency list
+local function snapshot_start()
+ local prev = getstats()
+ while snapshots_count do
+ local is_empty = true
+ -- Get current snapshot
+ local cur, stats_dt = getstats(), {}
+ for k,v in pairs(cur) do
+ if gauges[k] then
+ stats_dt[k] = v
+ else
+ stats_dt[k] = v - (prev[k] or 0)
+ end
+ is_empty = is_empty and stats_dt[k] == 0
+ end
+ prev = cur
+ -- Calculate upstreams and geotag them if possible
+ local upstreams
+ if http.geoip then
+ upstreams = stats.upstreams()
+ for k,v in pairs(upstreams) do
+ local gi
+ if string.find(k, '.', 1, true) then
+ gi = http.geoip:search_ipv4(k)
+ else
+ gi = http.geoip:search_ipv6(k)
+ end
+ if gi then
+ upstreams[k] = {data=v, location=gi.location, country=gi.country and gi.country.iso_code}
+ end
+ end
+ end
+ -- Aggregate per-worker metrics
+ local wdata = {}
+ for _, info in pairs(map 'worker.info()') do
+ if type(info) == 'table' then
+ wdata[tostring(info.pid)] = {
+ rss = info.rss,
+ usertime = info.usertime,
+ systime = info.systime,
+ pagefaults = info.pagefaults,
+ queries = info.queries
+ }
+ end
+ end
+ -- Publish stats updates periodically
+ if not is_empty then
+ local update = {time=os.time(), stats=stats_dt, upstreams=upstreams, workers=wdata}
+ table.insert(snapshots, update)
+ if #snapshots > snapshots_count then
+ table.remove(snapshots, 1)
+ end
+ end
+ worker.sleep(1)
+ end
+end
+
+-- Function to sort frequency list
+local function stream_stats(_, ws)
+ -- Initially, stream history
+ local ok, last = true, nil
+ local batch = {}
+ for i, s in ipairs(snapshots) do
+ table.insert(batch, s)
+ if #batch == 20 or i + 1 == #snapshots then
+ ok = ws:send(tojson(batch))
+ batch = {}
+ end
+ end
+ -- Publish stats updates periodically
+ while ok do
+ -- Get last snapshot
+ local id = #snapshots - 1
+ if id > 0 and snapshots[id].time ~= last then
+ local push = tojson(snapshots[id])
+ last = snapshots[id].time
+ ok = ws:send(push)
+ end
+ worker.sleep(1)
+ end
+end
+
+-- Render stats in Prometheus text format
+local function serve_prometheus()
+ -- First aggregate metrics list and print counters
+ local slist, render = getstats(), {}
+ local latency = {}
+ local counter = '# TYPE %s counter\n%s %f'
+ for k,v in pairs(slist) do
+ k = select(1, k:gsub('%.', '_'))
+ -- Aggregate histograms
+ local band = k:match('answer_([%d]+)ms')
+ if band then
+ table.insert(latency, {band, v})
+ elseif k == 'answer_slow' then
+ table.insert(latency, {'+Inf', v})
+ -- Counter as a fallback
+ else
+ local key = M.namespace .. k
+ table.insert(render, string.format(counter, key, key, v))
+ end
+ end
+ -- Fill in latency histogram
+ local function kweight(x) return tonumber(x) or math.huge end
+ table.sort(latency, function (a,b) return kweight(a[1]) < kweight(b[1]) end)
+ table.insert(render, string.format('# TYPE %slatency histogram', M.namespace))
+ local count, sum = 0.0, 0.0
+ for _,e in ipairs(latency) do
+ -- The information about the %Inf bin is lost, so we treat it
+ -- as a timeout (3000ms) for metrics purposes
+ count = count + e[2]
+ sum = sum + e[2] * (math.min(tonumber(e[1]), 3000.0))
+ table.insert(render, string.format('%slatency_bucket{le="%s"} %f', M.namespace, e[1], count))
+ end
+ table.insert(render, string.format('%slatency_count %f', M.namespace, count))
+ table.insert(render, string.format('%slatency_sum %f', M.namespace, sum))
+ -- Finalize metrics table before rendering
+ if type(M.finalize) == 'function' then
+ M.finalize(render)
+ end
+ return table.concat(render, '\n') .. '\n'
+end
+
+-- Export module interface
+M.init = snapshot_start
+M.deinit = snapshot_end
+M.endpoints = {
+ ['/stats'] = {'application/json', getstats, stream_stats},
+ ['/frequent'] = {'application/json', function () return stats.frequent() end},
+ ['/upstreams'] = {'application/json', function () return stats.upstreams() end},
+ ['/bogus'] = {'application/json', function () return bogus_log.frequent() end},
+ ['/metrics'] = {'text/plain; version=0.0.4', serve_prometheus},
+}
+
+return M
diff --git a/modules/http/static/LICENSE b/modules/http/static/LICENSE
new file mode 100644
index 0000000..51f768f
--- /dev/null
+++ b/modules/http/static/LICENSE
@@ -0,0 +1,7 @@
+jQuery is provided under MIT license <https://jquery.org/license/>
+D3 under BSD license <https://github.com/mbostock/d3/blob/master/LICENSE>
+Epoch under MIT license <https://github.com/epochjs/epoch/blob/master/LICENSE>
+TopoJSON under BSD license <https://github.com/mbostock/topojson/blob/master/LICENSE>
+DataMaps under MIT license <https://github.com/markmarkoh/datamaps/blob/master/LICENSE>
+Bootstrap under MIT license <https://github.com/twbs/bootstrap/blob/master/LICENSE>
+Selectize.js under Apache 2.0 license <https://github.com/selectize/selectize.js/blob/master/LICENSE>
diff --git a/modules/http/static/bootstrap-theme.min.css b/modules/http/static/bootstrap-theme.min.css
new file mode 100644
index 0000000..dc95d8e
--- /dev/null
+++ b/modules/http/static/bootstrap-theme.min.css
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
+/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file
diff --git a/modules/http/static/bootstrap.min.css b/modules/http/static/bootstrap.min.css
new file mode 100644
index 0000000..91d431c
--- /dev/null
+++ b/modules/http/static/bootstrap.min.css
@@ -0,0 +1,11 @@
+/*!
+ * bootswatch v3.3.6
+ * Homepage: http://bootswatch.com
+ * Copyright 2012-2016 Thomas Park
+ * Licensed under MIT
+ * Based on Bootstrap
+*//*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../glyphicons-halflings-regular.eot');src:url('../glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../glyphicons-halflings-regular.woff2') format('woff2'),url('../glyphicons-halflings-regular.woff') format('woff'),url('../glyphicons-halflings-regular.ttf') format('truetype'),url('../glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#222222;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#008cba;text-decoration:none}a:hover,a:focus{color:#008cba;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:0}.img-thumbnail{padding:4px;line-height:1.4;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #dddddd}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:21px;margin-bottom:10.5px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10.5px;margin-bottom:10.5px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:39px}h2,.h2{font-size:32px}h3,.h3{font-size:26px}h4,.h4{font-size:19px}h5,.h5{font-size:15px}h6,.h6{font-size:13px}p{margin:0 0 10.5px}.lead{margin-bottom:21px;font-size:17px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:22.5px}}small,.small{font-size:80%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#008cba}a.text-primary:hover,a.text-primary:focus{color:#006687}.text-success{color:#43ac6a}a.text-success:hover,a.text-success:focus{color:#358753}.text-info{color:#5bc0de}a.text-info:hover,a.text-info:focus{color:#31b0d5}.text-warning{color:#e99002}a.text-warning:hover,a.text-warning:focus{color:#b67102}.text-danger{color:#f04124}a.text-danger:hover,a.text-danger:focus{color:#d32a0e}.bg-primary{color:#fff;background-color:#008cba}a.bg-primary:hover,a.bg-primary:focus{background-color:#006687}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9.5px;margin:42px 0 21px;border-bottom:1px solid #dddddd}ul,ol{margin-top:0;margin-bottom:10.5px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:21px}dt,dd{line-height:1.4}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10.5px 21px;margin:0 0 21px;font-size:18.75px;border-left:5px solid #dddddd}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.4;color:#6f6f6f}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #dddddd;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:21px;font-style:normal;line-height:1.4}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:0}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:0;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:10px;margin:0 0 10.5px;font-size:14px;line-height:1.4;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:0}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:21px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.4;vertical-align:top;border-top:1px solid #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #dddddd}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15.75px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:21px;font-size:22.5px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:9px;font-size:15px;line-height:1.4;color:#6f6f6f}.form-control{display:block;width:100%;height:39px;padding:8px 12px;font-size:15px;line-height:1.4;color:#6f6f6f;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:39px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:36px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:60px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:21px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:9px;padding-bottom:9px;margin-bottom:0;min-height:36px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}select.input-sm{height:36px;line-height:36px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}.form-group-sm select.form-control{height:36px;line-height:36px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:36px;min-height:33px;padding:9px 12px;font-size:12px;line-height:1.5}.input-lg{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-lg{height:60px;line-height:60px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}.form-group-lg select.form-control{height:60px;line-height:60px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:60px;min-height:40px;padding:17px 20px;font-size:19px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:48.75px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:39px;height:39px;line-height:39px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:60px;height:60px;line-height:60px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:36px;height:36px;line-height:36px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#43ac6a}.has-success .form-control{border-color:#43ac6a;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#358753;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #85d0a1;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #85d0a1}.has-success .input-group-addon{color:#43ac6a;border-color:#43ac6a;background-color:#dff0d8}.has-success .form-control-feedback{color:#43ac6a}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#e99002}.has-warning .form-control{border-color:#e99002;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#b67102;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #febc53;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #febc53}.has-warning .input-group-addon{color:#e99002;border-color:#e99002;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#e99002}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#f04124}.has-error .form-control{border-color:#f04124;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#d32a0e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #f79483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #f79483}.has-error .input-group-addon{color:#f04124;border-color:#f04124;background-color:#f2dede}.has-error .form-control-feedback{color:#f04124}.has-feedback label~.form-control-feedback{top:26px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#626262}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:9px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:30px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:9px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:17px;font-size:19px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:9px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:8px 12px;font-size:15px;line-height:1.4;border-radius:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333333;background-color:#e7e7e7;border-color:#cccccc}.btn-default:focus,.btn-default.focus{color:#333333;background-color:#cecece;border-color:#8c8c8c}.btn-default:hover{color:#333333;background-color:#cecece;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333333;background-color:#cecece;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333333;background-color:#bcbcbc;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#e7e7e7;border-color:#cccccc}.btn-default .badge{color:#e7e7e7;background-color:#333333}.btn-primary{color:#ffffff;background-color:#008cba;border-color:#0079a1}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#006687;border-color:#001921}.btn-primary:hover{color:#ffffff;background-color:#006687;border-color:#004b63}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#006687;border-color:#004b63}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#004b63;border-color:#001921}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#008cba;border-color:#0079a1}.btn-primary .badge{color:#008cba;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#43ac6a;border-color:#3c9a5f}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#358753;border-color:#183e26}.btn-success:hover{color:#ffffff;background-color:#358753;border-color:#2b6e44}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#358753;border-color:#2b6e44}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#2b6e44;border-color:#183e26}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#43ac6a;border-color:#3c9a5f}.btn-success .badge{color:#43ac6a;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#ffffff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#e99002;border-color:#d08002}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#b67102;border-color:#513201}.btn-warning:hover{color:#ffffff;background-color:#b67102;border-color:#935b01}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#b67102;border-color:#935b01}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#935b01;border-color:#513201}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#e99002;border-color:#d08002}.btn-warning .badge{color:#e99002;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#f04124;border-color:#ea2f10}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#d32a0e;border-color:#731708}.btn-danger:hover{color:#ffffff;background-color:#d32a0e;border-color:#b1240c}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#d32a0e;border-color:#b1240c}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#b1240c;border-color:#731708}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#f04124;border-color:#ea2f10}.btn-danger .badge{color:#f04124;background-color:#ffffff}.btn-link{color:#008cba;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#008cba;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:8px 12px;font-size:12px;border-radius:0}.btn-xs,.btn-group-xs>.btn{padding:4px 6px;font-size:12px;line-height:1.5;border-radius:0}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:15px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:0;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:rgba(0,0,0,0.2)}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.4;color:#555555;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#eeeeee}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#008cba}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.4;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:60px;padding:16px 20px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:60px;line-height:60px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:36px;padding:8px 12px;font-size:12px;line-height:1.5;border-radius:0}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:36px;line-height:36px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:8px 12px;font-size:15px;font-weight:normal;line-height:1;color:#6f6f6f;text-align:center;background-color:#eeeeee;border:1px solid #cccccc;border-radius:0}.input-group-addon.input-sm{padding:8px 12px;font-size:12px;border-radius:0}.input-group-addon.input-lg{padding:16px 20px;font-size:19px;border-radius:0}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#008cba}.nav .nav-divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #dddddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.4;border:1px solid transparent;border-radius:0 0 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#6f6f6f;background-color:#ffffff;border:1px solid #dddddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:0}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#008cba}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:45px;margin-bottom:21px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:0}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:12px 15px;font-size:19px;line-height:21px;height:45px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:5.5px;margin-bottom:5.5px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:0}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:6px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:21px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:21px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:12px;padding-bottom:12px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:3px;margin-bottom:3px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:3px;margin-bottom:3px}.navbar-btn.btn-sm{margin-top:4.5px;margin-bottom:4.5px}.navbar-btn.btn-xs{margin-top:11.5px;margin-bottom:11.5px}.navbar-text{margin-top:12px;margin-bottom:12px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#333333;border-color:#222222}.navbar-default .navbar-brand{color:#ffffff}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-default .navbar-text{color:#ffffff}.navbar-default .navbar-nav>li>a{color:#ffffff}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:transparent}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:transparent}.navbar-default .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#222222}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#272727;color:#ffffff}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#272727}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent}}.navbar-default .navbar-link{color:#ffffff}.navbar-default .navbar-link:hover{color:#ffffff}.navbar-default .btn-link{color:#ffffff}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#ffffff}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#cccccc}.navbar-inverse{background-color:#008cba;border-color:#006687}.navbar-inverse .navbar-brand{color:#ffffff}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-text{color:#ffffff}.navbar-inverse .navbar-nav>li>a{color:#ffffff}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:transparent}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:transparent}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#007196}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#006687;color:#ffffff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#006687}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent}}.navbar-inverse .navbar-link{color:#ffffff}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#ffffff}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444444}.breadcrumb{padding:8px 15px;margin-bottom:21px;list-style:none;background-color:#f5f5f5;border-radius:0}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#999999}.breadcrumb>.active{color:#333333}.pagination{display:inline-block;padding-left:0;margin:21px 0;border-radius:0}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:8px 12px;line-height:1.4;text-decoration:none;color:#008cba;background-color:transparent;border:1px solid transparent;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:0;border-top-left-radius:0}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#008cba;background-color:#eeeeee;border-color:transparent}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;background-color:#008cba;border-color:transparent;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#ffffff;border-color:transparent;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:16px 20px;font-size:19px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:0;border-top-left-radius:0}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pagination-sm>li>a,.pagination-sm>li>span{padding:8px 12px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:0;border-top-left-radius:0}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pager{padding-left:0;margin:21px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:transparent;border:1px solid transparent;border-radius:3px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:transparent;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#008cba}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#006687}.label-success{background-color:#43ac6a}.label-success[href]:hover,.label-success[href]:focus{background-color:#358753}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#e99002}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#b67102}.label-danger{background-color:#f04124}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#d32a0e}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#008cba;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#008cba;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#fafafa}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:23px;font-weight:200}.jumbotron>hr{border-top-color:#e1e1e1}.container .jumbotron,.container-fluid .jumbotron{border-radius:0;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:68px}}.thumbnail{display:block;padding:4px;margin-bottom:21px;line-height:1.4;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#008cba}.thumbnail .caption{padding:9px;color:#222222}.alert{padding:15px;margin-bottom:21px;border:1px solid transparent;border-radius:0}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#43ac6a;border-color:#3c9a5f;color:#ffffff}.alert-success hr{border-top-color:#358753}.alert-success .alert-link{color:#e6e6e6}.alert-info{background-color:#5bc0de;border-color:#3db5d8;color:#ffffff}.alert-info hr{border-top-color:#2aabd2}.alert-info .alert-link{color:#e6e6e6}.alert-warning{background-color:#e99002;border-color:#d08002;color:#ffffff}.alert-warning hr{border-top-color:#b67102}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{background-color:#f04124;border-color:#ea2f10;color:#ffffff}.alert-danger hr{border-top-color:#d32a0e}.alert-danger .alert-link{color:#e6e6e6}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:21px;margin-bottom:21px;background-color:#f5f5f5;border-radius:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:21px;color:#ffffff;text-align:center;background-color:#008cba;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#43ac6a}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#e99002}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#f04124}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#008cba;border-color:#008cba}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#87e1ff}.list-group-item-success{color:#43ac6a;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#43ac6a}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#43ac6a;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#43ac6a;border-color:#43ac6a}.list-group-item-info{color:#5bc0de;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#5bc0de}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#5bc0de;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#5bc0de;border-color:#5bc0de}.list-group-item-warning{color:#e99002;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#e99002}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#e99002;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#e99002;border-color:#e99002}.list-group-item-danger{color:#f04124;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#f04124}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#f04124;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#f04124;border-color:#f04124}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:21px;background-color:#ffffff;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:-1;border-top-left-radius:-1}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:17px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:-1;border-top-left-radius:-1}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:-1;border-top-left-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:-1;border-top-right-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:-1}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:-1}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:-1;border-bottom-left-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:-1;border-bottom-right-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:-1}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:-1}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:21px}.panel-group .panel{margin-bottom:0;border-radius:0}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#008cba}.panel-primary>.panel-heading{color:#ffffff;background-color:#008cba;border-color:#008cba}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#008cba}.panel-primary>.panel-heading .badge{color:#008cba;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#008cba}.panel-success{border-color:#3c9a5f}.panel-success>.panel-heading{color:#ffffff;background-color:#43ac6a;border-color:#3c9a5f}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#3c9a5f}.panel-success>.panel-heading .badge{color:#43ac6a;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#3c9a5f}.panel-info{border-color:#3db5d8}.panel-info>.panel-heading{color:#ffffff;background-color:#5bc0de;border-color:#3db5d8}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#3db5d8}.panel-info>.panel-heading .badge{color:#5bc0de;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#3db5d8}.panel-warning{border-color:#d08002}.panel-warning>.panel-heading{color:#ffffff;background-color:#e99002;border-color:#d08002}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d08002}.panel-warning>.panel-heading .badge{color:#e99002;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d08002}.panel-danger{border-color:#ea2f10}.panel-danger>.panel-heading{color:#ffffff;background-color:#f04124;border-color:#ea2f10}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ea2f10}.panel-danger>.panel-heading .badge{color:#f04124;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ea2f10}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#fafafa;border:1px solid #e8e8e8;border-radius:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:0}.well-sm{padding:9px;border-radius:0}.close{float:right;font-size:22.5px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#ffffff;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid rgba(0,0,0,0.2);border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.4}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.4;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#333333;border-radius:0}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#333333}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#333333}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#333333}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#333333}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.4;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:15px;background-color:#333333;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #333333;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:15px;background-color:#333333;border-bottom:1px solid #262626;border-radius:-1 -1 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#000000;border-top-color:rgba(0,0,0,0.05);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#333333}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#000000;border-right-color:rgba(0,0,0,0.05)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#333333}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#000000;border-bottom-color:rgba(0,0,0,0.05);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#333333}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#000000;border-left-color:rgba(0,0,0,0.05)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#333333;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border:none;font-size:13px;font-weight:300}.navbar .navbar-toggle:hover .icon-bar{background-color:#b3b3b3}.navbar-collapse{border-top-color:rgba(0,0,0,0.2);-webkit-box-shadow:none;box-shadow:none}.navbar .btn{padding-top:6px;padding-bottom:6px}.navbar-form{margin-top:7px;margin-bottom:5px}.navbar-form .form-control{height:auto;padding:4px 6px}.navbar-text{margin:12px 15px;line-height:21px}.navbar .dropdown-menu{border:none}.navbar .dropdown-menu>li>a,.navbar .dropdown-menu>li>a:focus{background-color:transparent;font-size:13px;font-weight:300}.navbar .dropdown-header{color:rgba(255,255,255,0.5)}.navbar-default .dropdown-menu{background-color:#333333}.navbar-default .dropdown-menu>li>a,.navbar-default .dropdown-menu>li>a:focus{color:#ffffff}.navbar-default .dropdown-menu>li>a:hover,.navbar-default .dropdown-menu>.active>a,.navbar-default .dropdown-menu>.active>a:hover{background-color:#272727}.navbar-inverse .dropdown-menu{background-color:#008cba}.navbar-inverse .dropdown-menu>li>a,.navbar-inverse .dropdown-menu>li>a:focus{color:#ffffff}.navbar-inverse .dropdown-menu>li>a:hover,.navbar-inverse .dropdown-menu>.active>a,.navbar-inverse .dropdown-menu>.active>a:hover{background-color:#006687}.btn{padding:8px 12px}.btn-lg{padding:16px 20px}.btn-sm{padding:8px 12px}.btn-xs{padding:4px 6px}.btn-group .btn~.dropdown-toggle{padding-left:16px;padding-right:16px}.btn-group .dropdown-menu{border-top-width:0}.btn-group.dropup .dropdown-menu{border-top-width:1px;border-bottom-width:0;margin-bottom:0}.btn-group .dropdown-toggle.btn-default~.dropdown-menu{background-color:#e7e7e7;border-color:#cccccc}.btn-group .dropdown-toggle.btn-default~.dropdown-menu>li>a{color:#333333}.btn-group .dropdown-toggle.btn-default~.dropdown-menu>li>a:hover{background-color:#d3d3d3}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu{background-color:#008cba;border-color:#0079a1}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-primary~.dropdown-menu>li>a:hover{background-color:#006d91}.btn-group .dropdown-toggle.btn-success~.dropdown-menu{background-color:#43ac6a;border-color:#3c9a5f}.btn-group .dropdown-toggle.btn-success~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-success~.dropdown-menu>li>a:hover{background-color:#388f58}.btn-group .dropdown-toggle.btn-info~.dropdown-menu{background-color:#5bc0de;border-color:#46b8da}.btn-group .dropdown-toggle.btn-info~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-info~.dropdown-menu>li>a:hover{background-color:#39b3d7}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu{background-color:#e99002;border-color:#d08002}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-warning~.dropdown-menu>li>a:hover{background-color:#c17702}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu{background-color:#f04124;border-color:#ea2f10}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu>li>a{color:#ffffff}.btn-group .dropdown-toggle.btn-danger~.dropdown-menu>li>a:hover{background-color:#dc2c0f}.lead{color:#6f6f6f}cite{font-style:italic}blockquote{border-left-width:1px;color:#6f6f6f}blockquote.pull-right{border-right-width:1px}blockquote small{font-size:12px;font-weight:300}table{font-size:12px}label,.control-label,.help-block,.checkbox,.radio{font-size:12px;font-weight:normal}input[type="radio"],input[type="checkbox"]{margin-top:1px}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{border-color:transparent}.nav-tabs>li>a{background-color:#e7e7e7;color:#222222}.nav-tabs .caret{border-top-color:#222222;border-bottom-color:#222222}.nav-pills{font-weight:300}.breadcrumb{border:1px solid #dddddd;border-radius:3px;font-size:10px;font-weight:300;text-transform:uppercase}.pagination{font-size:12px;font-weight:300;color:#999999}.pagination>li>a,.pagination>li>span{margin-left:4px;color:#999999}.pagination>.active>a,.pagination>.active>span{color:#fff}.pagination>li>a,.pagination>li:first-child>a,.pagination>li:last-child>a,.pagination>li>span,.pagination>li:first-child>span,.pagination>li:last-child>span{border-radius:3px}.pagination-lg>li>a,.pagination-lg>li>span{padding-left:22px;padding-right:22px}.pagination-sm>li>a,.pagination-sm>li>span{padding:0 5px}.pager{font-size:12px;font-weight:300;color:#999999}.list-group{font-size:12px;font-weight:300}.close{opacity:0.4;text-decoration:none;text-shadow:none}.close:hover,.close:focus{opacity:1}.alert{font-size:12px;font-weight:300}.alert .alert-link{font-weight:normal;color:#fff;text-decoration:underline}.label{padding-left:1em;padding-right:1em;border-radius:0;font-weight:300}.label-default{background-color:#e7e7e7;color:#333333}.badge{font-weight:300}.progress{height:22px;padding:2px;background-color:#f6f6f6;border:1px solid #ccc;-webkit-box-shadow:none;box-shadow:none}.dropdown-menu{padding:0;margin-top:0;font-size:12px}.dropdown-menu>li>a{padding:12px 15px}.dropdown-header{padding-left:15px;padding-right:15px;font-size:9px;text-transform:uppercase}.popover{color:#fff;font-size:12px;font-weight:300}.panel-heading,.panel-footer{border-top-right-radius:0;border-top-left-radius:0}.panel-default .close{color:#222222}.modal .close{color:#222222} \ No newline at end of file
diff --git a/modules/http/static/bootstrap.min.js b/modules/http/static/bootstrap.min.js
new file mode 100644
index 0000000..e79c065
--- /dev/null
+++ b/modules/http/static/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");
+d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file
diff --git a/modules/http/static/d3.js b/modules/http/static/d3.js
new file mode 100644
index 0000000..1984d17
--- /dev/null
+++ b/modules/http/static/d3.js
@@ -0,0 +1,5 @@
+!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function c(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function l(){this._=Object.create(null)}function s(n){return(n+="")===pa||n[0]===va?va+n:n}function f(n){return(n+="")[0]===va?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=da.length;r>e;++e){var u=da[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new l;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function S(){ta.event.preventDefault()}function k(){for(var n,t=ta.event;n=t.sourceEvent;)t=n;return t}function E(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=ta.event;u.target=n,ta.event=u,t[u.type].apply(e,r)}finally{ta.event=i}}},t}function A(n){return ya(n,_a),n}function N(n){return"function"==typeof n?n:function(){return Ma(n,this)}}function C(n){return"function"==typeof n?n:function(){return xa(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ta.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function q(n){return n.trim().replace(/\s+/g," ")}function L(n){return new RegExp("(?:^|\\s+)"+ta.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=T(n).map(D);var u=n.length;return"function"==typeof t?r:e}function D(n){var t=L(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",q(u+" "+n))):e.setAttribute("class",q(u.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e?t.createElementNS(e,n):t.createElement(n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=ta.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return ba(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function Z(n){return ya(n,Sa),n}function V(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,ra(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+ta.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=$;a>0&&(n=n.slice(0,a));var l=ka.get(n);return l&&(n=l,c=B),a?t?u:r:t?b:i}function $(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Aa,u="click"+r,i=ta.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ea&&(Ea="onselectstart"in e?!1:x(e.style,"userSelect")),Ea){var o=n(e).style,a=o[Ea];o[Ea]="none"}return function(n){if(i.on(r,null),Ea&&(o[Ea]=a),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Na){var i=t(n);if(i.scrollX||i.scrollY){r=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Na=!(o.f||o.e),r.remove()}}return Na?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ta.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nt(n){return n>1?0:-1>n?qa:Math.acos(n)}function tt(n){return n>1?Ra:-1>n?-Ra:Math.asin(n)}function et(n){return((n=Math.exp(n))-1/n)/2}function rt(n){return((n=Math.exp(n))+1/n)/2}function ut(n){return((n=Math.exp(2*n))-1)/(n+1)}function it(n){return(n=Math.sin(n/2))*n}function ot(){}function at(n,t,e){return this instanceof at?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof at?new at(n.h,n.s,n.l):bt(""+n,_t,at):new at(n,t,e)}function ct(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new mt(u(n+120),u(n),u(n-120))}function lt(n,t,e){return this instanceof lt?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof lt?new lt(n.h,n.c,n.l):n instanceof ft?gt(n.l,n.a,n.b):gt((n=wt((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new lt(n,t,e)}function st(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new ft(e,Math.cos(n*=Da)*t,Math.sin(n)*t)}function ft(n,t,e){return this instanceof ft?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof ft?new ft(n.l,n.a,n.b):n instanceof lt?st(n.h,n.c,n.l):wt((n=mt(n)).r,n.g,n.b):new ft(n,t,e)}function ht(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=pt(u)*Xa,r=pt(r)*$a,i=pt(i)*Ba,new mt(dt(3.2404542*u-1.5371385*r-.4985314*i),dt(-.969266*u+1.8760108*r+.041556*i),dt(.0556434*u-.2040259*r+1.0572252*i))}function gt(n,t,e){return n>0?new lt(Math.atan2(e,t)*Pa,Math.sqrt(t*t+e*e),n):new lt(0/0,0/0,n)}function pt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function vt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function dt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mt(n,t,e){return this instanceof mt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mt?new mt(n.r,n.g,n.b):bt(""+n,mt,ct):new mt(n,t,e)}function yt(n){return new mt(n>>16,n>>8&255,255&n)}function Mt(n){return yt(n)+""}function xt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function bt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(kt(u[0]),kt(u[1]),kt(u[2]))}return(i=Ga.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function _t(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new at(r,u,c)}function wt(n,t,e){n=St(n),t=St(t),e=St(e);var r=vt((.4124564*n+.3575761*t+.1804375*e)/Xa),u=vt((.2126729*n+.7151522*t+.072175*e)/$a),i=vt((.0193339*n+.119192*t+.9503041*e)/Ba);return ft(116*u-16,500*(r-u),200*(u-i))}function St(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function kt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function Et(n){return"function"==typeof n?n:function(){return n}}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return void o.error.call(i,r)}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(tc),tc=setTimeout(qt,t)),nc=0):(nc=1,rc(qt))}function Lt(){var n=Date.now();for(ec=Ka;ec;)n>=ec.t&&(ec.f=ec.c(n-ec.t)),ec=ec.n;return n}function Tt(){for(var n,t=Ka,e=1/0;t;)t.f?t=n?n.n=t.n:Ka=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return Qa=n,e}function Rt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Dt(n,t){var e=Math.pow(10,3*ga(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=ic.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=oc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new cc(e-1)),1),e}function i(n,e){return t(n=new cc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{cc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{cc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{cc=jt;var r=new jt;return r._=t,n(r,e)._}finally{cc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.slice(c,a)),null!=(u=sc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=N[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.slice(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&cc!==jt,o=new(i?jt:cc);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,l=e.length;c>a;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in sc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{cc=jt;var t=new cc;return t._=n,r(t)}finally{cc=Date}}var r=t(n);return e.parse=function(n){try{cc=jt;var t=r.parse(n);return t&&t._}finally{cc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=Yt(v),b=Zt(v),_=Yt(d),w=Zt(d),S=Yt(m),k=Zt(m),E=Yt(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return It(n.getDate(),t,2)},e:function(n,t){return It(n.getDate(),t,2)},H:function(n,t){return It(n.getHours(),t,2)},I:function(n,t){return It(n.getHours()%12||12,t,2)},j:function(n,t){return It(1+ac.dayOfYear(n),t,3)},L:function(n,t){return It(n.getMilliseconds(),t,3)},m:function(n,t){return It(n.getMonth()+1,t,2)},M:function(n,t){return It(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return It(n.getSeconds(),t,2)},U:function(n,t){return It(ac.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return It(ac.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return It(n.getFullYear()%100,t,2)},Y:function(n,t){return It(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function It(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Yt(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new l,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Vt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Xt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function $t(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Bt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Wt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.y=Gt(+r[0]),e+r[0].length):-1}function Jt(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Gt(n){return n+(n>68?1900:2e3)}function Kt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=ga(t)/60|0,u=ga(t)%60;return e+It(r,"0",2)+It(u,"0",2)}function oe(n,t,e){hc.lastIndex=0;var r=hc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ce(){}function le(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function se(n,t){n&&dc.hasOwnProperty(n.type)&&dc[n.type](n,t)}function fe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function he(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)fe(n[e],t,1);t.polygonEnd()}function ge(){function n(n,t){n*=Da,t=t*Da/2+qa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);yc.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;Mc.point=function(o,a){Mc.point=n,r=(t=o)*Da,u=Math.cos(a=(e=a)*Da/2+qa/4),i=Math.sin(a)},Mc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),tt(n[2])]}function be(n,t){return ga(n[0]-t[0])<Ca&&ga(n[1]-t[1])<Ca}function _e(n,t){n*=Da;var e=Math.cos(t*=Da);we(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function we(n,t,e){++xc,_c+=(n-_c)/xc,wc+=(t-wc)/xc,Sc+=(e-Sc)/xc}function Se(){function n(n,u){n*=Da;var i=Math.cos(u*=Da),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),l=Math.atan2(Math.sqrt((l=e*c-r*a)*l+(l=r*o-t*c)*l+(l=t*a-e*o)*l),t*o+e*a+r*c);bc+=l,kc+=l*(t+(t=o)),Ec+=l*(e+(e=a)),Ac+=l*(r+(r=c)),we(t,e,r)}var t,e,r;qc.point=function(u,i){u*=Da;var o=Math.cos(i*=Da);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),qc.point=n,we(t,e,r)}}function ke(){qc.point=_e}function Ee(){function n(n,t){n*=Da;var e=Math.cos(t*=Da),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),l=u*c-i*a,s=i*o-r*c,f=r*a-u*o,h=Math.sqrt(l*l+s*s+f*f),g=r*o+u*a+i*c,p=h&&-nt(g)/h,v=Math.atan2(h,g);Nc+=p*l,Cc+=p*s,zc+=p*f,bc+=v,kc+=v*(r+(r=o)),Ec+=v*(u+(u=a)),Ac+=v*(i+(i=c)),we(r,u,i)}var t,e,r,u,i;qc.point=function(o,a){t=o,e=a,qc.point=n,o*=Da;var c=Math.cos(a*=Da);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),we(r,u,i)},qc.lineEnd=function(){n(t,e),qc.lineEnd=ke,qc.point=_e}}function Ae(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function Ne(){return!0}function Ce(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(be(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return void u.lineEnd()}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function qe(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Le(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function l(){y.point=o,d.lineEnd()}function s(n,t){v.push([n,t]);var e=u(n,t);x.point(e[0],e[1])}function f(){x.lineStart(),v=[]}function h(){s(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&t){n=e[0];var u,r=n.length-1,o=-1;if(r>0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);i.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-Ra-Ca:Ra-n[1])-((t=t.x)[0]<0?t[1]-Ra-Ca:Ra-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?qa:-qa,c=ga(i-e);ga(c-qa)<Ca?(n.point(e,r=(r+o)/2>0?Ra:-Ra),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=qa&&(ga(e-u)<Ca&&(e-=u*Ca),ga(i-a)<Ca&&(i-=a*Ca),r=Ue(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function Ue(n,t,e,r){var u,i,o=Math.sin(n-e);return ga(o)>Ca?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*Ra,r.point(-qa,u),r.point(0,u),r.point(qa,u),r.point(qa,0),r.point(qa,-u),r.point(0,-u),r.point(-qa,-u),r.point(-qa,0),r.point(-qa,u);else if(ga(n[0]-t[0])>Ca){var i=n[0]<t[0]?qa:-qa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Fe(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;yc.reset();for(var a=0,c=t.length;c>a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+qa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+qa/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>qa,k=p*M;if(yc.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*La:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*tt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ca>i||Ca>i&&0>yc)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?qa:-qa),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ca,p[1]+=Ca,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=ga(A-qa)<Ca,C=N||Ca>A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(ga(b[0]-w)<Ca?k:E):k<=b[1]&&b[1]<=E:A>qa^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:qa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ga(i)>Ca,c=gr(n,6*Da);return Le(t,e,c,o?[0,-n]:[-qa,n-qa])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ie(n,t,e,r){function u(r,u){return ga(r[0]-n)<Ca?u>0?0:3:ga(r[0]-e)<Ca?u>0?2:1:ga(r[1]-t)<Ca?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&Q(l,i,n)>0&&++t:i[1]<=r&&Q(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Tc,Math.min(Tc,n)),t=Math.max(-Tc,Math.min(Tc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ye(n){var t=0,e=qa/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*qa/180,e=n[1]*qa/180):[t/qa*180,e/qa*180]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,tt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Dc+=u*n-r*t,r=n,u=t}var t,e,r,u;Hc.point=function(i,o){Hc.point=n,t=r=i,e=u=o},Hc.lineEnd=function(){n(t,e)}}function Xe(n,t){Pc>n&&(Pc=n),n>jc&&(jc=n),Uc>t&&(Uc=t),t>Fc&&(Fc=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){_c+=n,wc+=t,++Sc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);kc+=o*(t+n)/2,Ec+=o*(e+r)/2,Ac+=o,We(t=n,e=r)}var t,e;Ic.point=function(r,u){Ic.point=n,We(t=r,e=u)}}function Ge(){Ic.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);kc+=o*(r+n)/2,Ec+=o*(u+t)/2,Ac+=o,o=u*n-r*t,Nc+=o*(r+n),Cc+=o*(u+t),zc+=3*o,We(r=n,u=t)}var t,e,r,u;Ic.point=function(i,o){Ic.point=n,We(t=r=i,e=u=o)},Ic.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,La)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c
+},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)<Ca||ga(r-h)<Ca?(r+h)/2:Math.atan2(_,b),A=n(E,k),N=A[0],C=A[1],z=N-t,q=C-e,L=M*z-y*q;(L*L/x>i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Pa,e*Pa])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Da,n[1]*Da),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Pa,n[1]*Pa]}function r(){a=Ae(o=lr(m,M,x),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Lc,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(b(o,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Lc):He((w=+n)*Da),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Ie(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Da,d=n[1]%360*Da,r()):[v*Pa,d*Pa]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Da,M=n[1]%360*Da,x=n.length>2?n[2]%360*Da:0,r()):[m*Pa,M*Pa,x*Pa]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Da,e*Da)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>qa?n-La:-qa>n?n+La:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>qa?t-La:-qa>t?t+La:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),tt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),tt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*La)):(u=n+o*La,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=nt(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ca)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(it(r-t)+u*o*it(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Pa,Math.atan2(o,Math.sqrt(r*r+u*u))*Pa]}:function(){return[n*Pa,t*Pa]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Da),o=Math.cos(u),a=ga((n*=Da)-t),c=Math.cos(a);Yc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Zc.point=function(u,i){t=u*Da,e=Math.sin(i*=Da),r=Math.cos(i),Zc.point=n},Zc.lineEnd=function(){Zc.point=Zc.lineEnd=b}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-Ra+Ca>t&&(t=-Ra+Ca):t>Ra-Ca&&(t=Ra-Ca);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(qa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ra]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ga(u)<Ca?ar:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-K(u)*Math.sqrt(n*n+e*e)]},e)}function Sr(n,t){return[n,Math.log(Math.tan(qa/4+t/2))]}function kr(n){var t,e=ur(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=qa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Er(n,t){return[Math.log(Math.tan(qa/4+t/2)),-n]}function Ar(n){return n[0]}function Nr(n){return n[1]}function Cr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=el.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),Qc.remove(n),el.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&ga(e-c.circle.x)<Ca&&ga(r-c.circle.cy)<Ca;)i=c.P,a.unshift(c),Pr(c),c=i;a.unshift(c),Xr(c);for(var l=o;l.circle&&ga(e-l.circle.x)<Ca&&ga(r-l.circle.cy)<Ca;)o=l.N,a.push(l),Pr(l),l=o;a.push(l),Xr(l);var s,f=a.length;for(s=1;f>s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Qc._;a;)if(r=Fr(a,o)-i,r>Ca)a=a.L;else{if(u=i-Hr(a,o),!(u>Ca)){r>-Ca?(t=a.P,e=a):u>-Ca?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(Qc.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),Qc.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),void Vr(e);if(!e)return void(c.edge=Jr(t.site,c.site));Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Ir(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Kc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(ga(r-t)>Ca||ga(u-e)>Ca)&&(a.splice(o,0,new Qr(Gr(i.site,s,ga(r-f)<Ca&&p-u>Ca?{x:f,y:ga(t-f)<Ca?e:p}:ga(u-p)<Ca&&h-r>Ca?{x:ga(e-p)<Ca?t:h,y:p}:ga(r-h)<Ca&&u-g>Ca?{x:h,y:ga(t-h)<Ca?e:g}:ga(u-g)<Ca&&r-f>Ca?{x:ga(e-g)<Ca?t:f,y:g}:null),i.site,null)),++c)}function Yr(n,t){return t.angle-n.angle}function Zr(){tu(this),this.x=this.y=this.arc=this.site=this.cy=null}function Vr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,l=r.y-a,s=i.x-o,f=i.y-a,h=2*(c*f-l*s);if(!(h>=-za)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=rl.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=tl._;M;)if(m.y<M.y||m.y===M.y&&m.x<=M.x){if(!M.L){y=M.P;break}M=M.L}else{if(!M.R){y=M;break}M=M.R}tl.insert(y,m),y||(nl=m)}}}}function Xr(n){var t=n.circle;t&&(t.P||(nl=t.N),tl.remove(t),rl.push(t),tu(t),n.circle=null)}function $r(n){for(var t,e=Gc,r=Oe(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Br(t,n)||!r(t)||ga(t.a.x-t.b.x)<Ca&&ga(t.a.y-t.b.y)<Ca)&&(t.a=t.b=null,e.splice(u,1))}function Br(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],l=t[1][1],s=n.l,f=n.r,h=s.x,g=s.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.y<c)return}else i={x:d,y:l};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.y<c)return}else i={x:(l-u)/r,y:l};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Wr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Jr(n,t,e,r){var u=new Wr(n,t);return Gc.push(u),e&&Kr(u,n,t,e),r&&Kr(u,t,n,r),Kc[n.i].edges.push(new Qr(u,n,t)),Kc[t.i].edges.push(new Qr(u,t,n)),u}function Gr(n,t,e){var r=new Wr(n,null);return r.a=t,r.b=e,Gc.push(r),r}function Kr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Qr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function nu(){this._=null}function tu(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function eu(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ru(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function uu(n){for(;n.L;)n=n.L;return n}function iu(n,t){var e,r,u,i=n.sort(ou).pop();for(Gc=[],Kc=new Array(n.length),Qc=new nu,tl=new nu;;)if(u=nl,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Kc[i.i]=new Or(i),jr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;Ur(u.arc)}t&&($r(t),Ir(t));var o={cells:Kc,edges:Gc};return Qc=tl=Gc=Kc=null,o}function ou(n,t){return t.y-n.y||t.x-n.x}function au(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function cu(n){return n.x}function lu(n){return n.y}function su(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function fu(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&fu(n,c[0],e,r,o,a),c[1]&&fu(n,c[1],o,r,u,a),c[2]&&fu(n,c[2],e,a,o,i),c[3]&&fu(n,c[3],o,a,u,i)}}function hu(n,t,e,r,u,i,o){var a,c=1/0;return function l(n,s,f,h,g){if(!(s>i||f>o||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+xt(Math.round(e+i*n))+xt(Math.round(r+o*n))+xt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=il.lastIndex=ol.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=il.exec(n))&&(r=ol.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=ol.lastIndex;return i<t.length&&(u=t.slice(i),a[o]?a[o]+=u:a[++o]=u),a.length<2?c[0]?(t=c[0].x,function(n){return t(n)+""}):function(){return t}:(t=c.length,function(n){for(var e,r=0;t>r;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*Ra)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/La*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*La/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return st(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ht(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Pa,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Pa:0}function Uu(n,t){return n[0]*t[0]+n[1]*t[1]}function ju(n){var t=Math.sqrt(Uu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Fu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Hu(n,t){var e,r=[],u=[],i=ta.transform(n),o=ta.transform(t),a=i.translate,c=o.translate,l=i.rotate,s=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:vu(a[0],c[0])},{i:3,x:vu(a[1],c[1])})):r.push(c[0]||c[1]?"translate("+c+")":""),l!=s?(l-s>180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Ou(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Iu(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Yu(n){for(var t=n.source,e=n.target,r=Vu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Zu(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Vu(n,t){if(n===t)return n;for(var e=Zu(n),r=Zu(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Xu(n){n.fixed|=2}function $u(n){n.fixed&=-7}function Bu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Wu(n){n.fixed&=-5}function Ju(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Ju(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var l=t*e[n.point.index];n.charge+=n.pointCharge=l,r+=l*n.point.x,u+=l*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Gu(n,t){return ta.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=ri,n}function Ku(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&&(r=u.length))for(var r,u;--r>=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++o<u;)e.push(i[o]);for(;null!=(n=r.pop());)t(n)}function ni(n){return n.children}function ti(n){return n.value}function ei(n,t){return t.value-n.value}function ri(n){return ta.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function ui(n){return n.x}function ii(n){return n.y}function oi(n,t,e){n.y0=t,n.y=e}function ai(n){return ta.range(n.length)}function ci(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function li(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?mi(r,u=a):mi(r=c,u),o--):(di(r,i),u=i,t(i))}var m=(s+f)/2,y=(h+g)/2,M=0;for(o=0;l>o;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)_i(u[i],t,e,r)}function wi(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),l=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+l*i,e.y=n.y+c*i-l*u}else e.x=n.x+r,e.y=n.y}function Si(n,t){return n.parent==t.parent?1:2}function ki(n){var t=n.children;return t.length?t[0]:n.t}function Ei(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ai(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Ni(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ml}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=ta.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Ii(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Oi:ji,c=r?Iu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Ii(n,t,e,r)},u()}function Yi(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=ic.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(ga(r[0]),ga(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in yl?Math.abs(e-Bi(Math.max(ga(t[0]),ga(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:xl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++<s;)for(var h=f-1;h>0;h--)o.push(i(l)*h);for(l=0;o[l]<a;l++);for(s=o.length;o[s-1]>c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return Ml;arguments.length<2?t=Ml:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Yi(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Yi(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new l;for(var i,o=-1,a=r.length;++o<a;)u.has(i=r[o])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,o=0,t={t:"range",a:arguments},e):i},e.rangePoints=function(u,a){arguments.length<2&&(a=0);var c=u[0],l=u[1],s=n.length<2?(c=(c+l)/2,0):(l-c)/(n.length-1+a);return i=r(c+s*a/2,s),o=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(u,a){arguments.length<2&&(a=0);var c=u[0],l=u[1],s=n.length<2?(c=l=Math.round((c+l)/2),0):(l-c)/(n.length-1+a)|0;return i=r(c+Math.round(s*a/2+(l-c-(n.length-1+a)*s)/2),s),o=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(u,a,c){arguments.length<2&&(a=0),arguments.length<3&&(c=a);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=(f-s)/(n.length-a+2*c);return i=r(s+h*c,h),l&&i.reverse(),o=h*(1-a),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,a,c){arguments.length<2&&(a=0),arguments.length<3&&(c=a);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=Math.floor((f-s)/(n.length-a+2*c));return i=r(s+Math.round((f-s-(n.length-a)*h)/2),h),l&&i.reverse(),o=Math.round(h*(1-a)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Pi(t.a[0])},e.copy=function(){return Qi(n,t)},e.domain(n)}function no(n,t){function i(){var e=0,r=t.length;for(a=[];++e<r;)a[e-1]=ta.quantile(n,e/r);return o}function o(n){return isNaN(n=+n)?void 0:t[ta.bisect(a,n)]}var a;return o.domain=function(t){return arguments.length?(n=t.map(r).filter(u).sort(e),i()):n},o.range=function(n){return arguments.length?(t=n,i()):t},o.quantiles=function(){return a},o.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?a[e-1]:n[0],e<a.length?a[e]:n[n.length-1]]},o.copy=function(){return no(n,t)},i()}function to(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=Et(e),p=Et(r);++f<h;)u.call(this,c=t[f],f)?s.push([+g.call(this,c,f),+p.call(this,c,f)]):s.length&&(o(),s=[]);return s.length&&o(),l.length?l.join(""):null}var e=Ar,r=Nr,u=Ne,i=go,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=El.get(n)||go).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function go(n){return n.join("L")}function po(n){return go(n)+"Z"}function vo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function yo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function Mo(n,t){return n.length<4?go(n):n[1]+_o(n.slice(1,-1),wo(n,t))}function xo(n,t){return n.length<3?go(n):n[0]+_o((n.push(n[0]),n),wo([n[n.length-2]].concat(n,[n[1]]),t))}function bo(n,t){return n.length<3?go(n):n[0]+_o(n,wo(n,t))}function _o(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return go(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l<t.length;l++,c++)i=n[c],a=t[l],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var s=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+s[0]+","+s[1]}return r}function wo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function So(n){if(n.length<3)return go(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",No(Cl,o),",",No(Cl,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Co(c,o,a);return n.pop(),c.push("L",r),c.join("")}function ko(n){if(n.length<4)return go(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(No(Cl,i)+","+No(Cl,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),Co(e,i,o);return e.join("")}function Eo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[No(Cl,o),",",No(Cl,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Co(t,o,a);return t.join("")}function Ao(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,l=-1;++l<=e;)r=n[l],u=l/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return So(n)}function No(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Co(n,t,e){n.push("C",No(Al,t),",",No(Al,e),",",No(Nl,t),",",No(Nl,e),",",No(Cl,t),",",No(Cl,e))}function zo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function qo(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=zo(u,i);++t<e;)r[t]=(o+(o=zo(u=i,i=n[t+1])))/2;return r[t]=o,r}function Lo(n){for(var t,e,r,u,i=[],o=qo(n),a=-1,c=n.length-1;++a<c;)t=zo(n[a],n[a+1]),ga(t)<Ca?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]-Ra,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Do(n){function t(t){function c(){v.push("M",a(n(m),f),s,l(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,M=t.length,x=Et(e),b=Et(u),_=e===r?function(){return g}:Et(r),w=u===i?function(){return p}:Et(i);++y<M;)o.call(this,h=t[y],y)?(d.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),m.push([+_.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=Ar,r=Ar,u=0,i=Nr,o=Ne,a=go,c=a.key,l=a,s="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r
+},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=El.get(n)||go).key,l=a.reverse||a,s=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Po(n){return n.radius}function Uo(n){return[n.x,n.y]}function jo(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Ra;return[e*Math.cos(r),e*Math.sin(r)]}}function Fo(){return 64}function Ho(){return"circle"}function Oo(n){var t=Math.sqrt(n/qa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Io(n){return function(){var t,e;(t=this[n])&&(e=t[t.active])&&(--t.count?delete t[t.active]:delete this[n],t.active+=.5,e.event&&e.event.interrupt.call(this,this.__data__,e.index))}}function Yo(n,t,e){return ya(n,Pl),n.namespace=t,n.id=e,n}function Zo(n,t,e,r){var u=n.id,i=n.namespace;return Y(n,"function"==typeof e?function(n,o,a){n[i][u].tween.set(t,r(e.call(n,n.__data__,o,a)))}:(e=r(e),function(n){n[i][u].tween.set(t,e)}))}function Vo(n){return null==n&&(n=""),function(){this.textContent=n}}function Xo(n){return null==n?"__transition__":"__transition_"+n+"__"}function $o(n,t,e,r,u){var i=n[e]||(n[e]={active:0,count:0}),o=i[r];if(!o){var a=u.time;o=i[r]={tween:new l,time:a,delay:u.delay,duration:u.duration,ease:u.ease,index:t},u=null,++i.count,ta.timer(function(u){function c(e){if(i.active>r)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,a)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=ec,v=[];return p.t=g+a,u>=g?c(u-g):void(p.c=c)},0,a)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Vl,u);return i==Vl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Vl[i-1]<Vl[i]/u?i-1:i]:[Bl,Vi(n,e)[2]]}return r.invert=function(t){return Ko(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Ko)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Ko(+e+1),t).length}var i=r.domain(),o=Pi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Fi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Yi(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.6"},ea=[].slice,ra=function(n){return ea.call(n)},ua=this.document;if(ua)try{ra(ua.documentElement.childNodes)[0].nodeType}catch(ia){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),ua)try{ua.createElement("DIV").style.setProperty("opacity",0,"")}catch(oa){var aa=this.Element.prototype,ca=aa.setAttribute,la=aa.setAttributeNS,sa=this.CSSStyleDeclaration.prototype,fa=sa.setProperty;aa.setAttribute=function(n,t){ca.call(this,n,t+"")},aa.setAttributeNS=function(n,t,e){la.call(this,n,t,e+"")},sa.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ta.ascending=e,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o;)if(null!=(r=n[i])&&r>=r){e=u=r;break}for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=u=r;break}for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var e,r=0,i=n.length,o=-1;if(1===arguments.length)for(;++o<i;)u(e=+n[o])&&(r+=e);else for(;++o<i;)u(e=+t.call(n,n[o],o))&&(r+=e);return r},ta.mean=function(n,t){var e,i=0,o=n.length,a=-1,c=o;if(1===arguments.length)for(;++a<o;)u(e=r(n[a]))?i+=e:--c;else for(;++a<o;)u(e=r(t.call(n,n[a],a)))?i+=e:--c;return c?i/c:void 0},ta.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},ta.median=function(n,t){var i,o=[],a=n.length,c=-1;if(1===arguments.length)for(;++c<a;)u(i=r(n[c]))&&o.push(i);else for(;++c<a;)u(i=r(t.call(n,n[c],c)))&&o.push(i);return o.length?ta.quantile(o.sort(e),.5):void 0},ta.variance=function(n,t){var e,i,o=n.length,a=0,c=0,l=-1,s=0;if(1===arguments.length)for(;++l<o;)u(e=r(n[l]))&&(i=e-a,a+=i/++s,c+=i*(e-a));else for(;++l<o;)u(e=r(t.call(n,n[l],l)))&&(i=e-a,a+=i/++s,c+=i*(e-a));return s>1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ha=i(e);ta.bisectLeft=ha.left,ta.bisect=ta.bisectRight=ha.right,ta.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,o),e=new Array(t);++n<t;)for(var r,u=-1,i=e[n]=new Array(r);++u<r;)i[u]=arguments[u][n];return e},ta.transpose=function(n){return ta.zip.apply(ta,n)},ta.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ta.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ta.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ta.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ga=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=a(ga(e)),o=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++o)>t;)u.push(r/i);else for(;(r=n+e*++o)<t;)u.push(r/i);return u},ta.map=function(n,t){var e=new l;if(n instanceof l)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,u=-1,i=n.length;if(1===arguments.length)for(;++u<i;)e.set(u,n[u]);else for(;++u<i;)e.set(t.call(n,r=n[u],u),r)}else for(var o in n)e.set(o,n[o]);return e};var pa="__proto__",va="\x00";c(l,{has:h,get:function(n){return this._[s(n)]},set:function(n,t){return this._[s(n)]=t},remove:g,keys:p,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:f(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t),this._[t])}}),ta.nest=function(){function n(t,o,a){if(a>=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var c,s,f,h,g=-1,p=o.length,v=i[a++],d=new l;++g<p;)(h=d.get(c=v(s=o[g])))?h.push(s):d.set(c,[s]);return t?(s=t(),f=function(e,r){s.set(e,n(t,r,a))}):(s={},f=function(e,r){s[e]=n(t,r,a)}),d.forEach(f),s}function t(n,e){if(e>=i.length)return n;var r=[],u=o[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ta.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return o[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ta.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},c(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),ta.behavior={},ta.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=M(n,t,t[e]);return n};var da=["webkit","ms","moz","Moz","o","O"];ta.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ta.event=null,ta.requote=function(n){return n.replace(ma,"\\$&")};var ma=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ya={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ma=function(n,t){return t.querySelector(n)},xa=function(n,t){return t.querySelectorAll(n)},ba=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(ba=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(Ma=function(n,t){return Sizzle(n,t)[0]||null},xa=Sizzle,ba=Sizzle.matchesSelector),ta.selection=function(){return ta.select(ua.documentElement)};var _a=ta.selection.prototype=[];_a.select=function(n){var t,e,r,u,i=[];n=N(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,l=r.length;++c<l;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return A(i)},_a.selectAll=function(n){var t,e,r=[];n=C(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=ra(n.call(e,e.__data__,a,u))),t.parentNode=e);return A(r)};var wa={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ta.ns={prefix:wa,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.slice(0,t),n=n.slice(t+1)),wa.hasOwnProperty(e)?{space:wa[e],local:n}:n}},_a.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ta.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},_a.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!L(n[u]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},_a.style=function(n,e,r){var u=arguments.length;if(3>u){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},_a.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},_a.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},_a.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},_a.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},_a.insert=function(n,t){return n=j(n),t=N(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},_a.remove=function(){return this.each(F)},_a.data=function(n,t){function e(n,e){var r,u,i,o=n.length,f=e.length,h=Math.min(o,f),g=new Array(f),p=new Array(f),v=new Array(o);if(t){var d,m=new l,y=new Array(o);for(r=-1;++r<o;)m.has(d=t.call(u=n[r],u.__data__,r))?v[r]=u:m.set(d,u),y[r]=d;for(r=-1;++r<f;)(u=m.get(d=t.call(e,i=e[r],r)))?u!==!0&&(g[r]=u,u.__data__=i):p[r]=H(i),m.set(d,!0);for(r=-1;++r<o;)m.get(y[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=H(i);for(;f>r;++r)p[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,a.push(p),c.push(g),s.push(v)}var r,u,i=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++i<o;)(u=r[i])&&(n[i]=u.__data__);return n}var a=Z([]),c=A([]),s=A([]);if("function"==typeof n)for(;++i<o;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i<o;)e(r=this[i],n);return c.enter=function(){return a},c.exit=function(){return s},c},_a.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},_a.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return A(u)},_a.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},_a.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},_a.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},_a.call=function(n){var t=ra(arguments);return n.apply(t[0]=this,t),this},_a.empty=function(){return!this.node()},_a.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},_a.size=function(){var n=0;return Y(this,function(){++n}),n};var Sa=[];ta.selection.enter=Z,ta.selection.enter.prototype=Sa,Sa.append=_a.append,Sa.empty=_a.empty,Sa.node=_a.node,Sa.call=_a.call,Sa.size=_a.size,Sa.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var l=-1,s=u.length;++l<s;)(i=u[l])?(t.push(r[l]=e=n.call(u.parentNode,i.__data__,l,a)),e.__data__=i.__data__):t.push(null)}return A(o)},Sa.insert=function(n,t){return arguments.length<2&&(t=V(this)),_a.insert.call(this,n,t)},ta.select=function(t){var e;return"string"==typeof t?(e=[Ma(t,ua)],e.parentNode=ua.documentElement):(e=[t],e.parentNode=n(t)),A([e])},ta.selectAll=function(n){var t;return"string"==typeof n?(t=ra(xa(n,ua)),t.parentNode=ua.documentElement):(t=n,t.parentNode=null),A([t])},_a.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var ka=ta.map({mouseenter:"mouseover",mouseleave:"mouseout"});ua&&ka.forEach(function(n){"on"+n in ua&&ka.remove(n)});var Ea,Aa=0;ta.mouse=function(n){return J(n,k())};var Na=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ta.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},ta.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",o)}function e(n,t,e,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+l[0],y:r[1]+l[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&ta.event.target===f),g({type:"dragend"}))}var l,s=this,f=ta.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=ta.select(e(f)).on(i+d,a).on(o+d,c),y=W(f),M=t(h,v);u?(l=u.apply(s,arguments),l=[l.x-M[0],l.y-M[1]]):l=[0,0],g({type:"dragstart"})}}var r=E(n,"drag","dragstart","dragend"),u=null,i=e(b,ta.mouse,t,"mousemove","mouseup"),o=e(G,ta.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},ta.rebind(n,r,"on")},ta.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ra(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Ca=1e-6,za=Ca*Ca,qa=Math.PI,La=2*qa,Ta=La-Ca,Ra=qa/2,Da=qa/180,Pa=180/qa,Ua=Math.SQRT2,ja=2,Fa=4;ta.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=rt(v),o=i/(ja*h)*(e*ut(Ua*t+v)-et(v));return[r+o*l,u+o*s,i*e/rt(Ua*t+v)]}return[r+n*l,u+n*s,i*Math.exp(Ua*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+Fa*f)/(2*i*ja*h),p=(c*c-i*i-Fa*f)/(2*c*ja*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ua;return e.duration=1e3*y,e},ta.behavior.zoom=function(){function n(n){n.on(q,f).on(Oa+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(N[0],Math.min(N[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,o)),i(d=e,r),t=ta.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function c(n){z++||n({type:"zoomstart"})}function l(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||(n({type:"zoomend"}),d=null)}function f(){function n(){f=1,i(ta.mouse(u),g),l(a)}function r(){h.on(L,null).on(T,null),p(f&&ta.event.target===o),s(a)}var u=this,o=ta.event.target,a=D.of(u,arguments),f=0,h=ta.select(t(u)).on(L,n).on(T,r),g=e(ta.mouse(u)),p=W(u);Dl.call(u),c(a)}function h(){function n(){var n=ta.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ta.event.target;ta.select(t).on(x,r).on(b,a),_.push(t);for(var e=ta.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var c=n(),l=Date.now();if(1===c.length){if(500>l-M){var s=c[0];o(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=l}else if(c.length>1){var s=c[0],f=c[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,o=ta.touches(p);Dl.call(p);for(var a=0,c=o.length;c>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),l(v)}function a(){if(ta.event.touches.length){for(var t=ta.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}ta.selectAll(_).on(y,null),w.on(q,f).on(R,h),E(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+ta.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=ta.select(p),E=W(p);t(),c(v),w.on(q,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(Dl.call(this),v=e(d=m||ta.mouse(this)),c(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Ha())*k.k),i(d,v),l(n)}function p(){var n=ta.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ta.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},A=[960,500],N=Ia,C=250,z=0,q="mousedown.zoom",L="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=E(n,"zoomstart","zoom","zoomend");return Oa||(Oa="onwheel"in ua?(Ha=function(){return-ta.event.deltaY*(ta.event.deltaMode?120:1)},"wheel"):"onmousewheel"in ua?(Ha=function(){return ta.event.wheelDelta},"mousewheel"):(Ha=function(){return-ta.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Tl?ta.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},c(n)}).tween("zoom:zoom",function(){var e=A[0],r=A[1],u=d?d[0]:e/2,i=d?d[1]:r/2,o=ta.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:u-r[0]*a,y:i-r[1]*a,k:a},l(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,c(n),l(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:+t},a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(N=null==t?Ia:[+t[0],+t[1]],n):N},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(A=t&&[+t[0],+t[1]],n):A},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ta.rebind(n,D,"on")};var Ha,Oa,Ia=[0,1/0];ta.color=ot,ot.prototype.toString=function(){return this.rgb()+""},ta.hsl=at;var Ya=at.prototype=new ot;Ya.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,this.l/n)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,n*this.l)},Ya.rgb=function(){return ct(this.h,this.s,this.l)},ta.hcl=lt;var Za=lt.prototype=new ot;Za.brighter=function(n){return new lt(this.h,this.c,Math.min(100,this.l+Va*(arguments.length?n:1)))},Za.darker=function(n){return new lt(this.h,this.c,Math.max(0,this.l-Va*(arguments.length?n:1)))},Za.rgb=function(){return st(this.h,this.c,this.l).rgb()},ta.lab=ft;var Va=18,Xa=.95047,$a=1,Ba=1.08883,Wa=ft.prototype=new ot;Wa.brighter=function(n){return new ft(Math.min(100,this.l+Va*(arguments.length?n:1)),this.a,this.b)},Wa.darker=function(n){return new ft(Math.max(0,this.l-Va*(arguments.length?n:1)),this.a,this.b)},Wa.rgb=function(){return ht(this.l,this.a,this.b)},ta.rgb=mt;var Ja=mt.prototype=new ot;Ja.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new mt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mt(u,u,u)},Ja.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mt(n*this.r,n*this.g,n*this.b)},Ja.hsl=function(){return _t(this.r,this.g,this.b)},Ja.toString=function(){return"#"+xt(this.r)+xt(this.g)+xt(this.b)};var Ga=ta.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ga.forEach(function(n,t){Ga.set(n,yt(t))}),ta.functor=Et,ta.xhr=At(y),ta.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=Nt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=l)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++<l;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}s=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++s):10===r&&(u=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;l>s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==c)continue;return n.slice(t,s-a)}return n.slice(t)}for(var r,u,i={},o={},a=[],l=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,f++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},ta.csv=ta.dsv(",","text/csv"),ta.tsv=ta.dsv(" ","text/tab-separated-values");var Ka,Qa,nc,tc,ec,rc=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ta.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Qa?Qa.n=i:Ka=i,Qa=i,nc||(tc=clearTimeout(tc),nc=1,rc(qt))},ta.timer.flush=function(){Lt(),Tt()},ta.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var uc=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);ta.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ta.round(n,Rt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),uc[8+e/3]};var ic=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,oc=ta.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ta.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),ac=ta.time={},cc=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){lc.setUTCDate.apply(this._,arguments)},setDay:function(){lc.setUTCDay.apply(this._,arguments)},setFullYear:function(){lc.setUTCFullYear.apply(this._,arguments)},setHours:function(){lc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){lc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){lc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){lc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){lc.setUTCSeconds.apply(this._,arguments)},setTime:function(){lc.setTime.apply(this._,arguments)}};var lc=Date.prototype;ac.year=Ft(function(n){return n=ac.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ac.years=ac.year.range,ac.years.utc=ac.year.utc.range,ac.day=Ft(function(n){var t=new cc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ac.days=ac.day.range,ac.days.utc=ac.day.utc.range,ac.dayOfYear=function(n){var t=ac.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ac[n]=Ft(function(n){return(n=ac.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ac[n+"s"]=e.range,ac[n+"s"].utc=e.utc.range,ac[n+"OfYear"]=function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)}}),ac.week=ac.sunday,ac.weeks=ac.sunday.range,ac.weeks.utc=ac.sunday.utc.range,ac.weekOfYear=ac.sundayOfYear;var sc={"-":"",_:" ",0:"0"},fc=/^\s*\d+/,hc=/^%/;ta.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var gc=ta.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ta.format=gc.numberFormat,ta.geo={},ce.prototype={s:0,t:0,add:function(n){le(n,this.t,pc),le(pc.s,this.s,this),this.s?this.t+=pc.t:this.s=pc.t
+},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var pc=new ce;ta.geo.stream=function(n,t){n&&vc.hasOwnProperty(n.type)?vc[n.type](n,t):se(n,t)};var vc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)se(e[r].geometry,t)}},dc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){fe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)fe(e[r],t,0)},Polygon:function(n,t){he(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)he(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)se(e[r],t)}};ta.geo.area=function(n){return mc=0,ta.geo.stream(n,Mc),mc};var mc,yc=new ce,Mc={sphere:function(){mc+=4*qa},point:b,lineStart:b,lineEnd:b,polygonStart:function(){yc.reset(),Mc.lineStart=ge},polygonEnd:function(){var n=2*yc;mc+=0>n?4*qa+n:n,Mc.lineStart=Mc.lineEnd=Mc.point=b}};ta.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=pe([t*Da,e*Da]);if(m){var u=de(m,r),i=[u[1],-u[0],0],o=de(i,u);Me(o),o=xe(o);var c=t-p,l=c>0?1:-1,v=o[0]*Pa*l,d=ga(c)>180;if(d^(v>l*p&&l*t>v)){var y=o[1]*Pa;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>l*p&&l*t>v)){var y=-o[1]*Pa;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ga(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Mc.point(n,e),t(n,e)}function i(){Mc.lineStart()}function o(){u(v,d),Mc.lineEnd(),ga(y)>Ca&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var s,f,h,g,p,v,d,m,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=u,b.lineStart=i,b.lineEnd=o,y=0,Mc.polygonStart()},polygonEnd:function(){Mc.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>yc?(s=-(h=180),f=-(g=90)):y>Ca?g=90:-Ca>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],ta.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),ta.geo.centroid=function(n){xc=bc=_c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,qc);var t=Nc,e=Cc,r=zc,u=t*t+e*e+r*r;return za>u&&(t=kc,e=Ec,r=Ac,Ca>bc&&(t=_c,e=wc,r=Sc),u=t*t+e*e+r*r,za>u)?[0/0,0/0]:[Math.atan2(e,t)*Pa,tt(r/Math.sqrt(u))*Pa]};var xc,bc,_c,wc,Sc,kc,Ec,Ac,Nc,Cc,zc,qc={sphere:b,point:_e,lineStart:Se,lineEnd:ke,polygonStart:function(){qc.lineStart=Ee},polygonEnd:function(){qc.lineStart=Se}},Lc=Le(Ne,Pe,je,[-qa,-qa/2]),Tc=1e9;ta.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ie(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ta.geo.conicEqualArea=function(){return Ye(Ze)}).raw=Ze,ta.geo.albers=function(){return ta.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ta.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=ta.geo.albers(),o=ta.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ta.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Ca,f+.12*l+Ca],[s-.214*l-Ca,f+.234*l-Ca]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Ca,f+.166*l+Ca],[s-.115*l-Ca,f+.234*l-Ca]]).stream(c).point,n},n.scale(1070)};var Rc,Dc,Pc,Uc,jc,Fc,Hc={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Dc=0,Hc.lineStart=Ve},polygonEnd:function(){Hc.lineStart=Hc.lineEnd=Hc.point=b,Rc+=ga(Dc/2)}},Oc={point:Xe,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Ic={point:We,lineStart:Je,lineEnd:Ge,polygonStart:function(){Ic.lineStart=Ke},polygonEnd:function(){Ic.point=We,Ic.lineStart=Je,Ic.lineEnd=Ge}};ta.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),ta.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Rc=0,ta.geo.stream(n,u(Hc)),Rc},n.centroid=function(n){return _c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,u(Ic)),zc?[Nc/zc,Cc/zc]:Ac?[kc/Ac,Ec/Ac]:Sc?[_c/Sc,wc/Sc]:[0/0,0/0]},n.bounds=function(n){return jc=Fc=-(Pc=Uc=1/0),ta.geo.stream(n,u(Oc)),[[Pc,Uc],[jc,Fc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||tr(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new $e:new Qe(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(ta.geo.albersUsa()).context(null)},ta.geo.transform=function(n){return{stream:function(t){var e=new er(t);for(var r in n)e[r]=n[r];return e}}},er.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ta.geo.projection=ur,ta.geo.projectionMutator=ir,(ta.geo.equirectangular=function(){return ur(ar)}).raw=ar.invert=ar,ta.geo.rotation=function(n){function t(t){return t=n(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t}return n=lr(n[0]%360*Da,n[1]*Da,n.length>2?n[2]*Da:0),t.invert=function(t){return t=n.invert(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t},t},cr.invert=ar,ta.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=lr(-n[0]*Da,-n[1]*Da,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Pa,n[1]*=Pa}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=gr((t=+r)*Da,u*Da),n):t},n.precision=function(r){return arguments.length?(e=gr(t*Da,(u=+r)*Da),n):u},n.angle(90)},ta.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Da,u=n[1]*Da,i=t[1]*Da,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},ta.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ta.range(Math.ceil(i/d)*d,u,d).map(h).concat(ta.range(Math.ceil(l/m)*m,c,m).map(g)).concat(ta.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ga(n%d)>Ca}).map(s)).concat(ta.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ga(n%m)>Ca}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=vr(a,o,90),f=dr(r,e,y),h=vr(l,c,90),g=dr(i,u,y),n):y},n.majorExtent([[-180,-90+Ca],[180,90-Ca]]).minorExtent([[-180,-80-Ca],[180,80+Ca]])},ta.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=mr,u=yr;return n.distance=function(){return ta.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},ta.geo.interpolate=function(n,t){return Mr(n[0]*Da,n[1]*Da,t[0]*Da,t[1]*Da)},ta.geo.length=function(n){return Yc=0,ta.geo.stream(n,Zc),Yc};var Yc,Zc={sphere:b,point:b,lineStart:xr,lineEnd:b,polygonStart:b,polygonEnd:b},Vc=br(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ta.geo.azimuthalEqualArea=function(){return ur(Vc)}).raw=Vc;var Xc=br(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(ta.geo.azimuthalEquidistant=function(){return ur(Xc)}).raw=Xc,(ta.geo.conicConformal=function(){return Ye(_r)}).raw=_r,(ta.geo.conicEquidistant=function(){return Ye(wr)}).raw=wr;var $c=br(function(n){return 1/n},Math.atan);(ta.geo.gnomonic=function(){return ur($c)}).raw=$c,Sr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ra]},(ta.geo.mercator=function(){return kr(Sr)}).raw=Sr;var Bc=br(function(){return 1},Math.asin);(ta.geo.orthographic=function(){return ur(Bc)}).raw=Bc;var Wc=br(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ta.geo.stereographic=function(){return ur(Wc)}).raw=Wc,Er.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ra]},(ta.geo.transverseMercator=function(){var n=kr(Er),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Er,ta.geom={},ta.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=Et(e),i=Et(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(zr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var l=Cr(a),s=Cr(c),f=s[0]===l[0],h=s[s.length-1]===l[l.length-1],g=[];for(t=l.length-1;t>=0;--t)g.push(n[a[l[t]][2]]);for(t=+f;t<s.length-h;++t)g.push(n[a[s[t]][2]]);return g}var e=Ar,r=Nr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ta.geom.polygon=function(n){return ya(n,Jc),n};var Jc=ta.geom.polygon.prototype=[];Jc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Jc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Jc.clip=function(n){for(var t,e,r,u,i,o,a=Tr(n),c=-1,l=this.length-Tr(this),s=this[l-1];++c<l;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],qr(o,s,u)?(qr(i,s,u)||n.push(Lr(i,o,s,u)),n.push(o)):qr(i,s,u)&&n.push(Lr(i,o,s,u)),i=o;a&&n.push(n[0]),s=u}return n};var Gc,Kc,Qc,nl,tl,el=[],rl=[];Or.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Yr),t.length},Qr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},nu.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=uu(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(eu(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ru(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(ru(this,e),n=e,e=n.U),e.C=!1,r.C=!0,eu(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?uu(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,eu(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ru(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,eu(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,ru(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,eu(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,ru(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},ta.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return iu(e(n),a).cells.forEach(function(e,a){var c=e.edges,l=e.site,s=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):l.x>=r&&l.x<=i&&l.y>=u&&l.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];s.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Ca)*Ca,y:Math.round(o(n,t)/Ca)*Ca,i:t}})}var r=Ar,u=Nr,i=r,o=u,a=ul;return n?t(n):(t.links=function(n){return iu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return iu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Yr),c=-1,l=a.length,s=a[l-1].edge,f=s.l===o?s.r:s.l;++c<l;)u=s,i=f,s=a[c].edge,f=s.l===o?s.r:s.l,r<i.i&&r<f.i&&au(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=Et(r=n),t):r},t.y=function(n){return arguments.length?(o=Et(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?ul:n,t):a===ul?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===ul?null:a&&a[1]},t)};var ul=[[-1e6,-1e6],[1e6,1e6]];ta.geom.delaunay=function(n){return ta.geom.voronoi().triangles(n)},ta.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,s=n.y;if(null!=c)if(ga(c-e)+ga(s-r)<.01)l(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,l(n,f,c,s,u,i,o,a),l(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,u,i,o,a)}function l(n,t,e,r,u,o,a,c){var l=.5*(u+a),s=.5*(o+c),f=e>=l,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=su()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,v,d,m,y,M=Et(a),x=Et(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.x<v&&(v=s.x),s.y<d&&(d=s.y),s.x>m&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=su();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){fu(n,k,v,d,m,y)},k.find=function(n){return hu(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=s=null,k}var o,a=Ar,c=Nr;return(o=arguments.length)?(a=cu,c=lu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},ta.interpolateRgb=gu,ta.interpolateObject=pu,ta.interpolateNumber=vu,ta.interpolateString=du;var il=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,ol=new RegExp(il.source,"g");ta.interpolate=mu,ta.interpolators=[function(n,t){var e=typeof t;return("string"===e?Ga.has(t.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(t)?gu:du:t instanceof ot?gu:Array.isArray(t)?yu:"object"===e&&isNaN(t)?pu:vu)(n,t)}],ta.interpolateArray=yu;var al=function(){return y},cl=ta.map({linear:al,poly:ku,quad:function(){return _u},cubic:function(){return wu},sin:function(){return Eu},exp:function(){return Au},circle:function(){return Nu},elastic:Cu,back:zu,bounce:function(){return qu}}),ll=ta.map({"in":y,out:xu,"in-out":bu,"out-in":function(n){return bu(xu(n))}});ta.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=cl.get(e)||al,r=ll.get(r)||y,Mu(r(e.apply(null,ea.call(arguments,1))))},ta.interpolateHcl=Lu,ta.interpolateHsl=Tu,ta.interpolateLab=Ru,ta.interpolateRound=Du,ta.transform=function(n){var t=ua.createElementNS(ta.ns.prefix.svg,"g");return(ta.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Pu(e?e.matrix:sl)})(n)},Pu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var sl={a:1,b:0,c:0,d:1,e:0,f:0};ta.interpolateTransform=Hu,ta.layout={},ta.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Yu(n[e]));return t}},ta.layout.chord=function(){function n(){var n,l,f,h,g,p={},v=[],d=ta.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(l=0,g=-1;++g<i;)l+=u[h][g];v.push(l),m.push(ta.range(i)),n+=l}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(La-s*i)/n,l=0,h=-1;++h<i;){for(f=l,g=-1;++g<i;){var y=d[h],M=m[y][g],x=u[y][M],b=l,_=l+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:f,endAngle:l,value:(l-f)/n},l+=s}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,l={},s=0;return l.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,l):u},l.padding=function(n){return arguments.length?(s=n,e=r=null,l):s},l.sortGroups=function(n){return arguments.length?(o=n,e=r=null,l):o},l.sortSubgroups=function(n){return arguments.length?(a=n,e=null,l):a},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},ta.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var l=t.charge/c;n.px-=i*l,n.py-=o*l}return!0}if(t.point&&c&&p>c){var l=t.pointCharge/c;n.px-=i*l,n.py-=o*l}}return!t.charge}}function t(n){n.px=ta.event.x,n.py=ta.event.y,a.resume()}var e,r,u,i,o,a={},c=ta.dispatch("start","tick","end"),l=[1,1],s=.9,f=fl,h=hl,g=-30,p=gl,v=.1,d=.64,m=[],M=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,y,x,b=m.length,_=M.length;for(e=0;_>e;++e)a=M[e],f=a.source,h=a.target,y=h.x-f.x,x=h.y-f.y,(p=y*y+x*x)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,y*=p,x*=p,h.x-=y*(d=f.weight/(h.weight+f.weight)),h.y-=x*d,f.x+=y*(d=1-d),f.y+=x*d);if((d=r*v)&&(y=l[0]/2,x=l[1]/2,e=-1,d))for(;++e<b;)a=m[e],a.x+=(y-a.x)*d,a.y+=(x-a.y)*d;if(g)for(Ju(t=ta.geom.quadtree(m),r,o),e=-1;++e<b;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<b;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*s,a.y-=(a.py-(a.py=a.y))*s);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(M=n,a):M},a.size=function(n){return arguments.length?(l=n,a):l},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(s=+n,a):s},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ta.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=M[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,l=o.length;++a<l;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,s=M.length,p=l[0],v=l[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;s>t;++t)r=M[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;s>t;++t)u[t]=+f.call(this,M[t],t);else for(t=0;s>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;s>t;++t)i[t]=+h.call(this,M[t],t);else for(t=0;s>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=ta.behavior.drag().origin(y).on("dragstart.force",Xu).on("drag.force",t).on("dragend.force",$u)),arguments.length?void this.on("mouseover.force",Bu).on("mouseout.force",Wu).call(e):e},ta.rebind(a,c,"on")};var fl=20,hl=1,gl=1/0;ta.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(l=e.call(n,i,i.depth))&&(c=l.length)){for(var c,l,s;--c>=0;)o.push(s=l[c]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=l}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Qu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ei,e=ni,r=ti;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ku(t,function(n){n.children&&(n.value=0)}),Qu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ta.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++l<o;)n(a=i[l],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=ta.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Gu(e,r)},ta.layout.pie=function(){function n(o){var a,c=o.length,l=o.map(function(e,r){return+t.call(n,e,r)}),s=+("function"==typeof r?r.apply(this,arguments):r),f=("function"==typeof u?u.apply(this,arguments):u)-s,h=Math.min(Math.abs(f)/c,+("function"==typeof i?i.apply(this,arguments):i)),g=h*(0>f?-1:1),p=(f-c*g)/ta.sum(l),v=ta.range(c),d=[];return null!=e&&v.sort(e===pl?function(n,t){return l[t]-l[n]}:function(n,t){return e(o[n],o[t])}),v.forEach(function(n){d[n]={data:o[n],value:a=l[n],startAngle:s,endAngle:s+=a*p+g,padAngle:h}}),d}var t=Number,e=pl,r=0,u=La,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var pl={};ta.layout.stack=function(){function n(a,c){if(!(h=a.length))return a;var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=ta.permute(l,f),s=ta.permute(s,f);var h,g,p,v,d=r.call(n,s,c),m=l[0].length;for(p=0;m>p;++p)for(u.call(n,l[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,l[g][p],v+=s[g-1][p][1],s[g][p][1]);return a}var t=y,e=ai,r=ci,u=oi,i=ui,o=ii;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:vl.get(t)||ai,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:dl.get(t)||ci,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var vl=ta.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(li),i=n.map(si),o=ta.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return ta.range(n.length).reverse()},"default":ai}),dl=ta.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ci});ta.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=l[i],a>=s[0]&&a<=s[1]&&(o=c[ta.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=pi,u=hi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=Et(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return gi(n,t)}:Et(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ta.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Qu(a,function(n){n.r=+s(n.value)}),Qu(a,Mi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Qu(a,function(n){n.r+=f}),Qu(a,Mi),Qu(a,function(n){n.r-=f})}return _i(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=ta.layout.hierarchy().sort(vi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Gu(n,e)},ta.layout.tree=function(){function n(n,u){var s=o.call(this,n,u),f=s[0],h=t(f);if(Qu(h,e),h.parent.m=-h.z,Ku(h,r),l)Ku(f,i);else{var g=f,p=f,v=f;Ku(f,function(n){n.x<g.x&&(g=n),n.x>p.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);Ku(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Ni(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],l=u.m,s=i.m,f=o.m,h=c.m;o=Ei(o),u=ki(u),o&&u;)c=ki(c),i=Ei(i),i.a=n,r=o.z+f-u.z-l+a(o._,u._),r>0&&(Ai(Ci(o,n,e),n,r),l+=r,s+=r),f+=o.m,l+=u.m,h+=c.m,s+=i.m;o&&!Ei(i)&&(i.t=o,i.m+=f-s),u&&!ki(c)&&(c.t=u,c.m+=l-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=ta.layout.hierarchy().sort(null).value(null),a=Si,c=[1,1],l=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(l=null==(c=t)?i:null,n):l?null:c},n.nodeSize=function(t){return arguments.length?(l=null==(c=t)?null:i,n):l?c:null},Gu(n,o)},ta.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Qu(c,function(n){var t=n.children;t&&t.length?(n.x=qi(t),n.y=zi(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Li(c),f=Ti(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Qu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=ta.layout.hierarchy().sort(null).value(null),e=Si,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Gu(n,t)},ta.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,v))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,v,l,!1),v=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++i<o;)u=n[i],u.x=a,u.y=l,u.dy=s,a+=u.dx=Math.min(e.x+e.dx-a,s?c(u.area/s):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=s,e.dy-=s}else{for((r||s>e.dx)&&(s=e.dx);++i<o;)u=n[i],u.x=a,u.y=l,u.dx=s,l+=u.dy=Math.min(e.y+e.dy-l,s?c(u.area/s):0);u.z=!1,u.dy+=e.y+e.dy-l,e.x+=s,e.dx-=s}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=l[0],i.dy=l[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=ta.layout.hierarchy(),c=Math.round,l=[1,1],s=null,f=Ri,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));
+return i.size=function(n){return arguments.length?(l=n,i):l},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ri(t):Di(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Di(t,n)}if(!arguments.length)return s;var r;return f=null==(s=n)?Ri:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Gu(i,a)},ta.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=ta.random.normal.apply(ta,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ta.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ta.scale={};var ml={floor:y,ceil:y};ta.scale.linear=function(){return Ii([0,1],[0,1],mu,!1)};var yl={s:1,g:1,p:1,r:1,e:1};ta.scale.log=function(){return Ji(ta.scale.linear().domain([0,1]),10,!0,[1,10])};var Ml=ta.format(".0e"),xl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ta.scale.pow=function(){return Gi(ta.scale.linear(),1,[0,1])},ta.scale.sqrt=function(){return ta.scale.pow().exponent(.5)},ta.scale.ordinal=function(){return Qi([],{t:"range",a:[[]]})},ta.scale.category10=function(){return ta.scale.ordinal().range(bl)},ta.scale.category20=function(){return ta.scale.ordinal().range(_l)},ta.scale.category20b=function(){return ta.scale.ordinal().range(wl)},ta.scale.category20c=function(){return ta.scale.ordinal().range(Sl)};var bl=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(Mt),_l=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(Mt),wl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(Mt),Sl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(Mt);ta.scale.quantile=function(){return no([],[])},ta.scale.quantize=function(){return to(0,1,[0,1])},ta.scale.threshold=function(){return eo([.5],[0,1])},ta.scale.identity=function(){return ro([0,1])},ta.svg={},ta.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),l=Math.max(0,+r.apply(this,arguments)),s=o.apply(this,arguments)-Ra,f=a.apply(this,arguments)-Ra,h=Math.abs(f-s),g=s>f?0:1;if(n>l&&(p=l,l=n,n=p),h>=Ta)return t(l,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,E=0,A=0,N=[];if((m=(+c.apply(this,arguments)||0)/2)&&(d=i===kl?Math.sqrt(n*n+l*l):+i.apply(this,arguments),g||(A*=-1),l&&(A=tt(d/l*Math.sin(m))),n&&(E=tt(d/n*Math.sin(m)))),l){y=l*Math.cos(s+A),M=l*Math.sin(s+A),x=l*Math.cos(f-A),b=l*Math.sin(f-A);var C=Math.abs(f-s-2*A)<=qa?0:1;if(A&&so(y,M,x,b)===g^C){var z=(s+f)/2;y=l*Math.cos(z),M=l*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-E),w=n*Math.sin(f-E),S=n*Math.cos(s+E),k=n*Math.sin(s+E);var q=Math.abs(s-f+2*E)<=qa?0:1;if(E&&so(_,w,S,k)===1-g^q){var L=(s+f)/2;_=n*Math.cos(L),w=n*Math.sin(L),S=k=null}}else _=w=0;if((p=Math.min(Math.abs(l-n)/2,+u.apply(this,arguments)))>.001){v=l>n^g?0:1;var T=null==S?[_,w]:null==x?[y,M]:Lr([y,M],[S,k],[x,b],[_,w]),R=y-T[0],D=M-T[1],P=x-T[0],U=b-T[1],j=1/Math.sin(Math.acos((R*P+D*U)/(Math.sqrt(R*R+D*D)*Math.sqrt(P*P+U*U)))/2),F=Math.sqrt(T[0]*T[0]+T[1]*T[1]);if(null!=x){var H=Math.min(p,(l-F)/(j+1)),O=fo(null==S?[_,w]:[S,k],[y,M],l,H,g),I=fo([x,b],[_,w],l,H,g);p===H?N.push("M",O[0],"A",H,",",H," 0 0,",v," ",O[1],"A",l,",",l," 0 ",1-g^so(O[1][0],O[1][1],I[1][0],I[1][1]),",",g," ",I[1],"A",H,",",H," 0 0,",v," ",I[0]):N.push("M",O[0],"A",H,",",H," 0 1,",v," ",I[0])}else N.push("M",y,",",M);if(null!=S){var Y=Math.min(p,(n-F)/(j-1)),Z=fo([y,M],[S,k],n,-Y,g),V=fo([_,w],null==x?[y,M]:[x,b],n,-Y,g);p===Y?N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^so(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",Y,",",Y," 0 0,",v," ",Z[0]):N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",Z[0])}else N.push("L",_,",",w)}else N.push("M",y,",",M),null!=x&&N.push("A",l,",",l," 0 ",C,",",g," ",x,",",b),N.push("L",_,",",w),null!=S&&N.push("A",n,",",n," 0 ",q,",",1-g," ",S,",",k);return N.push("Z"),N.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=io,r=oo,u=uo,i=kl,o=ao,a=co,c=lo;return n.innerRadius=function(t){return arguments.length?(e=Et(t),n):e},n.outerRadius=function(t){return arguments.length?(r=Et(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=Et(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==kl?kl:Et(t),n):i},n.startAngle=function(t){return arguments.length?(o=Et(t),n):o},n.endAngle=function(t){return arguments.length?(a=Et(t),n):a},n.padAngle=function(t){return arguments.length?(c=Et(t),n):c},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Ra;return[Math.cos(t)*n,Math.sin(t)*n]},n};var kl="auto";ta.svg.line=function(){return ho(y)};var El=ta.map({linear:go,"linear-closed":po,step:vo,"step-before":mo,"step-after":yo,basis:So,"basis-open":ko,"basis-closed":Eo,bundle:Ao,cardinal:bo,"cardinal-open":Mo,"cardinal-closed":xo,monotone:To});El.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Al=[0,2/3,1/3,0],Nl=[0,1/3,2/3,0],Cl=[0,1/6,2/3,1/6];ta.svg.line.radial=function(){var n=ho(Ro);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},mo.reverse=yo,yo.reverse=mo,ta.svg.area=function(){return Do(y)},ta.svg.area.radial=function(){var n=Do(Ro);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ta.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)-Ra,s=l.call(n,u,r)-Ra;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>qa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=mr,o=yr,a=Po,c=ao,l=co;return n.radius=function(t){return arguments.length?(a=Et(t),n):a},n.source=function(t){return arguments.length?(i=Et(t),n):i},n.target=function(t){return arguments.length?(o=Et(t),n):o},n.startAngle=function(t){return arguments.length?(c=Et(t),n):c},n.endAngle=function(t){return arguments.length?(l=Et(t),n):l},n},ta.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=mr,e=yr,r=Uo;return n.source=function(e){return arguments.length?(t=Et(e),n):t},n.target=function(t){return arguments.length?(e=Et(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ta.svg.diagonal.radial=function(){var n=ta.svg.diagonal(),t=Uo,e=n.projection;return n.projection=function(n){return arguments.length?e(jo(t=n)):t},n},ta.svg.symbol=function(){function n(n,r){return(zl.get(t.call(this,n,r))||Oo)(e.call(this,n,r))}var t=Ho,e=Fo;return n.type=function(e){return arguments.length?(t=Et(e),n):t},n.size=function(t){return arguments.length?(e=Et(t),n):e},n};var zl=ta.map({circle:Oo,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ll)),e=t*Ll;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ta.svg.symbolTypes=zl.keys();var ql=Math.sqrt(3),Ll=Math.tan(30*Da);_a.transition=function(n){for(var t,e,r=Tl||++Ul,u=Xo(n),i=[],o=Rl||{time:Date.now(),ease:Su,delay:0,duration:250},a=-1,c=this.length;++a<c;){i.push(t=[]);for(var l=this[a],s=-1,f=l.length;++s<f;)(e=l[s])&&$o(e,s,u,r,o),t.push(e)}return Yo(i,u,r)},_a.interrupt=function(n){return this.each(null==n?Dl:Io(Xo(n)))};var Tl,Rl,Dl=Io(Xo()),Pl=[],Ul=0;Pl.call=_a.call,Pl.empty=_a.empty,Pl.node=_a.node,Pl.size=_a.size,ta.transition=function(n,t){return n&&n.transition?Tl?n.transition(t):n:ta.selection().transition(n)},ta.transition.prototype=Pl,Pl.select=function(n){var t,e,r,u=this.id,i=this.namespace,o=[];n=N(n);for(var a=-1,c=this.length;++a<c;){o.push(t=[]);for(var l=this[a],s=-1,f=l.length;++s<f;)(r=l[s])&&(e=n.call(r,r.__data__,s,a))?("__data__"in r&&(e.__data__=r.__data__),$o(e,s,i,u,r[i][u]),t.push(e)):t.push(null)}return Yo(o,i,u)},Pl.selectAll=function(n){var t,e,r,u,i,o=this.id,a=this.namespace,c=[];n=C(n);for(var l=-1,s=this.length;++l<s;)for(var f=this[l],h=-1,g=f.length;++h<g;)if(r=f[h]){i=r[a][o],e=n.call(r,r.__data__,h,l),c.push(t=[]);for(var p=-1,v=e.length;++p<v;)(u=e[p])&&$o(u,p,a,o,i),t.push(u)}return Yo(c,a,o)},Pl.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Yo(u,this.namespace,this.id)},Pl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Pl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Hu:mu,a=ta.ns.qualify(n);return Zo(this,"attr."+n,t,a.local?i:u)},Pl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=ta.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Pl.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=mu(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Zo(this,"style."+n,e,i)},Pl.styleTween=function(n,e,r){function u(u,i){var o=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Pl.text=function(n){return Zo(this,"text",n,Vo)},Pl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Pl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ta.ease.apply(ta,arguments)),Y(this,function(r){r[e][t].ease=n}))},Pl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Pl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Pl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Rl,i=Tl;try{Tl=e,Y(this,function(t,u,i){Rl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Rl=u,Tl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=ta.dispatch("start","end","interrupt"))).on(n,t)});return this},Pl.transition=function(){for(var n,t,e,r,u=this.id,i=++Ul,o=this.namespace,a=[],c=0,l=this.length;l>c;c++){a.push(n=[]);for(var t=this[c],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[o][u],$o(e,s,o,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Yo(a,o,i)},ta.svg.axis=function(){function n(n){n.each(function(){var n,l=ta.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):y:t,p=l.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Ca),d=ta.transition(p.exit()).style("opacity",Ca).remove(),m=ta.transition(p.order()).style("opacity",1),M=Math.max(u,0)+o,x=Ui(f),b=l.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ta.transition(b));v.append("line"),v.append("text");var w,S,k,E,A=v.select("line"),N=m.select("line"),C=p.select("text").text(g),z=v.select("text"),q=m.select("text"),L="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=Bo,w="x",k="y",S="x2",E="y2",C.attr("dy",0>L?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+L*i+"V0H"+x[1]+"V"+L*i)):(n=Wo,w="y",k="x",S="y2",E="x2",C.attr("dy",".32em").style("text-anchor",0>L?"end":"start"),_.attr("d","M"+L*i+","+x[0]+"H0V"+x[1]+"H"+L*i)),A.attr(E,L*u),z.attr(k,L*M),N.attr(S,0).attr(E,L*u),q.attr(w,0).attr(k,L*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=ta.scale.linear(),r=jl,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Fl?t+"":jl,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var jl="bottom",Fl={top:1,right:1,bottom:1,left:1};ta.svg.brush=function(){function n(t){t.each(function(){var t=ta.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,y);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Hl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var c,f=ta.transition(t),h=ta.transition(o);l&&(c=Ui(l),h.attr("x",c[0]).attr("width",c[1]-c[0]),r(f)),s&&(c=Ui(s),h.attr("y",c[0]).attr("height",c[1]-c[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==ta.event.keyCode&&(C||(M=null,q[0]-=f[1],q[1]-=h[1],C=2),S())}function v(){32==ta.event.keyCode&&2==C&&(q[0]+=f[1],q[1]+=h[1],C=0,S())}function d(){var n=ta.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ta.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),q[0]=f[+(n[0]<M[0])],q[1]=h[+(n[1]<M[1])]):M=null),A&&m(n,l,0)&&(r(k),t=!0),N&&m(n,s,1)&&(u(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,i=Ui(t),c=i[0],l=i[1],s=q[e],v=e?h:f,d=v[1]-v[0];return C&&(c-=s,l-=d+s),r=(e?p:g)?Math.max(c,Math.min(l,n[e])):n[e],C?u=(r+=s)+d:(M&&(s=Math.max(c,Math.min(l,2*M[e]-r))),r>s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?a=null:o=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ta.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ta.select(ta.event.target),w=c.of(b,arguments),k=ta.select(b),E=_.datum(),A=!/^(n|s)$/.test(E)&&l,N=!/^(e|w)$/.test(E)&&s,C=_.classed("extent"),z=W(b),q=ta.mouse(b),L=ta.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(ta.event.changedTouches?L.on("touchmove.brush",d).on("touchend.brush",y):L.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)q[0]=f[0]-q[0],q[1]=h[0]-q[1];else if(E){var T=+/w$/.test(E),R=+/^n/.test(E);x=[f[1-T]-q[0],h[1-R]-q[1]],q[0]=f[T],q[1]=h[R]}else ta.event.altKey&&(M=q.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ta.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,c=E(n,"brushstart","brush","brushend"),l=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=Ol[0];return n.event=function(n){n.each(function(){var n=c.of(this,arguments),t={x:f,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Tl?ta.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=yu(f,t.x),r=yu(h,t.y);return o=a=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(l=t,v=Ol[!l<<1|!s],n):l},n.y=function(t){return arguments.length?(s=t,v=Ol[!l<<1|!s],n):s},n.clamp=function(t){return arguments.length?(l&&s?(g=!!t[0],p=!!t[1]):l?g=!!t:s&&(p=!!t),n):l&&s?[g,p]:l?g:s?p:null},n.extent=function(t){var e,r,u,i,c;return arguments.length?(l&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),o=[e,r],l.invert&&(e=l(e),r=l(r)),e>r&&(c=e,e=r,r=c),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],l&&(u=u[1],i=i[1]),a=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(c=u,u=i,i=c),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(l&&(o?(e=o[0],r=o[1]):(e=f[0],r=f[1],l.invert&&(e=l.invert(e),r=l.invert(r)),e>r&&(c=e,e=r,r=c))),s&&(a?(u=a[0],i=a[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(c=u,u=i,i=c))),l&&s?[[e,u],[r,i]]:l?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!l&&f[0]==f[1]||!!s&&h[0]==h[1]},ta.rebind(n,c,"on")};var Hl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ol=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Il=ac.format=gc.timeFormat,Yl=Il.utc,Zl=Yl("%Y-%m-%dT%H:%M:%S.%LZ");Il.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Jo:Zl,Jo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Jo.toString=Zl.toString,ac.second=Ft(function(n){return new cc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ac.seconds=ac.second.range,ac.seconds.utc=ac.second.utc.range,ac.minute=Ft(function(n){return new cc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ac.minutes=ac.minute.range,ac.minutes.utc=ac.minute.utc.range,ac.hour=Ft(function(n){var t=n.getTimezoneOffset()/60;return new cc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ac.hours=ac.hour.range,ac.hours.utc=ac.hour.utc.range,ac.month=Ft(function(n){return n=ac.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ac.months=ac.month.range,ac.months.utc=ac.month.utc.range;var Vl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Xl=[[ac.second,1],[ac.second,5],[ac.second,15],[ac.second,30],[ac.minute,1],[ac.minute,5],[ac.minute,15],[ac.minute,30],[ac.hour,1],[ac.hour,3],[ac.hour,6],[ac.hour,12],[ac.day,1],[ac.day,2],[ac.week,1],[ac.month,1],[ac.month,3],[ac.year,1]],$l=Il.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",Ne]]),Bl={range:function(n,t,e){return ta.range(Math.ceil(n/e)*e,+t,e).map(Ko)},floor:y,ceil:y};Xl.year=ac.year,ac.scale=function(){return Go(ta.scale.linear(),Xl,$l)};var Wl=Xl.map(function(n){return[n[0].utc,n[1]]}),Jl=Yl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",Ne]]);Wl.year=ac.year.utc,ac.scale.utc=function(){return Go(ta.scale.linear(),Wl,Jl)},ta.text=At(function(n){return n.responseText}),ta.json=function(n,t){return Nt(n,"application/json",Qo,t)},ta.html=function(n,t){return Nt(n,"text/html",na,t)},ta.xml=At(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(ta):"object"==typeof module&&module.exports&&(module.exports=ta),this.d3=ta}(); \ No newline at end of file
diff --git a/modules/http/static/datamaps.world.min.js b/modules/http/static/datamaps.world.min.js
new file mode 100644
index 0000000..8b5d932
--- /dev/null
+++ b/modules/http/static/datamaps.world.min.js
@@ -0,0 +1,2 @@
+!function(){function a(a,b,c){return this.svg=m.select(a).append("svg").attr("width",c||a.offsetWidth).attr("data-width",c||a.offsetWidth).attr("class","datamap").attr("height",b||a.offsetHeight).style("overflow","hidden"),this.options.responsive&&(m.select(this.options.element).style({position:"relative","padding-bottom":"60%"}),m.select(this.options.element).select("svg").style({position:"absolute",width:"100%",height:"100%"}),m.select(this.options.element).select("svg").select("g").selectAll("path").style("vector-effect","non-scaling-stroke")),this.svg}function b(a,b){var c,d,e=b.width||a.offsetWidth,f=b.height||a.offsetHeight,g=this.svg;return b&&"undefined"==typeof b.scope&&(b.scope="world"),"usa"===b.scope?c=m.geo.albersUsa().scale(e).translate([e/2,f/2]):"world"===b.scope&&(c=m.geo[b.projection]().scale((e+1)/2/Math.PI).translate([e/2,f/("mercator"===b.projection?1.45:1.8)])),"orthographic"===b.projection&&(g.append("defs").append("path").datum({type:"Sphere"}).attr("id","sphere").attr("d",d),g.append("use").attr("class","stroke").attr("xlink:href","#sphere"),g.append("use").attr("class","fill").attr("xlink:href","#sphere"),c.scale(250).clipAngle(90).rotate(b.projectionConfig.rotation)),d=m.geo.path().projection(c),{path:d,projection:c}}function c(){m.select(".datamaps-style-block").empty()&&m.select("head").append("style").attr("class","datamaps-style-block").html('.datamap path.datamaps-graticule { fill: none; stroke: #777; stroke-width: 0.5px; stroke-opacity: .5; pointer-events: none; } .datamap .labels {pointer-events: none;} .datamap path {stroke: #FFFFFF; stroke-width: 1px;} .datamaps-legend dt, .datamaps-legend dd { float: left; margin: 0 3px 0 0;} .datamaps-legend dd {width: 20px; margin-right: 6px; border-radius: 3px;} .datamaps-legend {padding-bottom: 20px; z-index: 1001; position: absolute; left: 4px; font-size: 12px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;} .datamaps-hoverover {display: none; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .hoverinfo {padding: 4px; border-radius: 1px; background-color: #FFF; box-shadow: 1px 1px 5px #CCC; font-size: 12px; border: 1px solid #CCC; } .hoverinfo hr {border:1px dotted #CCC; }')}function d(a){var b=this.options.fills,c=this.options.data||{},d=this.options.geographyConfig,e=this.svg.select("g.datamaps-subunits");e.empty()&&(e=this.addLayer("datamaps-subunits",null,!0));var f=n.feature(a,a.objects[this.options.scope]).features;d.hideAntarctica&&(f=f.filter(function(a){return"ATA"!==a.id}));var g=e.selectAll("path.datamaps-subunit").data(f);g.enter().append("path").attr("d",this.path).attr("class",function(a){return"datamaps-subunit "+a.id}).attr("data-info",function(a){return JSON.stringify(c[a.id])}).style("fill",function(a){var d;return c[a.id]&&(d=b[c[a.id].fillKey]),d||b.defaultFill}).style("stroke-width",d.borderWidth).style("stroke",d.borderColor)}function e(){function a(){this.parentNode.appendChild(this)}var b=this.svg,c=this,d=this.options.geographyConfig;(d.highlightOnHover||d.popupOnHover)&&b.selectAll(".datamaps-subunit").on("mouseover",function(e){var f=m.select(this);if(d.highlightOnHover){var g={fill:f.style("fill"),stroke:f.style("stroke"),"stroke-width":f.style("stroke-width"),"fill-opacity":f.style("fill-opacity")};f.style("fill",d.highlightFillColor).style("stroke",d.highlightBorderColor).style("stroke-width",d.highlightBorderWidth).style("fill-opacity",d.highlightFillOpacity).attr("data-previousAttributes",JSON.stringify(g)),/((MSIE)|(Trident))/.test||a.call(this)}d.popupOnHover&&c.updatePopup(f,e,d,b)}).on("mouseout",function(){var a=m.select(this);if(d.highlightOnHover){var b=JSON.parse(a.attr("data-previousAttributes"));for(var c in b)a.style(c,b[c])}a.on("mousemove",null),m.selectAll(".datamaps-hoverover").style("display","none")})}function f(a,b){if(b=b||{},this.options.fills){var c="<dl>",d="";b.legendTitle&&(c="<h2>"+b.legendTitle+"</h2>"+c);for(var e in this.options.fills){if("defaultFill"===e){if(!b.defaultFillName)continue;d=b.defaultFillName}else d=b.labels&&b.labels[e]?b.labels[e]:e+": ";c+="<dt>"+d+"</dt>",c+='<dd style="background-color:'+this.options.fills[e]+'">&nbsp;</dd>'}c+="</dl>",m.select(this.options.element).append("div").attr("class","datamaps-legend").html(c)}}function g(){var a=m.geo.graticule();this.svg.insert("path",".datamaps-subunits").datum(a).attr("class","datamaps-graticule").attr("d",this.path)}function h(a,b,c){var d=this;if(this.svg,!b||b&&!b.slice)throw"Datamaps Error - arcs must be an array";"undefined"==typeof c&&(c=o.arcConfig);var e=a.selectAll("path.datamaps-arc").data(b,JSON.stringify),f=m.geo.path().projection(d.projection),g=m.geo.greatArc().source(function(a){return[a.origin.longitude,a.origin.latitude]}).target(function(a){return[a.destination.longitude,a.destination.latitude]});e.enter().append("svg:path").attr("class","datamaps-arc").style("stroke-linecap","round").style("stroke",function(a){return a.options&&a.options.strokeColor?a.options.strokeColor:c.strokeColor}).style("fill","none").style("stroke-width",function(a){return a.options&&a.options.strokeWidth?a.options.strokeWidth:c.strokeWidth}).attr("d",function(a){var b=d.latLngToXY(a.origin.latitude,a.origin.longitude),e=d.latLngToXY(a.destination.latitude,a.destination.longitude),h=[(b[0]+e[0])/2,(b[1]+e[1])/2];return c.greatArc?f(g(a)):"M"+b[0]+","+b[1]+"S"+(h[0]+50*c.arcSharpness)+","+(h[1]-75*c.arcSharpness)+","+e[0]+","+e[1]}).transition().delay(100).style("fill",function(){var a=this.getTotalLength();return this.style.transition=this.style.WebkitTransition="none",this.style.strokeDasharray=a+" "+a,this.style.strokeDashoffset=a,this.getBoundingClientRect(),this.style.transition=this.style.WebkitTransition="stroke-dashoffset "+c.animationSpeed+"ms ease-out",this.style.strokeDashoffset="0","none"}),e.exit().transition().style("opacity",0).remove()}function i(a,b){var c=this;b=b||{};var d=this.projection([-67.707617,42.722131]);this.svg.selectAll(".datamaps-subunit").attr("data-foo",function(e){var f=c.path.centroid(e),g=7.5,h=5;["FL","KY","MI"].indexOf(e.id)>-1&&(g=-2.5),"NY"===e.id&&(g=-1),"MI"===e.id&&(h=18),"LA"===e.id&&(g=13);var i,j;i=f[0]-g,j=f[1]+h;var k=["VT","NH","MA","RI","CT","NJ","DE","MD","DC"].indexOf(e.id);if(k>-1){var l=d[1];i=d[0],j=l+k*(2+(b.fontSize||12)),a.append("line").attr("x1",i-3).attr("y1",j-5).attr("x2",f[0]).attr("y2",f[1]).style("stroke",b.labelColor||"#000").style("stroke-width",b.lineWidth||1)}return a.append("text").attr("x",i).attr("y",j).style("font-size",(b.fontSize||10)+"px").style("font-family",b.fontFamily||"Verdana").style("fill",b.labelColor||"#000").text(e.id),"bar"})}function j(a,b,c){function d(a){return"undefined"!=typeof a&&"undefined"!=typeof a.latitude&&"undefined"!=typeof a.longitude}var e=this,f=this.options.fills,g=this.svg;if(!b||b&&!b.slice)throw"Datamaps Error - bubbles must be an array";var h=a.selectAll("circle.datamaps-bubble").data(b,JSON.stringify);h.enter().append("svg:circle").attr("class","datamaps-bubble").attr("cx",function(a){var b;return d(a)?b=e.latLngToXY(a.latitude,a.longitude):a.centered&&(b=e.path.centroid(g.select("path."+a.centered).data()[0])),b?b[0]:void 0}).attr("cy",function(a){var b;return d(a)?b=e.latLngToXY(a.latitude,a.longitude):a.centered&&(b=e.path.centroid(g.select("path."+a.centered).data()[0])),b?b[1]:void 0}).attr("r",0).attr("data-info",function(a){return JSON.stringify(a)}).style("stroke",function(a){return"undefined"!=typeof a.borderColor?a.borderColor:c.borderColor}).style("stroke-width",function(a){return"undefined"!=typeof a.borderWidth?a.borderWidth:c.borderWidth}).style("fill-opacity",function(a){return"undefined"!=typeof a.fillOpacity?a.fillOpacity:c.fillOpacity}).style("fill",function(a){var b=f[a.fillKey];return b||f.defaultFill}).on("mouseover",function(a){var b=m.select(this);if(c.highlightOnHover){var d={fill:b.style("fill"),stroke:b.style("stroke"),"stroke-width":b.style("stroke-width"),"fill-opacity":b.style("fill-opacity")};b.style("fill",c.highlightFillColor).style("stroke",c.highlightBorderColor).style("stroke-width",c.highlightBorderWidth).style("fill-opacity",c.highlightFillOpacity).attr("data-previousAttributes",JSON.stringify(d))}c.popupOnHover&&e.updatePopup(b,a,c,g)}).on("mouseout",function(){var a=m.select(this);if(c.highlightOnHover){var b=JSON.parse(a.attr("data-previousAttributes"));for(var d in b)a.style(d,b[d])}m.selectAll(".datamaps-hoverover").style("display","none")}).transition().duration(400).attr("r",function(a){return a.radius}),h.exit().transition().delay(c.exitDelay).attr("r",0).remove()}function k(a){return Array.prototype.slice.call(arguments,1).forEach(function(b){if(b)for(var c in b)null==a[c]&&(a[c]=b[c])}),a}function l(b){if("undefined"==typeof m||"undefined"==typeof n)throw new Error("Include d3.js (v3.0.3 or greater) and topojson on this page before creating a new map");return this.options=k(b,o),this.options.geographyConfig=k(b.geographyConfig,o.geographyConfig),this.options.projectionConfig=k(b.projectionConfig,o.projectionConfig),this.options.bubblesConfig=k(b.bubblesConfig,o.bubblesConfig),this.options.arcConfig=k(b.arcConfig,o.arcConfig),m.select(this.options.element).select("svg").length>0&&a.call(this,this.options.element,this.options.height,this.options.width),this.addPlugin("bubbles",j),this.addPlugin("legend",f),this.addPlugin("arc",h),this.addPlugin("labels",i),this.addPlugin("graticule",g),this.options.disableDefaultStyles||c(),this.draw()}var m=window.d3,n=window.topojson,o={scope:"world",responsive:!1,setProjection:b,projection:"equirectangular",dataType:"json",done:function(){},fills:{defaultFill:"#ABDDA4"},geographyConfig:{dataUrl:null,hideAntarctica:!0,borderWidth:1,borderColor:"#FDFDFD",popupTemplate:function(a){return'<div class="hoverinfo"><strong>'+a.properties.name+"</strong></div>"},popupOnHover:!0,highlightOnHover:!0,highlightFillColor:"#FC8D59",highlightBorderColor:"rgba(250, 15, 160, 0.2)",highlightBorderWidth:2},projectionConfig:{rotation:[97,0]},bubblesConfig:{borderWidth:2,borderColor:"#FFFFFF",popupOnHover:!0,popupTemplate:function(a,b){return'<div class="hoverinfo"><strong>'+b.name+"</strong></div>"},fillOpacity:.75,animate:!0,highlightOnHover:!0,highlightFillColor:"#FC8D59",highlightBorderColor:"rgba(250, 15, 160, 0.2)",highlightBorderWidth:2,highlightFillOpacity:.85,exitDelay:100},arcConfig:{strokeColor:"#DD1C77",strokeWidth:1,arcSharpness:1,animationSpeed:600}};l.prototype.resize=function(){var a=this,b=a.options;if(b.responsive){var c="-webkit-transform"in document.body.style?"-webkit-":"-moz-transform"in document.body.style?"-moz-":"-ms-transform"in document.body.style?"-ms-":"",d=b.element.clientWidth,e=m.select(b.element).select("svg").attr("data-width");m.select(b.element).select("svg").selectAll("g").style(c+"transform","scale("+d/e+")")}},l.prototype.draw=function(){function a(a){b.options.dataUrl&&m[b.options.dataType](b.options.dataUrl,function(a){if("csv"===b.options.dataType&&a&&a.slice){for(var c={},d=0;d<a.length;d++)c[a[d].id]=a[d];a=c}Datamaps.prototype.updateChoropleth.call(b,a)}),d.call(b,a),e.call(b),(b.options.geographyConfig.popupOnHover||b.options.bubblesConfig.popupOnHover)&&(hoverover=m.select(b.options.element).append("div").attr("class","datamaps-hoverover").style("z-index",10001).style("position","absolute")),b.options.done(b)}var b=this,c=b.options,f=c.setProjection.apply(b,[c.element,c]);return this.path=f.path,this.projection=f.projection,c.geographyConfig.dataUrl?m.json(c.geographyConfig.dataUrl,function(c,d){if(c)throw new Error(c);b.customTopo=d,a(d)}):a(this[c.scope+"Topo"]||c.geographyConfig.dataJson),this},l.prototype.worldTopo={type:"Topology",objects:{world:{type:"GeometryCollection",geometries:[{type:"Polygon",properties:{name:"Afghanistan"},id:"AFG",arcs:[[0,1,2,3,4,5]]},{type:"MultiPolygon",properties:{name:"Angola"},id:"AGO",arcs:[[[6,7,8,9]],[[10,11,12]]]},{type:"Polygon",properties:{name:"Albania"},id:"ALB",arcs:[[13,14,15,16,17]]},{type:"Polygon",properties:{name:"United Arab Emirates"},id:"ARE",arcs:[[18,19,20,21,22]]},{type:"MultiPolygon",properties:{name:"Argentina"},id:"ARG",arcs:[[[23,24]],[[25,26,27,28,29,30]]]},{type:"Polygon",properties:{name:"Armenia"},id:"ARM",arcs:[[31,32,33,34,35]]},{type:"MultiPolygon",properties:{name:"Antarctica"},id:"ATA",arcs:[[[36]],[[37]],[[38]],[[39]],[[40]],[[41]],[[42]],[[43]]]},{type:"Polygon",properties:{name:"French Southern and Antarctic Lands"},id:"ATF",arcs:[[44]]},{type:"MultiPolygon",properties:{name:"Australia"},id:"AUS",arcs:[[[45]],[[46]]]},{type:"Polygon",properties:{name:"Austria"},id:"AUT",arcs:[[47,48,49,50,51,52,53]]},{type:"MultiPolygon",properties:{name:"Azerbaijan"},id:"AZE",arcs:[[[54,-35]],[[55,56,-33,57,58]]]},{type:"Polygon",properties:{name:"Burundi"},id:"BDI",arcs:[[59,60,61]]},{type:"Polygon",properties:{name:"Belgium"},id:"BEL",arcs:[[62,63,64,65,66]]},{type:"Polygon",properties:{name:"Benin"},id:"BEN",arcs:[[67,68,69,70,71]]},{type:"Polygon",properties:{name:"Burkina Faso"},id:"BFA",arcs:[[72,73,74,-70,75,76]]},{type:"Polygon",properties:{name:"Bangladesh"},id:"BGD",arcs:[[77,78,79]]},{type:"Polygon",properties:{name:"Bulgaria"},id:"BGR",arcs:[[80,81,82,83,84,85]]},{type:"MultiPolygon",properties:{name:"The Bahamas"},id:"BHS",arcs:[[[86]],[[87]],[[88]]]},{type:"Polygon",properties:{name:"Bosnia and Herzegovina"},id:"BIH",arcs:[[89,90,91]]},{type:"Polygon",properties:{name:"Belarus"},id:"BLR",arcs:[[92,93,94,95,96]]},{type:"Polygon",properties:{name:"Belize"},id:"BLZ",arcs:[[97,98,99]]},{type:"Polygon",properties:{name:"Bolivia"},id:"BOL",arcs:[[100,101,102,103,-31]]},{type:"Polygon",properties:{name:"Brazil"},id:"BRA",arcs:[[-27,104,-103,105,106,107,108,109,110,111,112]]},{type:"Polygon",properties:{name:"Brunei"},id:"BRN",arcs:[[113,114]]},{type:"Polygon",properties:{name:"Bhutan"},id:"BTN",arcs:[[115,116]]},{type:"Polygon",properties:{name:"Botswana"},id:"BWA",arcs:[[117,118,119,120]]},{type:"Polygon",properties:{name:"Central African Republic"},id:"CAF",arcs:[[121,122,123,124,125,126,127]]},{type:"MultiPolygon",properties:{name:"Canada"},id:"CAN",arcs:[[[128]],[[129]],[[130]],[[131]],[[132]],[[133]],[[134]],[[135]],[[136]],[[137]],[[138,139,140,141]],[[142]],[[143]],[[144]],[[145]],[[146]],[[147]],[[148]],[[149]],[[150]],[[151]],[[152]],[[153]],[[154]],[[155]],[[156]],[[157]],[[158]],[[159]],[[160]]]},{type:"Polygon",properties:{name:"Switzerland"},id:"CHE",arcs:[[-51,161,162,163]]},{type:"MultiPolygon",properties:{name:"Chile"},id:"CHL",arcs:[[[-24,164]],[[-30,165,166,-101]]]},{type:"MultiPolygon",properties:{name:"China"},id:"CHN",arcs:[[[167]],[[168,169,170,171,172,173,-117,174,175,176,177,-4,178,179,180,181,182,183]]]},{type:"Polygon",properties:{name:"Ivory Coast"},id:"CIV",arcs:[[184,185,186,187,-73,188]]},{type:"Polygon",properties:{name:"Cameroon"},id:"CMR",arcs:[[189,190,191,192,193,194,-128,195]]},{type:"Polygon",properties:{name:"Democratic Republic of the Congo"},id:"COD",arcs:[[196,197,-60,198,199,-10,200,-13,201,-126,202]]},{type:"Polygon",properties:{name:"Republic of the Congo"},id:"COG",arcs:[[-12,203,204,-196,-127,-202]]},{type:"Polygon",properties:{name:"Colombia"},id:"COL",arcs:[[205,206,207,208,209,-107,210]]},{type:"Polygon",properties:{name:"Costa Rica"},id:"CRI",arcs:[[211,212,213,214]]},{type:"Polygon",properties:{name:"Cuba"},id:"CUB",arcs:[[215]]},{type:"Polygon",properties:{name:"Northern Cyprus"},id:"-99",arcs:[[216,217]]},{type:"Polygon",properties:{name:"Cyprus"},id:"CYP",arcs:[[218,-218]]},{type:"Polygon",properties:{name:"Czech Republic"},id:"CZE",arcs:[[-53,219,220,221]]},{type:"Polygon",properties:{name:"Germany"},id:"DEU",arcs:[[222,223,-220,-52,-164,224,225,-64,226,227,228]]},{type:"Polygon",properties:{name:"Djibouti"},id:"DJI",arcs:[[229,230,231,232]]},{type:"MultiPolygon",properties:{name:"Denmark"},id:"DNK",arcs:[[[233]],[[-229,234]]]},{type:"Polygon",properties:{name:"Dominican Republic"},id:"DOM",arcs:[[235,236]]},{type:"Polygon",properties:{name:"Algeria"},id:"DZA",arcs:[[237,238,239,240,241,242,243,244]]},{type:"Polygon",properties:{name:"Ecuador"},id:"ECU",arcs:[[245,-206,246]]},{type:"Polygon",properties:{name:"Egypt"},id:"EGY",arcs:[[247,248,249,250,251]]},{type:"Polygon",properties:{name:"Eritrea"},id:"ERI",arcs:[[252,253,254,-233]]},{type:"Polygon",properties:{name:"Spain"},id:"ESP",arcs:[[255,256,257,258]]},{type:"Polygon",properties:{name:"Estonia"},id:"EST",arcs:[[259,260,261]]},{type:"Polygon",properties:{name:"Ethiopia"},id:"ETH",arcs:[[-232,262,263,264,265,266,267,-253]]},{type:"Polygon",properties:{name:"Finland"},id:"FIN",arcs:[[268,269,270,271]]},{type:"MultiPolygon",properties:{name:"Fiji"},id:"FJI",arcs:[[[272]],[[273,274]],[[275,-275]]]},{type:"Polygon",properties:{name:"Falkland Islands"},id:"FLK",arcs:[[276]]},{type:"MultiPolygon",properties:{name:"France"},id:"FRA",arcs:[[[277]],[[278,-225,-163,279,280,-257,281,-66]]]},{type:"Polygon",properties:{name:"French Guiana"},id:"GUF",arcs:[[282,283,284,285,-111]]},{type:"Polygon",properties:{name:"Gabon"},id:"GAB",arcs:[[286,287,-190,-205]]},{type:"MultiPolygon",properties:{name:"United Kingdom"},id:"GBR",arcs:[[[288,289]],[[290]]]},{type:"Polygon",properties:{name:"Georgia"},id:"GEO",arcs:[[291,292,-58,-32,293]]},{type:"Polygon",properties:{name:"Ghana"},id:"GHA",arcs:[[294,-189,-77,295]]},{type:"Polygon",properties:{name:"Guinea"},id:"GIN",arcs:[[296,297,298,299,300,301,-187]]},{type:"Polygon",properties:{name:"Gambia"},id:"GMB",arcs:[[302,303]]},{type:"Polygon",properties:{name:"Guinea Bissau"},id:"GNB",arcs:[[304,305,-300]]},{type:"Polygon",properties:{name:"Equatorial Guinea"},id:"GNQ",arcs:[[306,-191,-288]]},{type:"MultiPolygon",properties:{name:"Greece"},id:"GRC",arcs:[[[307]],[[308,-15,309,-84,310]]]},{type:"Polygon",properties:{name:"Greenland"},id:"GRL",arcs:[[311]]},{type:"Polygon",properties:{name:"Guatemala"},id:"GTM",arcs:[[312,313,-100,314,315,316]]},{type:"Polygon",properties:{name:"Guyana"},id:"GUY",arcs:[[317,318,-109,319]]},{type:"Polygon",properties:{name:"Honduras"},id:"HND",arcs:[[320,321,-316,322,323]]},{type:"Polygon",properties:{name:"Croatia"},id:"HRV",arcs:[[324,-92,325,326,327,328]]},{type:"Polygon",properties:{name:"Haiti"},id:"HTI",arcs:[[-237,329]]},{type:"Polygon",properties:{name:"Hungary"},id:"HUN",arcs:[[-48,330,331,332,333,-329,334]]},{type:"MultiPolygon",properties:{name:"Indonesia"},id:"IDN",arcs:[[[335]],[[336,337]],[[338]],[[339]],[[340]],[[341]],[[342]],[[343]],[[344,345]],[[346]],[[347]],[[348,349]],[[350]]]},{type:"Polygon",properties:{name:"India"},id:"IND",arcs:[[-177,351,-175,-116,-174,352,-80,353,354]]},{type:"Polygon",properties:{name:"Ireland"},id:"IRL",arcs:[[355,-289]]},{type:"Polygon",properties:{name:"Iran"},id:"IRN",arcs:[[356,-6,357,358,359,360,-55,-34,-57,361]]},{type:"Polygon",properties:{name:"Iraq"},id:"IRQ",arcs:[[362,363,364,365,366,367,-360]]},{type:"Polygon",properties:{name:"Iceland"},id:"ISL",arcs:[[368]]},{type:"Polygon",properties:{name:"Israel"},id:"ISR",arcs:[[369,370,371,-252,372,373,374]]},{type:"MultiPolygon",properties:{name:"Italy"},id:"ITA",arcs:[[[375]],[[376]],[[377,378,-280,-162,-50]]]},{type:"Polygon",properties:{name:"Jamaica"},id:"JAM",arcs:[[379]]},{type:"Polygon",properties:{name:"Jordan"},id:"JOR",arcs:[[-370,380,-366,381,382,-372,383]]},{type:"MultiPolygon",properties:{name:"Japan"},id:"JPN",arcs:[[[384]],[[385]],[[386]]]},{type:"Polygon",properties:{name:"Kazakhstan"},id:"KAZ",arcs:[[387,388,389,390,-181,391]]},{type:"Polygon",properties:{name:"Kenya"},id:"KEN",arcs:[[392,393,394,395,-265,396]]},{type:"Polygon",properties:{name:"Kyrgyzstan"},id:"KGZ",arcs:[[-392,-180,397,398]]},{type:"Polygon",properties:{name:"Cambodia"},id:"KHM",arcs:[[399,400,401,402]]},{type:"Polygon",properties:{name:"South Korea"},id:"KOR",arcs:[[403,404]]},{type:"Polygon",properties:{name:"Kosovo"},id:"-99",arcs:[[-18,405,406,407]]},{type:"Polygon",properties:{name:"Kuwait"},id:"KWT",arcs:[[408,409,-364]]},{type:"Polygon",properties:{name:"Laos"},id:"LAO",arcs:[[410,411,-172,412,-401]]},{type:"Polygon",properties:{name:"Lebanon"},id:"LBN",arcs:[[-374,413,414]]},{type:"Polygon",properties:{name:"Liberia"},id:"LBR",arcs:[[415,416,-297,-186]]},{type:"Polygon",properties:{name:"Libya"},id:"LBY",arcs:[[417,-245,418,419,-250,420,421]]},{type:"Polygon",properties:{name:"Sri Lanka"},id:"LKA",arcs:[[422]]},{type:"Polygon",properties:{name:"Lesotho"},id:"LSO",arcs:[[423]]},{type:"Polygon",properties:{name:"Lithuania"},id:"LTU",arcs:[[424,425,426,-93,427]]},{type:"Polygon",properties:{name:"Luxembourg"},id:"LUX",arcs:[[-226,-279,-65]]},{type:"Polygon",properties:{name:"Latvia"},id:"LVA",arcs:[[428,-262,429,-94,-427]]},{type:"Polygon",properties:{name:"Morocco"},id:"MAR",arcs:[[-242,430,431]]},{type:"Polygon",properties:{name:"Moldova"},id:"MDA",arcs:[[432,433]]},{type:"Polygon",properties:{name:"Madagascar"},id:"MDG",arcs:[[434]]},{type:"Polygon",properties:{name:"Mexico"},id:"MEX",arcs:[[435,-98,-314,436,437]]},{type:"Polygon",properties:{name:"Macedonia"},id:"MKD",arcs:[[-408,438,-85,-310,-14]]},{type:"Polygon",properties:{name:"Mali"},id:"MLI",arcs:[[439,-239,440,-74,-188,-302,441]]},{type:"Polygon",properties:{name:"Myanmar"},id:"MMR",arcs:[[442,-78,-353,-173,-412,443]]},{type:"Polygon",properties:{name:"Montenegro"},id:"MNE",arcs:[[444,-326,-91,445,-406,-17]]},{type:"Polygon",properties:{name:"Mongolia"},id:"MNG",arcs:[[446,-183]]},{type:"Polygon",properties:{name:"Mozambique"},id:"MOZ",arcs:[[447,448,449,450,451,452,453,454]]},{type:"Polygon",properties:{name:"Mauritania"},id:"MRT",arcs:[[455,456,457,-240,-440]]},{type:"Polygon",properties:{name:"Malawi"},id:"MWI",arcs:[[-455,458,459]]},{type:"MultiPolygon",properties:{name:"Malaysia"},id:"MYS",arcs:[[[460,461]],[[-349,462,-115,463]]]},{type:"Polygon",properties:{name:"Namibia"},id:"NAM",arcs:[[464,-8,465,-119,466]]},{type:"Polygon",properties:{name:"New Caledonia"},id:"NCL",arcs:[[467]]},{type:"Polygon",properties:{name:"Niger"},id:"NER",arcs:[[-75,-441,-238,-418,468,-194,469,-71]]},{type:"Polygon",properties:{name:"Nigeria"},id:"NGA",arcs:[[470,-72,-470,-193]]},{type:"Polygon",properties:{name:"Nicaragua"},id:"NIC",arcs:[[471,-324,472,-213]]},{type:"Polygon",properties:{name:"Netherlands"},id:"NLD",arcs:[[-227,-63,473]]},{type:"MultiPolygon",properties:{name:"Norway"},id:"NOR",arcs:[[[474,-272,475,476]],[[477]],[[478]],[[479]]]},{type:"Polygon",properties:{name:"Nepal"},id:"NPL",arcs:[[-352,-176]]},{type:"MultiPolygon",properties:{name:"New Zealand"},id:"NZL",arcs:[[[480]],[[481]]]},{type:"MultiPolygon",properties:{name:"Oman"},id:"OMN",arcs:[[[482,483,-22,484]],[[-20,485]]]},{type:"Polygon",properties:{name:"Pakistan"},id:"PAK",arcs:[[-178,-355,486,-358,-5]]},{type:"Polygon",properties:{name:"Panama"},id:"PAN",arcs:[[487,-215,488,-208]]},{type:"Polygon",properties:{name:"Peru"},id:"PER",arcs:[[-167,489,-247,-211,-106,-102]]},{type:"MultiPolygon",properties:{name:"Philippines"},id:"PHL",arcs:[[[490]],[[491]],[[492]],[[493]],[[494]],[[495]],[[496]]]},{type:"MultiPolygon",properties:{name:"Papua New Guinea"},id:"PNG",arcs:[[[497]],[[498]],[[-345,499]],[[500]]]},{type:"Polygon",properties:{name:"Poland"},id:"POL",arcs:[[-224,501,502,-428,-97,503,504,-221]]},{type:"Polygon",properties:{name:"Puerto Rico"},id:"PRI",arcs:[[505]]},{type:"Polygon",properties:{name:"North Korea"},id:"PRK",arcs:[[506,507,-405,508,-169]]},{type:"Polygon",properties:{name:"Portugal"},id:"PRT",arcs:[[-259,509]]},{type:"Polygon",properties:{name:"Paraguay"},id:"PRY",arcs:[[-104,-105,-26]]},{type:"Polygon",properties:{name:"Qatar"},id:"QAT",arcs:[[510,511]]},{type:"Polygon",properties:{name:"Romania"},id:"ROU",arcs:[[512,-434,513,514,-81,515,-333]]},{type:"MultiPolygon",properties:{name:"Russia"},id:"RUS",arcs:[[[516]],[[-503,517,-425]],[[518,519]],[[520]],[[521]],[[522]],[[523]],[[524]],[[525]],[[526,-507,-184,-447,-182,-391,527,-59,-293,528,529,-95,-430,-261,530,-269,-475,531,-520]],[[532]],[[533]],[[534]]]},{type:"Polygon",properties:{name:"Rwanda"},id:"RWA",arcs:[[535,-61,-198,536]]},{type:"Polygon",properties:{name:"Western Sahara"},id:"ESH",arcs:[[-241,-458,537,-431]]},{type:"Polygon",properties:{name:"Saudi Arabia"},id:"SAU",arcs:[[538,-382,-365,-410,539,-512,540,-23,-484,541]]},{type:"Polygon",properties:{name:"Sudan"},id:"SDN",arcs:[[542,543,-123,544,-421,-249,545,-254,-268,546]]},{type:"Polygon",properties:{name:"South Sudan"},id:"SSD",arcs:[[547,-266,-396,548,-203,-125,549,-543]]},{type:"Polygon",properties:{name:"Senegal"},id:"SEN",arcs:[[550,-456,-442,-301,-306,551,-304]]},{type:"MultiPolygon",properties:{name:"Solomon Islands"},id:"SLB",arcs:[[[552]],[[553]],[[554]],[[555]],[[556]]]},{type:"Polygon",properties:{name:"Sierra Leone"},id:"SLE",arcs:[[557,-298,-417]]},{type:"Polygon",properties:{name:"El Salvador"},id:"SLV",arcs:[[558,-317,-322]]},{type:"Polygon",properties:{name:"Somaliland"},id:"-99",arcs:[[-263,-231,559,560]]},{type:"Polygon",properties:{name:"Somalia"},id:"SOM",arcs:[[-397,-264,-561,561]]},{type:"Polygon",properties:{name:"Republic of Serbia"},id:"SRB",arcs:[[-86,-439,-407,-446,-90,-325,-334,-516]]},{type:"Polygon",properties:{name:"Suriname"},id:"SUR",arcs:[[562,-285,563,-283,-110,-319]]},{type:"Polygon",properties:{name:"Slovakia"},id:"SVK",arcs:[[-505,564,-331,-54,-222]]},{type:"Polygon",properties:{name:"Slovenia"},id:"SVN",arcs:[[-49,-335,-328,565,-378]]},{type:"Polygon",properties:{name:"Sweden"},id:"SWE",arcs:[[-476,-271,566]]},{type:"Polygon",properties:{name:"Swaziland"},id:"SWZ",arcs:[[567,-451]]},{type:"Polygon",properties:{name:"Syria"},id:"SYR",arcs:[[-381,-375,-415,568,569,-367]]},{type:"Polygon",properties:{name:"Chad"},id:"TCD",arcs:[[-469,-422,-545,-122,-195]]},{type:"Polygon",properties:{name:"Togo"},id:"TGO",arcs:[[570,-296,-76,-69]]},{type:"Polygon",properties:{name:"Thailand"},id:"THA",arcs:[[571,-462,572,-444,-411,-400]]},{type:"Polygon",properties:{name:"Tajikistan"},id:"TJK",arcs:[[-398,-179,-3,573]]},{type:"Polygon",properties:{name:"Turkmenistan"},id:"TKM",arcs:[[-357,574,-389,575,-1]]},{type:"Polygon",properties:{name:"East Timor"},id:"TLS",arcs:[[576,-337]]},{type:"Polygon",properties:{name:"Trinidad and Tobago"},id:"TTO",arcs:[[577]]},{type:"Polygon",properties:{name:"Tunisia"},id:"TUN",arcs:[[-244,578,-419]]},{type:"MultiPolygon",properties:{name:"Turkey"},id:"TUR",arcs:[[[-294,-36,-361,-368,-570,579]],[[-311,-83,580]]]},{type:"Polygon",properties:{name:"Taiwan"},id:"TWN",arcs:[[581]]},{type:"Polygon",properties:{name:"United Republic of Tanzania"},id:"TZA",arcs:[[-394,582,-448,-460,583,-199,-62,-536,584]]},{type:"Polygon",properties:{name:"Uganda"},id:"UGA",arcs:[[-537,-197,-549,-395,-585]]},{type:"Polygon",properties:{name:"Ukraine"},id:"UKR",arcs:[[-530,585,-514,-433,-513,-332,-565,-504,-96]]},{type:"Polygon",properties:{name:"Uruguay"},id:"URY",arcs:[[-113,586,-28]]},{type:"MultiPolygon",properties:{name:"United States of America"},id:"USA",arcs:[[[587]],[[588]],[[589]],[[590]],[[591]],[[592,-438,593,-139]],[[594]],[[595]],[[596]],[[-141,597]]]},{type:"Polygon",properties:{name:"Uzbekistan"},id:"UZB",arcs:[[-576,-388,-399,-574,-2]]},{type:"Polygon",properties:{name:"Venezuela"},id:"VEN",arcs:[[598,-320,-108,-210]]},{type:"Polygon",properties:{name:"Vietnam"},id:"VNM",arcs:[[599,-402,-413,-171]]},{type:"MultiPolygon",properties:{name:"Vanuatu"},id:"VUT",arcs:[[[600]],[[601]]]},{type:"Polygon",properties:{name:"West Bank"},id:"PSE",arcs:[[-384,-371]]},{type:"Polygon",properties:{name:"Yemen"},id:"YEM",arcs:[[602,-542,-483]]},{type:"Polygon",properties:{name:"South Africa"},id:"ZAF",arcs:[[-467,-118,603,-452,-568,-450,604],[-424]]},{type:"Polygon",properties:{name:"Zambia"},id:"ZMB",arcs:[[-459,-454,605,-120,-466,-7,-200,-584]]},{type:"Polygon",properties:{name:"Zimbabwe"},id:"ZWE",arcs:[[-604,-121,-606,-453]]}]}},arcs:[[[6700,7164],[28,-23],[21,8],[6,27],[22,9],[15,18],[6,47],[23,11],[5,21],[13,-15],[8,-2]],[[6847,7265],[16,-1],[20,-12]],[[6883,7252],[9,-7],[20,19],[9,-12],[9,27],[17,-1],[4,9],[3,24],[12,20],[15,-13],[-3,-18],[9,-3],[-3,-50],[11,-19],[10,12],[12,6],[17,27],[19,-5],[29,0]],[[7082,7268],[5,-17]],[[7087,7251],[-16,-6],[-14,-11],[-32,-7],[-30,-13],[-16,-25],[6,-25],[4,-30],[-14,-25],[1,-22],[-8,-22],[-26,2],[11,-39],[-18,-15],[-12,-35],[2,-36],[-11,-16],[-10,5],[-22,-8],[-3,-16],[-20,0],[-16,-34],[-1,-50],[-36,-24],[-19,5],[-6,-13],[-16,7],[-28,-8],[-47,30]],[[6690,6820],[25,53],[-2,38],[-21,10],[-2,38],[-9,47],[12,32],[-12,9],[7,43],[12,74]],[[5664,4412],[3,-18],[-4,-29],[5,-28],[-4,-22],[3,-20],[-58,1],[-2,-188],[19,-49],[18,-37]],[[5644,4022],[-51,-24],[-67,9],[-19,28],[-113,-3],[-4,-4],[-17,27],[-18,2],[-16,-10],[-14,-12]],[[5325,4035],[-2,38],[4,51],[9,55],[2,25],[9,53],[6,24],[16,39],[9,26],[3,44],[-1,34],[-9,21],[-7,36],[-7,35],[2,12],[8,24],[-8,57],[-6,39],[-14,38],[3,11]],[[5342,4697],[11,8],[8,-1],[10,7],[82,-1],[7,-44],[8,-35],[6,-19],[11,-31],[18,5],[9,8],[16,-8],[4,14],[7,35],[17,2],[2,10],[14,1],[-3,-22],[34,1],[1,-37],[5,-23],[-4,-36],[2,-36],[9,-22],[-1,-70],[7,5],[12,-1],[17,8],[13,-3]],[[5338,4715],[-8,45]],[[5330,4760],[12,25],[8,10],[10,-20]],[[5360,4775],[-10,-12],[-4,-16],[-1,-25],[-7,-7]],[[5571,7530],[-3,-20],[4,-25],[11,-15]],[[5583,7470],[0,-15],[-9,-9],[-2,-19],[-13,-29]],[[5559,7398],[-5,5],[0,13],[-15,19],[-3,29],[2,40],[4,18],[-4,10]],[[5538,7532],[-2,18],[12,29],[1,-11],[8,6]],[[5557,7574],[6,-16],[7,-6],[1,-22]],[[6432,6490],[5,3],[1,-16],[22,9],[23,-2],[17,-1],[19,39],[20,38],[18,37]],[[6557,6597],[5,-20]],[[6562,6577],[4,-47]],[[6566,6530],[-14,0],[-3,-39],[5,-8],[-12,-12],[0,-24],[-8,-24],[-1,-24]],[[6533,6399],[-6,-12],[-83,29],[-11,60],[-1,14]],[[3140,1814],[-17,2],[-30,0],[0,132]],[[3093,1948],[11,-27],[14,-45],[36,-35],[39,-15],[-13,-30],[-26,-2],[-14,20]],[[3258,3743],[51,-96],[23,-9],[34,-44],[29,-23],[4,-26],[-28,-90],[28,-16],[32,-9],[22,10],[25,45],[4,52]],[[3482,3537],[14,11],[14,-34],[-1,-47],[-23,-33],[-19,-24],[-31,-57],[-37,-81]],[[3399,3272],[-7,-47],[-7,-61],[0,-58],[-6,-14],[-2,-38]],[[3377,3054],[-2,-31],[35,-50],[-4,-41],[18,-26],[-2,-29],[-26,-75],[-42,-32],[-55,-12],[-31,6],[6,-36],[-6,-44],[5,-30],[-16,-20],[-29,-8],[-26,21],[-11,-15],[4,-59],[18,-18],[16,19],[8,-31],[-26,-18],[-22,-37],[-4,-59],[-7,-32],[-26,0],[-22,-31],[-8,-44],[28,-43],[26,-12],[-9,-53],[-33,-33],[-18,-70],[-25,-23],[-12,-28],[9,-61],[19,-34],[-12,3]],[[3095,1968],[-26,9],[-67,8],[-11,34],[0,45],[-18,-4],[-10,21],[-3,63],[22,26],[9,37],[-4,30],[15,51],[10,78],[-3,35],[12,11],[-3,22],[-13,12],[10,25],[-13,22],[-6,68],[11,12],[-5,72],[7,61],[7,52],[17,22],[-9,58],[0,54],[21,38],[-1,50],[16,57],[0,55],[-7,11],[-13,102],[17,60],[-2,58],[10,53],[18,56],[20,36],[-9,24],[6,19],[-1,98],[30,29],[10,62],[-3,14]],[[3136,3714],[23,54],[36,-15],[16,-42],[11,47],[32,-2],[4,-13]],[[6210,7485],[39,9]],[[6249,7494],[5,-15],[11,-10],[-6,-15],[15,-21],[-8,-18],[12,-16],[13,-10],[0,-41]],[[6291,7348],[-10,-2]],[[6281,7346],[-11,34],[0,10],[-12,-1],[-9,16],[-5,-1]],[[6244,7404],[-11,17],[-21,15],[3,28],[-5,21]],[[3345,329],[-8,-30],[-8,-27],[-59,8],[-62,-3],[-34,20],[0,2],[-16,17],[63,-2],[60,-6],[20,24],[15,21],[29,-24]],[[577,361],[-53,-8],[-36,21],[-17,21],[-1,3],[-18,16],[17,22],[52,-9],[28,-18],[21,-21],[7,-27]],[[3745,447],[35,-26],[12,-36],[3,-25],[1,-30],[-43,-19],[-45,-15],[-52,-14],[-59,-11],[-65,3],[-37,20],[5,24],[59,16],[24,20],[18,26],[12,22],[17,20],[18,25],[14,0],[41,12],[42,-12]],[[1633,715],[36,-9],[33,10],[-16,-20],[-26,-15],[-39,4],[-27,21],[6,20],[33,-11]],[[1512,716],[43,-23],[-17,3],[-36,5],[-38,17],[20,12],[28,-14]],[[2250,808],[31,-8],[30,7],[17,-34],[-22,5],[-34,-2],[-34,2],[-38,-4],[-28,12],[-15,24],[18,11],[35,-8],[40,-5]],[[3098,866],[4,-27],[-5,-23],[-8,-22],[-33,-8],[-31,-12],[-36,1],[14,24],[-33,-9],[-31,-8],[-21,18],[-2,24],[30,23],[20,7],[32,-2],[8,30],[1,22],[0,47],[16,28],[25,9],[15,-22],[6,-22],[12,-26],[10,-26],[7,-26]],[[3371,1268],[-11,-13],[-21,9],[-23,-6],[-19,-14],[-20,-15],[-14,-17],[-4,-23],[2,-22],[13,-20],[-19,-14],[-26,-4],[-15,-20],[-17,-19],[-17,-25],[-4,-22],[9,-24],[15,-19],[23,-14],[21,-18],[12,-23],[6,-22],[8,-24],[13,-19],[8,-22],[4,-55],[8,-22],[2,-23],[9,-23],[-4,-31],[-15,-24],[-17,-20],[-37,-8],[-12,-21],[-17,-20],[-42,-22],[-37,-9],[-35,-13],[-37,-13],[-22,-24],[-45,-2],[-49,2],[-44,-4],[-47,0],[9,-24],[42,-10],[31,-16],[18,-21],[-31,-19],[-48,6],[-40,-15],[-2,-24],[-1,-23],[33,-20],[6,-22],[35,-22],[59,-9],[50,-16],[40,-19],[50,-18],[70,-10],[68,-16],[47,-17],[52,-20],[27,-28],[13,-22],[34,21],[46,17],[48,19],[58,15],[49,16],[69,1],[68,-8],[56,-14],[18,26],[39,17],[70,1],[55,13],[52,13],[58,8],[62,10],[43,15],[-20,21],[-12,21],[0,22],[-54,-2],[-57,-10],[-54,0],[-8,22],[4,44],[12,13],[40,14],[47,14],[34,17],[33,18],[25,23],[38,10],[38,8],[19,5],[43,2],[41,8],[34,12],[34,14],[30,14],[39,18],[24,20],[26,17],[9,24],[-30,13],[10,25],[18,18],[29,12],[31,14],[28,18],[22,23],[13,28],[21,16],[33,-3],[13,-20],[34,-2],[1,22],[14,23],[30,-6],[7,-22],[33,-3],[36,10],[35,7],[31,-3],[12,-25],[31,20],[28,10],[31,9],[31,8],[29,14],[31,9],[24,13],[17,20],[20,-15],[29,8],[20,-27],[16,-21],[32,11],[12,24],[28,16],[37,-4],[11,-22],[22,22],[30,7],[33,3],[29,-2],[31,-7],[30,-3],[13,-20],[18,-17],[31,10],[32,3],[32,0],[31,1],[28,8],[29,7],[25,16],[26,11],[28,5],[21,17],[15,32],[16,20],[29,-10],[11,-21],[24,-13],[29,4],[19,-21],[21,-15],[28,14],[10,26],[25,10],[29,20],[27,8],[33,11],[22,13],[22,14],[22,13],[26,-7],[25,21],[18,16],[26,-1],[23,14],[6,21],[23,16],[23,11],[28,10],[25,4],[25,-3],[26,-6],[22,-16],[3,-26],[24,-19],[17,-17],[33,-7],[19,-16],[23,-16],[26,-3],[23,11],[24,24],[26,-12],[27,-7],[26,-7],[27,-5],[28,0],[23,-61],[-1,-15],[-4,-27],[-26,-15],[-22,-22],[4,-23],[31,1],[-4,-23],[-14,-22],[-13,-24],[21,-19],[32,-6],[32,11],[15,23],[10,22],[15,18],[17,18],[7,21],[15,29],[18,5],[31,3],[28,7],[28,9],[14,23],[8,22],[19,22],[27,15],[23,12],[16,19],[15,11],[21,9],[27,-6],[25,6],[28,7],[30,-4],[20,17],[14,39],[11,-16],[13,-28],[23,-12],[27,-4],[26,7],[29,-5],[26,-1],[17,6],[24,-4],[21,-12],[25,8],[30,0],[25,8],[29,-8],[19,19],[14,20],[19,16],[35,44],[18,-8],[21,-16],[18,-21],[36,-36],[27,-1],[25,0],[30,7],[30,8],[23,16],[19,18],[31,2],[21,13],[22,-12],[14,-18],[19,-19],[31,2],[19,-15],[33,-15],[35,-5],[29,4],[21,19],[19,18],[25,5],[25,-8],[29,-6],[26,9],[25,0],[24,-6],[26,-5],[25,10],[30,9],[28,3],[32,0],[25,5],[25,5],[8,29],[1,24],[17,-16],[5,-27],[10,-24],[11,-20],[23,-10],[32,4],[36,1],[25,3],[37,0],[26,1],[36,-2],[31,-5],[20,-18],[-5,-22],[18,-18],[30,-13],[31,-15],[35,-11],[38,-9],[28,-9],[32,-2],[18,20],[24,-16],[21,-19],[25,-13],[34,-6],[32,-7],[13,-23],[32,-14],[21,-21],[31,-9],[32,1],[30,-4],[33,1],[34,-4],[31,-8],[28,-14],[29,-12],[20,-17],[-3,-23],[-15,-21],[-13,-27],[-9,-21],[-14,-24],[-36,-9],[-16,-21],[-36,-13],[-13,-23],[-19,-22],[-20,-18],[-11,-25],[-7,-22],[-3,-26],[0,-22],[16,-23],[6,-22],[13,-21],[52,-8],[11,-26],[-50,-9],[-43,-13],[-52,-2],[-24,-34],[-5,-27],[-12,-22],[-14,-22],[37,-20],[14,-24],[24,-22],[33,-20],[39,-19],[42,-18],[64,-19],[14,-29],[80,-12],[5,-5],[21,-17],[77,15],[63,-19],[48,-14],[-9997,-1],[24,35],[50,-19],[3,2],[30,19],[4,0],[3,-1],[40,-25],[35,25],[7,3],[81,11],[27,-14],[13,-7],[41,-20],[79,-15],[63,-18],[107,-14],[80,16],[118,-11],[67,-19],[73,17],[78,17],[6,27],[-110,3],[-89,14],[-24,23],[-74,12],[5,27],[10,24],[10,22],[-5,25],[-46,16],[-22,21],[-43,18],[68,-3],[64,9],[40,-20],[50,18],[45,22],[23,19],[-10,25],[-36,16],[-41,17],[-57,4],[-50,8],[-54,6],[-18,22],[-36,18],[-21,21],[-9,67],[14,-6],[25,-18],[45,6],[44,8],[23,-26],[44,6],[37,13],[35,16],[32,20],[41,5],[-1,22],[-9,22],[8,21],[36,11],[16,-20],[42,12],[32,15],[40,1],[38,6],[37,13],[30,13],[34,13],[22,-4],[19,-4],[41,8],[37,-10],[38,1],[37,8],[37,-6],[41,-6],[39,3],[40,-2],[42,-1],[38,3],[28,17],[34,9],[35,-13],[33,11],[30,21],[18,-19],[9,-21],[18,-19],[29,17],[33,-22],[38,-7],[32,-16],[39,3],[36,11],[41,-3],[38,-8],[38,-10],[15,25],[-18,20],[-14,21],[-36,5],[-15,22],[-6,22],[-10,43],[21,-8],[36,-3],[36,3],[33,-9],[28,-17],[12,-21],[38,-4],[36,9],[38,11],[34,7],[28,-14],[37,5],[24,45],[23,-27],[32,-10],[34,6],[23,-23],[37,-3],[33,-7],[34,-12],[21,22],[11,20],[28,-23],[38,6],[28,-13],[19,-19],[37,5],[29,13],[29,15],[33,8],[39,7],[36,8],[27,13],[16,19],[7,25],[-3,24],[-9,24],[-10,23],[-9,23],[-7,21],[-1,23],[2,23],[13,22],[11,24],[5,23],[-6,26],[-3,23],[14,27],[15,17],[18,22],[19,19],[22,17],[11,25],[15,17],[18,15],[26,3],[18,19],[19,11],[23,7],[20,15],[16,19],[22,7],[16,-15],[-10,-20],[-29,-17]],[[6914,2185],[18,-19],[26,-7],[1,-11],[-7,-27],[-43,-4],[-1,31],[4,25],[2,12]],[[9038,2648],[27,-21],[15,8],[22,12],[16,-4],[2,-70],[-9,-21],[-3,-47],[-10,16],[-19,-41],[-6,3],[-17,2],[-17,50],[-4,39],[-16,52],[1,27],[18,-5]],[[8987,4244],[10,-46],[18,22],[9,-25],[13,-23],[-3,-26],[6,-51],[5,-29],[7,-7],[7,-51],[-3,-30],[9,-40],[31,-31],[19,-28],[19,-26],[-4,-14],[16,-37],[11,-64],[11,13],[11,-26],[7,9],[5,-63],[19,-36],[13,-22],[22,-48],[8,-48],[1,-33],[-2,-37],[13,-50],[-2,-52],[-5,-28],[-7,-52],[1,-34],[-6,-43],[-12,-53],[-21,-29],[-10,-46],[-9,-29],[-8,-51],[-11,-30],[-7,-44],[-4,-41],[2,-18],[-16,-21],[-31,-2],[-26,-24],[-13,-23],[-17,-26],[-23,27],[-17,10],[5,31],[-15,-11],[-25,-43],[-24,16],[-15,9],[-16,4],[-27,17],[-18,37],[-5,45],[-7,30],[-13,24],[-27,7],[9,28],[-7,44],[-13,-41],[-25,-11],[14,33],[5,34],[10,29],[-2,44],[-22,-50],[-18,-21],[-10,-47],[-22,25],[1,31],[-18,43],[-14,22],[5,14],[-36,35],[-19,2],[-27,29],[-50,-6],[-36,-21],[-31,-20],[-27,4],[-29,-30],[-24,-14],[-6,-31],[-10,-24],[-23,-1],[-18,-5],[-24,10],[-20,-6],[-19,-3],[-17,-31],[-8,2],[-14,-16],[-13,-19],[-21,2],[-18,0],[-30,38],[-15,11],[1,34],[14,8],[4,14],[-1,21],[4,41],[-3,35],[-15,60],[-4,33],[1,34],[-11,38],[-1,18],[-12,23],[-4,47],[-16,46],[-4,26],[13,-26],[-10,55],[14,-17],[8,-23],[0,30],[-14,47],[-3,18],[-6,18],[3,34],[6,15],[4,29],[-3,35],[11,42],[2,-45],[12,41],[22,20],[14,25],[21,22],[13,4],[7,-7],[22,22],[17,6],[4,13],[8,6],[15,-2],[29,18],[15,26],[7,31],[17,30],[1,24],[1,32],[19,50],[12,-51],[12,12],[-10,28],[9,29],[12,-13],[3,45],[15,29],[7,23],[14,10],[0,17],[13,-7],[0,15],[12,8],[14,8],[20,-27],[16,-35],[17,0],[18,-6],[-6,33],[13,47],[13,15],[-5,15],[12,34],[17,21],[14,-7],[24,11],[-1,30],[-20,19],[15,9],[18,-15],[15,-24],[23,-15],[8,6],[17,-18],[17,17],[10,-5],[7,11],[12,-29],[-7,-32],[-11,-24],[-9,-2],[3,-23],[-8,-30],[-10,-29],[2,-17],[22,-32],[21,-19],[15,-20],[20,-35],[8,0],[14,-15],[4,-19],[27,-20],[18,20],[6,32],[5,26],[4,33],[8,47],[-4,28],[2,17],[-3,34],[4,45],[5,12],[-4,20],[7,31],[5,32],[1,17],[10,22],[8,-29],[2,-37],[7,-7],[1,-25],[10,-30],[2,-33],[-1,-22]],[[5471,7900],[-2,-24],[-16,0],[6,-13],[-9,-38]],[[5450,7825],[-6,-10],[-24,-1],[-14,-13],[-23,4]],[[5383,7805],[-40,15],[-6,21],[-27,-10],[-4,-12],[-16,9]],[[5290,7828],[-15,1],[-12,11],[4,15],[-1,10]],[[5266,7865],[8,3],[14,-16],[4,16],[25,-3],[20,11],[13,-2],[9,-12],[2,10],[-4,38],[10,8],[10,27]],[[5377,7945],[21,-19],[15,24],[10,5],[22,-18],[13,3],[13,-12]],[[5471,7928],[-3,-7],[3,-21]],[[6281,7346],[-19,8],[-14,27],[-4,23]],[[6349,7527],[15,-31],[14,-42],[13,-2],[8,-16],[-23,-5],[-5,-46],[-4,-21],[-11,-13],[1,-30]],[[6357,7321],[-7,-3],[-17,31],[10,30],[-9,17],[-10,-4],[-33,-44]],[[6249,7494],[6,10],[21,-17],[15,-4],[4,7],[-14,32],[7,9]],[[6288,7531],[8,-2],[19,-36],[13,-4],[4,15],[17,23]],[[5814,4792],[-1,71],[-7,27]],[[5806,4890],[17,-5],[8,34],[15,-4]],[[5846,4915],[1,-23],[6,-14],[1,-19],[-7,-12],[-11,-31],[-10,-22],[-12,-2]],[[5092,8091],[20,-5],[26,12],[17,-25],[16,-14]],[[5171,8059],[-4,-40]],[[5167,8019],[-7,-2],[-3,-33]],[[5157,7984],[-24,26],[-14,-4],[-20,28],[-13,23],[-13,1],[-4,21]],[[5069,8079],[23,12]],[[5074,5427],[-23,-7]],[[5051,5420],[-7,41],[2,136],[-6,12],[-1,29],[-10,21],[-8,17],[3,31]],[[5024,5707],[10,7],[6,26],[13,5],[6,18]],[[5059,5763],[10,17],[10,0],[21,-34]],[[5100,5746],[-1,-19],[6,-35],[-6,-24],[3,-16],[-13,-37],[-9,-18],[-5,-37],[1,-38],[-2,-95]],[[4921,5627],[-19,15],[-13,-2],[-10,-15],[-12,13],[-5,19],[-13,13]],[[4849,5670],[-1,34],[7,26],[-1,20],[23,48],[4,41],[7,14],[14,-8],[11,12],[4,16],[22,26],[5,19],[26,24],[15,9],[7,-12],[18,0]],[[5010,5939],[-2,-28],[3,-27],[16,-39],[1,-28],[32,-14],[-1,-40]],[[5024,5707],[-24,1]],[[5e3,5708],[-13,5],[-9,-9],[-12,4],[-48,-3],[-1,-33],[4,-45]],[[7573,6360],[0,-43],[-10,9],[2,-47]],[[7565,6279],[-8,30],[-1,31],[-6,28],[-11,34],[-26,3],[3,-25],[-9,-32],[-12,12],[-4,-11],[-8,6],[-11,5]],[[7472,6360],[-4,49],[-10,45],[5,35],[-17,16],[6,22],[18,22],[-20,31],[9,40],[22,-26],[14,-3],[2,-41],[26,-8],[26,1],[16,-10],[-13,-50],[-12,-3],[-9,-34],[16,-31],[4,38],[8,0],[14,-93]],[[5629,7671],[8,-25],[11,5],[21,-9],[41,-4],[13,16],[33,13],[20,-21],[17,-6]],[[5793,7640],[-15,-25],[-10,-42],[9,-34]],[[5777,7539],[-24,8],[-28,-18]],[[5725,7529],[0,-30],[-26,-5],[-19,20],[-22,-16],[-21,2]],[[5637,7500],[-2,39],[-14,19]],[[5621,7558],[5,8],[-3,7],[4,19],[11,18],[-14,26],[-2,21],[7,14]],[[2846,6461],[-7,-3],[-7,34],[-10,17],[6,38],[8,-3],[10,-49],[0,-34]],[[2838,6628],[-30,-10],[-2,22],[13,5],[18,-2],[1,-15]],[[2861,6628],[-5,-42],[-5,8],[0,31],[-12,23],[0,7],[22,-27]],[[5527,7708],[10,0],[-7,-26],[14,-23],[-4,-28],[-7,-2]],[[5533,7629],[-5,-6],[-9,-13],[-4,-33]],[[5515,7577],[-25,23],[-10,24],[-11,13],[-12,22],[-6,19],[-14,27],[6,25],[10,-14],[6,12],[13,2],[24,-10],[19,1],[12,-13]],[[5652,8242],[27,0],[30,22],[6,34],[23,19],[-3,26]],[[5735,8343],[17,10],[30,23]],[[5782,8376],[29,-15],[4,-15],[15,7],[27,-14],[3,-27],[-6,-16],[17,-39],[12,-11],[-2,-11],[19,-10],[8,-16],[-11,-13],[-23,2],[-5,-5],[7,-20],[6,-37]],[[5882,8136],[-23,-4],[-9,-13],[-2,-30],[-11,6],[-25,-3],[-7,14],[-11,-10],[-10,8],[-22,1],[-31,15],[-28,4],[-22,-1],[-15,-16],[-13,-2]],[[5653,8105],[-1,26],[-8,27],[17,12],[0,24],[-8,22],[-1,26]],[[2524,6110],[-1,8],[4,3],[5,-7],[10,36],[5,0]],[[2547,6150],[0,-8],[5,-1],[0,-16],[-5,-25],[3,-9],[-3,-21],[2,-6],[-4,-30],[-5,-16],[-5,-1],[-6,-21]],[[2529,5996],[-8,0],[2,67],[1,47]],[[3136,3714],[-20,-8],[-11,82],[-15,66],[9,57],[-15,25],[-4,43],[-13,40]],[[3067,4019],[17,64],[-12,49],[7,20],[-5,22],[10,30],[1,50],[1,41],[6,20],[-24,96]],[[3068,4411],[21,-5],[14,1],[6,18],[25,24],[14,22],[37,10],[-3,-44],[3,-23],[-2,-40],[30,-53],[31,-9],[11,-23],[19,-11],[11,-17],[18,0],[16,-17],[1,-34],[6,-18],[0,-25],[-8,-1],[11,-69],[53,-2],[-4,-35],[3,-23],[15,-16],[6,-37],[-4,-47],[-8,-26],[3,-33],[-9,-12]],[[3384,3866],[-1,18],[-25,30],[-26,1],[-49,-17],[-13,-52],[-1,-32],[-11,-71]],[[3482,3537],[6,34],[3,35],[1,32],[-10,11],[-11,-9],[-10,2],[-4,23],[-2,54],[-5,18],[-19,16],[-11,-12],[-30,11],[2,81],[-8,33]],[[3068,4411],[-15,-11],[-13,7],[2,90],[-23,-35],[-24,2],[-11,31],[-18,4],[5,25],[-15,36],[-11,53],[7,11],[0,25],[17,17],[-3,32],[7,20],[2,28],[32,40],[22,11],[4,9],[25,-2]],[[3058,4804],[13,162],[0,25],[-4,34],[-12,22],[0,42],[15,10],[6,-6],[1,23],[-16,6],[-1,37],[54,-2],[10,21],[7,-19],[6,-35],[5,8]],[[3142,5132],[15,-32],[22,4],[5,18],[21,14],[11,10],[4,25],[19,17],[-1,12],[-24,5],[-3,37],[1,40],[-13,15],[5,6],[21,-8],[22,-15],[8,14],[20,9],[31,23],[10,22],[-3,17]],[[3313,5365],[14,2],[7,-13],[-4,-26],[9,-9],[7,-28],[-8,-20],[-4,-51],[7,-30],[2,-27],[17,-28],[14,-3],[3,12],[8,3],[13,10],[9,16],[15,-5],[7,2]],[[3429,5170],[15,-5],[3,12],[-5,12],[3,17],[11,-5],[13,6],[16,-13]],[[3485,5194],[12,-12],[9,16],[6,-3],[4,-16],[13,4],[11,22],[8,44],[17,54]],[[3565,5303],[9,3],[7,-33],[16,-103],[14,-10],[1,-41],[-21,-48],[9,-18],[49,-9],[1,-60],[21,39],[35,-21],[46,-36],[14,-35],[-5,-32],[33,18],[54,-32],[41,3],[41,-49],[36,-66],[21,-17],[24,-3],[10,-18],[9,-76],[5,-35],[-11,-98],[-14,-39],[-39,-82],[-18,-67],[-21,-51],[-7,-1],[-7,-43],[2,-111],[-8,-91],[-3,-39],[-9,-23],[-5,-79],[-28,-77],[-5,-61],[-22,-26],[-7,-35],[-30,0],[-44,-23],[-19,-26],[-31,-18],[-33,-47],[-23,-58],[-5,-44],[5,-33],[-5,-60],[-6,-28],[-20,-33],[-31,-104],[-24,-47],[-19,-27],[-13,-57],[-18,-33]],[[3517,3063],[-8,33],[13,28],[-16,40],[-22,33],[-29,38],[-10,-2],[-28,46],[-18,-7]],[[8172,5325],[11,22],[23,32]],[[8206,5379],[-1,-29],[-2,-37],[-13,1],[-6,-20],[-12,31]],[[7546,6698],[12,-19],[-2,-36],[-23,-2],[-23,4],[-18,-9],[-25,22],[-1,12]],[[7466,6670],[19,44],[15,15],[20,-14],[14,-1],[12,-16]],[[5817,3752],[-39,-43],[-25,-44],[-10,-40],[-8,-22],[-15,-4],[-5,-29],[-3,-18],[-17,-14],[-23,3],[-13,17],[-12,7],[-14,-14],[-6,-28],[-14,-18],[-13,-26],[-20,-6],[-6,20],[2,36],[-16,56],[-8,9]],[[5552,3594],[0,173],[27,2],[1,210],[21,2],[43,21],[10,-24],[18,23],[9,0],[15,13]],[[5696,4014],[5,-4]],[[5701,4010],[11,-48],[5,-10],[9,-34],[32,-65],[12,-7],[0,-20],[8,-38],[21,-9],[18,-27]],[[5424,5496],[23,4],[5,16],[5,-2],[7,-13],[34,23],[12,23],[15,20],[-3,21],[8,6],[27,-4],[26,27],[20,65],[14,24],[18,10]],[[5635,5716],[3,-26],[16,-36],[0,-25],[-5,-24],[2,-18],[10,-18]],[[5661,5569],[21,-25]],[[5682,5544],[15,-24],[0,-19],[19,-31],[12,-26],[7,-35],[20,-24],[5,-18]],[[5760,5367],[-9,-7],[-18,2],[-21,6],[-10,-5],[-5,-14],[-9,-2],[-10,12],[-31,-29],[-13,6],[-4,-5],[-8,-35],[-21,11],[-20,6],[-18,22],[-23,20],[-15,-19],[-10,-30],[-3,-41]],[[5512,5265],[-18,3],[-19,10],[-16,-32],[-15,-55]],[[5444,5191],[-3,18],[-1,27],[-13,19],[-10,30],[-2,21],[-13,31],[2,18],[-3,25],[2,45],[7,11],[14,60]],[[3231,7808],[20,-8],[26,1],[-14,-24],[-10,-4],[-35,25],[-7,20],[10,18],[10,-28]],[[3283,7958],[-14,-1],[-36,19],[-26,28],[10,5],[37,-15],[28,-25],[1,-11]],[[1569,7923],[-14,-8],[-46,27],[-8,21],[-25,21],[-5,16],[-28,11],[-11,32],[2,14],[30,-13],[17,-9],[26,-6],[9,-21],[14,-28],[28,-24],[11,-33]],[[3440,8052],[-18,-52],[18,20],[19,-12],[-10,-21],[25,-16],[12,14],[28,-18],[-8,-43],[19,10],[4,-32],[8,-36],[-11,-52],[-13,-2],[-18,11],[6,48],[-8,8],[-32,-52],[-17,2],[20,28],[-27,14],[-30,-3],[-54,2],[-4,17],[17,21],[-12,16],[24,36],[28,94],[18,33],[24,21],[13,-3],[-6,-16],[-15,-37]],[[1313,8250],[27,5],[-8,-67],[24,-48],[-11,0],[-17,27],[-10,27],[-14,19],[-5,26],[1,19],[13,-8]],[[2798,8730],[-11,-31],[-12,5],[-8,17],[2,4],[10,18],[12,-1],[7,-12]],[[2725,8762],[-33,-32],[-19,1],[-6,16],[20,27],[38,0],[0,-12]],[[2634,8936],[5,-26],[15,9],[16,-15],[30,-20],[32,-19],[2,-28],[21,5],[20,-20],[-25,-18],[-43,14],[-16,26],[-27,-31],[-40,-31],[-9,35],[-38,-6],[24,30],[4,46],[9,54],[20,-5]],[[2892,9024],[-31,-3],[-7,29],[12,34],[26,8],[21,-17],[1,-25],[-4,-8],[-18,-18]],[[2343,9140],[-17,-21],[-38,18],[-22,-6],[-38,26],[24,19],[19,25],[30,-16],[17,-11],[8,-11],[17,-23]],[[3135,7724],[-18,33],[0,81],[-13,17],[-18,-10],[-10,16],[-21,-45],[-8,-46],[-10,-27],[-12,-9],[-9,-3],[-3,-15],[-51,0],[-42,0],[-12,-11],[-30,-42],[-3,-5],[-9,-23],[-26,0],[-27,0],[-12,-10],[4,-11],[2,-18],[0,-6],[-36,-30],[-29,-9],[-32,-31],[-7,0],[-10,9],[-3,8],[1,6],[6,21],[13,33],[8,35],[-5,51],[-6,53],[-29,28],[3,11],[-4,7],[-8,0],[-5,9],[-2,14],[-5,-6],[-7,2],[1,6],[-6,6],[-3,15],[-21,19],[-23,20],[-27,23],[-26,21],[-25,-17],[-9,0],[-34,15],[-23,-8],[-27,19],[-28,9],[-19,4],[-9,10],[-5,32],[-9,0],[-1,-23],[-57,0],[-95,0],[-94,0],[-84,0],[-83,0],[-82,0],[-85,0],[-27,0],[-82,0],[-79,0]],[[1588,7952],[-4,0],[-54,58],[-20,26],[-50,24],[-15,53],[3,36],[-35,25],[-5,48],[-34,43],[0,30]],[[1374,8295],[15,29],[0,37],[-48,37],[-28,68],[-17,42],[-26,27],[-19,24],[-14,31],[-28,-20],[-27,-33],[-25,39],[-19,26],[-27,16],[-28,2],[0,337],[1,219]],[[1084,9176],[51,-14],[44,-29],[29,-5],[24,24],[34,19],[41,-7],[42,26],[45,14],[20,-24],[20,14],[6,27],[20,-6],[47,-53],[37,40],[3,-45],[34,10],[11,17],[34,-3],[42,-25],[65,-22],[38,-10],[28,4],[37,-30],[-39,-29],[50,-13],[75,7],[24,11],[29,-36],[31,30],[-29,25],[18,20],[34,3],[22,6],[23,-14],[28,-32],[31,5],[49,-27],[43,9],[40,-1],[-3,37],[25,10],[43,-20],[0,-56],[17,47],[23,-1],[12,59],[-30,36],[-32,24],[2,65],[33,43],[37,-9],[28,-26],[38,-67],[-25,-29],[52,-12],[-1,-60],[38,46],[33,-38],[-9,-44],[27,-40],[29,43],[21,51],[1,65],[40,-5],[41,-8],[37,-30],[2,-29],[-21,-31],[20,-32],[-4,-29],[-54,-41],[-39,-9],[-29,18],[-8,-30],[-27,-50],[-8,-26],[-32,-40],[-40,-4],[-22,-25],[-2,-38],[-32,-7],[-34,-48],[-30,-67],[-11,-46],[-1,-69],[40,-10],[13,-55],[13,-45],[39,12],[51,-26],[28,-22],[20,-28],[35,-17],[29,-24],[46,-4],[30,-6],[-4,-51],[8,-59],[21,-66],[41,-56],[21,19],[15,61],[-14,93],[-20,31],[45,28],[31,41],[16,41],[-3,40],[-19,50],[-33,44],[32,62],[-12,54],[-9,92],[19,14],[48,-16],[29,-6],[23,15],[25,-20],[35,-34],[8,-23],[50,-4],[-1,-50],[9,-74],[25,-10],[21,-35],[40,33],[26,65],[19,28],[21,-53],[36,-75],[31,-71],[-11,-37],[37,-33],[25,-34],[44,-15],[18,-19],[11,-50],[22,-8],[11,-22],[2,-67],[-20,-22],[-20,-21],[-46,-21],[-35,-48],[-47,-10],[-59,13],[-42,0],[-29,-4],[-23,-43],[-35,-26],[-40,-78],[-32,-54],[23,9],[45,78],[58,49],[42,6],[24,-29],[-26,-40],[9,-63],[9,-45],[36,-29],[46,8],[28,67],[2,-43],[17,-22],[-34,-38],[-61,-36],[-28,-23],[-31,-43],[-21,4],[-1,50],[48,49],[-44,-2],[-31,-7]],[[1829,9377],[-14,-27],[61,17],[39,-29],[31,30],[26,-20],[23,-58],[14,25],[-20,60],[24,9],[28,-9],[31,-24],[17,-58],[9,-41],[47,-30],[50,-28],[-3,-26],[-46,-4],[18,-23],[-9,-22],[-51,9],[-48,16],[-32,-3],[-52,-20],[-70,-9],[-50,-6],[-15,28],[-38,16],[-24,-6],[-35,47],[19,6],[43,10],[39,-3],[36,11],[-54,13],[-59,-4],[-39,1],[-15,22],[64,23],[-42,-1],[-49,16],[23,44],[20,24],[74,36],[29,-12]],[[2097,9395],[-24,-39],[-44,41],[10,9],[37,2],[21,-13]],[[2879,9376],[3,-16],[-30,2],[-30,1],[-30,-8],[-8,3],[-31,32],[1,21],[14,4],[63,-6],[48,-33]],[[2595,9379],[22,-36],[26,47],[70,24],[48,-61],[-4,-38],[55,17],[26,23],[62,-30],[38,-28],[3,-25],[52,13],[29,-38],[67,-23],[24,-24],[26,-55],[-51,-28],[66,-38],[44,-13],[40,-55],[44,-3],[-9,-42],[-49,-69],[-34,26],[-44,57],[-36,-8],[-3,-34],[29,-34],[38,-27],[11,-16],[18,-58],[-9,-43],[-35,16],[-70,47],[39,-51],[29,-35],[5,-21],[-76,24],[-59,34],[-34,29],[10,17],[-42,30],[-40,29],[0,-18],[-80,-9],[-23,20],[18,44],[52,1],[57,7],[-9,21],[10,30],[36,57],[-8,27],[-11,20],[-42,29],[-57,20],[18,15],[-29,36],[-25,4],[-22,20],[-14,-18],[-51,-7],[-101,13],[-59,17],[-45,9],[-23,21],[29,27],[-39,0],[-9,60],[21,53],[29,24],[72,16],[-21,-39]],[[2212,9420],[33,-12],[50,7],[7,-17],[-26,-28],[42,-26],[-5,-53],[-45,-23],[-27,5],[-19,23],[-69,45],[0,19],[57,-7],[-31,38],[33,29]],[[2411,9357],[-30,-45],[-32,3],[-17,52],[1,29],[14,25],[28,16],[58,-2],[53,-14],[-42,-53],[-33,-11]],[[1654,9275],[-73,-29],[-15,26],[-64,31],[12,25],[19,43],[24,39],[-27,36],[94,10],[39,-13],[71,-3],[27,-17],[30,-25],[-35,-15],[-68,-41],[-34,-42],[0,-25]],[[2399,9487],[-15,-23],[-40,5],[-34,15],[15,27],[40,16],[24,-21],[10,-19]],[[2264,9590],[21,-27],[1,-31],[-13,-44],[-46,-6],[-30,10],[1,34],[-45,-4],[-2,45],[30,-2],[41,21],[40,-4],[2,8]],[[1994,9559],[11,-21],[25,10],[29,-2],[5,-29],[-17,-28],[-94,-10],[-70,-25],[-43,-2],[-3,20],[57,26],[-125,-7],[-39,10],[38,58],[26,17],[78,-20],[50,-35],[48,-5],[-40,57],[26,21],[29,-7],[9,-28]],[[2370,9612],[30,-19],[55,0],[24,-19],[-6,-22],[32,-14],[17,-14],[38,-2],[40,-5],[44,13],[57,5],[45,-5],[30,-22],[6,-24],[-17,-16],[-42,-13],[-35,8],[-80,-10],[-57,-1],[-45,8],[-74,19],[-9,32],[-4,29],[-27,26],[-58,7],[-32,19],[10,24],[58,-4]],[[1772,9645],[-4,-46],[-21,-20],[-26,-3],[-52,-26],[-44,-9],[-38,13],[47,44],[57,39],[43,-1],[38,9]],[[2393,9637],[-13,-2],[-52,4],[-7,17],[56,-1],[19,-11],[-3,-7]],[[1939,9648],[-52,-17],[-41,19],[23,19],[40,6],[39,-10],[-9,-17]],[[1954,9701],[-34,-11],[-46,0],[0,8],[29,18],[14,-3],[37,-12]],[[2338,9669],[-41,-12],[-23,13],[-12,23],[-2,24],[36,-2],[16,-4],[33,-21],[-7,-21]],[[2220,9685],[11,-25],[-45,7],[-46,19],[-62,2],[27,18],[-34,14],[-2,22],[55,-8],[75,-21],[21,-28]],[[2583,9764],[33,-20],[-38,-17],[-51,-45],[-50,-4],[-57,8],[-30,24],[0,21],[22,16],[-50,0],[-31,19],[-18,27],[20,26],[19,18],[28,4],[-12,14],[65,3],[35,-32],[47,-12],[46,-11],[22,-39]],[[3097,9967],[74,-4],[60,-8],[51,-16],[-2,-16],[-67,-25],[-68,-12],[-25,-14],[61,1],[-66,-36],[-45,-17],[-48,-48],[-57,-10],[-18,-12],[-84,-6],[39,-8],[-20,-10],[23,-29],[-26,-21],[-43,-16],[-13,-24],[-39,-17],[4,-14],[48,3],[0,-15],[-74,-35],[-73,16],[-81,-9],[-42,7],[-52,3],[-4,29],[52,13],[-14,43],[17,4],[74,-26],[-38,38],[-45,11],[23,23],[49,14],[8,21],[-39,23],[-12,31],[76,-3],[22,-6],[43,21],[-62,7],[-98,-4],[-49,20],[-23,24],[-32,17],[-6,21],[41,11],[32,2],[55,9],[41,22],[34,-3],[30,-16],[21,32],[37,9],[50,7],[85,2],[14,-6],[81,10],[60,-4],[60,-4]],[[5290,7828],[-3,-24],[-12,-10],[-20,7],[-6,-24],[-14,-2],[-5,10],[-15,-20],[-13,-3],[-12,13]],[[5190,7775],[-10,25],[-13,-9],[0,27],[21,33],[-1,15],[12,-5],[8,10]],[[5207,7871],[24,-1],[5,13],[30,-18]],[[3140,1814],[-10,-24],[-23,-18],[-14,2],[-16,5],[-21,18],[-29,8],[-35,33],[-28,32],[-38,66],[23,-12],[39,-40],[36,-21],[15,27],[9,41],[25,24],[20,-7]],[[3095,1968],[-25,0],[-13,-14],[-25,-22],[-5,-55],[-11,-1],[-32,19],[-32,41],[-34,34],[-9,37],[8,35],[-14,39],[-4,101],[12,57],[30,45],[-43,18],[27,52],[9,98],[31,-21],[15,123],[-19,15],[-9,-73],[-17,8],[9,84],[9,110],[13,40],[-8,58],[-2,66],[11,2],[17,96],[20,94],[11,88],[-6,89],[8,49],[-3,72],[16,73],[5,114],[9,123],[9,132],[-2,96],[-6,84]],[[3045,3974],[14,15],[8,30]],[[8064,6161],[-24,-28],[-23,18],[0,51],[13,26],[31,17],[16,-1],[6,-23],[-12,-26],[-7,-34]],[[8628,7562],[-18,35],[-11,-33],[-43,-26],[4,-31],[-24,2],[-13,19],[-19,-42],[-30,-32],[-23,-38]],[[8451,7416],[-39,-17],[-20,-27],[-30,-17],[15,28],[-6,23],[22,40],[-15,30],[-24,-20],[-32,-41],[-17,-39],[-27,-2],[-14,-28],[15,-40],[22,-10],[1,-26],[22,-17],[31,42],[25,-23],[18,-2],[4,-31],[-39,-16],[-13,-32],[-27,-30],[-14,-41],[30,-33],[11,-58],[17,-54],[18,-45],[0,-44],[-17,-16],[6,-32],[17,-18],[-5,-48],[-7,-47],[-15,-5],[-21,-64],[-22,-78],[-26,-70],[-38,-55],[-39,-50],[-31,-6],[-17,-27],[-10,20],[-15,-30],[-39,-29],[-29,-9],[-10,-63],[-15,-3],[-8,43],[7,22],[-37,19],[-13,-9]],[[8001,6331],[-28,15],[-14,24],[5,34],[-26,11],[-13,22],[-24,-31],[-27,-7],[-22,0],[-15,-14]],[[7837,6385],[-14,-9],[4,-68],[-15,2],[-2,14]],[[7810,6324],[-1,24],[-20,-17],[-12,11],[-21,22],[8,49],[-18,12],[-6,54],[-30,-10],[4,70],[26,50],[1,48],[-1,46],[-12,14],[-9,35],[-16,-5]],[[7703,6727],[-30,9],[9,25],[-13,36],[-20,-24],[-23,14],[-32,-37],[-25,-44],[-23,-8]],[[7466,6670],[-2,47],[-17,-13]],[[7447,6704],[-32,6],[-32,14],[-22,26],[-22,11],[-9,29],[-16,8],[-28,39],[-22,18],[-12,-14]],[[7252,6841],[-38,41],[-28,37],[-7,65],[20,-7],[1,30],[-12,30],[3,48],[-30,69]],[[7161,7154],[-45,24],[-8,46],[-21,27]],[[7082,7268],[-4,34],[1,23],[-17,13],[-9,-6],[-7,55]],[[7046,7387],[8,13],[-4,14],[26,28],[20,12],[29,-8],[11,38],[35,7],[10,23],[44,32],[4,13]],[[7229,7559],[-2,34],[19,15],[-25,103],[55,24],[14,13],[20,106],[55,-20],[15,27],[2,59],[23,6],[21,39]],[[7426,7965],[11,5]],[[7437,7970],[7,-41],[23,-32],[40,-22],[19,-47],[-10,-70],[10,-25],[33,-10],[37,-8],[33,-37],[18,-7],[12,-54],[17,-35],[30,1],[58,-13],[36,8],[28,-9],[41,-36],[34,0],[12,-18],[32,32],[45,20],[42,2],[32,21],[20,32],[20,20],[-5,19],[-9,23],[15,38],[15,-5],[29,-12],[28,31],[42,23],[20,39],[20,17],[40,8],[22,-7],[3,21],[-25,41],[-22,19],[-22,-22],[-27,10],[-16,-8],[-7,24],[20,59],[13,45]],[[8240,8005],[34,-23],[39,38],[-1,26],[26,62],[15,19],[0,33],[-16,14],[23,29],[35,11],[37,2],[41,-18],[25,-22],[17,-59],[10,-26],[10,-36],[10,-58],[49,-19],[32,-42],[12,-55],[42,0],[24,23],[46,17],[-15,-53],[-11,-21],[-9,-65],[-19,-58],[-33,11],[-24,-21],[7,-51],[-4,-69],[-14,-2],[0,-30]],[[4920,5353],[-12,-1],[-20,12],[-18,-1],[-33,-10],[-19,-18],[-27,-21],[-6,1]],[[4785,5315],[2,49],[3,7],[-1,24],[-12,24],[-8,4],[-8,17],[6,26],[-3,28],[1,18]],[[4765,5512],[5,0],[1,25],[-2,12],[3,8],[10,7],[-7,47],[-6,25],[2,20],[5,4]],[[4776,5660],[4,6],[8,-9],[21,-1],[5,18],[5,-1],[8,6],[4,-25],[7,7],[11,9]],[[4921,5627],[7,-84],[-11,-50],[-8,-66],[12,-51],[-1,-23]],[[5363,5191],[-4,4],[-16,-8],[-17,8],[-13,-4]],[[5313,5191],[-45,1]],[[5268,5192],[4,47],[-11,39],[-13,10],[-6,27],[-7,8],[1,16]],[[5236,5339],[7,42],[13,57],[8,1],[17,34],[10,1],[16,-24],[19,20],[2,25],[7,23],[4,30],[15,25],[5,41],[6,13],[4,31],[7,37],[24,46],[1,20],[3,10],[-11,24]],[[5393,5795],[1,19],[8,3]],[[5402,5817],[11,-38],[2,-39],[-1,-39],[15,-54],[-15,1],[-8,-4],[-13,6],[-6,-28],[16,-35],[13,-10],[3,-24],[9,-41],[-4,-16]],[[5444,5191],[-2,-31],[-22,14],[-22,15],[-35,2]],[[5856,5265],[-2,-69],[11,-8],[-9,-21],[-10,-16],[-11,-31],[-6,-27],[-1,-48],[-7,-22],[0,-45]],[[5821,4978],[-8,-16],[-1,-35],[-4,-5],[-2,-32]],[[5814,4792],[5,-55],[-2,-30],[5,-35],[16,-33],[15,-74]],[[5853,4565],[-11,6],[-37,-10],[-7,-7],[-8,-38],[6,-26],[-5,-70],[-3,-59],[7,-11],[19,-23],[8,11],[2,-64],[-21,1],[-11,32],[-10,25],[-22,9],[-6,31],[-17,-19],[-22,8],[-10,27],[-17,6],[-13,-2],[-2,19],[-9,1]],[[5342,4697],[-4,18]],[[5360,4775],[8,-6],[9,23],[15,-1],[2,-17],[11,-10],[16,37],[16,29],[7,19],[-1,48],[12,58],[13,30],[18,29],[3,18],[1,22],[5,21],[-2,33],[4,52],[5,37],[8,32],[2,36]],[[5760,5367],[17,-49],[12,-7],[8,10],[12,-4],[16,12],[6,-25],[25,-39]],[[5330,4760],[-22,62]],[[5308,4822],[21,33],[-11,39],[10,15],[19,7],[2,26],[15,-28],[24,-2],[9,27],[3,40],[-3,46],[-13,35],[12,68],[-7,12],[-21,-5],[-7,31],[2,25]],[[2906,5049],[-12,14],[-14,19],[-7,-9],[-24,8],[-7,25],[-5,-1],[-28,34]],[[2809,5139],[-3,18],[10,5],[-1,29],[6,22],[14,4],[12,37],[10,31],[-10,14],[5,34],[-6,54],[6,16],[-4,50],[-12,31]],[[2836,5484],[4,29],[9,-4],[5,17],[-6,35],[3,9]],[[2851,5570],[14,-2],[21,41],[12,6],[0,20],[5,50],[16,27],[17,1],[3,13],[21,-5],[22,30],[11,13],[14,28],[9,-3],[8,-16],[-6,-20]],[[3018,5753],[-18,-10],[-7,-29],[-10,-17],[-8,-22],[-4,-42],[-8,-35],[15,-4],[3,-27],[6,-13],[3,-24],[-4,-22],[1,-12],[7,-5],[7,-20],[36,5],[16,-7],[19,-51],[11,6],[20,-3],[16,7],[10,-10],[-5,-32],[-6,-20],[-2,-42],[5,-40],[8,-17],[1,-13],[-14,-30],[10,-13],[8,-21],[8,-58]],[[3058,4804],[-14,31],[-8,1],[18,61],[-21,27],[-17,-5],[-10,10],[-15,-15],[-21,7],[-16,62],[-13,15],[-9,28],[-19,28],[-7,-5]],[[2695,5543],[-15,14],[-6,12],[4,10],[-1,13],[-8,14],[-11,12],[-10,8],[-1,17],[-8,10],[2,-17],[-5,-14],[-7,17],[-9,5],[-4,12],[1,18],[3,19],[-8,8],[7,12]],[[2619,5713],[4,7],[18,-15],[7,7],[9,-5],[4,-12],[8,-4],[7,13]],[[2676,5704],[7,-32],[11,-24],[13,-25]],[[2707,5623],[-11,-6],[0,-23],[6,-9],[-4,-7],[1,-11],[-2,-12],[-2,-12]],[[2715,6427],[23,-4],[22,0],[26,-21],[11,-21],[26,6],[10,-13],[24,-37],[17,-27],[9,1],[17,-12],[-2,-17],[20,-2],[21,-24],[-3,-14],[-19,-7],[-18,-3],[-19,4],[-40,-5],[18,32],[-11,16],[-18,4],[-9,17],[-7,33],[-16,-2],[-26,16],[-8,12],[-36,10],[-10,11],[11,15],[-28,3],[-20,-31],[-11,-1],[-4,-14],[-14,-7],[-12,6],[15,18],[6,22],[13,13],[14,11],[21,6],[7,6]],[[5909,7133],[2,1],[4,14],[20,-1],[25,18],[-19,-25],[2,-11]],[[5943,7129],[-3,2],[-5,-5],[-4,1],[-2,-2],[0,6],[-2,4],[-6,0],[-7,-5],[-5,3]],[[5943,7129],[1,-5],[-28,-24],[-14,8],[-7,23],[14,2]],[[5377,7945],[-16,25],[-14,15],[-3,25],[-5,17],[21,13],[10,15],[20,11],[7,11],[7,-6],[13,6]],[[5417,8077],[13,-19],[21,-5],[-2,-17],[15,-12],[4,15],[19,-6],[3,-19],[20,-3],[13,-29]],[[5523,7982],[-8,0],[-4,-11],[-7,-3],[-2,-13],[-5,-3],[-1,-5],[-9,-7],[-12,1],[-4,-13]],[[5275,8306],[1,-23],[28,-14],[-1,-21],[29,11],[15,16],[32,-23],[13,-19]],[[5392,8233],[6,-30],[-8,-16],[11,-21],[6,-31],[-2,-21],[12,-37]],[[5207,7871],[3,42],[14,40],[-40,11],[-13,16]],[[5171,7980],[2,26],[-6,13]],[[5171,8059],[-5,62],[17,0],[7,22],[6,54],[-5,20]],[[5191,8217],[6,13],[23,3],[5,-13],[19,29],[-6,22],[-2,34]],[[5236,8305],[21,-8],[18,9]],[[6196,5808],[7,-19],[-1,-24],[-16,-14],[12,-16]],[[6198,5735],[-10,-32]],[[6188,5703],[-7,11],[-6,-5],[-16,1],[0,18],[-2,17],[9,27],[10,26]],[[6176,5798],[12,-5],[8,15]],[[5352,8343],[-17,-48],[-29,33],[-4,25],[41,19],[9,-29]],[[5236,8305],[-11,32],[-1,61],[5,16],[8,17],[24,4],[10,16],[22,17],[-1,-30],[-8,-20],[4,-16],[15,-9],[-7,-22],[-8,6],[-20,-42],[7,-29]],[[3008,6222],[3,10],[22,0],[16,-15],[8,1],[5,-21],[15,1],[-1,-17],[12,-2],[14,-22],[-10,-24],[-14,13],[-12,-3],[-9,3],[-5,-11],[-11,-3],[-4,14],[-10,-8],[-11,-41],[-7,10],[-1,17]],[[3008,6124],[0,16],[-7,17],[7,10],[2,23],[-2,32]],[[5333,6444],[-95,-112],[-81,-117],[-39,-26]],[[5118,6189],[-31,-6],[0,38],[-13,10],[-17,16],[-7,28],[-94,129],[-93,129]],[[4863,6533],[-105,143]],[[4758,6676],[1,11],[0,4]],[[4759,6691],[0,70],[44,44],[28,9],[23,16],[11,29],[32,24],[1,44],[16,5],[13,22],[36,9],[5,23],[-7,13],[-10,62],[-1,36],[-11,38]],[[4939,7135],[27,32],[30,11],[17,24],[27,18],[47,11],[46,4],[14,-8],[26,23],[30,0],[11,-13],[19,3]],[[5233,7240],[-5,-30],[4,-56],[-6,-49],[-18,-33],[3,-45],[23,-35],[0,-14],[17,-24],[12,-106]],[[5263,6848],[9,-52],[1,-28],[-5,-48],[2,-27],[-3,-32],[2,-37],[-11,-25],[17,-43],[1,-25],[10,-33],[13,11],[22,-28],[12,-37]],[[2769,4856],[15,45],[-6,25],[-11,-27],[-16,26],[5,16],[-4,54],[9,9],[5,37],[11,38],[-2,24],[15,13],[19,23]],[[2906,5049],[4,-45],[-9,-39],[-30,-62],[-33,-23],[-17,-51],[-6,-40],[-15,-24],[-12,29],[-11,7],[-12,-5],[-1,22],[8,14],[-3,24]],[[5969,6800],[-7,-23],[-6,-45],[-8,-31],[-6,-10],[-10,19],[-12,26],[-20,85],[-3,-5],[12,-63],[17,-59],[21,-92],[10,-32],[9,-34],[25,-65],[-6,-10],[1,-39],[33,-53],[4,-12]],[[6023,6357],[-110,0],[-107,0],[-112,0]],[[5694,6357],[0,218],[0,210],[-8,47],[7,37],[-5,25],[10,29]],[[5698,6923],[37,0],[27,-15],[28,-18],[13,-9],[21,19],[11,17],[25,5],[20,-8],[7,-29],[7,19],[22,-14],[22,-3],[13,15]],[[5951,6902],[18,-102]],[[6176,5798],[-10,20],[-11,34],[-12,19],[-8,21],[-24,23],[-19,1],[-7,12],[-16,-14],[-17,27],[-8,-44],[-33,13]],[[6011,5910],[-3,23],[12,87],[3,39],[9,18],[20,10],[14,34]],[[6066,6121],[16,-69],[8,-54],[15,-29],[38,-55],[16,-34],[15,-34],[8,-20],[14,-18]],[[4749,7532],[1,42],[-11,25],[39,43],[34,-11],[37,1],[30,-10],[23,3],[45,-2]],[[4947,7623],[11,-23],[51,-27],[10,13],[31,-27],[32,8]],[[5082,7567],[2,-35],[-26,-39],[-36,-12],[-2,-20],[-18,-33],[-10,-48],[11,-34],[-16,-26],[-6,-39],[-21,-11],[-20,-46],[-35,-1],[-27,1],[-17,-21],[-11,-22],[-13,5],[-11,20],[-8,34],[-26,9]],[[4792,7249],[-2,20],[10,22],[4,16],[-9,17],[7,39],[-11,36],[12,5],[1,27],[5,9],[0,46],[13,16],[-8,30],[-16,2],[-5,-8],[-16,0],[-7,29],[-11,-8],[-10,-15]],[[5675,8472],[3,35],[-10,-8],[-18,21],[-2,34],[35,17],[35,8],[30,-10],[29,2]],[[5777,8571],[4,-10],[-20,-34],[8,-55],[-12,-19]],[[5757,8453],[-22,0],[-24,22],[-13,7],[-23,-10]],[[6188,5703],[-6,-21],[10,-32],[10,-29],[11,-21],[90,-70],[24,0]],[[6327,5530],[-79,-177],[-36,-3],[-25,-41],[-17,-1],[-8,-19]],[[6162,5289],[-19,0],[-11,20],[-26,-25],[-8,-24],[-18,4],[-6,7],[-7,-1],[-9,0],[-35,50],[-19,0],[-10,20],[0,33],[-14,10]],[[5980,5383],[-17,64],[-12,14],[-5,23],[-14,29],[-17,4],[9,34],[15,2],[4,18]],[[5943,5571],[0,53]],[[5943,5624],[8,62],[13,16],[3,24],[12,45],[17,30],[11,58],[4,51]],[[5794,9138],[-4,-42],[42,-39],[-26,-45],[33,-67],[-19,-51],[25,-43],[-11,-39],[41,-40],[-11,-31],[-25,-34],[-60,-75]],[[5779,8632],[-50,-5],[-49,-21],[-45,-13],[-16,32],[-27,20],[6,58],[-14,53],[14,35],[25,37],[63,64],[19,12],[-3,25],[-39,28]],[[5663,8957],[-9,23],[-1,91],[-43,40],[-37,29]],[[5573,9140],[17,16],[30,-32],[37,3],[30,-14],[26,26],[14,44],[43,20],[35,-24],[-11,-41]],[[9954,4033],[9,-17],[-4,-31],[-17,-8],[-16,7],[-2,26],[10,21],[13,-8],[7,10]],[[0,4079],[9981,-14],[-17,-13],[-4,23],[14,12],[9,3],[-9983,18]],[[0,4108],[0,-29]],[[0,4108],[6,3],[-4,-28],[-2,-4]],[[3300,1994],[33,36],[24,-15],[16,24],[22,-27],[-8,-21],[-37,-17],[-13,20],[-23,-26],[-14,26]],[[5265,7548],[-9,-46],[-13,12],[-6,40],[5,22],[18,22],[5,-50]],[[5157,7984],[6,-6],[8,2]],[[5190,7775],[-2,-17],[9,-22],[-10,-18],[7,-46],[15,-8],[-3,-25]],[[5206,7639],[-25,-34],[-55,16],[-40,-19],[-4,-35]],[[4947,7623],[14,35],[5,118],[-28,62],[-21,30],[-42,23],[-3,43],[36,12],[47,-15],[-9,67],[26,-25],[65,46],[8,48],[24,12]],[[3485,5194],[7,25],[3,27]],[[3495,5246],[4,26],[-10,34]],[[3489,5306],[-3,41],[15,51]],[[3501,5398],[9,-7],[21,-14],[29,-50],[5,-24]],[[5308,4822],[-29,60],[-18,49],[-17,61],[1,19],[6,19],[7,43],[5,44]],[[5263,5117],[10,4],[40,-1],[0,71]],[[4827,8240],[-21,12],[-17,-1],[6,32],[-6,32]],[[4789,8315],[23,2],[30,-37],[-15,-40]],[[4916,8521],[-30,-63],[29,8],[30,-1],[-7,-48],[-25,-53],[29,-4],[2,-6],[25,-69],[19,-10],[17,-67],[8,-24],[33,-11],[-3,-38],[-14,-17],[11,-30],[-25,-31],[-37,0],[-48,-16],[-13,12],[-18,-28],[-26,7],[-19,-23],[-15,12],[41,62],[25,13],[-1,0],[-43,9],[-8,24],[29,18],[-15,32],[5,39],[42,-6],[4,35],[-19,36],[0,1],[-34,10],[-7,16],[10,27],[-9,16],[-15,-28],[-1,57],[-14,30],[10,61],[21,48],[23,-4],[33,4]],[[6154,7511],[4,26],[-7,40],[-16,22],[-16,6],[-10,19]],[[6109,7624],[4,6],[23,-10],[41,-9],[38,-28],[5,-11],[17,9],[25,-13],[9,-24],[17,-13]],[[6210,7485],[-27,29],[-29,-3]],[[5029,5408],[-44,-35],[-15,-20],[-25,-17],[-25,17]],[[5e3,5708],[-2,-18],[12,-30],[0,-43],[2,-47],[7,-21],[-6,-54],[2,-29],[8,-37],[6,-21]],[[4765,5512],[-8,1],[-5,-24],[-8,1],[-6,12],[2,24],[-11,36],[-8,-7],[-6,-1]],[[4715,5554],[-7,-3],[0,21],[-4,16],[0,17],[-6,25],[-7,21],[-23,0],[-6,-11],[-8,-1],[-4,-13],[-4,-17],[-14,-26]],[[4632,5583],[-13,35],[-10,24],[-8,7],[-6,12],[-4,26],[-4,13],[-8,10]],[[4579,5710],[13,29],[8,-2],[7,10],[6,0],[5,8],[-3,20],[3,6],[1,20]],[[4619,5801],[13,-1],[20,-14],[6,1],[3,7],[15,-5],[4,4]],[[4680,5793],[1,-22],[5,0],[7,8],[5,-2],[7,-15],[12,-5],[8,13],[9,8],[6,8],[6,-1],[6,-13],[3,-17],[12,-24],[-6,-16],[-1,-19],[6,6],[3,-7],[-1,-17],[8,-18]],[[4532,5834],[3,27]],[[4535,5861],[31,1],[6,14],[9,1],[11,-14],[8,-1],[9,10],[6,-17],[-12,-13],[-12,1],[-12,13],[-10,-14],[-5,-1],[-7,-8],[-25,1]],[[4579,5710],[-15,24],[-11,4],[-7,17],[1,9],[-9,13],[-2,12]],[[4536,5789],[15,10],[9,-2],[8,7],[51,-3]],[[5263,5117],[-5,9],[10,66]],[[5658,7167],[15,-20],[22,3],[20,-4],[0,-10],[15,7],[-4,-18],[-40,-5],[1,10],[-34,12],[5,25]],[[5723,7469],[-17,2],[-14,6],[-34,-16],[19,-33],[-14,-10],[-15,0],[-15,31],[-5,-13],[6,-36],[14,-27],[-10,-13],[15,-27],[14,-18],[0,-33],[-25,16],[8,-30],[-18,-7],[11,-52],[-19,-1],[-23,26],[-10,47],[-5,40],[-11,27],[-14,34],[-2,16]],[[5583,7470],[18,6],[11,13],[15,-2],[5,11],[5,2]],[[5725,7529],[13,-16],[-8,-37],[-7,-7]],[[3701,9939],[93,35],[97,-2],[36,21],[98,6],[222,-7],[174,-47],[-52,-23],[-106,-3],[-150,-5],[14,-11],[99,7],[83,-21],[54,18],[23,-21],[-30,-34],[71,22],[135,23],[83,-12],[15,-25],[-113,-42],[-16,-14],[-88,-10],[64,-3],[-32,-43],[-23,-38],[1,-66],[33,-38],[-43,-3],[-46,-19],[52,-31],[6,-50],[-30,-6],[36,-50],[-61,-5],[32,-24],[-9,-20],[-39,-10],[-39,0],[35,-40],[0,-26],[-55,24],[-14,-15],[37,-15],[37,-36],[10,-48],[-49,-11],[-22,22],[-34,34],[10,-40],[-33,-31],[73,-2],[39,-3],[-75,-52],[-75,-46],[-81,-21],[-31,0],[-29,-23],[-38,-62],[-60,-42],[-19,-2],[-37,-15],[-40,-13],[-24,-37],[0,-41],[-15,-39],[-45,-47],[11,-47],[-12,-48],[-14,-58],[-39,-4],[-41,49],[-56,0],[-27,32],[-18,58],[-49,73],[-14,39],[-3,53],[-39,54],[10,44],[-18,21],[27,69],[42,22],[11,25],[6,46],[-32,-21],[-15,-9],[-25,-8],[-34,19],[-2,40],[11,31],[25,1],[57,-15],[-48,37],[-24,20],[-28,-8],[-23,15],[31,55],[-17,22],[-22,41],[-34,62],[-35,23],[0,25],[-74,34],[-59,5],[-74,-3],[-68,-4],[-32,19],[-49,37],[73,19],[56,3],[-119,15],[-62,24],[3,23],[106,28],[101,29],[11,21],[-75,22],[24,23],[97,41],[40,7],[-12,26],[66,16],[86,9],[85,1],[30,-19],[74,33],[66,-22],[39,-5],[58,-19],[-66,32],[4,25]],[[2497,5869],[-14,10],[-17,1],[-13,12],[-15,24]],[[2438,5916],[1,18],[3,13],[-4,12],[13,48],[36,0],[1,20],[-5,4],[-3,12],[-10,14],[-11,20],[13,0],[0,33],[26,0],[26,0]],[[2529,5996],[10,-11],[2,9],[8,-7]],[[2549,5987],[-13,-23],[-13,-16],[-2,-12],[2,-11],[-5,-15]],[[2518,5910],[-7,-4],[2,-7],[-6,-6],[-9,-15],[-1,-9]],[[3340,5552],[18,-22],[17,-38],[1,-31],[10,-1],[15,-29],[11,-21]],[[3412,5410],[-4,-53],[-17,-15],[1,-14],[-5,-31],[13,-42],[9,-1],[3,-33],[17,-51]],[[3313,5365],[-19,45],[7,16],[0,27],[17,10],[7,11],[-10,22],[3,21],[22,35]],[[2574,5825],[-5,18],[-8,5]],[[2561,5848],[2,24],[-4,6],[-6,4],[-12,-7],[-1,8],[-8,10],[-6,12],[-8,5]],[[2549,5987],[3,-3],[6,11],[8,1],[3,-5],[4,3],[13,-6],[13,2],[9,6],[3,7],[9,-3],[6,-4],[8,1],[5,5],[13,-8],[4,-1],[9,-11],[8,-13],[10,-9],[7,-17]],[[2690,5943],[-9,2],[-4,-8],[-10,-8],[-7,0],[-6,-8],[-6,3],[-4,9],[-3,-2],[-4,-14],[-3,1],[0,-12],[-10,-17],[-5,-7],[-3,-7],[-8,12],[-6,-16],[-6,1],[-6,-2],[0,-29],[-4,0],[-3,-14],[-9,-2]],[[5522,7770],[7,-23],[9,-17],[-11,-22]],[[5515,7577],[-3,-10]],[[5512,7567],[-26,22],[-16,21],[-26,18],[-23,43],[6,5],[-13,25],[-1,19],[-17,10],[-9,-26],[-8,20],[0,21],[1,1]],[[5380,7746],[20,-2],[5,9],[9,-9],[11,-1],[0,16],[10,6],[2,24],[23,16]],[[5460,7805],[8,-7],[21,-26],[23,-11],[10,9]],[[3008,6124],[-19,10],[-13,-5],[-17,5],[-13,-11],[-15,18],[3,19],[25,-8],[21,-5],[10,13],[-12,26],[0,23],[-18,9],[7,16],[17,-3],[24,-9]],[[5471,7900],[14,-15],[10,-6],[24,7],[2,12],[11,2],[14,9],[3,-4],[13,8],[6,13],[9,4],[30,-18],[6,6]],[[5613,7918],[15,-16],[2,-16]],[[5630,7886],[-17,-12],[-13,-40],[-17,-40],[-22,-11]],[[5561,7783],[-17,2],[-22,-15]],[[5460,7805],[-6,20],[-4,0]],[[8352,4453],[-11,-2],[-37,42],[26,11],[14,-18],[10,-17],[-2,-16]],[[8471,4532],[2,-11],[1,-18]],[[8474,4503],[-18,-45],[-24,-13],[-3,8],[2,20],[12,36],[28,23]],[[8274,4579],[10,-16],[17,5],[7,-25],[-32,-12],[-19,-8],[-15,1],[10,34],[15,0],[7,21]],[[8413,4579],[-4,-32],[-42,-17],[-37,7],[0,22],[22,12],[18,-18],[18,5],[25,21]],[[8017,4657],[53,-6],[6,25],[51,-29],[10,-38],[42,-11],[34,-35],[-31,-23],[-31,24],[-25,-1],[-29,4],[-26,11],[-32,22],[-21,6],[-11,-7],[-51,24],[-5,25],[-25,5],[19,56],[34,-3],[22,-23],[12,-5],[4,-21]],[[8741,4690],[-14,-40],[-3,45],[5,21],[6,20],[7,-17],[-1,-29]],[[8534,4853],[-11,-19],[-19,10],[-5,26],[28,3],[7,-20]],[[8623,4875],[10,-45],[-23,24],[-23,5],[-16,-4],[-19,2],[6,33],[35,2],[30,-17]],[[8916,4904],[0,-193],[1,-192]],[[8917,4519],[-25,48],[-28,12],[-7,-17],[-35,-1],[12,48],[17,16],[-7,64],[-14,50],[-53,50],[-23,5],[-42,54],[-8,-28],[-11,-5],[-6,21],[0,26],[-21,29],[29,21],[20,-1],[-2,16],[-41,0],[-11,35],[-25,11],[-11,29],[37,14],[14,20],[45,-25],[4,-22],[8,-95],[29,-35],[23,62],[32,36],[25,0],[23,-21],[21,-21],[30,-11]],[[8478,5141],[-22,-58],[-21,-12],[-27,12],[-46,-3],[-24,-8],[-4,-45],[24,-53],[15,27],[52,20],[-2,-27],[-12,9],[-12,-35],[-25,-23],[27,-76],[-5,-20],[25,-68],[-1,-39],[-14,-17],[-11,20],[13,49],[-27,-23],[-7,16],[3,23],[-20,35],[3,57],[-19,-18],[2,-69],[1,-84],[-17,-9],[-12,18],[8,54],[-4,57],[-12,1],[-9,40],[12,39],[4,47],[14,89],[5,24],[24,44],[22,-18],[35,-8],[32,3],[27,43],[5,-14]],[[8574,5124],[-2,-51],[-14,6],[-4,-36],[11,-32],[-8,-7],[-11,38],[-8,75],[6,47],[9,22],[2,-32],[16,-5],[3,-25]],[[8045,5176],[5,-39],[19,-34],[18,12],[18,-4],[16,30],[13,5],[26,-17],[23,13],[14,82],[11,21],[10,67],[32,0],[24,-10]],[[8274,5302],[-16,-53],[20,-56],[-5,-28],[32,-54],[-33,-7],[-10,-40],[2,-54],[-27,-40],[-1,-59],[-10,-91],[-5,21],[-31,-26],[-11,36],[-20,3],[-14,19],[-33,-21],[-10,29],[-18,-4],[-23,7],[-4,79],[-14,17],[-13,50],[-4,52],[3,55],[16,39]],[[7939,4712],[-31,-1],[-24,49],[-35,48],[-12,36],[-21,48],[-14,44],[-21,83],[-24,49],[-9,51],[-10,46],[-25,37],[-14,51],[-21,33],[-29,65],[-3,30],[18,-2],[43,-12],[25,-57],[21,-40],[16,-25],[26,-63],[28,-1],[23,-41],[16,-49],[22,-27],[-12,-49],[16,-20],[10,-2],[5,-41],[10,-33],[20,-5],[14,-37],[-7,-74],[-1,-91]],[[7252,6841],[-17,-27],[-11,-55],[27,-23],[26,-29],[36,-33],[38,-8],[16,-30],[22,-5],[33,-14],[23,1],[4,23],[-4,38],[2,25]],[[7703,6727],[2,-22],[-10,-11],[2,-36],[-19,10],[-36,-41],[0,-33],[-15,-50],[-1,-29],[-13,-48],[-21,13],[-1,-61],[-7,-20],[3,-25],[-14,-14]],[[7472,6360],[-4,-21],[-19,1],[-34,-13],[2,-44],[-15,-35],[-40,-40],[-31,-69],[-21,-38],[-28,-38],[0,-27],[-13,-15],[-26,-21],[-12,-3],[-9,-45],[6,-77],[1,-49],[-11,-56],[0,-101],[-15,-2],[-12,-46],[8,-19],[-25,-17],[-10,-40],[-11,-17],[-26,55],[-13,83],[-11,60],[-9,28],[-15,56],[-7,74],[-5,37],[-25,81],[-12,115],[-8,75],[0,72],[-5,55],[-41,-35],[-19,7],[-36,71],[13,22],[-8,23],[-33,50]],[[6893,6457],[19,40],[61,-1],[-6,51],[-15,30],[-4,46],[-18,26],[31,62],[32,-4],[29,61],[18,60],[27,60],[-1,42],[24,34],[-23,29],[-9,40],[-10,52],[14,25],[42,-14],[31,9],[26,49]],[[4827,8240],[5,-42],[-21,-53],[-49,-35],[-40,9],[23,62],[-15,60],[38,46],[21,28]],[[6497,7255],[25,12],[19,33],[19,-1],[12,11],[20,-6],[31,-30],[22,-6],[31,-53],[21,-2],[3,-49]],[[6690,6820],[14,-31],[11,-36],[27,-26],[1,-52],[13,-10],[2,-27],[-40,-30],[-10,-69]],[[6708,6539],[-53,18],[-30,13],[-31,8],[-12,73],[-13,10],[-22,-11],[-28,-28],[-34,20],[-28,45],[-27,17],[-18,56],[-21,79],[-15,-10],[-17,20],[-11,-24]],[[6348,6825],[-15,32],[0,31],[-9,0],[5,43],[-15,45],[-34,32],[-19,56],[6,46],[14,21],[-2,34],[-18,18],[-18,70]],[[6243,7253],[-15,48],[5,18],[-8,68],[19,17]],[[6357,7321],[9,-43],[26,-13],[20,-29],[39,-10],[44,15],[2,14]],[[6348,6825],[-16,3]],[[6332,6828],[-19,5],[-20,-56]],[[6293,6777],[-52,4],[-78,119],[-41,41],[-34,16]],[[6088,6957],[-11,72]],[[6077,7029],[61,62],[11,71],[-3,43],[16,15],[14,37]],[[6176,7257],[12,9],[32,-8],[10,-15],[13,10]],[[4597,8984],[-7,-39],[31,-40],[-36,-45],[-80,-41],[-24,-10],[-36,8],[-78,19],[28,26],[-61,29],[49,12],[-1,17],[-58,14],[19,38],[42,9],[43,-40],[42,32],[35,-17],[45,32],[47,-4]],[[5992,6990],[-5,-19]],[[5987,6971],[-10,8],[-6,-39],[7,-7],[-7,-8],[-1,-15],[13,8]],[[5983,6918],[0,-23],[-14,-95]],[[5951,6902],[8,19],[-2,4],[8,27],[5,45],[4,15],[1,0]],[[5975,7012],[9,0],[3,11],[7,0]],[[5994,7023],[1,-24],[-4,-9],[1,0]],[[5431,7316],[-10,-46],[4,-19],[-6,-30],[-21,22],[-14,7],[-39,30],[4,30],[32,-6],[28,7],[22,5]],[[5255,7492],[17,-42],[-4,-78],[-13,4],[-11,-20],[-10,16],[-2,71],[-6,34],[15,-3],[14,18]],[[5383,7805],[-3,-29],[7,-25]],[[5387,7751],[-22,8],[-23,-20],[1,-30],[-3,-17],[9,-30],[26,-29],[14,-49],[31,-48],[22,0],[7,-13],[-8,-11],[25,-22],[20,-18],[24,-30],[3,-11],[-5,-22],[-16,28],[-24,10],[-12,-39],[20,-21],[-3,-31],[-11,-4],[-15,-50],[-12,-5],[0,18],[6,32],[6,12],[-11,35],[-8,29],[-12,8],[-8,25],[-18,11],[-12,24],[-21,4],[-21,26],[-26,39],[-19,34],[-8,58],[-14,7],[-23,20],[-12,-8],[-16,-28],[-12,-4]],[[2845,6150],[19,-5],[14,-15],[5,-16],[-19,-1],[-9,-10],[-15,10],[-16,21],[3,14],[12,4],[6,-2]],[[5992,6990],[31,-24],[54,63]],[[6088,6957],[-5,-8],[-56,-30],[28,-59],[-9,-10],[-5,-20],[-21,-8],[-7,-21],[-12,-19],[-31,10]],[[5970,6792],[-1,8]],[[5983,6918],[4,17],[0,36]],[[8739,7075],[4,-20],[-16,-36],[-11,19],[-15,-14],[-7,-34],[-18,16],[0,28],[15,36],[16,-7],[12,25],[20,-13]],[[8915,7252],[-10,-47],[4,-30],[-14,-42],[-35,-27],[-49,-4],[-40,-67],[-19,22],[-1,44],[-48,-13],[-33,-27],[-32,-2],[28,-43],[-19,-101],[-18,-24],[-13,23],[7,53],[-18,17],[-11,41],[26,18],[15,37],[28,30],[20,41],[55,17],[30,-12],[29,105],[19,-28],[40,59],[16,23],[18,72],[-5,67],[11,37],[30,11],[15,-82],[-1,-48],[-25,-59],[0,-61]],[[8997,7667],[19,-12],[20,25],[6,-67],[-41,-16],[-25,-59],[-43,41],[-15,-65],[-31,-1],[-4,59],[14,46],[29,3],[8,82],[9,46],[32,-62],[22,-20]],[[6970,7554],[-15,-10],[-37,-42],[-12,-42],[-11,0],[-7,28],[-36,2],[-5,48],[-14,0],[2,60],[-33,43],[-48,-5],[-32,-8],[-27,53],[-22,22],[-43,43],[-6,5],[-71,-35],[1,-218]],[[6554,7498],[-14,-3],[-20,46],[-18,17],[-32,-12],[-12,-20]],[[6458,7526],[-2,14],[7,25],[-5,21],[-32,20],[-13,53],[-15,15],[-1,19],[27,-6],[1,44],[23,9],[25,-9],[5,58],[-5,36],[-28,-2],[-24,14],[-32,-26],[-26,-12]],[[6363,7799],[-14,9],[3,31],[-18,39],[-20,-2],[-24,40],[16,45],[-8,12],[22,65],[29,-34],[3,43],[58,64],[43,2],[61,-41],[33,-24],[30,25],[44,1],[35,-30],[8,17],[39,-2],[7,28],[-45,40],[27,29],[-5,16],[26,15],[-20,41],[13,20],[104,21],[13,14],[70,22],[25,24],[50,-12],[9,-61],[29,14],[35,-20],[-2,-32],[27,3],[69,56],[-10,-19],[35,-46],[62,-150],[15,31],[39,-34],[39,16],[16,-11],[13,-34],[20,-12],[11,-25],[36,8],[15,-36]],[[7229,7559],[-17,9],[-14,21],[-42,6],[-46,2],[-10,-6],[-39,24],[-16,-12],[-4,-35],[-46,21],[-18,-9],[-7,-26]],[[6155,4958],[-20,-24],[-7,-24],[-10,-4],[-4,-42],[-9,-24],[-5,-39],[-12,-20]],[[6088,4781],[-40,59],[-1,35],[-101,120],[-5,6]],[[5941,5001],[0,63],[8,24],[14,39],[10,43],[-13,68],[-3,30],[-13,41]],[[5944,5309],[17,35],[19,39]],[[6162,5289],[-24,-67],[0,-215],[17,-49]],[[7046,7387],[-53,-9],[-34,19],[-30,-4],[3,34],[30,-10],[10,18]],[[6972,7435],[21,-6],[36,43],[-33,31],[-20,-15],[-21,22],[24,39],[-9,5]],[[7849,5777],[-7,72],[18,49],[36,11],[26,-8]],[[7922,5901],[23,-23],[12,40],[25,-21]],[[7982,5897],[6,-40],[-3,-71],[-47,-45],[13,-36],[-30,-4],[-24,-24]],[[7897,5677],[-23,9],[-11,30],[-14,61]],[[8564,7339],[24,-70],[7,-38],[0,-68],[-10,-33],[-25,-11],[-22,-25],[-25,-5],[-3,32],[5,45],[-13,61],[21,10],[-19,51]],[[8504,7288],[2,5],[12,-2],[11,27],[20,2],[11,4],[4,15]],[[5557,7574],[5,13]],[[5562,7587],[7,4],[4,20],[5,3],[4,-8],[5,-4],[3,-10],[5,-2],[5,-11],[4,0],[-3,-14],[-3,-7],[1,-5]],[[5599,7553],[-6,-2],[-17,-9],[-1,-12],[-4,0]],[[6332,6828],[6,-26],[-3,-13],[9,-45]],[[6344,6744],[-19,-1],[-7,28],[-25,6]],[[7922,5901],[9,26],[1,50],[-22,52],[-2,58],[-21,48],[-21,4],[-6,-20],[-16,-2],[-8,10],[-30,-35],[0,53],[7,62],[-19,3],[-2,36],[-12,18]],[[7780,6264],[6,21],[24,39]],[[7837,6385],[17,-47],[12,-54],[34,0],[11,-52],[-18,-15],[-8,-21],[34,-36],[23,-70],[17,-52],[21,-41],[7,-41],[-5,-59]],[[5975,7012],[10,49],[14,41],[0,2]],[[5999,7104],[13,-3],[4,-23],[-15,-22],[-7,-33]],[[4785,5315],[-7,0],[-29,28],[-25,45],[-24,32],[-18,38]],[[4682,5458],[6,19],[2,17],[12,33],[13,27]],[[5412,6408],[-20,-22],[-15,33],[-44,25]],[[5263,6848],[13,14],[3,25],[-3,24],[19,23],[8,19],[14,17],[2,45]],[[5319,7015],[32,-20],[12,5],[23,-10],[37,-26],[13,-53],[25,-11],[39,-25],[30,-29],[13,15],[13,27],[-6,45],[9,29],[20,28],[19,8],[37,-12],[10,-27],[10,0],[9,-10],[28,-7],[6,-19]],[[5694,6357],[0,-118],[-32,0],[0,-25]],[[5662,6214],[-111,113],[-111,113],[-28,-32]],[[7271,5502],[-4,-62],[-12,-16],[-24,-14],[-13,47],[-5,85],[13,96],[19,-33],[13,-42],[13,-61]],[[5804,3347],[10,-18],[-9,-29],[-4,-19],[-16,-9],[-5,-19],[-10,-6],[-21,46],[15,37],[15,23],[13,12],[12,-18]],[[5631,8267],[-2,15],[3,16],[-13,10],[-29,10]],[[5590,8318],[-6,50]],[[5584,8368],[32,18],[47,-4],[27,6],[4,-12],[15,-4],[26,-29]],[[5652,8242],[-7,19],[-14,6]],[[5584,8368],[1,44],[14,37],[26,20],[22,-44],[22,1],[6,46]],[[5757,8453],[14,-14],[2,-28],[9,-35]],[[4759,6691],[-4,0],[0,-31],[-17,-2],[-9,-14],[-13,0],[-10,8],[-23,-6],[-9,-46],[-9,-5],[-13,-74],[-38,-64],[-9,-81],[-12,-27],[-3,-21],[-63,-5]],[[4527,6323],[1,27],[11,17],[9,30],[-2,20],[10,42],[15,38],[9,9],[8,35],[0,31],[10,37],[19,21],[18,60],[0,1],[14,23],[26,6],[22,41],[14,16],[23,49],[-7,73],[10,51],[4,31],[18,40],[28,27],[21,25],[18,61],[9,36],[20,0],[17,-25],[26,4],[29,-13],[12,-1]],[[5739,7906],[6,9],[19,6],[20,-19],[12,-2],[12,-16],[-2,-20],[11,-9],[4,-25],[9,-15],[-2,-9],[5,-6],[-7,-4],[-16,1],[-3,9],[-6,-5],[2,-11],[-7,-19],[-5,-20],[-7,-6]],[[5784,7745],[-5,27],[3,25],[-1,26],[-16,35],[-9,25],[-9,17],[-8,6]],[[6376,4321],[7,-25],[7,-39],[4,-71],[7,-28],[-2,-28],[-5,-18],[-10,35],[-5,-18],[5,-43],[-2,-25],[-8,-14],[-1,-50],[-11,-69],[-14,-81],[-17,-112],[-11,-82],[-12,-69],[-23,-14],[-24,-25],[-16,15],[-22,21],[-8,31],[-2,53],[-10,47],[-2,42],[5,43],[13,10],[0,20],[13,45],[2,37],[-6,28],[-5,38],[-2,54],[9,33],[4,38],[14,2],[15,12],[11,10],[12,1],[16,34],[23,36],[8,30],[-4,25],[12,-7],[15,41],[1,36],[9,26],[10,-25]],[[2301,6586],[-10,-52],[-5,-43],[-2,-79],[-3,-29],[5,-32],[9,-29],[5,-45],[19,-44],[6,-34],[11,-29],[29,-16],[12,-25],[24,17],[21,6],[21,11],[18,10],[17,24],[7,34],[2,50],[5,17],[19,16],[29,13],[25,-2],[17,5],[6,-12],[-1,-29],[-15,-35],[-6,-36],[5,-10],[-4,-26],[-7,-46],[-7,15],[-6,-1]],[[2438,5916],[-32,64],[-14,19],[-23,16],[-15,-5],[-22,-22],[-14,-6],[-20,16],[-21,11],[-26,27],[-21,8],[-31,28],[-23,28],[-7,16],[-16,3],[-28,19],[-12,27],[-30,34],[-14,37],[-6,29],[9,5],[-3,17],[7,16],[0,20],[-10,27],[-2,23],[-9,30],[-25,59],[-28,46],[-13,37],[-24,24],[-5,14],[4,37],[-14,13],[-17,29],[-7,41],[-14,5],[-17,31],[-13,29],[-1,19],[-15,44],[-10,45],[1,23],[-20,23],[-10,-2],[-15,16],[-5,-24],[5,-28],[2,-45],[10,-24],[21,-41],[4,-14],[4,-4],[4,-20],[5,1],[6,-38],[8,-15],[6,-21],[17,-30],[10,-55],[8,-26],[8,-28],[1,-31],[13,-2],[12,-27],[10,-26],[-1,-11],[-12,-21],[-5,0],[-7,36],[-18,33],[-20,29],[-14,15],[1,43],[-5,32],[-13,19],[-19,26],[-4,-8],[-7,16],[-17,14],[-16,34],[2,5],[11,-4],[11,22],[1,27],[-22,42],[-16,17],[-10,36],[-11,39],[-12,47],[-12,54]],[[1746,6980],[32,4],[35,7],[-2,-12],[41,-29],[64,-41],[55,0],[22,0],[0,24],[48,0],[10,-20],[15,-19],[16,-26],[9,-31],[7,-32],[15,-18],[23,-18],[17,47],[23,1],[19,-24],[14,-40],[10,-35],[16,-34],[6,-41],[8,-28],[22,-18],[20,-13],[10,2]],[[5599,7553],[9,4],[13,1]],[[4661,5921],[10,11],[4,35],[9,1],[20,-16],[15,11],[11,-4],[4,13],[112,1],[6,42],[-5,7],[-13,255],[-14,255],[43,1]],[[5118,6189],[0,-136],[-15,-39],[-2,-37],[-25,-9],[-38,-5],[-10,-21],[-18,-3]],[[4680,5793],[1,18],[-2,23],[-11,16],[-5,34],[-2,37]],[[7737,5644],[-3,44],[9,45],[-10,35],[3,65],[-12,30],[-9,71],[-5,75],[-12,49],[-18,-30],[-32,-42],[-15,5],[-17,14],[9,73],[-6,56],[-21,68],[3,21],[-16,7],[-20,49]],[[7780,6264],[-16,-14],[-16,-26],[-20,-2],[-12,-64],[-12,-11],[14,-52],[17,-43],[12,-39],[-11,-51],[-9,-11],[6,-30],[19,-47],[3,-33],[0,-27],[11,-54],[-16,-55],[-13,-61]],[[5538,7532],[-6,4],[-8,19],[-12,12]],[[5533,7629],[8,-10],[4,-9],[9,-6],[10,-12],[-2,-5]],[[7437,7970],[29,10],[53,51],[42,28],[24,-18],[29,-1],[19,-28],[28,-2],[40,-15],[27,41],[-11,35],[28,61],[31,-24],[26,-7],[32,-15],[6,-44],[39,-25],[26,11],[36,7],[27,-7],[28,-29],[16,-30],[26,1],[35,-10],[26,15],[36,9],[41,42],[17,-6],[14,-20],[33,5]],[[5959,4377],[21,5],[34,-17],[7,8],[19,1],[10,18],[17,-1],[30,23],[22,34]],[[6119,4448],[5,-26],[-1,-59],[3,-52],[1,-92],[5,-29],[-8,-43],[-11,-41],[-18,-36],[-25,-23],[-31,-28],[-32,-64],[-10,-11],[-20,-42],[-11,-13],[-3,-42],[14,-45],[5,-35],[0,-17],[5,3],[-1,-58],[-4,-28],[6,-10],[-4,-25],[-11,-21],[-23,-20],[-34,-32],[-12,-21],[3,-25],[7,-4],[-3,-31]],[[5911,3478],[-21,0]],[[5890,3478],[-2,26],[-4,27]],[[5884,3531],[-3,21],[5,66],[-7,42],[-13,83]],[[5866,3743],[29,67],[7,43],[5,5],[3,35],[-5,17],[1,44],[6,41],[0,75],[-15,19],[-13,4],[-6,15],[-13,12],[-23,-1],[-2,22]],[[5840,4141],[-2,42],[84,49]],[[5922,4232],[16,-28],[8,5],[11,-15],[1,-23],[-6,-28],[2,-42],[19,-36],[8,41],[12,12],[-2,76],[-12,43],[-10,19],[-10,-1],[-7,77],[7,45]],[[4661,5921],[-18,41],[-17,43],[-18,16],[-13,17],[-16,-1],[-13,-12],[-14,5],[-10,-19]],[[4542,6011],[-2,32],[8,29],[3,55],[-3,59],[-3,29],[2,30],[-7,28],[-14,25]],[[4526,6298],[6,20],[108,-1],[-5,86],[7,30],[26,5],[-1,152],[91,-4],[0,90]],[[5922,4232],[-15,15],[9,55],[9,21],[-6,49],[6,48],[5,16],[-7,50],[-14,26]],[[5909,4512],[28,-11],[5,-16],[10,-28],[7,-80]],[[7836,5425],[7,-5],[16,-36],[12,-40],[2,-39],[-3,-27],[2,-21],[2,-35],[10,-16],[11,-52],[-1,-20],[-19,-4],[-27,44],[-32,47],[-4,30],[-16,39],[-4,49],[-10,32],[4,43],[-7,25]],[[7779,5439],[5,11],[23,-26],[2,-30],[18,7],[9,24]],[[8045,5176],[21,-20],[21,11],[6,50],[12,11],[33,13],[20,47],[14,37]],[[8206,5379],[22,41],[14,47],[11,0],[14,-30],[1,-26],[19,-16],[23,-18],[-2,-23],[-19,-3],[5,-29],[-20,-20]],[[5453,3369],[-20,45],[-11,43],[-6,58],[-7,42],[-9,91],[-1,71],[-3,32],[-11,25],[-15,48],[-14,71],[-6,37],[-23,58],[-2,45]],[[5644,4022],[23,14],[18,-4],[11,-13],[0,-5]],[[5552,3594],[0,-218],[-25,-30],[-15,-4],[-17,11],[-13,4],[-4,25],[-11,17],[-14,-30]],[[9604,3812],[23,-36],[14,-28],[-10,-14],[-16,16],[-19,27],[-18,31],[-19,42],[-4,20],[12,-1],[16,-20],[12,-20],[9,-17]],[[5412,6408],[7,-92],[10,-15],[1,-19],[11,-20],[-6,-25],[-11,-120],[-1,-77],[-35,-56],[-12,-78],[11,-22],[0,-38],[18,-1],[-3,-28]],[[5393,5795],[-5,-1],[-19,64],[-6,3],[-22,-33],[-21,17],[-15,3],[-8,-8],[-17,2],[-16,-25],[-14,-2],[-34,31],[-13,-15],[-14,1],[-10,23],[-28,22],[-30,-7],[-7,-13],[-4,-34],[-8,-24],[-2,-53]],[[5236,5339],[-29,-21],[-11,3],[-10,-13],[-23,1],[-15,37],[-9,43],[-19,39],[-21,-1],[-25,0]],[[2619,5713],[-10,18],[-13,24],[-6,20],[-12,19],[-13,26],[3,9],[4,-9],[2,5]],[[2690,5943],[-2,-5],[-2,-13],[3,-22],[-6,-20],[-3,-24],[-1,-26],[1,-15],[1,-27],[-4,-6],[-3,-25],[2,-15],[-6,-16],[2,-16],[4,-9]],[[5092,8091],[14,16],[24,87],[38,25],[23,-2]],[[5863,9167],[-47,-24],[-22,-5]],[[5573,9140],[-17,-2],[-4,-39],[-53,9],[-7,-33],[-27,1],[-18,-42],[-28,-66],[-43,-83],[10,-20],[-10,-24],[-27,1],[-18,-55],[2,-79],[17,-29],[-9,-70],[-23,-40],[-12,-34]],[[5306,8535],[-19,36],[-55,-69],[-37,-13],[-38,30],[-10,63],[-9,137],[26,38],[73,49],[55,61],[51,82],[66,115],[47,44],[76,74],[61,26],[46,-3],[42,49],[51,-3],[50,12],[87,-43],[-36,-16],[30,-37]],[[5686,9657],[-62,-24],[-49,13],[19,16],[-16,19],[57,11],[11,-22],[40,-13]],[[5506,9766],[92,-44],[-70,-23],[-15,-44],[-25,-11],[-13,-49],[-34,-2],[-59,36],[25,21],[-42,17],[-54,50],[-21,46],[75,21],[16,-20],[39,0],[11,21],[40,2],[35,-21]],[[5706,9808],[55,-21],[-41,-32],[-81,-7],[-82,10],[-5,16],[-40,1],[-30,27],[86,17],[40,-14],[28,17],[70,-14]],[[9805,2640],[6,-24],[20,24],[8,-25],[0,-25],[-10,-27],[-18,-44],[-14,-24],[10,-28],[-22,-1],[-23,-22],[-8,-39],[-16,-60],[-21,-26],[-14,-17],[-26,1],[-18,20],[-30,4],[-5,22],[15,43],[35,59],[18,11],[20,22],[24,31],[16,31],[13,44],[10,15],[5,33],[19,27],[6,-25]],[[9849,2922],[20,-63],[1,41],[13,-16],[4,-45],[22,-19],[19,-5],[16,22],[14,-6],[-7,-53],[-8,-34],[-22,1],[-7,-18],[3,-25],[-4,-11],[-11,-32],[-14,-41],[-21,-23],[-5,15],[-12,9],[16,48],[-9,33],[-30,23],[1,22],[20,20],[5,46],[-1,38],[-12,40],[1,10],[-13,25],[-22,52],[-12,42],[11,4],[15,-33],[21,-15],[8,-52]],[[6475,6041],[-9,41],[-22,98]],[[6444,6180],[83,59],[19,118],[-13,42]],[[6566,6530],[12,-40],[16,-22],[20,-8],[17,-10],[12,-34],[8,-20],[10,-7],[0,-13],[-10,-36],[-5,-16],[-12,-19],[-10,-41],[-13,3],[-5,-14],[-5,-30],[4,-39],[-3,-7],[-13,0],[-17,-22],[-3,-29],[-6,-12],[-18,0],[-10,-15],[0,-24],[-14,-16],[-15,5],[-19,-19],[-12,-4]],[[6557,6597],[8,20],[3,-5],[-2,-25],[-4,-10]],[[6893,6457],[-20,15],[-9,43],[-21,45],[-51,-12],[-45,-1],[-39,-8]],[[2836,5484],[-9,17],[-6,32],[7,16],[-7,4],[-5,20],[-14,16],[-12,-4],[-6,-20],[-11,-15],[-6,-2],[-3,-13],[13,-32],[-7,-7],[-4,-9],[-13,-3],[-5,35],[-4,-10],[-9,4],[-5,24],[-12,3],[-7,7],[-12,0],[-1,-13],[-3,9]],[[2707,5623],[10,-22],[-1,-12],[11,-3],[3,5],[8,-14],[13,4],[12,15],[17,12],[9,17],[16,-3],[-1,-6],[15,-2],[12,-10],[10,-18],[10,-16]],[[3045,3974],[-28,33],[-2,25],[-55,59],[-50,65],[-22,36],[-11,49],[4,17],[-23,77],[-28,109],[-26,118],[-11,27],[-9,43],[-21,39],[-20,24],[9,26],[-14,57],[9,41],[22,37]],[[8510,5555],[2,-40],[2,-33],[-9,-54],[-11,60],[-13,-30],[9,-43],[-8,-28],[-32,35],[-8,42],[8,28],[-17,28],[-9,-24],[-13,2],[-21,-33],[-4,17],[11,50],[17,17],[15,22],[10,-27],[21,17],[5,26],[19,1],[-1,46],[22,-28],[3,-30],[2,-21]],[[8443,5665],[-10,-20],[-9,-37],[-8,-17],[-17,40],[5,16],[7,17],[3,36],[16,4],[-5,-40],[21,57],[-3,-56]],[[8291,5608],[-37,-56],[14,41],[20,37],[16,41],[15,58],[5,-48],[-18,-33],[-15,-40]],[[8385,5760],[16,-18],[18,0],[0,-25],[-13,-25],[-18,-18],[-1,28],[2,30],[-4,28]],[[8485,5776],[8,-66],[-21,16],[0,-20],[7,-37],[-13,-13],[-1,42],[-9,3],[-4,36],[16,-5],[0,22],[-17,45],[27,-1],[7,-22]],[[8375,5830],[-7,-51],[-12,29],[-15,45],[24,-2],[10,-21]],[[8369,6151],[17,-17],[9,15],[2,-15],[-4,-24],[9,-43],[-7,-49],[-16,-19],[-5,-48],[7,-47],[14,-7],[13,7],[34,-32],[-2,-32],[9,-15],[-3,-27],[-22,29],[-10,31],[-7,-22],[-18,36],[-25,-9],[-14,13],[1,25],[9,15],[-8,13],[-4,-21],[-14,34],[-4,26],[-1,56],[11,-19],[3,92],[9,54],[17,0]],[[9329,4655],[-8,-6],[-12,22],[-12,38],[-6,45],[4,6],[3,-18],[8,-13],[14,-38],[13,-20],[-4,-16]],[[9221,4734],[-15,-5],[-4,-17],[-15,-14],[-15,-14],[-14,0],[-23,18],[-16,16],[2,18],[25,-8],[15,4],[5,29],[4,1],[2,-31],[16,4],[8,20],[16,21],[-4,35],[17,1],[6,-9],[-1,-33],[-9,-36]],[[8916,4904],[48,-41],[51,-34],[19,-30],[16,-30],[4,-34],[46,-37],[7,-31],[-25,-7],[6,-39],[25,-39],[18,-62],[15,2],[-1,-27],[22,-10],[-9,-11],[30,-25],[-3,-17],[-18,-4],[-7,16],[-24,6],[-28,9],[-22,38],[-16,32],[-14,52],[-36,26],[-24,-17],[-17,-20],[4,-43],[-22,-20],[-16,9],[-28,3]],[[9253,4792],[-9,-16],[-5,35],[-6,23],[-13,19],[-16,25],[-20,18],[8,14],[15,-17],[9,-13],[12,-14],[11,-25],[11,-19],[3,-30]],[[5392,8233],[19,18],[43,27],[35,20],[28,-10],[2,-14],[27,-1]],[[5546,8273],[34,-7],[51,1]],[[5653,8105],[14,-52],[-3,-17],[-14,-6],[-25,-50],[7,-26],[-6,3]],[[5626,7957],[-26,23],[-20,-8],[-13,6],[-17,-13],[-14,21],[-11,-8],[-2,4]],[[3159,6151],[14,-5],[5,-12],[-7,-15],[-21,1],[-17,-2],[-1,25],[4,9],[23,-1]],[[8628,7562],[4,-10]],[[8632,7552],[-11,3],[-12,-20],[-8,-20],[1,-42],[-14,-13],[-5,-11],[-11,-17],[-18,-10],[-12,-16],[-1,-25],[-3,-7],[11,-9],[15,-26]],[[8504,7288],[-13,11],[-4,-11],[-8,-5],[-1,11],[-7,5],[-8,10],[8,26],[7,7],[-3,11],[7,31],[-2,10],[-16,7],[-13,15]],[[4792,7249],[-11,-15],[-14,8],[-15,-6],[5,46],[-3,36],[-12,6],[-7,22],[2,39],[11,21],[2,24],[6,36],[-1,25],[-5,21],[-1,20]],[[6411,6520],[-2,43],[7,31],[8,6],[8,-18],[1,-35],[-6,-35]],[[6427,6512],[-8,-4],[-8,12]],[[5630,7886],[12,13],[17,-7],[18,0],[13,-14],[10,9],[20,5],[7,14],[12,0]],[[5784,7745],[12,-11],[13,9],[13,-10]],[[5822,7733],[0,-15],[-13,-13],[-9,6],[-7,-71]],[[5629,7671],[-5,10],[6,10],[-7,7],[-8,-13],[-17,17],[-2,25],[-17,14],[-3,18],[-15,24]],[[8989,8056],[28,-105],[-41,19],[-17,-85],[27,-61],[-1,-41],[-21,36],[-18,-46],[-5,50],[3,57],[-3,64],[6,45],[2,79],[-17,58],[3,80],[25,28],[-11,27],[13,8],[7,-39],[10,-57],[-1,-58],[11,-59]],[[5546,8273],[6,26],[38,19]],[[0,9132],[68,-45],[73,-59],[-3,-37],[19,-15],[-6,43],[75,-8],[55,-56],[-28,-26],[-46,-6],[0,-57],[-11,-13],[-26,2],[-22,21],[-36,17],[-7,26],[-28,9],[-31,-7],[-16,20],[6,22],[-33,-14],[13,-28],[-16,-25]],[[0,8896],[0,236]],[[0,9282],[9999,-40],[-30,-3],[-5,19],[-9964,24]],[[0,9282],[4,3],[23,0],[40,-17],[-2,-8],[-29,-14],[-36,-4],[0,40]],[[8988,9383],[-42,-1],[-57,7],[-5,3],[27,23],[34,6],[40,-23],[3,-15]],[[9186,9493],[-32,-23],[-44,5],[-52,23],[7,20],[51,-9],[70,-16]],[[9029,9522],[-22,-44],[-102,1],[-46,-14],[-55,39],[15,40],[37,11],[73,-2],[100,-31]],[[6598,9235],[-17,-5],[-91,8],[-7,26],[-50,16],[-4,32],[28,13],[-1,32],[55,50],[-25,7],[66,52],[-7,27],[62,31],[91,38],[93,11],[48,22],[54,8],[19,-23],[-19,-19],[-98,-29],[-85,-28],[-86,-57],[-42,-57],[-43,-57],[5,-49],[54,-49]],[[0,8896],[9963,-26],[-36,4],[25,-31],[17,-49],[13,-16],[3,-24],[-7,-16],[-52,13],[-78,-44],[-25,-7],[-42,-42],[-40,-36],[-11,-27],[-39,41],[-73,-46],[-12,22],[-27,-26],[-37,8],[-9,-38],[-33,-58],[1,-24],[31,-13],[-4,-86],[-25,-2],[-12,-49],[11,-26],[-48,-30],[-10,-67],[-41,-15],[-9,-60],[-40,-55],[-10,41],[-12,86],[-15,131],[13,82],[23,35],[2,28],[43,13],[50,75],[47,60],[50,48],[23,83],[-34,-5],[-17,-49],[-70,-65],[-23,73],[-72,-20],[-69,-99],[23,-36],[-62,-16],[-43,-6],[2,43],[-43,9],[-35,-29],[-85,10],[-91,-18],[-90,-115],[-106,-139],[43,-8],[14,-37],[27,-13],[18,30],[30,-4],[40,-65],[1,-50],[-21,-59],[-3,-71],[-12,-94],[-42,-86],[-9,-41],[-38,-69],[-38,-68],[-18,-35],[-37,-34],[-17,-1],[-17,29],[-38,-44],[-4,-19]],[[6363,7799],[-12,-35],[-27,-10],[-28,-61],[25,-56],[-2,-40],[30,-70]],[[6109,7624],[-35,49],[-32,23],[-24,34],[20,10],[23,49],[-15,24],[41,24],[-1,13],[-25,-10]],[[6061,7840],[1,26],[14,17],[27,4],[5,20],[-7,33],[12,30],[-1,18],[-41,19],[-16,-1],[-17,28],[-21,-9],[-35,20],[0,12],[-10,26],[-22,3],[-2,18],[7,12],[-18,33],[-29,-5],[-8,3],[-7,-14],[-11,3]],[[5777,8571],[31,33],[-29,28]],[[5863,9167],[29,20],[46,-35],[76,-14],[105,-67],[21,-28],[2,-40],[-31,-31],[-45,-15],[-124,44],[-21,-7],[45,-43],[2,-28],[2,-60],[36,-18],[22,-15],[3,28],[-17,26],[18,22],[67,-37],[24,15],[-19,43],[65,58],[25,-4],[26,-20],[16,40],[-23,35],[14,36],[-21,36],[78,-18],[16,-34],[-35,-7],[0,-33],[22,-20],[43,13],[7,38],[58,28],[97,50],[20,-3],[-27,-35],[35,-7],[19,21],[52,1],[42,25],[31,-36],[32,39],[-29,35],[14,19],[82,-18],[39,-18],[100,-68],[19,31],[-28,31],[-1,13],[-34,6],[10,28],[-15,46],[-1,19],[51,53],[18,54],[21,11],[74,-15],[5,-33],[-26,-48],[17,-19],[9,-41],[-6,-81],[31,-36],[-12,-40],[-55,-84],[32,-8],[11,21],[31,15],[7,29],[24,29],[-16,33],[13,39],[-31,5],[-6,33],[22,59],[-36,48],[50,40],[-7,42],[14,2],[15,-33],[-11,-57],[29,-11],[-12,43],[46,23],[58,3],[51,-34],[-25,49],[-2,63],[48,12],[67,-2],[60,7],[-23,31],[33,39],[31,2],[54,29],[74,8],[9,16],[73,6],[23,-14],[62,32],[51,-1],[8,25],[26,25],[66,25],[48,-19],[-38,-15],[63,-9],[7,-29],[25,14],[82,-1],[62,-29],[23,-22],[-7,-30],[-31,-18],[-73,-33],[-21,-17],[35,-8],[41,-15],[25,11],[14,-38],[12,15],[44,10],[90,-10],[6,-28],[116,-9],[2,46],[59,-11],[44,1],[45,-32],[13,-37],[-17,-25],[35,-47],[44,-24],[27,62],[44,-26],[48,16],[53,-18],[21,16],[45,-8],[-20,55],[37,25],[251,-38],[24,-35],[72,-45],[112,11],[56,-10],[23,-24],[-4,-44],[35,-16],[37,12],[49,1],[52,-11],[53,6],[49,-52],[34,19],[-23,37],[13,27],[88,-17],[58,4],[80,-29],[-9960,-25]],[[7918,9684],[-157,-23],[51,77],[23,7],[21,-4],[70,-33],[-8,-24]],[[6420,9816],[-37,-8],[-25,-4],[-4,-10],[-33,-10],[-30,14],[16,19],[-62,2],[54,10],[43,1],[5,-16],[16,14],[26,10],[42,-13],[-11,-9]],[[7775,9718],[-60,-8],[-78,17],[-46,23],[-21,42],[-38,12],[72,40],[60,14],[54,-30],[64,-57],[-7,-53]],[[5844,4990],[11,-33],[-1,-35],[-8,-7]],[[5821,4978],[7,-6],[16,18]],[[4526,6298],[1,25]],[[6188,6023],[-4,26],[-8,17],[-2,24],[-15,21],[-15,50],[-7,48],[-20,40],[-12,10],[-18,56],[-4,41],[2,35],[-16,66],[-13,23],[-15,12],[-10,34],[2,13],[-8,31],[-8,13],[-11,44],[-17,48],[-14,40],[-14,0],[5,33],[1,20],[3,24]],[[6344,6744],[11,-51],[14,-13],[5,-21],[18,-25],[2,-24],[-3,-20],[4,-20],[8,-16],[4,-20],[4,-14]],[[6427,6512],[5,-22]],[[6444,6180],[-80,-23],[-26,-26],[-20,-62],[-13,-10],[-7,20],[-11,-3],[-27,6],[-5,5],[-32,-1],[-7,-5],[-12,15],[-7,-29],[3,-25],[-12,-19]],[[5943,5617],[-4,1],[0,29],[-3,20],[-14,24],[-4,42],[4,44],[-13,4],[-2,-13],[-17,-3],[7,-17],[2,-36],[-15,-32],[-14,-43],[-14,-6],[-23,34],[-11,-12],[-3,-17],[-14,-11],[-1,-12],[-28,0],[-3,12],[-20,2],[-10,-10],[-8,5],[-14,34],[-5,17],[-20,-9],[-8,-27],[-7,-53],[-10,-11],[-8,-6]],[[5663,5567],[-2,2]],[[5635,5716],[0,14],[-10,17],[-1,35],[-5,23],[-10,-4],[3,22],[7,25],[-3,24],[9,18],[-6,14],[7,36],[13,44],[24,-4],[-1,234]],[[6023,6357],[9,-58],[-6,-10],[4,-61],[11,-71],[10,-14],[15,-22]],[[5943,5624],[0,-7]],[[5943,5617],[0,-46]],[[5944,5309],[-17,-28],[-20,1],[-22,-14],[-18,13],[-11,-16]],[[5682,5544],[-19,23]],[[4535,5861],[-11,46],[-14,21],[12,11],[14,41],[6,31]],[[4536,5789],[-4,45]],[[9502,4438],[8,-20],[-19,0],[-11,37],[17,-15],[5,-2]],[[9467,4474],[-11,-1],[-17,6],[-5,9],[1,23],[19,-9],[9,-12],[4,-16]],[[9490,4490],[-4,-11],[-21,52],[-5,35],[9,0],[10,-47],[11,-29]],[[9440,4565],[1,-12],[-22,25],[-15,21],[-10,20],[4,6],[13,-14],[23,-27],[6,-19]],[[9375,4623],[-5,-3],[-13,14],[-11,24],[1,10],[17,-25],[11,-20]],[[4682,5458],[-8,5],[-20,24],[-14,31],[-5,22],[-3,43]],[[2561,5848],[-3,-14],[-16,1],[-10,6],[-12,12],[-15,3],[-8,13]],[[6198,5735],[9,-11],[5,-25],[13,-24],[14,-1],[26,16],[30,7],[25,18],[13,4],[10,11],[16,2]],[[6359,5732],[0,-1],[0,-25],[0,-59],[0,-31],[-13,-36],[-19,-50]],[[6359,5732],[9,1],[13,9],[14,6],[14,20],[10,0],[1,-16],[-3,-35],[0,-31],[-6,-21],[-7,-64],[-14,-66],[-17,-75],[-24,-87],[-23,-66],[-33,-81],[-28,-48],[-42,-58],[-25,-45],[-31,-72],[-6,-31],[-6,-14]],[[3412,5410],[34,-11],[2,10],[23,4],[30,-15]],[[3489,5306],[10,-35],[-4,-25]],[[5626,7957],[-8,-15],[-5,-24]],[[5380,7746],[7,5]],[[5663,8957],[-47,-17],[-27,-41],[4,-36],[-44,-48],[-54,-50],[-20,-84],[20,-41],[26,-33],[-25,-67],[-29,-14],[-11,-99],[-15,-55],[-34,6],[-16,-47],[-32,-3],[-9,56],[-23,67],[-21,84]],[[5890,3478],[-5,-26],[-17,-6],[-16,32],[0,20],[7,22],[3,17],[8,5],[14,-11]],[[5999,7104],[-2,45],[7,25]],[[6004,7174],[7,13],[7,13],[2,33],[9,-12],[31,17],[14,-12],[23,1],[32,22],[15,-1],[32,9]],[[5051,5420],[-22,-12]],[[7849,5777],[-25,28],[-24,-2],[4,47],[-24,0],[-2,-65],[-15,-87],[-10,-52],[2,-43],[18,-2],[12,-53],[5,-52],[15,-33],[17,-7],[14,-31]],[[7779,5439],[-11,23],[-4,29],[-15,34],[-14,28],[-4,-35],[-5,33],[3,37],[8,56]],[[6883,7252],[16,60],[-6,44],[-20,14],[7,26],[23,-3],[13,33],[9,38],[37,13],[-6,-27],[4,-17],[12,2]],[[6497,7255],[-5,42],[4,62],[-22,20],[8,40],[-19,4],[6,49],[26,-14],[25,19],[-20,35],[-8,34],[-23,-15],[-3,-43],[-8,38]],[[6554,7498],[31,1],[-4,29],[24,21],[23,34],[37,-31],[3,-47],[11,-12],[30,2],[9,-10],[14,-61],[32,-41],[18,-28],[29,-29],[37,-25],[-1,-36]],[[8471,4532],[3,14],[24,13],[19,2],[9,8],[10,-8],[-10,-16],[-29,-25],[-23,-17]],[[3286,5693],[16,8],[6,-2],[-1,-44],[-23,-7],[-5,6],[8,16],[-1,23]],[[5233,7240],[31,24],[19,-7],[-1,-30],[24,22],[2,-12],[-14,-29],[0,-27],[9,-15],[-3,-51],[-19,-29],[6,-33],[14,-1],[7,-28],[11,-9]],[[6004,7174],[-11,27],[11,22],[-17,-5],[-23,13],[-19,-34],[-43,-6],[-22,31],[-30,2],[-6,-24],[-20,-7],[-26,31],[-31,-1],[-16,59],[-21,33],[14,46],[-18,28],[31,56],[43,3],[12,45],[53,-8],[33,38],[32,17],[46,1],[49,-42],[40,-22],[32,9],[24,-6],[33,31]],[[5777,7539],[3,-23],[25,-19],[-5,-14],[-33,-3],[-12,-19],[-23,-31],[-9,27],[0,12]],[[8382,6499],[-17,-95],[-12,-49],[-14,50],[-4,44],[17,58],[22,45],[13,-18],[-5,-35]],[[6088,4781],[-12,-73],[1,-33],[18,-22],[1,-15],[-8,-36],[2,-18],[-2,-28],[10,-37],[11,-58],[10,-13]],[[5909,4512],[-15,18],[-18,10],[-11,10],[-12,15]],[[5844,4990],[10,8],[31,-1],[56,4]],[[6061,7840],[-22,-5],[-18,-19],[-26,-3],[-24,-22],[1,-37],[14,-14],[28,4],[-5,-21],[-31,-11],[-37,-34],[-16,12],[6,28],[-30,17],[5,12],[26,19],[-8,14],[-43,15],[-2,22],[-25,-8],[-11,-32],[-21,-44]],[[3517,3063],[-12,-38],[-31,-32],[-21,11],[-15,-6],[-26,25],[-18,-1],[-17,32]],[[679,6185],[-4,-10],[-7,8],[1,17],[-4,21],[1,7],[5,10],[-2,11],[1,6],[3,-1],[10,-10],[5,-5],[5,-8],[7,-21],[-1,-3],[-11,-13],[-9,-9]],[[664,6277],[-9,-4],[-5,12],[-3,5],[0,4],[3,5],[9,-6],[8,-9],[-3,-7]],[[646,6309],[-1,-7],[-15,2],[2,7],[14,-2]],[[621,6317],[-2,-3],[-2,1],[-9,2],[-4,13],[-1,2],[7,8],[3,-3],[8,-20]],[[574,6356],[-4,-6],[-9,11],[1,4],[5,6],[6,-1],[1,-14]],[[3135,7724],[5,-19],[-30,-29],[-29,-20],[-29,-18],[-15,-35],[-4,-13],[-1,-31],[10,-32],[11,-1],[-3,21],[8,-13],[-2,-17],[-19,-9],[-13,1],[-20,-10],[-12,-3],[-17,-3],[-23,-17],[41,11],[8,-11],[-39,-18],[-17,0],[0,7],[-8,-16],[8,-3],[-6,-43],[-20,-45],[-2,15],[-6,3],[-9,15],[5,-32],[7,-10],[1,-23],[-9,-23],[-16,-47],[-2,3],[8,40],[-14,22],[-3,49],[-5,-25],[5,-38],[-18,10],[19,-19],[1,-57],[8,-4],[3,-20],[4,-59],[-17,-44],[-29,-18],[-18,-34],[-14,-4],[-14,-22],[-4,-20],[-31,-38],[-16,-28],[-13,-35],[-4,-42],[5,-41],[9,-51],[13,-41],[0,-26],[13,-69],[-1,-39],[-1,-23],[-7,-36],[-8,-8],[-14,7],[-4,26],[-11,14],[-15,51],[-13,45],[-4,23],[6,39],[-8,33],[-22,49],[-10,9],[-28,-27],[-5,3],[-14,28],[-17,14],[-32,-7],[-24,7],[-21,-5],[-12,-9],[5,-15],[0,-24],[5,-12],[-5,-8],[-10,9],[-11,-11],[-20,2],[-20,31],[-25,-8],[-20,14],[-17,-4],[-24,-14],[-25,-44],[-27,-25],[-16,-28],[-6,-27],[0,-41],[1,-28],[5,-20]],[[1746,6980],[-4,30],[-18,34],[-13,7],[-3,17],[-16,3],[-10,16],[-26,6],[-7,9],[-3,32],[-27,60],[-23,82],[1,14],[-13,19],[-21,50],[-4,48],[-15,32],[6,49],[-1,51],[-8,45],[10,56],[4,53],[3,54],[-5,79],[-9,51],[-8,27],[4,12],[40,-20],[15,-56],[7,15],[-5,49],[-9,48]],[[750,8432],[-28,-23],[-14,15],[-4,28],[25,21],[15,9],[18,-4],[12,-18],[-24,-28]],[[401,8597],[-18,-9],[-18,11],[-17,16],[28,10],[22,-6],[3,-22]],[[230,8826],[17,-12],[17,6],[23,-15],[27,-8],[-2,-7],[-21,-12],[-21,13],[-11,11],[-24,-4],[-7,5],[2,23]],[[1374,8295],[-15,22],[-25,19],[-8,52],[-36,47],[-15,56],[-26,4],[-44,2],[-33,17],[-57,61],[-27,11],[-49,21],[-38,-5],[-55,27],[-33,25],[-30,-12],[5,-41],[-15,-4],[-32,-12],[-25,-20],[-30,-13],[-4,35],[12,58],[30,18],[-8,15],[-35,-33],[-19,-39],[-40,-42],[20,-29],[-26,-42],[-30,-25],[-28,-18],[-7,-26],[-43,-31],[-9,-28],[-32,-25],[-20,5],[-25,-17],[-29,-20],[-23,-20],[-47,-16],[-5,9],[31,28],[27,18],[29,33],[35,6],[14,25],[38,35],[6,12],[21,21],[5,44],[14,35],[-32,-18],[-9,11],[-15,-22],[-18,30],[-8,-21],[-10,29],[-28,-23],[-17,0],[-3,35],[5,21],[-17,22],[-37,-12],[-23,28],[-19,14],[0,34],[-22,25],[11,34],[23,33],[10,30],[22,4],[19,-9],[23,28],[20,-5],[21,19],[-5,27],[-16,10],[21,23],[-17,-1],[-30,-13],[-8,-13],[-22,13],[-39,-6],[-41,14],[-12,24],[-35,34],[39,25],[62,29],[23,0],[-4,-30],[59,2],[-23,37],[-34,23],[-20,29],[-26,25],[-38,19],[15,31],[49,2],[35,27],[7,29],[28,28],[28,6],[52,27],[26,-4],[42,31],[42,-12],[21,-27],[12,11],[47,-3],[-2,-14],[43,-10],[28,6],[59,-18],[53,-6],[21,-8],[37,10],[42,-18],[31,-8]],[[3018,5753],[-1,-14],[-16,-7],[9,-26],[0,-31],[-12,-35],[10,-47],[12,4],[6,43],[-8,21],[-2,45],[35,24],[-4,27],[10,19],[10,-41],[19,-1],[18,-33],[1,-20],[25,0],[30,6],[16,-27],[21,-7],[16,18],[0,15],[34,4],[34,1],[-24,-18],[10,-28],[22,-4],[21,-29],[4,-48],[15,2],[11,-14]],[[8001,6331],[-37,-51],[-24,-56],[-6,-41],[22,-62],[25,-77],[26,-37],[17,-47],[12,-109],[-3,-104],[-24,-39],[-31,-38],[-23,-49],[-35,-55],[-10,37],[8,40],[-21,34]],[[9661,4085],[-9,-8],[-9,26],[1,16],[17,-34]],[[9641,4175],[4,-47],[-7,7],[-6,-3],[-4,16],[0,45],[13,-18]],[[6475,6041],[-21,-16],[-5,-26],[-1,-20],[-27,-25],[-45,-28],[-24,-41],[-13,-3],[-8,3],[-16,-25],[-18,-11],[-23,-3],[-7,-3],[-6,-16],[-8,-4],[-4,-15],[-14,1],[-9,-8],[-19,3],[-7,35],[1,32],[-5,17],[-5,44],[-8,24],[5,3],[-2,27],[3,12],[-1,25]],[[5817,3752],[11,0],[14,-10],[9,7],[15,-6]],[[5911,3478],[-7,-43],[-3,-49],[-7,-27],[-19,-30],[-5,-8],[-12,-30],[-8,-31],[-16,-42],[-31,-61],[-20,-36],[-21,-26],[-29,-23],[-14,-3],[-3,-17],[-17,9],[-14,-11],[-30,11],[-17,-7],[-12,3],[-28,-23],[-24,-10],[-17,-22],[-13,-1],[-11,21],[-10,1],[-12,26],[-1,-8],[-4,16],[0,34],[-9,40],[9,11],[0,45],[-19,55],[-14,50],[0,1],[-20,76]],[[5840,4141],[-21,-8],[-15,-23],[-4,-21],[-10,-4],[-24,-49],[-15,-38],[-10,-2],[-9,7],[-31,7]]],transform:{scale:[.036003600360036005,.016927109510951093],translate:[-180,-85.609038]}},l.prototype.usaTopo="__USA__",l.prototype.latLngToXY=function(a,b){return this.projection([b,a])
+},l.prototype.addLayer=function(a,b,c){var d;return d=c?this.svg.insert("g",":first-child"):this.svg.append("g"),d.attr("id",b||"").attr("class",a||"")},l.prototype.updateChoropleth=function(a){var b=this.svg;for(var c in a)if(a.hasOwnProperty(c)){var d,e=a[c];if(!c)continue;d="string"==typeof e?e:"string"==typeof e.color?e.color:this.options.fills[e.fillKey],e===Object(e)&&(this.options.data[c]=k(e,this.options.data[c]||{}),this.svg.select("."+c).attr("data-info",JSON.stringify(this.options.data[c]))),b.selectAll("."+c).transition().style("fill",d)}},l.prototype.updatePopup=function(a,b,c){var d=this;a.on("mousemove",null),a.on("mousemove",function(){var e=m.mouse(d.options.element);m.select(d.svg[0][0].parentNode).select(".datamaps-hoverover").style("top",e[1]+30+"px").html(function(){var d=JSON.parse(a.attr("data-info"));return c.popupTemplate(b,d)}).style("left",e[0]+"px")}),m.select(d.svg[0][0].parentNode).select(".datamaps-hoverover").style("display","block")},l.prototype.addPlugin=function(a,b){var c=this;"undefined"==typeof l.prototype[a]&&(l.prototype[a]=function(d,e,f,g){var h;"undefined"==typeof g&&(g=!1),"function"==typeof e&&(f=e,e=void 0),e=k(e||{},c.options[a+"Config"]),!g&&this.options[a+"Layer"]?(h=this.options[a+"Layer"],e=e||this.options[a+"Options"]):(h=this.addLayer(a),this.options[a+"Layer"]=h,this.options[a+"Options"]=e),b.apply(this,[h,d,e]),f&&f(h)})},"function"==typeof define&&define.amd?define("datamaps",function(a){return m=a("d3"),n=a("topojson"),l}):window.Datamap=window.Datamaps=l,window.jQuery&&(window.jQuery.fn.datamaps=function(a,b){a=a||{},a.element=this[0];var c=new l(a);return"function"==typeof b&&b(c,a),this})}(); \ No newline at end of file
diff --git a/modules/http/static/dygraph-combined.js b/modules/http/static/dygraph-combined.js
new file mode 100644
index 0000000..0ec8abb
--- /dev/null
+++ b/modules/http/static/dygraph-combined.js
@@ -0,0 +1,6 @@
+/*! @license Copyright 2017 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Dygraph=t()}}(function(){return function t(e,a,i){function n(o,s){if(!a[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var h=new Error("Cannot find module '"+o+"'");throw h.code="MODULE_NOT_FOUND",h}var u=a[o]={exports:{}};e[o][0].call(u.exports,function(t){var a=e[o][1][t];return n(a||t)},u,u.exports,t,e,a,i)}return a[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)n(i[o]);return n}({1:[function(t,e,a){function i(){throw new Error("setTimeout has not been defined")}function n(){throw new Error("clearTimeout has not been defined")}function r(t){if(d===setTimeout)return setTimeout(t,0);if((d===i||!d)&&setTimeout)return d=setTimeout,setTimeout(t,0);try{return d(t,0)}catch(e){try{return d.call(null,t,0)}catch(e){return d.call(this,t,0)}}}function o(t){if(c===clearTimeout)return clearTimeout(t);if((c===n||!c)&&clearTimeout)return c=clearTimeout,clearTimeout(t);try{return c(t)}catch(e){try{return c.call(null,t)}catch(e){return c.call(this,t)}}}function s(){_&&g&&(_=!1,g.length?f=g.concat(f):v=-1,f.length&&l())}function l(){if(!_){var t=r(s);_=!0;for(var e=f.length;e;){for(g=f,f=[];++v<e;)g&&g[v].run();v=-1,e=f.length}g=null,_=!1,o(t)}}function h(t,e){this.fun=t,this.array=e}function u(){}var d,c,p=e.exports={};!function(){try{d="function"==typeof setTimeout?setTimeout:i}catch(t){d=i}try{c="function"==typeof clearTimeout?clearTimeout:n}catch(t){c=n}}();var g,f=[],_=!1,v=-1;p.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var a=1;a<arguments.length;a++)e[a-1]=arguments[a];f.push(new h(t,e)),1!==f.length||_||r(l)},h.prototype.run=function(){this.fun.apply(null,this.array)},p.title="browser",p.browser=!0,p.env={},p.argv=[],p.version="",p.versions={},p.on=u,p.addListener=u,p.once=u,p.off=u,p.removeListener=u,p.removeAllListeners=u,p.emit=u,p.prependListener=u,p.prependOnceListener=u,p.listeners=function(t){return[]},p.binding=function(t){throw new Error("process.binding is not supported")},p.cwd=function(){return"/"},p.chdir=function(t){throw new Error("process.chdir is not supported")},p.umask=function(){return 0}},{}],2:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o=[],s=a.get("logscale"),l=0;l<t.length;l++)i=t[l][0],r=t[l][e],s&&null!==r&&(r[0]<=0||r[1]<=0||r[2]<=0)&&(r=null),null!==r?(n=r[1],null===n||isNaN(n)?o.push([i,n,[n,n]]):o.push([i,n,[r[0],r[2]]])):o.push([i,null,[null,null]]);return o},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u=[];for(n=0,o=0,r=0,s=0,l=0;l<t.length;l++){if(i=t[l][1],h=t[l][2],u[l]=t[l],null===i||isNaN(i)||(n+=h[0],o+=i,r+=h[1],s+=1),l-e>=0){var d=t[l-e];null===d[1]||isNaN(d[1])||(n-=d[2][0],o-=d[1],r-=d[2][1],s-=1)}u[l]=s?[t[l][0],1*o/s,[1*n/s,1*r/s]]:[t[l][0],null,[null,null]]}return u},a.default=r,e.exports=a.default},{"./bars":5}],3:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("logscale"),u=0;u<t.length;u++)i=t[u][0],o=t[u][e],h&&null!==o&&(o[0]<=0||o[0]-l*o[1]<=0)&&(o=null),null!==o?(n=o[0],null===n||isNaN(n)?s.push([i,n,[n,n,n]]):(r=l*o[1],s.push([i,n,[n-r,n+r,o[1]]]))):s.push([i,null,[null,null,null]]);return s},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u,d,c=[],p=a.get("sigma");for(i=0;i<t.length;i++){for(s=0,u=0,l=0,n=Math.max(0,i-e+1);n<i+1;n++)null===(r=t[n][1])||isNaN(r)||(l++,s+=r,u+=Math.pow(t[n][2][2],2));l?(h=Math.sqrt(u)/l,d=s/l,c[i]=[t[i][0],d,[d-p*h,d+p*h]]):(o=1==e?t[i][1]:null,c[i]=[t[i][0],o,[o,o]])}return c},a.default=r,e.exports=a.default},{"./bars":5}],4:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h,u,d=[],c=a.get("sigma"),p=a.get("logscale"),g=0;g<t.length;g++)i=t[g][0],r=t[g][e],p&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?d.push([i,o,[o,o,o,s]]):(l=s?o/s:0,h=s?c*Math.sqrt(l*(1-l)/s):1,u=100*h,n=100*l,d.push([i,n,[n-u,n+u,o,s]]))):d.push([i,null,[null,null,null,null]]);return d},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("wilsonInterval"),u=0,d=0;for(r=0;r<t.length;r++){u+=t[r][2][2],d+=t[r][2][3],r-e>=0&&(u-=t[r-e][2][2],d-=t[r-e][2][3]);var c=t[r][0],p=d?u/d:0;if(h)if(d){var g=p<0?0:p,f=d,_=l*Math.sqrt(g*(1-g)/f+l*l/(4*f*f)),v=1+l*l/d;i=(g+l*l/(2*d)-_)/v,n=(g+l*l/(2*d)+_)/v,s[r]=[c,100*g,[100*i,100*n]]}else s[r]=[c,0,[0,0]];else o=d?l*Math.sqrt(p*(1-p)/d):1,s[r]=[c,100*p,[100*(p-o),100*(p+o)]]}return s},a.default=r,e.exports=a.default},{"./bars":5}],5:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=i(n),o=t("../dygraph-layout"),s=i(o),l=function(){r.default.call(this)};l.prototype=new r.default,l.prototype.extractSeries=function(t,e,a){},l.prototype.rollingAverage=function(t,e,a){},l.prototype.onPointsCreated_=function(t,e){for(var a=0;a<t.length;++a){var i=t[a],n=e[a];n.y_top=NaN,n.y_bottom=NaN,n.yval_minus=r.default.parseFloat(i[2][0]),n.yval_plus=r.default.parseFloat(i[2][1])}},l.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=t.length-1,s=0;s<=o;s++)if(null!==(i=t[s][1])&&!isNaN(i)){var l=t[s][2][0],h=t[s][2][1];l>i&&(l=i),h<i&&(h=i),(null===r||h>r)&&(r=h),(null===n||l<n)&&(n=l)}return[n,r]},l.prototype.onLineEvaluated=function(t,e,a){for(var i,n=0;n<t.length;n++)i=t[n],i.y_top=s.default.calcYNormal_(e,i.yval_minus,a),i.y_bottom=s.default.calcYNormal_(e,i.yval_plus,a)},a.default=l,e.exports=a.default},{"../dygraph-layout":13,"./datahandler":6}],6:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){},n=i;n.X=0,n.Y=1,n.EXTRAS=2,n.prototype.extractSeries=function(t,e,a){},n.prototype.seriesToPoints=function(t,e,a){for(var i=[],r=0;r<t.length;++r){var o=t[r],s=o[1],l=null===s?null:n.parseFloat(s),h={x:NaN,y:NaN,xval:n.parseFloat(o[0]),yval:l,name:e,idx:r+a};i.push(h)}return this.onPointsCreated_(t,i),i},n.prototype.onPointsCreated_=function(t,e){},n.prototype.rollingAverage=function(t,e,a){},n.prototype.getExtremeYValues=function(t,e,a){},n.prototype.onLineEvaluated=function(t,e,a){},n.parseFloat=function(t){return null===t?NaN:t},a.default=i,e.exports=a.default},{}],7:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=(i(n),t("./default")),o=i(r),s=function(){};s.prototype=new o.default,s.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h=[],u=a.get("logscale"),d=0;d<t.length;d++)i=t[d][0],r=t[d][e],u&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?h.push([i,o,[o,s]]):(l=s?o/s:0,n=100*l,h.push([i,n,[o,s]]))):h.push([i,null,[null,null]]);return h},s.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n=[],r=0,o=0;for(i=0;i<t.length;i++){r+=t[i][2][0],o+=t[i][2][1],i-e>=0&&(r-=t[i-e][2][0],o-=t[i-e][2][1]);var s=t[i][0],l=o?r/o:0;n[i]=[s,100*l]}return n},a.default=s,e.exports=a.default},{"./datahandler":6,"./default":8}],8:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./datahandler"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i=[],n=a.get("logscale"),r=0;r<t.length;r++){var o=t[r][0],s=t[r][e];n&&s<=0&&(s=null),i.push([o,s])}return i},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l=[];if(1==e)return t;for(i=0;i<t.length;i++){for(o=0,s=0,n=Math.max(0,i-e+1);n<i+1;n++)null===(r=t[n][1])||isNaN(r)||(s++,o+=t[n][1]);l[i]=s?[t[i][0],o/s]:[t[i][0],null]}return l},r.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=t.length-1,s=0;s<=o;s++)null===(i=t[s][1])||isNaN(i)||((null===r||i>r)&&(r=i),(null===n||i<n)&&(n=i));return[n,r]},a.default=r,e.exports=a.default},{"./datahandler":6}],9:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=t("./dygraph"),o=function(t){return t&&t.__esModule?t:{default:t}}(r),s=function(t,e,a,i){if(this.dygraph_=t,this.layout=i,this.element=e,this.elementContext=a,this.height=t.height_,this.width=t.width_,!n.isCanvasSupported(this.element))throw"Canvas is not supported.";this.area=i.getPlotArea();var r=this.dygraph_.canvas_ctx_;r.beginPath(),r.rect(this.area.x,this.area.y,this.area.w,this.area.h),r.clip(),r=this.dygraph_.hidden_ctx_,r.beginPath(),r.rect(this.area.x,this.area.y,this.area.w,this.area.h),r.clip()};s.prototype.clear=function(){this.elementContext.clearRect(0,0,this.width,this.height)},s.prototype.render=function(){this._updatePoints(),this._renderLineChart()},s._getIteratorPredicate=function(t){return t?s._predicateThatSkipsEmptyPoints:null},s._predicateThatSkipsEmptyPoints=function(t,e){return null!==t[e].yval},s._drawStyledLine=function(t,e,a,i,r,o,l){var h=t.dygraph,u=h.getBooleanOption("stepPlot",t.setName);n.isArrayLike(i)||(i=null);var d=h.getBooleanOption("drawGapEdgePoints",t.setName),c=t.points,p=t.setName,g=n.createIterator(c,0,c.length,s._getIteratorPredicate(h.getBooleanOption("connectSeparatedPoints",p))),f=i&&i.length>=2,_=t.drawingContext;_.save(),f&&_.setLineDash&&_.setLineDash(i);var v=s._drawSeries(t,g,a,l,r,d,u,e);s._drawPointsOnLine(t,v,o,e,l),f&&_.setLineDash&&_.setLineDash([]),_.restore()},s._drawSeries=function(t,e,a,i,n,r,o,s){var l,h,u=null,d=null,c=null,p=[],g=!0,f=t.drawingContext;f.beginPath(),f.strokeStyle=s,f.lineWidth=a;for(var _=e.array_,v=e.end_,y=e.predicate_,x=e.start_;x<v;x++){if(h=_[x],y){for(;x<v&&!y(_,x);)x++;if(x==v)break;h=_[x]}if(null===h.canvasy||h.canvasy!=h.canvasy)o&&null!==u&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),u=d=null;else{if(l=!1,r||null===u){e.nextIdx_=x,e.next(),c=e.hasNext?e.peek.canvasy:null;var m=null===c||c!=c;l=null===u&&m,r&&(!g&&null===u||e.hasNext&&m)&&(l=!0)}null!==u?a&&(o&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),f.lineTo(h.canvasx,h.canvasy)):f.moveTo(h.canvasx,h.canvasy),(n||l)&&p.push([h.canvasx,h.canvasy,h.idx]),u=h.canvasx,d=h.canvasy}g=!1}return f.stroke(),p},s._drawPointsOnLine=function(t,e,a,i,n){for(var r=t.drawingContext,o=0;o<e.length;o++){var s=e[o];r.save(),a.call(t.dygraph,t.dygraph,t.setName,r,s[0],s[1],i,n,s[2]),r.restore()}},s.prototype._updatePoints=function(){for(var t=this.layout.points,e=t.length;e--;)for(var a=t[e],i=a.length;i--;){var n=a[i];n.canvasx=this.area.w*n.x+this.area.x,n.canvasy=this.area.h*n.y+this.area.y}},s.prototype._renderLineChart=function(t,e){var a,i,r=e||this.elementContext,o=this.layout.points,s=this.layout.setNames;this.colors=this.dygraph_.colorsMap_;var l=this.dygraph_.getOption("plotter"),h=l;n.isArrayLike(h)||(h=[h]);var u={};for(a=0;a<s.length;a++){i=s[a];var d=this.dygraph_.getOption("plotter",i);d!=l&&(u[i]=d)}for(a=0;a<h.length;a++)for(var c=h[a],p=a==h.length-1,g=0;g<o.length;g++)if(i=s[g],!t||i==t){var f=o[g],_=c;if(i in u){if(!p)continue;_=u[i]}var v=this.colors[i],y=this.dygraph_.getOption("strokeWidth",i);r.save(),r.strokeStyle=v,r.lineWidth=y,_({points:f,setName:i,drawingContext:r,color:v,strokeWidth:y,dygraph:this.dygraph_,axis:this.dygraph_.axisPropertiesForSeries(i),plotArea:this.area,seriesIndex:g,seriesCount:o.length,singleSeriesName:t,allSeriesPoints:o}),r.restore()}},s._Plotters={linePlotter:function(t){s._linePlotter(t)},fillPlotter:function(t){s._fillPlotter(t)},errorPlotter:function(t){s._errorPlotter(t)}},s._linePlotter=function(t){var e=t.dygraph,a=t.setName,i=t.strokeWidth,r=e.getNumericOption("strokeBorderWidth",a),o=e.getOption("drawPointCallback",a)||n.Circles.DEFAULT,l=e.getOption("strokePattern",a),h=e.getBooleanOption("drawPoints",a),u=e.getNumericOption("pointSize",a);r&&i&&s._drawStyledLine(t,e.getOption("strokeBorderColor",a),i+2*r,l,h,o,u),s._drawStyledLine(t,t.color,i,l,h,o,u)},s._errorPlotter=function(t){var e=t.dygraph,a=t.setName;if(e.getBooleanOption("errorBars")||e.getBooleanOption("customBars")){e.getBooleanOption("fillGraph",a)&&console.warn("Can't use fillGraph option with error bars");var i,r=t.drawingContext,o=t.color,l=e.getNumericOption("fillAlpha",a),h=e.getBooleanOption("stepPlot",a),u=t.points,d=n.createIterator(u,0,u.length,s._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",a))),c=NaN,p=NaN,g=[-1,-1],f=n.toRGB_(o),_="rgba("+f.r+","+f.g+","+f.b+","+l+")";r.fillStyle=_,r.beginPath();for(var v=function(t){return null===t||void 0===t||isNaN(t)};d.hasNext;){var y=d.next();!h&&v(y.y)||h&&!isNaN(p)&&v(p)?c=NaN:(i=[y.y_bottom,y.y_top],h&&(p=y.y),isNaN(i[0])&&(i[0]=y.y),isNaN(i[1])&&(i[1]=y.y),i[0]=t.plotArea.h*i[0]+t.plotArea.y,i[1]=t.plotArea.h*i[1]+t.plotArea.y,isNaN(c)||(h?(r.moveTo(c,g[0]),r.lineTo(y.canvasx,g[0]),r.lineTo(y.canvasx,g[1])):(r.moveTo(c,g[0]),r.lineTo(y.canvasx,i[0]),r.lineTo(y.canvasx,i[1])),r.lineTo(c,g[1]),r.closePath()),g=i,c=y.canvasx)}r.fill()}},s._fastCanvasProxy=function(t){var e=[],a=null,i=null,n=0,r=function(t){if(!(e.length<=1)){for(var a=e.length-1;a>0;a--){var i=e[a];if(2==i[0]){var n=e[a-1];n[1]==i[1]&&n[2]==i[2]&&e.splice(a,1)}}for(var a=0;a<e.length-1;){var i=e[a];2==i[0]&&2==e[a+1][0]?e.splice(a,1):a++}if(e.length>2&&!t){var r=0;2==e[0][0]&&r++;for(var o=null,s=null,a=r;a<e.length;a++){var i=e[a];if(1==i[0])if(null===o&&null===s)o=a,s=a;else{var l=i[2];l<e[o][2]?o=a:l>e[s][2]&&(s=a)}}var h=e[o],u=e[s];e.splice(r,e.length-r),o<s?(e.push(h),e.push(u)):o>s?(e.push(u),e.push(h)):e.push(h)}}},o=function(a){r(a);for(var o=0,s=e.length;o<s;o++){var l=e[o];1==l[0]?t.lineTo(l[1],l[2]):2==l[0]&&t.moveTo(l[1],l[2])}e.length&&(i=e[e.length-1][1]),n+=e.length,e=[]},s=function(t,n,r){var s=Math.round(n);if(null===a||s!=a){var l=a-i>1,h=s-a>1;o(l||h),a=s}e.push([t,n,r])};return{moveTo:function(t,e){s(2,t,e)},lineTo:function(t,e){s(1,t,e)},stroke:function(){o(!0),t.stroke()},fill:function(){o(!0),t.fill()},beginPath:function(){o(!0),t.beginPath()},closePath:function(){o(!0),t.closePath()},_count:function(){return n}}},s._fillPlotter=function(t){if(!t.singleSeriesName&&0===t.seriesIndex){for(var e=t.dygraph,a=e.getLabels().slice(1),i=a.length;i>=0;i--)e.visibility()[i]||a.splice(i,1);if(function(){for(var t=0;t<a.length;t++)if(e.getBooleanOption("fillGraph",a[t]))return!0;return!1}())for(var r,l,h=t.plotArea,u=t.allSeriesPoints,d=u.length,c=e.getBooleanOption("stackedGraph"),p=e.getColors(),g={},f=function(t,e,a,i){if(t.lineTo(e,a),c)for(var n=i.length-1;n>=0;n--){var r=i[n];t.lineTo(r[0],r[1])}},_=d-1;_>=0;_--){var v=t.drawingContext,y=a[_];if(e.getBooleanOption("fillGraph",y)){var x=e.getNumericOption("fillAlpha",y),m=e.getBooleanOption("stepPlot",y),b=p[_],w=e.axisPropertiesForSeries(y),A=1+w.minyval*w.yscale;A<0?A=0:A>1&&(A=1),A=h.h*A+h.y;var O,D=u[_],E=n.createIterator(D,0,D.length,s._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",y))),L=NaN,T=[-1,-1],S=n.toRGB_(b),P="rgba("+S.r+","+S.g+","+S.b+","+x+")";v.fillStyle=P,v.beginPath();var C,M=!0;(D.length>2*e.width_||o.default.FORCE_FAST_PROXY)&&(v=s._fastCanvasProxy(v));for(var N,F=[];E.hasNext;)if(N=E.next(),n.isOK(N.y)||m){if(c){if(!M&&C==N.xval)continue;M=!1,C=N.xval,r=g[N.canvasx];var k;k=void 0===r?A:l?r[0]:r,O=[N.canvasy,k],m?-1===T[0]?g[N.canvasx]=[N.canvasy,A]:g[N.canvasx]=[N.canvasy,T[0]]:g[N.canvasx]=N.canvasy}else O=isNaN(N.canvasy)&&m?[h.y+h.h,A]:[N.canvasy,A];isNaN(L)?(v.moveTo(N.canvasx,O[1]),v.lineTo(N.canvasx,O[0])):(m?(v.lineTo(N.canvasx,T[0]),v.lineTo(N.canvasx,O[0])):v.lineTo(N.canvasx,O[0]),c&&(F.push([L,T[1]]),l&&r?F.push([N.canvasx,r[1]]):F.push([N.canvasx,O[1]]))),T=O,L=N.canvasx}else f(v,L,T[1],F),F=[],L=NaN,null===N.y_stacked||isNaN(N.y_stacked)||(g[N.canvasx]=h.h*N.y_stacked+h.y);l=m,O&&N&&(f(v,N.canvasx,O[1],F),F=[]),v.fill()}}}},a.default=s,e.exports=a.default},{"./dygraph":18,"./dygraph-utils":17}],10:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-tickers"),o=n(r),s=t("./dygraph-interaction-model"),l=i(s),h=t("./dygraph-canvas"),u=i(h),d=t("./dygraph-utils"),c=n(d),p={highlightCircleSize:3,highlightSeriesOpts:null,highlightSeriesBackgroundAlpha:.5,highlightSeriesBackgroundColor:"rgb(255, 255, 255)",labelsSeparateLines:!1,labelsShowZeroValues:!0,labelsKMB:!1,labelsKMG2:!1,showLabelsOnHighlight:!0,digitsAfterDecimal:2,maxNumberWidth:6,sigFigs:null,strokeWidth:1,strokeBorderWidth:0,strokeBorderColor:"white",axisTickSize:3,axisLabelFontSize:14,rightGap:5,showRoller:!1,xValueParser:void 0,delimiter:",",sigma:2,errorBars:!1,fractions:!1,wilsonInterval:!0,customBars:!1,fillGraph:!1,fillAlpha:.15,connectSeparatedPoints:!1,stackedGraph:!1,stackedGraphNaNFill:"all",hideOverlayOnMouseOut:!0,legend:"onmouseover",stepPlot:!1,xRangePad:0,yRangePad:null,drawAxesAtZero:!1,titleHeight:28,xLabelHeight:18,yLabelWidth:18,axisLineColor:"black",axisLineWidth:.3,gridLineWidth:.3,axisLabelWidth:50,gridLineColor:"rgb(128,128,128)",interactionModel:l.default.defaultModel,animatedZooms:!1,showRangeSelector:!1,rangeSelectorHeight:40,rangeSelectorPlotStrokeColor:"#808FAB",rangeSelectorPlotFillGradientColor:"white",rangeSelectorPlotFillColor:"#A7B1C4",rangeSelectorBackgroundStrokeColor:"gray",rangeSelectorBackgroundLineWidth:1,rangeSelectorPlotLineWidth:1.5,rangeSelectorForegroundStrokeColor:"black",rangeSelectorForegroundLineWidth:1,rangeSelectorAlpha:.6,showInRangeSelector:null,plotter:[u.default._fillPlotter,u.default._errorPlotter,u.default._linePlotter],plugins:[],axes:{x:{pixelsPerLabel:70,axisLabelWidth:60,axisLabelFormatter:c.dateAxisLabelFormatter,valueFormatter:c.dateValueFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.dateTicker},y:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.numericTicks},y2:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawAxis:!0,drawGrid:!1,independentTicks:!1,ticker:o.numericTicks}}};a.default=p,e.exports=a.default},{"./dygraph-canvas":9,"./dygraph-interaction-model":12,"./dygraph-tickers":16,"./dygraph-utils":17}],11:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(t){this.container=t};r.prototype.draw=function(t,e){this.container.innerHTML="",void 0!==this.date_graph&&this.date_graph.destroy(),this.date_graph=new n.default(this.container,t,e)},r.prototype.setSelection=function(t){var e=!1;t.length&&(e=t[0].row),this.date_graph.setSelection(e)},r.prototype.getSelection=function(){var t=[],e=this.date_graph.getSelection();if(e<0)return t;for(var a=this.date_graph.layout_.points,i=0;i<a.length;++i)t.push({row:e,column:i+1});return t},a.default=r,e.exports=a.default},{"./dygraph":18}],12:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r={};r.maybeTreatMouseOpAsClick=function(t,e,a){a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=Math.abs(a.dragEndX-a.dragStartX),o=Math.abs(a.dragEndY-a.dragStartY);i<2&&o<2&&void 0!==e.lastx_&&-1!=e.lastx_&&r.treatMouseOpAsClick(e,t,a),a.regionWidth=i,a.regionHeight=o},r.startPan=function(t,e,a){var i,r;a.isPanning=!0;var o=e.xAxisRange();if(e.getOptionForAxis("logscale","x")?(a.initialLeftmostDate=n.log10(o[0]),a.dateRange=n.log10(o[1])-n.log10(o[0])):(a.initialLeftmostDate=o[0],a.dateRange=o[1]-o[0]),a.xUnitsPerPixel=a.dateRange/(e.plotter_.area.w-1),e.getNumericOption("panEdgeFraction")){var s=e.width_*e.getNumericOption("panEdgeFraction"),l=e.xAxisExtremes(),h=e.toDomXCoord(l[0])-s,u=e.toDomXCoord(l[1])+s,d=e.toDataXCoord(h),c=e.toDataXCoord(u);a.boundedDates=[d,c];var p=[],g=e.height_*e.getNumericOption("panEdgeFraction");for(i=0;i<e.axes_.length;i++){r=e.axes_[i];var f=r.extremeRange,_=e.toDomYCoord(f[0],i)+g,v=e.toDomYCoord(f[1],i)-g,y=e.toDataYCoord(_,i),x=e.toDataYCoord(v,i);p[i]=[y,x]}a.boundedValues=p}for(a.is2DPan=!1,a.axes=[],i=0;i<e.axes_.length;i++){r=e.axes_[i];var m={},b=e.yAxisRange(i);e.attributes_.getForAxis("logscale",i)?(m.initialTopValue=n.log10(b[1]),m.dragValueRange=n.log10(b[1])-n.log10(b[0])):(m.initialTopValue=b[1],m.dragValueRange=b[1]-b[0]),m.unitsPerPixel=m.dragValueRange/(e.plotter_.area.h-1),a.axes.push(m),r.valueRange&&(a.is2DPan=!0)}},r.movePan=function(t,e,a){a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=a.initialLeftmostDate-(a.dragEndX-a.dragStartX)*a.xUnitsPerPixel;a.boundedDates&&(i=Math.max(i,a.boundedDates[0]));var r=i+a.dateRange;if(a.boundedDates&&r>a.boundedDates[1]&&(i-=r-a.boundedDates[1],r=i+a.dateRange),e.getOptionForAxis("logscale","x")?e.dateWindow_=[Math.pow(n.LOG_SCALE,i),Math.pow(n.LOG_SCALE,r)]:e.dateWindow_=[i,r],a.is2DPan)for(var o=a.dragEndY-a.dragStartY,s=0;s<e.axes_.length;s++){var l=e.axes_[s],h=a.axes[s],u=o*h.unitsPerPixel,d=a.boundedValues?a.boundedValues[s]:null,c=h.initialTopValue+u;d&&(c=Math.min(c,d[1]));var p=c-h.dragValueRange;d&&p<d[0]&&(c-=p-d[0],p=c-h.dragValueRange),e.attributes_.getForAxis("logscale",s)?l.valueRange=[Math.pow(n.LOG_SCALE,p),Math.pow(n.LOG_SCALE,c)]:l.valueRange=[p,c]}e.drawGraph_(!1)},r.endPan=r.maybeTreatMouseOpAsClick,r.startZoom=function(t,e,a){a.isZooming=!0,a.zoomMoved=!1},r.moveZoom=function(t,e,a){a.zoomMoved=!0,a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=Math.abs(a.dragStartX-a.dragEndX),r=Math.abs(a.dragStartY-a.dragEndY);a.dragDirection=i<r/2?n.VERTICAL:n.HORIZONTAL,e.drawZoomRect_(a.dragDirection,a.dragStartX,a.dragEndX,a.dragStartY,a.dragEndY,a.prevDragDirection,a.prevEndX,a.prevEndY),a.prevEndX=a.dragEndX,a.prevEndY=a.dragEndY,a.prevDragDirection=a.dragDirection},r.treatMouseOpAsClick=function(t,e,a){for(var i=t.getFunctionOption("clickCallback"),n=t.getFunctionOption("pointClickCallback"),r=null,o=-1,s=Number.MAX_VALUE,l=0;l<t.selPoints_.length;l++){var h=t.selPoints_[l],u=Math.pow(h.canvasx-a.dragEndX,2)+Math.pow(h.canvasy-a.dragEndY,2);!isNaN(u)&&(-1==o||u<s)&&(s=u,o=l)}var d=t.getNumericOption("highlightCircleSize")+2;if(s<=d*d&&(r=t.selPoints_[o]),r){var c={cancelable:!0,point:r,canvasx:a.dragEndX,canvasy:a.dragEndY};if(t.cascadeEvents_("pointClick",c))return;n&&n.call(t,e,r)}var c={cancelable:!0,xval:t.lastx_,pts:t.selPoints_,canvasx:a.dragEndX,canvasy:a.dragEndY};t.cascadeEvents_("click",c)||i&&i.call(t,e,t.lastx_,t.selPoints_)},r.endZoom=function(t,e,a){e.clearZoomRect_(),a.isZooming=!1,r.maybeTreatMouseOpAsClick(t,e,a);var i=e.getArea();if(a.regionWidth>=10&&a.dragDirection==n.HORIZONTAL){var o=Math.min(a.dragStartX,a.dragEndX),s=Math.max(a.dragStartX,a.dragEndX);o=Math.max(o,i.x),s=Math.min(s,i.x+i.w),o<s&&e.doZoomX_(o,s),a.cancelNextDblclick=!0}else if(a.regionHeight>=10&&a.dragDirection==n.VERTICAL){var l=Math.min(a.dragStartY,a.dragEndY),h=Math.max(a.dragStartY,a.dragEndY);l=Math.max(l,i.y),h=Math.min(h,i.y+i.h),l<h&&e.doZoomY_(l,h),a.cancelNextDblclick=!0}a.dragStartX=null,a.dragStartY=null},r.startTouch=function(t,e,a){t.preventDefault(),t.touches.length>1&&(a.startTimeForDoubleTapMs=null);for(var i=[],n=0;n<t.touches.length;n++){var r=t.touches[n];i.push({pageX:r.pageX,pageY:r.pageY,dataX:e.toDataXCoord(r.pageX),dataY:e.toDataYCoord(r.pageY)})}if(a.initialTouches=i,1==i.length)a.initialPinchCenter=i[0],a.touchDirections={x:!0,y:!0};else if(i.length>=2){a.initialPinchCenter={pageX:.5*(i[0].pageX+i[1].pageX),pageY:.5*(i[0].pageY+i[1].pageY),dataX:.5*(i[0].dataX+i[1].dataX),dataY:.5*(i[0].dataY+i[1].dataY)};var o=180/Math.PI*Math.atan2(a.initialPinchCenter.pageY-i[0].pageY,i[0].pageX-a.initialPinchCenter.pageX);o=Math.abs(o),o>90&&(o=90-o),a.touchDirections={x:o<67.5,y:o>22.5}}a.initialRange={x:e.xAxisRange(),y:e.yAxisRange()}},r.moveTouch=function(t,e,a){a.startTimeForDoubleTapMs=null;var i,n=[];for(i=0;i<t.touches.length;i++){var r=t.touches[i];n.push({pageX:r.pageX,pageY:r.pageY})}var o,s=a.initialTouches,l=a.initialPinchCenter;o=1==n.length?n[0]:{pageX:.5*(n[0].pageX+n[1].pageX),pageY:.5*(n[0].pageY+n[1].pageY)};var h={pageX:o.pageX-l.pageX,pageY:o.pageY-l.pageY},u=a.initialRange.x[1]-a.initialRange.x[0],d=a.initialRange.y[0]-a.initialRange.y[1];h.dataX=h.pageX/e.plotter_.area.w*u,h.dataY=h.pageY/e.plotter_.area.h*d;var c,p;if(1==n.length)c=1,p=1;else if(n.length>=2){var g=s[1].pageX-l.pageX;c=(n[1].pageX-o.pageX)/g;var f=s[1].pageY-l.pageY;p=(n[1].pageY-o.pageY)/f}c=Math.min(8,Math.max(.125,c)),p=Math.min(8,Math.max(.125,p));var _=!1;if(a.touchDirections.x&&(e.dateWindow_=[l.dataX-h.dataX+(a.initialRange.x[0]-l.dataX)/c,l.dataX-h.dataX+(a.initialRange.x[1]-l.dataX)/c],_=!0),a.touchDirections.y)for(i=0;i<1;i++){var v=e.axes_[i],y=e.attributes_.getForAxis("logscale",i);y||(v.valueRange=[l.dataY-h.dataY+(a.initialRange.y[0]-l.dataY)/p,l.dataY-h.dataY+(a.initialRange.y[1]-l.dataY)/p],_=!0)}if(e.drawGraph_(!1),_&&n.length>1&&e.getFunctionOption("zoomCallback")){var x=e.xAxisRange();e.getFunctionOption("zoomCallback").call(e,x[0],x[1],e.yAxisRanges())}},r.endTouch=function(t,e,a){if(0!==t.touches.length)r.startTouch(t,e,a);else if(1==t.changedTouches.length){var i=(new Date).getTime(),n=t.changedTouches[0];a.startTimeForDoubleTapMs&&i-a.startTimeForDoubleTapMs<500&&a.doubleTapX&&Math.abs(a.doubleTapX-n.screenX)<50&&a.doubleTapY&&Math.abs(a.doubleTapY-n.screenY)<50?e.resetZoom():(a.startTimeForDoubleTapMs=i,a.doubleTapX=n.screenX,a.doubleTapY=n.screenY)}};var o=function(t,e,a){return t<e?e-t:t>a?t-a:0},s=function(t,e){var a=n.findPos(e.canvas_),i={left:a.x,right:a.x+e.canvas_.offsetWidth,top:a.y,bottom:a.y+e.canvas_.offsetHeight},r={x:n.pageX(t),y:n.pageY(t)},s=o(r.x,i.left,i.right),l=o(r.y,i.top,i.bottom);return Math.max(s,l)};r.defaultModel={mousedown:function(t,e,a){if(!t.button||2!=t.button){a.initializeMouseDown(t,e,a),t.altKey||t.shiftKey?r.startPan(t,e,a):r.startZoom(t,e,a);var i=function(t){if(a.isZooming){s(t,e)<100?r.moveZoom(t,e,a):null!==a.dragEndX&&(a.dragEndX=null,a.dragEndY=null,e.clearZoomRect_())}else a.isPanning&&r.movePan(t,e,a)},o=function t(o){a.isZooming?null!==a.dragEndX?r.endZoom(o,e,a):r.maybeTreatMouseOpAsClick(o,e,a):a.isPanning&&r.endPan(o,e,a),n.removeEvent(document,"mousemove",i),n.removeEvent(document,"mouseup",t),a.destroy()};e.addAndTrackEvent(document,"mousemove",i),e.addAndTrackEvent(document,"mouseup",o)}},willDestroyContextMyself:!0,touchstart:function(t,e,a){r.startTouch(t,e,a)},touchmove:function(t,e,a){r.moveTouch(t,e,a)},touchend:function(t,e,a){r.endTouch(t,e,a)},dblclick:function(t,e,a){if(a.cancelNextDblclick)return void(a.cancelNextDblclick=!1);var i={canvasx:a.dragEndX,canvasy:a.dragEndY,cancelable:!0};e.cascadeEvents_("dblclick",i)||t.altKey||t.shiftKey||e.resetZoom()}},r.nonInteractiveModel_={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a)},mouseup:r.maybeTreatMouseOpAsClick},r.dragIsPanInteractionModel={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a),r.startPan(t,e,a)},mousemove:function(t,e,a){a.isPanning&&r.movePan(t,e,a)},mouseup:function(t,e,a){a.isPanning&&r.endPan(t,e,a)}},a.default=r,e.exports=a.default},{"./dygraph-utils":17}],13:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(t){this.dygraph_=t,this.points=[],this.setNames=[],this.annotations=[],this.yAxes_=null,this.xTicks_=null,this.yTicks_=null};r.prototype.addDataset=function(t,e){this.points.push(e),this.setNames.push(t)},r.prototype.getPlotArea=function(){return this.area_},r.prototype.computePlotArea=function(){var t={x:0,y:0};t.w=this.dygraph_.width_-t.x-this.dygraph_.getOption("rightGap"),t.h=this.dygraph_.height_;var e={chart_div:this.dygraph_.graphDiv,reserveSpaceLeft:function(e){var a={x:t.x,y:t.y,w:e,h:t.h};return t.x+=e,t.w-=e,a},reserveSpaceRight:function(e){var a={x:t.x+t.w-e,y:t.y,w:e,h:t.h};return t.w-=e,a},reserveSpaceTop:function(e){var a={x:t.x,y:t.y,w:t.w,h:e};return t.y+=e,t.h-=e,a},reserveSpaceBottom:function(e){var a={x:t.x,y:t.y+t.h-e,w:t.w,h:e};return t.h-=e,a},chartRect:function(){return{x:t.x,y:t.y,w:t.w,h:t.h}}};this.dygraph_.cascadeEvents_("layout",e),this.area_=t},r.prototype.setAnnotations=function(t){this.annotations=[];for(var e=this.dygraph_.getOption("xValueParser")||function(t){return t},a=0;a<t.length;a++){var i={};if(!t[a].xval&&void 0===t[a].x)return void console.error("Annotations must have an 'x' property");if(t[a].icon&&(!t[a].hasOwnProperty("width")||!t[a].hasOwnProperty("height")))return void console.error("Must set width and height when setting annotation.icon property");n.update(i,t[a]),i.xval||(i.xval=e(i.x)),this.annotations.push(i)}},r.prototype.setXTicks=function(t){this.xTicks_=t},r.prototype.setYAxes=function(t){this.yAxes_=t},r.prototype.evaluate=function(){this._xAxis={},this._evaluateLimits(),this._evaluateLineCharts(),this._evaluateLineTicks(),this._evaluateAnnotations()},r.prototype._evaluateLimits=function(){var t=this.dygraph_.xAxisRange();this._xAxis.minval=t[0],this._xAxis.maxval=t[1];var e=t[1]-t[0];this._xAxis.scale=0!==e?1/e:1,this.dygraph_.getOptionForAxis("logscale","x")&&(this._xAxis.xlogrange=n.log10(this._xAxis.maxval)-n.log10(this._xAxis.minval),this._xAxis.xlogscale=0!==this._xAxis.xlogrange?1/this._xAxis.xlogrange:1);for(var a=0;a<this.yAxes_.length;a++){var i=this.yAxes_[a];i.minyval=i.computedValueRange[0],i.maxyval=i.computedValueRange[1],i.yrange=i.maxyval-i.minyval,i.yscale=0!==i.yrange?1/i.yrange:1,this.dygraph_.getOption("logscale")&&(i.ylogrange=n.log10(i.maxyval)-n.log10(i.minyval),i.ylogscale=0!==i.ylogrange?1/i.ylogrange:1,isFinite(i.ylogrange)&&!isNaN(i.ylogrange)||console.error("axis "+a+" of graph at "+i.g+" can't be displayed in log scale for range ["+i.minyval+" - "+i.maxyval+"]"))}},r.calcXNormal_=function(t,e,a){return a?(n.log10(t)-n.log10(e.minval))*e.xlogscale:(t-e.minval)*e.scale},r.calcYNormal_=function(t,e,a){if(a){var i=1-(n.log10(e)-n.log10(t.minyval))*t.ylogscale;return isFinite(i)?i:NaN}return 1-(e-t.minyval)*t.yscale},r.prototype._evaluateLineCharts=function(){for(var t=this.dygraph_.getOption("stackedGraph"),e=this.dygraph_.getOptionForAxis("logscale","x"),a=0;a<this.points.length;a++){for(var i=this.points[a],n=this.setNames[a],o=this.dygraph_.getOption("connectSeparatedPoints",n),s=this.dygraph_.axisPropertiesForSeries(n),l=this.dygraph_.attributes_.getForSeries("logscale",n),h=0;h<i.length;h++){var u=i[h];u.x=r.calcXNormal_(u.xval,this._xAxis,e);var d=u.yval;t&&(u.y_stacked=r.calcYNormal_(s,u.yval_stacked,l),
+null===d||isNaN(d)||(d=u.yval_stacked)),null===d&&(d=NaN,o||(u.yval=NaN)),u.y=r.calcYNormal_(s,d,l)}this.dygraph_.dataHandler_.onLineEvaluated(i,s,l)}},r.prototype._evaluateLineTicks=function(){var t,e,a,i,n,r;for(this.xticks=[],t=0;t<this.xTicks_.length;t++)e=this.xTicks_[t],a=e.label,r=!("label_v"in e),n=r?e.v:e.label_v,(i=this.dygraph_.toPercentXCoord(n))>=0&&i<1&&this.xticks.push({pos:i,label:a,has_tick:r});for(this.yticks=[],t=0;t<this.yAxes_.length;t++)for(var o=this.yAxes_[t],s=0;s<o.ticks.length;s++)e=o.ticks[s],a=e.label,r=!("label_v"in e),n=r?e.v:e.label_v,(i=this.dygraph_.toPercentYCoord(n,t))>0&&i<=1&&this.yticks.push({axis:t,pos:i,label:a,has_tick:r})},r.prototype._evaluateAnnotations=function(){var t,e={};for(t=0;t<this.annotations.length;t++){var a=this.annotations[t];e[a.xval+","+a.series]=a}if(this.annotated_points=[],this.annotations&&this.annotations.length)for(var i=0;i<this.points.length;i++){var n=this.points[i];for(t=0;t<n.length;t++){var r=n[t],o=r.xval+","+r.name;o in e&&(r.annotation=e[o],this.annotated_points.push(r))}}},r.prototype.removeAllDatasets=function(){delete this.points,delete this.setNames,delete this.setPointsLengths,delete this.setPointsOffsets,this.points=[],this.setNames=[],this.setPointsLengths=[],this.setPointsOffsets=[]},a.default=r,e.exports=a.default},{"./dygraph-utils":17}],14:[function(t,e,a){(function(t){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=null;if(void 0!==t);a.default=i,e.exports=a.default}).call(this,t("_process"))},{_process:1}],15:[function(t,e,a){(function(i){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-utils"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(r),s=t("./dygraph-default-attrs"),l=n(s),h=t("./dygraph-options-reference"),u=(n(h),function(t){this.dygraph_=t,this.yAxes_=[],this.xAxis_={},this.series_={},this.global_=this.dygraph_.attrs_,this.user_=this.dygraph_.user_attrs_||{},this.labels_=[],this.highlightSeries_=this.get("highlightSeriesOpts")||{},this.reparseSeries()});if(u.AXIS_STRING_MAPPINGS_={y:0,Y:0,y1:0,Y1:0,y2:1,Y2:1},u.axisToIndex_=function(t){if("string"==typeof t){if(u.AXIS_STRING_MAPPINGS_.hasOwnProperty(t))return u.AXIS_STRING_MAPPINGS_[t];throw"Unknown axis : "+t}if("number"==typeof t){if(0===t||1===t)return t;throw"Dygraphs only supports two y-axes, indexed from 0-1."}if(t)throw"Unknown axis : "+t;return 0},u.prototype.reparseSeries=function(){var t=this.get("labels");if(t){this.labels_=t.slice(1),this.yAxes_=[{series:[],options:{}}],this.xAxis_={options:{}},this.series_={};for(var e=this.user_.series||{},a=0;a<this.labels_.length;a++){var i=this.labels_[a],n=e[i]||{},r=u.axisToIndex_(n.axis);this.series_[i]={idx:a,yAxis:r,options:n},this.yAxes_[r]?this.yAxes_[r].series.push(i):this.yAxes_[r]={series:[i],options:{}}}var s=this.user_.axes||{};o.update(this.yAxes_[0].options,s.y||{}),this.yAxes_.length>1&&o.update(this.yAxes_[1].options,s.y2||{}),o.update(this.xAxis_.options,s.x||{})}},u.prototype.get=function(t){var e=this.getGlobalUser_(t);return null!==e?e:this.getGlobalDefault_(t)},u.prototype.getGlobalUser_=function(t){return this.user_.hasOwnProperty(t)?this.user_[t]:null},u.prototype.getGlobalDefault_=function(t){return this.global_.hasOwnProperty(t)?this.global_[t]:l.default.hasOwnProperty(t)?l.default[t]:null},u.prototype.getForAxis=function(t,e){var a,i;if("number"==typeof e)a=e,i=0===a?"y":"y2";else{if("y1"==e&&(e="y"),"y"==e)a=0;else if("y2"==e)a=1;else{if("x"!=e)throw"Unknown axis "+e;a=-1}i=e}var n=-1==a?this.xAxis_:this.yAxes_[a];if(n){var r=n.options;if(r.hasOwnProperty(t))return r[t]}if("x"!==e||"logscale"!==t){var o=this.getGlobalUser_(t);if(null!==o)return o}var s=l.default.axes[i];return s.hasOwnProperty(t)?s[t]:this.getGlobalDefault_(t)},u.prototype.getForSeries=function(t,e){if(e===this.dygraph_.getHighlightSeries()&&this.highlightSeries_.hasOwnProperty(t))return this.highlightSeries_[t];if(!this.series_.hasOwnProperty(e))throw"Unknown series: "+e;var a=this.series_[e],i=a.options;return i.hasOwnProperty(t)?i[t]:this.getForAxis(t,a.yAxis)},u.prototype.numAxes=function(){return this.yAxes_.length},u.prototype.axisForSeries=function(t){return this.series_[t].yAxis},u.prototype.axisOptions=function(t){return this.yAxes_[t].options},u.prototype.seriesForAxis=function(t){return this.yAxes_[t].series},u.prototype.seriesNames=function(){return this.labels_},void 0!==i);a.default=u,e.exports=a.default}).call(this,t("_process"))},{"./dygraph-default-attrs":10,"./dygraph-options-reference":14,"./dygraph-utils":17,_process:1}],16:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(t,e,a,i,n,r){return o(t,e,a,function(t){return"logscale"!==t&&i(t)},n,r)};a.numericLinearTicks=r;var o=function(t,e,a,i,r,o){var s,l,h,u,c=i("pixelsPerLabel"),p=[];if(o)for(s=0;s<o.length;s++)p.push({v:o[s]});else{if(i("logscale")){u=Math.floor(a/c);var g=n.binarySearch(t,d,1),f=n.binarySearch(e,d,-1);-1==g&&(g=0),-1==f&&(f=d.length-1);var _=null;if(f-g>=u/4){for(var v=f;v>=g;v--){var y=d[v],x=Math.log(y/t)/Math.log(e/t)*a,m={v:y};null===_?_={tickValue:y,pixel_coord:x}:Math.abs(x-_.pixel_coord)>=c?_={tickValue:y,pixel_coord:x}:m.label="",p.push(m)}p.reverse()}}if(0===p.length){var b,w,A=i("labelsKMG2");A?(b=[1,2,4,8,16,32,64,128,256],w=16):(b=[1,2,5,10,20,50,100],w=10);var O,D,E,L=Math.ceil(a/c),T=Math.abs(e-t)/L,S=Math.floor(Math.log(T)/Math.log(w)),P=Math.pow(w,S);for(l=0;l<b.length&&(O=P*b[l],D=Math.floor(t/O)*O,E=Math.ceil(e/O)*O,u=Math.abs(E-D)/O,!(a/u>c));l++);for(D>E&&(O*=-1),s=0;s<=u;s++)h=D+s*O,p.push({v:h})}}var C=i("axisLabelFormatter");for(s=0;s<p.length;s++)void 0===p[s].label&&(p[s].label=C.call(r,p[s].v,0,i,r));return p};a.numericTicks=o;var s=function(t,e,a,i,n,r){var o=c(t,e,a,i);return o>=0?g(t,e,o,i,n):[]};a.dateTicker=s;var l={MILLISECONDLY:0,TWO_MILLISECONDLY:1,FIVE_MILLISECONDLY:2,TEN_MILLISECONDLY:3,FIFTY_MILLISECONDLY:4,HUNDRED_MILLISECONDLY:5,FIVE_HUNDRED_MILLISECONDLY:6,SECONDLY:7,TWO_SECONDLY:8,FIVE_SECONDLY:9,TEN_SECONDLY:10,THIRTY_SECONDLY:11,MINUTELY:12,TWO_MINUTELY:13,FIVE_MINUTELY:14,TEN_MINUTELY:15,THIRTY_MINUTELY:16,HOURLY:17,TWO_HOURLY:18,SIX_HOURLY:19,DAILY:20,TWO_DAILY:21,WEEKLY:22,MONTHLY:23,QUARTERLY:24,BIANNUAL:25,ANNUAL:26,DECADAL:27,CENTENNIAL:28,NUM_GRANULARITIES:29};a.Granularity=l;var h={DATEFIELD_Y:0,DATEFIELD_M:1,DATEFIELD_D:2,DATEFIELD_HH:3,DATEFIELD_MM:4,DATEFIELD_SS:5,DATEFIELD_MS:6,NUM_DATEFIELDS:7},u=[];u[l.MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:1,spacing:1},u[l.TWO_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:2,spacing:2},u[l.FIVE_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:5,spacing:5},u[l.TEN_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:10,spacing:10},u[l.FIFTY_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:50,spacing:50},u[l.HUNDRED_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:100,spacing:100},u[l.FIVE_HUNDRED_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:500,spacing:500},u[l.SECONDLY]={datefield:h.DATEFIELD_SS,step:1,spacing:1e3},u[l.TWO_SECONDLY]={datefield:h.DATEFIELD_SS,step:2,spacing:2e3},u[l.FIVE_SECONDLY]={datefield:h.DATEFIELD_SS,step:5,spacing:5e3},u[l.TEN_SECONDLY]={datefield:h.DATEFIELD_SS,step:10,spacing:1e4},u[l.THIRTY_SECONDLY]={datefield:h.DATEFIELD_SS,step:30,spacing:3e4},u[l.MINUTELY]={datefield:h.DATEFIELD_MM,step:1,spacing:6e4},u[l.TWO_MINUTELY]={datefield:h.DATEFIELD_MM,step:2,spacing:12e4},u[l.FIVE_MINUTELY]={datefield:h.DATEFIELD_MM,step:5,spacing:3e5},u[l.TEN_MINUTELY]={datefield:h.DATEFIELD_MM,step:10,spacing:6e5},u[l.THIRTY_MINUTELY]={datefield:h.DATEFIELD_MM,step:30,spacing:18e5},u[l.HOURLY]={datefield:h.DATEFIELD_HH,step:1,spacing:36e5},u[l.TWO_HOURLY]={datefield:h.DATEFIELD_HH,step:2,spacing:72e5},u[l.SIX_HOURLY]={datefield:h.DATEFIELD_HH,step:6,spacing:216e5},u[l.DAILY]={datefield:h.DATEFIELD_D,step:1,spacing:864e5},u[l.TWO_DAILY]={datefield:h.DATEFIELD_D,step:2,spacing:1728e5},u[l.WEEKLY]={datefield:h.DATEFIELD_D,step:7,spacing:6048e5},u[l.MONTHLY]={datefield:h.DATEFIELD_M,step:1,spacing:2629817280},u[l.QUARTERLY]={datefield:h.DATEFIELD_M,step:3,spacing:216e5*365.2524},u[l.BIANNUAL]={datefield:h.DATEFIELD_M,step:6,spacing:432e5*365.2524},u[l.ANNUAL]={datefield:h.DATEFIELD_Y,step:1,spacing:864e5*365.2524},u[l.DECADAL]={datefield:h.DATEFIELD_Y,step:10,spacing:315578073600},u[l.CENTENNIAL]={datefield:h.DATEFIELD_Y,step:100,spacing:3155780736e3};var d=function(){for(var t=[],e=-39;e<=39;e++)for(var a=Math.pow(10,e),i=1;i<=9;i++){var n=a*i;t.push(n)}return t}(),c=function(t,e,a,i){for(var n=i("pixelsPerLabel"),r=0;r<l.NUM_GRANULARITIES;r++){if(a/p(t,e,r)>=n)return r}return-1},p=function(t,e,a){var i=u[a].spacing;return Math.round(1*(e-t)/i)},g=function(t,e,a,i,r){var o=i("axisLabelFormatter"),s=i("labelsUTC"),d=s?n.DateAccessorsUTC:n.DateAccessorsLocal,c=u[a].datefield,p=u[a].step,g=u[a].spacing,f=new Date(t),_=[];_[h.DATEFIELD_Y]=d.getFullYear(f),_[h.DATEFIELD_M]=d.getMonth(f),_[h.DATEFIELD_D]=d.getDate(f),_[h.DATEFIELD_HH]=d.getHours(f),_[h.DATEFIELD_MM]=d.getMinutes(f),_[h.DATEFIELD_SS]=d.getSeconds(f),_[h.DATEFIELD_MS]=d.getMilliseconds(f);var v=_[c]%p;a==l.WEEKLY&&(v=d.getDay(f)),_[c]-=v;for(var y=c+1;y<h.NUM_DATEFIELDS;y++)_[y]=y===h.DATEFIELD_D?1:0;var x=[],m=d.makeDate.apply(null,_),b=m.getTime();if(a<=l.HOURLY)for(b<t&&(b+=g,m=new Date(b));b<=e;)x.push({v:b,label:o.call(r,m,a,i,r)}),b+=g,m=new Date(b);else for(b<t&&(_[c]+=p,m=d.makeDate.apply(null,_),b=m.getTime());b<=e;)(a>=l.DAILY||d.getHours(m)%p==0)&&x.push({v:b,label:o.call(r,m,a,i,r)}),_[c]+=p,m=d.makeDate.apply(null,_),b=m.getTime();return x};a.getDateAxis=g},{"./dygraph-utils":17}],17:[function(t,e,a){"use strict";function i(t,e,a){t.removeEventListener(e,a,!1)}function n(t){return t=t||window.event,t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),t.cancelBubble=!0,t.cancel=!0,t.returnValue=!1,!1}function r(t,e,a){var i,n,r;if(0===e)i=a,n=a,r=a;else{var o=Math.floor(6*t),s=6*t-o,l=a*(1-e),h=a*(1-e*s),u=a*(1-e*(1-s));switch(o){case 1:i=h,n=a,r=l;break;case 2:i=l,n=a,r=u;break;case 3:i=l,n=h,r=a;break;case 4:i=u,n=l,r=a;break;case 5:i=a,n=l,r=h;break;case 6:case 0:i=a,n=u,r=l}}return i=Math.floor(255*i+.5),n=Math.floor(255*n+.5),r=Math.floor(255*r+.5),"rgb("+i+","+n+","+r+")"}function o(t){var e=t.getBoundingClientRect(),a=window,i=document.documentElement;return{x:e.left+(a.pageXOffset||i.scrollLeft),y:e.top+(a.pageYOffset||i.scrollTop)}}function s(t){return!t.pageX||t.pageX<0?0:t.pageX}function l(t){return!t.pageY||t.pageY<0?0:t.pageY}function h(t,e){return s(t)-e.px}function u(t,e){return l(t)-e.py}function d(t){return!!t&&!isNaN(t)}function c(t,e){return!!t&&(null!==t.yval&&(null!==t.x&&void 0!==t.x&&(null!==t.y&&void 0!==t.y&&!(isNaN(t.x)||!e&&isNaN(t.y)))))}function p(t,e){var a=Math.min(Math.max(1,e||2),21);return Math.abs(t)<.001&&0!==t?t.toExponential(a-1):t.toPrecision(a)}function g(t){return t<10?"0"+t:""+t}function f(t,e,a,i){var n=g(t)+":"+g(e);if(a&&(n+=":"+g(a),i)){var r=""+i;n+="."+("000"+r).substring(r.length)}return n}function _(t,e){var a=e?tt:$,i=new Date(t),n=a.getFullYear(i),r=a.getMonth(i),o=a.getDate(i),s=a.getHours(i),l=a.getMinutes(i),h=a.getSeconds(i),u=a.getMilliseconds(i),d=""+n,c=g(r+1),p=g(o),_=3600*s+60*l+h+.001*u,v=d+"/"+c+"/"+p;return _&&(v+=" "+f(s,l,h,u)),v}function v(t,e){var a=Math.pow(10,e);return Math.round(t*a)/a}function y(t,e,a,i,n){for(var r=!0;r;){var o=t,s=e,l=a,h=i,u=n;if(r=!1,null!==h&&void 0!==h&&null!==u&&void 0!==u||(h=0,u=s.length-1),h>u)return-1;null!==l&&void 0!==l||(l=0);var d,c=function(t){return t>=0&&t<s.length},p=parseInt((h+u)/2,10),g=s[p];if(g==o)return p;if(g>o){if(l>0&&(d=p-1,c(d)&&s[d]<o))return p;t=o,e=s,a=l,i=h,n=p-1,r=!0,c=p=g=d=void 0}else{if(!(g<o))return-1;if(l<0&&(d=p+1,c(d)&&s[d]>o))return p;t=o,e=s,a=l,i=p+1,n=u,r=!0,c=p=g=d=void 0}}}function x(t){var e,a;if((-1==t.search("-")||-1!=t.search("T")||-1!=t.search("Z"))&&(a=m(t))&&!isNaN(a))return a;if(-1!=t.search("-")){for(e=t.replace("-","/","g");-1!=e.search("-");)e=e.replace("-","/");a=m(e)}else 8==t.length?(e=t.substr(0,4)+"/"+t.substr(4,2)+"/"+t.substr(6,2),a=m(e)):a=m(t);return a&&!isNaN(a)||console.error("Couldn't parse "+t+" as a date"),a}function m(t){return new Date(t).getTime()}function b(t,e){if(void 0!==e&&null!==e)for(var a in e)e.hasOwnProperty(a)&&(t[a]=e[a]);return t}function w(t,e){if(void 0!==e&&null!==e)for(var a in e)e.hasOwnProperty(a)&&(null===e[a]?t[a]=null:A(e[a])?t[a]=e[a].slice():!function(t){return"object"==typeof Node?t instanceof Node:"object"==typeof t&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName}(e[a])&&"object"==typeof e[a]?("object"==typeof t[a]&&null!==t[a]||(t[a]={}),w(t[a],e[a])):t[a]=e[a]);return t}function A(t){var e=typeof t;return("object"==e||"function"==e&&"function"==typeof t.item)&&null!==t&&"number"==typeof t.length&&3!==t.nodeType}function O(t){return"object"==typeof t&&null!==t&&"function"==typeof t.getTime}function D(t){for(var e=[],a=0;a<t.length;a++)A(t[a])?e.push(D(t[a])):e.push(t[a]);return e}function E(){return document.createElement("canvas")}function L(t){try{var e=window.devicePixelRatio,a=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return void 0!==e?e/a:1}catch(t){return 1}}function T(t,e,a,i){e=e||0,a=a||t.length,this.hasNext=!0,this.peek=null,this.start_=e,this.array_=t,this.predicate_=i,this.end_=Math.min(t.length,e+a),this.nextIdx_=e-1,this.next()}function S(t,e,a,i){return new T(t,e,a,i)}function P(t,e,a,i){var n,r=0,o=(new Date).getTime();if(t(r),1==e)return void i();var s=e-1;!function l(){r>=e||et.call(window,function(){var e=(new Date).getTime(),h=e-o;n=r,r=Math.floor(h/a);var u=r-n;r+u>s||r>=s?(t(s),i()):(0!==u&&t(r),l())})}()}function C(t,e){var a={};if(t)for(var i=1;i<t.length;i++)a[t[i]]=!0;var n=function(t){for(var e in t)if(t.hasOwnProperty(e)&&!at[e])return!0;return!1};for(var r in e)if(e.hasOwnProperty(r))if("highlightSeriesOpts"==r||a[r]&&!e.series){if(n(e[r]))return!0}else if("series"==r||"axes"==r){var o=e[r];for(var s in o)if(o.hasOwnProperty(s)&&n(o[s]))return!0}else if(!at[r])return!0;return!1}function M(t){for(var e=0;e<t.length;e++){var a=t.charAt(e);if("\r"===a)return e+1<t.length&&"\n"===t.charAt(e+1)?"\r\n":a;if("\n"===a)return e+1<t.length&&"\r"===t.charAt(e+1)?"\n\r":a}return null}function N(t,e){if(null===e||null===t)return!1;for(var a=t;a&&a!==e;)a=a.parentNode;return a===e}function F(t,e){return e<0?1/Math.pow(t,-e):Math.pow(t,e)}function k(t){var e=nt.exec(t);if(!e)return null;var a=parseInt(e[1],10),i=parseInt(e[2],10),n=parseInt(e[3],10);return e[4]?{r:a,g:i,b:n,a:parseFloat(e[4])}:{r:a,g:i,b:n}}function R(t){var e=k(t);if(e)return e;var a=document.createElement("div");a.style.backgroundColor=t,a.style.visibility="hidden",document.body.appendChild(a);var i=window.getComputedStyle(a,null).backgroundColor;return document.body.removeChild(a),k(i)}function I(t){try{(t||document.createElement("canvas")).getContext("2d")}catch(t){return!1}return!0}function H(t,e,a){var i=parseFloat(t);if(!isNaN(i))return i;if(/^ *$/.test(t))return null;if(/^ *nan *$/i.test(t))return NaN;var n="Unable to parse '"+t+"' as a number";return void 0!==a&&void 0!==e&&(n+=" on line "+(1+(e||0))+" ('"+a+"') of CSV."),console.error(n),null}function Y(t,e){var a=e("sigFigs");if(null!==a)return p(t,a);var i,n=e("digitsAfterDecimal"),r=e("maxNumberWidth"),o=e("labelsKMB"),s=e("labelsKMG2");if(i=0!==t&&(Math.abs(t)>=Math.pow(10,r)||Math.abs(t)<Math.pow(10,-n))?t.toExponential(n):""+v(t,n),o||s){var l,h=[],u=[];o&&(l=1e3,h=rt),s&&(o&&console.warn("Setting both labelsKMB and labelsKMG2. Pick one!"),l=1024,h=ot,u=st);for(var d=Math.abs(t),c=F(l,h.length),g=h.length-1;g>=0;g--,c/=l)if(d>=c){i=v(t/c,n)+h[g];break}if(s){var f=String(t.toExponential()).split("e-");2===f.length&&f[1]>=3&&f[1]<=24&&(i=f[1]%3>0?v(f[0]/F(10,f[1]%3),n):Number(f[0]).toFixed(2),i+=u[Math.floor(f[1]/3)-1])}}return i}function X(t,e,a){return Y.call(this,t,a)}function V(t,e,a){var i=a("labelsUTC"),n=i?tt:$,r=n.getFullYear(t),o=n.getMonth(t),s=n.getDate(t),l=n.getHours(t),h=n.getMinutes(t),u=n.getSeconds(t),d=n.getMilliseconds(t);if(e>=G.Granularity.DECADAL)return""+r;if(e>=G.Granularity.MONTHLY)return lt[o]+"&#160;"+r;if(0===3600*l+60*h+u+.001*d||e>=G.Granularity.DAILY)return g(s)+"&#160;"+lt[o];if(e<G.Granularity.SECONDLY){var c=""+d;return g(u)+"."+("000"+c).substring(c.length)}return e>G.Granularity.MINUTELY?f(l,h,u,0):f(l,h,u,d)}function Z(t,e){return _(t,e("labelsUTC"))}Object.defineProperty(a,"__esModule",{value:!0}),a.removeEvent=i,a.cancelEvent=n,a.hsvToRGB=r,a.findPos=o,a.pageX=s,a.pageY=l,a.dragGetX_=h,a.dragGetY_=u,a.isOK=d,a.isValidPoint=c,a.floatFormat=p,a.zeropad=g,a.hmsString_=f,a.dateString_=_,a.round_=v,a.binarySearch=y,a.dateParser=x,a.dateStrToMillis=m,a.update=b,a.updateDeep=w,a.isArrayLike=A,a.isDateLike=O,a.clone=D,a.createCanvas=E,a.getContextPixelRatio=L,a.Iterator=T,a.createIterator=S,a.repeatAndCleanup=P,a.isPixelChangingOptionList=C,a.detectLineDelimiter=M,a.isNodeContainedBy=N,a.pow=F,a.toRGB_=R,a.isCanvasSupported=I,a.parseFloat_=H,a.numberValueFormatter=Y,a.numberAxisLabelFormatter=X,a.dateAxisLabelFormatter=V,a.dateValueFormatter=Z;var B=t("./dygraph-tickers"),G=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(B);a.LOG_SCALE=10;var W=Math.log(10);a.LN_TEN=W;var U=function(t){return Math.log(t)/W};a.log10=U;var z=function(t,e,a){var i=U(t),n=U(e),r=i+a*(n-i);return Math.pow(10,r)};a.logRangeFraction=z;var j=[2,2];a.DOTTED_LINE=j;var K=[7,3];a.DASHED_LINE=K;var q=[7,2,2,2];a.DOT_DASH_LINE=q;a.HORIZONTAL=1;a.VERTICAL=2;var Q=function(t){return t.getContext("2d")};a.getContext=Q;var J=function(t,e,a){t.addEventListener(e,a,!1)};a.addEvent=J;var $={getFullYear:function(t){return t.getFullYear()},getMonth:function(t){return t.getMonth()},getDate:function(t){return t.getDate()},getHours:function(t){return t.getHours()},getMinutes:function(t){return t.getMinutes()},getSeconds:function(t){return t.getSeconds()},getMilliseconds:function(t){return t.getMilliseconds()},getDay:function(t){return t.getDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(t,e,a,i,n,r,o)}};a.DateAccessorsLocal=$;var tt={getFullYear:function(t){return t.getUTCFullYear()},getMonth:function(t){return t.getUTCMonth()},getDate:function(t){return t.getUTCDate()},getHours:function(t){return t.getUTCHours()},getMinutes:function(t){return t.getUTCMinutes()},getSeconds:function(t){return t.getUTCSeconds()},getMilliseconds:function(t){return t.getUTCMilliseconds()},getDay:function(t){return t.getUTCDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(Date.UTC(t,e,a,i,n,r,o))}};a.DateAccessorsUTC=tt,T.prototype.next=function(){if(!this.hasNext)return null;for(var t=this.peek,e=this.nextIdx_+1,a=!1;e<this.end_;){if(!this.predicate_||this.predicate_(this.array_,e)){this.peek=this.array_[e],a=!0;break}e++}return this.nextIdx_=e,a||(this.hasNext=!1,this.peek=null),t};var et=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)}}();a.requestAnimFrame=et;var at={annotationClickHandler:!0,annotationDblClickHandler:!0,annotationMouseOutHandler:!0,annotationMouseOverHandler:!0,axisLineColor:!0,axisLineWidth:!0,clickCallback:!0,drawCallback:!0,drawHighlightPointCallback:!0,drawPoints:!0,drawPointCallback:!0,drawGrid:!0,fillAlpha:!0,gridLineColor:!0,gridLineWidth:!0,hideOverlayOnMouseOut:!0,highlightCallback:!0,highlightCircleSize:!0,interactionModel:!0,labelsDiv:!0,labelsKMB:!0,labelsKMG2:!0,labelsSeparateLines:!0,labelsShowZeroValues:!0,legend:!0,panEdgeFraction:!0,pixelsPerYLabel:!0,pointClickCallback:!0,pointSize:!0,rangeSelectorPlotFillColor:!0,rangeSelectorPlotFillGradientColor:!0,rangeSelectorPlotStrokeColor:!0,rangeSelectorBackgroundStrokeColor:!0,rangeSelectorBackgroundLineWidth:!0,rangeSelectorPlotLineWidth:!0,rangeSelectorForegroundStrokeColor:!0,rangeSelectorForegroundLineWidth:!0,rangeSelectorAlpha:!0,showLabelsOnHighlight:!0,showRoller:!0,strokeWidth:!0,underlayCallback:!0,unhighlightCallback:!0,zoomCallback:!0},it={DEFAULT:function(t,e,a,i,n,r,o){a.beginPath(),a.fillStyle=r,a.arc(i,n,o,0,2*Math.PI,!1),a.fill()}};a.Circles=it;var nt=/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([01](?:\.\d+)?))?\)$/,rt=["K","M","B","T","Q"],ot=["k","M","G","T","P","E","Z","Y"],st=["m","u","n","p","f","a","z","y"],lt=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},{"./dygraph-tickers":16}],18:[function(t,e,a){(function(i){"use strict";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}function r(t){return t&&t.__esModule?t:{default:t}}function o(t){var e=t[0],a=e[0];if("number"!=typeof a&&!x.isDateLike(a))throw new Error("Expected number or date but got "+typeof a+": "+a+".");for(var i=1;i<e.length;i++){var n=e[i];if(null!==n&&void 0!==n&&("number"!=typeof n&&!x.isArrayLike(n)))throw new Error("Expected number or array but got "+typeof n+": "+n+".")}}Object.defineProperty(a,"__esModule",{value:!0});var s=function(){function t(t,e){var a=[],i=!0,n=!1,r=void 0;try{for(var o,s=t[Symbol.iterator]();!(i=(o=s.next()).done)&&(a.push(o.value),!e||a.length!==e);i=!0);}catch(t){n=!0,r=t}finally{try{!i&&s.return&&s.return()}finally{if(n)throw r}}return a}return function(e,a){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,a);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),l=t("./dygraph-layout"),h=r(l),u=t("./dygraph-canvas"),d=r(u),c=t("./dygraph-options"),p=r(c),g=t("./dygraph-interaction-model"),f=r(g),_=t("./dygraph-tickers"),v=n(_),y=t("./dygraph-utils"),x=n(y),m=t("./dygraph-default-attrs"),b=r(m),w=t("./dygraph-options-reference"),A=(r(w),t("./iframe-tarp")),O=r(A),D=t("./datahandler/default"),E=r(D),L=t("./datahandler/bars-error"),T=r(L),S=t("./datahandler/bars-custom"),P=r(S),C=t("./datahandler/default-fractions"),M=r(C),N=t("./datahandler/bars-fractions"),F=r(N),k=t("./datahandler/bars"),R=r(k),I=t("./plugins/annotations"),H=r(I),Y=t("./plugins/axes"),X=r(Y),V=t("./plugins/chart-labels"),Z=r(V),B=t("./plugins/grid"),G=r(B),W=t("./plugins/legend"),U=r(W),z=t("./plugins/range-selector"),j=r(z),K=t("./dygraph-gviz"),q=r(K),Q=function(t,e,a){this.__init__(t,e,a)};Q.NAME="Dygraph",Q.VERSION="2.0.0",Q.DEFAULT_ROLL_PERIOD=1,Q.DEFAULT_WIDTH=480,Q.DEFAULT_HEIGHT=320,Q.ANIMATION_STEPS=12,Q.ANIMATION_DURATION=200,Q.Plotters=d.default._Plotters,Q.addedAnnotationCSS=!1,Q.prototype.__init__=function(t,e,a){if(this.is_initial_draw_=!0,this.readyFns_=[],null!==a&&void 0!==a||(a={}),a=Q.copyUserAttrs_(a),"string"==typeof t&&(t=document.getElementById(t)),!t)throw new Error("Constructing dygraph with a non-existent div!");this.maindiv_=t,this.file_=e,this.rollPeriod_=a.rollPeriod||Q.DEFAULT_ROLL_PERIOD,this.previousVerticalX_=-1,this.fractions_=a.fractions||!1,this.dateWindow_=a.dateWindow||null,this.annotations_=[],t.innerHTML="",""===t.style.width&&a.width&&(t.style.width=a.width+"px"),""===t.style.height&&a.height&&(t.style.height=a.height+"px"),""===t.style.height&&0===t.clientHeight&&(t.style.height=Q.DEFAULT_HEIGHT+"px",""===t.style.width&&(t.style.width=Q.DEFAULT_WIDTH+"px")),this.width_=t.clientWidth||a.width||0,this.height_=t.clientHeight||a.height||0,a.stackedGraph&&(a.fillGraph=!0),this.user_attrs_={},x.update(this.user_attrs_,a),this.attrs_={},x.updateDeep(this.attrs_,b.default),this.boundaryIds_=[],this.setIndexByName_={},this.datasetIndex_=[],this.registeredEvents_=[],this.eventListeners_={},this.attributes_=new p.default(this),this.createInterface_(),this.plugins_=[];for(var i=Q.PLUGINS.concat(this.getOption("plugins")),n=0;n<i.length;n++){var r,o=i[n];r=void 0!==o.activate?o:new o;var s={plugin:r,events:{},options:{},pluginOptions:{}},l=r.activate(this);for(var h in l)l.hasOwnProperty(h)&&(s.events[h]=l[h]);this.plugins_.push(s)}for(var n=0;n<this.plugins_.length;n++){var u=this.plugins_[n];for(var h in u.events)if(u.events.hasOwnProperty(h)){var d=u.events[h],c=[u.plugin,d];h in this.eventListeners_?this.eventListeners_[h].push(c):this.eventListeners_[h]=[c]}}this.createDragInterface_(),this.start_()},Q.prototype.cascadeEvents_=function(t,e){if(!(t in this.eventListeners_))return!1;var a={dygraph:this,cancelable:!1,defaultPrevented:!1,preventDefault:function(){if(!a.cancelable)throw"Cannot call preventDefault on non-cancelable event.";a.defaultPrevented=!0},propagationStopped:!1,stopPropagation:function(){a.propagationStopped=!0}};x.update(a,e);var i=this.eventListeners_[t];if(i)for(var n=i.length-1;n>=0;n--){var r=i[n][0],o=i[n][1];if(o.call(r,a),a.propagationStopped)break}return a.defaultPrevented},Q.prototype.getPluginInstance_=function(t){for(var e=0;e<this.plugins_.length;e++){var a=this.plugins_[e];if(a.plugin instanceof t)return a.plugin}return null},Q.prototype.isZoomed=function(t){var e=!!this.dateWindow_;if("x"===t)return e;var a=this.axes_.map(function(t){return!!t.valueRange}).indexOf(!0)>=0;if(null===t||void 0===t)return e||a;if("y"===t)return a;throw new Error("axis parameter is ["+t+"] must be null, 'x' or 'y'.")},Q.prototype.toString=function(){var t=this.maindiv_;return"[Dygraph "+(t&&t.id?t.id:t)+"]"},Q.prototype.attr_=function(t,e){return e?this.attributes_.getForSeries(t,e):this.attributes_.get(t)},Q.prototype.getOption=function(t,e){return this.attr_(t,e)},Q.prototype.getNumericOption=function(t,e){return this.getOption(t,e)},Q.prototype.getStringOption=function(t,e){return this.getOption(t,e)},Q.prototype.getBooleanOption=function(t,e){return this.getOption(t,e)},Q.prototype.getFunctionOption=function(t,e){return this.getOption(t,e)},Q.prototype.getOptionForAxis=function(t,e){return this.attributes_.getForAxis(t,e)},Q.prototype.optionsViewForAxis_=function(t){var e=this;return function(a){var i=e.user_attrs_.axes;return i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:("x"!==t||"logscale"!==a)&&(void 0!==e.user_attrs_[a]?e.user_attrs_[a]:(i=e.attrs_.axes,i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:"y"==t&&e.axes_[0].hasOwnProperty(a)?e.axes_[0][a]:"y2"==t&&e.axes_[1].hasOwnProperty(a)?e.axes_[1][a]:e.attr_(a)))}},Q.prototype.rollPeriod=function(){return this.rollPeriod_},Q.prototype.xAxisRange=function(){return this.dateWindow_?this.dateWindow_:this.xAxisExtremes()},Q.prototype.xAxisExtremes=function(){var t=this.getNumericOption("xRangePad")/this.plotter_.area.w;if(0===this.numRows())return[0-t,1+t];var e=this.rawData_[0][0],a=this.rawData_[this.rawData_.length-1][0];if(t){var i=a-e;e-=i*t,a+=i*t}return[e,a]},Q.prototype.yAxisExtremes=function(){var t=this.gatherDatasets_(this.rolledSeries_,null),e=t.extremes,a=this.axes_;this.computeYAxisRanges_(e);var i=this.axes_;return this.axes_=a,i.map(function(t){return t.extremeRange})},Q.prototype.yAxisRange=function(t){if(void 0===t&&(t=0),t<0||t>=this.axes_.length)return null;var e=this.axes_[t];return[e.computedValueRange[0],e.computedValueRange[1]]},Q.prototype.yAxisRanges=function(){for(var t=[],e=0;e<this.axes_.length;e++)t.push(this.yAxisRange(e));return t},Q.prototype.toDomCoords=function(t,e,a){return[this.toDomXCoord(t),this.toDomYCoord(e,a)]},Q.prototype.toDomXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();return e.x+(t-a[0])/(a[1]-a[0])*e.w},Q.prototype.toDomYCoord=function(t,e){var a=this.toPercentYCoord(t,e);if(null===a)return null;var i=this.plotter_.area;return i.y+a*i.h},Q.prototype.toDataCoords=function(t,e,a){return[this.toDataXCoord(t),this.toDataYCoord(e,a)]},Q.prototype.toDataXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();if(this.attributes_.getForAxis("logscale","x")){var i=(t-e.x)/e.w;return x.logRangeFraction(a[0],a[1],i)}return a[0]+(t-e.x)/e.w*(a[1]-a[0])},Q.prototype.toDataYCoord=function(t,e){if(null===t)return null;var a=this.plotter_.area,i=this.yAxisRange(e);if(void 0===e&&(e=0),this.attributes_.getForAxis("logscale",e)){var n=(t-a.y)/a.h;return x.logRangeFraction(i[1],i[0],n)}return i[0]+(a.y+a.h-t)/a.h*(i[1]-i[0])},Q.prototype.toPercentYCoord=function(t,e){if(null===t)return null;void 0===e&&(e=0);var a,i=this.yAxisRange(e);if(this.attributes_.getForAxis("logscale",e)){var n=x.log10(i[0]),r=x.log10(i[1]);a=(r-x.log10(t))/(r-n)}else a=(i[1]-t)/(i[1]-i[0]);return a},Q.prototype.toPercentXCoord=function(t){if(null===t)return null;var e,a=this.xAxisRange();if(!0===this.attributes_.getForAxis("logscale","x")){var i=x.log10(a[0]),n=x.log10(a[1]);e=(x.log10(t)-i)/(n-i)}else e=(t-a[0])/(a[1]-a[0]);return e},Q.prototype.numColumns=function(){return this.rawData_?this.rawData_[0]?this.rawData_[0].length:this.attr_("labels").length:0},Q.prototype.numRows=function(){return this.rawData_?this.rawData_.length:0},Q.prototype.getValue=function(t,e){return t<0||t>this.rawData_.length?null:e<0||e>this.rawData_[t].length?null:this.rawData_[t][e]},Q.prototype.createInterface_=function(){var t=this.maindiv_;this.graphDiv=document.createElement("div"),this.graphDiv.style.textAlign="left",this.graphDiv.style.position="relative",t.appendChild(this.graphDiv),this.canvas_=x.createCanvas(),this.canvas_.style.position="absolute",this.hidden_=this.createPlotKitCanvas_(this.canvas_),this.canvas_ctx_=x.getContext(this.canvas_),this.hidden_ctx_=x.getContext(this.hidden_),this.resizeElements_(),this.graphDiv.appendChild(this.hidden_),this.graphDiv.appendChild(this.canvas_),this.mouseEventElement_=this.createMouseEventElement_(),this.layout_=new h.default(this);var e=this;this.mouseMoveHandler_=function(t){e.mouseMove_(t)},this.mouseOutHandler_=function(t){var a=t.target||t.fromElement,i=t.relatedTarget||t.toElement;x.isNodeContainedBy(a,e.graphDiv)&&!x.isNodeContainedBy(i,e.graphDiv)&&e.mouseOut_(t)},this.addAndTrackEvent(window,"mouseout",this.mouseOutHandler_),this.addAndTrackEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),this.resizeHandler_||(this.resizeHandler_=function(t){e.resize()},this.addAndTrackEvent(window,"resize",this.resizeHandler_))},Q.prototype.resizeElements_=function(){this.graphDiv.style.width=this.width_+"px",this.graphDiv.style.height=this.height_+"px";var t=this.getNumericOption("pixelRatio"),e=t||x.getContextPixelRatio(this.canvas_ctx_);this.canvas_.width=this.width_*e,this.canvas_.height=this.height_*e,this.canvas_.style.width=this.width_+"px",this.canvas_.style.height=this.height_+"px",1!==e&&this.canvas_ctx_.scale(e,e);var a=t||x.getContextPixelRatio(this.hidden_ctx_);this.hidden_.width=this.width_*a,this.hidden_.height=this.height_*a,this.hidden_.style.width=this.width_+"px",this.hidden_.style.height=this.height_+"px",1!==a&&this.hidden_ctx_.scale(a,a)},Q.prototype.destroy=function(){this.canvas_ctx_.restore(),this.hidden_ctx_.restore();for(var t=this.plugins_.length-1;t>=0;t--){var e=this.plugins_.pop();e.plugin.destroy&&e.plugin.destroy()}this.removeTrackedEvents_(),x.removeEvent(window,"mouseout",this.mouseOutHandler_),x.removeEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),x.removeEvent(window,"resize",this.resizeHandler_),this.resizeHandler_=null,function t(e){for(;e.hasChildNodes();)t(e.firstChild),e.removeChild(e.firstChild)}(this.maindiv_);var a=function(t){for(var e in t)"object"==typeof t[e]&&(t[e]=null)};a(this.layout_),a(this.plotter_),a(this)},Q.prototype.createPlotKitCanvas_=function(t){var e=x.createCanvas();return e.style.position="absolute",e.style.top=t.style.top,e.style.left=t.style.left,
+e.width=this.width_,e.height=this.height_,e.style.width=this.width_+"px",e.style.height=this.height_+"px",e},Q.prototype.createMouseEventElement_=function(){return this.canvas_},Q.prototype.setColors_=function(){var t=this.getLabels(),e=t.length-1;this.colors_=[],this.colorsMap_={};for(var a=this.getNumericOption("colorSaturation")||1,i=this.getNumericOption("colorValue")||.5,n=Math.ceil(e/2),r=this.getOption("colors"),o=this.visibility(),s=0;s<e;s++)if(o[s]){var l=t[s+1],h=this.attributes_.getForSeries("color",l);if(!h)if(r)h=r[s%r.length];else{var u=s%2?n+(s+1)/2:Math.ceil((s+1)/2),d=1*u/(1+e);h=x.hsvToRGB(d,a,i)}this.colors_.push(h),this.colorsMap_[l]=h}},Q.prototype.getColors=function(){return this.colors_},Q.prototype.getPropertiesForSeries=function(t){for(var e=-1,a=this.getLabels(),i=1;i<a.length;i++)if(a[i]==t){e=i;break}return-1==e?null:{name:t,column:e,visible:this.visibility()[e-1],color:this.colorsMap_[t],axis:1+this.attributes_.axisForSeries(t)}},Q.prototype.createRollInterface_=function(){var t=this,e=this.roller_;e||(this.roller_=e=document.createElement("input"),e.type="text",e.style.display="none",e.className="dygraph-roller",this.graphDiv.appendChild(e));var a=this.getBooleanOption("showRoller")?"block":"none",i=this.getArea(),n={top:i.y+i.h-25+"px",left:i.x+1+"px",display:a};e.size="2",e.value=this.rollPeriod_,x.update(e.style,n),e.onchange=function(){return t.adjustRoll(e.value)}},Q.prototype.createDragInterface_=function(){var t={isZooming:!1,isPanning:!1,is2DPan:!1,dragStartX:null,dragStartY:null,dragEndX:null,dragEndY:null,dragDirection:null,prevEndX:null,prevEndY:null,prevDragDirection:null,cancelNextDblclick:!1,initialLeftmostDate:null,xUnitsPerPixel:null,dateRange:null,px:0,py:0,boundedDates:null,boundedValues:null,tarp:new O.default,initializeMouseDown:function(t,e,a){t.preventDefault?t.preventDefault():(t.returnValue=!1,t.cancelBubble=!0);var i=x.findPos(e.canvas_);a.px=i.x,a.py=i.y,a.dragStartX=x.dragGetX_(t,a),a.dragStartY=x.dragGetY_(t,a),a.cancelNextDblclick=!1,a.tarp.cover()},destroy:function(){var t=this;if((t.isZooming||t.isPanning)&&(t.isZooming=!1,t.dragStartX=null,t.dragStartY=null),t.isPanning){t.isPanning=!1,t.draggingDate=null,t.dateRange=null;for(var e=0;e<a.axes_.length;e++)delete a.axes_[e].draggingValue,delete a.axes_[e].dragValueRange}t.tarp.uncover()}},e=this.getOption("interactionModel"),a=this;for(var i in e)e.hasOwnProperty(i)&&this.addAndTrackEvent(this.mouseEventElement_,i,function(e){return function(i){e(i,a,t)}}(e[i]));if(!e.willDestroyContextMyself){var n=function(e){t.destroy()};this.addAndTrackEvent(document,"mouseup",n)}},Q.prototype.drawZoomRect_=function(t,e,a,i,n,r,o,s){var l=this.canvas_ctx_;r==x.HORIZONTAL?l.clearRect(Math.min(e,o),this.layout_.getPlotArea().y,Math.abs(e-o),this.layout_.getPlotArea().h):r==x.VERTICAL&&l.clearRect(this.layout_.getPlotArea().x,Math.min(i,s),this.layout_.getPlotArea().w,Math.abs(i-s)),t==x.HORIZONTAL?a&&e&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(Math.min(e,a),this.layout_.getPlotArea().y,Math.abs(a-e),this.layout_.getPlotArea().h)):t==x.VERTICAL&&n&&i&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(this.layout_.getPlotArea().x,Math.min(i,n),this.layout_.getPlotArea().w,Math.abs(n-i)))},Q.prototype.clearZoomRect_=function(){this.currentZoomRectArgs_=null,this.canvas_ctx_.clearRect(0,0,this.width_,this.height_)},Q.prototype.doZoomX_=function(t,e){this.currentZoomRectArgs_=null;var a=this.toDataXCoord(t),i=this.toDataXCoord(e);this.doZoomXDates_(a,i)},Q.prototype.doZoomXDates_=function(t,e){var a=this,i=this.xAxisRange(),n=[t,e],r=this.getFunctionOption("zoomCallback");this.doAnimatedZoom(i,n,null,null,function(){r&&r.call(a,t,e,a.yAxisRanges())})},Q.prototype.doZoomY_=function(t,e){var a=this;this.currentZoomRectArgs_=null;for(var i=this.yAxisRanges(),n=[],r=0;r<this.axes_.length;r++){var o=this.toDataYCoord(t,r),l=this.toDataYCoord(e,r);n.push([l,o])}var h=this.getFunctionOption("zoomCallback");this.doAnimatedZoom(null,null,i,n,function(){if(h){var t=a.xAxisRange(),e=s(t,2),i=e[0],n=e[1];h.call(a,i,n,a.yAxisRanges())}})},Q.zoomAnimationFunction=function(t,e){return(1-Math.pow(1.5,-t))/(1-Math.pow(1.5,-e))},Q.prototype.resetZoom=function(){var t=this,e=this.isZoomed("x"),a=this.isZoomed("y"),i=e||a;if(this.clearSelection(),i){var n=this.xAxisExtremes(),r=s(n,2),o=r[0],l=r[1],h=this.getBooleanOption("animatedZooms"),u=this.getFunctionOption("zoomCallback");if(!h)return this.dateWindow_=null,this.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),this.drawGraph_(),void(u&&u.call(this,o,l,this.yAxisRanges()));var d=null,c=null,p=null,g=null;e&&(d=this.xAxisRange(),c=[o,l]),a&&(p=this.yAxisRanges(),g=this.yAxisExtremes()),this.doAnimatedZoom(d,c,p,g,function(){t.dateWindow_=null,t.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),u&&u.call(t,o,l,t.yAxisRanges())})}},Q.prototype.doAnimatedZoom=function(t,e,a,i,n){var r,o,s=this,l=this.getBooleanOption("animatedZooms")?Q.ANIMATION_STEPS:1,h=[],u=[];if(null!==t&&null!==e)for(r=1;r<=l;r++)o=Q.zoomAnimationFunction(r,l),h[r-1]=[t[0]*(1-o)+o*e[0],t[1]*(1-o)+o*e[1]];if(null!==a&&null!==i)for(r=1;r<=l;r++){o=Q.zoomAnimationFunction(r,l);for(var d=[],c=0;c<this.axes_.length;c++)d.push([a[c][0]*(1-o)+o*i[c][0],a[c][1]*(1-o)+o*i[c][1]]);u[r-1]=d}x.repeatAndCleanup(function(t){if(u.length)for(var e=0;e<s.axes_.length;e++){var a=u[t][e];s.axes_[e].valueRange=[a[0],a[1]]}h.length&&(s.dateWindow_=h[t]),s.drawGraph_()},l,Q.ANIMATION_DURATION/l,n)},Q.prototype.getArea=function(){return this.plotter_.area},Q.prototype.eventToDomCoords=function(t){if(t.offsetX&&t.offsetY)return[t.offsetX,t.offsetY];var e=x.findPos(this.mouseEventElement_);return[x.pageX(t)-e.x,x.pageY(t)-e.y]},Q.prototype.findClosestRow=function(t){for(var e=1/0,a=-1,i=this.layout_.points,n=0;n<i.length;n++)for(var r=i[n],o=r.length,s=0;s<o;s++){var l=r[s];if(x.isValidPoint(l,!0)){var h=Math.abs(l.canvasx-t);h<e&&(e=h,a=l.idx)}}return a},Q.prototype.findClosestPoint=function(t,e){for(var a,i,n,r,o,s,l,h=1/0,u=this.layout_.points.length-1;u>=0;--u)for(var d=this.layout_.points[u],c=0;c<d.length;++c)r=d[c],x.isValidPoint(r)&&(i=r.canvasx-t,n=r.canvasy-e,(a=i*i+n*n)<h&&(h=a,o=r,s=u,l=r.idx));return{row:l,seriesName:this.layout_.setNames[s],point:o}},Q.prototype.findStackedPoint=function(t,e){for(var a,i,n=this.findClosestRow(t),r=0;r<this.layout_.points.length;++r){var o=this.getLeftBoundary_(r),s=n-o,l=this.layout_.points[r];if(!(s>=l.length)){var h=l[s];if(x.isValidPoint(h)){var u=h.canvasy;if(t>h.canvasx&&s+1<l.length){var d=l[s+1];if(x.isValidPoint(d)){var c=d.canvasx-h.canvasx;if(c>0){var p=(t-h.canvasx)/c;u+=p*(d.canvasy-h.canvasy)}}}else if(t<h.canvasx&&s>0){var g=l[s-1];if(x.isValidPoint(g)){var c=h.canvasx-g.canvasx;if(c>0){var p=(h.canvasx-t)/c;u+=p*(g.canvasy-h.canvasy)}}}(0===r||u<e)&&(a=h,i=r)}}}return{row:n,seriesName:this.layout_.setNames[i],point:a}},Q.prototype.mouseMove_=function(t){var e=this.layout_.points;if(void 0!==e&&null!==e){var a=this.eventToDomCoords(t),i=a[0],n=a[1],r=this.getOption("highlightSeriesOpts"),o=!1;if(r&&!this.isSeriesLocked()){var s;s=this.getBooleanOption("stackedGraph")?this.findStackedPoint(i,n):this.findClosestPoint(i,n),o=this.setSelection(s.row,s.seriesName)}else{var l=this.findClosestRow(i);o=this.setSelection(l)}var h=this.getFunctionOption("highlightCallback");h&&o&&h.call(this,t,this.lastx_,this.selPoints_,this.lastRow_,this.highlightSet_)}},Q.prototype.getLeftBoundary_=function(t){if(this.boundaryIds_[t])return this.boundaryIds_[t][0];for(var e=0;e<this.boundaryIds_.length;e++)if(void 0!==this.boundaryIds_[e])return this.boundaryIds_[e][0];return 0},Q.prototype.animateSelection_=function(t){void 0===this.fadeLevel&&(this.fadeLevel=0),void 0===this.animateId&&(this.animateId=0);var e=this.fadeLevel,a=t<0?e:10-e;if(a<=0)return void(this.fadeLevel&&this.updateSelection_(1));var i=++this.animateId,n=this,r=function(){0!==n.fadeLevel&&t<0&&(n.fadeLevel=0,n.clearSelection())};x.repeatAndCleanup(function(e){n.animateId==i&&(n.fadeLevel+=t,0===n.fadeLevel?n.clearSelection():n.updateSelection_(n.fadeLevel/10))},a,30,r)},Q.prototype.updateSelection_=function(t){this.cascadeEvents_("select",{selectedRow:-1===this.lastRow_?void 0:this.lastRow_,selectedX:-1===this.lastx_?void 0:this.lastx_,selectedPoints:this.selPoints_});var e,a=this.canvas_ctx_;if(this.getOption("highlightSeriesOpts")){a.clearRect(0,0,this.width_,this.height_);var i=1-this.getNumericOption("highlightSeriesBackgroundAlpha"),n=x.toRGB_(this.getOption("highlightSeriesBackgroundColor"));if(i){if(void 0===t)return void this.animateSelection_(1);i*=t,a.fillStyle="rgba("+n.r+","+n.g+","+n.b+","+i+")",a.fillRect(0,0,this.width_,this.height_)}this.plotter_._renderLineChart(this.highlightSet_,a)}else if(this.previousVerticalX_>=0){var r=0,o=this.attr_("labels");for(e=1;e<o.length;e++){var s=this.getNumericOption("highlightCircleSize",o[e]);s>r&&(r=s)}var l=this.previousVerticalX_;a.clearRect(l-r-1,0,2*r+2,this.height_)}if(this.selPoints_.length>0){var h=this.selPoints_[0].canvasx;for(a.save(),e=0;e<this.selPoints_.length;e++){var u=this.selPoints_[e];if(!isNaN(u.canvasy)){var d=this.getNumericOption("highlightCircleSize",u.name),c=this.getFunctionOption("drawHighlightPointCallback",u.name),p=this.plotter_.colors[u.name];c||(c=x.Circles.DEFAULT),a.lineWidth=this.getNumericOption("strokeWidth",u.name),a.strokeStyle=p,a.fillStyle=p,c.call(this,this,u.name,a,h,u.canvasy,p,d,u.idx)}}a.restore(),this.previousVerticalX_=h}},Q.prototype.setSelection=function(t,e,a){this.selPoints_=[];var i=!1;if(!1!==t&&t>=0){t!=this.lastRow_&&(i=!0),this.lastRow_=t;for(var n=0;n<this.layout_.points.length;++n){var r=this.layout_.points[n],o=t-this.getLeftBoundary_(n);if(o>=0&&o<r.length&&r[o].idx==t){var s=r[o];null!==s.yval&&this.selPoints_.push(s)}else for(var l=0;l<r.length;++l){var s=r[l];if(s.idx==t){null!==s.yval&&this.selPoints_.push(s);break}}}}else this.lastRow_>=0&&(i=!0),this.lastRow_=-1;return this.selPoints_.length?this.lastx_=this.selPoints_[0].xval:this.lastx_=-1,void 0!==e&&(this.highlightSet_!==e&&(i=!0),this.highlightSet_=e),void 0!==a&&(this.lockedSet_=a),i&&this.updateSelection_(void 0),i},Q.prototype.mouseOut_=function(t){this.getFunctionOption("unhighlightCallback")&&this.getFunctionOption("unhighlightCallback").call(this,t),this.getBooleanOption("hideOverlayOnMouseOut")&&!this.lockedSet_&&this.clearSelection()},Q.prototype.clearSelection=function(){if(this.cascadeEvents_("deselect",{}),this.lockedSet_=!1,this.fadeLevel)return void this.animateSelection_(-1);this.canvas_ctx_.clearRect(0,0,this.width_,this.height_),this.fadeLevel=0,this.selPoints_=[],this.lastx_=-1,this.lastRow_=-1,this.highlightSet_=null},Q.prototype.getSelection=function(){if(!this.selPoints_||this.selPoints_.length<1)return-1;for(var t=0;t<this.layout_.points.length;t++)for(var e=this.layout_.points[t],a=0;a<e.length;a++)if(e[a].x==this.selPoints_[0].x)return e[a].idx;return-1},Q.prototype.getHighlightSeries=function(){return this.highlightSet_},Q.prototype.isSeriesLocked=function(){return this.lockedSet_},Q.prototype.loadedEvent_=function(t){this.rawData_=this.parseCSV_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_()},Q.prototype.addXTicks_=function(){var t;t=this.dateWindow_?[this.dateWindow_[0],this.dateWindow_[1]]:this.xAxisExtremes();var e=this.optionsViewForAxis_("x"),a=e("ticker")(t[0],t[1],this.plotter_.area.w,e,this);this.layout_.setXTicks(a)},Q.prototype.getHandlerClass_=function(){return this.attr_("dataHandler")?this.attr_("dataHandler"):this.fractions_?this.getBooleanOption("errorBars")?F.default:M.default:this.getBooleanOption("customBars")?P.default:this.getBooleanOption("errorBars")?T.default:E.default},Q.prototype.predraw_=function(){var t=new Date;this.dataHandler_=new(this.getHandlerClass_()),this.layout_.computePlotArea(),this.computeYAxes_(),this.is_initial_draw_||(this.canvas_ctx_.restore(),this.hidden_ctx_.restore()),this.canvas_ctx_.save(),this.hidden_ctx_.save(),this.plotter_=new d.default(this,this.hidden_,this.hidden_ctx_,this.layout_),this.createRollInterface_(),this.cascadeEvents_("predraw"),this.rolledSeries_=[null];for(var e=1;e<this.numColumns();e++){var a=this.dataHandler_.extractSeries(this.rawData_,e,this.attributes_);this.rollPeriod_>1&&(a=this.dataHandler_.rollingAverage(a,this.rollPeriod_,this.attributes_)),this.rolledSeries_.push(a)}this.drawGraph_();var i=new Date;this.drawingTimeMs_=i-t},Q.PointType=void 0,Q.stackPoints_=function(t,e,a,i){for(var n=null,r=null,o=null,s=-1,l=0;l<t.length;++l){var h=t[l],u=h.xval;void 0===e[u]&&(e[u]=0);var d=h.yval;isNaN(d)||null===d?"none"==i?d=0:(!function(e){if(!(s>=e))for(var a=e;a<t.length;++a)if(o=null,!isNaN(t[a].yval)&&null!==t[a].yval){s=a,o=t[a];break}}(l),d=r&&o&&"none"!=i?r.yval+(o.yval-r.yval)*((u-r.xval)/(o.xval-r.xval)):r&&"all"==i?r.yval:o&&"all"==i?o.yval:0):r=h;var c=e[u];n!=u&&(c+=d,e[u]=c),n=u,h.yval_stacked=c,c>a[1]&&(a[1]=c),c<a[0]&&(a[0]=c)}},Q.prototype.gatherDatasets_=function(t,e){var a,i,n,r,o,s,l=[],h=[],u=[],d={},c=t.length-1;for(a=c;a>=1;a--)if(this.visibility()[a-1]){if(e){s=t[a];var p=e[0],g=e[1];for(n=null,r=null,i=0;i<s.length;i++)s[i][0]>=p&&null===n&&(n=i),s[i][0]<=g&&(r=i);null===n&&(n=0);for(var f=n,_=!0;_&&f>0;)f--,_=null===s[f][1];null===r&&(r=s.length-1);var v=r;for(_=!0;_&&v<s.length-1;)v++,_=null===s[v][1];f!==n&&(n=f),v!==r&&(r=v),l[a-1]=[n,r],s=s.slice(n,r+1)}else s=t[a],l[a-1]=[0,s.length-1];var y=this.attr_("labels")[a],x=this.dataHandler_.getExtremeYValues(s,e,this.getBooleanOption("stepPlot",y)),m=this.dataHandler_.seriesToPoints(s,y,l[a-1][0]);this.getBooleanOption("stackedGraph")&&(o=this.attributes_.axisForSeries(y),void 0===u[o]&&(u[o]=[]),Q.stackPoints_(m,u[o],x,this.getBooleanOption("stackedGraphNaNFill"))),d[y]=x,h[a]=m}return{points:h,extremes:d,boundaryIds:l}},Q.prototype.drawGraph_=function(){var t=new Date,e=this.is_initial_draw_;this.is_initial_draw_=!1,this.layout_.removeAllDatasets(),this.setColors_(),this.attrs_.pointSize=.5*this.getNumericOption("highlightCircleSize");var a=this.gatherDatasets_(this.rolledSeries_,this.dateWindow_),i=a.points,n=a.extremes;this.boundaryIds_=a.boundaryIds,this.setIndexByName_={};for(var r=this.attr_("labels"),o=0,s=1;s<i.length;s++)this.visibility()[s-1]&&(this.layout_.addDataset(r[s],i[s]),this.datasetIndex_[s]=o++);for(var s=0;s<r.length;s++)this.setIndexByName_[r[s]]=s;if(this.computeYAxisRanges_(n),this.layout_.setYAxes(this.axes_),this.addXTicks_(),this.layout_.evaluate(),this.renderGraph_(e),this.getStringOption("timingName")){var l=new Date;console.log(this.getStringOption("timingName")+" - drawGraph: "+(l-t)+"ms")}},Q.prototype.renderGraph_=function(t){this.cascadeEvents_("clearChart"),this.plotter_.clear();var e=this.getFunctionOption("underlayCallback");e&&e.call(this,this.hidden_ctx_,this.layout_.getPlotArea(),this,this);var a={canvas:this.hidden_,drawingContext:this.hidden_ctx_};this.cascadeEvents_("willDrawChart",a),this.plotter_.render(),this.cascadeEvents_("didDrawChart",a),this.lastRow_=-1,this.canvas_.getContext("2d").clearRect(0,0,this.width_,this.height_);var i=this.getFunctionOption("drawCallback");if(null!==i&&i.call(this,this,t),t)for(this.readyFired_=!0;this.readyFns_.length>0;){var n=this.readyFns_.pop();n(this)}},Q.prototype.computeYAxes_=function(){var t,e,a;for(this.axes_=[],t=0;t<this.attributes_.numAxes();t++)e={g:this},x.update(e,this.attributes_.axisOptions(t)),this.axes_[t]=e;for(t=0;t<this.axes_.length;t++)if(0===t)e=this.optionsViewForAxis_("y"+(t?"2":"")),(a=e("valueRange"))&&(this.axes_[t].valueRange=a);else{var i=this.user_attrs_.axes;i&&i.y2&&(a=i.y2.valueRange)&&(this.axes_[t].valueRange=a)}},Q.prototype.numAxes=function(){return this.attributes_.numAxes()},Q.prototype.axisPropertiesForSeries=function(t){return this.axes_[this.attributes_.axisForSeries(t)]},Q.prototype.computeYAxisRanges_=function(t){for(var e,a,i,n,r,o=function(t){return isNaN(parseFloat(t))},s=this.attributes_.numAxes(),l=0;l<s;l++){var h=this.axes_[l],u=this.attributes_.getForAxis("logscale",l),d=this.attributes_.getForAxis("includeZero",l),c=this.attributes_.getForAxis("independentTicks",l);i=this.attributes_.seriesForAxis(l),e=!0,n=.1;var p=this.getNumericOption("yRangePad");if(null!==p&&(e=!1,n=p/this.plotter_.area.h),0===i.length)h.extremeRange=[0,1];else{for(var g,f,_=1/0,v=-1/0,y=0;y<i.length;y++)t.hasOwnProperty(i[y])&&(g=t[i[y]][0],null!==g&&(_=Math.min(g,_)),null!==(f=t[i[y]][1])&&(v=Math.max(f,v)));d&&!u&&(_>0&&(_=0),v<0&&(v=0)),_==1/0&&(_=0),v==-1/0&&(v=1),a=v-_,0===a&&(0!==v?a=Math.abs(v):(v=1,a=1));var m=v,b=_;e&&(u?(m=v+n*a,b=_):(m=v+n*a,b=_-n*a,b<0&&_>=0&&(b=0),m>0&&v<=0&&(m=0))),h.extremeRange=[b,m]}if(h.valueRange){var w=o(h.valueRange[0])?h.extremeRange[0]:h.valueRange[0],A=o(h.valueRange[1])?h.extremeRange[1]:h.valueRange[1];h.computedValueRange=[w,A]}else h.computedValueRange=h.extremeRange;if(!e)if(u){w=h.computedValueRange[0],A=h.computedValueRange[1];var O=n/(2*n-1),D=(n-1)/(2*n-1);h.computedValueRange[0]=x.logRangeFraction(w,A,O),h.computedValueRange[1]=x.logRangeFraction(w,A,D)}else w=h.computedValueRange[0],A=h.computedValueRange[1],a=A-w,h.computedValueRange[0]=w-a*n,h.computedValueRange[1]=A+a*n;if(c){h.independentTicks=c;var E=this.optionsViewForAxis_("y"+(l?"2":"")),L=E("ticker");h.ticks=L(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,E,this),r||(r=h)}}if(void 0===r)throw'Configuration Error: At least one axis has to have the "independentTicks" option activated.';for(var l=0;l<s;l++){var h=this.axes_[l];if(!h.independentTicks){for(var E=this.optionsViewForAxis_("y"+(l?"2":"")),L=E("ticker"),T=r.ticks,S=r.computedValueRange[1]-r.computedValueRange[0],P=h.computedValueRange[1]-h.computedValueRange[0],C=[],M=0;M<T.length;M++){var N=(T[M].v-r.computedValueRange[0])/S,F=h.computedValueRange[0]+N*P;C.push(F)}h.ticks=L(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,E,this,C)}}},Q.prototype.detectTypeFromString_=function(t){var e=!1,a=t.indexOf("-");a>0&&"e"!=t[a-1]&&"E"!=t[a-1]||t.indexOf("/")>=0||isNaN(parseFloat(t))?e=!0:8==t.length&&t>"19700101"&&t<"20371231"&&(e=!0),this.setXAxisOptions_(e)},Q.prototype.setXAxisOptions_=function(t){t?(this.attrs_.xValueParser=x.dateParser,this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter):(this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter)},Q.prototype.parseCSV_=function(t){var e,a,i=[],n=x.detectLineDelimiter(t),r=t.split(n||"\n"),o=this.getStringOption("delimiter");-1==r[0].indexOf(o)&&r[0].indexOf("\t")>=0&&(o="\t");var s=0;"labels"in this.user_attrs_||(s=1,this.attrs_.labels=r[0].split(o),this.attributes_.reparseSeries());for(var l,h=!1,u=this.attr_("labels").length,d=!1,c=s;c<r.length;c++){var p=r[c];if(c,0!==p.length&&"#"!=p[0]){var g=p.split(o);if(!(g.length<2)){var f=[];if(h||(this.detectTypeFromString_(g[0]),l=this.getFunctionOption("xValueParser"),h=!0),f[0]=l(g[0],this),this.fractions_)for(a=1;a<g.length;a++)e=g[a].split("/"),2!=e.length?(console.error('Expected fractional "num/den" values in CSV data but found a value \''+g[a]+"' on line "+(1+c)+" ('"+p+"') which is not of this form."),f[a]=[0,0]):f[a]=[x.parseFloat_(e[0],c,p),x.parseFloat_(e[1],c,p)];else if(this.getBooleanOption("errorBars"))for(g.length%2!=1&&console.error("Expected alternating (value, stdev.) pairs in CSV data but line "+(1+c)+" has an odd number of values ("+(g.length-1)+"): '"+p+"'"),a=1;a<g.length;a+=2)f[(a+1)/2]=[x.parseFloat_(g[a],c,p),x.parseFloat_(g[a+1],c,p)];else if(this.getBooleanOption("customBars"))for(a=1;a<g.length;a++){var _=g[a];/^ *$/.test(_)?f[a]=[null,null,null]:(e=_.split(";"),3==e.length?f[a]=[x.parseFloat_(e[0],c,p),x.parseFloat_(e[1],c,p),x.parseFloat_(e[2],c,p)]:console.warn('When using customBars, values must be either blank or "low;center;high" tuples (got "'+_+'" on line '+(1+c)))}else for(a=1;a<g.length;a++)f[a]=x.parseFloat_(g[a],c,p);if(i.length>0&&f[0]<i[i.length-1][0]&&(d=!0),f.length!=u&&console.error("Number of columns in line "+c+" ("+f.length+") does not agree with number of labels ("+u+") "+p),0===c&&this.attr_("labels")){var v=!0;for(a=0;v&&a<f.length;a++)f[a]&&(v=!1);if(v){console.warn("The dygraphs 'labels' option is set, but the first row of CSV data ('"+p+"') appears to also contain labels. Will drop the CSV labels and use the option labels.");continue}}i.push(f)}}}return d&&(console.warn("CSV is out of order; order it correctly to speed loading."),i.sort(function(t,e){return t[0]-e[0]})),i},Q.prototype.parseArray_=function(t){if(0===t.length)return console.error("Can't plot empty data set"),null;if(0===t[0].length)return console.error("Data set cannot contain an empty row"),null;o(t);var e;if(null===this.attr_("labels")){for(console.warn("Using default labels. Set labels explicitly via 'labels' in the options parameter"),this.attrs_.labels=["X"],e=1;e<t[0].length;e++)this.attrs_.labels.push("Y"+e);this.attributes_.reparseSeries()}else{var a=this.attr_("labels");if(a.length!=t[0].length)return console.error("Mismatch between number of labels ("+a+") and number of columns in array ("+t[0].length+")"),null}if(x.isDateLike(t[0][0])){this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter;var i=x.clone(t);for(e=0;e<t.length;e++){if(0===i[e].length)return console.error("Row "+(1+e)+" of data is empty"),null;if(null===i[e][0]||"function"!=typeof i[e][0].getTime||isNaN(i[e][0].getTime()))return console.error("x value in row "+(1+e)+" is not a Date"),null;i[e][0]=i[e][0].getTime()}return i}return this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=x.numberAxisLabelFormatter,t},Q.prototype.parseDataTable_=function(t){var e=t.getNumberOfColumns(),a=t.getNumberOfRows(),i=t.getColumnType(0);if("date"==i||"datetime"==i)this.attrs_.xValueParser=x.dateParser,this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter;else{if("number"!=i)throw new Error("only 'date', 'datetime' and 'number' types are supported for column 1 of DataTable input (Got '"+i+"')");this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter}var n,r,o=[],s={},l=!1;for(n=1;n<e;n++){var h=t.getColumnType(n);if("number"==h)o.push(n);else{if("string"!=h||!this.getBooleanOption("displayAnnotations"))throw new Error("Only 'number' is supported as a dependent type with Gviz. 'string' is only supported if displayAnnotations is true");var u=o[o.length-1];s.hasOwnProperty(u)?s[u].push(n):s[u]=[n],l=!0}}var d=[t.getColumnLabel(0)];for(n=0;n<o.length;n++)d.push(t.getColumnLabel(o[n])),this.getBooleanOption("errorBars")&&(n+=1);this.attrs_.labels=d,e=d.length;var c=[],p=!1,g=[];for(n=0;n<a;n++){var f=[];if(void 0!==t.getValue(n,0)&&null!==t.getValue(n,0)){if("date"==i||"datetime"==i?f.push(t.getValue(n,0).getTime()):f.push(t.getValue(n,0)),this.getBooleanOption("errorBars"))for(r=0;r<e-1;r++)f.push([t.getValue(n,1+2*r),t.getValue(n,2+2*r)]);else{for(r=0;r<o.length;r++){var _=o[r];if(f.push(t.getValue(n,_)),l&&s.hasOwnProperty(_)&&null!==t.getValue(n,s[_][0])){var y={};y.series=t.getColumnLabel(_),y.xval=f[0],y.shortText=function(t){var e=String.fromCharCode(65+t%26);for(t=Math.floor(t/26);t>0;)e=String.fromCharCode(65+(t-1)%26)+e.toLowerCase(),t=Math.floor((t-1)/26);return e}(g.length),y.text="";for(var m=0;m<s[_].length;m++)m&&(y.text+="\n"),y.text+=t.getValue(n,s[_][m]);g.push(y)}}for(r=0;r<f.length;r++)isFinite(f[r])||(f[r]=null)}c.length>0&&f[0]<c[c.length-1][0]&&(p=!0),c.push(f)}else console.warn("Ignoring row "+n+" of DataTable because of undefined or null first column.")}p&&(console.warn("DataTable is out of order; order it correctly to speed loading."),c.sort(function(t,e){return t[0]-e[0]})),this.rawData_=c,g.length>0&&this.setAnnotations(g,!0),this.attributes_.reparseSeries()},Q.prototype.cascadeDataDidUpdateEvent_=function(){this.cascadeEvents_("dataDidUpdate",{})},Q.prototype.start_=function(){var t=this.file_;if("function"==typeof t&&(t=t()),x.isArrayLike(t))this.rawData_=this.parseArray_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("object"==typeof t&&"function"==typeof t.getColumnRange)this.parseDataTable_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("string"==typeof t){var e=x.detectLineDelimiter(t);if(e)this.loadedEvent_(t);else{var a;a=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");var i=this;a.onreadystatechange=function(){4==a.readyState&&(200!==a.status&&0!==a.status||i.loadedEvent_(a.responseText))},a.open("GET",t,!0),a.send(null)}}else console.error("Unknown data format: "+typeof t)},Q.prototype.updateOptions=function(t,e){void 0===e&&(e=!1);var a=t.file,i=Q.copyUserAttrs_(t);"rollPeriod"in i&&(this.rollPeriod_=i.rollPeriod),"dateWindow"in i&&(this.dateWindow_=i.dateWindow);var n=x.isPixelChangingOptionList(this.attr_("labels"),i);x.updateDeep(this.user_attrs_,i),this.attributes_.reparseSeries(),a?(this.cascadeEvents_("dataWillUpdate",{}),this.file_=a,e||this.start_()):e||(n?this.predraw_():this.renderGraph_(!1))},Q.copyUserAttrs_=function(t){var e={};for(var a in t)t.hasOwnProperty(a)&&"file"!=a&&t.hasOwnProperty(a)&&(e[a]=t[a]);return e},Q.prototype.resize=function(t,e){if(!this.resize_lock){this.resize_lock=!0,null===t!=(null===e)&&(console.warn("Dygraph.resize() should be called with zero parameters or two non-NULL parameters. Pretending it was zero."),t=e=null);var a=this.width_,i=this.height_;t?(this.maindiv_.style.width=t+"px",this.maindiv_.style.height=e+"px",this.width_=t,this.height_=e):(this.width_=this.maindiv_.clientWidth,this.height_=this.maindiv_.clientHeight),a==this.width_&&i==this.height_||(this.resizeElements_(),this.predraw_()),this.resize_lock=!1}},Q.prototype.adjustRoll=function(t){this.rollPeriod_=t,this.predraw_()},Q.prototype.visibility=function(){for(this.getOption("visibility")||(this.attrs_.visibility=[]);this.getOption("visibility").length<this.numColumns()-1;)this.attrs_.visibility.push(!0);return this.getOption("visibility")},Q.prototype.setVisibility=function(t,e){var a=this.visibility(),i=!1;if(Array.isArray(t)||(null!==t&&"object"==typeof t?i=!0:t=[t]),i)for(var n in t)t.hasOwnProperty(n)&&(n<0||n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]);else for(var n=0;n<t.length;n++)"boolean"==typeof t[n]?n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]:t[n]<0||t[n]>=a.length?console.warn("Invalid series number in setVisibility: "+t[n]):a[t[n]]=e;this.predraw_()},Q.prototype.size=function(){return{width:this.width_,height:this.height_}},Q.prototype.setAnnotations=function(t,e){if(this.annotations_=t,!this.layout_)return void console.warn("Tried to setAnnotations before dygraph was ready. Try setting them in a ready() block. See dygraphs.com/tests/annotation.html");this.layout_.setAnnotations(this.annotations_),e||this.predraw_()},Q.prototype.annotations=function(){return this.annotations_},Q.prototype.getLabels=function(){var t=this.attr_("labels");return t?t.slice():null},Q.prototype.indexFromSetName=function(t){return this.setIndexByName_[t]},Q.prototype.getRowForX=function(t){for(var e=0,a=this.numRows()-1;e<=a;){var i=a+e>>1,n=this.getValue(i,0);if(n<t)e=i+1;else if(n>t)a=i-1;else{if(e==i)return i;a=i}}return null},Q.prototype.ready=function(t){this.is_initial_draw_?this.readyFns_.push(t):t.call(this,this)},Q.prototype.addAndTrackEvent=function(t,e,a){x.addEvent(t,e,a),this.registeredEvents_.push({elem:t,type:e,fn:a})},Q.prototype.removeTrackedEvents_=function(){if(this.registeredEvents_)for(var t=0;t<this.registeredEvents_.length;t++){var e=this.registeredEvents_[t];x.removeEvent(e.elem,e.type,e.fn)}this.registeredEvents_=[]},Q.PLUGINS=[U.default,X.default,j.default,Z.default,H.default,G.default],Q.GVizChart=q.default,Q.DASHED_LINE=x.DASHED_LINE,Q.DOT_DASH_LINE=x.DOT_DASH_LINE,Q.dateAxisLabelFormatter=x.dateAxisLabelFormatter,Q.toRGB_=x.toRGB_,Q.findPos=x.findPos,Q.pageX=x.pageX,Q.pageY=x.pageY,Q.dateString_=x.dateString_,Q.defaultInteractionModel=f.default.defaultModel,Q.nonInteractiveModel=Q.nonInteractiveModel_=f.default.nonInteractiveModel_,Q.Circles=x.Circles,Q.Plugins={Legend:U.default,Axes:X.default,Annotations:H.default,ChartLabels:Z.default,Grid:G.default,RangeSelector:j.default},Q.DataHandlers={DefaultHandler:E.default,BarsHandler:R.default,CustomBarsHandler:P.default,DefaultFractionHandler:M.default,ErrorBarsHandler:T.default,FractionsBarsHandler:F.default},Q.startPan=f.default.startPan,Q.startZoom=f.default.startZoom,Q.movePan=f.default.movePan,Q.moveZoom=f.default.moveZoom,Q.endPan=f.default.endPan,Q.endZoom=f.default.endZoom,Q.numericLinearTicks=v.numericLinearTicks,Q.numericTicks=v.numericTicks,Q.dateTicker=v.dateTicker,Q.Granularity=v.Granularity,Q.getDateAxis=v.getDateAxis,Q.floatFormat=x.floatFormat,a.default=Q,e.exports=a.default}).call(this,t("_process"))},{"./datahandler/bars":5,"./datahandler/bars-custom":2,"./datahandler/bars-error":3,"./datahandler/bars-fractions":4,"./datahandler/default":8,"./datahandler/default-fractions":7,"./dygraph-canvas":9,"./dygraph-default-attrs":10,"./dygraph-gviz":11,"./dygraph-interaction-model":12,"./dygraph-layout":13,"./dygraph-options":15,"./dygraph-options-reference":14,"./dygraph-tickers":16,"./dygraph-utils":17,"./iframe-tarp":19,"./plugins/annotations":20,"./plugins/axes":21,"./plugins/chart-labels":22,"./plugins/grid":23,"./plugins/legend":24,"./plugins/range-selector":25,_process:1}],19:[function(t,e,a){"use strict";function i(){this.tarps=[]}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n);i.prototype.cover=function(){for(var t=document.getElementsByTagName("iframe"),e=0;e<t.length;e++){var a=t[e],i=r.findPos(a),n=i.x,o=i.y,s=a.offsetWidth,l=a.offsetHeight,h=document.createElement("div");h.style.position="absolute",h.style.left=n+"px",h.style.top=o+"px",h.style.width=s+"px",h.style.height=l+"px",h.style.zIndex=999,document.body.appendChild(h),this.tarps.push(h)}},i.prototype.uncover=function(){for(var t=0;t<this.tarps.length;t++)this.tarps[t].parentNode.removeChild(this.tarps[t]);this.tarps=[]},a.default=i,e.exports=a.default},{"./dygraph-utils":17}],20:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.annotations_=[]};i.prototype.toString=function(){return"Annotations Plugin"},i.prototype.activate=function(t){return{clearChart:this.clearChart,didDrawChart:this.didDrawChart}},i.prototype.detachLabels=function(){for(var t=0;t<this.annotations_.length;t++){var e=this.annotations_[t];e.parentNode&&e.parentNode.removeChild(e),this.annotations_[t]=null}this.annotations_=[]},i.prototype.clearChart=function(t){this.detachLabels()},i.prototype.didDrawChart=function(t){var e=t.dygraph,a=e.layout_.annotated_points;if(a&&0!==a.length)for(var i=t.canvas.parentNode,n=function(t,a,i){return function(n){var r=i.annotation;r.hasOwnProperty(t)?r[t](r,i,e,n):e.getOption(a)&&e.getOption(a)(r,i,e,n)}},r=t.dygraph.getArea(),o={},s=0;s<a.length;s++){var l=a[s];if(!(l.canvasx<r.x||l.canvasx>r.x+r.w||l.canvasy<r.y||l.canvasy>r.y+r.h)){var h=l.annotation,u=6;h.hasOwnProperty("tickHeight")&&(u=h.tickHeight);var d=document.createElement("div")
+;d.style.fontSize=e.getOption("axisLabelFontSize")+"px";var c="dygraph-annotation";h.hasOwnProperty("icon")||(c+=" dygraphDefaultAnnotation dygraph-default-annotation"),h.hasOwnProperty("cssClass")&&(c+=" "+h.cssClass),d.className=c;var p=h.hasOwnProperty("width")?h.width:16,g=h.hasOwnProperty("height")?h.height:16;if(h.hasOwnProperty("icon")){var f=document.createElement("img");f.src=h.icon,f.width=p,f.height=g,d.appendChild(f)}else l.annotation.hasOwnProperty("shortText")&&d.appendChild(document.createTextNode(l.annotation.shortText));var _=l.canvasx-p/2;d.style.left=_+"px";var v=0;if(h.attachAtBottom){var y=r.y+r.h-g-u;o[_]?y-=o[_]:o[_]=0,o[_]+=u+g,v=y}else v=l.canvasy-g-u;d.style.top=v+"px",d.style.width=p+"px",d.style.height=g+"px",d.title=l.annotation.text,d.style.color=e.colorsMap_[l.name],d.style.borderColor=e.colorsMap_[l.name],h.div=d,e.addAndTrackEvent(d,"click",n("clickHandler","annotationClickHandler",l)),e.addAndTrackEvent(d,"mouseover",n("mouseOverHandler","annotationMouseOverHandler",l)),e.addAndTrackEvent(d,"mouseout",n("mouseOutHandler","annotationMouseOutHandler",l)),e.addAndTrackEvent(d,"dblclick",n("dblClickHandler","annotationDblClickHandler",l)),i.appendChild(d),this.annotations_.push(d);var x=t.drawingContext;if(x.save(),x.strokeStyle=h.hasOwnProperty("tickColor")?h.tickColor:e.colorsMap_[l.name],x.lineWidth=h.hasOwnProperty("tickWidth")?h.tickWidth:e.getOption("strokeWidth"),x.beginPath(),h.attachAtBottom){var y=v+g;x.moveTo(l.canvasx,y),x.lineTo(l.canvasx,y+u)}else x.moveTo(l.canvasx,l.canvasy),x.lineTo(l.canvasx,l.canvasy-2-u);x.closePath(),x.stroke(),x.restore()}}},i.prototype.destroy=function(){this.detachLabels()},a.default=i,e.exports=a.default},{}],21:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("../dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(){this.xlabels_=[],this.ylabels_=[]};r.prototype.toString=function(){return"Axes Plugin"},r.prototype.activate=function(t){return{layout:this.layout,clearChart:this.clearChart,willDrawChart:this.willDrawChart}},r.prototype.layout=function(t){var e=t.dygraph;if(e.getOptionForAxis("drawAxis","y")){var a=e.getOptionForAxis("axisLabelWidth","y")+2*e.getOptionForAxis("axisTickSize","y");t.reserveSpaceLeft(a)}if(e.getOptionForAxis("drawAxis","x")){var i;i=e.getOption("xAxisHeight")?e.getOption("xAxisHeight"):e.getOptionForAxis("axisLabelFontSize","x")+2*e.getOptionForAxis("axisTickSize","x"),t.reserveSpaceBottom(i)}if(2==e.numAxes()){if(e.getOptionForAxis("drawAxis","y2")){var a=e.getOptionForAxis("axisLabelWidth","y2")+2*e.getOptionForAxis("axisTickSize","y2");t.reserveSpaceRight(a)}}else e.numAxes()>2&&e.error("Only two y-axes are supported at this time. (Trying to use "+e.numAxes()+")")},r.prototype.detachLabels=function(){function t(t){for(var e=0;e<t.length;e++){var a=t[e];a.parentNode&&a.parentNode.removeChild(a)}}t(this.xlabels_),t(this.ylabels_),this.xlabels_=[],this.ylabels_=[]},r.prototype.clearChart=function(t){this.detachLabels()},r.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i=this,r=t.dygraph;if(r.getOptionForAxis("drawAxis","x")||r.getOptionForAxis("drawAxis","y")||r.getOptionForAxis("drawAxis","y2")){var o,s,l,h=t.drawingContext,u=t.canvas.parentNode,d=r.width_,c=r.height_,p=function(t){return{position:"absolute",fontSize:r.getOptionForAxis("axisLabelFontSize",t)+"px",width:r.getOptionForAxis("axisLabelWidth",t)+"px"}},g={x:p("x"),y:p("y"),y2:p("y2")},f=function(t,e,a){var i=document.createElement("div"),r=g["y2"==a?"y2":e];n.update(i.style,r);var o=document.createElement("div");return o.className="dygraph-axis-label dygraph-axis-label-"+e+(a?" dygraph-axis-label-"+a:""),o.innerHTML=t,i.appendChild(o),i};h.save();var _=r.layout_,v=t.dygraph.plotter_.area,y=function(t){return function(e){return r.getOptionForAxis(e,t)}};if(r.getOptionForAxis("drawAxis","y")){if(_.yticks&&_.yticks.length>0){var x=r.numAxes(),m=[y("y"),y("y2")];_.yticks.forEach(function(t){if(void 0!==t.label){s=v.x;var e="y1",a=m[0];1==t.axis&&(s=v.x+v.w,-1,e="y2",a=m[1]);var n=a("axisLabelFontSize");l=v.y+t.pos*v.h,o=f(t.label,"y",2==x?e:null);var r=l-n/2;r<0&&(r=0),r+n+3>c?o.style.bottom="0":o.style.top=r+"px",0===t.axis?(o.style.left=v.x-a("axisLabelWidth")-a("axisTickSize")+"px",o.style.textAlign="right"):1==t.axis&&(o.style.left=v.x+v.w+a("axisTickSize")+"px",o.style.textAlign="left"),o.style.width=a("axisLabelWidth")+"px",u.appendChild(o),i.ylabels_.push(o)}});var b=this.ylabels_[0],w=r.getOptionForAxis("axisLabelFontSize","y");parseInt(b.style.top,10)+w>c-w&&(b.style.top=parseInt(b.style.top,10)-w/2+"px")}var A;if(r.getOption("drawAxesAtZero")){var O=r.toPercentXCoord(0);(O>1||O<0||isNaN(O))&&(O=0),A=e(v.x+O*v.w)}else A=e(v.x);h.strokeStyle=r.getOptionForAxis("axisLineColor","y"),h.lineWidth=r.getOptionForAxis("axisLineWidth","y"),h.beginPath(),h.moveTo(A,a(v.y)),h.lineTo(A,a(v.y+v.h)),h.closePath(),h.stroke(),2==r.numAxes()&&(h.strokeStyle=r.getOptionForAxis("axisLineColor","y2"),h.lineWidth=r.getOptionForAxis("axisLineWidth","y2"),h.beginPath(),h.moveTo(a(v.x+v.w),a(v.y)),h.lineTo(a(v.x+v.w),a(v.y+v.h)),h.closePath(),h.stroke())}if(r.getOptionForAxis("drawAxis","x")){if(_.xticks){var D=y("x");_.xticks.forEach(function(t){if(void 0!==t.label){s=v.x+t.pos*v.w,l=v.y+v.h,o=f(t.label,"x"),o.style.textAlign="center",o.style.top=l+D("axisTickSize")+"px";var e=s-D("axisLabelWidth")/2;e+D("axisLabelWidth")>d&&(e=d-D("axisLabelWidth"),o.style.textAlign="right"),e<0&&(e=0,o.style.textAlign="left"),o.style.left=e+"px",o.style.width=D("axisLabelWidth")+"px",u.appendChild(o),i.xlabels_.push(o)}})}h.strokeStyle=r.getOptionForAxis("axisLineColor","x"),h.lineWidth=r.getOptionForAxis("axisLineWidth","x"),h.beginPath();var E;if(r.getOption("drawAxesAtZero")){var O=r.toPercentYCoord(0,0);(O>1||O<0)&&(O=1),E=a(v.y+O*v.h)}else E=a(v.y+v.h);h.moveTo(e(v.x),E),h.lineTo(e(v.x+v.w),E),h.closePath(),h.stroke()}h.restore()}},a.default=r,e.exports=a.default},{"../dygraph-utils":17}],22:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};i.prototype.toString=function(){return"ChartLabels Plugin"},i.prototype.activate=function(t){return{layout:this.layout,didDrawChart:this.didDrawChart}};var n=function(t){var e=document.createElement("div");return e.style.position="absolute",e.style.left=t.x+"px",e.style.top=t.y+"px",e.style.width=t.w+"px",e.style.height=t.h+"px",e};i.prototype.detachLabels_=function(){for(var t=[this.title_div_,this.xlabel_div_,this.ylabel_div_,this.y2label_div_],e=0;e<t.length;e++){var a=t[e];a&&(a.parentNode&&a.parentNode.removeChild(a))}this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};var r=function(t,e,a,i,n){var r=document.createElement("div");r.style.position="absolute",r.style.left=1==a?"0px":e.x+"px",r.style.top=e.y+"px",r.style.width=e.w+"px",r.style.height=e.h+"px",r.style.fontSize=t.getOption("yLabelWidth")-2+"px";var o=document.createElement("div");o.style.position="absolute",o.style.width=e.h+"px",o.style.height=e.w+"px",o.style.top=e.h/2-e.w/2+"px",o.style.left=e.w/2-e.h/2+"px",o.className="dygraph-label-rotate-"+(1==a?"right":"left");var s=document.createElement("div");return s.className=i,s.innerHTML=n,o.appendChild(s),r.appendChild(o),r};i.prototype.layout=function(t){this.detachLabels_();var e=t.dygraph,a=t.chart_div;if(e.getOption("title")){var i=t.reserveSpaceTop(e.getOption("titleHeight"));this.title_div_=n(i),this.title_div_.style.fontSize=e.getOption("titleHeight")-8+"px";var o=document.createElement("div");o.className="dygraph-label dygraph-title",o.innerHTML=e.getOption("title"),this.title_div_.appendChild(o),a.appendChild(this.title_div_)}if(e.getOption("xlabel")){var s=t.reserveSpaceBottom(e.getOption("xLabelHeight"));this.xlabel_div_=n(s),this.xlabel_div_.style.fontSize=e.getOption("xLabelHeight")-2+"px";var o=document.createElement("div");o.className="dygraph-label dygraph-xlabel",o.innerHTML=e.getOption("xlabel"),this.xlabel_div_.appendChild(o),a.appendChild(this.xlabel_div_)}if(e.getOption("ylabel")){var l=t.reserveSpaceLeft(0);this.ylabel_div_=r(e,l,1,"dygraph-label dygraph-ylabel",e.getOption("ylabel")),a.appendChild(this.ylabel_div_)}if(e.getOption("y2label")&&2==e.numAxes()){var h=t.reserveSpaceRight(0);this.y2label_div_=r(e,h,2,"dygraph-label dygraph-y2label",e.getOption("y2label")),a.appendChild(this.y2label_div_)}},i.prototype.didDrawChart=function(t){var e=t.dygraph;this.title_div_&&(this.title_div_.children[0].innerHTML=e.getOption("title")),this.xlabel_div_&&(this.xlabel_div_.children[0].innerHTML=e.getOption("xlabel")),this.ylabel_div_&&(this.ylabel_div_.children[0].children[0].innerHTML=e.getOption("ylabel")),this.y2label_div_&&(this.y2label_div_.children[0].children[0].innerHTML=e.getOption("y2label"))},i.prototype.clearChart=function(){},i.prototype.destroy=function(){this.detachLabels_()},a.default=i,e.exports=a.default},{}],23:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){};i.prototype.toString=function(){return"Gridline Plugin"},i.prototype.activate=function(t){return{willDrawChart:this.willDrawChart}},i.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i,n,r,o,s=t.dygraph,l=t.drawingContext,h=s.layout_,u=t.dygraph.plotter_.area;if(s.getOptionForAxis("drawGrid","y")){for(var d=["y","y2"],c=[],p=[],g=[],f=[],_=[],r=0;r<d.length;r++)g[r]=s.getOptionForAxis("drawGrid",d[r]),g[r]&&(c[r]=s.getOptionForAxis("gridLineColor",d[r]),p[r]=s.getOptionForAxis("gridLineWidth",d[r]),_[r]=s.getOptionForAxis("gridLinePattern",d[r]),f[r]=_[r]&&_[r].length>=2);o=h.yticks,l.save(),o.forEach(function(t){if(t.has_tick){var r=t.axis;g[r]&&(l.save(),f[r]&&l.setLineDash&&l.setLineDash(_[r]),l.strokeStyle=c[r],l.lineWidth=p[r],i=e(u.x),n=a(u.y+t.pos*u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i+u.w,n),l.stroke(),l.restore())}}),l.restore()}if(s.getOptionForAxis("drawGrid","x")){o=h.xticks,l.save();var _=s.getOptionForAxis("gridLinePattern","x"),f=_&&_.length>=2;f&&l.setLineDash&&l.setLineDash(_),l.strokeStyle=s.getOptionForAxis("gridLineColor","x"),l.lineWidth=s.getOptionForAxis("gridLineWidth","x"),o.forEach(function(t){t.has_tick&&(i=e(u.x+t.pos*u.w),n=a(u.y+u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i,u.y),l.closePath(),l.stroke())}),f&&l.setLineDash&&l.setLineDash([]),l.restore()}},i.prototype.destroy=function(){},a.default=i,e.exports=a.default},{}],24:[function(t,e,a){"use strict";function i(t,e,a){if(!t||t.length<=1)return'<div class="dygraph-legend-line" style="border-bottom-color: '+e+';"></div>';var i,n,r,o,s,l=0,h=0,u=[];for(i=0;i<=t.length;i++)l+=t[i%t.length];if((s=Math.floor(a/(l-t[0])))>1){for(i=0;i<t.length;i++)u[i]=t[i]/a;h=u.length}else{for(s=1,i=0;i<t.length;i++)u[i]=t[i]/l;h=u.length+1}var d="";for(n=0;n<s;n++)for(i=0;i<h;i+=2)r=u[i%u.length],o=i<t.length?u[(i+1)%u.length]:0,d+='<div class="dygraph-legend-dash" style="margin-right: '+o+"em; padding-left: "+r+'em;"></div>';return d}Object.defineProperty(a,"__esModule",{value:!0});var n=t("../dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n),o=function(){this.legend_div_=null,this.is_generated_div_=!1};o.prototype.toString=function(){return"Legend Plugin"},o.prototype.activate=function(t){var e,a=t.getOption("labelsDiv");return a&&null!==a?e="string"==typeof a||a instanceof String?document.getElementById(a):a:(e=document.createElement("div"),e.className="dygraph-legend",t.graphDiv.appendChild(e),this.is_generated_div_=!0),this.legend_div_=e,this.one_em_width_=10,{select:this.select,deselect:this.deselect,predraw:this.predraw,didDrawChart:this.didDrawChart}};var s=function(t){var e=document.createElement("span");e.setAttribute("style","margin: 0; padding: 0 0 0 1em; border: 0;"),t.appendChild(e);var a=e.offsetWidth;return t.removeChild(e),a},l=function(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")};o.prototype.select=function(t){var e=t.selectedX,a=t.selectedPoints,i=t.selectedRow,n=t.dygraph.getOption("legend");if("never"===n)return void(this.legend_div_.style.display="none");if("follow"===n){var r=t.dygraph.plotter_.area,s=this.legend_div_.offsetWidth,l=t.dygraph.getOptionForAxis("axisLabelWidth","y"),h=a[0].x*r.w+50,u=a[0].y*r.h-50;h+s+1>r.w&&(h=h-100-s-(l-r.x)),t.dygraph.graphDiv.appendChild(this.legend_div_),this.legend_div_.style.left=l+h+"px",this.legend_div_.style.top=u+"px"}var d=o.generateLegendHTML(t.dygraph,e,a,this.one_em_width_,i);this.legend_div_.innerHTML=d,this.legend_div_.style.display=""},o.prototype.deselect=function(t){"always"!==t.dygraph.getOption("legend")&&(this.legend_div_.style.display="none");var e=s(this.legend_div_);this.one_em_width_=e;var a=o.generateLegendHTML(t.dygraph,void 0,void 0,e,null);this.legend_div_.innerHTML=a},o.prototype.didDrawChart=function(t){this.deselect(t)},o.prototype.predraw=function(t){if(this.is_generated_div_){t.dygraph.graphDiv.appendChild(this.legend_div_);var e=t.dygraph.getArea(),a=this.legend_div_.offsetWidth;this.legend_div_.style.left=e.x+e.w-a-1+"px",this.legend_div_.style.top=e.y+"px"}},o.prototype.destroy=function(){this.legend_div_=null},o.generateLegendHTML=function(t,e,a,n,s){var h={dygraph:t,x:e,series:[]},u={},d=t.getLabels();if(d)for(var c=1;c<d.length;c++){var p=t.getPropertiesForSeries(d[c]),g=t.getOption("strokePattern",d[c]),f={dashHTML:i(g,p.color,n),label:d[c],labelHTML:l(d[c]),isVisible:p.visible,color:p.color};h.series.push(f),u[d[c]]=f}if(void 0!==e){var _=t.optionsViewForAxis_("x"),v=_("valueFormatter");h.xHTML=v.call(t,e,_,d[0],t,s,0);for(var y=[],x=t.numAxes(),c=0;c<x;c++)y[c]=t.optionsViewForAxis_("y"+(c?1+c:""));var m=t.getOption("labelsShowZeroValues"),b=t.getHighlightSeries();for(c=0;c<a.length;c++){var w=a[c],f=u[w.name];if(f.y=w.yval,0===w.yval&&!m||isNaN(w.canvasy))f.isVisible=!1;else{var p=t.getPropertiesForSeries(w.name),A=y[p.axis-1],O=A("valueFormatter"),D=O.call(t,w.yval,A,w.name,t,s,d.indexOf(w.name));r.update(f,{yHTML:D}),w.name==b&&(f.isHighlighted=!0)}}}return(t.getOption("legendFormatter")||o.defaultFormatter).call(t,h)},o.defaultFormatter=function(t){var e=t.dygraph;if(!0!==e.getOption("showLabelsOnHighlight"))return"";var a,i=e.getOption("labelsSeparateLines");if(void 0===t.x){if("always"!=e.getOption("legend"))return"";a="";for(var n=0;n<t.series.length;n++){var r=t.series[n];r.isVisible&&(""!==a&&(a+=i?"<br/>":" "),a+="<span style='font-weight: bold; color: "+r.color+";'>"+r.dashHTML+" "+r.labelHTML+"</span>")}return a}a=t.xHTML+":";for(var n=0;n<t.series.length;n++){var r=t.series[n];if(r.isVisible){i&&(a+="<br>");a+="<span"+(r.isHighlighted?' class="highlight"':"")+"> <b><span style='color: "+r.color+";'>"+r.labelHTML+"</span></b>:&#160;"+r.yHTML+"</span>"}}return a},a.default=o,e.exports=a.default},{"../dygraph-utils":17}],25:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("../dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n),o=t("../dygraph-interaction-model"),s=i(o),l=t("../iframe-tarp"),h=i(l),u=function(){this.hasTouchInterface_="undefined"!=typeof TouchEvent,this.isMobileDevice_=/mobile|android/gi.test(navigator.appVersion),this.interfaceCreated_=!1};u.prototype.toString=function(){return"RangeSelector Plugin"},u.prototype.activate=function(t){return this.dygraph_=t,this.getOption_("showRangeSelector")&&this.createInterface_(),{layout:this.reserveSpace_,predraw:this.renderStaticLayer_,didDrawChart:this.renderInteractiveLayer_}},u.prototype.destroy=function(){this.bgcanvas_=null,this.fgcanvas_=null,this.leftZoomHandle_=null,this.rightZoomHandle_=null},u.prototype.getOption_=function(t,e){return this.dygraph_.getOption(t,e)},u.prototype.setDefaultOption_=function(t,e){this.dygraph_.attrs_[t]=e},u.prototype.createInterface_=function(){this.createCanvases_(),this.createZoomHandles_(),this.initInteraction_(),this.getOption_("animatedZooms")&&(console.warn("Animated zooms and range selector are not compatible; disabling animatedZooms."),this.dygraph_.updateOptions({animatedZooms:!1},!0)),this.interfaceCreated_=!0,this.addToGraph_()},u.prototype.addToGraph_=function(){var t=this.graphDiv_=this.dygraph_.graphDiv;t.appendChild(this.bgcanvas_),t.appendChild(this.fgcanvas_),t.appendChild(this.leftZoomHandle_),t.appendChild(this.rightZoomHandle_)},u.prototype.removeFromGraph_=function(){var t=this.graphDiv_;t.removeChild(this.bgcanvas_),t.removeChild(this.fgcanvas_),t.removeChild(this.leftZoomHandle_),t.removeChild(this.rightZoomHandle_),this.graphDiv_=null},u.prototype.reserveSpace_=function(t){this.getOption_("showRangeSelector")&&t.reserveSpaceBottom(this.getOption_("rangeSelectorHeight")+4)},u.prototype.renderStaticLayer_=function(){this.updateVisibility_()&&(this.resize_(),this.drawStaticLayer_())},u.prototype.renderInteractiveLayer_=function(){this.updateVisibility_()&&!this.isChangingRange_&&(this.placeZoomHandles_(),this.drawInteractiveLayer_())},u.prototype.updateVisibility_=function(){var t=this.getOption_("showRangeSelector");if(t)this.interfaceCreated_?this.graphDiv_&&this.graphDiv_.parentNode||this.addToGraph_():this.createInterface_();else if(this.graphDiv_){this.removeFromGraph_();var e=this.dygraph_;setTimeout(function(){e.width_=0,e.resize()},1)}return t},u.prototype.resize_=function(){function t(t,e,a,i){var n=i||r.getContextPixelRatio(e);t.style.top=a.y+"px",t.style.left=a.x+"px",t.width=a.w*n,t.height=a.h*n,t.style.width=a.w+"px",t.style.height=a.h+"px",1!=n&&e.scale(n,n)}var e=this.dygraph_.layout_.getPlotArea(),a=0;this.dygraph_.getOptionForAxis("drawAxis","x")&&(a=this.getOption_("xAxisHeight")||this.getOption_("axisLabelFontSize")+2*this.getOption_("axisTickSize")),this.canvasRect_={x:e.x,y:e.y+e.h+a+4,w:e.w,h:this.getOption_("rangeSelectorHeight")};var i=this.dygraph_.getNumericOption("pixelRatio");t(this.bgcanvas_,this.bgcanvas_ctx_,this.canvasRect_,i),t(this.fgcanvas_,this.fgcanvas_ctx_,this.canvasRect_,i)},u.prototype.createCanvases_=function(){this.bgcanvas_=r.createCanvas(),this.bgcanvas_.className="dygraph-rangesel-bgcanvas",this.bgcanvas_.style.position="absolute",this.bgcanvas_.style.zIndex=9,this.bgcanvas_ctx_=r.getContext(this.bgcanvas_),this.fgcanvas_=r.createCanvas(),this.fgcanvas_.className="dygraph-rangesel-fgcanvas",this.fgcanvas_.style.position="absolute",this.fgcanvas_.style.zIndex=9,this.fgcanvas_.style.cursor="default",this.fgcanvas_ctx_=r.getContext(this.fgcanvas_)},u.prototype.createZoomHandles_=function(){var t=new Image;t.className="dygraph-rangesel-zoomhandle",t.style.position="absolute",t.style.zIndex=10,t.style.visibility="hidden",t.style.cursor="col-resize",t.width=9,t.height=16,t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAzwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7sqSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=",this.isMobileDevice_&&(t.width*=2,t.height*=2),this.leftZoomHandle_=t,this.rightZoomHandle_=t.cloneNode(!1)},u.prototype.initInteraction_=function(){var t,e,a,i,n,o,l,u,d,c,p,g,f,_,v=this,y=document,x=0,m=null,b=!1,w=!1,A=!this.isMobileDevice_,O=new h.default;t=function(t){var e=v.dygraph_.xAxisExtremes(),a=(e[1]-e[0])/v.canvasRect_.w;return[e[0]+(t.leftHandlePos-v.canvasRect_.x)*a,e[0]+(t.rightHandlePos-v.canvasRect_.x)*a]},e=function(t){return r.cancelEvent(t),b=!0,x=t.clientX,m=t.target?t.target:t.srcElement,"mousedown"!==t.type&&"dragstart"!==t.type||(r.addEvent(y,"mousemove",a),r.addEvent(y,"mouseup",i)),v.fgcanvas_.style.cursor="col-resize",O.cover(),!0},a=function(t){if(!b)return!1;r.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a,i=v.getZoomHandleStatus_();m==v.leftZoomHandle_?(a=i.leftHandlePos+e,a=Math.min(a,i.rightHandlePos-m.width-3),a=Math.max(a,v.canvasRect_.x)):(a=i.rightHandlePos+e,a=Math.min(a,v.canvasRect_.x+v.canvasRect_.w),a=Math.max(a,i.leftHandlePos+m.width+3));var o=m.width/2;return m.style.left=a-o+"px",v.drawInteractiveLayer_(),A&&n(),!0},i=function(t){return!!b&&(b=!1,O.uncover(),r.removeEvent(y,"mousemove",a),r.removeEvent(y,"mouseup",i),v.fgcanvas_.style.cursor="default",A||n(),!0)},n=function(){try{var e=v.getZoomHandleStatus_();if(v.isChangingRange_=!0,e.isZoomed){var a=t(e);v.dygraph_.doZoomXDates_(a[0],a[1])}else v.dygraph_.resetZoom()}finally{v.isChangingRange_=!1}},o=function(t){var e=v.leftZoomHandle_.getBoundingClientRect(),a=e.left+e.width/2;e=v.rightZoomHandle_.getBoundingClientRect();var i=e.left+e.width/2;return t.clientX>a&&t.clientX<i},l=function(t){return!(w||!o(t)||!v.getZoomHandleStatus_().isZoomed)&&(r.cancelEvent(t),w=!0,x=t.clientX,"mousedown"===t.type&&(r.addEvent(y,"mousemove",u),r.addEvent(y,"mouseup",d)),!0)},u=function(t){if(!w)return!1;r.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a=v.getZoomHandleStatus_(),i=a.leftHandlePos,n=a.rightHandlePos,o=n-i;i+e<=v.canvasRect_.x?(i=v.canvasRect_.x,n=i+o):n+e>=v.canvasRect_.x+v.canvasRect_.w?(n=v.canvasRect_.x+v.canvasRect_.w,i=n-o):(i+=e,n+=e);var s=v.leftZoomHandle_.width/2;return v.leftZoomHandle_.style.left=i-s+"px",v.rightZoomHandle_.style.left=n-s+"px",v.drawInteractiveLayer_(),A&&c(),!0},d=function(t){return!!w&&(w=!1,r.removeEvent(y,"mousemove",u),r.removeEvent(y,"mouseup",d),A||c(),!0)},c=function(){try{v.isChangingRange_=!0,v.dygraph_.dateWindow_=t(v.getZoomHandleStatus_()),v.dygraph_.drawGraph_(!1)}finally{v.isChangingRange_=!1}},p=function(t){if(!b&&!w){var e=o(t)?"move":"default";e!=v.fgcanvas_.style.cursor&&(v.fgcanvas_.style.cursor=e)}},g=function(t){"touchstart"==t.type&&1==t.targetTouches.length?e(t.targetTouches[0])&&r.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?a(t.targetTouches[0])&&r.cancelEvent(t):i(t)},f=function(t){"touchstart"==t.type&&1==t.targetTouches.length?l(t.targetTouches[0])&&r.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?u(t.targetTouches[0])&&r.cancelEvent(t):d(t)},_=function(t,e){for(var a=["touchstart","touchend","touchmove","touchcancel"],i=0;i<a.length;i++)v.dygraph_.addAndTrackEvent(t,a[i],e)},this.setDefaultOption_("interactionModel",s.default.dragIsPanInteractionModel),this.setDefaultOption_("panEdgeFraction",1e-4);var D=window.opera?"mousedown":"dragstart";this.dygraph_.addAndTrackEvent(this.leftZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.rightZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousedown",l),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousemove",p),this.hasTouchInterface_&&(_(this.leftZoomHandle_,g),_(this.rightZoomHandle_,g),_(this.fgcanvas_,f))},u.prototype.drawStaticLayer_=function(){var t=this.bgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);try{this.drawMiniPlot_()}catch(t){console.warn(t)}this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorBackgroundLineWidth"),t.strokeStyle=this.getOption_("rangeSelectorBackgroundStrokeColor"),t.beginPath(),t.moveTo(.5,.5),t.lineTo(.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,.5),t.stroke()},u.prototype.drawMiniPlot_=function(){var t=this.getOption_("rangeSelectorPlotFillColor"),e=this.getOption_("rangeSelectorPlotFillGradientColor"),a=this.getOption_("rangeSelectorPlotStrokeColor");if(t||a){var i=this.getOption_("stepPlot"),n=this.computeCombinedSeriesAndLimits_(),r=n.yMax-n.yMin,o=this.bgcanvas_ctx_,s=this.dygraph_.xAxisExtremes(),l=Math.max(s[1]-s[0],1e-30),h=(this.canvasRect_.w-.5)/l,u=(this.canvasRect_.h-.5)/r,d=this.canvasRect_.w-.5,c=this.canvasRect_.h-.5,p=null,g=null;o.beginPath(),o.moveTo(.5,c);for(var f=0;f<n.data.length;f++){var _=n.data[f],v=null!==_[0]?(_[0]-s[0])*h:NaN,y=null!==_[1]?c-(_[1]-n.yMin)*u:NaN;(i||null===p||Math.round(v)!=Math.round(p))&&(isFinite(v)&&isFinite(y)?(null===p?o.lineTo(v,c):i&&o.lineTo(v,g),o.lineTo(v,y),p=v,g=y):(null!==p&&(i?(o.lineTo(v,g),o.lineTo(v,c)):o.lineTo(p,c)),p=g=null))}if(o.lineTo(d,c),o.closePath(),t){var x=this.bgcanvas_ctx_.createLinearGradient(0,0,0,c);e&&x.addColorStop(0,e),x.addColorStop(1,t),this.bgcanvas_ctx_.fillStyle=x,o.fill()}a&&(this.bgcanvas_ctx_.strokeStyle=a,this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorPlotLineWidth"),o.stroke())}},u.prototype.computeCombinedSeriesAndLimits_=function(){var t,e=this.dygraph_,a=this.getOption_("logscale"),i=e.numColumns(),n=e.getLabels(),o=new Array(i),s=!1,l=e.visibility(),h=[];for(t=1;t<i;t++){var u=this.getOption_("showInRangeSelector",n[t]);h.push(u),null!==u&&(s=!0)}if(s)for(t=1;t<i;t++)o[t]=h[t-1];else for(t=1;t<i;t++)o[t]=l[t-1];var d=[],c=e.dataHandler_,p=e.attributes_;for(t=1;t<e.numColumns();t++)if(o[t]){var g=c.extractSeries(e.rawData_,t,p);e.rollPeriod()>1&&(g=c.rollingAverage(g,e.rollPeriod(),p)),d.push(g)}var f=[];for(t=0;t<d[0].length;t++){for(var _=0,v=0,y=0;y<d.length;y++){var x=d[y][t][1];null===x||isNaN(x)||(v++,_+=x)}f.push([d[0][t][0],_/v])}var m=Number.MAX_VALUE,b=-Number.MAX_VALUE;for(t=0;t<f.length;t++){var w=f[t][1];null!==w&&isFinite(w)&&(!a||w>0)&&(m=Math.min(m,w),b=Math.max(b,w))}if(a)for(b=r.log10(b),b+=.25*b,m=r.log10(m),t=0;t<f.length;t++)f[t][1]=r.log10(f[t][1]);else{var A,O=b-m;A=O<=Number.MIN_VALUE?.25*b:.25*O,b+=A,m-=A}return{data:f,yMin:m,yMax:b}},u.prototype.placeZoomHandles_=function(){var t=this.dygraph_.xAxisExtremes(),e=this.dygraph_.xAxisRange(),a=t[1]-t[0],i=Math.max(0,(e[0]-t[0])/a),n=Math.max(0,(t[1]-e[1])/a),r=this.canvasRect_.x+this.canvasRect_.w*i,o=this.canvasRect_.x+this.canvasRect_.w*(1-n),s=Math.max(this.canvasRect_.y,this.canvasRect_.y+(this.canvasRect_.h-this.leftZoomHandle_.height)/2),l=this.leftZoomHandle_.width/2;this.leftZoomHandle_.style.left=r-l+"px",this.leftZoomHandle_.style.top=s+"px",this.rightZoomHandle_.style.left=o-l+"px",this.rightZoomHandle_.style.top=this.leftZoomHandle_.style.top,this.leftZoomHandle_.style.visibility="visible",this.rightZoomHandle_.style.visibility="visible"},u.prototype.drawInteractiveLayer_=function(){var t=this.fgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);var e=this.canvasRect_.w-1,a=this.canvasRect_.h-1,i=this.getZoomHandleStatus_();if(t.strokeStyle=this.getOption_("rangeSelectorForegroundStrokeColor"),t.lineWidth=this.getOption_("rangeSelectorForegroundLineWidth"),i.isZoomed){var n=Math.max(1,i.leftHandlePos-this.canvasRect_.x),r=Math.min(e,i.rightHandlePos-this.canvasRect_.x);t.fillStyle="rgba(240, 240, 240, "+this.getOption_("rangeSelectorAlpha").toString()+")",t.fillRect(0,0,n,this.canvasRect_.h),t.fillRect(r,0,this.canvasRect_.w-r,this.canvasRect_.h),t.beginPath(),t.moveTo(1,1),t.lineTo(n,1),t.lineTo(n,a),t.lineTo(r,a),t.lineTo(r,1),t.lineTo(e,1),t.stroke()}else t.beginPath(),t.moveTo(1,1),t.lineTo(1,a),t.lineTo(e,a),t.lineTo(e,1),t.stroke()},u.prototype.getZoomHandleStatus_=function(){var t=this.leftZoomHandle_.width/2,e=parseFloat(this.leftZoomHandle_.style.left)+t,a=parseFloat(this.rightZoomHandle_.style.left)+t;return{leftHandlePos:e,rightHandlePos:a,isZoomed:e-1>this.canvasRect_.x||a+1<this.canvasRect_.x+this.canvasRect_.w}},a.default=u,e.exports=a.default},{"../dygraph-interaction-model":12,"../dygraph-utils":17,"../iframe-tarp":19}]},{},[18])(18)});
+//# sourceMappingURL=dist/dygraph.min.js.map \ No newline at end of file
diff --git a/modules/http/static/epoch.css b/modules/http/static/epoch.css
new file mode 100644
index 0000000..39999ee
--- /dev/null
+++ b/modules/http/static/epoch.css
@@ -0,0 +1 @@
+.epoch .axis path,.epoch .axis line{shape-rendering:crispEdges}.epoch .axis.canvas .tick line{shape-rendering:geometricPrecision}div#_canvas_css_reference{width:0;height:0;position:absolute;top:-1000px;left:-1000px}div#_canvas_css_reference svg{position:absolute;width:0;height:0;top:-1000px;left:-1000px}.epoch{font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;font-size:12pt}.epoch .axis path,.epoch .axis line{fill:transparent;stroke:#000}.epoch .axis .tick text{font-size:9pt}.epoch .line{fill:transparent;stroke-width:2px}.epoch.sparklines .line{stroke-width:1px}.epoch .area{stroke:transparent}.epoch .arc.pie{stroke:#fff;stroke-width:1.5px}.epoch .arc.pie text{stroke:transparent;fill:white;font-size:9pt}.epoch .gauge-labels .value{text-anchor:middle;font-size:140%;fill:#666}.epoch.gauge-tiny{width:120px;height:90px}.epoch.gauge-tiny .gauge-labels .value{font-size:80%}.epoch.gauge-tiny .gauge .arc.outer{stroke-width:2px}.epoch.gauge-small{width:180px;height:135px}.epoch.gauge-small .gauge-labels .value{font-size:120%}.epoch.gauge-small .gauge .arc.outer{stroke-width:3px}.epoch.gauge-medium{width:240px;height:180px}.epoch.gauge-medium .gauge .arc.outer{stroke-width:3px}.epoch.gauge-large{width:320px;height:240px}.epoch.gauge-large .gauge-labels .value{font-size:180%}.epoch .gauge .arc.outer{stroke-width:4px;stroke:#666}.epoch .gauge .arc.inner{stroke-width:1px;stroke:#555}.epoch .gauge .tick{stroke-width:1px;stroke:#555}.epoch .gauge .needle{fill:orange}.epoch .gauge .needle-base{fill:#666}.epoch div.ref.category1,.epoch.category10 div.ref.category1{background-color:#1f77b4}.epoch .category1 .line,.epoch.category10 .category1 .line{stroke:#1f77b4}.epoch .category1 .area,.epoch .category1 .dot,.epoch.category10 .category1 .area,.epoch.category10 .category1 .dot{fill:#1f77b4;stroke:transparent}.epoch .arc.category1 path,.epoch.category10 .arc.category1 path{fill:#1f77b4}.epoch .bar.category1,.epoch.category10 .bar.category1{fill:#1f77b4}.epoch div.ref.category2,.epoch.category10 div.ref.category2{background-color:#ff7f0e}.epoch .category2 .line,.epoch.category10 .category2 .line{stroke:#ff7f0e}.epoch .category2 .area,.epoch .category2 .dot,.epoch.category10 .category2 .area,.epoch.category10 .category2 .dot{fill:#ff7f0e;stroke:transparent}.epoch .arc.category2 path,.epoch.category10 .arc.category2 path{fill:#ff7f0e}.epoch .bar.category2,.epoch.category10 .bar.category2{fill:#ff7f0e}.epoch div.ref.category3,.epoch.category10 div.ref.category3{background-color:#2ca02c}.epoch .category3 .line,.epoch.category10 .category3 .line{stroke:#2ca02c}.epoch .category3 .area,.epoch .category3 .dot,.epoch.category10 .category3 .area,.epoch.category10 .category3 .dot{fill:#2ca02c;stroke:transparent}.epoch .arc.category3 path,.epoch.category10 .arc.category3 path{fill:#2ca02c}.epoch .bar.category3,.epoch.category10 .bar.category3{fill:#2ca02c}.epoch div.ref.category4,.epoch.category10 div.ref.category4{background-color:#d62728}.epoch .category4 .line,.epoch.category10 .category4 .line{stroke:#d62728}.epoch .category4 .area,.epoch .category4 .dot,.epoch.category10 .category4 .area,.epoch.category10 .category4 .dot{fill:#d62728;stroke:transparent}.epoch .arc.category4 path,.epoch.category10 .arc.category4 path{fill:#d62728}.epoch .bar.category4,.epoch.category10 .bar.category4{fill:#d62728}.epoch div.ref.category5,.epoch.category10 div.ref.category5{background-color:#9467bd}.epoch .category5 .line,.epoch.category10 .category5 .line{stroke:#9467bd}.epoch .category5 .area,.epoch .category5 .dot,.epoch.category10 .category5 .area,.epoch.category10 .category5 .dot{fill:#9467bd;stroke:transparent}.epoch .arc.category5 path,.epoch.category10 .arc.category5 path{fill:#9467bd}.epoch .bar.category5,.epoch.category10 .bar.category5{fill:#9467bd}.epoch div.ref.category6,.epoch.category10 div.ref.category6{background-color:#8c564b}.epoch .category6 .line,.epoch.category10 .category6 .line{stroke:#8c564b}.epoch .category6 .area,.epoch .category6 .dot,.epoch.category10 .category6 .area,.epoch.category10 .category6 .dot{fill:#8c564b;stroke:transparent}.epoch .arc.category6 path,.epoch.category10 .arc.category6 path{fill:#8c564b}.epoch .bar.category6,.epoch.category10 .bar.category6{fill:#8c564b}.epoch div.ref.category7,.epoch.category10 div.ref.category7{background-color:#e377c2}.epoch .category7 .line,.epoch.category10 .category7 .line{stroke:#e377c2}.epoch .category7 .area,.epoch .category7 .dot,.epoch.category10 .category7 .area,.epoch.category10 .category7 .dot{fill:#e377c2;stroke:transparent}.epoch .arc.category7 path,.epoch.category10 .arc.category7 path{fill:#e377c2}.epoch .bar.category7,.epoch.category10 .bar.category7{fill:#e377c2}.epoch div.ref.category8,.epoch.category10 div.ref.category8{background-color:#7f7f7f}.epoch .category8 .line,.epoch.category10 .category8 .line{stroke:#7f7f7f}.epoch .category8 .area,.epoch .category8 .dot,.epoch.category10 .category8 .area,.epoch.category10 .category8 .dot{fill:#7f7f7f;stroke:transparent}.epoch .arc.category8 path,.epoch.category10 .arc.category8 path{fill:#7f7f7f}.epoch .bar.category8,.epoch.category10 .bar.category8{fill:#7f7f7f}.epoch div.ref.category9,.epoch.category10 div.ref.category9{background-color:#bcbd22}.epoch .category9 .line,.epoch.category10 .category9 .line{stroke:#bcbd22}.epoch .category9 .area,.epoch .category9 .dot,.epoch.category10 .category9 .area,.epoch.category10 .category9 .dot{fill:#bcbd22;stroke:transparent}.epoch .arc.category9 path,.epoch.category10 .arc.category9 path{fill:#bcbd22}.epoch .bar.category9,.epoch.category10 .bar.category9{fill:#bcbd22}.epoch div.ref.category10,.epoch.category10 div.ref.category10{background-color:#17becf}.epoch .category10 .line,.epoch.category10 .category10 .line{stroke:#17becf}.epoch .category10 .area,.epoch .category10 .dot,.epoch.category10 .category10 .area,.epoch.category10 .category10 .dot{fill:#17becf;stroke:transparent}.epoch .arc.category10 path,.epoch.category10 .arc.category10 path{fill:#17becf}.epoch .bar.category10,.epoch.category10 .bar.category10{fill:#17becf}.epoch.category20 div.ref.category1{background-color:#1f77b4}.epoch.category20 .category1 .line{stroke:#1f77b4}.epoch.category20 .category1 .area,.epoch.category20 .category1 .dot{fill:#1f77b4;stroke:transparent}.epoch.category20 .arc.category1 path{fill:#1f77b4}.epoch.category20 .bar.category1{fill:#1f77b4}.epoch.category20 div.ref.category2{background-color:#aec7e8}.epoch.category20 .category2 .line{stroke:#aec7e8}.epoch.category20 .category2 .area,.epoch.category20 .category2 .dot{fill:#aec7e8;stroke:transparent}.epoch.category20 .arc.category2 path{fill:#aec7e8}.epoch.category20 .bar.category2{fill:#aec7e8}.epoch.category20 div.ref.category3{background-color:#ff7f0e}.epoch.category20 .category3 .line{stroke:#ff7f0e}.epoch.category20 .category3 .area,.epoch.category20 .category3 .dot{fill:#ff7f0e;stroke:transparent}.epoch.category20 .arc.category3 path{fill:#ff7f0e}.epoch.category20 .bar.category3{fill:#ff7f0e}.epoch.category20 div.ref.category4{background-color:#ffbb78}.epoch.category20 .category4 .line{stroke:#ffbb78}.epoch.category20 .category4 .area,.epoch.category20 .category4 .dot{fill:#ffbb78;stroke:transparent}.epoch.category20 .arc.category4 path{fill:#ffbb78}.epoch.category20 .bar.category4{fill:#ffbb78}.epoch.category20 div.ref.category5{background-color:#2ca02c}.epoch.category20 .category5 .line{stroke:#2ca02c}.epoch.category20 .category5 .area,.epoch.category20 .category5 .dot{fill:#2ca02c;stroke:transparent}.epoch.category20 .arc.category5 path{fill:#2ca02c}.epoch.category20 .bar.category5{fill:#2ca02c}.epoch.category20 div.ref.category6{background-color:#98df8a}.epoch.category20 .category6 .line{stroke:#98df8a}.epoch.category20 .category6 .area,.epoch.category20 .category6 .dot{fill:#98df8a;stroke:transparent}.epoch.category20 .arc.category6 path{fill:#98df8a}.epoch.category20 .bar.category6{fill:#98df8a}.epoch.category20 div.ref.category7{background-color:#d62728}.epoch.category20 .category7 .line{stroke:#d62728}.epoch.category20 .category7 .area,.epoch.category20 .category7 .dot{fill:#d62728;stroke:transparent}.epoch.category20 .arc.category7 path{fill:#d62728}.epoch.category20 .bar.category7{fill:#d62728}.epoch.category20 div.ref.category8{background-color:#ff9896}.epoch.category20 .category8 .line{stroke:#ff9896}.epoch.category20 .category8 .area,.epoch.category20 .category8 .dot{fill:#ff9896;stroke:transparent}.epoch.category20 .arc.category8 path{fill:#ff9896}.epoch.category20 .bar.category8{fill:#ff9896}.epoch.category20 div.ref.category9{background-color:#9467bd}.epoch.category20 .category9 .line{stroke:#9467bd}.epoch.category20 .category9 .area,.epoch.category20 .category9 .dot{fill:#9467bd;stroke:transparent}.epoch.category20 .arc.category9 path{fill:#9467bd}.epoch.category20 .bar.category9{fill:#9467bd}.epoch.category20 div.ref.category10{background-color:#c5b0d5}.epoch.category20 .category10 .line{stroke:#c5b0d5}.epoch.category20 .category10 .area,.epoch.category20 .category10 .dot{fill:#c5b0d5;stroke:transparent}.epoch.category20 .arc.category10 path{fill:#c5b0d5}.epoch.category20 .bar.category10{fill:#c5b0d5}.epoch.category20 div.ref.category11{background-color:#8c564b}.epoch.category20 .category11 .line{stroke:#8c564b}.epoch.category20 .category11 .area,.epoch.category20 .category11 .dot{fill:#8c564b;stroke:transparent}.epoch.category20 .arc.category11 path{fill:#8c564b}.epoch.category20 .bar.category11{fill:#8c564b}.epoch.category20 div.ref.category12{background-color:#c49c94}.epoch.category20 .category12 .line{stroke:#c49c94}.epoch.category20 .category12 .area,.epoch.category20 .category12 .dot{fill:#c49c94;stroke:transparent}.epoch.category20 .arc.category12 path{fill:#c49c94}.epoch.category20 .bar.category12{fill:#c49c94}.epoch.category20 div.ref.category13{background-color:#e377c2}.epoch.category20 .category13 .line{stroke:#e377c2}.epoch.category20 .category13 .area,.epoch.category20 .category13 .dot{fill:#e377c2;stroke:transparent}.epoch.category20 .arc.category13 path{fill:#e377c2}.epoch.category20 .bar.category13{fill:#e377c2}.epoch.category20 div.ref.category14{background-color:#f7b6d2}.epoch.category20 .category14 .line{stroke:#f7b6d2}.epoch.category20 .category14 .area,.epoch.category20 .category14 .dot{fill:#f7b6d2;stroke:transparent}.epoch.category20 .arc.category14 path{fill:#f7b6d2}.epoch.category20 .bar.category14{fill:#f7b6d2}.epoch.category20 div.ref.category15{background-color:#7f7f7f}.epoch.category20 .category15 .line{stroke:#7f7f7f}.epoch.category20 .category15 .area,.epoch.category20 .category15 .dot{fill:#7f7f7f;stroke:transparent}.epoch.category20 .arc.category15 path{fill:#7f7f7f}.epoch.category20 .bar.category15{fill:#7f7f7f}.epoch.category20 div.ref.category16{background-color:#c7c7c7}.epoch.category20 .category16 .line{stroke:#c7c7c7}.epoch.category20 .category16 .area,.epoch.category20 .category16 .dot{fill:#c7c7c7;stroke:transparent}.epoch.category20 .arc.category16 path{fill:#c7c7c7}.epoch.category20 .bar.category16{fill:#c7c7c7}.epoch.category20 div.ref.category17{background-color:#bcbd22}.epoch.category20 .category17 .line{stroke:#bcbd22}.epoch.category20 .category17 .area,.epoch.category20 .category17 .dot{fill:#bcbd22;stroke:transparent}.epoch.category20 .arc.category17 path{fill:#bcbd22}.epoch.category20 .bar.category17{fill:#bcbd22}.epoch.category20 div.ref.category18{background-color:#dbdb8d}.epoch.category20 .category18 .line{stroke:#dbdb8d}.epoch.category20 .category18 .area,.epoch.category20 .category18 .dot{fill:#dbdb8d;stroke:transparent}.epoch.category20 .arc.category18 path{fill:#dbdb8d}.epoch.category20 .bar.category18{fill:#dbdb8d}.epoch.category20 div.ref.category19{background-color:#17becf}.epoch.category20 .category19 .line{stroke:#17becf}.epoch.category20 .category19 .area,.epoch.category20 .category19 .dot{fill:#17becf;stroke:transparent}.epoch.category20 .arc.category19 path{fill:#17becf}.epoch.category20 .bar.category19{fill:#17becf}.epoch.category20 div.ref.category20{background-color:#9edae5}.epoch.category20 .category20 .line{stroke:#9edae5}.epoch.category20 .category20 .area,.epoch.category20 .category20 .dot{fill:#9edae5;stroke:transparent}.epoch.category20 .arc.category20 path{fill:#9edae5}.epoch.category20 .bar.category20{fill:#9edae5}.epoch.category20b div.ref.category1{background-color:#393b79}.epoch.category20b .category1 .line{stroke:#393b79}.epoch.category20b .category1 .area,.epoch.category20b .category1 .dot{fill:#393b79;stroke:transparent}.epoch.category20b .arc.category1 path{fill:#393b79}.epoch.category20b .bar.category1{fill:#393b79}.epoch.category20b div.ref.category2{background-color:#5254a3}.epoch.category20b .category2 .line{stroke:#5254a3}.epoch.category20b .category2 .area,.epoch.category20b .category2 .dot{fill:#5254a3;stroke:transparent}.epoch.category20b .arc.category2 path{fill:#5254a3}.epoch.category20b .bar.category2{fill:#5254a3}.epoch.category20b div.ref.category3{background-color:#6b6ecf}.epoch.category20b .category3 .line{stroke:#6b6ecf}.epoch.category20b .category3 .area,.epoch.category20b .category3 .dot{fill:#6b6ecf;stroke:transparent}.epoch.category20b .arc.category3 path{fill:#6b6ecf}.epoch.category20b .bar.category3{fill:#6b6ecf}.epoch.category20b div.ref.category4{background-color:#9c9ede}.epoch.category20b .category4 .line{stroke:#9c9ede}.epoch.category20b .category4 .area,.epoch.category20b .category4 .dot{fill:#9c9ede;stroke:transparent}.epoch.category20b .arc.category4 path{fill:#9c9ede}.epoch.category20b .bar.category4{fill:#9c9ede}.epoch.category20b div.ref.category5{background-color:#637939}.epoch.category20b .category5 .line{stroke:#637939}.epoch.category20b .category5 .area,.epoch.category20b .category5 .dot{fill:#637939;stroke:transparent}.epoch.category20b .arc.category5 path{fill:#637939}.epoch.category20b .bar.category5{fill:#637939}.epoch.category20b div.ref.category6{background-color:#8ca252}.epoch.category20b .category6 .line{stroke:#8ca252}.epoch.category20b .category6 .area,.epoch.category20b .category6 .dot{fill:#8ca252;stroke:transparent}.epoch.category20b .arc.category6 path{fill:#8ca252}.epoch.category20b .bar.category6{fill:#8ca252}.epoch.category20b div.ref.category7{background-color:#b5cf6b}.epoch.category20b .category7 .line{stroke:#b5cf6b}.epoch.category20b .category7 .area,.epoch.category20b .category7 .dot{fill:#b5cf6b;stroke:transparent}.epoch.category20b .arc.category7 path{fill:#b5cf6b}.epoch.category20b .bar.category7{fill:#b5cf6b}.epoch.category20b div.ref.category8{background-color:#cedb9c}.epoch.category20b .category8 .line{stroke:#cedb9c}.epoch.category20b .category8 .area,.epoch.category20b .category8 .dot{fill:#cedb9c;stroke:transparent}.epoch.category20b .arc.category8 path{fill:#cedb9c}.epoch.category20b .bar.category8{fill:#cedb9c}.epoch.category20b div.ref.category9{background-color:#8c6d31}.epoch.category20b .category9 .line{stroke:#8c6d31}.epoch.category20b .category9 .area,.epoch.category20b .category9 .dot{fill:#8c6d31;stroke:transparent}.epoch.category20b .arc.category9 path{fill:#8c6d31}.epoch.category20b .bar.category9{fill:#8c6d31}.epoch.category20b div.ref.category10{background-color:#bd9e39}.epoch.category20b .category10 .line{stroke:#bd9e39}.epoch.category20b .category10 .area,.epoch.category20b .category10 .dot{fill:#bd9e39;stroke:transparent}.epoch.category20b .arc.category10 path{fill:#bd9e39}.epoch.category20b .bar.category10{fill:#bd9e39}.epoch.category20b div.ref.category11{background-color:#e7ba52}.epoch.category20b .category11 .line{stroke:#e7ba52}.epoch.category20b .category11 .area,.epoch.category20b .category11 .dot{fill:#e7ba52;stroke:transparent}.epoch.category20b .arc.category11 path{fill:#e7ba52}.epoch.category20b .bar.category11{fill:#e7ba52}.epoch.category20b div.ref.category12{background-color:#e7cb94}.epoch.category20b .category12 .line{stroke:#e7cb94}.epoch.category20b .category12 .area,.epoch.category20b .category12 .dot{fill:#e7cb94;stroke:transparent}.epoch.category20b .arc.category12 path{fill:#e7cb94}.epoch.category20b .bar.category12{fill:#e7cb94}.epoch.category20b div.ref.category13{background-color:#843c39}.epoch.category20b .category13 .line{stroke:#843c39}.epoch.category20b .category13 .area,.epoch.category20b .category13 .dot{fill:#843c39;stroke:transparent}.epoch.category20b .arc.category13 path{fill:#843c39}.epoch.category20b .bar.category13{fill:#843c39}.epoch.category20b div.ref.category14{background-color:#ad494a}.epoch.category20b .category14 .line{stroke:#ad494a}.epoch.category20b .category14 .area,.epoch.category20b .category14 .dot{fill:#ad494a;stroke:transparent}.epoch.category20b .arc.category14 path{fill:#ad494a}.epoch.category20b .bar.category14{fill:#ad494a}.epoch.category20b div.ref.category15{background-color:#d6616b}.epoch.category20b .category15 .line{stroke:#d6616b}.epoch.category20b .category15 .area,.epoch.category20b .category15 .dot{fill:#d6616b;stroke:transparent}.epoch.category20b .arc.category15 path{fill:#d6616b}.epoch.category20b .bar.category15{fill:#d6616b}.epoch.category20b div.ref.category16{background-color:#e7969c}.epoch.category20b .category16 .line{stroke:#e7969c}.epoch.category20b .category16 .area,.epoch.category20b .category16 .dot{fill:#e7969c;stroke:transparent}.epoch.category20b .arc.category16 path{fill:#e7969c}.epoch.category20b .bar.category16{fill:#e7969c}.epoch.category20b div.ref.category17{background-color:#7b4173}.epoch.category20b .category17 .line{stroke:#7b4173}.epoch.category20b .category17 .area,.epoch.category20b .category17 .dot{fill:#7b4173;stroke:transparent}.epoch.category20b .arc.category17 path{fill:#7b4173}.epoch.category20b .bar.category17{fill:#7b4173}.epoch.category20b div.ref.category18{background-color:#a55194}.epoch.category20b .category18 .line{stroke:#a55194}.epoch.category20b .category18 .area,.epoch.category20b .category18 .dot{fill:#a55194;stroke:transparent}.epoch.category20b .arc.category18 path{fill:#a55194}.epoch.category20b .bar.category18{fill:#a55194}.epoch.category20b div.ref.category19{background-color:#ce6dbd}.epoch.category20b .category19 .line{stroke:#ce6dbd}.epoch.category20b .category19 .area,.epoch.category20b .category19 .dot{fill:#ce6dbd;stroke:transparent}.epoch.category20b .arc.category19 path{fill:#ce6dbd}.epoch.category20b .bar.category19{fill:#ce6dbd}.epoch.category20b div.ref.category20{background-color:#de9ed6}.epoch.category20b .category20 .line{stroke:#de9ed6}.epoch.category20b .category20 .area,.epoch.category20b .category20 .dot{fill:#de9ed6;stroke:transparent}.epoch.category20b .arc.category20 path{fill:#de9ed6}.epoch.category20b .bar.category20{fill:#de9ed6}.epoch.category20c div.ref.category1{background-color:#3182bd}.epoch.category20c .category1 .line{stroke:#3182bd}.epoch.category20c .category1 .area,.epoch.category20c .category1 .dot{fill:#3182bd;stroke:transparent}.epoch.category20c .arc.category1 path{fill:#3182bd}.epoch.category20c .bar.category1{fill:#3182bd}.epoch.category20c div.ref.category2{background-color:#6baed6}.epoch.category20c .category2 .line{stroke:#6baed6}.epoch.category20c .category2 .area,.epoch.category20c .category2 .dot{fill:#6baed6;stroke:transparent}.epoch.category20c .arc.category2 path{fill:#6baed6}.epoch.category20c .bar.category2{fill:#6baed6}.epoch.category20c div.ref.category3{background-color:#9ecae1}.epoch.category20c .category3 .line{stroke:#9ecae1}.epoch.category20c .category3 .area,.epoch.category20c .category3 .dot{fill:#9ecae1;stroke:transparent}.epoch.category20c .arc.category3 path{fill:#9ecae1}.epoch.category20c .bar.category3{fill:#9ecae1}.epoch.category20c div.ref.category4{background-color:#c6dbef}.epoch.category20c .category4 .line{stroke:#c6dbef}.epoch.category20c .category4 .area,.epoch.category20c .category4 .dot{fill:#c6dbef;stroke:transparent}.epoch.category20c .arc.category4 path{fill:#c6dbef}.epoch.category20c .bar.category4{fill:#c6dbef}.epoch.category20c div.ref.category5{background-color:#e6550d}.epoch.category20c .category5 .line{stroke:#e6550d}.epoch.category20c .category5 .area,.epoch.category20c .category5 .dot{fill:#e6550d;stroke:transparent}.epoch.category20c .arc.category5 path{fill:#e6550d}.epoch.category20c .bar.category5{fill:#e6550d}.epoch.category20c div.ref.category6{background-color:#fd8d3c}.epoch.category20c .category6 .line{stroke:#fd8d3c}.epoch.category20c .category6 .area,.epoch.category20c .category6 .dot{fill:#fd8d3c;stroke:transparent}.epoch.category20c .arc.category6 path{fill:#fd8d3c}.epoch.category20c .bar.category6{fill:#fd8d3c}.epoch.category20c div.ref.category7{background-color:#fdae6b}.epoch.category20c .category7 .line{stroke:#fdae6b}.epoch.category20c .category7 .area,.epoch.category20c .category7 .dot{fill:#fdae6b;stroke:transparent}.epoch.category20c .arc.category7 path{fill:#fdae6b}.epoch.category20c .bar.category7{fill:#fdae6b}.epoch.category20c div.ref.category8{background-color:#fdd0a2}.epoch.category20c .category8 .line{stroke:#fdd0a2}.epoch.category20c .category8 .area,.epoch.category20c .category8 .dot{fill:#fdd0a2;stroke:transparent}.epoch.category20c .arc.category8 path{fill:#fdd0a2}.epoch.category20c .bar.category8{fill:#fdd0a2}.epoch.category20c div.ref.category9{background-color:#31a354}.epoch.category20c .category9 .line{stroke:#31a354}.epoch.category20c .category9 .area,.epoch.category20c .category9 .dot{fill:#31a354;stroke:transparent}.epoch.category20c .arc.category9 path{fill:#31a354}.epoch.category20c .bar.category9{fill:#31a354}.epoch.category20c div.ref.category10{background-color:#74c476}.epoch.category20c .category10 .line{stroke:#74c476}.epoch.category20c .category10 .area,.epoch.category20c .category10 .dot{fill:#74c476;stroke:transparent}.epoch.category20c .arc.category10 path{fill:#74c476}.epoch.category20c .bar.category10{fill:#74c476}.epoch.category20c div.ref.category11{background-color:#a1d99b}.epoch.category20c .category11 .line{stroke:#a1d99b}.epoch.category20c .category11 .area,.epoch.category20c .category11 .dot{fill:#a1d99b;stroke:transparent}.epoch.category20c .arc.category11 path{fill:#a1d99b}.epoch.category20c .bar.category11{fill:#a1d99b}.epoch.category20c div.ref.category12{background-color:#c7e9c0}.epoch.category20c .category12 .line{stroke:#c7e9c0}.epoch.category20c .category12 .area,.epoch.category20c .category12 .dot{fill:#c7e9c0;stroke:transparent}.epoch.category20c .arc.category12 path{fill:#c7e9c0}.epoch.category20c .bar.category12{fill:#c7e9c0}.epoch.category20c div.ref.category13{background-color:#756bb1}.epoch.category20c .category13 .line{stroke:#756bb1}.epoch.category20c .category13 .area,.epoch.category20c .category13 .dot{fill:#756bb1;stroke:transparent}.epoch.category20c .arc.category13 path{fill:#756bb1}.epoch.category20c .bar.category13{fill:#756bb1}.epoch.category20c div.ref.category14{background-color:#9e9ac8}.epoch.category20c .category14 .line{stroke:#9e9ac8}.epoch.category20c .category14 .area,.epoch.category20c .category14 .dot{fill:#9e9ac8;stroke:transparent}.epoch.category20c .arc.category14 path{fill:#9e9ac8}.epoch.category20c .bar.category14{fill:#9e9ac8}.epoch.category20c div.ref.category15{background-color:#bcbddc}.epoch.category20c .category15 .line{stroke:#bcbddc}.epoch.category20c .category15 .area,.epoch.category20c .category15 .dot{fill:#bcbddc;stroke:transparent}.epoch.category20c .arc.category15 path{fill:#bcbddc}.epoch.category20c .bar.category15{fill:#bcbddc}.epoch.category20c div.ref.category16{background-color:#dadaeb}.epoch.category20c .category16 .line{stroke:#dadaeb}.epoch.category20c .category16 .area,.epoch.category20c .category16 .dot{fill:#dadaeb;stroke:transparent}.epoch.category20c .arc.category16 path{fill:#dadaeb}.epoch.category20c .bar.category16{fill:#dadaeb}.epoch.category20c div.ref.category17{background-color:#636363}.epoch.category20c .category17 .line{stroke:#636363}.epoch.category20c .category17 .area,.epoch.category20c .category17 .dot{fill:#636363;stroke:transparent}.epoch.category20c .arc.category17 path{fill:#636363}.epoch.category20c .bar.category17{fill:#636363}.epoch.category20c div.ref.category18{background-color:#969696}.epoch.category20c .category18 .line{stroke:#969696}.epoch.category20c .category18 .area,.epoch.category20c .category18 .dot{fill:#969696;stroke:transparent}.epoch.category20c .arc.category18 path{fill:#969696}.epoch.category20c .bar.category18{fill:#969696}.epoch.category20c div.ref.category19{background-color:#bdbdbd}.epoch.category20c .category19 .line{stroke:#bdbdbd}.epoch.category20c .category19 .area,.epoch.category20c .category19 .dot{fill:#bdbdbd;stroke:transparent}.epoch.category20c .arc.category19 path{fill:#bdbdbd}.epoch.category20c .bar.category19{fill:#bdbdbd}.epoch.category20c div.ref.category20{background-color:#d9d9d9}.epoch.category20c .category20 .line{stroke:#d9d9d9}.epoch.category20c .category20 .area,.epoch.category20c .category20 .dot{fill:#d9d9d9;stroke:transparent}.epoch.category20c .arc.category20 path{fill:#d9d9d9}.epoch.category20c .bar.category20{fill:#d9d9d9}.epoch .category1 .bucket,.epoch.heatmap5 .category1 .bucket{fill:#1f77b4}.epoch .category2 .bucket,.epoch.heatmap5 .category2 .bucket{fill:#2ca02c}.epoch .category3 .bucket,.epoch.heatmap5 .category3 .bucket{fill:#d62728}.epoch .category4 .bucket,.epoch.heatmap5 .category4 .bucket{fill:#8c564b}.epoch .category5 .bucket,.epoch.heatmap5 .category5 .bucket{fill:#7f7f7f}.epoch-theme-dark .epoch .axis path,.epoch-theme-dark .epoch .axis line{stroke:#d0d0d0}.epoch-theme-dark .epoch .axis .tick text{fill:#d0d0d0}.epoch-theme-dark .arc.pie{stroke:#333}.epoch-theme-dark .arc.pie text{fill:#333}.epoch-theme-dark .epoch .gauge-labels .value{fill:#BBB}.epoch-theme-dark .epoch .gauge .arc.outer{stroke:#999}.epoch-theme-dark .epoch .gauge .arc.inner{stroke:#AAA}.epoch-theme-dark .epoch .gauge .tick{stroke:#AAA}.epoch-theme-dark .epoch .gauge .needle{fill:#F3DE88}.epoch-theme-dark .epoch .gauge .needle-base{fill:#999}.epoch-theme-dark .epoch div.ref.category1,.epoch-theme-dark .epoch.category10 div.ref.category1{background-color:#909CFF}.epoch-theme-dark .epoch .category1 .line,.epoch-theme-dark .epoch.category10 .category1 .line{stroke:#909CFF}.epoch-theme-dark .epoch .category1 .area,.epoch-theme-dark .epoch .category1 .dot,.epoch-theme-dark .epoch.category10 .category1 .area,.epoch-theme-dark .epoch.category10 .category1 .dot{fill:#909CFF;stroke:transparent}.epoch-theme-dark .epoch .arc.category1 path,.epoch-theme-dark .epoch.category10 .arc.category1 path{fill:#909CFF}.epoch-theme-dark .epoch .bar.category1,.epoch-theme-dark .epoch.category10 .bar.category1{fill:#909CFF}.epoch-theme-dark .epoch div.ref.category2,.epoch-theme-dark .epoch.category10 div.ref.category2{background-color:#FFAC89}.epoch-theme-dark .epoch .category2 .line,.epoch-theme-dark .epoch.category10 .category2 .line{stroke:#FFAC89}.epoch-theme-dark .epoch .category2 .area,.epoch-theme-dark .epoch .category2 .dot,.epoch-theme-dark .epoch.category10 .category2 .area,.epoch-theme-dark .epoch.category10 .category2 .dot{fill:#FFAC89;stroke:transparent}.epoch-theme-dark .epoch .arc.category2 path,.epoch-theme-dark .epoch.category10 .arc.category2 path{fill:#FFAC89}.epoch-theme-dark .epoch .bar.category2,.epoch-theme-dark .epoch.category10 .bar.category2{fill:#FFAC89}.epoch-theme-dark .epoch div.ref.category3,.epoch-theme-dark .epoch.category10 div.ref.category3{background-color:#E889E8}.epoch-theme-dark .epoch .category3 .line,.epoch-theme-dark .epoch.category10 .category3 .line{stroke:#E889E8}.epoch-theme-dark .epoch .category3 .area,.epoch-theme-dark .epoch .category3 .dot,.epoch-theme-dark .epoch.category10 .category3 .area,.epoch-theme-dark .epoch.category10 .category3 .dot{fill:#E889E8;stroke:transparent}.epoch-theme-dark .epoch .arc.category3 path,.epoch-theme-dark .epoch.category10 .arc.category3 path{fill:#E889E8}.epoch-theme-dark .epoch .bar.category3,.epoch-theme-dark .epoch.category10 .bar.category3{fill:#E889E8}.epoch-theme-dark .epoch div.ref.category4,.epoch-theme-dark .epoch.category10 div.ref.category4{background-color:#78E8D3}.epoch-theme-dark .epoch .category4 .line,.epoch-theme-dark .epoch.category10 .category4 .line{stroke:#78E8D3}.epoch-theme-dark .epoch .category4 .area,.epoch-theme-dark .epoch .category4 .dot,.epoch-theme-dark .epoch.category10 .category4 .area,.epoch-theme-dark .epoch.category10 .category4 .dot{fill:#78E8D3;stroke:transparent}.epoch-theme-dark .epoch .arc.category4 path,.epoch-theme-dark .epoch.category10 .arc.category4 path{fill:#78E8D3}.epoch-theme-dark .epoch .bar.category4,.epoch-theme-dark .epoch.category10 .bar.category4{fill:#78E8D3}.epoch-theme-dark .epoch div.ref.category5,.epoch-theme-dark .epoch.category10 div.ref.category5{background-color:#C2FF97}.epoch-theme-dark .epoch .category5 .line,.epoch-theme-dark .epoch.category10 .category5 .line{stroke:#C2FF97}.epoch-theme-dark .epoch .category5 .area,.epoch-theme-dark .epoch .category5 .dot,.epoch-theme-dark .epoch.category10 .category5 .area,.epoch-theme-dark .epoch.category10 .category5 .dot{fill:#C2FF97;stroke:transparent}.epoch-theme-dark .epoch .arc.category5 path,.epoch-theme-dark .epoch.category10 .arc.category5 path{fill:#C2FF97}.epoch-theme-dark .epoch .bar.category5,.epoch-theme-dark .epoch.category10 .bar.category5{fill:#C2FF97}.epoch-theme-dark .epoch div.ref.category6,.epoch-theme-dark .epoch.category10 div.ref.category6{background-color:#B7BCD1}.epoch-theme-dark .epoch .category6 .line,.epoch-theme-dark .epoch.category10 .category6 .line{stroke:#B7BCD1}.epoch-theme-dark .epoch .category6 .area,.epoch-theme-dark .epoch .category6 .dot,.epoch-theme-dark .epoch.category10 .category6 .area,.epoch-theme-dark .epoch.category10 .category6 .dot{fill:#B7BCD1;stroke:transparent}.epoch-theme-dark .epoch .arc.category6 path,.epoch-theme-dark .epoch.category10 .arc.category6 path{fill:#B7BCD1}.epoch-theme-dark .epoch .bar.category6,.epoch-theme-dark .epoch.category10 .bar.category6{fill:#B7BCD1}.epoch-theme-dark .epoch div.ref.category7,.epoch-theme-dark .epoch.category10 div.ref.category7{background-color:#FF857F}.epoch-theme-dark .epoch .category7 .line,.epoch-theme-dark .epoch.category10 .category7 .line{stroke:#FF857F}.epoch-theme-dark .epoch .category7 .area,.epoch-theme-dark .epoch .category7 .dot,.epoch-theme-dark .epoch.category10 .category7 .area,.epoch-theme-dark .epoch.category10 .category7 .dot{fill:#FF857F;stroke:transparent}.epoch-theme-dark .epoch .arc.category7 path,.epoch-theme-dark .epoch.category10 .arc.category7 path{fill:#FF857F}.epoch-theme-dark .epoch .bar.category7,.epoch-theme-dark .epoch.category10 .bar.category7{fill:#FF857F}.epoch-theme-dark .epoch div.ref.category8,.epoch-theme-dark .epoch.category10 div.ref.category8{background-color:#F3DE88}.epoch-theme-dark .epoch .category8 .line,.epoch-theme-dark .epoch.category10 .category8 .line{stroke:#F3DE88}.epoch-theme-dark .epoch .category8 .area,.epoch-theme-dark .epoch .category8 .dot,.epoch-theme-dark .epoch.category10 .category8 .area,.epoch-theme-dark .epoch.category10 .category8 .dot{fill:#F3DE88;stroke:transparent}.epoch-theme-dark .epoch .arc.category8 path,.epoch-theme-dark .epoch.category10 .arc.category8 path{fill:#F3DE88}.epoch-theme-dark .epoch .bar.category8,.epoch-theme-dark .epoch.category10 .bar.category8{fill:#F3DE88}.epoch-theme-dark .epoch div.ref.category9,.epoch-theme-dark .epoch.category10 div.ref.category9{background-color:#C9935E}.epoch-theme-dark .epoch .category9 .line,.epoch-theme-dark .epoch.category10 .category9 .line{stroke:#C9935E}.epoch-theme-dark .epoch .category9 .area,.epoch-theme-dark .epoch .category9 .dot,.epoch-theme-dark .epoch.category10 .category9 .area,.epoch-theme-dark .epoch.category10 .category9 .dot{fill:#C9935E;stroke:transparent}.epoch-theme-dark .epoch .arc.category9 path,.epoch-theme-dark .epoch.category10 .arc.category9 path{fill:#C9935E}.epoch-theme-dark .epoch .bar.category9,.epoch-theme-dark .epoch.category10 .bar.category9{fill:#C9935E}.epoch-theme-dark .epoch div.ref.category10,.epoch-theme-dark .epoch.category10 div.ref.category10{background-color:#A488FF}.epoch-theme-dark .epoch .category10 .line,.epoch-theme-dark .epoch.category10 .category10 .line{stroke:#A488FF}.epoch-theme-dark .epoch .category10 .area,.epoch-theme-dark .epoch .category10 .dot,.epoch-theme-dark .epoch.category10 .category10 .area,.epoch-theme-dark .epoch.category10 .category10 .dot{fill:#A488FF;stroke:transparent}.epoch-theme-dark .epoch .arc.category10 path,.epoch-theme-dark .epoch.category10 .arc.category10 path{fill:#A488FF}.epoch-theme-dark .epoch .bar.category10,.epoch-theme-dark .epoch.category10 .bar.category10{fill:#A488FF}.epoch-theme-dark .epoch.category20 div.ref.category1{background-color:#909CFF}.epoch-theme-dark .epoch.category20 .category1 .line{stroke:#909CFF}.epoch-theme-dark .epoch.category20 .category1 .area,.epoch-theme-dark .epoch.category20 .category1 .dot{fill:#909CFF;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category1 path{fill:#909CFF}.epoch-theme-dark .epoch.category20 .bar.category1{fill:#909CFF}.epoch-theme-dark .epoch.category20 div.ref.category2{background-color:#626AAD}.epoch-theme-dark .epoch.category20 .category2 .line{stroke:#626AAD}.epoch-theme-dark .epoch.category20 .category2 .area,.epoch-theme-dark .epoch.category20 .category2 .dot{fill:#626AAD;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category2 path{fill:#626AAD}.epoch-theme-dark .epoch.category20 .bar.category2{fill:#626AAD}.epoch-theme-dark .epoch.category20 div.ref.category3{background-color:#FFAC89}.epoch-theme-dark .epoch.category20 .category3 .line{stroke:#FFAC89}.epoch-theme-dark .epoch.category20 .category3 .area,.epoch-theme-dark .epoch.category20 .category3 .dot{fill:#FFAC89;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category3 path{fill:#FFAC89}.epoch-theme-dark .epoch.category20 .bar.category3{fill:#FFAC89}.epoch-theme-dark .epoch.category20 div.ref.category4{background-color:#BD7F66}.epoch-theme-dark .epoch.category20 .category4 .line{stroke:#BD7F66}.epoch-theme-dark .epoch.category20 .category4 .area,.epoch-theme-dark .epoch.category20 .category4 .dot{fill:#BD7F66;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category4 path{fill:#BD7F66}.epoch-theme-dark .epoch.category20 .bar.category4{fill:#BD7F66}.epoch-theme-dark .epoch.category20 div.ref.category5{background-color:#E889E8}.epoch-theme-dark .epoch.category20 .category5 .line{stroke:#E889E8}.epoch-theme-dark .epoch.category20 .category5 .area,.epoch-theme-dark .epoch.category20 .category5 .dot{fill:#E889E8;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category5 path{fill:#E889E8}.epoch-theme-dark .epoch.category20 .bar.category5{fill:#E889E8}.epoch-theme-dark .epoch.category20 div.ref.category6{background-color:#995A99}.epoch-theme-dark .epoch.category20 .category6 .line{stroke:#995A99}.epoch-theme-dark .epoch.category20 .category6 .area,.epoch-theme-dark .epoch.category20 .category6 .dot{fill:#995A99;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category6 path{fill:#995A99}.epoch-theme-dark .epoch.category20 .bar.category6{fill:#995A99}.epoch-theme-dark .epoch.category20 div.ref.category7{background-color:#78E8D3}.epoch-theme-dark .epoch.category20 .category7 .line{stroke:#78E8D3}.epoch-theme-dark .epoch.category20 .category7 .area,.epoch-theme-dark .epoch.category20 .category7 .dot{fill:#78E8D3;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category7 path{fill:#78E8D3}.epoch-theme-dark .epoch.category20 .bar.category7{fill:#78E8D3}.epoch-theme-dark .epoch.category20 div.ref.category8{background-color:#4F998C}.epoch-theme-dark .epoch.category20 .category8 .line{stroke:#4F998C}.epoch-theme-dark .epoch.category20 .category8 .area,.epoch-theme-dark .epoch.category20 .category8 .dot{fill:#4F998C;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category8 path{fill:#4F998C}.epoch-theme-dark .epoch.category20 .bar.category8{fill:#4F998C}.epoch-theme-dark .epoch.category20 div.ref.category9{background-color:#C2FF97}.epoch-theme-dark .epoch.category20 .category9 .line{stroke:#C2FF97}.epoch-theme-dark .epoch.category20 .category9 .area,.epoch-theme-dark .epoch.category20 .category9 .dot{fill:#C2FF97;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category9 path{fill:#C2FF97}.epoch-theme-dark .epoch.category20 .bar.category9{fill:#C2FF97}.epoch-theme-dark .epoch.category20 div.ref.category10{background-color:#789E5E}.epoch-theme-dark .epoch.category20 .category10 .line{stroke:#789E5E}.epoch-theme-dark .epoch.category20 .category10 .area,.epoch-theme-dark .epoch.category20 .category10 .dot{fill:#789E5E;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category10 path{fill:#789E5E}.epoch-theme-dark .epoch.category20 .bar.category10{fill:#789E5E}.epoch-theme-dark .epoch.category20 div.ref.category11{background-color:#B7BCD1}.epoch-theme-dark .epoch.category20 .category11 .line{stroke:#B7BCD1}.epoch-theme-dark .epoch.category20 .category11 .area,.epoch-theme-dark .epoch.category20 .category11 .dot{fill:#B7BCD1;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category11 path{fill:#B7BCD1}.epoch-theme-dark .epoch.category20 .bar.category11{fill:#B7BCD1}.epoch-theme-dark .epoch.category20 div.ref.category12{background-color:#7F8391}.epoch-theme-dark .epoch.category20 .category12 .line{stroke:#7F8391}.epoch-theme-dark .epoch.category20 .category12 .area,.epoch-theme-dark .epoch.category20 .category12 .dot{fill:#7F8391;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category12 path{fill:#7F8391}.epoch-theme-dark .epoch.category20 .bar.category12{fill:#7F8391}.epoch-theme-dark .epoch.category20 div.ref.category13{background-color:#CCB889}.epoch-theme-dark .epoch.category20 .category13 .line{stroke:#CCB889}.epoch-theme-dark .epoch.category20 .category13 .area,.epoch-theme-dark .epoch.category20 .category13 .dot{fill:#CCB889;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category13 path{fill:#CCB889}.epoch-theme-dark .epoch.category20 .bar.category13{fill:#CCB889}.epoch-theme-dark .epoch.category20 div.ref.category14{background-color:#A1906B}.epoch-theme-dark .epoch.category20 .category14 .line{stroke:#A1906B}.epoch-theme-dark .epoch.category20 .category14 .area,.epoch-theme-dark .epoch.category20 .category14 .dot{fill:#A1906B;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category14 path{fill:#A1906B}.epoch-theme-dark .epoch.category20 .bar.category14{fill:#A1906B}.epoch-theme-dark .epoch.category20 div.ref.category15{background-color:#F3DE88}.epoch-theme-dark .epoch.category20 .category15 .line{stroke:#F3DE88}.epoch-theme-dark .epoch.category20 .category15 .area,.epoch-theme-dark .epoch.category20 .category15 .dot{fill:#F3DE88;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category15 path{fill:#F3DE88}.epoch-theme-dark .epoch.category20 .bar.category15{fill:#F3DE88}.epoch-theme-dark .epoch.category20 div.ref.category16{background-color:#A89A5E}.epoch-theme-dark .epoch.category20 .category16 .line{stroke:#A89A5E}.epoch-theme-dark .epoch.category20 .category16 .area,.epoch-theme-dark .epoch.category20 .category16 .dot{fill:#A89A5E;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category16 path{fill:#A89A5E}.epoch-theme-dark .epoch.category20 .bar.category16{fill:#A89A5E}.epoch-theme-dark .epoch.category20 div.ref.category17{background-color:#FF857F}.epoch-theme-dark .epoch.category20 .category17 .line{stroke:#FF857F}.epoch-theme-dark .epoch.category20 .category17 .area,.epoch-theme-dark .epoch.category20 .category17 .dot{fill:#FF857F;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category17 path{fill:#FF857F}.epoch-theme-dark .epoch.category20 .bar.category17{fill:#FF857F}.epoch-theme-dark .epoch.category20 div.ref.category18{background-color:#BA615D}.epoch-theme-dark .epoch.category20 .category18 .line{stroke:#BA615D}.epoch-theme-dark .epoch.category20 .category18 .area,.epoch-theme-dark .epoch.category20 .category18 .dot{fill:#BA615D;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category18 path{fill:#BA615D}.epoch-theme-dark .epoch.category20 .bar.category18{fill:#BA615D}.epoch-theme-dark .epoch.category20 div.ref.category19{background-color:#A488FF}.epoch-theme-dark .epoch.category20 .category19 .line{stroke:#A488FF}.epoch-theme-dark .epoch.category20 .category19 .area,.epoch-theme-dark .epoch.category20 .category19 .dot{fill:#A488FF;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category19 path{fill:#A488FF}.epoch-theme-dark .epoch.category20 .bar.category19{fill:#A488FF}.epoch-theme-dark .epoch.category20 div.ref.category20{background-color:#7662B8}.epoch-theme-dark .epoch.category20 .category20 .line{stroke:#7662B8}.epoch-theme-dark .epoch.category20 .category20 .area,.epoch-theme-dark .epoch.category20 .category20 .dot{fill:#7662B8;stroke:transparent}.epoch-theme-dark .epoch.category20 .arc.category20 path{fill:#7662B8}.epoch-theme-dark .epoch.category20 .bar.category20{fill:#7662B8}.epoch-theme-dark .epoch.category20b div.ref.category1{background-color:#909CFF}.epoch-theme-dark .epoch.category20b .category1 .line{stroke:#909CFF}.epoch-theme-dark .epoch.category20b .category1 .area,.epoch-theme-dark .epoch.category20b .category1 .dot{fill:#909CFF;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category1 path{fill:#909CFF}.epoch-theme-dark .epoch.category20b .bar.category1{fill:#909CFF}.epoch-theme-dark .epoch.category20b div.ref.category2{background-color:#7680D1}.epoch-theme-dark .epoch.category20b .category2 .line{stroke:#7680D1}.epoch-theme-dark .epoch.category20b .category2 .area,.epoch-theme-dark .epoch.category20b .category2 .dot{fill:#7680D1;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category2 path{fill:#7680D1}.epoch-theme-dark .epoch.category20b .bar.category2{fill:#7680D1}.epoch-theme-dark .epoch.category20b div.ref.category3{background-color:#656DB2}.epoch-theme-dark .epoch.category20b .category3 .line{stroke:#656DB2}.epoch-theme-dark .epoch.category20b .category3 .area,.epoch-theme-dark .epoch.category20b .category3 .dot{fill:#656DB2;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category3 path{fill:#656DB2}.epoch-theme-dark .epoch.category20b .bar.category3{fill:#656DB2}.epoch-theme-dark .epoch.category20b div.ref.category4{background-color:#525992}.epoch-theme-dark .epoch.category20b .category4 .line{stroke:#525992}.epoch-theme-dark .epoch.category20b .category4 .area,.epoch-theme-dark .epoch.category20b .category4 .dot{fill:#525992;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category4 path{fill:#525992}.epoch-theme-dark .epoch.category20b .bar.category4{fill:#525992}.epoch-theme-dark .epoch.category20b div.ref.category5{background-color:#FFAC89}.epoch-theme-dark .epoch.category20b .category5 .line{stroke:#FFAC89}.epoch-theme-dark .epoch.category20b .category5 .area,.epoch-theme-dark .epoch.category20b .category5 .dot{fill:#FFAC89;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category5 path{fill:#FFAC89}.epoch-theme-dark .epoch.category20b .bar.category5{fill:#FFAC89}.epoch-theme-dark .epoch.category20b div.ref.category6{background-color:#D18D71}.epoch-theme-dark .epoch.category20b .category6 .line{stroke:#D18D71}.epoch-theme-dark .epoch.category20b .category6 .area,.epoch-theme-dark .epoch.category20b .category6 .dot{fill:#D18D71;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category6 path{fill:#D18D71}.epoch-theme-dark .epoch.category20b .bar.category6{fill:#D18D71}.epoch-theme-dark .epoch.category20b div.ref.category7{background-color:#AB735C}.epoch-theme-dark .epoch.category20b .category7 .line{stroke:#AB735C}.epoch-theme-dark .epoch.category20b .category7 .area,.epoch-theme-dark .epoch.category20b .category7 .dot{fill:#AB735C;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category7 path{fill:#AB735C}.epoch-theme-dark .epoch.category20b .bar.category7{fill:#AB735C}.epoch-theme-dark .epoch.category20b div.ref.category8{background-color:#92624E}.epoch-theme-dark .epoch.category20b .category8 .line{stroke:#92624E}.epoch-theme-dark .epoch.category20b .category8 .area,.epoch-theme-dark .epoch.category20b .category8 .dot{fill:#92624E;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category8 path{fill:#92624E}.epoch-theme-dark .epoch.category20b .bar.category8{fill:#92624E}.epoch-theme-dark .epoch.category20b div.ref.category9{background-color:#E889E8}.epoch-theme-dark .epoch.category20b .category9 .line{stroke:#E889E8}.epoch-theme-dark .epoch.category20b .category9 .area,.epoch-theme-dark .epoch.category20b .category9 .dot{fill:#E889E8;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category9 path{fill:#E889E8}.epoch-theme-dark .epoch.category20b .bar.category9{fill:#E889E8}.epoch-theme-dark .epoch.category20b div.ref.category10{background-color:#BA6EBA}.epoch-theme-dark .epoch.category20b .category10 .line{stroke:#BA6EBA}.epoch-theme-dark .epoch.category20b .category10 .area,.epoch-theme-dark .epoch.category20b .category10 .dot{fill:#BA6EBA;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category10 path{fill:#BA6EBA}.epoch-theme-dark .epoch.category20b .bar.category10{fill:#BA6EBA}.epoch-theme-dark .epoch.category20b div.ref.category11{background-color:#9B5C9B}.epoch-theme-dark .epoch.category20b .category11 .line{stroke:#9B5C9B}.epoch-theme-dark .epoch.category20b .category11 .area,.epoch-theme-dark .epoch.category20b .category11 .dot{fill:#9B5C9B;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category11 path{fill:#9B5C9B}.epoch-theme-dark .epoch.category20b .bar.category11{fill:#9B5C9B}.epoch-theme-dark .epoch.category20b div.ref.category12{background-color:#7B487B}.epoch-theme-dark .epoch.category20b .category12 .line{stroke:#7B487B}.epoch-theme-dark .epoch.category20b .category12 .area,.epoch-theme-dark .epoch.category20b .category12 .dot{fill:#7B487B;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category12 path{fill:#7B487B}.epoch-theme-dark .epoch.category20b .bar.category12{fill:#7B487B}.epoch-theme-dark .epoch.category20b div.ref.category13{background-color:#78E8D3}.epoch-theme-dark .epoch.category20b .category13 .line{stroke:#78E8D3}.epoch-theme-dark .epoch.category20b .category13 .area,.epoch-theme-dark .epoch.category20b .category13 .dot{fill:#78E8D3;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category13 path{fill:#78E8D3}.epoch-theme-dark .epoch.category20b .bar.category13{fill:#78E8D3}.epoch-theme-dark .epoch.category20b div.ref.category14{background-color:#60BAAA}.epoch-theme-dark .epoch.category20b .category14 .line{stroke:#60BAAA}.epoch-theme-dark .epoch.category20b .category14 .area,.epoch-theme-dark .epoch.category20b .category14 .dot{fill:#60BAAA;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category14 path{fill:#60BAAA}.epoch-theme-dark .epoch.category20b .bar.category14{fill:#60BAAA}.epoch-theme-dark .epoch.category20b div.ref.category15{background-color:#509B8D}.epoch-theme-dark .epoch.category20b .category15 .line{stroke:#509B8D}.epoch-theme-dark .epoch.category20b .category15 .area,.epoch-theme-dark .epoch.category20b .category15 .dot{fill:#509B8D;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category15 path{fill:#509B8D}.epoch-theme-dark .epoch.category20b .bar.category15{fill:#509B8D}.epoch-theme-dark .epoch.category20b div.ref.category16{background-color:#3F7B70}.epoch-theme-dark .epoch.category20b .category16 .line{stroke:#3F7B70}.epoch-theme-dark .epoch.category20b .category16 .area,.epoch-theme-dark .epoch.category20b .category16 .dot{fill:#3F7B70;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category16 path{fill:#3F7B70}.epoch-theme-dark .epoch.category20b .bar.category16{fill:#3F7B70}.epoch-theme-dark .epoch.category20b div.ref.category17{background-color:#C2FF97}.epoch-theme-dark .epoch.category20b .category17 .line{stroke:#C2FF97}.epoch-theme-dark .epoch.category20b .category17 .area,.epoch-theme-dark .epoch.category20b .category17 .dot{fill:#C2FF97;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category17 path{fill:#C2FF97}.epoch-theme-dark .epoch.category20b .bar.category17{fill:#C2FF97}.epoch-theme-dark .epoch.category20b div.ref.category18{background-color:#9FD17C}.epoch-theme-dark .epoch.category20b .category18 .line{stroke:#9FD17C}.epoch-theme-dark .epoch.category20b .category18 .area,.epoch-theme-dark .epoch.category20b .category18 .dot{fill:#9FD17C;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category18 path{fill:#9FD17C}.epoch-theme-dark .epoch.category20b .bar.category18{fill:#9FD17C}.epoch-theme-dark .epoch.category20b div.ref.category19{background-color:#7DA361}.epoch-theme-dark .epoch.category20b .category19 .line{stroke:#7DA361}.epoch-theme-dark .epoch.category20b .category19 .area,.epoch-theme-dark .epoch.category20b .category19 .dot{fill:#7DA361;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category19 path{fill:#7DA361}.epoch-theme-dark .epoch.category20b .bar.category19{fill:#7DA361}.epoch-theme-dark .epoch.category20b div.ref.category20{background-color:#65854E}.epoch-theme-dark .epoch.category20b .category20 .line{stroke:#65854E}.epoch-theme-dark .epoch.category20b .category20 .area,.epoch-theme-dark .epoch.category20b .category20 .dot{fill:#65854E;stroke:transparent}.epoch-theme-dark .epoch.category20b .arc.category20 path{fill:#65854E}.epoch-theme-dark .epoch.category20b .bar.category20{fill:#65854E}.epoch-theme-dark .epoch.category20c div.ref.category1{background-color:#B7BCD1}.epoch-theme-dark .epoch.category20c .category1 .line{stroke:#B7BCD1}.epoch-theme-dark .epoch.category20c .category1 .area,.epoch-theme-dark .epoch.category20c .category1 .dot{fill:#B7BCD1;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category1 path{fill:#B7BCD1}.epoch-theme-dark .epoch.category20c .bar.category1{fill:#B7BCD1}.epoch-theme-dark .epoch.category20c div.ref.category2{background-color:#979DAD}.epoch-theme-dark .epoch.category20c .category2 .line{stroke:#979DAD}.epoch-theme-dark .epoch.category20c .category2 .area,.epoch-theme-dark .epoch.category20c .category2 .dot{fill:#979DAD;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category2 path{fill:#979DAD}.epoch-theme-dark .epoch.category20c .bar.category2{fill:#979DAD}.epoch-theme-dark .epoch.category20c div.ref.category3{background-color:#6E717D}.epoch-theme-dark .epoch.category20c .category3 .line{stroke:#6E717D}.epoch-theme-dark .epoch.category20c .category3 .area,.epoch-theme-dark .epoch.category20c .category3 .dot{fill:#6E717D;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category3 path{fill:#6E717D}.epoch-theme-dark .epoch.category20c .bar.category3{fill:#6E717D}.epoch-theme-dark .epoch.category20c div.ref.category4{background-color:#595C66}.epoch-theme-dark .epoch.category20c .category4 .line{stroke:#595C66}.epoch-theme-dark .epoch.category20c .category4 .area,.epoch-theme-dark .epoch.category20c .category4 .dot{fill:#595C66;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category4 path{fill:#595C66}.epoch-theme-dark .epoch.category20c .bar.category4{fill:#595C66}.epoch-theme-dark .epoch.category20c div.ref.category5{background-color:#FF857F}.epoch-theme-dark .epoch.category20c .category5 .line{stroke:#FF857F}.epoch-theme-dark .epoch.category20c .category5 .area,.epoch-theme-dark .epoch.category20c .category5 .dot{fill:#FF857F;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category5 path{fill:#FF857F}.epoch-theme-dark .epoch.category20c .bar.category5{fill:#FF857F}.epoch-theme-dark .epoch.category20c div.ref.category6{background-color:#DE746E}.epoch-theme-dark .epoch.category20c .category6 .line{stroke:#DE746E}.epoch-theme-dark .epoch.category20c .category6 .area,.epoch-theme-dark .epoch.category20c .category6 .dot{fill:#DE746E;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category6 path{fill:#DE746E}.epoch-theme-dark .epoch.category20c .bar.category6{fill:#DE746E}.epoch-theme-dark .epoch.category20c div.ref.category7{background-color:#B55F5A}.epoch-theme-dark .epoch.category20c .category7 .line{stroke:#B55F5A}.epoch-theme-dark .epoch.category20c .category7 .area,.epoch-theme-dark .epoch.category20c .category7 .dot{fill:#B55F5A;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category7 path{fill:#B55F5A}.epoch-theme-dark .epoch.category20c .bar.category7{fill:#B55F5A}.epoch-theme-dark .epoch.category20c div.ref.category8{background-color:#964E4B}.epoch-theme-dark .epoch.category20c .category8 .line{stroke:#964E4B}.epoch-theme-dark .epoch.category20c .category8 .area,.epoch-theme-dark .epoch.category20c .category8 .dot{fill:#964E4B;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category8 path{fill:#964E4B}.epoch-theme-dark .epoch.category20c .bar.category8{fill:#964E4B}.epoch-theme-dark .epoch.category20c div.ref.category9{background-color:#F3DE88}.epoch-theme-dark .epoch.category20c .category9 .line{stroke:#F3DE88}.epoch-theme-dark .epoch.category20c .category9 .area,.epoch-theme-dark .epoch.category20c .category9 .dot{fill:#F3DE88;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category9 path{fill:#F3DE88}.epoch-theme-dark .epoch.category20c .bar.category9{fill:#F3DE88}.epoch-theme-dark .epoch.category20c div.ref.category10{background-color:#DBC87B}.epoch-theme-dark .epoch.category20c .category10 .line{stroke:#DBC87B}.epoch-theme-dark .epoch.category20c .category10 .area,.epoch-theme-dark .epoch.category20c .category10 .dot{fill:#DBC87B;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category10 path{fill:#DBC87B}.epoch-theme-dark .epoch.category20c .bar.category10{fill:#DBC87B}.epoch-theme-dark .epoch.category20c div.ref.category11{background-color:#BAAA68}.epoch-theme-dark .epoch.category20c .category11 .line{stroke:#BAAA68}.epoch-theme-dark .epoch.category20c .category11 .area,.epoch-theme-dark .epoch.category20c .category11 .dot{fill:#BAAA68;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category11 path{fill:#BAAA68}.epoch-theme-dark .epoch.category20c .bar.category11{fill:#BAAA68}.epoch-theme-dark .epoch.category20c div.ref.category12{background-color:#918551}.epoch-theme-dark .epoch.category20c .category12 .line{stroke:#918551}.epoch-theme-dark .epoch.category20c .category12 .area,.epoch-theme-dark .epoch.category20c .category12 .dot{fill:#918551;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category12 path{fill:#918551}.epoch-theme-dark .epoch.category20c .bar.category12{fill:#918551}.epoch-theme-dark .epoch.category20c div.ref.category13{background-color:#C9935E}.epoch-theme-dark .epoch.category20c .category13 .line{stroke:#C9935E}.epoch-theme-dark .epoch.category20c .category13 .area,.epoch-theme-dark .epoch.category20c .category13 .dot{fill:#C9935E;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category13 path{fill:#C9935E}.epoch-theme-dark .epoch.category20c .bar.category13{fill:#C9935E}.epoch-theme-dark .epoch.category20c div.ref.category14{background-color:#B58455}.epoch-theme-dark .epoch.category20c .category14 .line{stroke:#B58455}.epoch-theme-dark .epoch.category20c .category14 .area,.epoch-theme-dark .epoch.category20c .category14 .dot{fill:#B58455;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category14 path{fill:#B58455}.epoch-theme-dark .epoch.category20c .bar.category14{fill:#B58455}.epoch-theme-dark .epoch.category20c div.ref.category15{background-color:#997048}.epoch-theme-dark .epoch.category20c .category15 .line{stroke:#997048}.epoch-theme-dark .epoch.category20c .category15 .area,.epoch-theme-dark .epoch.category20c .category15 .dot{fill:#997048;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category15 path{fill:#997048}.epoch-theme-dark .epoch.category20c .bar.category15{fill:#997048}.epoch-theme-dark .epoch.category20c div.ref.category16{background-color:#735436}.epoch-theme-dark .epoch.category20c .category16 .line{stroke:#735436}.epoch-theme-dark .epoch.category20c .category16 .area,.epoch-theme-dark .epoch.category20c .category16 .dot{fill:#735436;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category16 path{fill:#735436}.epoch-theme-dark .epoch.category20c .bar.category16{fill:#735436}.epoch-theme-dark .epoch.category20c div.ref.category17{background-color:#A488FF}.epoch-theme-dark .epoch.category20c .category17 .line{stroke:#A488FF}.epoch-theme-dark .epoch.category20c .category17 .area,.epoch-theme-dark .epoch.category20c .category17 .dot{fill:#A488FF;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category17 path{fill:#A488FF}.epoch-theme-dark .epoch.category20c .bar.category17{fill:#A488FF}.epoch-theme-dark .epoch.category20c div.ref.category18{background-color:#8670D1}.epoch-theme-dark .epoch.category20c .category18 .line{stroke:#8670D1}.epoch-theme-dark .epoch.category20c .category18 .area,.epoch-theme-dark .epoch.category20c .category18 .dot{fill:#8670D1;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category18 path{fill:#8670D1}.epoch-theme-dark .epoch.category20c .bar.category18{fill:#8670D1}.epoch-theme-dark .epoch.category20c div.ref.category19{background-color:#705CAD}.epoch-theme-dark .epoch.category20c .category19 .line{stroke:#705CAD}.epoch-theme-dark .epoch.category20c .category19 .area,.epoch-theme-dark .epoch.category20c .category19 .dot{fill:#705CAD;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category19 path{fill:#705CAD}.epoch-theme-dark .epoch.category20c .bar.category19{fill:#705CAD}.epoch-theme-dark .epoch.category20c div.ref.category20{background-color:#52447F}.epoch-theme-dark .epoch.category20c .category20 .line{stroke:#52447F}.epoch-theme-dark .epoch.category20c .category20 .area,.epoch-theme-dark .epoch.category20c .category20 .dot{fill:#52447F;stroke:transparent}.epoch-theme-dark .epoch.category20c .arc.category20 path{fill:#52447F}.epoch-theme-dark .epoch.category20c .bar.category20{fill:#52447F}
diff --git a/modules/http/static/epoch.js b/modules/http/static/epoch.js
new file mode 100644
index 0000000..a2c0015
--- /dev/null
+++ b/modules/http/static/epoch.js
@@ -0,0 +1,3 @@
+var base,base1,base2,base3;null==window.Epoch&&(window.Epoch={}),null==(base=window.Epoch).Chart&&(base.Chart={}),null==(base1=window.Epoch).Time&&(base1.Time={}),null==(base2=window.Epoch).Util&&(base2.Util={}),null==(base3=window.Epoch).Formats&&(base3.Formats={}),Epoch.warn=function(t){return(console.warn||console.log)("Epoch Warning: "+t)},Epoch.exception=function(t){throw"Epoch Error: "+t},Epoch.TestContext=function(){function t(){var t,n,e;for(this._log=[],t=0,n=i.length;n>t;t++)e=i[t],this._makeFauxMethod(e)}var i;return i=["arc","arcTo","beginPath","bezierCurveTo","clearRect","clip","closePath","drawImage","fill","fillRect","fillText","moveTo","quadraticCurveTo","rect","restore","rotate","save","scale","scrollPathIntoView","setLineDash","setTransform","stroke","strokeRect","strokeText","transform","translate","lineTo"],t.prototype._makeFauxMethod=function(t){return this[t]=function(){var i;return this._log.push(t+"("+function(){var t,n,e;for(e=[],t=0,n=arguments.length;n>t;t++)i=arguments[t],e.push(i.toString());return e}.apply(this,arguments).join(",")+")")}},t.prototype.getImageData=function(){var t;return this._log.push("getImageData("+function(){var i,n,e;for(e=[],i=0,n=arguments.length;n>i;i++)t=arguments[i],e.push(t.toString());return e}.apply(this,arguments).join(",")+")"),{width:0,height:0,resolution:1,data:[]}},t}();var ref,typeFunction,hasProp={}.hasOwnProperty;typeFunction=function(t){return function(i){return Object.prototype.toString.call(i)==="[object "+t+"]"}},Epoch.isArray=null!=(ref=Array.isArray)?ref:typeFunction("Array"),Epoch.isObject=typeFunction("Object"),Epoch.isString=typeFunction("String"),Epoch.isFunction=typeFunction("Function"),Epoch.isNumber=typeFunction("Number"),Epoch.isElement=function(t){return"undefined"!=typeof HTMLElement&&null!==HTMLElement?t instanceof HTMLElement:null!=t&&Epoch.isObject(t)&&1===t.nodeType&&Epoch.isString(t.nodeName)},Epoch.isNonEmptyArray=function(t){return Epoch.isArray(t)&&t.length>0},Epoch.Util.copy=function(t){var i,n,e;if(null==t)return null;i={};for(n in t)hasProp.call(t,n)&&(e=t[n],i[n]=e);return i},Epoch.Util.defaults=function(t,i){var n,e,r,o,s,a;s=Epoch.Util.copy(t);for(r in i)hasProp.call(i,r)&&(a=i[r],o=t[r],e=i[r],n=Epoch.isObject(o)&&Epoch.isObject(e),null!=o&&null!=e?n&&!Epoch.isArray(o)?s[r]=Epoch.Util.defaults(o,e):s[r]=o:null!=o?s[r]=o:s[r]=e);return s},Epoch.Util.formatSI=function(t,i,n){var e,r,o,s,a;if(null==i&&(i=1),null==n&&(n=!1),1e3>t)return s=t,((0|s)!==s||n)&&(s=s.toFixed(i)),s;a=["K","M","G","T","P","E","Z","Y"];for(r in a)if(hasProp.call(a,r)&&(o=a[r],e=Math.pow(10,3*((0|r)+1)),t>=e&&t<Math.pow(10,3*((0|r)+2))))return s=t/e,(s%1!==0||n)&&(s=s.toFixed(i)),s+" "+o},Epoch.Util.formatBytes=function(t,i,n){var e,r,o,s,a;if(null==i&&(i=1),null==n&&(n=!1),1024>t)return s=t,(s%1!==0||n)&&(s=s.toFixed(i)),s+" B";a=["KB","MB","GB","TB","PB","EB","ZB","YB"];for(r in a)if(hasProp.call(a,r)&&(o=a[r],e=Math.pow(1024,(0|r)+1),t>=e&&t<Math.pow(1024,(0|r)+2)))return s=t/e,(s%1!==0||n)&&(s=s.toFixed(i)),s+" "+o},Epoch.Util.dasherize=function(t){return Epoch.Util.trim(t).replace("\n","").replace(/\s+/g,"-").toLowerCase()},Epoch.Util.domain=function(t,i){var n,e,r,o,s,a,h,p,l;for(null==i&&(i="x"),l={},n=[],r=0,a=t.length;a>r;r++)for(s=t[r],p=s.values,o=0,h=p.length;h>o;o++)e=p[o],null==l[e[i]]&&(n.push(e[i]),l[e[i]]=!0);return n},Epoch.Util.trim=function(t){return Epoch.isString(t)?t.replace(/^\s+/g,"").replace(/\s+$/g,""):null},Epoch.Util.getComputedStyle=function(t,i){return Epoch.isFunction(window.getComputedStyle)?window.getComputedStyle(t,i):null!=t.currentStyle?t.currentStyle:void 0},Epoch.Util.toRGBA=function(t,i){var n,e,r,o,s,a,h;return(o=t.match(/^rgba\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*[0-9\.]+\)/))?(n=o[0],s=o[1],r=o[2],e=o[3],a="rgba("+s+","+r+","+e+","+i+")"):(h=d3.rgb(t))&&(a="rgba("+h.r+","+h.g+","+h.b+","+i+")"),a},Epoch.Util.getContext=function(t,i){return null==i&&(i="2d"),t.getContext(i)},Epoch.Events=function(){function t(){this._events={}}return t.prototype.on=function(t,i){var n;if(null!=i)return null==(n=this._events)[t]&&(n[t]=[]),this._events[t].push(i)},t.prototype.onAll=function(t){var i,n,e;if(Epoch.isObject(t)){e=[];for(n in t)hasProp.call(t,n)&&(i=t[n],e.push(this.on(n,i)));return e}},t.prototype.off=function(t,i){var n,e;if(Epoch.isArray(this._events[t])){if(null==i)return delete this._events[t];for(e=[];(n=this._events[t].indexOf(i))>=0;)e.push(this._events[t].splice(n,1));return e}},t.prototype.offAll=function(t){var i,n,e,r,o,s;if(Epoch.isArray(t)){for(o=[],n=0,e=t.length;e>n;n++)r=t[n],o.push(this.off(r));return o}if(Epoch.isObject(t)){s=[];for(r in t)hasProp.call(t,r)&&(i=t[r],s.push(this.off(r,i)));return s}},t.prototype.trigger=function(t){var i,n,e,r,o,s,a,h;if(null!=this._events[t]){for(i=function(){var t,i,n;for(n=[],r=t=1,i=arguments.length;i>=1?i>t:t>i;r=i>=1?++t:--t)n.push(arguments[r]);return n}.apply(this,arguments),a=this._events[t],h=[],o=0,s=a.length;s>o;o++)n=a[o],e=null,Epoch.isString(n)?e=this[n]:Epoch.isFunction(n)&&(e=n),null==e&&Epoch.exception("Callback for event '"+t+"' is not a function or reference to a method."),h.push(e.apply(this,i));return h}},t}(),Epoch.Util.flatten=function(t){var i,n,e,r,o,s,a;if(!Array.isArray(t))throw new Error("Epoch.Util.flatten only accepts arrays");for(a=[],e=0,o=t.length;o>e;e++)if(i=t[e],Array.isArray(i))for(r=0,s=i.length;s>r;r++)n=i[r],a.push(n);else a.push(i);return a},d3.selection.prototype.width=function(t){return null!=t&&Epoch.isString(t)?this.style("width",t):null!=t&&Epoch.isNumber(t)?this.style("width",t+"px"):+Epoch.Util.getComputedStyle(this.node(),null).width.replace("px","")},d3.selection.prototype.height=function(t){return null!=t&&Epoch.isString(t)?this.style("height",t):null!=t&&Epoch.isNumber(t)?this.style("height",t+"px"):+Epoch.Util.getComputedStyle(this.node(),null).height.replace("px","")};var d3Seconds;Epoch.Formats.regular=function(t){return t},Epoch.Formats.si=function(t){return Epoch.Util.formatSI(t)},Epoch.Formats.percent=function(t){return(100*t).toFixed(1)+"%"},Epoch.Formats.seconds=function(t){return d3Seconds(new Date(1e3*t))},d3Seconds=d3.time.format("%I:%M:%S %p"),Epoch.Formats.bytes=function(t){return Epoch.Util.formatBytes(t)};var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Base=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this),this.options.model?(null!=this.options.model.hasData()?this.setData(this.options.model.getData(this.options.type,this.options.dataFormat)):this.setData(this.options.data||[]),this.options.model.on("data:updated",function(t){return function(){return t.setDataFromModel()}}(this))):this.setData(this.options.data||[]),null!=this.options.el&&(this.el=d3.select(this.options.el)),this.width=this.options.width,this.height=this.options.height,null!=this.el?(null==this.width&&(this.width=this.el.width()),null==this.height&&(this.height=this.el.height())):(null==this.width&&(this.width=n.width),null==this.height&&(this.height=n.height),this.el=d3.select(document.createElement("DIV")).attr("width",this.width).attr("height",this.height)),this.onAll(e)}var n,e;return extend(i,t),n={width:320,height:240,dataFormat:null},e={"option:width":"dimensionsChanged","option:height":"dimensionsChanged","layer:shown":"layerChanged","layer:hidden":"layerChanged"},i.prototype._getAllOptions=function(){return Epoch.Util.defaults({},this.options)},i.prototype._getOption=function(t){var i,n,e;for(i=t.split("."),n=this.options;i.length&&null!=n;)e=i.shift(),n=n[e];return n},i.prototype._setOption=function(t,i){var n,e,r;for(n=t.split("."),e=this.options;n.length;){if(r=n.shift(),0===n.length)return e[r]=arguments[1],void this.trigger("option:"+arguments[0]);null==e[r]&&(e[r]={}),e=e[r]}},i.prototype._setManyOptions=function(t,i){var n,e,r;null==i&&(i=""),e=[];for(n in t)hasProp.call(t,n)&&(r=t[n],Epoch.isObject(r)?e.push(this._setManyOptions(r,i+n+".")):e.push(this._setOption(i+n,r)));return e},i.prototype.option=function(){return 0===arguments.length?this._getAllOptions():1===arguments.length&&Epoch.isString(arguments[0])?this._getOption(arguments[0]):2===arguments.length&&Epoch.isString(arguments[0])?this._setOption(arguments[0],arguments[1]):1===arguments.length&&Epoch.isObject(arguments[0])?this._setManyOptions(arguments[0]):void 0},i.prototype.setDataFromModel=function(){var t;return t=this._prepareData(this.options.model.getData(this.options.type,this.options.dataFormat)),this.data=this._annotateLayers(t),this.draw()},i.prototype.setData=function(t,i){var n;return null==i&&(i={}),n=this._prepareData(this.rawData=this._formatData(t)),this.data=this._annotateLayers(n)},i.prototype._prepareData=function(t){return t},i.prototype._formatData=function(t){return Epoch.Data.formatData(t,this.options.type,this.options.dataFormat)},i.prototype._annotateLayers=function(t){var i,n,e,r,o;for(i=1,e=0,o=t.length;o>e;e++)r=t[e],n=["layer"],n.push("category"+i),r.category=i,r.visible=!0,null!=r.label&&n.push(Epoch.Util.dasherize(r.label)),r.className=n.join(" "),i++;return t},i.prototype._findLayer=function(t){var i,n,e,r,o,s;if(r=null,Epoch.isString(t)){for(s=this.data,i=0,o=s.length;o>i;i++)if(e=s[i],e.label===t){r=e;break}}else Epoch.isNumber(t)&&(n=parseInt(t),0>n||n>=this.data.length||(r=this.data[n]));return r},i.prototype.showLayer=function(t){var i;if((i=this._findLayer(t))&&!i.visible)return i.visible=!0,this.trigger("layer:shown")},i.prototype.hideLayer=function(t){var i;if((i=this._findLayer(t))&&i.visible)return i.visible=!1,this.trigger("layer:hidden")},i.prototype.toggleLayer=function(t){var i;if(i=this._findLayer(t))return i.visible=!i.visible,i.visible?this.trigger("layer:shown"):this.trigger("layer:hidden")},i.prototype.isLayerVisible=function(t){var i;return(i=this._findLayer(t))?i.visible:null},i.prototype.getVisibleLayers=function(){return this.data.filter(function(t){return t.visible})},i.prototype.update=function(t,i){return null==i&&(i=!0),this.setData(t),i?this.draw():void 0},i.prototype.draw=function(){return this.trigger("draw")},i.prototype._getScaleDomain=function(t){var i,n,e,r;return Array.isArray(t)?t:Epoch.isString(t)&&(i=this.getVisibleLayers().filter(function(i){return i.range===t}).map(function(t){return t.values}),null!=i&&i.length)?(r=Epoch.Util.flatten(i).map(function(t){return t.y}),e=function(t,i){return t>i?i:t},n=function(t,i){return i>t?i:t},[r.reduce(e,r[0]),r.reduce(n,r[0])]):Array.isArray(this.options.range)?this.options.range:this.options.range&&Array.isArray(this.options.range.left)?this.options.range.left:this.options.range&&Array.isArray(this.options.range.right)?this.options.range.right:this.extent(function(t){return t.y})},i.prototype.extent=function(t){return[d3.min(this.getVisibleLayers(),function(i){return d3.min(i.values,t)}),d3.max(this.getVisibleLayers(),function(i){return d3.max(i.values,t)})]},i.prototype.dimensionsChanged=function(){return this.width=this.option("width")||this.width,this.height=this.option("height")||this.height,this.el.width(this.width),this.el.height(this.height)},i.prototype.layerChanged=function(){return this.draw()},i}(Epoch.Events),Epoch.Chart.SVG=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options),null!=this.el?this.svg=this.el.append("svg"):this.svg=d3.select(document.createElement("svg")),this.svg.attr({xmlns:"http://www.w3.org/2000/svg",width:this.width,height:this.height})}return extend(i,t),i.prototype.dimensionsChanged=function(){return i.__super__.dimensionsChanged.call(this),this.svg.attr("width",this.width).attr("height",this.height)},i}(Epoch.Chart.Base),Epoch.Chart.Canvas=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options),null!=this.options.pixelRatio?this.pixelRatio=this.options.pixelRatio:null!=window.devicePixelRatio?this.pixelRatio=window.devicePixelRatio:this.pixelRatio=1,this.canvas=d3.select(document.createElement("CANVAS")),this.canvas.style({width:this.width+"px",height:this.height+"px"}),this.canvas.attr({width:this.getWidth(),height:this.getHeight()}),null!=this.el&&this.el.node().appendChild(this.canvas.node()),this.ctx=Epoch.Util.getContext(this.canvas.node())}return extend(i,t),i.prototype.getWidth=function(){return this.width*this.pixelRatio},i.prototype.getHeight=function(){return this.height*this.pixelRatio},i.prototype.clear=function(){return this.ctx.clearRect(0,0,this.getWidth(),this.getHeight())},i.prototype.getStyles=function(t){return Epoch.QueryCSS.getStyles(t,this.el)},i.prototype.dimensionsChanged=function(){return i.__super__.dimensionsChanged.call(this),this.canvas.style({width:this.width+"px",height:this.height+"px"}),this.canvas.attr({width:this.getWidth(),height:this.getHeight()})},i.prototype.redraw=function(){return Epoch.QueryCSS.purge(),this.draw()},i}(Epoch.Chart.Base);var QueryCSS;QueryCSS=function(){function t(){}var i,n,e,r,o,s,a;return e="_canvas_css_reference",i="data-epoch-container-id",r=0,s=function(){return"epoch-container-"+r++},n=/^([^#. ]+)?(#[^. ]+)?(\.[^# ]+)?$/,o=!1,a=function(t){var i,e,r,o,s,a;return o=t.match(n),null==o?Epoch.error("Query CSS cannot match given selector: "+t):(a=o[0],s=o[1],r=o[2],i=o[3],s=(null!=s?s:"div").toUpperCase(),e=document.createElement(s),null!=r&&(e.id=r.substr(1)),null!=i&&(e.className=i.substr(1).replace(/\./g," ")),e)},t.log=function(t){return o=t},t.cache={},t.styleList=["fill","stroke","stroke-width"],t.container=null,t.purge=function(){return t.cache={}},t.getContainer=function(){var i;return null!=t.container?t.container:(i=document.createElement("DIV"),i.id=e,document.body.appendChild(i),t.container=d3.select(i))},t.hash=function(t,n){var e;return e=n.attr(i),null==e&&(e=s(),n.attr(i,e)),e+"__"+t},t.getStyles=function(i,n){var r,s,h,p,l,u,c,g,d,f,y,m,v,x,_,w,k,b,E,C,A,S;if(s=t.hash(i,n),r=t.cache[s],null!=r)return r;for(x=[],v=n.node().parentNode;null!=v&&"body"!==v.nodeName.toLowerCase();)x.unshift(v),v=v.parentNode;for(x.push(n.node()),C=[],l=0,g=x.length;g>l;l++)p=x[l],E=p.nodeName.toLowerCase(),null!=p.id&&p.id.length>0&&(E+="#"+p.id),null!=p.className&&p.className.length>0&&(E+="."+Epoch.Util.trim(p.className).replace(/\s+/g,".")),C.push(E);for(C.push("svg"),w=Epoch.Util.trim(i).split(/\s+/),u=0,d=w.length;d>u;u++)S=w[u],C.push(S);for(o&&console.log(C),m=b=a(C.shift());C.length;)h=a(C.shift()),m.appendChild(h),m=h;for(o&&console.log(b),t.getContainer().node().appendChild(b),_=d3.select("#"+e+" "+i),A={},k=t.styleList,c=0,f=k.length;f>c;c++)y=k[c],A[y]=_.style(y);return t.cache[s]=A,t.getContainer().html(""),A},t}(),Epoch.QueryCSS=QueryCSS;var applyLayerLabel,base,hasProp={}.hasOwnProperty,slice=[].slice;null==Epoch.Data&&(Epoch.Data={}),null==(base=Epoch.Data).Format&&(base.Format={}),applyLayerLabel=function(t,i,n,e){var r,o,s,a,h;if(null==e&&(e=[]),h=[i.labels,i.autoLabels,i.keyLabels],a=h[0],r=h[1],o=h[2],null!=a&&Epoch.isArray(a)&&a.length>n)t.label=a[n];else if(o&&e.length>n)t.label=e[n];else if(r){for(s=[];n>=0;)s.push(String.fromCharCode(65+n%26)),n-=26;t.label=s.join("")}return t},Epoch.Data.Format.array=function(){var t,i,n,e,r,o,s;return i={x:function(t,i){return i},y:function(t,i){return t},time:function(t,i,n){return parseInt(n)+parseInt(i)},type:"area",autoLabels:!1,labels:[],startTime:parseInt((new Date).getTime()/1e3)},t=function(t,i,n){var e,r,o;if(r=[],Epoch.isArray(t[0]))for(e in t)hasProp.call(t,e)&&(o=t[e],r.push(applyLayerLabel({values:o.map(n)},i,parseInt(e))));else r.push(applyLayerLabel({values:t.map(n)},i,0));return r},e=function(i,n){return t(i,n,function(t,i){return{x:n.x(t,i),y:n.y(t,i)}})},s=function(i,n){return t(i,n,function(t,i){return{time:n.time(t,i,n.startTime),y:n.y(t,i)}})},r=function(i,n){return t(i,n,function(t,i){return{time:n.time(t,i,n.startTime),histogram:t}})},o=function(t,i){var n,e,r;e=[];for(n in t)if(hasProp.call(t,n)){if(r=t[n],!Epoch.isNumber(t[0]))return[];e.push(applyLayerLabel({value:r},i,n))}return e},n=function(t,n){var a;return null==t&&(t=[]),null==n&&(n={}),Epoch.isNonEmptyArray(t)?(a=Epoch.Util.defaults(n,i),"time.heatmap"===a.type?r(t,a):a.type.match(/^time\./)?s(t,a):"pie"===a.type?o(t,a):e(t,a)):[]},n.entry=function(t,e){var r,o,s,a,h,p,l,u;if(null==e&&(e={}),"time.gauge"===e.type)return null==t?0:(p=Epoch.Util.defaults(e,i),r=Epoch.isArray(t)?t[0]:t,p.y(r,0));if(null==t)return[];for(null==e.startTime&&(e.startTime=parseInt((new Date).getTime()/1e3)),o=Epoch.isArray(t)?t.map(function(t){return[t]}):[t],l=n(o,e),u=[],s=0,h=l.length;h>s;s++)a=l[s],u.push(a.values[0]);return u},n}(),Epoch.Data.Format.tuple=function(){var t,i,n;return i={x:function(t,i){return t},y:function(t,i){return t},time:function(t,i){return t},type:"area",autoLabels:!1,labels:[]},t=function(t,i,n){var e,r,o;if(!Epoch.isArray(t[0]))return[];if(r=[],Epoch.isArray(t[0][0]))for(e in t)hasProp.call(t,e)&&(o=t[e],r.push(applyLayerLabel({values:o.map(n)},i,parseInt(e))));else r.push(applyLayerLabel({values:t.map(n)},i,0));return r},n=function(n,e){var r;return null==n&&(n=[]),null==e&&(e={}),Epoch.isNonEmptyArray(n)?(r=Epoch.Util.defaults(e,i),"pie"===r.type||"time.heatmap"===r.type||"time.gauge"===r.type?[]:r.type.match(/^time\./)?t(n,r,function(t,i){return{time:r.time(t[0],parseInt(i)),y:r.y(t[1],parseInt(i))}}):t(n,r,function(t,i){return{x:r.x(t[0],parseInt(i)),y:r.y(t[1],parseInt(i))}})):[]},n.entry=function(t,i){var e,r,o,s,a,h;if(null==i&&(i={}),null==t)return[];for(null==i.startTime&&(i.startTime=parseInt((new Date).getTime()/1e3)),e=Epoch.isArray(t)&&Epoch.isArray(t[0])?t.map(function(t){return[t]}):[t],a=n(e,i),h=[],r=0,s=a.length;s>r;r++)o=a[r],h.push(o.values[0]);return h},n}(),Epoch.Data.Format.keyvalue=function(){var t,i,n,e,r;return i={type:"area",x:function(t,i){return parseInt(i)},y:function(t,i){return t},time:function(t,i,n){return parseInt(n)+parseInt(i)},labels:[],autoLabels:!1,keyLabels:!0,startTime:parseInt((new Date).getTime()/1e3)},t=function(t,i,n,e){var r,o,s,a,h,p;h=[];for(s in i)if(hasProp.call(i,s)){a=i[s],p=[];for(o in t)hasProp.call(t,o)&&(r=t[o],p.push(e(r,a,parseInt(o))));h.push(applyLayerLabel({values:p},n,parseInt(s),i))}return h},e=function(i,n,e){return t(i,n,e,function(t,i,n){var r;return r=Epoch.isString(e.x)?t[e.x]:e.x(t,parseInt(n)),{x:r,y:e.y(t[i],parseInt(n))}})},r=function(i,n,e,r){return null==r&&(r="y"),t(i,n,e,function(t,i,n){var o;return o=Epoch.isString(e.time)?{time:t[e.time]}:{time:e.time(t,parseInt(n),e.startTime)},o[r]=e.y(t[i],parseInt(n)),o})},n=function(t,n,o){var s;return null==t&&(t=[]),null==n&&(n=[]),null==o&&(o={}),Epoch.isNonEmptyArray(t)&&Epoch.isNonEmptyArray(n)?(s=Epoch.Util.defaults(o,i),"pie"===s.type||"time.gauge"===s.type?[]:"time.heatmap"===s.type?r(t,n,s,"histogram"):s.type.match(/^time\./)?r(t,n,s):e(t,n,s)):[]},n.entry=function(t,i,e){var r,o,s,a,h;if(null==i&&(i=[]),null==e&&(e={}),null==t||!Epoch.isNonEmptyArray(i))return[];for(null==e.startTime&&(e.startTime=parseInt((new Date).getTime()/1e3)),a=n([t],i,e),h=[],r=0,s=a.length;s>r;r++)o=a[r],h.push(o.values[0]);return h},n}(),Epoch.data=function(){var t,i,n;return n=arguments[0],t=2<=arguments.length?slice.call(arguments,1):[],null==(i=Epoch.Data.Format[n])?[]:i.apply(i,t)},Epoch.Data.formatData=function(t,i,n){var e,r,o,s,a,h;if(null==t&&(t=[]),!Epoch.isNonEmptyArray(t))return t;if(Epoch.isString(n))return a={type:i},Epoch.data(n,t,a);if(!Epoch.isObject(n))return t;if(null==n.name||!Epoch.isString(n.name))return t;if(null==Epoch.Data.Format[n.name])return t;if(r=[n.name,t],null!=n.arguments&&Epoch.isArray(n.arguments))for(h=n.arguments,o=0,s=h.length;s>o;o++)e=h[o],r.push(e);return null!=n.options?(a=n.options,null!=i&&null==a.type&&(a.type=i),r.push(a)):null!=i&&r.push({type:i}),Epoch.data.apply(Epoch.data,r)},Epoch.Data.formatEntry=function(t,i,n){var e,r,o,s,a,h,p,l;if(null==n)return t;if(Epoch.isString(n))return p={type:i},Epoch.Data.Format[n].entry(t,p);if(!Epoch.isObject(n))return t;if(null==n.name||!Epoch.isString(n.name))return t;if(null==Epoch.Data.Format[n.name])return t;if(o=Epoch.Util.defaults(n,{}),r=[t],null!=o.arguments&&Epoch.isArray(o.arguments))for(l=o.arguments,a=0,h=l.length;h>a;a++)e=l[a],r.push(e);return null!=o.options?(p=o.options,p.type=i,r.push(p)):null!=i&&r.push({type:i}),s=Epoch.Data.Format[o.name].entry,s.apply(s,r)};var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Model=function(t){function i(t){null==t&&(t={}),i.__super__.constructor.call(this),t=Epoch.Util.defaults(t,n),this.dataFormat=t.dataFormat,this.data=t.data,this.loading=!1}var n;return extend(i,t),n={dataFormat:null},i.prototype.setData=function(t){return this.data=t,this.trigger("data:updated")},i.prototype.push=function(t){return this.entry=t,this.trigger("data:push")},i.prototype.hasData=function(){return null!=this.data},i.prototype.getData=function(t,i){return null==i&&(i=this.dataFormat),Epoch.Data.formatData(this.data,t,i)},i.prototype.getNext=function(t,i){return null==i&&(i=this.dataFormat),Epoch.Data.formatEntry(this.entry,t,i)},i}(Epoch.Events);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Plot=function(t){function i(t){var o,s,a,h,p;for(this.options=null!=t?t:{},o=Epoch.Util.copy(this.options.margins)||{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,e)),this.margins={},p=["top","right","bottom","left"],s=0,a=p.length;a>s;s++)h=p[s],this.margins[h]=null!=this.options.margins&&null!=this.options.margins[h]?this.options.margins[h]:this.hasAxis(h)?n[h]:6;this.g=this.svg.append("g").attr("transform","translate("+this.margins.left+", "+this.margins.top+")"),this.onAll(r)}var n,e,r;return extend(i,t),e={domain:null,range:null,axes:["left","bottom"],ticks:{top:14,bottom:14,left:5,right:5},tickFormats:{top:Epoch.Formats.regular,bottom:Epoch.Formats.regular,left:Epoch.Formats.si,right:Epoch.Formats.si}},n={top:25,right:50,bottom:25,left:50},r={"option:margins.top":"marginsChanged","option:margins.right":"marginsChanged","option:margins.bottom":"marginsChanged","option:margins.left":"marginsChanged","option:axes":"axesChanged","option:ticks.top":"ticksChanged","option:ticks.right":"ticksChanged","option:ticks.bottom":"ticksChanged","option:ticks.left":"ticksChanged","option:tickFormats.top":"tickFormatsChanged","option:tickFormats.right":"tickFormatsChanged","option:tickFormats.bottom":"tickFormatsChanged","option:tickFormats.left":"tickFormatsChanged","option:domain":"domainChanged","option:range":"rangeChanged"},i.prototype.setTickFormat=function(t,i){return this.options.tickFormats[t]=i},i.prototype.hasAxis=function(t){return this.options.axes.indexOf(t)>-1},i.prototype.innerWidth=function(){return this.width-(this.margins.left+this.margins.right)},i.prototype.innerHeight=function(){return this.height-(this.margins.top+this.margins.bottom)},i.prototype.x=function(){var t,i;return t=null!=(i=this.options.domain)?i:this.extent(function(t){return t.x}),d3.scale.linear().domain(t).range([0,this.innerWidth()])},i.prototype.y=function(t){return d3.scale.linear().domain(this._getScaleDomain(t)).range([this.innerHeight(),0])},i.prototype.bottomAxis=function(){return d3.svg.axis().scale(this.x()).orient("bottom").ticks(this.options.ticks.bottom).tickFormat(this.options.tickFormats.bottom)},i.prototype.topAxis=function(){return d3.svg.axis().scale(this.x()).orient("top").ticks(this.options.ticks.top).tickFormat(this.options.tickFormats.top)},i.prototype.leftAxis=function(){var t;return t=this.options.range?this.options.range.left:null,d3.svg.axis().scale(this.y(t)).orient("left").ticks(this.options.ticks.left).tickFormat(this.options.tickFormats.left)},i.prototype.rightAxis=function(){var t;return t=this.options.range?this.options.range.right:null,d3.svg.axis().scale(this.y(t)).orient("right").ticks(this.options.ticks.right).tickFormat(this.options.tickFormats.right)},i.prototype.draw=function(){return this._axesDrawn?this._redrawAxes():this._drawAxes(),i.__super__.draw.call(this)},i.prototype._redrawAxes=function(){return this.hasAxis("bottom")&&this.g.selectAll(".x.axis.bottom").transition().duration(500).ease("linear").call(this.bottomAxis()),this.hasAxis("top")&&this.g.selectAll(".x.axis.top").transition().duration(500).ease("linear").call(this.topAxis()),this.hasAxis("left")&&this.g.selectAll(".y.axis.left").transition().duration(500).ease("linear").call(this.leftAxis()),this.hasAxis("right")?this.g.selectAll(".y.axis.right").transition().duration(500).ease("linear").call(this.rightAxis()):void 0},i.prototype._drawAxes=function(){return this.hasAxis("bottom")&&this.g.append("g").attr("class","x axis bottom").attr("transform","translate(0, "+this.innerHeight()+")").call(this.bottomAxis()),this.hasAxis("top")&&this.g.append("g").attr("class","x axis top").call(this.topAxis()),this.hasAxis("left")&&this.g.append("g").attr("class","y axis left").call(this.leftAxis()),this.hasAxis("right")&&this.g.append("g").attr("class","y axis right").attr("transform","translate("+this.innerWidth()+", 0)").call(this.rightAxis()),this._axesDrawn=!0},i.prototype.dimensionsChanged=function(){return i.__super__.dimensionsChanged.call(this),this.g.selectAll(".axis").remove(),this._axesDrawn=!1,this.draw()},i.prototype.marginsChanged=function(){var t,i,n;if(null!=this.options.margins){i=this.options.margins;for(t in i)hasProp.call(i,t)&&(n=i[t],null==n?this.margins[t]=6:this.margins[t]=n);return this.g.transition().duration(750).attr("transform","translate("+this.margins.left+", "+this.margins.top+")"),this.draw()}},i.prototype.axesChanged=function(){var t,i,e,r;for(r=["top","right","bottom","left"],t=0,i=r.length;i>t;t++)e=r[t],(null==this.options.margins||null==this.options.margins[e])&&(this.hasAxis(e)?this.margins[e]=n[e]:this.margins[e]=6);return this.g.transition().duration(750).attr("transform","translate("+this.margins.left+", "+this.margins.top+")"),this.g.selectAll(".axis").remove(),this._axesDrawn=!1,this.draw()},i.prototype.ticksChanged=function(){return this.draw()},i.prototype.tickFormatsChanged=function(){return this.draw()},i.prototype.domainChanged=function(){return this.draw()},i.prototype.rangeChanged=function(){return this.draw()},i}(Epoch.Chart.SVG);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Area=function(t){function i(t){var n;this.options=null!=t?t:{},null==(n=this.options).type&&(n.type="area"),i.__super__.constructor.call(this,this.options),this.draw()}return extend(i,t),i.prototype.y=function(){var t,i,n,e,r,o,s,a,h;for(t=[],o=this.getVisibleLayers(),i=0,r=o.length;r>i;i++){e=o[i],s=e.values;for(n in s)hasProp.call(s,n)&&(h=s[n],null!=t[n]&&(t[n]+=h.y),null==t[n]&&(t[n]=h.y))}return d3.scale.linear().domain(null!=(a=this.options.range)?a:[0,d3.max(t)]).range([this.height-this.margins.top-this.margins.bottom,0])},i.prototype.draw=function(){var t,n,e,r,o,s,a,h;return o=[this.x(),this.y(),this.getVisibleLayers()],a=o[0],h=o[1],r=o[2],this.g.selectAll(".layer").remove(),0!==r.length?(t=d3.svg.area().x(function(t){return a(t.x)}).y0(function(t){return h(t.y0)}).y1(function(t){return h(t.y0+t.y)}),s=d3.layout.stack().values(function(t){return t.values}),n=s(r),e=this.g.selectAll(".layer").data(r,function(t){return t.category}),e.select(".area").attr("d",function(i){return t(i.values)}),e.enter().append("g").attr("class",function(t){return t.className}),e.append("path").attr("class","area").attr("d",function(i){return t(i.values)}),i.__super__.draw.call(this)):void 0},i}(Epoch.Chart.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Bar=function(t){function i(t){this.options=null!=t?t:{},this._isHorizontal()?this.options=Epoch.Util.defaults(this.options,e):this.options=Epoch.Util.defaults(this.options,n),i.__super__.constructor.call(this,this.options),this.onAll(o),this.draw()}var n,e,r,o;return extend(i,t),n={type:"bar",style:"grouped",orientation:"vertical",padding:{bar:.08,group:.1},outerPadding:{bar:.08,group:.1}},r={tickFormats:{top:Epoch.Formats.si,bottom:Epoch.Formats.si,left:Epoch.Formats.regular,right:Epoch.Formats.regular}},e=Epoch.Util.defaults(r,n),o={"option:orientation":"orientationChanged","option:padding":"paddingChanged","option:outerPadding":"paddingChanged","option:padding:bar":"paddingChanged","option:padding:group":"paddingChanged","option:outerPadding:bar":"paddingChanged","option:outerPadding:group":"paddingChanged"},i.prototype._isVertical=function(){return"vertical"===this.options.orientation},i.prototype._isHorizontal=function(){return"horizontal"===this.options.orientation},i.prototype.x=function(){var t;return this._isVertical()?d3.scale.ordinal().domain(Epoch.Util.domain(this.getVisibleLayers())).rangeRoundBands([0,this.innerWidth()],this.options.padding.group,this.options.outerPadding.group):(t=this.extent(function(t){return t.y}),t[0]=Math.min(0,t[0]),d3.scale.linear().domain(t).range([0,this.width-this.margins.left-this.margins.right]))},i.prototype.x1=function(t){var i;return d3.scale.ordinal().domain(function(){var t,n,e,r;for(e=this.getVisibleLayers(),r=[],t=0,n=e.length;n>t;t++)i=e[t],r.push(i.category);return r}.call(this)).rangeRoundBands([0,t.rangeBand()],this.options.padding.bar,this.options.outerPadding.bar)},i.prototype.y=function(){var t;return this._isVertical()?(t=this.extent(function(t){return t.y}),t[0]=Math.min(0,t[0]),d3.scale.linear().domain(t).range([this.height-this.margins.top-this.margins.bottom,0])):d3.scale.ordinal().domain(Epoch.Util.domain(this.getVisibleLayers())).rangeRoundBands([0,this.innerHeight()],this.options.padding.group,this.options.outerPadding.group)},i.prototype.y1=function(t){var i;return d3.scale.ordinal().domain(function(){var t,n,e,r;for(e=this.getVisibleLayers(),r=[],t=0,n=e.length;n>t;t++)i=e[t],r.push(i.category);return r}.call(this)).rangeRoundBands([0,t.rangeBand()],this.options.padding.bar,this.options.outerPadding.bar)},i.prototype._remapData=function(){var t,i,n,e,r,o,s,a,h,p,l,u,c,g;for(h={},l=this.getVisibleLayers(),n=0,s=l.length;s>n;n++)for(o=l[n],t="bar "+o.className.replace(/\s*layer\s*/,""),u=o.values,r=0,a=u.length;a>r;r++)i=u[r],null==h[p=i.x]&&(h[p]=[]),h[i.x].push({label:o.category,y:i.y,className:t});c=[];for(e in h)hasProp.call(h,e)&&(g=h[e],c.push({group:e,values:g}));return c},i.prototype.draw=function(){return this._isVertical()?this._drawVertical():this._drawHorizontal(),i.__super__.draw.call(this)},i.prototype._drawVertical=function(){var t,i,n,e,r,o,s,a;return r=[this.x(),this.y()],o=r[0],a=r[1],s=this.x1(o),i=this.height-this.margins.top-this.margins.bottom,t=this._remapData(),n=this.g.selectAll(".layer").data(t,function(t){return t.group}),n.transition().duration(750).attr("transform",function(t){return"translate("+o(t.group)+", 0)"}),n.enter().append("g").attr("class","layer").attr("transform",function(t){return"translate("+o(t.group)+", 0)"}),e=n.selectAll("rect").data(function(t){return t.values}),e.attr("class",function(t){return t.className}),e.transition().duration(600).attr("x",function(t){return s(t.label)}).attr("y",function(t){return a(t.y)}).attr("width",s.rangeBand()).attr("height",function(t){return i-a(t.y)}),e.enter().append("rect").attr("class",function(t){return t.className}).attr("x",function(t){return s(t.label)}).attr("y",function(t){return a(t.y)}).attr("width",s.rangeBand()).attr("height",function(t){
+return i-a(t.y)}),e.exit().transition().duration(150).style("opacity","0").remove(),n.exit().transition().duration(750).style("opacity","0").remove()},i.prototype._drawHorizontal=function(){var t,i,n,e,r,o,s,a;return e=[this.x(),this.y()],o=e[0],s=e[1],a=this.y1(s),r=this.width-this.margins.left-this.margins.right,t=this._remapData(),i=this.g.selectAll(".layer").data(t,function(t){return t.group}),i.transition().duration(750).attr("transform",function(t){return"translate(0, "+s(t.group)+")"}),i.enter().append("g").attr("class","layer").attr("transform",function(t){return"translate(0, "+s(t.group)+")"}),n=i.selectAll("rect").data(function(t){return t.values}),n.attr("class",function(t){return t.className}),n.transition().duration(600).attr("x",function(t){return 0}).attr("y",function(t){return a(t.label)}).attr("height",a.rangeBand()).attr("width",function(t){return o(t.y)}),n.enter().append("rect").attr("class",function(t){return t.className}).attr("x",function(t){return 0}).attr("y",function(t){return a(t.label)}).attr("height",a.rangeBand()).attr("width",function(t){return o(t.y)}),n.exit().transition().duration(150).style("opacity","0").remove(),i.exit().transition().duration(750).style("opacity","0").remove()},i.prototype._getTickValues=function(t,i){var n,e,r,o;return null==i&&(i="x"),null==this.data[0]?[]:(o=this.data[0].values.length,e=0|Math.ceil(o/t),r=function(){var t,i,r,s;for(s=[],n=t=0,i=o,r=e;r>0?i>t:t>i;n=t+=r)s.push(this.data[0].values[n].x);return s}.call(this))},i.prototype.bottomAxis=function(){var t;return t=d3.svg.axis().scale(this.x()).orient("bottom").ticks(this.options.ticks.bottom).tickFormat(this.options.tickFormats.bottom),this._isVertical()&&null!=this.options.ticks.bottom&&t.tickValues(this._getTickValues(this.options.ticks.bottom)),t},i.prototype.topAxis=function(){var t;return t=d3.svg.axis().scale(this.x()).orient("top").ticks(this.options.ticks.top).tickFormat(this.options.tickFormats.top),this._isVertical()&&null!=this.options.ticks.top&&t.tickValues(this._getTickValues(this.options.ticks.top)),t},i.prototype.leftAxis=function(){var t;return t=d3.svg.axis().scale(this.y()).orient("left").ticks(this.options.ticks.left).tickFormat(this.options.tickFormats.left),this._isHorizontal()&&null!=this.options.ticks.left&&t.tickValues(this._getTickValues(this.options.ticks.left)),t},i.prototype.rightAxis=function(){var t;return t=d3.svg.axis().scale(this.y()).orient("right").ticks(this.options.ticks.right).tickFormat(this.options.tickFormats.right),this._isHorizontal()&&null!=this.options.ticks.right&&t.tickValues(this._getTickValues(this.options.ticks.right)),t},i.prototype.orientationChanged=function(){var t,i,n,e;return e=this.options.tickFormats.top,t=this.options.tickFormats.bottom,i=this.options.tickFormats.left,n=this.options.tickFormats.right,this.options.tickFormats.left=e,this.options.tickFormats.right=t,this.options.tickFormats.top=i,this.options.tickFormats.bottom=n,this.draw()},i.prototype.paddingChanged=function(){return this.draw()},i}(Epoch.Chart.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Histogram=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,n)),this.onAll(e),this.draw()}var n,e;return extend(i,t),n={type:"histogram",domain:[0,100],bucketRange:[0,100],buckets:10,cutOutliers:!1},e={"option:bucketRange":"bucketRangeChanged","option:buckets":"bucketsChanged","option:cutOutliers":"cutOutliersChanged"},i.prototype._prepareData=function(t){var i,n,e,r,o,s,a,h,p,l,u,c,g,d,f;for(i=(this.options.bucketRange[1]-this.options.bucketRange[0])/this.options.buckets,c=[],o=0,p=t.length;p>o;o++){for(h=t[o],n=function(){var t,i,n;for(n=[],e=t=0,i=this.options.buckets;i>=0?i>t:t>i;e=i>=0?++t:--t)n.push(0);return n}.call(this),d=h.values,a=0,l=d.length;l>a;a++)u=d[a],r=parseInt((u.x-this.options.bucketRange[0])/i),this.options.cutOutliers&&(0>r||r>=this.options.buckets)||(0>r?r=0:r>=this.options.buckets&&(r=this.options.buckets-1),n[r]+=parseInt(u.y));g={values:n.map(function(t,n){return{x:parseInt(n)*i,y:t}})};for(s in h)hasProp.call(h,s)&&(f=h[s],"values"!==s&&(g[s]=f));c.push(g)}return c},i.prototype.resetData=function(){return this.setData(this.rawData),this.draw()},i.prototype.bucketRangeChanged=function(){return this.resetData()},i.prototype.bucketsChanged=function(){return this.resetData()},i.prototype.cutOutliersChanged=function(){return this.resetData()},i}(Epoch.Chart.Bar);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Line=function(t){function i(t){var n;this.options=null!=t?t:{},null==(n=this.options).type&&(n.type="line"),i.__super__.constructor.call(this,this.options),this.draw()}return extend(i,t),i.prototype.line=function(t){var i,n,e;return i=[this.x(),this.y(t.range)],n=i[0],e=i[1],d3.svg.line().x(function(t){return n(t.x)}).y(function(t){return e(t.y)})},i.prototype.draw=function(){var t,n,e,r,o;return e=[this.x(),this.y(),this.getVisibleLayers()],r=e[0],o=e[1],n=e[2],0===n.length?this.g.selectAll(".layer").remove():(t=this.g.selectAll(".layer").data(n,function(t){return t.category}),t.select(".line").transition().duration(500).attr("d",function(t){return function(i){return t.line(i)(i.values)}}(this)),t.enter().append("g").attr("class",function(t){return t.className}).append("path").attr("class","line").attr("d",function(t){return function(i){return t.line(i)(i.values)}}(this)),t.exit().transition().duration(750).style("opacity","0").remove(),i.__super__.draw.call(this))},i}(Epoch.Chart.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Pie=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,n)),this.pie=d3.layout.pie().sort(null).value(function(t){return t.value}),this.arc=d3.svg.arc().outerRadius(function(t){return function(){return Math.max(t.width,t.height)/2-t.options.margin}}(this)).innerRadius(function(t){return function(){return t.options.inner}}(this)),this.g=this.svg.append("g").attr("transform","translate("+this.width/2+", "+this.height/2+")"),this.on("option:margin","marginChanged"),this.on("option:inner","innerChanged"),this.draw()}var n;return extend(i,t),n={type:"pie",margin:10,inner:0},i.prototype.draw=function(){var t,n,e;return this.g.selectAll(".arc").remove(),t=this.g.selectAll(".arc").data(this.pie(this.getVisibleLayers()),function(t){return t.data.category}),t.enter().append("g").attr("class",function(t){return"arc pie "+t.data.className}),t.select("path").attr("d",this.arc),t.select("text").attr("transform",function(t){return function(i){return"translate("+t.arc.centroid(i)+")"}}(this)).text(function(t){return t.data.label||t.data.category}),n=t.append("path").attr("d",this.arc).each(function(t){return this._current=t}),e=t.append("text").attr("transform",function(t){return function(i){return"translate("+t.arc.centroid(i)+")"}}(this)).attr("dy",".35em").style("text-anchor","middle").text(function(t){return t.data.label||t.data.category}),i.__super__.draw.call(this)},i.prototype.marginChanged=function(){return this.draw()},i.prototype.innerChanged=function(){return this.draw()},i}(Epoch.Chart.SVG);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Chart.Scatter=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,n)),this.on("option:radius","radiusChanged"),this.draw()}var n;return extend(i,t),n={type:"scatter",radius:3.5,axes:["top","bottom","left","right"]},i.prototype.draw=function(){var t,n,e,r,o,s,a;return o=[this.x(),this.y(),this.getVisibleLayers()],s=o[0],a=o[1],e=o[2],r=this.options.radius,0===e.length?this.g.selectAll(".layer").remove():(n=this.g.selectAll(".layer").data(e,function(t){return t.category}),n.enter().append("g").attr("class",function(t){return t.className}),t=n.selectAll(".dot").data(function(t){return t.values}),t.transition().duration(500).attr("r",function(t){var i;return null!=(i=t.r)?i:r}).attr("cx",function(t){return s(t.x)}).attr("cy",function(t){return a(t.y)}),t.enter().append("circle").attr("class","dot").attr("r",function(t){var i;return null!=(i=t.r)?i:r}).attr("cx",function(t){return s(t.x)}).attr("cy",function(t){return a(t.y)}),t.exit().transition().duration(750).style("opacity",0).remove(),n.exit().transition().duration(750).style("opacity",0).remove(),i.__super__.draw.call(this))},i.prototype.radiusChanged=function(){return this.draw()},i}(Epoch.Chart.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Plot=function(t){function i(t){var o,s,a,h,p;for(this.options=t,o=Epoch.Util.copy(this.options.margins)||{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,e)),this.options.model&&this.options.model.on("data:push",function(t){return function(){return t.pushFromModel()}}(this)),this._queue=[],this.margins={},p=["top","right","bottom","left"],s=0,a=p.length;a>s;s++)h=p[s],this.margins[h]=null!=this.options.margins&&null!=this.options.margins[h]?this.options.margins[h]:this.hasAxis(h)?n[h]:6;this.svg=this.el.insert("svg",":first-child").attr("width",this.width).attr("height",this.height).style("z-index","1000"),"absolute"!==this.el.style("position")&&"relative"!==this.el.style("position")&&this.el.style("position","relative"),this.canvas.style({position:"absolute","z-index":"999"}),this._sizeCanvas(),this.animation={interval:null,active:!1,delta:function(t){return function(){return-(t.w()/t.options.fps)}}(this),tickDelta:function(t){return function(){return-(t.w()/t.pixelRatio/t.options.fps)}}(this),frame:0,duration:this.options.fps},this._buildAxes(),this.animationCallback=function(t){return function(){return t._animate()}}(this),this.onAll(r)}var n,e,r;return extend(i,t),e={range:null,fps:24,historySize:120,windowSize:40,queueSize:10,axes:["bottom"],ticks:{time:15,left:5,right:5},tickFormats:{top:Epoch.Formats.seconds,bottom:Epoch.Formats.seconds,left:Epoch.Formats.si,right:Epoch.Formats.si}},n={top:25,right:50,bottom:25,left:50},r={"option:margins":"marginsChanged","option:margins.top":"marginsChanged","option:margins.right":"marginsChanged","option:margins.bottom":"marginsChanged","option:margins.left":"marginsChanged","option:axes":"axesChanged","option:ticks":"ticksChanged","option:ticks.top":"ticksChanged","option:ticks.right":"ticksChanged","option:ticks.bottom":"ticksChanged","option:ticks.left":"ticksChanged","option:tickFormats":"tickFormatsChanged","option:tickFormats.top":"tickFormatsChanged","option:tickFormats.right":"tickFormatsChanged","option:tickFormats.bottom":"tickFormatsChanged","option:tickFormats.left":"tickFormatsChanged"},i.prototype._sizeCanvas=function(){return this.canvas.attr({width:this.innerWidth(),height:this.innerHeight()}),this.canvas.style({width:this.innerWidth()/this.pixelRatio+"px",height:this.innerHeight()/this.pixelRatio+"px",top:this.margins.top+"px",left:this.margins.left+"px"})},i.prototype._buildAxes=function(){return this.svg.selectAll(".axis").remove(),this._prepareTimeAxes(),this._prepareRangeAxes()},i.prototype._annotateLayers=function(t){var i,n,e,r,o,s;e=[];for(r in t)hasProp.call(t,r)&&(o=t[r],n=Epoch.Util.copy(o),s=Math.max(0,o.values.length-this.options.historySize),n.values=o.values.slice(s),i=["layer"],i.push("category"+((0|r)+1)),null!=o.label&&i.push(Epoch.Util.dasherize(o.label)),n.className=i.join(" "),n.visible=!0,e.push(n));return e},i.prototype._offsetX=function(){return 0},i.prototype._prepareTimeAxes=function(){var t;return this.hasAxis("bottom")&&(t=this.bottomAxis=this.svg.append("g").attr("class","x axis bottom canvas").attr("transform","translate("+(this.margins.left-1)+", "+(this.innerHeight()/this.pixelRatio+this.margins.top)+")"),t.append("path").attr("class","domain").attr("d","M0,0H"+(this.innerWidth()/this.pixelRatio+1))),this.hasAxis("top")&&(t=this.topAxis=this.svg.append("g").attr("class","x axis top canvas").attr("transform","translate("+(this.margins.left-1)+", "+this.margins.top+")"),t.append("path").attr("class","domain").attr("d","M0,0H"+(this.innerWidth()/this.pixelRatio+1))),this._resetInitialTimeTicks()},i.prototype._resetInitialTimeTicks=function(){var t,i,n,e,r,o,s,a,h;for(h=this.options.ticks.time,this._ticks=[],this._tickTimer=h,null!=this.bottomAxis&&this.bottomAxis.selectAll(".tick").remove(),null!=this.topAxis&&this.topAxis.selectAll(".tick").remove(),o=this.data,a=[],n=0,r=o.length;r>n;n++)if(e=o[n],Epoch.isNonEmptyArray(e.values)){for(s=[this.options.windowSize-1,e.values.length-1],t=s[0],i=s[1];t>=0&&i>=0;)this._pushTick(t,e.values[i].time,!1,!0),t-=h,i-=h;break}return a},i.prototype._prepareRangeAxes=function(){return this.hasAxis("left")&&this.svg.append("g").attr("class","y axis left").attr("transform","translate("+(this.margins.left-1)+", "+this.margins.top+")").call(this.leftAxis()),this.hasAxis("right")?this.svg.append("g").attr("class","y axis right").attr("transform","translate("+(this.width-this.margins.right)+", "+this.margins.top+")").call(this.rightAxis()):void 0},i.prototype.leftAxis=function(){var t,i;return i=this.options.ticks.left,t=d3.svg.axis().scale(this.ySvgLeft()).orient("left").tickFormat(this.options.tickFormats.left),2===i?t.tickValues(this.extent(function(t){return t.y})):t.ticks(i)},i.prototype.rightAxis=function(){var t,i,n;return i=this.extent(function(t){return t.y}),n=this.options.ticks.right,t=d3.svg.axis().scale(this.ySvgRight()).orient("right").tickFormat(this.options.tickFormats.right),2===n?t.tickValues(this.extent(function(t){return t.y})):t.ticks(n)},i.prototype.hasAxis=function(t){return this.options.axes.indexOf(t)>-1},i.prototype.innerWidth=function(){return(this.width-(this.margins.left+this.margins.right))*this.pixelRatio},i.prototype.innerHeight=function(){return(this.height-(this.margins.top+this.margins.bottom))*this.pixelRatio},i.prototype._prepareEntry=function(t){return t},i.prototype._prepareLayers=function(t){return t},i.prototype._startTransition=function(){return this.animation.active!==!0&&0!==this._queue.length?(this.trigger("transition:start"),this._shift(),this.animation.active=!0,this.animation.interval=setInterval(this.animationCallback,1e3/this.options.fps)):void 0},i.prototype._stopTransition=function(){var t,i,n,e,r,o,s;if(this.inTransition()){for(o=this.data,i=0,r=o.length;r>i;i++)e=o[i],e.values.length>this.options.windowSize+1&&e.values.shift();return s=[this._ticks[0],this._ticks[this._ticks.length-1]],t=s[0],n=s[1],null!=n&&n.enter&&(n.enter=!1,n.opacity=1),null!=t&&t.exit&&this._shiftTick(),this.animation.frame=0,this.trigger("transition:end"),this._queue.length>0?this._shift():(this.animation.active=!1,clearInterval(this.animation.interval))}},i.prototype.inTransition=function(){return this.animation.active},i.prototype.push=function(t){return t=this._prepareLayers(t),this._queue.length>this.options.queueSize&&this._queue.splice(this.options.queueSize,this._queue.length-this.options.queueSize),this._queue.length===this.options.queueSize?!1:(this._queue.push(t.map(function(t){return function(i){return t._prepareEntry(i)}}(this))),this.trigger("push"),this.inTransition()?void 0:this._startTransition())},i.prototype.pushFromModel=function(){return this.push(this.options.model.getNext(this.options.type,this.options.dataFormat))},i.prototype._shift=function(){var t,i,n,e;this.trigger("before:shift"),t=this._queue.shift(),e=this.data;for(i in e)hasProp.call(e,i)&&(n=e[i],n.values.push(t[i]));return this._updateTicks(t[0].time),this._transitionRangeAxes(),this.trigger("after:shift")},i.prototype._transitionRangeAxes=function(){return this.hasAxis("left")&&this.svg.selectAll(".y.axis.left").transition().duration(500).ease("linear").call(this.leftAxis()),this.hasAxis("right")?this.svg.selectAll(".y.axis.right").transition().duration(500).ease("linear").call(this.rightAxis()):void 0},i.prototype._animate=function(){return this.inTransition()?(++this.animation.frame===this.animation.duration&&this._stopTransition(),this.draw(this.animation.frame*this.animation.delta()),this._updateTimeAxes()):void 0},i.prototype.y=function(t){return d3.scale.linear().domain(this._getScaleDomain(t)).range([this.innerHeight(),0])},i.prototype.ySvg=function(t){return d3.scale.linear().domain(this._getScaleDomain(t)).range([this.innerHeight()/this.pixelRatio,0])},i.prototype.ySvgLeft=function(){return null!=this.options.range?this.ySvg(this.options.range.left):this.ySvg()},i.prototype.ySvgRight=function(){return null!=this.options.range?this.ySvg(this.options.range.right):this.ySvg()},i.prototype.w=function(){return this.innerWidth()/this.options.windowSize},i.prototype._updateTicks=function(t){return(this.hasAxis("top")||this.hasAxis("bottom"))&&(++this._tickTimer%this.options.ticks.time||this._pushTick(this.options.windowSize,t,!0),this._ticks.length>0)?this._ticks[0].x-this.w()/this.pixelRatio>=0?void 0:this._ticks[0].exit=!0:void 0},i.prototype._pushTick=function(t,i,n,e){var r,o;return null==n&&(n=!1),null==e&&(e=!1),this.hasAxis("top")||this.hasAxis("bottom")?(o={time:i,x:t*(this.w()/this.pixelRatio)+this._offsetX(),opacity:n?0:1,enter:n?!0:!1,exit:!1},this.hasAxis("bottom")&&(r=this.bottomAxis.append("g").attr("class","tick major").attr("transform","translate("+(o.x+1)+",0)").style("opacity",o.opacity),r.append("line").attr("y2",6),r.append("text").attr("text-anchor","middle").attr("dy",19).text(this.options.tickFormats.bottom(o.time)),o.bottomEl=r),this.hasAxis("top")&&(r=this.topAxis.append("g").attr("class","tick major").attr("transform","translate("+(o.x+1)+",0)").style("opacity",o.opacity),r.append("line").attr("y2",-6),r.append("text").attr("text-anchor","middle").attr("dy",-10).text(this.options.tickFormats.top(o.time)),o.topEl=r),e?this._ticks.unshift(o):this._ticks.push(o),o):void 0},i.prototype._shiftTick=function(){var t;if(this._ticks.length>0)return t=this._ticks.shift(),null!=t.topEl&&t.topEl.remove(),null!=t.bottomEl?t.bottomEl.remove():void 0},i.prototype._updateTimeAxes=function(){var t,i,n,e,r,o,s,a;if(this.hasAxis("top")||this.hasAxis("bottom")){for(r=[this.animation.tickDelta(),1/this.options.fps],i=r[0],t=r[1],o=this._ticks,s=[],n=0,e=o.length;e>n;n++)a=o[n],a.x+=i,this.hasAxis("bottom")&&a.bottomEl.attr("transform","translate("+(a.x+1)+",0)"),this.hasAxis("top")&&a.topEl.attr("transform","translate("+(a.x+1)+",0)"),a.enter?a.opacity+=t:a.exit&&(a.opacity-=t),a.enter||a.exit?(this.hasAxis("bottom")&&a.bottomEl.style("opacity",a.opacity),this.hasAxis("top")?s.push(a.topEl.style("opacity",a.opacity)):s.push(void 0)):s.push(void 0);return s}},i.prototype.draw=function(t){return null==t&&(t=0),i.__super__.draw.call(this)},i.prototype.dimensionsChanged=function(){return i.__super__.dimensionsChanged.call(this),this.svg.attr("width",this.width).attr("height",this.height),this._sizeCanvas(),this._buildAxes(),this.draw(this.animation.frame*this.animation.delta())},i.prototype.axesChanged=function(){var t,i,e,r;for(r=["top","right","bottom","left"],t=0,i=r.length;i>t;t++)e=r[t],(null==this.options.margins||null==this.options.margins[e])&&(this.hasAxis(e)?this.margins[e]=n[e]:this.margins[e]=6);return this._sizeCanvas(),this._buildAxes(),this.draw(this.animation.frame*this.animation.delta())},i.prototype.ticksChanged=function(){return this._resetInitialTimeTicks(),this._transitionRangeAxes(),this.draw(this.animation.frame*this.animation.delta())},i.prototype.tickFormatsChanged=function(){return this._resetInitialTimeTicks(),this._transitionRangeAxes(),this.draw(this.animation.frame*this.animation.delta())},i.prototype.marginsChanged=function(){var t,i,n;if(null!=this.options.margins){i=this.options.margins;for(t in i)hasProp.call(i,t)&&(n=i[t],null==n?this.margins[t]=6:this.margins[t]=n);return this._sizeCanvas(),this.draw(this.animation.frame*this.animation.delta())}},i.prototype.layerChanged=function(){return this._transitionRangeAxes(),i.__super__.layerChanged.call(this)},i}(Epoch.Chart.Canvas),Epoch.Time.Stack=function(t){function i(){return i.__super__.constructor.apply(this,arguments)}return extend(i,t),i.prototype._stackLayers=function(){var t,i,n,e,r,o,s;if((e=this.getVisibleLayers()).length>0){for(o=[],t=i=0,r=e[0].values.length;r>=0?r>i:i>r;t=r>=0?++i:--i)s=0,o.push(function(){var i,r,o;for(o=[],r=0,i=e.length;i>r;r++)n=e[r],n.values[t].y0=s,o.push(s+=n.values[t].y);return o}());return o}},i.prototype._prepareLayers=function(t){var i,n,e;e=0;for(n in t)hasProp.call(t,n)&&(i=t[n],this.data[n].visible&&(i.y0=e,e+=i.y));return t},i.prototype.setData=function(t){return i.__super__.setData.call(this,t),this._stackLayers()},i.prototype.extent=function(){var t,i,n,e,r,o,s,a,h,p;if(s=[0,this.getVisibleLayers()],o=s[0],e=s[1],!e.length)return[0,0];for(t=n=0,a=e[0].values.length;a>=0?a>n:n>a;t=a>=0?++n:--n){for(p=0,i=r=0,h=e.length;h>=0?h>r:r>h;i=h>=0?++r:--r)p+=e[i].values[t].y;p>o&&(o=p)}return[0,o]},i.prototype.layerChanged=function(){var t,n,e,r;for(this._stackLayers(),r=this._queue,t=0,e=r.length;e>t;t++)n=r[t],this._prepareLayers(n);return i.__super__.layerChanged.call(this)},i}(Epoch.Time.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Area=function(t){function i(t){var n;this.options=null!=t?t:{},null==(n=this.options).type&&(n.type="time.area"),i.__super__.constructor.call(this,this.options),this.draw()}return extend(i,t),i.prototype.setStyles=function(t){var i;return i=null!=t&&null!=t.className?this.getStyles("g."+t.className.replace(/\s/g,".")+" path.area"):this.getStyles("g path.area"),this.ctx.fillStyle=i.fill,null!=i.stroke&&(this.ctx.strokeStyle=i.stroke),null!=i["stroke-width"]?this.ctx.lineWidth=i["stroke-width"].replace("px",""):void 0},i.prototype._drawAreas=function(t){var i,n,e,r,o,s,a,h,p,l,u,c,g,d,f,y,m;for(null==t&&(t=0),u=[this.y(),this.w(),this.getVisibleLayers()],m=u[0],y=u[1],l=u[2],d=[],o=h=c=l.length-1;0>=c?0>=h:h>=0;o=0>=c?++h:--h)if(p=l[o]){for(this.setStyles(p),this.ctx.beginPath(),g=[this.options.windowSize,p.values.length,this.inTransition()],s=g[0],a=g[1],f=g[2],r=null;--s>=-2&&--a>=0;)e=p.values[a],i=[(s+1)*y+t,m(e.y+e.y0)],f&&(i[0]+=y),o===this.options.windowSize-1?this.ctx.moveTo.apply(this.ctx,i):this.ctx.lineTo.apply(this.ctx,i);n=f?(s+3)*y+t:(s+2)*y+t,this.ctx.lineTo(n,this.innerHeight()),this.ctx.lineTo(this.width*this.pixelRatio+y+t,this.innerHeight()),this.ctx.closePath(),d.push(this.ctx.fill())}return d},i.prototype._drawStrokes=function(t){var i,n,e,r,o,s,a,h,p,l,u,c,g,d,f;for(null==t&&(t=0),p=[this.y(),this.w(),this.getVisibleLayers()],f=p[0],d=p[1],h=p[2],c=[],r=s=l=h.length-1;0>=l?0>=s:s>=0;r=0>=l?++s:--s)if(a=h[r]){for(this.setStyles(a),this.ctx.beginPath(),u=[this.options.windowSize,a.values.length,this.inTransition()],r=u[0],o=u[1],g=u[2],e=null;--r>=-2&&--o>=0;)n=a.values[o],i=[(r+1)*d+t,f(n.y+n.y0)],g&&(i[0]+=d),r===this.options.windowSize-1?this.ctx.moveTo.apply(this.ctx,i):this.ctx.lineTo.apply(this.ctx,i);c.push(this.ctx.stroke())}return c},i.prototype.draw=function(t){return null==t&&(t=0),this.clear(),this._drawAreas(t),this._drawStrokes(t),i.__super__.draw.call(this)},i}(Epoch.Time.Stack);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Bar=function(t){function i(t){var n;this.options=null!=t?t:{},null==(n=this.options).type&&(n.type="time.bar"),i.__super__.constructor.call(this,this.options),this.draw()}return extend(i,t),i.prototype._offsetX=function(){return.5*this.w()/this.pixelRatio},i.prototype.setStyles=function(t){var i;return i=this.getStyles("rect.bar."+t.replace(/\s/g,".")),this.ctx.fillStyle=i.fill,null==i.stroke||"none"===i.stroke?this.ctx.strokeStyle="transparent":this.ctx.strokeStyle=i.stroke,null!=i["stroke-width"]?this.ctx.lineWidth=i["stroke-width"].replace("px",""):void 0},i.prototype.draw=function(t){var n,e,r,o,s,a,h,p,l,u,c,g,d,f,y,m,v,x;for(null==t&&(t=0),this.clear(),g=[this.y(),this.w()],x=g[0],v=g[1],d=this.getVisibleLayers(),p=0,c=d.length;c>p;p++)if(u=d[p],Epoch.isNonEmptyArray(u.values))for(this.setStyles(u.className),f=[this.options.windowSize,u.values.length,this.inTransition()],a=f[0],l=f[1],m=f[2],h=m?-1:0;--a>=h&&--l>=0;)e=u.values[l],y=[a*v+t,e.y,e.y0],r=y[0],o=y[1],s=y[2],m&&(r+=v),n=[r+1,x(o+s),v-2,this.innerHeight()-x(o)+.5*this.pixelRatio],this.ctx.fillRect.apply(this.ctx,n),this.ctx.strokeRect.apply(this.ctx,n);return i.__super__.draw.call(this)},i}(Epoch.Time.Stack);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Gauge=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,n)),this.value=this.options.value||0,this.options.model&&this.options.model.on("data:push",function(t){return function(){return t.pushFromModel()}}(this)),"absolute"!==this.el.style("position")&&"relative"!==this.el.style("position")&&this.el.style("position","relative"),this.svg=this.el.insert("svg",":first-child").attr("width",this.width).attr("height",this.height).attr("class","gauge-labels"),this.svg.style({position:"absolute","z-index":"1"}),this.svg.append("g").attr("transform","translate("+this.textX()+", "+this.textY()+")").append("text").attr("class","value").text(this.options.format(this.value)),this.animation={interval:null,active:!1,delta:0,target:0},this._animate=function(t){return function(){return Math.abs(t.animation.target-t.value)<Math.abs(t.animation.delta)?(t.value=t.animation.target,clearInterval(t.animation.interval),t.animation.active=!1):t.value+=t.animation.delta,t.svg.select("text.value").text(t.options.format(t.value)),t.draw()}}(this),this.onAll(e),this.draw()}var n,e;return extend(i,t),n={type:"time.gauge",domain:[0,1],ticks:10,tickSize:5,tickOffset:5,fps:34,format:Epoch.Formats.percent},e={"option:domain":"domainChanged","option:ticks":"ticksChanged","option:tickSize":"tickSizeChanged","option:tickOffset":"tickOffsetChanged","option:format":"formatChanged"},i.prototype.update=function(t){return this.animation.target=t,this.animation.delta=(t-this.value)/this.options.fps,this.animation.active?void 0:(this.animation.interval=setInterval(this._animate,1e3/this.options.fps),this.animation.active=!0)},i.prototype.push=function(t){return this.update(t)},i.prototype.pushFromModel=function(){var t;return t=this.options.model.getNext(this.options.type,this.options.dataFormat),this.update(t)},i.prototype.radius=function(){return this.getHeight()/1.58},i.prototype.centerX=function(){return this.getWidth()/2},i.prototype.centerY=function(){return.68*this.getHeight()},i.prototype.textX=function(){return this.width/2},i.prototype.textY=function(){return.48*this.height},i.prototype.getAngle=function(t){var i,n,e;return e=this.options.domain,i=e[0],n=e[1],(t-i)/(n-i)*(Math.PI+2*Math.PI/8)-Math.PI/2-Math.PI/8},i.prototype.setStyles=function(t){var i;return i=this.getStyles(t),this.ctx.fillStyle=i.fill,this.ctx.strokeStyle=i.stroke,null!=i["stroke-width"]?this.ctx.lineWidth=i["stroke-width"].replace("px",""):void 0},i.prototype.draw=function(){var t,n,e,r,o,s,a,h,p,l,u,c,g,d,f,y,m,v,x;for(h=[this.centerX(),this.centerY(),this.radius()],e=h[0],r=h[1],a=h[2],p=[this.options.tickOffset,this.options.tickSize],d=p[0],f=p[1],this.clear(),g=d3.scale.linear().domain([0,this.options.ticks]).range([-1.125*Math.PI,Math.PI/8]),this.setStyles(".epoch .gauge .tick"),this.ctx.beginPath(),o=s=0,l=this.options.ticks;l>=0?l>=s:s>=l;o=l>=0?++s:--s)t=g(o),u=[Math.cos(t),Math.sin(t)],n=u[0],c=u[1],y=n*(a-d)+e,v=c*(a-d)+r,m=n*(a-d-f)+e,x=c*(a-d-f)+r,this.ctx.moveTo(y,v),this.ctx.lineTo(m,x);return this.ctx.stroke(),this.setStyles(".epoch .gauge .arc.outer"),this.ctx.beginPath(),this.ctx.arc(e,r,a,-1.125*Math.PI,1/8*Math.PI,!1),this.ctx.stroke(),this.setStyles(".epoch .gauge .arc.inner"),this.ctx.beginPath(),this.ctx.arc(e,r,a-10,-1.125*Math.PI,1/8*Math.PI,!1),this.ctx.stroke(),this.drawNeedle(),i.__super__.draw.call(this)},i.prototype.drawNeedle=function(){var t,i,n,e,r;return r=[this.centerX(),this.centerY(),this.radius()],t=r[0],i=r[1],n=r[2],e=this.value/this.options.domain[1],this.setStyles(".epoch .gauge .needle"),this.ctx.beginPath(),this.ctx.save(),this.ctx.translate(t,i),this.ctx.rotate(this.getAngle(this.value)),this.ctx.moveTo(4*this.pixelRatio,0),this.ctx.lineTo(-4*this.pixelRatio,0),this.ctx.lineTo(-1*this.pixelRatio,19-n),this.ctx.lineTo(1,19-n),this.ctx.fill(),this.setStyles(".epoch .gauge .needle-base"),this.ctx.beginPath(),this.ctx.arc(0,0,this.getWidth()/25,0,2*Math.PI),this.ctx.fill(),this.ctx.restore()},i.prototype.domainChanged=function(){return this.draw()},i.prototype.ticksChanged=function(){return this.draw()},i.prototype.tickSizeChanged=function(){return this.draw()},i.prototype.tickOffsetChanged=function(){return this.draw()},i.prototype.formatChanged=function(){return this.svg.select("text.value").text(this.options.format(this.value))},i}(Epoch.Chart.Canvas);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Heatmap=function(t){function i(t){this.options=null!=t?t:{},i.__super__.constructor.call(this,this.options=Epoch.Util.defaults(this.options,e)),this._setOpacityFunction(),this._setupPaintCanvas(),this.onAll(r),this.draw()}var n,e,r;return extend(i,t),e={type:"time.heatmap",buckets:10,bucketRange:[0,100],opacity:"linear",bucketPadding:2,paintZeroValues:!1,cutOutliers:!1},n={root:function(t,i){return Math.pow(t/i,.5)},linear:function(t,i){return t/i},quadratic:function(t,i){return Math.pow(t/i,2)},cubic:function(t,i){return Math.pow(t/i,3)},quartic:function(t,i){return Math.pow(t/i,4)},quintic:function(t,i){return Math.pow(t/i,5)}},r={"option:buckets":"bucketsChanged","option:bucketRange":"bucketRangeChanged","option:opacity":"opacityChanged","option:bucketPadding":"bucketPaddingChanged","option:paintZeroValues":"paintZeroValuesChanged","option:cutOutliers":"cutOutliersChanged"},i.prototype._setOpacityFunction=function(){return Epoch.isString(this.options.opacity)?(this._opacityFn=n[this.options.opacity],null==this._opacityFn?Epoch.exception("Unknown coloring function provided '"+this.options.opacity+"'"):void 0):Epoch.isFunction(this.options.opacity)?this._opacityFn=this.options.opacity:Epoch.exception("Unknown type for provided coloring function.")},i.prototype.setData=function(t){var n,e,r,o,s;for(i.__super__.setData.call(this,t),o=this.data,s=[],n=0,r=o.length;r>n;n++)e=o[n],s.push(e.values=e.values.map(function(t){return function(i){return t._prepareEntry(i)}}(this)));return s},i.prototype._getBuckets=function(t){var i,n,e,r,o,s,a,h,p;s={time:t.time,max:0,buckets:function(){var t,i,n;for(n=[],e=t=0,i=this.options.buckets;i>=0?i>t:t>i;e=i>=0?++t:--t)n.push(0);return n}.call(this)},i=(this.options.bucketRange[1]-this.options.bucketRange[0])/this.options.buckets,
+a=t.histogram;for(p in a)hasProp.call(a,p)&&(n=a[p],r=parseInt((p-this.options.bucketRange[0])/i),this.options.cutOutliers&&(0>r||r>=this.options.buckets)||(0>r?r=0:r>=this.options.buckets&&(r=this.options.buckets-1),s.buckets[r]+=parseInt(n)));for(e=o=0,h=s.buckets.length;h>=0?h>o:o>h;e=h>=0?++o:--o)s.max=Math.max(s.max,s.buckets[e]);return s},i.prototype.y=function(){return d3.scale.linear().domain(this.options.bucketRange).range([this.innerHeight(),0])},i.prototype.ySvg=function(){return d3.scale.linear().domain(this.options.bucketRange).range([this.innerHeight()/this.pixelRatio,0])},i.prototype.h=function(){return this.innerHeight()/this.options.buckets},i.prototype._offsetX=function(){return.5*this.w()/this.pixelRatio},i.prototype._setupPaintCanvas=function(){return this.paintWidth=(this.options.windowSize+1)*this.w(),this.paintHeight=this.height*this.pixelRatio,this.paint=document.createElement("CANVAS"),this.paint.width=this.paintWidth,this.paint.height=this.paintHeight,this.p=Epoch.Util.getContext(this.paint),this.redraw(),this.on("after:shift","_paintEntry"),this.on("transition:end","_shiftPaintCanvas"),this.on("transition:end",function(t){return function(){return t.draw(t.animation.frame*t.animation.delta())}}(this))},i.prototype.redraw=function(){var t,i;if(Epoch.isNonEmptyArray(this.data)&&Epoch.isNonEmptyArray(this.data[0].values)){for(i=this.data[0].values.length,t=this.options.windowSize,this.inTransition()&&t++;--i>=0&&--t>=0;)this._paintEntry(i,t);return this.draw(this.animation.frame*this.animation.delta())}},i.prototype._computeColor=function(t,i,n){return Epoch.Util.toRGBA(n,this._opacityFn(t,i))},i.prototype._paintEntry=function(t,i){var n,e,r,o,s,a,h,p,l,u,c,g,d,f,y,m,v,x,_,w,k,b,E,C;for(null==t&&(t=null),null==i&&(i=null),v=[this.w(),this.h()],E=v[0],h=v[1],null==t&&(t=this.data[0].values.length-1),null==i&&(i=this.options.windowSize),s=[],e=function(){var t,i,n;for(n=[],p=t=0,i=this.options.buckets;i>=0?i>t:t>i;p=i>=0?++t:--t)n.push(0);return n}.call(this),m=0,x=this.getVisibleLayers(),u=0,g=x.length;g>u;u++){c=x[u],a=this._getBuckets(c.values[t]),_=a.buckets;for(n in _)hasProp.call(_,n)&&(o=_[n],e[n]+=o);m+=a.max,k=this.getStyles("."+c.className.split(" ").join(".")+" rect.bucket"),a.color=k.fill,s.push(a)}C=i*E,this.p.clearRect(C,0,E,this.paintHeight),l=this.options.buckets,w=[];for(n in e)if(hasProp.call(e,n)){for(b=e[n],r=this._avgLab(s,n),y=0,f=0,d=s.length;d>f;f++)a=s[f],y+=a.buckets[n]/b*m;(b>0||this.options.paintZeroValues)&&(this.p.fillStyle=this._computeColor(b,y,r),this.p.fillRect(C,(l-1)*h,E-this.options.bucketPadding,h-this.options.bucketPadding)),w.push(l--)}return w},i.prototype._shiftPaintCanvas=function(){var t;return t=this.p.getImageData(this.w(),0,this.paintWidth-this.w(),this.paintHeight),this.p.putImageData(t,0,0)},i.prototype._avgLab=function(t,i){var n,e,r,o,s,a,h,p,l,u,c,g;for(u=[0,0,0,0],h=u[0],n=u[1],e=u[2],c=u[3],a=0,p=t.length;p>a;a++)o=t[a],null!=o.buckets[i]&&(c+=o.buckets[i]);for(s in t)hasProp.call(t,s)&&(o=t[s],g=null!=o.buckets[i]?0|o.buckets[i]:0,l=g/c,r=d3.lab(o.color),h+=l*r.l,n+=l*r.a,e+=l*r.b);return d3.lab(h,n,e).toString()},i.prototype.draw=function(t){return null==t&&(t=0),this.clear(),this.ctx.drawImage(this.paint,t,0),i.__super__.draw.call(this)},i.prototype.bucketsChanged=function(){return this.redraw()},i.prototype.bucketRangeChanged=function(){return this._transitionRangeAxes(),this.redraw()},i.prototype.opacityChanged=function(){return this._setOpacityFunction(),this.redraw()},i.prototype.bucketPaddingChanged=function(){return this.redraw()},i.prototype.paintZeroValuesChanged=function(){return this.redraw()},i.prototype.cutOutliersChanged=function(){return this.redraw()},i.prototype.layerChanged=function(){return this.redraw()},i}(Epoch.Time.Plot);var extend=function(t,i){function n(){this.constructor=t}for(var e in i)hasProp.call(i,e)&&(t[e]=i[e]);return n.prototype=i.prototype,t.prototype=new n,t.__super__=i.prototype,t},hasProp={}.hasOwnProperty;Epoch.Time.Line=function(t){function i(t){var n;this.options=null!=t?t:{},null==(n=this.options).type&&(n.type="time.line"),i.__super__.constructor.call(this,this.options),this.draw()}return extend(i,t),i.prototype.setStyles=function(t){var i;return i=this.getStyles("g."+t.replace(/\s/g,".")+" path.line"),this.ctx.fillStyle=i.fill,this.ctx.strokeStyle=i.stroke,this.ctx.lineWidth=this.pixelRatio*i["stroke-width"].replace("px","")},i.prototype.draw=function(t){var n,e,r,o,s,a,h,p,l,u,c,g;for(null==t&&(t=0),this.clear(),c=this.w(),p=this.getVisibleLayers(),o=0,h=p.length;h>o;o++)if(a=p[o],Epoch.isNonEmptyArray(a.values)){for(this.setStyles(a.className),this.ctx.beginPath(),g=this.y(a.range),l=[this.options.windowSize,a.values.length,this.inTransition()],r=l[0],s=l[1],u=l[2];--r>=-2&&--s>=0;)e=a.values[s],n=[(r+1)*c+t,g(e.y)],u&&(n[0]+=c),r===this.options.windowSize-1?this.ctx.moveTo.apply(this.ctx,n):this.ctx.lineTo.apply(this.ctx,n);this.ctx.stroke()}return i.__super__.draw.call(this)},i}(Epoch.Time.Plot),Epoch._typeMap={area:Epoch.Chart.Area,bar:Epoch.Chart.Bar,line:Epoch.Chart.Line,pie:Epoch.Chart.Pie,scatter:Epoch.Chart.Scatter,histogram:Epoch.Chart.Histogram,"time.area":Epoch.Time.Area,"time.bar":Epoch.Time.Bar,"time.line":Epoch.Time.Line,"time.gauge":Epoch.Time.Gauge,"time.heatmap":Epoch.Time.Heatmap};var jQueryModule;jQueryModule=function(t){var i;return i="epoch-chart",t.fn.epoch=function(t){var n,e;return t.el=this.get(0),null==(n=this.data(i))&&(e=Epoch._typeMap[t.type],null==e&&Epoch.exception("Unknown chart type '"+t.type+"'"),this.data(i,n=new e(t))),n}},null!=window.jQuery&&jQueryModule(jQuery);var MooToolsModule;MooToolsModule=function(){var t;return t="epoch-chart",Element.implement("epoch",function(i){var n,e,r;return r=$$(this),null==(n=r.retrieve(t)[0])&&(i.el=this,e=Epoch._typeMap[i.type],null==e&&Epoch.exception("Unknown chart type '"+i.type+"'"),r.store(t,n=new e(i))),n})},null!=window.MooTools&&MooToolsModule();var zeptoModule;zeptoModule=function(t){var i,n,e,r;return i="epoch-chart",e={},n=0,r=function(){return i+"-"+ ++n},t.extend(t.fn,{epoch:function(t){var n,o,s;return null!=(o=this.data(i))?e[o]:(t.el=this.get(0),s=Epoch._typeMap[t.type],null==s&&Epoch.exception("Unknown chart type '"+t.type+"'"),this.data(i,o=r()),n=new s(t),e[o]=n,n)}})},null!=window.Zepto&&zeptoModule(Zepto); \ No newline at end of file
diff --git a/modules/http/static/favicon.ico b/modules/http/static/favicon.ico
new file mode 100644
index 0000000..2ffdb52
--- /dev/null
+++ b/modules/http/static/favicon.ico
Binary files differ
diff --git a/modules/http/static/glyphicons-halflings-regular.woff2 b/modules/http/static/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
--- /dev/null
+++ b/modules/http/static/glyphicons-halflings-regular.woff2
Binary files differ
diff --git a/modules/http/static/jquery.js b/modules/http/static/jquery.js
new file mode 100644
index 0000000..fc356ee
--- /dev/null
+++ b/modules/http/static/jquery.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){
+return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ia={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qa[0].contentDocument,b.write(),b.close(),c=sa(a,b),qa.detach()),ra[a]=c),c}var ua=/^margin/,va=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wa=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xa(a,b,c){var d,e,f,g,h=a.style;return c=c||wa(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),va.test(g)&&ua.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function ya(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var za=/^(none|table(?!-c[ea]).+)/,Aa=new RegExp("^("+Q+")(.*)$","i"),Ba=new RegExp("^([+-])=("+Q+")","i"),Ca={position:"absolute",visibility:"hidden",display:"block"},Da={letterSpacing:"0",fontWeight:"400"},Ea=["Webkit","O","Moz","ms"];function Fa(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Ea.length;while(e--)if(b=Ea[e]+c,b in a)return b;return d}function Ga(a,b,c){var d=Aa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Ha(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ia(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wa(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xa(a,b,f),(0>e||null==e)&&(e=a.style[b]),va.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Ha(a,b,c||(g?"border":"content"),d,f)+"px"}function Ja(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",ta(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xa(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fa(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Ba.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fa(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xa(a,b,d)),"normal"===e&&b in Da&&(e=Da[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?za.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Ca,function(){return Ia(a,b,d)}):Ia(a,b,d):void 0},set:function(a,c,d){var e=d&&wa(a);return Ga(a,c,d?Ha(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=ya(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ua.test(a)||(n.cssHooks[a+b].set=Ga)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wa(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Ja(this,!0)},hide:function(){return Ja(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Ka(a,b,c,d,e){return new Ka.prototype.init(a,b,c,d,e)}n.Tween=Ka,Ka.prototype={constructor:Ka,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ka.propHooks[this.prop];return a&&a.get?a.get(this):Ka.propHooks._default.get(this)},run:function(a){var b,c=Ka.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ka.propHooks._default.set(this),this}},Ka.prototype.init.prototype=Ka.prototype,Ka.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Ka.propHooks.scrollTop=Ka.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Ka.prototype.init,n.fx.step={};var La,Ma,Na=/^(?:toggle|show|hide)$/,Oa=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pa=/queueHooks$/,Qa=[Va],Ra={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Oa.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Oa.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sa(){return setTimeout(function(){La=void 0}),La=n.now()}function Ta(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ua(a,b,c){for(var d,e=(Ra[b]||[]).concat(Ra["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Va(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||ta(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Na.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?ta(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ua(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wa(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xa(a,b,c){var d,e,f=0,g=Qa.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=La||Sa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:La||Sa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wa(k,j.opts.specialEasing);g>f;f++)if(d=Qa[f].call(j,a,k,j.opts))return d;return n.map(k,Ua,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xa,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Ra[c]=Ra[c]||[],Ra[c].unshift(b)},prefilter:function(a,b){b?Qa.unshift(a):Qa.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xa(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pa.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Ta(b,!0),a,d,e)}}),n.each({slideDown:Ta("show"),slideUp:Ta("hide"),slideToggle:Ta("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(La=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),La=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ma||(Ma=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Ma),Ma=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Ya,Za,$a=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Za:Ya)),
+void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Za={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$a[b]||n.find.attr;$a[b]=function(a,b,d){var e,f;return d||(f=$a[b],$a[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$a[b]=f),e}});var _a=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_a.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ab=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ab," ").indexOf(b)>=0)return!0;return!1}});var bb=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cb=n.now(),db=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var eb=/#.*$/,fb=/([?&])_=[^&]*/,gb=/^(.*?):[ \t]*([^\r\n]*)$/gm,hb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ib=/^(?:GET|HEAD)$/,jb=/^\/\//,kb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lb={},mb={},nb="*/".concat("*"),ob=a.location.href,pb=kb.exec(ob.toLowerCase())||[];function qb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rb(a,b,c,d){var e={},f=a===mb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function ub(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ob,type:"GET",isLocal:hb.test(pb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sb(sb(a,n.ajaxSettings),b):sb(n.ajaxSettings,a)},ajaxPrefilter:qb(lb),ajaxTransport:qb(mb),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gb.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||ob)+"").replace(eb,"").replace(jb,pb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kb.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pb[1]&&h[2]===pb[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pb[3]||("http:"===pb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rb(lb,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ib.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(db.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fb.test(d)?d.replace(fb,"$1_="+cb++):d+(db.test(d)?"&":"?")+"_="+cb++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nb+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rb(mb,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tb(k,v,f)),u=ub(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vb=/%20/g,wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&").replace(vb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bb=0,Cb={},Db={0:200,1223:204},Eb=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cb)Cb[a]()}),k.cors=!!Eb&&"withCredentials"in Eb,k.ajax=Eb=!!Eb,n.ajaxTransport(function(a){var b;return k.cors||Eb&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cb[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Db[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cb[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fb=[],Gb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fb.pop()||n.expando+"_"+cb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gb.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gb,"$1"+e):b.jsonp!==!1&&(b.url+=(db.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hb)return Hb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ib=a.document.documentElement;function Jb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ib;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ib})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jb(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=ya(k.pixelPosition,function(a,c){return c?(c=xa(a,b),va.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kb=a.jQuery,Lb=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lb),b&&a.jQuery===n&&(a.jQuery=Kb),n},typeof b===U&&(a.jQuery=a.$=n),n}); \ No newline at end of file
diff --git a/modules/http/static/kresd.css b/modules/http/static/kresd.css
new file mode 100644
index 0000000..48040e4
--- /dev/null
+++ b/modules/http/static/kresd.css
@@ -0,0 +1,43 @@
+/*
+ * Base structure
+ */
+
+/* Move down content because we have a fixed navbar that is 50px tall */
+body {
+ padding-top: 50px;
+}
+
+/*
+ * Tags and labels.
+ */
+.tag {
+ margin: 0 3px 3px 0;
+}
+
+.tag-default {
+ background-color: #efefef !important;
+ color: #000 !important;
+}
+
+.tag-warning {
+ background-color: #f0ad4e !important;
+ border-color: #eea236 !important;
+ color: #fff !important;
+}
+.tag-success {
+ background-color: #5cb85c !important;
+ border-color: #4cae4c !important;
+ color: #fff !important;
+}
+
+.spark {
+ display: inline-block;
+}
+
+.spark-legend {
+ display: inline-block;
+}
+
+.dygraph-legend {
+ text-align: right;
+}
diff --git a/modules/http/static/kresd.js b/modules/http/static/kresd.js
new file mode 100644
index 0000000..ceb16ed
--- /dev/null
+++ b/modules/http/static/kresd.js
@@ -0,0 +1,366 @@
+var colours = ["#081d58", "#253494", "#225ea8", "#1d91c0", "#41b6c4", "#7fcdbb", "#c7e9b4", "#edf8b1", "#edf8b1"];
+var latency = ["slow", "1500ms", "1000ms", "500ms", "250ms", "100ms", "50ms", "10ms", "1ms"];
+var Socket = "MozWebSocket" in window ? MozWebSocket : WebSocket;
+let isGraphPaused = false;
+
+$(function() {
+ /* Helper functions */
+ function colorBracket(rtt) {
+ for (var i = latency.length - 1; i >= 0; i--) {
+ if (rtt <= parseInt(latency[i])) {
+ return 'q' + i;
+ }
+ }
+ return 'q8';
+ }
+ function toGeokey(lon, lat) {
+ return lon.toFixed(0)+'#'+lat.toFixed(0);
+ }
+ function updateVisibility(graph, metrics, id, toggle) {
+ /* Some labels are aggregates */
+ if (metrics[id] == null) {
+ for (var key in metrics) {
+ const m = metrics[key];
+ if (m.length > 3 && m[3] == id) {
+ graph.setVisibility(m[0], toggle);
+ }
+ }
+ } else {
+ graph.setVisibility(metrics[id][0], toggle);
+ }
+ }
+ function formatNumber(n) {
+ with (Math) {
+ var base = floor(log(abs(n))/log(1000));
+ var suffix = 'KMB'[base-1];
+ return suffix ? String(n/pow(1000,base)).substring(0,3)+suffix : ''+n;
+ }
+ }
+
+ /* Initialize snippets. */
+ $('section').each(function () {
+ const heading = $(this).find('h2');
+ $('#modules-dropdown').append('<li><a href="#'+this.id+'">'+heading.text()+'</a></li>');
+ });
+
+ /* Render other interesting metrics as lines (hidden by default) */
+ var data = [];
+ var last_metric = 17;
+ var metrics = {
+ 'answer.noerror': [0, 'NOERROR', null, 'By RCODE'],
+ 'answer.nodata': [1, 'NODATA', null, 'By RCODE'],
+ 'answer.nxdomain': [2, 'NXDOMAIN', null, 'By RCODE'],
+ 'answer.servfail': [3, 'SERVFAIL', null, 'By RCODE'],
+ 'answer.dnssec': [4, 'DNSSEC', null, 'By RCODE'],
+ 'cache.hit': [5, 'Cache hit'],
+ 'cache.miss': [6, 'Cache miss'],
+ 'cache.insert': [7, 'Cache insert'],
+ 'cache.delete': [8, 'Cache delete'],
+ 'worker.udp': [9, 'UDP queries'],
+ 'worker.tcp': [10, 'TCP queries'],
+ 'worker.ipv4': [11, 'IPv4 queries'],
+ 'worker.ipv6': [12, 'IPv6 queries'],
+ 'worker.concurrent': [13, 'Concurrent requests'],
+ 'worker.queries': [14, 'Queries received/s'],
+ 'worker.dropped': [15, 'Queries dropped'],
+ 'worker.usertime': [16, 'CPU (user)', null, 'Workers'],
+ 'worker.systime': [17, 'CPU (sys)', null, 'Workers'],
+ };
+
+ /* Render latency metrics as sort of a heatmap */
+ var series = {};
+ for (var i in latency) {
+ const name = 'RTT '+latency[i];
+ const colour = colours[colours.length - i - 1];
+ last_metric = last_metric + 1;
+ metrics['answer.'+latency[i]] = [last_metric, name, colour, 'latency'];
+ series[name] = {fillGraph: true, color: colour, fillAlpha: 1.0};
+ }
+ var labels = ['x'];
+ var visibility = [];
+ for (var key in metrics) {
+ labels.push(metrics[key][1]);
+ visibility.push(false);
+ }
+
+ /* Define how graph looks like. */
+ const graphContainer = $('#stats');
+ const graph = new Dygraph(
+ document.getElementById("chart"),
+ data, {
+ labels: labels,
+ labelsUTC: true,
+ labelsShowZeroValues: false,
+ visibility: visibility,
+ axes: { y: {
+ axisLabelFormatter: function(d) {
+ return formatNumber(d) + 'pps';
+ },
+ }},
+ series: series,
+ strokeWidth: 1,
+ highlightSeriesOpts: {
+ strokeWidth: 3,
+ strokeBorderWidth: 1,
+ highlightCircleSize: 5,
+ },
+ });
+ /* Define metric selector */
+ const chartSelector = $('#chart-selector').selectize({
+ maxItems: null,
+ create: false,
+ onItemAdd: function (x) { updateVisibility(graph, metrics, x, true); },
+ onItemRemove: function (x) { updateVisibility(graph, metrics, x, false); }
+ })[0].selectize;
+ for (var key in metrics) {
+ const m = metrics[key];
+ const groupid = m.length > 3 ? m[3] : key.split('.')[0];
+ const group = m.length > 3 ? m[3] : m[1].split(' ')[0];
+ /* Latency has a special aggregated item */
+ if (group != 'latency') {
+ chartSelector.addOptionGroup(groupid, { label: group } );
+ chartSelector.addOption({ text: m[1], value: key, optgroup: groupid });
+ }
+ }
+ /* Add latency as default */
+ chartSelector.addOption({ text: 'Latency', value: 'latency', optgroup: 'Queries' });
+ chartSelector.addItem('latency');
+ /* Add stacked graph control */
+ $('#chart-stacked').on('change', function(e) {
+ graph.updateOptions({stackedGraph: this.checked});
+ }).click();
+
+ /* Data map */
+ var fills = { defaultFill: '#F5F5F5' };
+ for (var i in colours) {
+ fills['q' + i] = colours[i];
+ }
+ const map = new Datamap({
+ element: document.getElementById('map'),
+ fills: fills,
+ data: {},
+ height: 400,
+ geographyConfig: {
+ highlightOnHover: false,
+ borderColor: '#ccc',
+ borderWidth: 0.5,
+ popupTemplate: function(geo, data) {
+ return ['<div class="hoverinfo">',
+ '<strong>', geo.properties.name, '</strong>',
+ '<br>Queries: <strong>', data ? data.queries : '0', '</strong>',
+ '</div>'].join('');
+ }
+ },
+ bubblesConfig: {
+ popupTemplate: function(geo, data) {
+ return ['<div class="hoverinfo">',
+ '<strong>', data.name, '</strong>',
+ '<br>Queries: <strong>', data ? data.queries : '0', '</strong>',
+ '<br>Average RTT: <strong>', data ? parseInt(data.rtt) : '0', ' ms</strong>',
+ '</div>'].join('');
+ }
+ }
+ });
+
+ /* Realtime updates over WebSockets */
+ function pushMetrics(resp, now, buffer) {
+ var line = new Array(labels.length);
+ line[0] = new Date(now * 1000);
+ for (var lb in resp) {
+ /* Push new datapoints */
+ const metric = metrics[lb];
+ if (metric) {
+ line[metric[0] + 1] = resp[lb];
+ }
+ }
+ /* Buffer graph changes. */
+ data.push(line);
+ if (data.length > 1000) {
+ data.shift();
+ }
+ if ( !buffer ) {
+ if ( !isGraphPaused ) {
+ graph.updateOptions( { 'file': data } );
+ }
+ }
+ }
+
+ var age = 0;
+ var bubbles = [];
+ var bubblemap = {};
+ function pushUpstreams(resp) {
+ if (resp == null) {
+ $('#map-container').hide();
+ return;
+ } else {
+ $('#map-container').show();
+ }
+ /* Get current maximum number of queries for bubble diameter adjustment */
+ var maxQueries = 1;
+ for (var key in resp) {
+ var val = resp[key];
+ if ('data' in val) {
+ maxQueries = Math.max(maxQueries, resp[key].data.length)
+ }
+ }
+ /* Update bubbles and prune the oldest */
+ for (var key in resp) {
+ var val = resp[key];
+ if (!val.data || !val.location || val.location.longitude == null) {
+ continue;
+ }
+ var sum = val.data.reduce(function(a, b) { return a + b; });
+ var avg = sum / val.data.length;
+ var geokey = toGeokey(val.location.longitude, val.location.latitude)
+ var found = bubblemap[geokey];
+ if (!found) {
+ found = {
+ name: [key],
+ longitude: val.location.longitude,
+ latitude: val.location.latitude,
+ queries: 0,
+ rtt: avg,
+ }
+ bubbles.push(found);
+ bubblemap[geokey] = found;
+ }
+ /* Update bubble parameters */
+ if (!(key in found.name)) {
+ found.name.push(key);
+ }
+ found.rtt = (found.rtt + avg) / 2.0;
+ found.fillKey = colorBracket(found.rtt);
+ found.queries = found.queries + val.data.length;
+ found.radius = Math.max(5, 15*(val.data.length/maxQueries));
+ found.age = age;
+ }
+ /* Prune bubbles not updated in a while. */
+ for (var i in bubbles) {
+ var b = bubbles[i];
+ if (b.age <= age - 5) {
+ bubbles.splice(i, 1)
+ bubblemap[i] = null;
+ }
+ }
+ map.bubbles(bubbles);
+ age = age + 1;
+ }
+
+ /* Per-worker information */
+ function updateRate(x, y, dt) {
+ return (100.0 * ((x - y) / dt)).toFixed(1);
+ }
+ function updateWorker(row, next, data, timestamp, buffer) {
+ const dt = timestamp - data.timestamp;
+ const cell = row.find('td');
+ /* Update spark lines and CPU times first */
+ if (dt > 0.0) {
+ const utimeRate = updateRate(next.usertime, data.last.usertime, dt);
+ const stimeRate = updateRate(next.systime, data.last.systime, dt);
+ cell.eq(1).find('span').text(utimeRate + '% / ' + stimeRate + '%');
+ /* Update sparkline graph */
+ data.data.push([new Date(timestamp * 1000), Number(utimeRate), Number(stimeRate)]);
+ if (data.data.length > 60) {
+ data.data.shift();
+ }
+ if (!buffer) {
+ data.graph.updateOptions( { 'file': data.data } );
+ }
+ }
+ /* Update other fields */
+ if (!buffer) {
+ cell.eq(2).text(formatNumber(next.rss) + 'B');
+ cell.eq(3).text(next.pagefaults);
+ cell.eq(4).text('Healthy').addClass('text-success');
+ }
+ }
+
+ var workerData = {};
+ function pushWorkers(resp, timestamp, buffer) {
+ if (resp == null) {
+ return;
+ }
+ const workerTable = $('#workers');
+ for (var pid in resp) {
+ var row = workerTable.find('tr[data-pid='+pid+']');
+ if (row.length == 0) {
+ row = workerTable.append(
+ '<tr data-pid='+pid+'><td>'+pid+'</td>'+
+ '<td><div class="spark" id="spark-'+pid+'" /><span /></td><td></td><td></td><td></td>'+
+ '</tr>');
+ /* Create sparkline visualisation */
+ const spark = row.find('#spark-'+pid);
+ spark.css({'margin-right': '1em', width: '80px', height: '1.4em'});
+ workerData[pid] = {timestamp: timestamp, data: [[new Date(timestamp * 1000),0,0]], last: resp[pid]};
+ const workerGraph = new Dygraph(spark[0],
+ workerData[pid].data, {
+ valueRange: [0, 100],
+ legend: 'never',
+ axes : {
+ x : {
+ drawGrid: false,
+ drawAxis : false,
+ },
+ y : {
+ drawGrid: false,
+ drawAxis : false,
+ }
+ },
+ labels: ['x', '%user', '%sys'],
+ labelsDiv: '',
+ stackedGraph: true,
+ }
+ );
+ workerData[pid].graph = workerGraph;
+ }
+ updateWorker(row, resp[pid], workerData[pid], timestamp, buffer);
+ /* Track last datapoint */
+ workerData[pid].last = resp[pid];
+ workerData[pid].timestamp = timestamp;
+ }
+ /* Prune unhealthy PIDs */
+ if (!buffer) {
+ workerTable.find('tr').each(function () {
+ const e = $(this);
+ if (!(e.data('pid') in resp)) {
+ const healthCell = e.find('td').last();
+ healthCell.removeClass('text-success')
+ healthCell.text('Dead').addClass('text-danger');
+ }
+ });
+ }
+ }
+
+ /* WebSocket endpoints */
+ var wsStats = (secure ? 'wss://' : 'ws://') + location.host + '/stats';
+ var ws = new Socket(wsStats);
+ ws.onmessage = function(evt) {
+ var data = JSON.parse(evt.data);
+ if (data[0]) {
+ if (data.length > 0) {
+ pushUpstreams(data[data.length - 1].upstreams);
+ }
+ /* Buffer datapoints and redraw last */
+ for (var i in data) {
+ const is_last = (i == data.length - 1);
+ pushWorkers(data[i].workers, data[i].time, !is_last);
+ pushMetrics(data[i].stats, data[i].time, !is_last);
+ }
+ } else {
+ pushUpstreams(data.upstreams);
+ pushWorkers(data.workers, data.time);
+ pushMetrics(data.stats, data.time);
+ }
+ };
+
+ chartElement.addEventListener( 'mouseover', ( event ) =>
+ {
+ isGraphPaused = true;
+ }, false );
+
+ chartElement.addEventListener( 'mouseout', ( event ) =>
+ {
+ isGraphPaused = false;
+ }, false );
+
+});
diff --git a/modules/http/static/main.tpl b/modules/http/static/main.tpl
new file mode 100644
index 0000000..e4eebbd
--- /dev/null
+++ b/modules/http/static/main.tpl
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>{{ title }}</title>
+<script type="text/javascript">
+ var host = "{{ host }}";
+ var secure = {{ secure }};
+</script>
+<script src="jquery.js"></script>
+<script src="bootstrap.min.js"></script>
+<script src="d3.js"></script>
+<script src="dygraph-combined.js"></script>
+<script src="selectize.min.js"></script>
+<script src="topojson.js"></script>
+<script src="datamaps.world.min.js"></script>
+<script src="kresd.js"></script>
+<link rel="icon" type="image/ico" href="favicon.ico">
+<link href="kresd.css" rel="stylesheet">
+<link href="bootstrap.min.css" rel="stylesheet">
+<link href="selectize.bootstrap3.min.css" rel="stylesheet">
+<nav class="navbar navbar-inverse navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="#">{{ title }}</a>
+ </div>
+ <ul class="nav navbar-nav navbar-right">
+ <li><a href="#">Metrics</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Modules <span class="caret"></span></a>
+ <ul class="dropdown-menu" id="modules-dropdown">
+ </ul>
+ </li>
+ </ul>
+ </div>
+</nav>
+<div class="container">
+ <div class="main">
+ <h2 class="sub-header">Metrics</h2>
+ <div class="col-md-12">
+ <div class="row">
+ <div id="stats" class="row placeholders">
+ <div id="chart" style="width:100%"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-12">
+ <h3><small>More metrics</small></h3>
+ <div class="col-md-11">
+ <select id="chart-selector" multiple></select>
+ </div>
+ <div class="col-md-1">
+ <div class="checkbox">
+ <label><input id="chart-stacked" type="checkbox">Stacked</label>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <h3>Instances</h3>
+ <div class="col-md-12">
+ <table id="workers" class="table table-responsive">
+ <tr>
+ <th>PID</th><th>CPU per-worker (user/sys)</th>
+ <th>RSS</th><th>Page faults</th><th>Status</th>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="row" id="map-container">
+ <a name="worldmap"></a>
+ <h2 class="sub-header">Outbound queries</h2>
+ <div class="col-md-12">
+ <div id="map" style="position: relative;"></div>
+ </div>
+ </div>
+ <div class="col-md-12">
+ {{ snippets }}
+ </div>
+ </div>
+</div>
diff --git a/modules/http/static/selectize.bootstrap3.min.css b/modules/http/static/selectize.bootstrap3.min.css
new file mode 100644
index 0000000..d5da6fd
--- /dev/null
+++ b/modules/http/static/selectize.bootstrap3.min.css
@@ -0,0 +1 @@
+.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,0.06) !important;border:0 none !important;-webkit-box-shadow:inset 0 0 12px 4px #fff;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:'!';visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{-webkit-box-shadow:0 2px 5px rgba(0,0,0,0.2);box-shadow:0 2px 5px rgba(0,0,0,0.2)}.selectize-dropdown-header{position:relative;padding:3px 12px;border-bottom:1px solid #d0d0d0;background:#f8f8f8;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.selectize-dropdown-header-close{position:absolute;right:12px;top:50%;color:#333;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px !important}.selectize-dropdown-header-close:hover{color:#000}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button [data-value]{position:relative;padding-right:24px !important}.selectize-control.plugin-remove_button [data-value] .remove{z-index:1;position:absolute;top:0;right:0;bottom:0;width:17px;text-align:center;font-weight:bold;font-size:12px;color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:1px 0 0 0;border-left:1px solid rgba(0,0,0,0);-webkit-border-radius:0 2px 2px 0;-moz-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-control.plugin-remove_button [data-value] .remove:hover{background:rgba(0,0,0,0.05)}.selectize-control.plugin-remove_button [data-value].active .remove{border-left-color:rgba(0,0,0,0)}.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover{background:0}.selectize-control.plugin-remove_button .disabled [data-value] .remove{border-left-color:rgba(77,77,77,0)}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:#333;font-family:inherit;font-size:inherit;line-height:20px;-webkit-font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:#fff;cursor:text;display:inline-block}.selectize-input{border:1px solid #ccc;padding:6px 12px;display:inline-block;width:100%;overflow:hidden;position:relative;z-index:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:none;box-shadow:none;}.selectize-control.multi .selectize-input.has-items{padding:5px 12px 2px}.selectize-input.full{background-color:#fff}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.15)}.selectize-input.dropdown-active{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.selectize-input>*{vertical-align:baseline;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 3px;background:#efefef;color:#333;border:0 solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input>div.active{background:#428bca;color:#fff;border:0 solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:gray;background:#fff;border:0 solid rgba(77,77,77,0)}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;-webkit-user-select:auto !important;-webkit-box-shadow:none !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input::after{content:' ';display:block;clear:left}.selectize-input.dropdown-active::before{content:' ';display:block;position:absolute;background:#fff;height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;z-index:10;border:1px solid #d0d0d0;background:#fff;margin:-1px 0 0 0;border-top:0 none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1);-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(255,237,40,0.4);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.selectize-dropdown [data-selectable],.selectize-dropdown .optgroup-header{padding:3px 12px}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#777;background:#fff;cursor:default}.selectize-dropdown .active{background-color:#f5f5f5;color:#262626}.selectize-dropdown .active.create{color:#262626}.selectize-dropdown .create{color:rgba(51,51,51,0.5)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input{cursor:text}.selectize-control.single .selectize-input:after{content:' ';display:block;position:absolute;top:50%;right:17px;margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#333 transparent transparent transparent}.selectize-control.single .selectize-input.dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent #333 transparent}.selectize-control.rtl.single .selectize-input:after{left:17px;right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:#fff}.selectize-dropdown,.selectize-dropdown.form-control{height:auto;padding:0;margin:2px 0 0 0;z-index:1000;background:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175)}.selectize-dropdown .optgroup-header{font-size:12px;line-height:1.42857143}.selectize-dropdown .optgroup:first-child:before{display:none}.selectize-dropdown .optgroup:before{content:' ';display:block;height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5;margin-left:-12px;margin-right:-12px}.selectize-dropdown-content{padding:5px 0}.selectize-dropdown-header{padding:6px 12px}.selectize-input{min-height:34px}.selectize-input.dropdown-active{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.selectize-input.dropdown-active::before{display:none}.selectize-input.focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6)}.has-error .selectize-input{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .selectize-input:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.selectize-control.multi .selectize-input.has-items{padding-left:9px;padding-right:9px}.selectize-control.multi .selectize-input>div{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.form-control.selectize-control{padding:0;height:auto;border:0;background:0;-webkit-box-shadow:none;box-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} \ No newline at end of file
diff --git a/modules/http/static/selectize.min.css b/modules/http/static/selectize.min.css
new file mode 100644
index 0000000..077488d
--- /dev/null
+++ b/modules/http/static/selectize.min.css
@@ -0,0 +1 @@
+.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,0.06) !important;border:0 none !important;-webkit-box-shadow:inset 0 0 12px 4px #fff;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:'!';visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{-webkit-box-shadow:0 2px 5px rgba(0,0,0,0.2);box-shadow:0 2px 5px rgba(0,0,0,0.2)}.selectize-dropdown-header{position:relative;padding:5px 8px;border-bottom:1px solid #d0d0d0;background:#f8f8f8;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.selectize-dropdown-header-close{position:absolute;right:8px;top:50%;color:#303030;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px !important}.selectize-dropdown-header-close:hover{color:#000}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button [data-value]{position:relative;padding-right:24px !important}.selectize-control.plugin-remove_button [data-value] .remove{z-index:1;position:absolute;top:0;right:0;bottom:0;width:17px;text-align:center;font-weight:bold;font-size:12px;color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:2px 0 0 0;border-left:1px solid #d0d0d0;-webkit-border-radius:0 2px 2px 0;-moz-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-control.plugin-remove_button [data-value] .remove:hover{background:rgba(0,0,0,0.05)}.selectize-control.plugin-remove_button [data-value].active .remove{border-left-color:#cacaca}.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover{background:0}.selectize-control.plugin-remove_button .disabled [data-value] .remove{border-left-color:#fff}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:#303030;font-family:inherit;font-size:13px;line-height:18px;-webkit-font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:#fff;cursor:text;display:inline-block}.selectize-input{border:1px solid #d0d0d0;padding:8px 8px;display:inline-block;width:100%;overflow:hidden;position:relative;z-index:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.1);box-shadow:inset 0 1px 1px rgba(0,0,0,0.1);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.selectize-control.multi .selectize-input.has-items{padding:6px 8px 3px}.selectize-input.full{background-color:#fff}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.15)}.selectize-input.dropdown-active{-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.selectize-input>*{vertical-align:baseline;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:2px 6px;background:#f2f2f2;color:#303030;border:0 solid #d0d0d0}.selectize-control.multi .selectize-input>div.active{background:#e8e8e8;color:#303030;border:0 solid #cacaca}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:#7d7d7d;background:#fff;border:0 solid #fff}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 2px 0 0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;-webkit-user-select:auto !important;-webkit-box-shadow:none !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input::after{content:' ';display:block;clear:left}.selectize-input.dropdown-active::before{content:' ';display:block;position:absolute;background:#f0f0f0;height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;z-index:10;border:1px solid #d0d0d0;background:#fff;margin:-1px 0 0 0;border-top:0 none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1);-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(125,168,208,0.2);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.selectize-dropdown [data-selectable],.selectize-dropdown .optgroup-header{padding:5px 8px}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#303030;background:#fff;cursor:default}.selectize-dropdown .active{background-color:#f5fafd;color:#495c68}.selectize-dropdown .active.create{color:#495c68}.selectize-dropdown .create{color:rgba(48,48,48,0.5)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input{cursor:text}.selectize-control.single .selectize-input:after{content:' ';display:block;position:absolute;top:50%;right:15px;margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#808080 transparent transparent transparent}.selectize-control.single .selectize-input.dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent #808080 transparent}.selectize-control.rtl.single .selectize-input:after{left:15px;right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:#fafafa} \ No newline at end of file
diff --git a/modules/http/static/selectize.min.js b/modules/http/static/selectize.min.js
new file mode 100644
index 0000000..b0236da
--- /dev/null
+++ b/modules/http/static/selectize.min.js
@@ -0,0 +1,3 @@
+/*! selectize.js - v0.12.1 | https://github.com/brianreavis/selectize.js | Apache License (v2) */
+!function(e,t){"function"==typeof define&&define.amd?define("sifter",t):"object"==typeof exports?module.exports=t():e.Sifter=t()}(this,function(){var e=function(e,t){this.items=e,this.settings=t||{diacritics:!0}};e.prototype.tokenize=function(e){if(e=i(String(e||"").toLowerCase()),!e||!e.length)return[];var t,n,r,a,l=[],p=e.split(/ +/);for(t=0,n=p.length;n>t;t++){if(r=o(p[t]),this.settings.diacritics)for(a in s)s.hasOwnProperty(a)&&(r=r.replace(new RegExp(a,"g"),s[a]));l.push({string:p[t],regex:new RegExp(r,"i")})}return l},e.prototype.iterator=function(e,t){var n;n=r(e)?Array.prototype.forEach||function(e){for(var t=0,n=this.length;n>t;t++)e(this[t],t,this)}:function(e){for(var t in this)this.hasOwnProperty(t)&&e(this[t],t,this)},n.apply(e,[t])},e.prototype.getScoreFunction=function(e,t){var n,i,o,r;n=this,e=n.prepareSearch(e,t),o=e.tokens,i=e.options.fields,r=o.length;var s=function(e,t){var n,i;return e?(e=String(e||""),i=e.search(t.regex),-1===i?0:(n=t.string.length/e.length,0===i&&(n+=.5),n)):0},a=function(){var e=i.length;return e?1===e?function(e,t){return s(t[i[0]],e)}:function(t,n){for(var o=0,r=0;e>o;o++)r+=s(n[i[o]],t);return r/e}:function(){return 0}}();return r?1===r?function(e){return a(o[0],e)}:"and"===e.options.conjunction?function(e){for(var t,n=0,i=0;r>n;n++){if(t=a(o[n],e),0>=t)return 0;i+=t}return i/r}:function(e){for(var t=0,n=0;r>t;t++)n+=a(o[t],e);return n/r}:function(){return 0}},e.prototype.getSortFunction=function(e,n){var i,o,r,s,a,l,p,u,c,d,h;if(r=this,e=r.prepareSearch(e,n),h=!e.query&&n.sort_empty||n.sort,c=function(e,t){return"$score"===e?t.score:r.items[t.id][e]},a=[],h)for(i=0,o=h.length;o>i;i++)(e.query||"$score"!==h[i].field)&&a.push(h[i]);if(e.query){for(d=!0,i=0,o=a.length;o>i;i++)if("$score"===a[i].field){d=!1;break}d&&a.unshift({field:"$score",direction:"desc"})}else for(i=0,o=a.length;o>i;i++)if("$score"===a[i].field){a.splice(i,1);break}for(u=[],i=0,o=a.length;o>i;i++)u.push("desc"===a[i].direction?-1:1);return l=a.length,l?1===l?(s=a[0].field,p=u[0],function(e,n){return p*t(c(s,e),c(s,n))}):function(e,n){var i,o,r;for(i=0;l>i;i++)if(r=a[i].field,o=u[i]*t(c(r,e),c(r,n)))return o;return 0}:null},e.prototype.prepareSearch=function(e,t){if("object"==typeof e)return e;t=n({},t);var i=t.fields,o=t.sort,s=t.sort_empty;return i&&!r(i)&&(t.fields=[i]),o&&!r(o)&&(t.sort=[o]),s&&!r(s)&&(t.sort_empty=[s]),{options:t,query:String(e||"").toLowerCase(),tokens:this.tokenize(e),total:0,items:[]}},e.prototype.search=function(e,t){var n,i,o,r,s=this;return i=this.prepareSearch(e,t),t=i.options,e=i.query,r=t.score||s.getScoreFunction(i),e.length?s.iterator(s.items,function(e,o){n=r(e),(t.filter===!1||n>0)&&i.items.push({score:n,id:o})}):s.iterator(s.items,function(e,t){i.items.push({score:1,id:t})}),o=s.getSortFunction(i,t),o&&i.items.sort(o),i.total=i.items.length,"number"==typeof t.limit&&(i.items=i.items.slice(0,t.limit)),i};var t=function(e,t){return"number"==typeof e&&"number"==typeof t?e>t?1:t>e?-1:0:(e=a(String(e||"")),t=a(String(t||"")),e>t?1:t>e?-1:0)},n=function(e){var t,n,i,o;for(t=1,n=arguments.length;n>t;t++)if(o=arguments[t])for(i in o)o.hasOwnProperty(i)&&(e[i]=o[i]);return e},i=function(e){return(e+"").replace(/^\s+|\s+$|/g,"")},o=function(e){return(e+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")},r=Array.isArray||$&&$.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},s={a:"[aÀÃÂÃÄÅàáâãäåĀÄÄ…Ä„]",c:"[cÇçćĆÄÄŒ]",d:"[dÄ‘ÄÄÄŽ]",e:"[eÈÉÊËèéêëěĚĒēęĘ]",i:"[iÃŒÃÃŽÃìíîïĪī]",l:"[lÅ‚Å]",n:"[nÑñňŇńŃ]",o:"[oÒÓÔÕÕÖØòóôõöøŌÅ]",r:"[rřŘ]",s:"[sŠšśŚ]",t:"[tťŤ]",u:"[uÙÚÛÜùúûüůŮŪū]",y:"[yŸÿýÃ]",z:"[zŽžżŻźŹ]"},a=function(){var e,t,n,i,o="",r={};for(n in s)if(s.hasOwnProperty(n))for(i=s[n].substring(2,s[n].length-1),o+=i,e=0,t=i.length;t>e;e++)r[i.charAt(e)]=n;var a=new RegExp("["+o+"]","g");return function(e){return e.replace(a,function(e){return r[e]}).toLowerCase()}}();return e}),function(e,t){"function"==typeof define&&define.amd?define("microplugin",t):"object"==typeof exports?module.exports=t():e.MicroPlugin=t()}(this,function(){var e={};e.mixin=function(e){e.plugins={},e.prototype.initializePlugins=function(e){var n,i,o,r=this,s=[];if(r.plugins={names:[],settings:{},requested:{},loaded:{}},t.isArray(e))for(n=0,i=e.length;i>n;n++)"string"==typeof e[n]?s.push(e[n]):(r.plugins.settings[e[n].name]=e[n].options,s.push(e[n].name));else if(e)for(o in e)e.hasOwnProperty(o)&&(r.plugins.settings[o]=e[o],s.push(o));for(;s.length;)r.require(s.shift())},e.prototype.loadPlugin=function(t){var n=this,i=n.plugins,o=e.plugins[t];if(!e.plugins.hasOwnProperty(t))throw new Error('Unable to find "'+t+'" plugin');i.requested[t]=!0,i.loaded[t]=o.fn.apply(n,[n.plugins.settings[t]||{}]),i.names.push(t)},e.prototype.require=function(e){var t=this,n=t.plugins;if(!t.plugins.loaded.hasOwnProperty(e)){if(n.requested[e])throw new Error('Plugin has circular dependency ("'+e+'")');t.loadPlugin(e)}return n.loaded[e]},e.define=function(t,n){e.plugins[t]={name:t,fn:n}}};var t={isArray:Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}};return e}),function(e,t){"function"==typeof define&&define.amd?define("selectize",["jquery","sifter","microplugin"],t):"object"==typeof exports?module.exports=t(require("jquery"),require("sifter"),require("microplugin")):e.Selectize=t(e.jQuery,e.Sifter,e.MicroPlugin)}(this,function(e,t,n){"use strict";var i=function(e,t){if("string"!=typeof t||t.length){var n="string"==typeof t?new RegExp(t,"i"):t,i=function(e){var t=0;if(3===e.nodeType){var o=e.data.search(n);if(o>=0&&e.data.length>0){var r=e.data.match(n),s=document.createElement("span");s.className="highlight";var a=e.splitText(o),l=(a.splitText(r[0].length),a.cloneNode(!0));s.appendChild(l),a.parentNode.replaceChild(s,a),t=1}}else if(1===e.nodeType&&e.childNodes&&!/(script|style)/i.test(e.tagName))for(var p=0;p<e.childNodes.length;++p)p+=i(e.childNodes[p]);return t};return e.each(function(){i(this)})}},o=function(){};o.prototype={on:function(e,t){this._events=this._events||{},this._events[e]=this._events[e]||[],this._events[e].push(t)},off:function(e,t){var n=arguments.length;return 0===n?delete this._events:1===n?delete this._events[e]:(this._events=this._events||{},void(e in this._events!=!1&&this._events[e].splice(this._events[e].indexOf(t),1)))},trigger:function(e){if(this._events=this._events||{},e in this._events!=!1)for(var t=0;t<this._events[e].length;t++)this._events[e][t].apply(this,Array.prototype.slice.call(arguments,1))}},o.mixin=function(e){for(var t=["on","off","trigger"],n=0;n<t.length;n++)e.prototype[t[n]]=o.prototype[t[n]]};var r=/Mac/.test(navigator.userAgent),s=65,a=13,l=27,p=37,u=38,c=80,d=39,h=40,f=78,g=8,v=46,m=16,y=r?91:17,w=r?18:17,O=9,$=1,C=2,b=!/android/i.test(window.navigator.userAgent)&&!!document.createElement("form").validity,x=function(e){return"undefined"!=typeof e},S=function(e){return"undefined"==typeof e||null===e?null:"boolean"==typeof e?e?"1":"0":e+""},I=function(e){return(e+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},_=function(e){return(e+"").replace(/\$/g,"$$$$")},F={};F.before=function(e,t,n){var i=e[t];e[t]=function(){return n.apply(e,arguments),i.apply(e,arguments)}},F.after=function(e,t,n){var i=e[t];e[t]=function(){var t=i.apply(e,arguments);return n.apply(e,arguments),t}};var D=function(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}},k=function(e,t){var n;return function(){var i=this,o=arguments;window.clearTimeout(n),n=window.setTimeout(function(){e.apply(i,o)},t)}},A=function(e,t,n){var i,o=e.trigger,r={};e.trigger=function(){var n=arguments[0];return-1===t.indexOf(n)?o.apply(e,arguments):void(r[n]=arguments)},n.apply(e,[]),e.trigger=o;for(i in r)r.hasOwnProperty(i)&&o.apply(e,r[i])},P=function(e,t,n,i){e.on(t,n,function(t){for(var n=t.target;n&&n.parentNode!==e[0];)n=n.parentNode;return t.currentTarget=n,i.apply(this,[t])})},z=function(e){var t={};if("selectionStart"in e)t.start=e.selectionStart,t.length=e.selectionEnd-t.start;else if(document.selection){e.focus();var n=document.selection.createRange(),i=document.selection.createRange().text.length;n.moveStart("character",-e.value.length),t.start=n.text.length-i,t.length=i}return t},T=function(e,t,n){var i,o,r={};if(n)for(i=0,o=n.length;o>i;i++)r[n[i]]=e.css(n[i]);else r=e.css();t.css(r)},j=function(t,n){if(!t)return 0;var i=e("<test>").css({position:"absolute",top:-99999,left:-99999,width:"auto",padding:0,whiteSpace:"pre"}).text(t).appendTo("body");T(n,i,["letterSpacing","fontSize","fontFamily","fontWeight","textTransform"]);var o=i.width();return i.remove(),o},q=function(e){var t=null,n=function(n,i){var o,r,s,a,l,p,u,c;n=n||window.event||{},i=i||{},n.metaKey||n.altKey||(i.force||e.data("grow")!==!1)&&(o=e.val(),n.type&&"keydown"===n.type.toLowerCase()&&(r=n.keyCode,s=r>=97&&122>=r||r>=65&&90>=r||r>=48&&57>=r||32===r,r===v||r===g?(c=z(e[0]),c.length?o=o.substring(0,c.start)+o.substring(c.start+c.length):r===g&&c.start?o=o.substring(0,c.start-1)+o.substring(c.start+1):r===v&&"undefined"!=typeof c.start&&(o=o.substring(0,c.start)+o.substring(c.start+1))):s&&(p=n.shiftKey,u=String.fromCharCode(n.keyCode),u=p?u.toUpperCase():u.toLowerCase(),o+=u)),a=e.attr("placeholder"),!o&&a&&(o=a),l=j(o,e)+4,l!==t&&(t=l,e.width(l),e.triggerHandler("resize")))};e.on("keydown keyup update blur",n),n()},E=function(n,i){var o,r,s,a,l=this;a=n[0],a.selectize=l;var p=window.getComputedStyle&&window.getComputedStyle(a,null);if(s=p?p.getPropertyValue("direction"):a.currentStyle&&a.currentStyle.direction,s=s||n.parents("[dir]:first").attr("dir")||"",e.extend(l,{order:0,settings:i,$input:n,tabIndex:n.attr("tabindex")||"",tagType:"select"===a.tagName.toLowerCase()?$:C,rtl:/rtl/i.test(s),eventNS:".selectize"+ ++E.count,highlightedValue:null,isOpen:!1,isDisabled:!1,isRequired:n.is("[required]"),isInvalid:!1,isLocked:!1,isFocused:!1,isInputHidden:!1,isSetup:!1,isShiftDown:!1,isCmdDown:!1,isCtrlDown:!1,ignoreFocus:!1,ignoreBlur:!1,ignoreHover:!1,hasOptions:!1,currentResults:null,lastValue:"",caretPos:0,loading:0,loadedSearches:{},$activeOption:null,$activeItems:[],optgroups:{},options:{},userOptions:{},items:[],renderCache:{},onSearchChange:null===i.loadThrottle?l.onSearchChange:k(l.onSearchChange,i.loadThrottle)}),l.sifter=new t(this.options,{diacritics:i.diacritics}),l.settings.options){for(o=0,r=l.settings.options.length;r>o;o++)l.registerOption(l.settings.options[o]);delete l.settings.options}if(l.settings.optgroups){for(o=0,r=l.settings.optgroups.length;r>o;o++)l.registerOptionGroup(l.settings.optgroups[o]);delete l.settings.optgroups}l.settings.mode=l.settings.mode||(1===l.settings.maxItems?"single":"multi"),"boolean"!=typeof l.settings.hideSelected&&(l.settings.hideSelected="multi"===l.settings.mode),l.initializePlugins(l.settings.plugins),l.setupCallbacks(),l.setupTemplates(),l.setup()};return o.mixin(E),n.mixin(E),e.extend(E.prototype,{setup:function(){var t,n,i,o,s,a,l,p,u,c=this,d=c.settings,h=c.eventNS,f=e(window),g=e(document),v=c.$input;if(l=c.settings.mode,p=v.attr("class")||"",t=e("<div>").addClass(d.wrapperClass).addClass(p).addClass(l),n=e("<div>").addClass(d.inputClass).addClass("items").appendTo(t),i=e('<input type="text" autocomplete="off" />').appendTo(n).attr("tabindex",v.is(":disabled")?"-1":c.tabIndex),a=e(d.dropdownParent||t),o=e("<div>").addClass(d.dropdownClass).addClass(l).hide().appendTo(a),s=e("<div>").addClass(d.dropdownContentClass).appendTo(o),c.settings.copyClassesToDropdown&&o.addClass(p),t.css({width:v[0].style.width}),c.plugins.names.length&&(u="plugin-"+c.plugins.names.join(" plugin-"),t.addClass(u),o.addClass(u)),(null===d.maxItems||d.maxItems>1)&&c.tagType===$&&v.attr("multiple","multiple"),c.settings.placeholder&&i.attr("placeholder",d.placeholder),!c.settings.splitOn&&c.settings.delimiter){var O=c.settings.delimiter.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");c.settings.splitOn=new RegExp("\\s*"+O+"+\\s*")}v.attr("autocorrect")&&i.attr("autocorrect",v.attr("autocorrect")),v.attr("autocapitalize")&&i.attr("autocapitalize",v.attr("autocapitalize")),c.$wrapper=t,c.$control=n,c.$control_input=i,c.$dropdown=o,c.$dropdown_content=s,o.on("mouseenter","[data-selectable]",function(){return c.onOptionHover.apply(c,arguments)}),o.on("mousedown click","[data-selectable]",function(){return c.onOptionSelect.apply(c,arguments)}),P(n,"mousedown","*:not(input)",function(){return c.onItemSelect.apply(c,arguments)}),q(i),n.on({mousedown:function(){return c.onMouseDown.apply(c,arguments)},click:function(){return c.onClick.apply(c,arguments)}}),i.on({mousedown:function(e){e.stopPropagation()},keydown:function(){return c.onKeyDown.apply(c,arguments)},keyup:function(){return c.onKeyUp.apply(c,arguments)},keypress:function(){return c.onKeyPress.apply(c,arguments)},resize:function(){c.positionDropdown.apply(c,[])},blur:function(){return c.onBlur.apply(c,arguments)},focus:function(){return c.ignoreBlur=!1,c.onFocus.apply(c,arguments)},paste:function(){return c.onPaste.apply(c,arguments)}}),g.on("keydown"+h,function(e){c.isCmdDown=e[r?"metaKey":"ctrlKey"],c.isCtrlDown=e[r?"altKey":"ctrlKey"],c.isShiftDown=e.shiftKey}),g.on("keyup"+h,function(e){e.keyCode===w&&(c.isCtrlDown=!1),e.keyCode===m&&(c.isShiftDown=!1),e.keyCode===y&&(c.isCmdDown=!1)}),g.on("mousedown"+h,function(e){if(c.isFocused){if(e.target===c.$dropdown[0]||e.target.parentNode===c.$dropdown[0])return!1;c.$control.has(e.target).length||e.target===c.$control[0]||c.blur(e.target)}}),f.on(["scroll"+h,"resize"+h].join(" "),function(){c.isOpen&&c.positionDropdown.apply(c,arguments)}),f.on("mousemove"+h,function(){c.ignoreHover=!1}),this.revertSettings={$children:v.children().detach(),tabindex:v.attr("tabindex")},v.attr("tabindex",-1).hide().after(c.$wrapper),e.isArray(d.items)&&(c.setValue(d.items),delete d.items),b&&v.on("invalid"+h,function(e){e.preventDefault(),c.isInvalid=!0,c.refreshState()}),c.updateOriginalInput(),c.refreshItems(),c.refreshState(),c.updatePlaceholder(),c.isSetup=!0,v.is(":disabled")&&c.disable(),c.on("change",this.onChange),v.data("selectize",c),v.addClass("selectized"),c.trigger("initialize"),d.preload===!0&&c.onSearchChange("")},setupTemplates:function(){var t=this,n=t.settings.labelField,i=t.settings.optgroupLabelField,o={optgroup:function(e){return'<div class="optgroup">'+e.html+"</div>"},optgroup_header:function(e,t){return'<div class="optgroup-header">'+t(e[i])+"</div>"},option:function(e,t){return'<div class="option">'+t(e[n])+"</div>"},item:function(e,t){return'<div class="item">'+t(e[n])+"</div>"},option_create:function(e,t){return'<div class="create">Add <strong>'+t(e.input)+"</strong>&hellip;</div>"}};t.settings.render=e.extend({},o,t.settings.render)},setupCallbacks:function(){var e,t,n={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",optgroup_add:"onOptionGroupAdd",optgroup_remove:"onOptionGroupRemove",optgroup_clear:"onOptionGroupClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType",load:"onLoad",focus:"onFocus",blur:"onBlur"};for(e in n)n.hasOwnProperty(e)&&(t=this.settings[n[e]],t&&this.on(e,t))},onClick:function(e){var t=this;t.isFocused||(t.focus(),e.preventDefault())},onMouseDown:function(t){var n=this,i=t.isDefaultPrevented();e(t.target);if(n.isFocused){if(t.target!==n.$control_input[0])return"single"===n.settings.mode?n.isOpen?n.close():n.open():i||n.setActiveItem(null),!1}else i||window.setTimeout(function(){n.focus()},0)},onChange:function(){this.$input.trigger("change")},onPaste:function(t){var n=this;n.isFull()||n.isInputHidden||n.isLocked?t.preventDefault():n.settings.splitOn&&setTimeout(function(){for(var t=e.trim(n.$control_input.val()||"").split(n.settings.splitOn),i=0,o=t.length;o>i;i++)n.createItem(t[i])},0)},onKeyPress:function(e){if(this.isLocked)return e&&e.preventDefault();var t=String.fromCharCode(e.keyCode||e.which);return this.settings.create&&"multi"===this.settings.mode&&t===this.settings.delimiter?(this.createItem(),e.preventDefault(),!1):void 0},onKeyDown:function(e){var t=(e.target===this.$control_input[0],this);if(t.isLocked)return void(e.keyCode!==O&&e.preventDefault());switch(e.keyCode){case s:if(t.isCmdDown)return void t.selectAll();break;case l:return void(t.isOpen&&(e.preventDefault(),e.stopPropagation(),t.close()));case f:if(!e.ctrlKey||e.altKey)break;case h:if(!t.isOpen&&t.hasOptions)t.open();else if(t.$activeOption){t.ignoreHover=!0;var n=t.getAdjacentOption(t.$activeOption,1);n.length&&t.setActiveOption(n,!0,!0)}return void e.preventDefault();case c:if(!e.ctrlKey||e.altKey)break;case u:if(t.$activeOption){t.ignoreHover=!0;var i=t.getAdjacentOption(t.$activeOption,-1);i.length&&t.setActiveOption(i,!0,!0)}return void e.preventDefault();case a:return void(t.isOpen&&t.$activeOption&&(t.onOptionSelect({currentTarget:t.$activeOption}),e.preventDefault()));case p:return void t.advanceSelection(-1,e);case d:return void t.advanceSelection(1,e);case O:return t.settings.selectOnTab&&t.isOpen&&t.$activeOption&&(t.onOptionSelect({currentTarget:t.$activeOption}),t.isFull()||e.preventDefault()),void(t.settings.create&&t.createItem()&&e.preventDefault());case g:case v:return void t.deleteSelection(e)}return!t.isFull()&&!t.isInputHidden||(r?e.metaKey:e.ctrlKey)?void 0:void e.preventDefault()},onKeyUp:function(e){var t=this;if(t.isLocked)return e&&e.preventDefault();var n=t.$control_input.val()||"";t.lastValue!==n&&(t.lastValue=n,t.onSearchChange(n),t.refreshOptions(),t.trigger("type",n))},onSearchChange:function(e){var t=this,n=t.settings.load;n&&(t.loadedSearches.hasOwnProperty(e)||(t.loadedSearches[e]=!0,t.load(function(i){n.apply(t,[e,i])})))},onFocus:function(e){var t=this,n=t.isFocused;return t.isDisabled?(t.blur(),e&&e.preventDefault(),!1):void(t.ignoreFocus||(t.isFocused=!0,"focus"===t.settings.preload&&t.onSearchChange(""),n||t.trigger("focus"),t.$activeItems.length||(t.showInput(),t.setActiveItem(null),t.refreshOptions(!!t.settings.openOnFocus)),t.refreshState()))},onBlur:function(e,t){var n=this;if(n.isFocused&&(n.isFocused=!1,!n.ignoreFocus)){if(!n.ignoreBlur&&document.activeElement===n.$dropdown_content[0])return n.ignoreBlur=!0,void n.onFocus(e);var i=function(){n.close(),n.setTextboxValue(""),n.setActiveItem(null),n.setActiveOption(null),n.setCaret(n.items.length),n.refreshState(),(t||document.body).focus(),n.ignoreFocus=!1,n.trigger("blur")};n.ignoreFocus=!0,n.settings.create&&n.settings.createOnBlur?n.createItem(null,!1,i):i()}},onOptionHover:function(e){this.ignoreHover||this.setActiveOption(e.currentTarget,!1)},onOptionSelect:function(t){var n,i,o=this;t.preventDefault&&(t.preventDefault(),t.stopPropagation()),i=e(t.currentTarget),i.hasClass("create")?o.createItem(null,function(){o.settings.closeAfterSelect&&o.close()}):(n=i.attr("data-value"),"undefined"!=typeof n&&(o.lastQuery=null,o.setTextboxValue(""),o.addItem(n),o.settings.closeAfterSelect?o.close():!o.settings.hideSelected&&t.type&&/mouse/.test(t.type)&&o.setActiveOption(o.getOption(n))))},onItemSelect:function(e){var t=this;t.isLocked||"multi"===t.settings.mode&&(e.preventDefault(),t.setActiveItem(e.currentTarget,e))},load:function(e){var t=this,n=t.$wrapper.addClass(t.settings.loadingClass);t.loading++,e.apply(t,[function(e){t.loading=Math.max(t.loading-1,0),e&&e.length&&(t.addOption(e),t.refreshOptions(t.isFocused&&!t.isInputHidden)),t.loading||n.removeClass(t.settings.loadingClass),t.trigger("load",e)}])},setTextboxValue:function(e){var t=this.$control_input,n=t.val()!==e;n&&(t.val(e).triggerHandler("update"),this.lastValue=e)},getValue:function(){return this.tagType===$&&this.$input.attr("multiple")?this.items:this.items.join(this.settings.delimiter)},setValue:function(e,t){var n=t?[]:["change"];A(this,n,function(){this.clear(t),this.addItems(e,t)})},setActiveItem:function(t,n){var i,o,r,s,a,l,p,u,c=this;if("single"!==c.settings.mode){if(t=e(t),!t.length)return e(c.$activeItems).removeClass("active"),c.$activeItems=[],void(c.isFocused&&c.showInput());if(i=n&&n.type.toLowerCase(),"mousedown"===i&&c.isShiftDown&&c.$activeItems.length){for(u=c.$control.children(".active:last"),s=Array.prototype.indexOf.apply(c.$control[0].childNodes,[u[0]]),a=Array.prototype.indexOf.apply(c.$control[0].childNodes,[t[0]]),s>a&&(p=s,s=a,a=p),o=s;a>=o;o++)l=c.$control[0].childNodes[o],-1===c.$activeItems.indexOf(l)&&(e(l).addClass("active"),c.$activeItems.push(l));n.preventDefault()}else"mousedown"===i&&c.isCtrlDown||"keydown"===i&&this.isShiftDown?t.hasClass("active")?(r=c.$activeItems.indexOf(t[0]),c.$activeItems.splice(r,1),t.removeClass("active")):c.$activeItems.push(t.addClass("active")[0]):(e(c.$activeItems).removeClass("active"),c.$activeItems=[t.addClass("active")[0]]);c.hideInput(),this.isFocused||c.focus()}},setActiveOption:function(t,n,i){var o,r,s,a,l,p=this;p.$activeOption&&p.$activeOption.removeClass("active"),p.$activeOption=null,t=e(t),t.length&&(p.$activeOption=t.addClass("active"),!n&&x(n)||(o=p.$dropdown_content.height(),r=p.$activeOption.outerHeight(!0),n=p.$dropdown_content.scrollTop()||0,s=p.$activeOption.offset().top-p.$dropdown_content.offset().top+n,a=s,l=s-o+r,s+r>o+n?p.$dropdown_content.stop().animate({scrollTop:l},i?p.settings.scrollDuration:0):n>s&&p.$dropdown_content.stop().animate({scrollTop:a},i?p.settings.scrollDuration:0)))},selectAll:function(){var e=this;"single"!==e.settings.mode&&(e.$activeItems=Array.prototype.slice.apply(e.$control.children(":not(input)").addClass("active")),e.$activeItems.length&&(e.hideInput(),e.close()),e.focus())},hideInput:function(){var e=this;e.setTextboxValue(""),e.$control_input.css({opacity:0,position:"absolute",left:e.rtl?1e4:-1e4}),e.isInputHidden=!0},showInput:function(){this.$control_input.css({opacity:1,position:"relative",left:0}),this.isInputHidden=!1},focus:function(){var e=this;e.isDisabled||(e.ignoreFocus=!0,e.$control_input[0].focus(),window.setTimeout(function(){e.ignoreFocus=!1,e.onFocus()},0))},blur:function(e){this.$control_input[0].blur(),this.onBlur(null,e)},getScoreFunction:function(e){return this.sifter.getScoreFunction(e,this.getSearchOptions())},getSearchOptions:function(){var e=this.settings,t=e.sortField;return"string"==typeof t&&(t=[{field:t}]),{fields:e.searchField,conjunction:e.searchConjunction,sort:t}},search:function(t){var n,i,o,r=this,s=r.settings,a=this.getSearchOptions();if(s.score&&(o=r.settings.score.apply(this,[t]),"function"!=typeof o))throw new Error('Selectize "score" setting must be a function that returns a function');if(t!==r.lastQuery?(r.lastQuery=t,i=r.sifter.search(t,e.extend(a,{score:o})),r.currentResults=i):i=e.extend(!0,{},r.currentResults),s.hideSelected)for(n=i.items.length-1;n>=0;n--)-1!==r.items.indexOf(S(i.items[n].id))&&i.items.splice(n,1);return i},refreshOptions:function(t){var n,o,r,s,a,l,p,u,c,d,h,f,g,v,m,y;"undefined"==typeof t&&(t=!0);var w=this,O=e.trim(w.$control_input.val()),$=w.search(O),C=w.$dropdown_content,b=w.$activeOption&&S(w.$activeOption.attr("data-value"));for(s=$.items.length,"number"==typeof w.settings.maxOptions&&(s=Math.min(s,w.settings.maxOptions)),a={},l=[],n=0;s>n;n++)for(p=w.options[$.items[n].id],u=w.render("option",p),c=p[w.settings.optgroupField]||"",d=e.isArray(c)?c:[c],o=0,r=d&&d.length;r>o;o++)c=d[o],w.optgroups.hasOwnProperty(c)||(c=""),a.hasOwnProperty(c)||(a[c]=[],l.push(c)),a[c].push(u);for(this.settings.lockOptgroupOrder&&l.sort(function(e,t){var n=w.optgroups[e].$order||0,i=w.optgroups[t].$order||0;return n-i}),h=[],n=0,s=l.length;s>n;n++)c=l[n],w.optgroups.hasOwnProperty(c)&&a[c].length?(f=w.render("optgroup_header",w.optgroups[c])||"",f+=a[c].join(""),h.push(w.render("optgroup",e.extend({},w.optgroups[c],{html:f})))):h.push(a[c].join(""));if(C.html(h.join("")),w.settings.highlight&&$.query.length&&$.tokens.length)for(n=0,s=$.tokens.length;s>n;n++)i(C,$.tokens[n].regex);if(!w.settings.hideSelected)for(n=0,s=w.items.length;s>n;n++)w.getOption(w.items[n]).addClass("selected");g=w.canCreate(O),g&&(C.prepend(w.render("option_create",{input:O})),y=e(C[0].childNodes[0])),w.hasOptions=$.items.length>0||g,w.hasOptions?($.items.length>0?(m=b&&w.getOption(b),m&&m.length?v=m:"single"===w.settings.mode&&w.items.length&&(v=w.getOption(w.items[0])),v&&v.length||(v=y&&!w.settings.addPrecedence?w.getAdjacentOption(y,1):C.find("[data-selectable]:first"))):v=y,w.setActiveOption(v),t&&!w.isOpen&&w.open()):(w.setActiveOption(null),t&&w.isOpen&&w.close())},addOption:function(t){var n,i,o,r=this;if(e.isArray(t))for(n=0,i=t.length;i>n;n++)r.addOption(t[n]);else(o=r.registerOption(t))&&(r.userOptions[o]=!0,r.lastQuery=null,r.trigger("option_add",o,t))},registerOption:function(e){var t=S(e[this.settings.valueField]);return!t||this.options.hasOwnProperty(t)?!1:(e.$order=e.$order||++this.order,this.options[t]=e,t)},registerOptionGroup:function(e){var t=S(e[this.settings.optgroupValueField]);return t?(e.$order=e.$order||++this.order,this.optgroups[t]=e,t):!1},addOptionGroup:function(e,t){t[this.settings.optgroupValueField]=e,(e=this.registerOptionGroup(t))&&this.trigger("optgroup_add",e,t)},removeOptionGroup:function(e){this.optgroups.hasOwnProperty(e)&&(delete this.optgroups[e],this.renderCache={},this.trigger("optgroup_remove",e))},clearOptionGroups:function(){this.optgroups={},this.renderCache={},this.trigger("optgroup_clear")},updateOption:function(t,n){var i,o,r,s,a,l,p,u=this;if(t=S(t),r=S(n[u.settings.valueField]),null!==t&&u.options.hasOwnProperty(t)){if("string"!=typeof r)throw new Error("Value must be set in option data");p=u.options[t].$order,r!==t&&(delete u.options[t],s=u.items.indexOf(t),-1!==s&&u.items.splice(s,1,r)),n.$order=n.$order||p,u.options[r]=n,a=u.renderCache.item,l=u.renderCache.option,a&&(delete a[t],delete a[r]),l&&(delete l[t],delete l[r]),-1!==u.items.indexOf(r)&&(i=u.getItem(t),o=e(u.render("item",n)),i.hasClass("active")&&o.addClass("active"),i.replaceWith(o)),u.lastQuery=null,u.isOpen&&u.refreshOptions(!1)}},removeOption:function(e,t){var n=this;e=S(e);var i=n.renderCache.item,o=n.renderCache.option;i&&delete i[e],o&&delete o[e],delete n.userOptions[e],delete n.options[e],n.lastQuery=null,n.trigger("option_remove",e),n.removeItem(e,t)},clearOptions:function(){var e=this;e.loadedSearches={},e.userOptions={},e.renderCache={},e.options=e.sifter.items={},e.lastQuery=null,e.trigger("option_clear"),e.clear()},getOption:function(e){return this.getElementWithValue(e,this.$dropdown_content.find("[data-selectable]"))},getAdjacentOption:function(t,n){var i=this.$dropdown.find("[data-selectable]"),o=i.index(t)+n;return o>=0&&o<i.length?i.eq(o):e()},getElementWithValue:function(t,n){if(t=S(t),"undefined"!=typeof t&&null!==t)for(var i=0,o=n.length;o>i;i++)if(n[i].getAttribute("data-value")===t)return e(n[i]);return e()},getItem:function(e){return this.getElementWithValue(e,this.$control.children())},addItems:function(t,n){for(var i=e.isArray(t)?t:[t],o=0,r=i.length;r>o;o++)this.isPending=r-1>o,this.addItem(i[o],n)},addItem:function(t,n){var i=n?[]:["change"];A(this,i,function(){var i,o,r,s,a,l=this,p=l.settings.mode;return t=S(t),-1!==l.items.indexOf(t)?void("single"===p&&l.close()):void(l.options.hasOwnProperty(t)&&("single"===p&&l.clear(n),"multi"===p&&l.isFull()||(i=e(l.render("item",l.options[t])),a=l.isFull(),l.items.splice(l.caretPos,0,t),l.insertAtCaret(i),(!l.isPending||!a&&l.isFull())&&l.refreshState(),l.isSetup&&(r=l.$dropdown_content.find("[data-selectable]"),l.isPending||(o=l.getOption(t),s=l.getAdjacentOption(o,1).attr("data-value"),l.refreshOptions(l.isFocused&&"single"!==p),s&&l.setActiveOption(l.getOption(s))),!r.length||l.isFull()?l.close():l.positionDropdown(),l.updatePlaceholder(),l.trigger("item_add",t,i),l.updateOriginalInput({silent:n})))))})},removeItem:function(e,t){var n,i,o,r=this;n="object"==typeof e?e:r.getItem(e),e=S(n.attr("data-value")),i=r.items.indexOf(e),-1!==i&&(n.remove(),n.hasClass("active")&&(o=r.$activeItems.indexOf(n[0]),r.$activeItems.splice(o,1)),r.items.splice(i,1),r.lastQuery=null,!r.settings.persist&&r.userOptions.hasOwnProperty(e)&&r.removeOption(e,t),i<r.caretPos&&r.setCaret(r.caretPos-1),r.refreshState(),r.updatePlaceholder(),r.updateOriginalInput({silent:t}),r.positionDropdown(),r.trigger("item_remove",e,n))},createItem:function(t,n){var i=this,o=i.caretPos;t=t||e.trim(i.$control_input.val()||"");var r=arguments[arguments.length-1];if("function"!=typeof r&&(r=function(){}),"boolean"!=typeof n&&(n=!0),!i.canCreate(t))return r(),!1;i.lock();var s="function"==typeof i.settings.create?this.settings.create:function(e){var t={};return t[i.settings.labelField]=e,t[i.settings.valueField]=e,t},a=D(function(e){if(i.unlock(),!e||"object"!=typeof e)return r();var t=S(e[i.settings.valueField]);return"string"!=typeof t?r():(i.setTextboxValue(""),i.addOption(e),i.setCaret(o),i.addItem(t),i.refreshOptions(n&&"single"!==i.settings.mode),void r(e))}),l=s.apply(this,[t,a]);return"undefined"!=typeof l&&a(l),!0},refreshItems:function(){this.lastQuery=null,this.isSetup&&this.addItem(this.items),this.refreshState(),this.updateOriginalInput()},refreshState:function(){var e,t=this;t.isRequired&&(t.items.length&&(t.isInvalid=!1),t.$control_input.prop("required",e)),t.refreshClasses()},refreshClasses:function(){var t=this,n=t.isFull(),i=t.isLocked;t.$wrapper.toggleClass("rtl",t.rtl),t.$control.toggleClass("focus",t.isFocused).toggleClass("disabled",t.isDisabled).toggleClass("required",t.isRequired).toggleClass("invalid",t.isInvalid).toggleClass("locked",i).toggleClass("full",n).toggleClass("not-full",!n).toggleClass("input-active",t.isFocused&&!t.isInputHidden).toggleClass("dropdown-active",t.isOpen).toggleClass("has-options",!e.isEmptyObject(t.options)).toggleClass("has-items",t.items.length>0),t.$control_input.data("grow",!n&&!i)},isFull:function(){return null!==this.settings.maxItems&&this.items.length>=this.settings.maxItems},updateOriginalInput:function(e){var t,n,i,o,r=this;if(e=e||{},r.tagType===$){for(i=[],t=0,n=r.items.length;n>t;t++)o=r.options[r.items[t]][r.settings.labelField]||"",i.push('<option value="'+I(r.items[t])+'" selected="selected">'+I(o)+"</option>");i.length||this.$input.attr("multiple")||i.push('<option value="" selected="selected"></option>'),r.$input.html(i.join(""))}else r.$input.val(r.getValue()),r.$input.attr("value",r.$input.val());r.isSetup&&(e.silent||r.trigger("change",r.$input.val()))},updatePlaceholder:function(){if(this.settings.placeholder){var e=this.$control_input;this.items.length?e.removeAttr("placeholder"):e.attr("placeholder",this.settings.placeholder),e.triggerHandler("update",{force:!0})}},open:function(){var e=this;e.isLocked||e.isOpen||"multi"===e.settings.mode&&e.isFull()||(e.focus(),e.isOpen=!0,e.refreshState(),e.$dropdown.css({visibility:"hidden",display:"block"}),e.positionDropdown(),e.$dropdown.css({visibility:"visible"}),e.trigger("dropdown_open",e.$dropdown))},close:function(){var e=this,t=e.isOpen;"single"===e.settings.mode&&e.items.length&&e.hideInput(),e.isOpen=!1,e.$dropdown.hide(),e.setActiveOption(null),e.refreshState(),t&&e.trigger("dropdown_close",e.$dropdown)},positionDropdown:function(){var e=this.$control,t="body"===this.settings.dropdownParent?e.offset():e.position();t.top+=e.outerHeight(!0),this.$dropdown.css({width:e.outerWidth(),top:t.top,left:t.left})},clear:function(e){var t=this;t.items.length&&(t.$control.children(":not(input)").remove(),t.items=[],t.lastQuery=null,t.setCaret(0),t.setActiveItem(null),t.updatePlaceholder(),t.updateOriginalInput({silent:e}),t.refreshState(),t.showInput(),t.trigger("clear"))},insertAtCaret:function(t){var n=Math.min(this.caretPos,this.items.length);0===n?this.$control.prepend(t):e(this.$control[0].childNodes[n]).before(t),this.setCaret(n+1)},deleteSelection:function(t){var n,i,o,r,s,a,l,p,u,c=this;if(o=t&&t.keyCode===g?-1:1,r=z(c.$control_input[0]),c.$activeOption&&!c.settings.hideSelected&&(l=c.getAdjacentOption(c.$activeOption,-1).attr("data-value")),s=[],c.$activeItems.length){for(u=c.$control.children(".active:"+(o>0?"last":"first")),
+a=c.$control.children(":not(input)").index(u),o>0&&a++,n=0,i=c.$activeItems.length;i>n;n++)s.push(e(c.$activeItems[n]).attr("data-value"));t&&(t.preventDefault(),t.stopPropagation())}else(c.isFocused||"single"===c.settings.mode)&&c.items.length&&(0>o&&0===r.start&&0===r.length?s.push(c.items[c.caretPos-1]):o>0&&r.start===c.$control_input.val().length&&s.push(c.items[c.caretPos]));if(!s.length||"function"==typeof c.settings.onDelete&&c.settings.onDelete.apply(c,[s])===!1)return!1;for("undefined"!=typeof a&&c.setCaret(a);s.length;)c.removeItem(s.pop());return c.showInput(),c.positionDropdown(),c.refreshOptions(!0),l&&(p=c.getOption(l),p.length&&c.setActiveOption(p)),!0},advanceSelection:function(e,t){var n,i,o,r,s,a,l=this;0!==e&&(l.rtl&&(e*=-1),n=e>0?"last":"first",i=z(l.$control_input[0]),l.isFocused&&!l.isInputHidden?(r=l.$control_input.val().length,s=0>e?0===i.start&&0===i.length:i.start===r,s&&!r&&l.advanceCaret(e,t)):(a=l.$control.children(".active:"+n),a.length&&(o=l.$control.children(":not(input)").index(a),l.setActiveItem(null),l.setCaret(e>0?o+1:o))))},advanceCaret:function(e,t){var n,i,o=this;0!==e&&(n=e>0?"next":"prev",o.isShiftDown?(i=o.$control_input[n](),i.length&&(o.hideInput(),o.setActiveItem(i),t&&t.preventDefault())):o.setCaret(o.caretPos+e))},setCaret:function(t){var n=this;if(t="single"===n.settings.mode?n.items.length:Math.max(0,Math.min(n.items.length,t)),!n.isPending){var i,o,r,s;for(r=n.$control.children(":not(input)"),i=0,o=r.length;o>i;i++)s=e(r[i]).detach(),t>i?n.$control_input.before(s):n.$control.append(s)}n.caretPos=t},lock:function(){this.close(),this.isLocked=!0,this.refreshState()},unlock:function(){this.isLocked=!1,this.refreshState()},disable:function(){var e=this;e.$input.prop("disabled",!0),e.$control_input.prop("disabled",!0).prop("tabindex",-1),e.isDisabled=!0,e.lock()},enable:function(){var e=this;e.$input.prop("disabled",!1),e.$control_input.prop("disabled",!1).prop("tabindex",e.tabIndex),e.isDisabled=!1,e.unlock()},destroy:function(){var t=this,n=t.eventNS,i=t.revertSettings;t.trigger("destroy"),t.off(),t.$wrapper.remove(),t.$dropdown.remove(),t.$input.html("").append(i.$children).removeAttr("tabindex").removeClass("selectized").attr({tabindex:i.tabindex}).show(),t.$control_input.removeData("grow"),t.$input.removeData("selectize"),e(window).off(n),e(document).off(n),e(document.body).off(n),delete t.$input[0].selectize},render:function(e,t){var n,i,o="",r=!1,s=this,a=/^[\t \r\n]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i;return"option"!==e&&"item"!==e||(n=S(t[s.settings.valueField]),r=!!n),r&&(x(s.renderCache[e])||(s.renderCache[e]={}),s.renderCache[e].hasOwnProperty(n))?s.renderCache[e][n]:(o=s.settings.render[e].apply(this,[t,I]),"option"!==e&&"option_create"!==e||(o=o.replace(a,"<$1 data-selectable")),"optgroup"===e&&(i=t[s.settings.optgroupValueField]||"",o=o.replace(a,'<$1 data-group="'+_(I(i))+'"')),"option"!==e&&"item"!==e||(o=o.replace(a,'<$1 data-value="'+_(I(n||""))+'"')),r&&(s.renderCache[e][n]=o),o)},clearCache:function(e){var t=this;"undefined"==typeof e?t.renderCache={}:delete t.renderCache[e]},canCreate:function(e){var t=this;if(!t.settings.create)return!1;var n=t.settings.createFilter;return e.length&&("function"!=typeof n||n.apply(t,[e]))&&("string"!=typeof n||new RegExp(n).test(e))&&(!(n instanceof RegExp)||n.test(e))}}),E.count=0,E.defaults={options:[],optgroups:[],plugins:[],delimiter:",",splitOn:null,persist:!0,diacritics:!0,create:!1,createOnBlur:!1,createFilter:null,highlight:!0,openOnFocus:!0,maxOptions:1e3,maxItems:null,hideSelected:null,addPrecedence:!1,selectOnTab:!1,preload:!1,allowEmptyOption:!1,closeAfterSelect:!1,scrollDuration:60,loadThrottle:300,loadingClass:"loading",dataAttr:"data-data",optgroupField:"optgroup",valueField:"value",labelField:"text",optgroupLabelField:"label",optgroupValueField:"value",lockOptgroupOrder:!1,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"selectize-control",inputClass:"selectize-input",dropdownClass:"selectize-dropdown",dropdownContentClass:"selectize-dropdown-content",dropdownParent:null,copyClassesToDropdown:!0,render:{}},e.fn.selectize=function(t){var n=e.fn.selectize.defaults,i=e.extend({},n,t),o=i.dataAttr,r=i.labelField,s=i.valueField,a=i.optgroupField,l=i.optgroupLabelField,p=i.optgroupValueField,u=function(t,n){var a,l,p,u,c=t.attr(o);if(c)for(n.options=JSON.parse(c),a=0,l=n.options.length;l>a;a++)n.items.push(n.options[a][s]);else{var d=e.trim(t.val()||"");if(!i.allowEmptyOption&&!d.length)return;for(p=d.split(i.delimiter),a=0,l=p.length;l>a;a++)u={},u[r]=p[a],u[s]=p[a],n.options.push(u);n.items=p}},c=function(t,n){var u,c,d,h,f=n.options,g={},v=function(e){var t=o&&e.attr(o);return"string"==typeof t&&t.length?JSON.parse(t):null},m=function(t,o){t=e(t);var l=S(t.attr("value"));if(l||i.allowEmptyOption)if(g.hasOwnProperty(l)){if(o){var p=g[l][a];p?e.isArray(p)?p.push(o):g[l][a]=[p,o]:g[l][a]=o}}else{var u=v(t)||{};u[r]=u[r]||t.text(),u[s]=u[s]||l,u[a]=u[a]||o,g[l]=u,f.push(u),t.is(":selected")&&n.items.push(l)}},y=function(t){var i,o,r,s,a;for(t=e(t),r=t.attr("label"),r&&(s=v(t)||{},s[l]=r,s[p]=r,n.optgroups.push(s)),a=e("option",t),i=0,o=a.length;o>i;i++)m(a[i],r)};for(n.maxItems=t.attr("multiple")?null:1,h=t.children(),u=0,c=h.length;c>u;u++)d=h[u].tagName.toLowerCase(),"optgroup"===d?y(h[u]):"option"===d&&m(h[u])};return this.each(function(){if(!this.selectize){var o,r=e(this),s=this.tagName.toLowerCase(),a=r.attr("placeholder")||r.attr("data-placeholder");a||i.allowEmptyOption||(a=r.children('option[value=""]').text());var l={placeholder:a,options:[],optgroups:[],items:[]};"select"===s?c(r,l):u(r,l),o=new E(r,e.extend(!0,{},n,l,t))}})},e.fn.selectize.defaults=E.defaults,e.fn.selectize.support={validity:b},E.define("drag_drop",function(){if(!e.fn.sortable)throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".');if("multi"===this.settings.mode){var t=this;t.lock=function(){var e=t.lock;return function(){var n=t.$control.data("sortable");return n&&n.disable(),e.apply(t,arguments)}}(),t.unlock=function(){var e=t.unlock;return function(){var n=t.$control.data("sortable");return n&&n.enable(),e.apply(t,arguments)}}(),t.setup=function(){var n=t.setup;return function(){n.apply(this,arguments);var i=t.$control.sortable({items:"[data-value]",forcePlaceholderSize:!0,disabled:t.isLocked,start:function(e,t){t.placeholder.css("width",t.helper.css("width")),i.css({overflow:"visible"})},stop:function(){i.css({overflow:"hidden"});var n=t.$activeItems?t.$activeItems.slice():null,o=[];i.children("[data-value]").each(function(){o.push(e(this).attr("data-value"))}),t.setValue(o),t.setActiveItem(n)}})}}()}}),E.define("dropdown_header",function(t){var n=this;t=e.extend({title:"Untitled",headerClass:"selectize-dropdown-header",titleRowClass:"selectize-dropdown-header-title",labelClass:"selectize-dropdown-header-label",closeClass:"selectize-dropdown-header-close",html:function(e){return'<div class="'+e.headerClass+'"><div class="'+e.titleRowClass+'"><span class="'+e.labelClass+'">'+e.title+'</span><a href="javascript:void(0)" class="'+e.closeClass+'">&times;</a></div></div>'}},t),n.setup=function(){var i=n.setup;return function(){i.apply(n,arguments),n.$dropdown_header=e(t.html(t)),n.$dropdown.prepend(n.$dropdown_header)}}()}),E.define("optgroup_columns",function(t){var n=this;t=e.extend({equalizeWidth:!0,equalizeHeight:!0},t),this.getAdjacentOption=function(t,n){var i=t.closest("[data-group]").find("[data-selectable]"),o=i.index(t)+n;return o>=0&&o<i.length?i.eq(o):e()},this.onKeyDown=function(){var e=n.onKeyDown;return function(t){var i,o,r,s;return!this.isOpen||t.keyCode!==p&&t.keyCode!==d?e.apply(this,arguments):(n.ignoreHover=!0,s=this.$activeOption.closest("[data-group]"),i=s.find("[data-selectable]").index(this.$activeOption),s=t.keyCode===p?s.prev("[data-group]"):s.next("[data-group]"),r=s.find("[data-selectable]"),o=r.eq(Math.min(r.length-1,i)),void(o.length&&this.setActiveOption(o)))}}();var i=function(){var e,t=i.width,n=document;return"undefined"==typeof t&&(e=n.createElement("div"),e.innerHTML='<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>',e=e.firstChild,n.body.appendChild(e),t=i.width=e.offsetWidth-e.clientWidth,n.body.removeChild(e)),t},o=function(){var o,r,s,a,l,p,u;if(u=e("[data-group]",n.$dropdown_content),r=u.length,r&&n.$dropdown_content.width()){if(t.equalizeHeight){for(s=0,o=0;r>o;o++)s=Math.max(s,u.eq(o).height());u.css({height:s})}t.equalizeWidth&&(p=n.$dropdown_content.innerWidth()-i(),a=Math.round(p/r),u.css({width:a}),r>1&&(l=p-a*(r-1),u.eq(r-1).css({width:l})))}};(t.equalizeHeight||t.equalizeWidth)&&(F.after(this,"positionDropdown",o),F.after(this,"refreshOptions",o))}),E.define("remove_button",function(t){if("single"!==this.settings.mode){t=e.extend({label:"&times;",title:"Remove",className:"remove",append:!0},t);var n=this,i='<a href="javascript:void(0)" class="'+t.className+'" tabindex="-1" title="'+I(t.title)+'">'+t.label+"</a>",o=function(e,t){var n=e.search(/(<\/[^>]+>\s*)$/);return e.substring(0,n)+t+e.substring(n)};this.setup=function(){var r=n.setup;return function(){if(t.append){var s=n.settings.render.item;n.settings.render.item=function(){return o(s.apply(this,arguments),i)}}r.apply(this,arguments),this.$control.on("click","."+t.className,function(t){if(t.preventDefault(),!n.isLocked){var i=e(t.currentTarget).parent();n.setActiveItem(i),n.deleteSelection()&&n.setCaret(n.items.length)}})}}()}}),E.define("restore_on_backspace",function(e){var t=this;e.text=e.text||function(e){return e[this.settings.labelField]},this.onKeyDown=function(){var n=t.onKeyDown;return function(t){var i,o;return t.keyCode===g&&""===this.$control_input.val()&&!this.$activeItems.length&&(i=this.caretPos-1,i>=0&&i<this.items.length)?(o=this.options[this.items[i]],this.deleteSelection(t)&&(this.setTextboxValue(e.text.apply(this,[o])),this.refreshOptions(!0)),void t.preventDefault()):n.apply(this,arguments)}}()}),E}); \ No newline at end of file
diff --git a/modules/http/static/topojson.js b/modules/http/static/topojson.js
new file mode 100644
index 0000000..02d566b
--- /dev/null
+++ b/modules/http/static/topojson.js
@@ -0,0 +1 @@
+!function(){function t(n,t){function r(t){var r,e=n.arcs[0>t?~t:t],o=e[0];return n.transform?(r=[0,0],e.forEach(function(n){r[0]+=n[0],r[1]+=n[1]})):r=e[e.length-1],0>t?[r,o]:[o,r]}function e(n,t){for(var r in n){var e=n[r];delete t[e.start],delete e.start,delete e.end,e.forEach(function(n){o[0>n?~n:n]=1}),f.push(e)}}var o={},i={},u={},f=[],c=-1;return t.forEach(function(r,e){var o,i=n.arcs[0>r?~r:r];i.length<3&&!i[1][0]&&!i[1][1]&&(o=t[++c],t[c]=r,t[e]=o)}),t.forEach(function(n){var t,e,o=r(n),f=o[0],c=o[1];if(t=u[f])if(delete u[t.end],t.push(n),t.end=c,e=i[c]){delete i[e.start];var a=e===t?t:t.concat(e);i[a.start=t.start]=u[a.end=e.end]=a}else i[t.start]=u[t.end]=t;else if(t=i[c])if(delete i[t.start],t.unshift(n),t.start=f,e=u[f]){delete u[e.end];var s=e===t?t:e.concat(t);i[s.start=e.start]=u[s.end=t.end]=s}else i[t.start]=u[t.end]=t;else t=[n],i[t.start=f]=u[t.end=c]=t}),e(u,i),e(i,u),t.forEach(function(n){o[0>n?~n:n]||f.push([n])}),f}function r(n,r,e){function o(n){var t=0>n?~n:n;(s[t]||(s[t]=[])).push({i:n,g:a})}function i(n){n.forEach(o)}function u(n){n.forEach(i)}function f(n){"GeometryCollection"===n.type?n.geometries.forEach(f):n.type in l&&(a=n,l[n.type](n.arcs))}var c=[];if(arguments.length>1){var a,s=[],l={LineString:i,MultiLineString:u,Polygon:u,MultiPolygon:function(n){n.forEach(u)}};f(r),s.forEach(arguments.length<3?function(n){c.push(n[0].i)}:function(n){e(n[0].g,n[n.length-1].g)&&c.push(n[0].i)})}else for(var h=0,p=n.arcs.length;p>h;++h)c.push(h);return{type:"MultiLineString",arcs:t(n,c)}}function e(r,e){function o(n){n.forEach(function(t){t.forEach(function(t){(f[t=0>t?~t:t]||(f[t]=[])).push(n)})}),c.push(n)}function i(n){return l(u(r,{type:"Polygon",arcs:[n]}).coordinates[0])>0}var f={},c=[],a=[];return e.forEach(function(n){"Polygon"===n.type?o(n.arcs):"MultiPolygon"===n.type&&n.arcs.forEach(o)}),c.forEach(function(n){if(!n._){var t=[],r=[n];for(n._=1,a.push(t);n=r.pop();)t.push(n),n.forEach(function(n){n.forEach(function(n){f[0>n?~n:n].forEach(function(n){n._||(n._=1,r.push(n))})})})}}),c.forEach(function(n){delete n._}),{type:"MultiPolygon",arcs:a.map(function(e){var o=[];if(e.forEach(function(n){n.forEach(function(n){n.forEach(function(n){f[0>n?~n:n].length<2&&o.push(n)})})}),o=t(r,o),(n=o.length)>1)for(var u,c=i(e[0][0]),a=0;n>a;++a)if(c===i(o[a])){u=o[0],o[0]=o[a],o[a]=u;break}return o})}}function o(n,t){return"GeometryCollection"===t.type?{type:"FeatureCollection",features:t.geometries.map(function(t){return i(n,t)})}:i(n,t)}function i(n,t){var r={type:"Feature",id:t.id,properties:t.properties||{},geometry:u(n,t)};return null==t.id&&delete r.id,r}function u(n,t){function r(n,t){t.length&&t.pop();for(var r,e=s[0>n?~n:n],o=0,i=e.length;i>o;++o)t.push(r=e[o].slice()),a(r,o);0>n&&f(t,i)}function e(n){return n=n.slice(),a(n,0),n}function o(n){for(var t=[],e=0,o=n.length;o>e;++e)r(n[e],t);return t.length<2&&t.push(t[0].slice()),t}function i(n){for(var t=o(n);t.length<4;)t.push(t[0].slice());return t}function u(n){return n.map(i)}function c(n){var t=n.type;return"GeometryCollection"===t?{type:t,geometries:n.geometries.map(c)}:t in l?{type:t,coordinates:l[t](n)}:null}var a=g(n.transform),s=n.arcs,l={Point:function(n){return e(n.coordinates)},MultiPoint:function(n){return n.coordinates.map(e)},LineString:function(n){return o(n.arcs)},MultiLineString:function(n){return n.arcs.map(o)},Polygon:function(n){return u(n.arcs)},MultiPolygon:function(n){return n.arcs.map(u)}};return c(t)}function f(n,t){for(var r,e=n.length,o=e-t;o<--e;)r=n[o],n[o++]=n[e],n[e]=r}function c(n,t){for(var r=0,e=n.length;e>r;){var o=r+e>>>1;n[o]<t?r=o+1:e=o}return r}function a(n){function t(n,t){n.forEach(function(n){0>n&&(n=~n);var r=o[n];r?r.push(t):o[n]=[t]})}function r(n,r){n.forEach(function(n){t(n,r)})}function e(n,t){"GeometryCollection"===n.type?n.geometries.forEach(function(n){e(n,t)}):n.type in u&&u[n.type](n.arcs,t)}var o={},i=n.map(function(){return[]}),u={LineString:t,MultiLineString:r,Polygon:r,MultiPolygon:function(n,t){n.forEach(function(n){r(n,t)})}};n.forEach(e);for(var f in o)for(var a=o[f],s=a.length,l=0;s>l;++l)for(var h=l+1;s>h;++h){var p,v=a[l],g=a[h];(p=i[v])[f=c(p,g)]!==g&&p.splice(f,0,g),(p=i[g])[f=c(p,v)]!==v&&p.splice(f,0,v)}return i}function s(n,t){function r(n){u.remove(n),n[1][2]=t(n),u.push(n)}var e,o=g(n.transform),i=m(n.transform),u=v(),f=0;for(t||(t=h),n.arcs.forEach(function(n){var r=[];n.forEach(o);for(var i=1,f=n.length-1;f>i;++i)e=n.slice(i-1,i+2),e[1][2]=t(e),r.push(e),u.push(e);n[0][2]=n[f][2]=1/0;for(var i=0,f=r.length;f>i;++i)e=r[i],e.previous=r[i-1],e.next=r[i+1]});e=u.pop();){var c=e.previous,a=e.next;e[1][2]<f?e[1][2]=f:f=e[1][2],c&&(c.next=a,c[2]=e[2],r(c)),a&&(a.previous=c,a[0]=e[0],r(a))}return n.arcs.forEach(function(n){n.forEach(i)}),n}function l(n){for(var t,r=-1,e=n.length,o=n[e-1],i=0;++r<e;)t=o,o=n[r],i+=t[0]*o[1]-t[1]*o[0];return.5*i}function h(n){var t=n[0],r=n[1],e=n[2];return Math.abs((t[0]-e[0])*(r[1]-t[1])-(t[0]-r[0])*(e[1]-t[1]))}function p(n,t){return n[1][2]-t[1][2]}function v(){function n(n,t){for(;t>0;){var r=(t+1>>1)-1,o=e[r];if(p(n,o)>=0)break;e[o._=t]=o,e[n._=t=r]=n}}function t(n,t){for(;;){var r=t+1<<1,i=r-1,u=t,f=e[u];if(o>i&&p(e[i],f)<0&&(f=e[u=i]),o>r&&p(e[r],f)<0&&(f=e[u=r]),u===t)break;e[f._=t]=f,e[n._=t=u]=n}}var r={},e=[],o=0;return r.push=function(t){return n(e[t._=o]=t,o++),o},r.pop=function(){if(!(0>=o)){var n,r=e[0];return--o>0&&(n=e[o],t(e[n._=0]=n,0)),r}},r.remove=function(r){var i,u=r._;if(e[u]===r)return u!==--o&&(i=e[o],(p(i,r)<0?n:t)(e[i._=u]=i,u)),u},r}function g(n){if(!n)return y;var t,r,e=n.scale[0],o=n.scale[1],i=n.translate[0],u=n.translate[1];return function(n,f){f||(t=r=0),n[0]=(t+=n[0])*e+i,n[1]=(r+=n[1])*o+u}}function m(n){if(!n)return y;var t,r,e=n.scale[0],o=n.scale[1],i=n.translate[0],u=n.translate[1];return function(n,f){f||(t=r=0);var c=(n[0]-i)/e|0,a=(n[1]-u)/o|0;n[0]=c-t,n[1]=a-r,t=c,r=a}}function y(){}var d={version:"1.6.9",mesh:function(n){return u(n,r.apply(this,arguments))},meshArcs:r,merge:function(n){return u(n,e.apply(this,arguments))},mergeArcs:e,feature:o,neighbors:a,presimplify:s};"function"==typeof define&&define.amd?define(d):"object"==typeof module&&module.exports?module.exports=d:this.topojson=d}(); \ No newline at end of file
diff --git a/modules/http/test_tls/broken.crt b/modules/http/test_tls/broken.crt
new file mode 100644
index 0000000..d93d1f8
--- /dev/null
+++ b/modules/http/test_tls/broken.crt
@@ -0,0 +1,3 @@
+Æ¿¯ˆž³psâ$Ðëí¯Ö¡«Æȼ[ŒîØ1´Ç =fl:°Êl=z†=M}iÉ»¤Ñ­†÷*7ƒ)Ä Ñ5
+ÈóîÒj¨šIÜWÈÀ­®·´ MwÚf[´HïŽíÙÑÅ-Á¯ËìýEȼë€fû¦Ö   2fTKÊqýFѬUÖ ƒ“(jÀ¤œaà,Õœ¥*²X:lFÌÍ¿£Mî©>ó3Œš
+¬‘áD<^O™qk¥ˆQŽÉý‘κM…gÄ]pUNÉö¥MÝ>ŒŸÂÿº¹á(EI”®µ'ÌGÅ€÷mÕÅ÷Ã:ž3 º_”!‚ÁÎ’? 3Œú$H[„E†¡M¡4èòR¨†ÒA+0w¥ö0ÏÓÁ“%é¸eo¤ašåëØó(öw;¥oÇ¥î¯$—!ZèÀˆr%Äùàü&ßýh;1¾@ˆñý-9((Ób7±á\„UâoÃJÊ`»:Þª€†¼™~ŸdÃŽa•œƒìÜЃÇŒEÂœ—PB*l«Î}!q7ü;+QRL‘¢¶vÉûËQ‡[KãYûXðRà 2(¬íùªå7ÀÜ+$ëÃE,óõ­Ûý³IRÄÙï· §^4µD ¼_r…,išÁèÁ\ðhξ \ No newline at end of file
diff --git a/modules/http/test_tls/broken.key b/modules/http/test_tls/broken.key
new file mode 100644
index 0000000..ebcbfcf
--- /dev/null
+++ b/modules/http/test_tls/broken.key
Binary files differ
diff --git a/modules/http/test_tls/test.crt b/modules/http/test_tls/test.crt
new file mode 100644
index 0000000..01c36f8
--- /dev/null
+++ b/modules/http/test_tls/test.crt
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBXDCCAQKgAwIBAgIRAONzB6ou1Lh79QSlofsBtBMwCgYIKoZIzj0EAwIwGTEX
+MBUGA1UEAwwOcm9oYW4tcmVzb2x2ZXIwHhcNMTgwNzIzMTA1MjE4WhcNMTgxMDIx
+MTA1MjE4WjAZMRcwFQYDVQQDDA5yb2hhbi1yZXNvbHZlcjBZMBMGByqGSM49AgEG
+CCqGSM49AwEHA0IABJPYWceFJkbjORCrO8aIhMk3Bw2PpTzuPC27O/rjojBjmadO
+vZyFxIKgfYiHp4uMr1z81K+cqq1s/q0+kW+tNaejKzApMBkGA1UdEQQSMBCCDnJv
+aGFuLXJlc29sdmVyMAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDSAAwRQIhAL+Z
+IElUAmI0nQdaSRLZw5LCZeC/OIFx9JfaoDzMNkW5AiABXCWYzR+/uyYV7KDucwtW
+LGh/LrjC/FZGK3Drefbu0A==
+-----END CERTIFICATE-----
diff --git a/modules/http/test_tls/test.key b/modules/http/test_tls/test.key
new file mode 100644
index 0000000..1256b5a
--- /dev/null
+++ b/modules/http/test_tls/test.key
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk9hZx4UmRuM5EKs7xoiEyTcHDY+l
+PO48Lbs7+uOiMGOZp069nIXEgqB9iIeni4yvXPzUr5yqrWz+rT6Rb601pw==
+-----END PUBLIC KEY-----
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgtgNJHFS7+jlibs3b
+4NMYVLgZvVgOh5ouMn/ujQrAbouhRANCAAST2FnHhSZG4zkQqzvGiITJNwcNj6U8
+7jwtuzv646IwY5mnTr2chcSCoH2Ih6eLjK9c/NSvnKqtbP6tPpFvrTWn
+-----END PRIVATE KEY-----
diff --git a/modules/http/test_tls/tls.test.lua b/modules/http/test_tls/tls.test.lua
new file mode 100644
index 0000000..9eac382
--- /dev/null
+++ b/modules/http/test_tls/tls.test.lua
@@ -0,0 +1,164 @@
+-- check prerequisites
+local has_http = pcall(require, 'http') and pcall(require, 'http.request')
+if not has_http then
+ pass('skipping http module test because its not installed')
+ done()
+else
+ local request = require('http.request')
+ local openssl_ctx = require('openssl.ssl.context')
+
+ local function setup_module(desc, config)
+ if http then
+ modules.unload('http')
+ end
+ modules.load('http')
+ same(http.config(config), nil, desc .. ' can be configured')
+
+ local server = http.servers[1]
+ ok(server ~= nil, desc .. ' creates server instance')
+ local _, host, port = server:localname()
+ ok(host and port, desc .. ' binds to an interface')
+ return host, port
+ end
+
+ local function http_get(uri)
+ -- disable certificate verification in this test
+ local req = request.new_from_uri(uri)
+ local idxstart = string.find(uri, 'https://')
+ if idxstart == 1 then
+ req.ctx = openssl_ctx.new()
+ assert(req.ctx, 'OpenSSL cert verification must be disabled')
+ req.ctx:setVerify(openssl_ctx.VERIFY_NONE)
+ end
+
+ local headers = assert(req:go())
+ return tonumber(headers:get(':status'))
+ end
+
+ -- test whether http interface responds and binds
+ local function check_protocol(uri, description, ok_expected)
+ if ok_expected then
+ local code = http_get(uri)
+ same(code, 200, description)
+ else
+ boom(http_get, {uri}, description)
+ end
+ end
+
+ local function test_defaults()
+ local host, port = setup_module('HTTP module default config', {})
+
+ local uri = string.format('http://%s:%d', host, port)
+ check_protocol(uri, 'HTTP is enabled by default', true)
+ uri = string.format('https://%s:%d', host, port)
+ check_protocol(uri, 'HTTPS is enabled by default', true)
+
+ modules.unload('http')
+ uri = string.format('http://%s:%d', host, port)
+ check_protocol(uri, 'HTTP stops working after module unload', false)
+ uri = string.format('https://%s:%d', host, port)
+ check_protocol(uri, 'HTTPS stops working after module unload', false)
+
+ end
+
+ local function test_http_only()
+ local desc = 'HTTP-only config'
+ local host, port = setup_module(desc,
+ {
+ port = 0, -- Select random port
+ tls = false,
+ })
+
+ local uri = string.format('http://%s:%d', host, port)
+ check_protocol(uri, 'HTTP works in ' .. desc, true)
+ uri = string.format('https://%s:%d', host, port)
+ check_protocol(uri, 'HTTPS does not work in ' .. desc, false)
+ end
+
+ local function test_https_only()
+ local desc = 'HTTPS-only config'
+ local host, port = setup_module(desc,
+ {
+ port = 0, -- Select random port
+ tls = true,
+ })
+
+ local uri = string.format('http://%s:%d', host, port)
+ check_protocol(uri, 'HTTP does not work in ' .. desc, false)
+ uri = string.format('https://%s:%d', host, port)
+ check_protocol(uri, 'HTTPS works in ' .. desc, true)
+ end
+
+ local function test_custom_cert()
+ desc = 'config with custom certificate'
+ local host, port = setup_module(desc, {{
+ host = host,
+ port = port,
+ cert = 'test.crt',
+ key = 'test.key'
+ }})
+
+ uri = string.format('https://%s:%d', host, port)
+ check_protocol(uri, 'HTTPS works for ' .. desc, true)
+ end
+
+ local function test_nonexistent_cert()
+ desc = 'config with non-existing certificate file'
+ boom(http.config, {{
+ port = 0,
+ cert = '/tmp/surely_nonexistent_cert_1532432095',
+ key = 'test.key'
+ }}, desc)
+ end
+
+ local function test_nonexistent_key()
+ desc = 'config with non-existing key file'
+ boom(http.config, {{
+ port = 0,
+ cert = 'test.crt',
+ key = '/tmp/surely_nonexistent_cert_1532432095'
+ }}, desc)
+ end
+
+ local function test_missing_key_param()
+ desc = 'config with missing key= param'
+ boom(http.config, {{
+ port = 0,
+ cert = 'test.crt'
+ }}, desc)
+ end
+
+ local function test_broken_cert()
+ desc = 'config with broken file in cert= param'
+ boom(http.config, {{
+ port = 0,
+ cert = 'broken.crt',
+ key = 'test.key'
+ }}, desc)
+ end
+
+ local function test_broken_key()
+ desc = 'config with broken file in key= param'
+ boom(http.config, {{
+ port = 0,
+ cert = 'test.crt',
+ key = 'broken.key'
+ }}, desc)
+ end
+
+
+ -- plan tests
+ local tests = {
+ test_defaults,
+ test_http_only,
+ test_https_only,
+ test_custom_cert,
+ test_nonexistent_cert,
+ test_nonexistent_key,
+ test_missing_key_param,
+ test_broken_cert,
+ test_broken_key
+ }
+
+ return tests
+end
diff --git a/modules/modules.mk b/modules/modules.mk
new file mode 100644
index 0000000..71c79b1
--- /dev/null
+++ b/modules/modules.mk
@@ -0,0 +1,106 @@
+# List of built-in modules
+modules_TARGETS := hints \
+ stats
+
+# DNS cookies
+ifeq ($(ENABLE_COOKIES),yes)
+modules_TARGETS += cookies
+endif
+
+ifeq ($(ENABLE_DNSTAP),yes)
+modules_TARGETS += dnstap
+endif
+
+# List of Lua modules
+ifeq ($(HAS_lua),yes)
+modules_TARGETS += bogus_log \
+ nsid \
+ etcd \
+ ta_sentinel \
+ experimental_dot_auth \
+ graphite \
+ policy \
+ view \
+ predict \
+ dns64 \
+ rebinding \
+ renumber \
+ http \
+ daf \
+ workarounds \
+ ta_signal_query \
+ priming \
+ serve_stale \
+ detect_time_skew \
+ detect_time_jump \
+ prefill \
+ edns_keepalive
+endif
+
+# Make C module
+define make_c_module
+$(1)-install: $(DESTDIR)$(MODULEDIR)
+$(eval $(call make_module,$(1),modules/$(1)))
+endef
+
+# Make Lua module
+define make_lua_module
+$(eval $(call lua_target,$(1),modules/$(1)))
+endef
+
+# Lua target definition
+define lua_target
+$(1) := $(1) $$(addprefix $(2)/,$$($(1)_SOURCES))
+$(1) : $$($(1)_DEPEND)
+$(1)-clean:
+ifeq ($$(strip $$($(1)_INSTALL)),)
+$(1)-dist:
+ $(INSTALL) -d $(DESTDIR)$(MODULEDIR)
+else
+$(1)-dist: $$($(1)_INSTALL)
+ $(INSTALL) -d $(DESTDIR)$(MODULEDIR)/$(1)
+ $(INSTALL) -m 0644 $$^ $(DESTDIR)$(MODULEDIR)/$(1)
+endif
+$(1)-install: $$(addprefix $(2)/,$$($(1)_SOURCES)) $(DESTDIR)$(MODULEDIR) $(1)-dist
+ $(INSTALL) -m 0644 $$(addprefix $(2)/,$$($(1)_SOURCES)) $(DESTDIR)$(MODULEDIR)
+.PHONY: $(1) $(1)-install $(1)-clean $(1)-dist
+endef
+
+# Make Go module
+define make_go_module
+$(eval $(call go_target,$(1),modules/$(1)))
+endef
+
+# Filter CGO flags
+CGO_CFLAGS := $(filter-out -flto,$(BUILD_CFLAGS))
+
+# Go target definition
+define go_target
+$(1) := $(2)/$(1)$(LIBEXT)
+$(2)/$(1)$(LIBEXT): $$($(1)_SOURCES) $$($(1)_DEPEND)
+ @echo " GO $(2)"; CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$$($(1)_LIBS) $(CFLAGS)" $(GO) build -buildmode=c-shared -o $$@ $$($(1)_SOURCES)
+$(1)-clean:
+ $(RM) -r $(2)/$(1).h $(2)/$(1)$(LIBEXT)
+ifeq ($$(strip $$($(1)_INSTALL)),)
+$(1)-dist:
+ $(INSTALL) -d $(DESTDIR)$(MODULEDIR)
+else
+$(1)-dist: $$($(1)_INSTALL)
+ $(INSTALL) -d $(DESTDIR)$(MODULEDIR)/$(1)
+ $(INSTALL) -m 0644 $$^ $(DESTDIR)$(MODULEDIR)/$(1)
+endif
+$(1)-install: $(2)/$(1)$(LIBEXT) $(1)-dist $(DESTDIR)$(MODULEDIR)
+ $(INSTALL) $(2)/$(1)$(LIBEXT) $(DESTDIR)$(MODULEDIR)
+.PHONY: $(1)-clean $(1)-install $(1)-dist
+endef
+
+# Include modules
+$(foreach module,$(modules_TARGETS),$(eval include modules/$(module)/$(module).mk))
+$(eval modules = $(foreach module,$(modules_TARGETS),$$($(module))))
+
+# Targets
+modules: $(modules)
+modules-clean: $(addsuffix -clean,$(modules_TARGETS))
+modules-install: $(addsuffix -install,$(modules_TARGETS))
+
+.PHONY: modules modules-clean modules-install
diff --git a/modules/nsid/README.rst b/modules/nsid/README.rst
new file mode 100644
index 0000000..ed052c9
--- /dev/null
+++ b/modules/nsid/README.rst
@@ -0,0 +1,35 @@
+.. _mod-nsid:
+
+Name Server Identifier (NSID)
+-----------------------------
+
+This module provides server-side support for :rfc:`5001`
+and is not enabled by default.
+
+DNS clients can request resolver to send back its NSID along with the reply
+to a DNS request. This is useful for identification of resolver instances
+in larger services (using anycast or load balancers).
+
+
+This is useful tool for debugging larger services,
+as it reveals which particular resolver instance sent the reply.
+
+NSID value can be configured in the resolver's configuration file:
+
+.. code-block:: lua
+
+ modules.load('nsid')
+ nsid.name('instance 1')
+
+You can also obtain configured NSID value:
+
+.. code-block:: lua
+
+ nsid.name()
+ instance 1
+
+The module can be disabled at run-time:
+
+.. code-block:: lua
+
+ modules.unload('nsid')
diff --git a/modules/nsid/nsid.c b/modules/nsid/nsid.c
new file mode 100644
index 0000000..fef6ecd
--- /dev/null
+++ b/modules/nsid/nsid.c
@@ -0,0 +1,122 @@
+/* Copyright (C) Knot Resolver contributors. Licensed under GNU GPLv3 or
+ * (at your option) any later version. See COPYING for text of the license.
+ *
+ * This module provides NSID support according to RFC 5001. */
+
+#include <libknot/packet/pkt.h>
+#include <contrib/cleanup.h>
+#include <ccan/json/json.h>
+#include <lauxlib.h>
+
+#include "daemon/engine.h"
+#include "lib/layer.h"
+
+struct nsid_config {
+ uint8_t *local_nsid;
+ size_t local_nsid_len;
+};
+
+static int nsid_finalize(kr_layer_t *ctx) {
+ const struct kr_module *module = ctx->api->data;
+ const struct nsid_config *config = module->data;
+ struct kr_request *req = ctx->req;
+
+ /* no local NSID configured, do nothing */
+ if (config->local_nsid == NULL)
+ return ctx->state;
+
+ const knot_rrset_t *src_opt = req->qsource.packet->opt_rr;
+ /* no EDNS in request, do nothing */
+ if (src_opt == NULL)
+ return ctx->state;
+
+ const uint8_t *req_nsid = knot_edns_get_option(src_opt, KNOT_EDNS_OPTION_NSID);
+ /* NSID option must be explicitly requested */
+ if (req_nsid == NULL)
+ return ctx->state;
+
+ /* Check violation of https://tools.ietf.org/html/rfc5001#section-2.1:
+ * The resolver MUST NOT include any NSID payload data in the query */
+ if (knot_edns_opt_get_length(req_nsid) != 0)
+ kr_log_verbose("[%05u. ][nsid] FORMERR: NSID option in query "
+ "must not contain payload, continuing\n", req->uid);
+ /* FIXME: actually change RCODE in answer to FORMERR? */
+
+ /* Sanity check, answer should have EDNS as well but who knows ... */
+ if (req->answer->opt_rr == NULL)
+ return ctx->state;
+
+ if (knot_edns_add_option(req->answer->opt_rr, KNOT_EDNS_OPTION_NSID,
+ config->local_nsid_len, config->local_nsid,
+ &req->pool) != KNOT_EOK) {
+ /* something went wrong and there is no way to salvage content of OPT RRset */
+ kr_log_verbose("[%05u. ][nsid] unable to add NSID option\n", req->uid);
+ knot_rrset_clear(req->answer->opt_rr, &req->pool);
+ }
+
+ return ctx->state;
+}
+
+KR_EXPORT
+const kr_layer_api_t *nsid_layer(struct kr_module *module)
+{
+ static kr_layer_api_t _layer = {
+ .answer_finalize = &nsid_finalize,
+ };
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_EXPORT
+int nsid_init(struct kr_module *module) {
+ struct nsid_config *config = calloc(1, sizeof(struct nsid_config));
+ if (config == NULL)
+ return kr_error(ENOMEM);
+
+ module->data = config;
+ return kr_ok();
+}
+
+static char* nsid_name(void *env, struct kr_module *module, const char *args)
+{
+ struct engine *engine = env;
+ struct nsid_config *config = module->data;
+ if (args) { /* set */
+ /* API is not binary safe, we need to fix this one day */
+ uint8_t *arg_copy = (uint8_t *)strdup(args);
+ if (arg_copy == NULL)
+ luaL_error(engine->L, "[nsid] error while allocating new NSID value\n");
+ free(config->local_nsid);
+ config->local_nsid = arg_copy;
+ config->local_nsid_len = strlen(args);
+ }
+
+ /* get */
+ if (config->local_nsid != NULL)
+ return json_encode_string((char *)config->local_nsid);
+ else
+ return NULL;
+}
+
+KR_EXPORT
+struct kr_prop *nsid_props(void)
+{
+ static struct kr_prop prop_list[] = {
+ { &nsid_name, "name", "Get or set local NSID value" },
+ { NULL, NULL, NULL }
+ };
+ return prop_list;
+}
+
+KR_EXPORT
+int nsid_deinit(struct kr_module *module) {
+ struct nsid_config *config = module->data;
+ if (config != NULL) {
+ free(config->local_nsid);
+ free(config);
+ module->data = NULL;
+ }
+ return kr_ok();
+}
+
+KR_MODULE_EXPORT(nsid)
diff --git a/modules/nsid/nsid.mk b/modules/nsid/nsid.mk
new file mode 100644
index 0000000..c7d2f51
--- /dev/null
+++ b/modules/nsid/nsid.mk
@@ -0,0 +1,6 @@
+nsid_CFLAGS := -fPIC
+nsid_LDFLAGS := -Wl,-undefined -Wl,dynamic_lookup
+nsid_SOURCES := modules/nsid/nsid.c
+nsid_DEPEND := $(libkres)
+nsid_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS)
+$(call make_c_module,nsid)
diff --git a/modules/nsid/nsid.test.lua b/modules/nsid/nsid.test.lua
new file mode 100644
index 0000000..ce178f8
--- /dev/null
+++ b/modules/nsid/nsid.test.lua
@@ -0,0 +1,21 @@
+-- disable networking so we can get SERVFAIL immediatelly
+net.ipv4 = false
+net.ipv6 = false
+
+-- test for nsid.name() interface
+local function test_nsid_name()
+ if nsid then
+ modules.unload('nsid')
+ end
+ modules.load('nsid')
+ same(nsid.name(), nil, 'NSID modes not provide default NSID value')
+ same(nsid.name('123456'), '123456', 'NSID value can be changed')
+ same(nsid.name(), '123456', 'NSID module remembers configured NSID value')
+ modules.unload('nsid')
+ modules.load('nsid')
+ same(nsid.name(), nil, 'NSID module reload removes configured value')
+end
+
+return {
+ test_nsid_name,
+}
diff --git a/modules/policy/README.rst b/modules/policy/README.rst
new file mode 100644
index 0000000..a68ad4d
--- /dev/null
+++ b/modules/policy/README.rst
@@ -0,0 +1,284 @@
+.. _mod-policy:
+
+Query policies
+--------------
+
+This module can block, rewrite, or alter inbound queries based on user-defined policies.
+
+Each policy *rule* has two parts: a *filter* and an *action*. A *filter* selects which queries will be affected by the policy, and *action* which modifies queries matching the associated filter.
+
+Typically a rule is defined as follows: ``filter(action(action parameters), filter parameters)``. For example, a filter can be ``suffix`` which matches queries whose suffix part is in specified set, and one of possible actions is ``DENY``, which denies resolution. These are combined together into ``policy.suffix(policy.DENY, {todname('badguy.example.')})``. The rule is effective when it is added into rule table using ``policy.add()``, please see `Policy examples`_.
+
+This module is enabled by default because it implements mandatory :rfc:`6761` logic.
+When no rule applies to a query, built-in rules for `special-use <https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml>`_ and `locally-served <http://www.iana.org/assignments/locally-served-dns-zones>`_ domain names are applied.
+These rules can be overriden by action ``PASS``, see `Policy examples`_ below. For debugging purposes you can also add ``modules.unload('policy')`` to your config to unload the module.
+
+
+Filters
+^^^^^^^
+A *filter* selects which queries will be affected by specified *action*. There are several policy filters available in the ``policy.`` table:
+
+* ``all(action)``
+ - always applies the action
+* ``pattern(action, pattern)``
+ - applies the action if QNAME matches a `regular expression <http://lua-users.org/wiki/PatternsTutorial>`_
+* ``suffix(action, table)``
+ - applies the action if QNAME suffix matches one of suffixes in the table (useful for "is domain in zone" rules),
+ uses `Aho-Corasick`_ string matching algorithm `from CloudFlare <https://github.com/cloudflare/lua-aho-corasick>`_ (BSD 3-clause)
+* :any:`policy.suffix_common`
+* ``rpz(default_action, path)``
+ - implements a subset of RPZ_ in zonefile format. See below for details: :any:`policy.rpz`.
+* custom filter function
+
+.. _mod-policy-actions:
+
+Actions
+^^^^^^^
+An *action* is function which modifies DNS query, and is either of type *chain* or *non-chain*. So-called *chain* actions modify the query and allow other rules to evaluate and modify the same query. *Non-chain* actions have opposite behavior, i.e. modify the query and stop rule processing.
+
+Resolver comes with several actions available in the ``policy.`` table:
+
+**Non-chain actions**
+
+Following actions stop the policy matching on the query, i.e. other rules are not evaluated once rule with following actions matches:
+
+* ``PASS`` - let the query pass through; it's useful to make exceptions before wider rules
+* ``DENY`` - reply NXDOMAIN authoritatively
+* ``DENY_MSG(msg)`` - reply NXDOMAIN authoritatively and add explanatory message to additional section
+* ``DROP`` - terminate query resolution and return SERVFAIL to the requestor
+* ``REFUSE`` - terminate query resolution and return REFUSED to the requestor
+* ``TC`` - set TC=1 if the request came through UDP, forcing client to retry with TCP
+* ``FORWARD(ip)`` - resolve a query via forwarding to an IP while validating and caching locally;
+* ``TLS_FORWARD({{ip, authentication}})`` - resolve a query via TLS connection forwarding to an IP while validating and caching locally;
+ the parameter can be a single IP (string) or a lua list of up to four IPs.
+* ``STUB(ip)`` - similar to ``FORWARD(ip)`` but *without* attempting DNSSEC validation.
+ Each request may be either answered from cache or simply sent to one of the IPs with proxying back the answer.
+* ``REROUTE({{subnet,target}, ...})`` - reroute addresses in response matching given subnet to given target, e.g. ``{'192.0.2.0/24', '127.0.0.0'}`` will rewrite '192.0.2.55' to '127.0.0.55', see :ref:`renumber module <mod-renumber>` for more information.
+
+
+**Chain actions**
+
+Following actions allow to keep trying to match other rules, until a non-chain action is triggered:
+
+* ``MIRROR(ip)`` - mirror query to given IP and continue solving it (useful for partial snooping).
+* ``QTRACE`` - pretty-print DNS response packets into the log for the query and its sub-queries. It's useful for debugging weird DNS servers.
+* ``FLAGS(set, clear)`` - set and/or clear some flags for the query. There can be multiple flags to set/clear. You can just pass a single flag name (string) or a set of names.
+
+
+Also, it is possible to write your own action (i.e. Lua function). It is possible to implement complex heuristics, e.g. to deflect `Slow drip DNS attacks <https://secure64.com/water-torture-slow-drip-dns-ddos-attack>`_ or gray-list resolution of misbehaving zones.
+
+.. warning:: The policy module currently only looks at whole DNS requests. The rules won't be re-applied e.g. when following CNAMEs.
+
+.. note:: The module (and ``kres``) expects domain names in wire format, not textual representation. So each label in name is prefixed with its length, e.g. "example.com" equals to ``"\7example\3com"``. You can use convenience function ``todname('example.com')`` for automatic conversion.
+
+Forwarding over TLS protocol (DNS-over-TLS)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Policy `TLS_FORWARD` allows you to forward queries using `Transport Layer Security`_ protocol, which hides the content of your queries from an attacker observing the network traffic. Further details about this protocol can be found in :rfc:`7858` and `IETF draft dprive-dtls-and-tls-profiles`_.
+
+Queries affected by `TLS_FORWARD` policy will always be resolved over TLS connection. Knot Resolver does not implement fallback to non-TLS connection, so if TLS connection cannot be established or authenticated according to the configuration, the resolution will fail.
+
+To test this feature you need to either :ref:`configure Knot Resolver as DNS-over-TLS server <tls-server-config>`, or pick some public DNS-over-TLS server. Please see `DNS Privacy Project`_ homepage for list of public servers.
+
+When multiple servers are specified, the one with the lowest round-trip time is used.
+
+CA+hostname authentication
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Traditional PKI authentication requires server to present certificate with specified hostname, which is issued by one of trusted CAs. Example policy is:
+
+.. code-block:: lua
+
+ policy.TLS_FORWARD({
+ {'2001:DB8::d0c', hostname='res.example.com'}})
+
+- `hostname` must exactly match hostname in server's certificate, i.e. in most cases it must not contain trailing dot (`res.example.com`).
+- System CA certificate store will be used if no `ca_file` option is specified.
+- Optional `ca_file` option can specify path to CA certificate (or certificate bundle) in `PEM format`_.
+
+TLS Examples
+~~~~~~~~~~~~
+
+.. code-block:: lua
+
+ modules = { 'policy' }
+ -- forward all queries over TLS to the specified server
+ policy.add(policy.all(policy.TLS_FORWARD({{'192.0.2.1', pin_sha256='YQ=='}})))
+ -- for brevity, other TLS examples omit policy.add(policy.all())
+ -- single server authenticated using its certificate pin_sha256
+ policy.TLS_FORWARD({{'192.0.2.1', pin_sha256='YQ=='}}) -- pin_sha256 is base64-encoded
+ -- single server authenticated using hostname and system-wide CA certificates
+ policy.TLS_FORWARD({{'192.0.2.1', hostname='res.example.com'}})
+ -- single server using non-standard port
+ policy.TLS_FORWARD({{'192.0.2.1@443', pin_sha256='YQ=='}}) -- use @ or # to specify port
+ -- single server with multiple valid pins (e.g. anycast)
+ policy.TLS_FORWARD({{'192.0.2.1', pin_sha256={'YQ==', 'Wg=='}})
+ -- multiple servers, each with own authenticator
+ policy.TLS_FORWARD({ -- please note that { here starts list of servers
+ {'192.0.2.1', pin_sha256='Wg=='},
+ -- server must present certificate issued by specified CA and hostname must match
+ {'2001:DB8::d0c', hostname='res.example.com', ca_file='/etc/knot-resolver/tlsca.crt'}
+ })
+
+.. _policy_examples:
+
+Policy examples
+^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ -- Whitelist 'www[0-9].badboy.cz'
+ policy.add(policy.pattern(policy.PASS, '\4www[0-9]\6badboy\2cz'))
+ -- Block all names below badboy.cz
+ policy.add(policy.suffix(policy.DENY, {todname('badboy.cz.')}))
+
+ -- Custom rule
+ local ffi = require('ffi')
+ local function genRR (state, req)
+ local answer = req.answer
+ local qry = req:current()
+ if qry.stype ~= kres.type.A then
+ return state
+ end
+ ffi.C.kr_pkt_make_auth_header(answer)
+ answer:rcode(kres.rcode.NOERROR)
+ answer:begin(kres.section.ANSWER)
+ answer:put(qry.sname, 900, answer:qclass(), kres.type.A, '\192\168\1\3')
+ return kres.DONE
+ end
+ policy.add(policy.suffix(genRR, { todname('my.example.cz.') }))
+
+ -- Disallow ANY queries
+ policy.add(function (req, query)
+ if query.stype == kres.type.ANY then
+ return policy.DROP
+ end
+ end)
+ -- Enforce local RPZ
+ policy.add(policy.rpz(policy.DENY, 'blacklist.rpz'))
+ -- Forward all queries below 'company.se' to given resolver;
+ -- beware: typically this won't work due to DNSSEC - see "Replacing part..." below
+ policy.add(policy.suffix(policy.FORWARD('192.168.1.1'), {todname('company.se')}))
+ -- Forward reverse queries about the 192.168.1.1/24 space to .1 port 5353
+ -- and do it directly without attempts to validate DNSSEC etc.
+ policy.add(policy.suffix(policy.STUB('192.168.1.1@5353'), {todname('1.168.192.in-addr.arpa')}))
+ -- Forward all queries matching pattern
+ policy.add(policy.pattern(policy.FORWARD('2001:DB8::1'), '\4bad[0-9]\2cz'))
+ -- Forward all queries (to public resolvers https://www.nic.cz/odvr)
+ policy.add(policy.all(policy.FORWARD({'2001:678:1::206', '193.29.206.206'})))
+ -- Print all responses with matching suffix
+ policy.add(policy.suffix(policy.QTRACE, {todname('rhybar.cz.')}))
+ -- Print all responses
+ policy.add(policy.all(policy.QTRACE))
+ -- Mirror all queries and retrieve information
+ local rule = policy.add(policy.all(policy.MIRROR('127.0.0.2')))
+ -- Print information about the rule
+ print(string.format('id: %d, matched queries: %d', rule.id, rule.count)
+ -- Reroute all addresses found in answer from 192.0.2.0/24 to 127.0.0.x
+ -- this policy is enforced on answers, therefore 'postrule'
+ local rule = policy.add(policy.REROUTE({'192.0.2.0/24', '127.0.0.0'}), true)
+ -- Delete rule that we just created
+ policy.del(rule.id)
+
+
+Replacing part of the DNS tree
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You may want to resolve most of the DNS namespace by usual means while letting some other resolver solve specific subtrees.
+Such data would typically be rejected by DNSSEC validation starting from the ICANN root keys. Therefore, if you trust the resolver and your link to it, you can simply use the ``STUB`` action instead of ``FORWARD`` to avoid validation only for those subtrees.
+
+Another issue is caused by caching, because Knot Resolver only keeps a single cache for everything.
+For example, if you add an alternative top-level domain while using the ICANN root zone for the rest, at some point the cache may obtain records proving that your top-level domain does not exist, and those records could then be used when the positive records fall out of cache. The easiest work-around is to disable reading from cache for those subtrees; the other resolver is often very close anyway.
+
+
+.. code-block:: lua
+ :caption: Example configuration: graft DNS sub-trees ``faketldtest``, ``sld.example``, and ``internal.example.com`` into existing namespace
+
+ extraTrees = policy.todnames({'faketldtest', 'sld.example', 'internal.example.com'})
+ -- Beware: the rule order is important, as STUB is not a chain action.
+ policy.add(policy.suffix(policy.FLAGS({'NO_CACHE'}), extraTrees))
+ policy.add(policy.suffix(policy.STUB({'2001:db8::1'}), extraTrees))
+
+
+Additional properties
+^^^^^^^^^^^^^^^^^^^^^
+
+Most properties (actions, filters) are described above.
+
+.. function:: policy.add(rule, postrule)
+
+ :param rule: added rule, i.e. ``policy.pattern(policy.DENY, '[0-9]+\2cz')``
+ :param postrule: boolean, if true the rule will be evaluated on answer instead of query
+ :return: rule description
+
+ Add a new policy rule that is executed either or queries or answers, depending on the ``postrule`` parameter. You can then use the returned rule description to get information and unique identifier for the rule, as well as match count.
+
+.. function:: policy.del(id)
+
+ :param id: identifier of a given rule
+ :return: boolean
+
+ Remove a rule from policy list.
+
+.. function:: policy.suffix_common(action, suffix_table[, common_suffix])
+
+ :param action: action if the pattern matches QNAME
+ :param suffix_table: table of valid suffixes
+ :param common_suffix: common suffix of entries in suffix_table
+
+ Like suffix match, but you can also provide a common suffix of all matches for faster processing (nil otherwise).
+ This function is faster for small suffix tables (in the order of "hundreds").
+
+.. function:: policy.rpz(action, path)
+
+ :param action: the default action for match in the zone; typically you want ``policy.DENY``
+ :param path: path to zone file | database
+
+ Enforce RPZ_ rules. This can be used in conjunction with published blocklist feeds.
+ The RPZ_ operation is well described in this `Jan-Piet Mens's post`_,
+ or the `Pro DNS and BIND`_ book. Here's compatibility table:
+
+ .. csv-table::
+ :header: "Policy Action", "RH Value", "Support"
+
+ "``action`` is used", "``.``", "**yes**, if ``action`` is ``DENY``"
+ "``action`` is used ", "``*.``", "*partial* [#]_"
+ "``policy.PASS``", "``rpz-passthru.``", "**yes**"
+ "``policy.DROP``", "``rpz-drop.``", "**yes**"
+ "``policy.TC``", "``rpz-tcp-only.``", "**yes**"
+ "Modified", "anything", "no"
+
+ .. [#] The specification for ``*.`` wants a ``NODATA`` answer.
+ For now, ``policy.DENY`` action doing ``NXDOMAIN`` is typically used instead.
+
+ .. csv-table::
+ :header: "Policy Trigger", "Support"
+
+ "QNAME", "**yes**"
+ "CLIENT-IP", "*partial*, may be done with :ref:`views <mod-view>`"
+ "IP", "no"
+ "NSDNAME", "no"
+ "NS-IP", "no"
+
+.. function:: policy.todnames({name, ...})
+
+ :param: names table of domain names in textual format
+
+ Returns table of domain names in wire format converted from strings.
+
+ .. code-block:: lua
+
+ -- Convert single name
+ assert(todname('example.com') == '\7example\3com\0')
+ -- Convert table of names
+ policy.todnames({'example.com', 'me.cz'})
+ { '\7example\3com\0', '\2me\2cz\0' }
+
+
+.. _`Aho-Corasick`: https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm
+.. _`@jgrahamc`: https://github.com/jgrahamc/aho-corasick-lua
+.. _RPZ: https://dnsrpz.info/
+.. _`PEM format`: https://en.wikipedia.org/wiki/Privacy-enhanced_Electronic_Mail
+.. _`Pro DNS and BIND`: http://www.zytrax.com/books/dns/ch7/rpz.html
+.. _`Jan-Piet Mens's post`: http://jpmens.net/2011/04/26/how-to-configure-your-bind-resolvers-to-lie-using-response-policy-zones-rpz/
+.. _`Transport Layer Security`: https://en.wikipedia.org/wiki/Transport_Layer_Security
+.. _`DNS Privacy Project`: https://dnsprivacy.org/
+.. _`IETF draft dprive-dtls-and-tls-profiles`: https://tools.ietf.org/html/draft-ietf-dprive-dtls-and-tls-profiles
diff --git a/modules/policy/lua-aho-corasick/.gitignore b/modules/policy/lua-aho-corasick/.gitignore
new file mode 100644
index 0000000..04fd221
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/.gitignore
@@ -0,0 +1,6 @@
+*.d
+*.o
+*.a
+*.so
+*_dep.txt
+tests/testinput
diff --git a/modules/policy/lua-aho-corasick/LICENSE b/modules/policy/lua-aho-corasick/LICENSE
new file mode 100644
index 0000000..dd65f72
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/LICENSE
@@ -0,0 +1,28 @@
+ Copyright (c) 2014 CloudFlare, Inc. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of CloudFlare, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ OWNER 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.
+
diff --git a/modules/policy/lua-aho-corasick/Makefile b/modules/policy/lua-aho-corasick/Makefile
new file mode 100644
index 0000000..6471664
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/Makefile
@@ -0,0 +1,134 @@
+OS := $(shell uname)
+
+ifeq ($(OS), Darwin)
+ SO_EXT := dylib
+else
+ SO_EXT := so
+endif
+
+#############################################################################
+#
+# Binaries we are going to build
+#
+#############################################################################
+#
+C_SO_NAME = libac.$(SO_EXT)
+LUA_SO_NAME = ahocorasick.$(SO_EXT)
+AR_NAME = libac.a
+
+#############################################################################
+#
+# Compile and link flags
+#
+#############################################################################
+PREFIX ?= /usr/local
+LUA_VERSION := 5.1
+LUA_INCLUDE_DIR := $(PREFIX)/include/lua$(LUA_VERSION)
+SO_TARGET_DIR := $(PREFIX)/lib/lua/$(LUA_VERSION)
+LUA_TARGET_DIR := $(PREFIX)/share/lua/$(LUA_VERSION)
+
+# Available directives:
+# -DDEBUG : Turn on debugging support
+# -DVERIFY : To verify if the slow-version and fast-version implementations
+# get exactly the same result. Note -DVERIFY implies -DDEBUG.
+#
+COMMON_FLAGS = -O3 #-g -DVERIFY -msse2 -msse3 -msse4.1
+COMMON_FLAGS += -fvisibility=hidden -Wall $(CXXFLAGS) $(MY_CXXFLAGS) $(CPPFLAGS)
+
+SO_CXXFLAGS = $(COMMON_FLAGS) -fPIC
+SO_LFLAGS = $(COMMON_FLAGS) $(LDFLAGS)
+AR_CXXFLAGS = $(COMMON_FLAGS)
+
+# -DVERIFY implies -DDEBUG
+ifneq ($(findstring -DVERIFY, $(COMMON_FLAGS)), )
+ifeq ($(findstring -DDEBUG, $(COMMON_FLAGS)), )
+ COMMON_FLAGS += -DDEBUG
+endif
+endif
+
+AR = ar
+AR_FLAGS = cru
+
+#############################################################################
+#
+# Divide source codes and objects into several categories
+#
+#############################################################################
+#
+SRC_COMMON := ac_fast.cxx ac_slow.cxx
+LIBAC_SO_SRC := $(SRC_COMMON) ac.cxx # source for libac.so
+LUA_SO_SRC := $(SRC_COMMON) ac_lua.cxx # source for ahocorasick.so
+LIBAC_A_SRC := $(LIBAC_SO_SRC) # source for libac.a
+
+#############################################################################
+#
+# Make rules
+#
+#############################################################################
+#
+.PHONY = all clean test benchmark prepare
+all : $(C_SO_NAME) $(LUA_SO_NAME) $(AR_NAME)
+
+-include c_so_dep.txt
+-include lua_so_dep.txt
+-include ar_dep.txt
+
+BUILD_SO_DIR := build_so
+BUILD_AR_DIR := build_ar
+
+$(BUILD_SO_DIR) :; mkdir $@
+$(BUILD_AR_DIR) :; mkdir $@
+
+$(BUILD_SO_DIR)/%.o : %.cxx | $(BUILD_SO_DIR)
+ $(CXX) $< -c $(SO_CXXFLAGS) -I$(LUA_INCLUDE_DIR) -MMD -o $@
+
+$(BUILD_AR_DIR)/%.o : %.cxx | $(BUILD_AR_DIR)
+ $(CXX) $< -c $(AR_CXXFLAGS) -I$(LUA_INCLUDE_DIR) -MMD -o $@
+
+ifneq ($(OS), Darwin)
+$(C_SO_NAME) : $(addprefix $(BUILD_SO_DIR)/, ${LIBAC_SO_SRC:.cxx=.o})
+ $(CXX) $+ -shared -Wl,-soname=$(C_SO_NAME) $(SO_LFLAGS) -o $@
+ cat $(addprefix $(BUILD_SO_DIR)/, ${LIBAC_SO_SRC:.cxx=.d}) > c_so_dep.txt
+
+$(LUA_SO_NAME) : $(addprefix $(BUILD_SO_DIR)/, ${LUA_SO_SRC:.cxx=.o})
+ $(CXX) $+ -shared -Wl,-soname=$(LUA_SO_NAME) $(SO_LFLAGS) -o $@
+ cat $(addprefix $(BUILD_SO_DIR)/, ${LUA_SO_SRC:.cxx=.d}) > lua_so_dep.txt
+
+else
+$(C_SO_NAME) : $(addprefix $(BUILD_SO_DIR)/, ${LIBAC_SO_SRC:.cxx=.o})
+ $(CXX) $+ -shared $(SO_LFLAGS) -o $@
+ cat $(addprefix $(BUILD_SO_DIR)/, ${LIBAC_SO_SRC:.cxx=.d}) > c_so_dep.txt
+
+$(LUA_SO_NAME) : $(addprefix $(BUILD_SO_DIR)/, ${LUA_SO_SRC:.cxx=.o})
+ $(CXX) $+ -shared $(SO_LFLAGS) -o $@ -Wl,-undefined,dynamic_lookup
+ cat $(addprefix $(BUILD_SO_DIR)/, ${LUA_SO_SRC:.cxx=.d}) > lua_so_dep.txt
+endif
+
+$(AR_NAME) : $(addprefix $(BUILD_AR_DIR)/, ${LIBAC_A_SRC:.cxx=.o})
+ $(AR) $(AR_FLAGS) $@ $+
+ cat $(addprefix $(BUILD_AR_DIR)/, ${LIBAC_A_SRC:.cxx=.d}) > lua_so_dep.txt
+
+#############################################################################
+#
+# Misc
+#
+#############################################################################
+#
+test : $(C_SO_NAME)
+ $(MAKE) -C tests && \
+ luajit tests/lua_test.lua && \
+ luajit tests/load_ac_test.lua
+
+benchmark: $(C_SO_NAME)
+ $(MAKE) benchmark -C tests
+
+clean :
+ -rm -rf *.o *.d c_so_dep.txt lua_so_dep.txt ar_dep.txt $(TEST) \
+ $(C_SO_NAME) $(LUA_SO_NAME) $(TEST) $(BUILD_SO_DIR) $(BUILD_AR_DIR) \
+ $(AR_NAME)
+ make clean -C tests
+
+install:
+ install -D -m 755 $(C_SO_NAME) $(DESTDIR)/$(SO_TARGET_DIR)/$(C_SO_NAME)
+ install -D -m 755 $(LUA_SO_NAME) $(DESTDIR)/$(SO_TARGET_DIR)/$(LUA_SO_NAME)
+ install -D -m 664 load_ac.lua $(DESTDIR)/$(LUA_TARGET_DIR)/load_ac.lua
diff --git a/modules/policy/lua-aho-corasick/README.md b/modules/policy/lua-aho-corasick/README.md
new file mode 100644
index 0000000..b5cc406
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/README.md
@@ -0,0 +1,40 @@
+aho-corasick-lua
+================
+
+C++ and Lua Implementation of the Aho-Corasick (AC) string matching algorithm
+(http://dl.acm.org/citation.cfm?id=360855).
+
+We began with pure Lua implementation and realize the performance is not
+satisfactory. So we switch to C/C++ implementation.
+
+There are two shared objects provied by this package: libac.so and ahocorasick.so
+The former is a regular shared object which can be directly used by C/C++
+application, or by Lua via FFI; and the later is a Lua module. An example usage
+is shown bellow:
+
+```lua
+local ac = require "ahocorasick"
+local dict = {"string1", "string", "etc"}
+local acinst = ac.create(dict)
+local r = ac.match(acinst, "mystring")
+```
+
+For efficiency reasons, the implementation is slightly different from the
+standard AC algorithm in that it doesn't return a set of strings in the dictionary
+that match the given string, instead it only returns one of them in case the string
+matches. The functionality of our implementation can be (precisely) described by
+following pseudo-c snippet.
+
+```C
+string foo(input-string, dictionary) {
+ string ret = the-end-of-input-string;
+ for each string s in dictionary {
+ // find the first occurrence match sub-string.
+ ret = min(ret, strstr(input-string, s);
+ }
+ return ret;
+}
+```
+
+It's pretty easy to get rid of this limitation, just to associate each state with
+a spare bit-vector dipicting the set of strings recognized by that state.
diff --git a/modules/policy/lua-aho-corasick/ac.cxx b/modules/policy/lua-aho-corasick/ac.cxx
new file mode 100644
index 0000000..23fb3b5
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac.cxx
@@ -0,0 +1,101 @@
+// Interface functions for libac.so
+//
+#include "ac_slow.hpp"
+#include "ac_fast.hpp"
+#include "ac.h"
+
+static inline ac_result_t
+_match(buf_header_t* ac, const char* str, unsigned int len) {
+ AC_Buffer* buf = (AC_Buffer*)(void*)ac;
+ ASSERT(ac->magic_num == AC_MAGIC_NUM);
+
+ ac_result_t r = Match(buf, str, len);
+
+ #ifdef VERIFY
+ {
+ Match_Result r2 = buf->slow_impl->Match(str, len);
+ if (r.match_begin != r2.begin) {
+ ASSERT(0);
+ } else {
+ ASSERT((r.match_begin < 0) ||
+ (r.match_end == r2.end &&
+ r.pattern_idx == r2.pattern_idx));
+ }
+ }
+ #endif
+ return r;
+}
+
+extern "C" int
+ac_match2(ac_t* ac, const char* str, unsigned int len) {
+ ac_result_t r = _match((buf_header_t*)(void*)ac, str, len);
+ return r.match_begin;
+}
+
+extern "C" ac_result_t
+ac_match(ac_t* ac, const char* str, unsigned int len) {
+ return _match((buf_header_t*)(void*)ac, str, len);
+}
+
+extern "C" ac_result_t
+ac_match_longest_l(ac_t* ac, const char* str, unsigned int len) {
+ AC_Buffer* buf = (AC_Buffer*)(void*)ac;
+ ASSERT(((buf_header_t*)ac)->magic_num == AC_MAGIC_NUM);
+
+ ac_result_t r = Match_Longest_L(buf, str, len);
+ return r;
+}
+
+class BufAlloc : public Buf_Allocator {
+public:
+ virtual AC_Buffer* alloc(int sz) {
+ return (AC_Buffer*)(new unsigned char[sz]);
+ }
+
+ // Do not de-allocate the buffer when the BufAlloc die.
+ virtual void free() {}
+
+ static void myfree(AC_Buffer* buf) {
+ ASSERT(buf->hdr.magic_num == AC_MAGIC_NUM);
+ const char* b = (const char*)buf;
+ delete[] b;
+ }
+};
+
+extern "C" ac_t*
+ac_create(const char** strv, unsigned int* strlenv, unsigned int v_len) {
+ if (v_len >= 65535) {
+ // TODO: Currently we use 16-bit to encode pattern-index (see the
+ // comment to AC_State::is_term), therefore we are not able to
+ // handle pattern set with more than 65535 entries.
+ return 0;
+ }
+
+ ACS_Constructor *acc;
+#ifdef VERIFY
+ acc = new ACS_Constructor;
+#else
+ ACS_Constructor tmp;
+ acc = &tmp;
+#endif
+ acc->Construct(strv, strlenv, v_len);
+
+ BufAlloc ba;
+ AC_Converter cvt(*acc, ba);
+ AC_Buffer* buf = cvt.Convert();
+
+#ifdef VERIFY
+ buf->slow_impl = acc;
+#endif
+ return (ac_t*)(void*)buf;
+}
+
+extern "C" void
+ac_free(void* ac) {
+ AC_Buffer* buf = (AC_Buffer*)ac;
+#ifdef VERIFY
+ delete buf->slow_impl;
+#endif
+
+ BufAlloc::myfree(buf);
+}
diff --git a/modules/policy/lua-aho-corasick/ac.h b/modules/policy/lua-aho-corasick/ac.h
new file mode 100644
index 0000000..30bf447
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac.h
@@ -0,0 +1,49 @@
+#ifndef AC_H
+#define AC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AC_EXPORT __attribute__ ((visibility ("default")))
+
+/* If the subject-string dosen't match any of the given patterns, "match_begin"
+ * should be a negative; otherwise the substring of the subject-string,
+ * starting from offset "match_begin" to "match_end" incusively,
+ * should exactly match the pattern specified by the 'pattern_idx' (i.e.
+ * the pattern is "pattern_v[pattern_idx]" where the "pattern_v" is the
+ * first acutal argument passing to ac_create())
+ */
+typedef struct {
+ int match_begin;
+ int match_end;
+ int pattern_idx;
+} ac_result_t;
+
+struct ac_t;
+
+/* Create an AC instance. "pattern_v" is a vector of patterns, the length of
+ * i-th pattern is specified by "pattern_len_v[i]"; the number of patterns
+ * is specified by "vect_len".
+ *
+ * Return the instance on success, or NUL otherwise.
+ */
+ac_t* ac_create(const char** pattern_v, unsigned int* pattern_len_v,
+ unsigned int vect_len) AC_EXPORT;
+
+ac_result_t ac_match(ac_t*, const char *str, unsigned int len) AC_EXPORT;
+
+ac_result_t ac_match_longest_l(ac_t*, const char *str, unsigned int len) AC_EXPORT;
+
+/* Similar to ac_match() except that it only returns match-begin. The rationale
+ * for this interface is that luajit has hard time in dealing with strcture-
+ * return-value.
+ */
+int ac_match2(ac_t*, const char *str, unsigned int len) AC_EXPORT;
+
+void ac_free(void*) AC_EXPORT;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AC_H */
diff --git a/modules/policy/lua-aho-corasick/ac_fast.cxx b/modules/policy/lua-aho-corasick/ac_fast.cxx
new file mode 100644
index 0000000..9dbc2e6
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_fast.cxx
@@ -0,0 +1,468 @@
+#include <algorithm> // for std::sort
+#include "ac_slow.hpp"
+#include "ac_fast.hpp"
+
+uint32
+AC_Converter::Calc_State_Sz(const ACS_State* s) const {
+ AC_State dummy;
+ uint32 sz = offsetof(AC_State, input_vect);
+ sz += s->Get_GotoNum() * sizeof(dummy.input_vect[0]);
+
+ if (sz < sizeof(AC_State))
+ sz = sizeof(AC_State);
+
+ uint32 align = __alignof__(dummy);
+ sz = (sz + align - 1) & ~(align - 1);
+ return sz;
+}
+
+AC_Buffer*
+AC_Converter::Alloc_Buffer() {
+ const vector<ACS_State*>& all_states = _acs.Get_All_States();
+ const ACS_State* root_state = _acs.Get_Root_State();
+ uint32 root_fanout = root_state->Get_GotoNum();
+
+ // Step 1: Calculate the buffer size
+ AC_Ofst root_goto_ofst, states_ofst_ofst, first_state_ofst;
+
+ // part 1 : buffer header
+ uint32 sz = root_goto_ofst = sizeof(AC_Buffer);
+
+ // part 2: Root-node's goto function
+ if (likely(root_fanout != 255))
+ sz += 256;
+ else
+ root_goto_ofst = 0;
+
+ // part 3: mapping of state's relative position.
+ unsigned align = __alignof__(AC_Ofst);
+ sz = (sz + align - 1) & ~(align - 1);
+ states_ofst_ofst = sz;
+
+ sz += sizeof(AC_Ofst) * all_states.size();
+
+ // part 4: state's contents
+ align = __alignof__(AC_State);
+ sz = (sz + align - 1) & ~(align - 1);
+ first_state_ofst = sz;
+
+ uint32 state_sz = 0;
+ for (vector<ACS_State*>::const_iterator i = all_states.begin(),
+ e = all_states.end(); i != e; i++) {
+ state_sz += Calc_State_Sz(*i);
+ }
+ state_sz -= Calc_State_Sz(root_state);
+
+ sz += state_sz;
+
+ // Step 2: Allocate buffer, and populate header.
+ AC_Buffer* buf = _buf_alloc.alloc(sz);
+
+ buf->hdr.magic_num = AC_MAGIC_NUM;
+ buf->hdr.impl_variant = IMPL_FAST_VARIANT;
+ buf->buf_len = sz;
+ buf->root_goto_ofst = root_goto_ofst;
+ buf->states_ofst_ofst = states_ofst_ofst;
+ buf->first_state_ofst = first_state_ofst;
+ buf->root_goto_num = root_fanout;
+ buf->state_num = _acs.Get_State_Num();
+ return buf;
+}
+
+void
+AC_Converter::Populate_Root_Goto_Func(AC_Buffer* buf,
+ GotoVect& goto_vect) {
+ unsigned char *buf_base = (unsigned char*)(buf);
+ InputTy* root_gotos = (InputTy*)(buf_base + buf->root_goto_ofst);
+ const ACS_State* root_state = _acs.Get_Root_State();
+
+ root_state->Get_Sorted_Gotos(goto_vect);
+
+ // Renumber the ID of root-node's immediate kids.
+ uint32 new_id = 1;
+ bool full_fantout = (goto_vect.size() == 255);
+ if (likely(!full_fantout))
+ bzero(root_gotos, 256*sizeof(InputTy));
+
+ for (GotoVect::iterator i = goto_vect.begin(), e = goto_vect.end();
+ i != e; i++, new_id++) {
+ InputTy c = i->first;
+ ACS_State* s = i->second;
+ _id_map[s->Get_ID()] = new_id;
+
+ if (likely(!full_fantout))
+ root_gotos[c] = new_id;
+ }
+}
+
+AC_Buffer*
+AC_Converter::Convert() {
+ // Step 1: Some preparation stuff.
+ GotoVect gotovect;
+
+ _id_map.clear();
+ _ofst_map.clear();
+ _id_map.resize(_acs.Get_Next_Node_Id());
+ _ofst_map.resize(_acs.Get_Next_Node_Id());
+
+ // Step 2: allocate buffer to accommodate the entire AC graph.
+ AC_Buffer* buf = Alloc_Buffer();
+ unsigned char* buf_base = (unsigned char*)buf;
+
+ // Step 3: Root node need special care.
+ Populate_Root_Goto_Func(buf, gotovect);
+ buf->root_goto_num = gotovect.size();
+ _id_map[_acs.Get_Root_State()->Get_ID()] = 0;
+
+ // Step 4: Converting the remaining states by BFSing the graph.
+ // First of all, enter root's immediate kids to the working list.
+ vector<const ACS_State*> wl;
+ State_ID id = 1;
+ for (GotoVect::iterator i = gotovect.begin(), e = gotovect.end();
+ i != e; i++, id++) {
+ ACS_State* s = i->second;
+ wl.push_back(s);
+ _id_map[s->Get_ID()] = id;
+ }
+
+ AC_Ofst* state_ofst_vect = (AC_Ofst*)(buf_base + buf->states_ofst_ofst);
+ AC_Ofst ofst = buf->first_state_ofst;
+ for (uint32 idx = 0; idx < wl.size(); idx++) {
+ const ACS_State* old_s = wl[idx];
+ AC_State* new_s = (AC_State*)(buf_base + ofst);
+
+ // This property should hold as we:
+ // - States are appended to worklist in the BFS order.
+ // - sibiling states are appended to worklist in the order of their
+ // corresponding input.
+ //
+ State_ID state_id = idx + 1;
+ ASSERT(_id_map[old_s->Get_ID()] == state_id);
+
+ state_ofst_vect[state_id] = ofst;
+
+ new_s->first_kid = wl.size() + 1;
+ new_s->depth = old_s->Get_Depth();
+ new_s->is_term = old_s->is_Terminal() ?
+ old_s->get_Pattern_Idx() + 1 : 0;
+
+ uint32 gotonum = old_s->Get_GotoNum();
+ new_s->goto_num = gotonum;
+
+ // Populate the "input" field
+ old_s->Get_Sorted_Gotos(gotovect);
+ uint32 input_idx = 0;
+ uint32 id = wl.size() + 1;
+ InputTy* input_vect = new_s->input_vect;
+ for (GotoVect::iterator i = gotovect.begin(), e = gotovect.end();
+ i != e; i++, id++, input_idx++) {
+ input_vect[input_idx] = i->first;
+
+ ACS_State* kid = i->second;
+ _id_map[kid->Get_ID()] = id;
+ wl.push_back(kid);
+ }
+
+ _ofst_map[old_s->Get_ID()] = ofst;
+ ofst += Calc_State_Sz(old_s);
+ }
+
+ // This assertion might be useful to catch buffer overflow
+ ASSERT(ofst == buf->buf_len);
+
+ // Populate the fail-link field.
+ for (vector<const ACS_State*>::iterator i = wl.begin(), e = wl.end();
+ i != e; i++) {
+ const ACS_State* slow_s = *i;
+ State_ID fast_s_id = _id_map[slow_s->Get_ID()];
+ AC_State* fast_s = (AC_State*)(buf_base + state_ofst_vect[fast_s_id]);
+ if (const ACS_State* fl = slow_s->Get_FailLink()) {
+ State_ID id = _id_map[fl->Get_ID()];
+ fast_s->fail_link = id;
+ } else
+ fast_s->fail_link = 0;
+ }
+#ifdef DEBUG
+ //dump_buffer(buf, stderr);
+#endif
+ return buf;
+}
+
+static inline AC_State*
+Get_State_Addr(unsigned char* buf_base, AC_Ofst* StateOfstVect, uint32 state_id) {
+ ASSERT(state_id != 0 && "root node is handled in speical way");
+ ASSERT(state_id < ((AC_Buffer*)buf_base)->state_num);
+ return (AC_State*)(buf_base + StateOfstVect[state_id]);
+}
+
+// The performance of the binary search is critical to this work.
+//
+// Here we provide two versions of binary-search functions.
+// The non-pristine version seems to consistently out-perform "pristine" one on
+// bunch of benchmarks we tested. With the benchmark under tests/testinput/
+//
+// The speedup is following on my laptop (core i7, ubuntu):
+//
+// benchmark was is
+// ----------------------------------------
+// image.bin 2.3s 2.0s
+// test.tar 6.7s 5.7s
+//
+// NOTE: As of I write this comment, we only measure the performance on about
+// 10+ benchmarks. It's still too early to say which one works better.
+//
+#if !defined(BS_MULTI_VER)
+static bool __attribute__((always_inline)) inline
+Binary_Search_Input(InputTy* input_vect, int vect_len, InputTy input, int& idx) {
+ if (vect_len <= 8) {
+ for (int i = 0; i < vect_len; i++) {
+ if (input_vect[i] == input) {
+ idx = i;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // The "low" and "high" must be signed integers, as they could become -1.
+ // Also since they are signed integer, "(low + high)/2" is sightly more
+ // expensive than (low+high)>>1 or ((unsigned)(low + high))/2.
+ //
+ int low = 0, high = vect_len - 1;
+ while (low <= high) {
+ int mid = (low + high) >> 1;
+ InputTy mid_c = input_vect[mid];
+
+ if (input < mid_c)
+ high = mid - 1;
+ else if (input > mid_c)
+ low = mid + 1;
+ else {
+ idx = mid;
+ return true;
+ }
+ }
+ return false;
+}
+
+#else
+
+/* Let us call this version "pristine" version. */
+static inline bool
+Binary_Search_Input(InputTy* input_vect, int vect_len, InputTy input, int& idx) {
+ int low = 0, high = vect_len - 1;
+ while (low <= high) {
+ int mid = (low + high) >> 1;
+ InputTy mid_c = input_vect[mid];
+
+ if (input < mid_c)
+ high = mid - 1;
+ else if (input > mid_c)
+ low = mid + 1;
+ else {
+ idx = mid;
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+typedef enum {
+ // Look for the first match. e.g. pattern set = {"ab", "abc", "def"},
+ // subject string "ababcdef". The first match would be "ab" at the
+ // beginning of the subject string.
+ MV_FIRST_MATCH,
+
+ // Look for the left-most longest match. Follow above example; there are
+ // two longest matches, "abc" and "def", and the left-most longest match
+ // is "abc".
+ MV_LEFT_LONGEST,
+
+ // Similar to the left-most longest match, except that it returns the
+ // *right* most longest match. Follow above example, the match would
+ // be "def". NYI.
+ MV_RIGHT_LONGEST,
+
+ // Return all patterns that match that given subject string. NYI.
+ MV_ALL_MATCHES,
+} MATCH_VARIANT;
+
+/* The Match_Tmpl is the template for vairants MV_FIRST_MATCH, MV_LEFT_LONGEST,
+ * MV_RIGHT_LONGEST (If we really really need MV_RIGHT_LONGEST variant, we are
+ * better off implementing it in a seprate function).
+ *
+ * The Match_Tmpl supports three variants at once "symbolically", once it's
+ * instanced to a particular variants, all the code irrelevant to the variants
+ * will be statically removed. So don't worry about the code like
+ * "if (variant == MV_XXXX)"; they will not incur any penalty.
+ *
+ * The drawback of using template is increased code size. Unfortunately, there
+ * is no silver bullet.
+ */
+template<MATCH_VARIANT variant> static ac_result_t
+Match_Tmpl(AC_Buffer* buf, const char* str, uint32 len) {
+ unsigned char* buf_base = (unsigned char*)(buf);
+ unsigned char* root_goto = buf_base + buf->root_goto_ofst;
+ AC_Ofst* states_ofst_vect = (AC_Ofst* )(buf_base + buf->states_ofst_ofst);
+
+ AC_State* state = 0;
+ uint32 idx = 0;
+
+ // Skip leading chars that are not valid input of root-nodes.
+ if (likely(buf->root_goto_num != 255)) {
+ while(idx < len) {
+ unsigned char c = str[idx++];
+ if (unsigned char kid_id = root_goto[c]) {
+ state = Get_State_Addr(buf_base, states_ofst_vect, kid_id);
+ break;
+ }
+ }
+ } else {
+ idx = 1;
+ state = Get_State_Addr(buf_base, states_ofst_vect, *str);
+ }
+
+ ac_result_t r = {-1, -1};
+ if (likely(state != 0)) {
+ if (unlikely(state->is_term)) {
+ /* Dictionary may have string of length 1 */
+ r.match_begin = idx - state->depth;
+ r.match_end = idx - 1;
+ r.pattern_idx = state->is_term - 1;
+
+ if (variant == MV_FIRST_MATCH) {
+ return r;
+ }
+ }
+ }
+
+ while (idx < len) {
+ unsigned char c = str[idx];
+ int res;
+ bool found;
+ found = Binary_Search_Input(state->input_vect, state->goto_num, c, res);
+ if (found) {
+ // The "t = goto(c, current_state)" is valid, advance to state "t".
+ uint32 kid = state->first_kid + res;
+ state = Get_State_Addr(buf_base, states_ofst_vect, kid);
+ idx++;
+ } else {
+ // Follow the fail-link.
+ State_ID fl = state->fail_link;
+ if (fl == 0) {
+ // fail-link is root-node, which implies the root-node dosen't
+ // have 255 valid transitions (otherwise, the fail-link should
+ // points to "goto(root, c)"), so we don't need speical handling
+ // as we did before this while-loop is entered.
+ //
+ while(idx < len) {
+ InputTy c = str[idx++];
+ if (unsigned char kid_id = root_goto[c]) {
+ state =
+ Get_State_Addr(buf_base, states_ofst_vect, kid_id);
+ break;
+ }
+ }
+ } else {
+ state = Get_State_Addr(buf_base, states_ofst_vect, fl);
+ }
+ }
+
+ // Check to see if the state is terminal state?
+ if (state->is_term) {
+ if (variant == MV_FIRST_MATCH) {
+ ac_result_t r;
+ r.match_begin = idx - state->depth;
+ r.match_end = idx - 1;
+ r.pattern_idx = state->is_term - 1;
+ return r;
+ }
+
+ if (variant == MV_LEFT_LONGEST) {
+ int match_begin = idx - state->depth;
+ int match_end = idx - 1;
+
+ if (r.match_begin == -1 ||
+ match_end - match_begin > r.match_end - r.match_begin) {
+ r.match_begin = match_begin;
+ r.match_end = match_end;
+ r.pattern_idx = state->is_term - 1;
+ }
+ continue;
+ }
+
+ ASSERT(false && "NYI");
+ }
+ }
+
+ return r;
+}
+
+ac_result_t
+Match(AC_Buffer* buf, const char* str, uint32 len) {
+ return Match_Tmpl<MV_FIRST_MATCH>(buf, str, len);
+}
+
+ac_result_t
+Match_Longest_L(AC_Buffer* buf, const char* str, uint32 len) {
+ return Match_Tmpl<MV_LEFT_LONGEST>(buf, str, len);
+}
+
+#ifdef DEBUG
+void
+AC_Converter::dump_buffer(AC_Buffer* buf, FILE* f) {
+ vector<AC_Ofst> state_ofst;
+ state_ofst.resize(_id_map.size());
+
+ fprintf(f, "Id maps between old/slow and new/fast graphs\n");
+ int old_id = 0;
+ for (vector<uint32>::iterator i = _id_map.begin(), e = _id_map.end();
+ i != e; i++, old_id++) {
+ State_ID new_id = *i;
+ if (new_id != 0) {
+ fprintf(f, "%d -> %d, ", old_id, new_id);
+ }
+ }
+ fprintf(f, "\n");
+
+ int idx = 0;
+ for (vector<uint32>::iterator i = _id_map.begin(), e = _id_map.end();
+ i != e; i++, idx++) {
+ uint32 id = *i;
+ if (id == 0) continue;
+ state_ofst[id] = _ofst_map[idx];
+ }
+
+ unsigned char* buf_base = (unsigned char*)buf;
+
+ // dump root goto-function.
+ fprintf(f, "root, fanout:%d goto {", buf->root_goto_num);
+ if (buf->root_goto_num != 255) {
+ unsigned char* root_goto = buf_base + buf->root_goto_ofst;
+ for (uint32 i = 0; i < 255; i++) {
+ if (root_goto[i] != 0)
+ fprintf(f, "%c->S:%d, ", (unsigned char)i, root_goto[i]);
+ }
+ } else {
+ fprintf(f, "full fanout\n");
+ }
+ fprintf(f, "}\n");
+
+ // dump remaining states.
+ AC_Ofst* state_ofst_vect = (AC_Ofst*)(buf_base + buf->states_ofst_ofst);
+ for (uint32 i = 1, e = buf->state_num; i < e; i++) {
+ AC_Ofst ofst = state_ofst_vect[i];
+ ASSERT(ofst == state_ofst[i]);
+ fprintf(f, "S:%d, ofst:%d, goto={", i, ofst);
+
+ AC_State* s = (AC_State*)(buf_base + ofst);
+ State_ID kid = s->first_kid;
+ for (uint32 k = 0, ke = s->goto_num; k < ke; k++, kid++)
+ fprintf(f, "%c->S:%d, ", s->input_vect[k], kid);
+
+ fprintf(f, "}, fail-link = S:%d, %s\n", s->fail_link,
+ s->is_term ? "terminal" : "");
+ }
+}
+#endif
diff --git a/modules/policy/lua-aho-corasick/ac_fast.hpp b/modules/policy/lua-aho-corasick/ac_fast.hpp
new file mode 100644
index 0000000..9ac557c
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_fast.hpp
@@ -0,0 +1,124 @@
+#ifndef AC_FAST_H
+#define AC_FAST_H
+
+#include <vector>
+#include "ac.h"
+#include "ac_slow.hpp"
+
+using namespace std;
+
+class ACS_Constructor;
+
+typedef uint32 AC_Ofst;
+typedef uint32 State_ID;
+
+// The entire "fast" AC graph is converted from its "slow" version, and store
+// in an consecutive trunk of memory or "buffer". Since the pointers in the
+// fast AC graph are represented as offset relative to the base address of
+// the buffer, this fast AC graph is position-independent, meaning cloning
+// the fast graph is just to memcpy the entire buffer.
+//
+// The buffer is laid-out as following:
+//
+// 1. The buffer header. (i.e. the AC_Buffer content)
+// 2. root-node's goto functions. It is represented as an array indiced by
+// root-node's valid inputs, and the element is the ID of the corresponding
+// transition state (aka kid). To save space, we used 8-bit to represent
+// the IDs. ID of root's kids starts with 1.
+//
+// Root may have 255 valid inputs. In this speical case, i-th element
+// stores value i -- i.e the i-th state. So, we don't need such array
+// at all. On the other hand, 8-bit is insufficient to encode kids' ID.
+//
+// 3. An array indiced by state's id, and the element is the offset
+// of correspoding state wrt the base address of the buffer.
+//
+// 4. the contents of states.
+//
+typedef struct {
+ buf_header_t hdr; // The header exposed to the user using this lib.
+#ifdef VERIFY
+ ACS_Constructor* slow_impl;
+#endif
+ uint32 buf_len;
+ AC_Ofst root_goto_ofst; // addr of root node's goto() function.
+ AC_Ofst states_ofst_ofst; // addr of state pointer vector (indiced by id)
+ AC_Ofst first_state_ofst; // addr of the first state in the buffer.
+ uint16 root_goto_num; // fan-out of root-node.
+ uint16 state_num; // number of states
+
+ // Followed by the gut of the buffer:
+ // 1. map: root's-valid-input -> kid's id
+ // 2. map: state's ID -> offset of the state
+ // 3. states' content.
+} AC_Buffer;
+
+// Depict the state of "fast" AC graph.
+typedef struct {
+ // transition are sorted. For instance, state s1, has two transitions :
+ // goto(b) -> S_b, goto(a)->S_a. The inputs are sorted in the ascending
+ // order, and the target states are permuted accordingly. In this case,
+ // the inputs are sorted as : a, b, and the target states are permuted
+ // into S_a, S_b. So, S_a is the 1st kid, the ID of kids are consecutive,
+ // so we don't need to save all the target kids.
+ //
+ State_ID first_kid;
+ AC_Ofst fail_link;
+ short depth; // How far away from root.
+ unsigned short is_term; // Is terminal node. if is_term != 0, it encodes
+ // the value of "1 + pattern-index".
+ unsigned char goto_num; // The number of valid transition.
+ InputTy input_vect[1]; // Vector of valid input. Must be last field!
+} AC_State;
+
+class Buf_Allocator {
+public:
+ Buf_Allocator() : _buf(0) {}
+ virtual ~Buf_Allocator() { free(); }
+
+ virtual AC_Buffer* alloc(int sz) = 0;
+ virtual void free() {};
+protected:
+ AC_Buffer* _buf;
+};
+
+// Convert slow-AC-graph into fast one.
+class AC_Converter {
+public:
+ AC_Converter(ACS_Constructor& acs, Buf_Allocator& ba) :
+ _acs(acs), _buf_alloc(ba) {}
+ AC_Buffer* Convert();
+
+private:
+ // Return the size in byte needed to to save the specified state.
+ uint32 Calc_State_Sz(const ACS_State *) const;
+
+ // In fast-AC-graph, the ID is bit trikcy. Given a state of slow-graph,
+ // this function is to return the ID of its counterpart in the fast-graph.
+ State_ID Get_Renumbered_Id(const ACS_State *s) const {
+ const vector<uint32> &m = _id_map;
+ return m[s->Get_ID()];
+ }
+
+ AC_Buffer* Alloc_Buffer();
+ void Populate_Root_Goto_Func(AC_Buffer *, GotoVect&);
+
+#ifdef DEBUG
+ void dump_buffer(AC_Buffer*, FILE*);
+#endif
+
+private:
+ ACS_Constructor& _acs;
+ Buf_Allocator& _buf_alloc;
+
+ // map: ID of state in slow-graph -> ID of counterpart in fast-graph.
+ vector<uint32> _id_map;
+
+ // map: ID of state in slow-graph -> offset of counterpart in fast-graph.
+ vector<AC_Ofst> _ofst_map;
+};
+
+ac_result_t Match(AC_Buffer* buf, const char* str, uint32 len);
+ac_result_t Match_Longest_L(AC_Buffer* buf, const char* str, uint32 len);
+
+#endif // AC_FAST_H
diff --git a/modules/policy/lua-aho-corasick/ac_lua.cxx b/modules/policy/lua-aho-corasick/ac_lua.cxx
new file mode 100644
index 0000000..ad7307e
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_lua.cxx
@@ -0,0 +1,173 @@
+// Interface functions for libac.so
+//
+#include <vector>
+#include <string>
+#include "ac_slow.hpp"
+#include "ac_fast.hpp"
+#include "ac.h" // for the definition of ac_result_t
+#include "ac_util.hpp"
+
+extern "C" {
+ #include <lua.h>
+ #include <lauxlib.h>
+}
+
+#if defined(USE_SLOW_VER)
+#error "Not going to implement it"
+#endif
+
+using namespace std;
+static const char* tname = "aho-corasick";
+
+class BufAlloc : public Buf_Allocator {
+public:
+ BufAlloc(lua_State* L) : _L(L) {}
+ virtual AC_Buffer* alloc(int sz) {
+ return (AC_Buffer*)lua_newuserdata (_L, sz);
+ }
+
+ // Let GC to take care.
+ virtual void free() {}
+
+private:
+ lua_State* _L;
+};
+
+static bool
+_create_helper(lua_State* L, const vector<const char*>& str_v,
+ const vector<unsigned int>& strlen_v) {
+ ASSERT(str_v.size() == strlen_v.size());
+
+ ACS_Constructor acc;
+ BufAlloc ba(L);
+
+ // Step 1: construt the slow version.
+ unsigned int strnum = str_v.size();
+ const char** str_vect = new const char*[strnum];
+ unsigned int* strlen_vect = new unsigned int[strnum];
+
+ int idx = 0;
+ for (vector<const char*>::const_iterator i = str_v.begin(), e = str_v.end();
+ i != e; i++) {
+ str_vect[idx++] = *i;
+ }
+
+ idx = 0;
+ for (vector<unsigned int>::const_iterator i = strlen_v.begin(),
+ e = strlen_v.end(); i != e; i++) {
+ strlen_vect[idx++] = *i;
+ }
+
+ acc.Construct(str_vect, strlen_vect, idx);
+ delete[] str_vect;
+ delete[] strlen_vect;
+
+ // Step 2: convert to fast version
+ AC_Converter cvt(acc, ba);
+ return cvt.Convert() != 0;
+}
+
+static ac_result_t
+_match_helper(buf_header_t* ac, const char *str, unsigned int len) {
+ AC_Buffer* buf = (AC_Buffer*)(void*)ac;
+ ASSERT(ac->magic_num == AC_MAGIC_NUM);
+
+ ac_result_t r = Match(buf, str, len);
+ return r;
+}
+
+// LUA sematic:
+// input: array of strings
+// output: userdata containing the AC-graph (i.e. the AC_Buffer).
+//
+static int
+lac_create(lua_State* L) {
+ // The table of the array must be the 1st argument.
+ int input_tab = 1;
+
+ luaL_checktype(L, input_tab, LUA_TTABLE);
+
+ // Init the "iteartor".
+ lua_pushnil(L);
+
+ vector<const char*> str_v;
+ vector<unsigned int> strlen_v;
+
+ // Loop over the elements
+ while (lua_next(L, input_tab)) {
+ size_t str_len;
+ const char* s = luaL_checklstring(L, -1, &str_len);
+ str_v.push_back(s);
+ strlen_v.push_back(str_len);
+
+ // remove the value, but keep the key as the iterator.
+ lua_pop(L, 1);
+ }
+
+ // pop the nil value
+ lua_pop(L, 1);
+
+ if (_create_helper(L, str_v, strlen_v)) {
+ // The AC graph, as a userdata is already pushed to the stack, hence 1.
+ return 1;
+ }
+
+ return 0;
+}
+
+// LUA input:
+// arg1: the userdata, representing the AC graph, returned from l_create().
+// arg2: the string to be matched.
+//
+// LUA return:
+// if match, return index range of the match; otherwise nil is returned.
+//
+static int
+lac_match(lua_State* L) {
+ buf_header_t* ac = (buf_header_t*)lua_touserdata(L, 1);
+ if (!ac) {
+ luaL_checkudata(L, 1, tname);
+ return 0;
+ }
+
+ size_t len;
+ const char* str;
+ #if LUA_VERSION_NUM >= 502
+ str = luaL_tolstring(L, 2, &len);
+ #else
+ str = lua_tolstring(L, 2, &len);
+ #endif
+ if (!str) {
+ luaL_checkstring(L, 2);
+ return 0;
+ }
+
+ ac_result_t r = _match_helper(ac, str, len);
+ if (r.match_begin != -1) {
+ lua_pushinteger(L, r.match_begin);
+ lua_pushinteger(L, r.match_end);
+ return 2;
+ }
+
+ return 0;
+}
+
+static const struct luaL_Reg lib_funcs[] = {
+ { "create", lac_create },
+ { "match", lac_match },
+ {0, 0}
+};
+
+extern "C" int AC_EXPORT
+luaopen_ahocorasick(lua_State* L) {
+ luaL_newmetatable(L, tname);
+
+#if LUA_VERSION_NUM == 501
+ luaL_register(L, tname, lib_funcs);
+#elif LUA_VERSION_NUM >= 502
+ luaL_newlib(L, lib_funcs);
+#else
+ #error "Don't know how to do it right"
+#endif
+ return 1;
+}
diff --git a/modules/policy/lua-aho-corasick/ac_slow.cxx b/modules/policy/lua-aho-corasick/ac_slow.cxx
new file mode 100644
index 0000000..cb3957a
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_slow.cxx
@@ -0,0 +1,318 @@
+#include <ctype.h>
+#include <strings.h> // for bzero
+#include <algorithm>
+#include "ac_slow.hpp"
+#include "ac.h"
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Implementation of AhoCorasick_Slow
+//
+//////////////////////////////////////////////////////////////////////////
+//
+ACS_Constructor::ACS_Constructor() : _next_node_id(1) {
+ _root = new_state();
+ _root_char = new InputTy[256];
+ bzero((void*)_root_char, 256);
+
+#ifdef VERIFY
+ _pattern_buf = 0;
+#endif
+}
+
+ACS_Constructor::~ACS_Constructor() {
+ for (std::vector<ACS_State* >::iterator i = _all_states.begin(),
+ e = _all_states.end(); i != e; i++) {
+ delete *i;
+ }
+ _all_states.clear();
+ delete[] _root_char;
+
+#ifdef VERIFY
+ delete[] _pattern_buf;
+#endif
+}
+
+ACS_State*
+ACS_Constructor::new_state() {
+ ACS_State* t = new ACS_State(_next_node_id++);
+ _all_states.push_back(t);
+ return t;
+}
+
+void
+ACS_Constructor::Add_Pattern(const char* str, unsigned int str_len,
+ int pattern_idx) {
+ ACS_State* state = _root;
+ for (unsigned int i = 0; i < str_len; i++) {
+ const char c = str[i];
+ ACS_State* new_s = state->Get_Goto(c);
+ if (!new_s) {
+ new_s = new_state();
+ new_s->_depth = state->_depth + 1;
+ state->Set_Goto(c, new_s);
+ }
+ state = new_s;
+ }
+ state->_is_terminal = true;
+ state->set_Pattern_Idx(pattern_idx);
+}
+
+void
+ACS_Constructor::Propagate_faillink() {
+ ACS_State* r = _root;
+ std::vector<ACS_State*> wl;
+
+ const ACS_Goto_Map& m = r->Get_Goto_Map();
+ for (ACS_Goto_Map::const_iterator i = m.begin(), e = m.end(); i != e; i++) {
+ ACS_State* s = i->second;
+ s->_fail_link = r;
+ wl.push_back(s);
+ }
+
+ // For any input c, make sure "goto(root, c)" is valid, which make the
+ // fail-link propagation lot easier.
+ ACS_Goto_Map goto_save = r->_goto_map;
+ for (uint32 i = 0; i <= 255; i++) {
+ ACS_State* s = r->Get_Goto(i);
+ if (!s) r->Set_Goto(i, r);
+ }
+
+ for (uint32 i = 0; i < wl.size(); i++) {
+ ACS_State* s = wl[i];
+ ACS_State* fl = s->_fail_link;
+
+ const ACS_Goto_Map& tran_map = s->Get_Goto_Map();
+
+ for (ACS_Goto_Map::const_iterator ii = tran_map.begin(),
+ ee = tran_map.end(); ii != ee; ii++) {
+ InputTy c = ii->first;
+ ACS_State *tran = ii->second;
+
+ ACS_State* tran_fl = 0;
+ for (ACS_State* fl_walk = fl; ;) {
+ if (ACS_State* t = fl_walk->Get_Goto(c)) {
+ tran_fl = t;
+ break;
+ } else {
+ fl_walk = fl_walk->Get_FailLink();
+ }
+ }
+
+ tran->_fail_link = tran_fl;
+ wl.push_back(tran);
+ }
+ }
+
+ // Remove "goto(root, c) == root" transitions
+ r->_goto_map = goto_save;
+}
+
+void
+ACS_Constructor::Construct(const char** strv, unsigned int* strlenv,
+ uint32 strnum) {
+ Save_Patterns(strv, strlenv, strnum);
+
+ for (uint32 i = 0; i < strnum; i++) {
+ Add_Pattern(strv[i], strlenv[i], i);
+ }
+
+ Propagate_faillink();
+ unsigned char* p = _root_char;
+
+ const ACS_Goto_Map& m = _root->Get_Goto_Map();
+ for (ACS_Goto_Map::const_iterator i = m.begin(), e = m.end();
+ i != e; i++) {
+ p[i->first] = 1;
+ }
+}
+
+Match_Result
+ACS_Constructor::MatchHelper(const char *str, uint32 len) const {
+ const ACS_State* root = _root;
+ const ACS_State* state = root;
+
+ uint32 idx = 0;
+ while (idx < len) {
+ InputTy c = str[idx];
+ idx++;
+ if (_root_char[c]) {
+ state = root->Get_Goto(c);
+ break;
+ }
+ }
+
+ if (unlikely(state->is_Terminal())) {
+ // This could happen if the one of the pattern has only one char!
+ uint32 pos = idx - 1;
+ Match_Result r(pos - state->Get_Depth() + 1, pos,
+ state->get_Pattern_Idx());
+ return r;
+ }
+
+ while (idx < len) {
+ InputTy c = str[idx];
+ ACS_State* gs = state->Get_Goto(c);
+
+ if (!gs) {
+ ACS_State* fl = state->Get_FailLink();
+ if (fl == root) {
+ while (idx < len) {
+ InputTy c = str[idx];
+ idx++;
+ if (_root_char[c]) {
+ state = root->Get_Goto(c);
+ break;
+ }
+ }
+ } else {
+ state = fl;
+ }
+ } else {
+ idx ++;
+ state = gs;
+ }
+
+ if (state->is_Terminal()) {
+ uint32 pos = idx - 1;
+ Match_Result r = Match_Result(pos - state->Get_Depth() + 1, pos,
+ state->get_Pattern_Idx());
+ return r;
+ }
+ }
+
+ return Match_Result(-1, -1, -1);
+}
+
+#ifdef DEBUG
+void
+ACS_Constructor::dump_text(const char* txtfile) const {
+ FILE* f = fopen(txtfile, "w+");
+ for (std::vector<ACS_State*>::const_iterator i = _all_states.begin(),
+ e = _all_states.end(); i != e; i++) {
+ ACS_State* s = *i;
+
+ fprintf(f, "S%d goto:{", s->Get_ID());
+ const ACS_Goto_Map& goto_func = s->Get_Goto_Map();
+
+ for (ACS_Goto_Map::const_iterator i = goto_func.begin(), e = goto_func.end();
+ i != e; i++) {
+ InputTy input = i->first;
+ ACS_State* tran = i->second;
+ if (isprint(input))
+ fprintf(f, "'%c' -> S:%d,", input, tran->Get_ID());
+ else
+ fprintf(f, "%#x -> S:%d,", input, tran->Get_ID());
+ }
+ fprintf(f, "} ");
+
+ if (s->_fail_link) {
+ fprintf(f, ", fail=S:%d", s->_fail_link->Get_ID());
+ }
+
+ if (s->_is_terminal) {
+ fprintf(f, ", terminal");
+ }
+
+ fprintf(f, "\n");
+ }
+ fclose(f);
+}
+
+void
+ACS_Constructor::dump_dot(const char *dotfile) const {
+ FILE* f = fopen(dotfile, "w+");
+ const char* indent = " ";
+
+ fprintf(f, "digraph G {\n");
+
+ // Emit node information
+ fprintf(f, "%s%d [style=filled];\n", indent, _root->Get_ID());
+ for (std::vector<ACS_State*>::const_iterator i = _all_states.begin(),
+ e = _all_states.end(); i != e; i++) {
+ ACS_State *s = *i;
+ if (s->_is_terminal) {
+ fprintf(f, "%s%d [shape=doublecircle];\n", indent, s->Get_ID());
+ }
+ }
+ fprintf(f, "\n");
+
+ // Emit edge information
+ for (std::vector<ACS_State*>::const_iterator i = _all_states.begin(),
+ e = _all_states.end(); i != e; i++) {
+ ACS_State* s = *i;
+ uint32 id = s->Get_ID();
+
+ const ACS_Goto_Map& m = s->Get_Goto_Map();
+ for (ACS_Goto_Map::const_iterator ii = m.begin(), ee = m.end();
+ ii != ee; ii++) {
+ InputTy input = ii->first;
+ ACS_State* tran = ii->second;
+ if (isalnum(input))
+ fprintf(f, "%s%d -> %d [label=%c];\n",
+ indent, id, tran->Get_ID(), input);
+ else
+ fprintf(f, "%s%d -> %d [label=\"%#x\"];\n",
+ indent, id, tran->Get_ID(), input);
+
+ }
+
+ // Emit fail-link
+ ACS_State* fl = s->Get_FailLink();
+ if (fl && fl != _root) {
+ fprintf(f, "%s%d -> %d [style=dotted, color=red]; \n",
+ indent, id, fl->Get_ID());
+ }
+ }
+ fprintf(f, "}\n");
+ fclose(f);
+}
+#endif
+
+#ifdef VERIFY
+void
+ACS_Constructor::Verify_Result(const char* subject, const Match_Result* r)
+ const {
+ if (r->begin >= 0) {
+ unsigned len = r->end - r->begin + 1;
+ int ptn_idx = r->pattern_idx;
+
+ ASSERT(ptn_idx >= 0 &&
+ len == get_ith_Pattern_Len(ptn_idx) &&
+ memcmp(subject + r->begin, get_ith_Pattern(ptn_idx), len) == 0);
+ }
+}
+
+void
+ACS_Constructor::Save_Patterns(const char** strv, unsigned int* strlenv,
+ int pattern_num) {
+ // calculate the total size needed to save all patterns.
+ //
+ int buf_size = 0;
+ for (int i = 0; i < pattern_num; i++) { buf_size += strlenv[i]; }
+
+ // HINT: patterns are delimited by '\0' in order to ease debugging.
+ buf_size += pattern_num;
+ ASSERT(_pattern_buf == 0);
+ _pattern_buf = new char[buf_size + 1];
+ #define MAGIC_NUM 0x5a
+ _pattern_buf[buf_size] = MAGIC_NUM;
+
+ int ofst = 0;
+ _pattern_lens.resize(pattern_num);
+ _pattern_vect.resize(pattern_num);
+ for (int i = 0; i < pattern_num; i++) {
+ int l = strlenv[i];
+ _pattern_lens[i] = l;
+ _pattern_vect[i] = _pattern_buf + ofst;
+
+ memcpy(_pattern_buf + ofst, strv[i], l);
+ ofst += l;
+ _pattern_buf[ofst++] = '\0';
+ }
+
+ ASSERT(_pattern_buf[buf_size] == MAGIC_NUM);
+ #undef MAGIC_NUM
+}
+
+#endif
diff --git a/modules/policy/lua-aho-corasick/ac_slow.hpp b/modules/policy/lua-aho-corasick/ac_slow.hpp
new file mode 100644
index 0000000..030b95d
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_slow.hpp
@@ -0,0 +1,158 @@
+#ifndef MY_AC_H
+#define MY_AC_H
+
+#include <string.h>
+#include <stdio.h>
+#include <map>
+#include <vector>
+#include <algorithm> // for std::sort
+#include "ac_util.hpp"
+
+// Forward decl. the acronym "ACS" stands for "Aho-Corasick Slow implementation"
+class ACS_State;
+class ACS_Constructor;
+class AhoCorasick;
+
+using namespace std;
+
+typedef std::map<InputTy, ACS_State*> ACS_Goto_Map;
+
+class Match_Result {
+public:
+ int begin;
+ int end;
+ int pattern_idx;
+ Match_Result(int b, int e, int p): begin(b), end(e), pattern_idx(p) {}
+};
+
+typedef pair<InputTy, ACS_State *> GotoPair;
+typedef vector<GotoPair> GotoVect;
+
+// Sorting functor
+class GotoSort {
+public:
+ bool operator() (const GotoPair& g1, const GotoPair& g2) {
+ return g1.first < g2.first;
+ }
+};
+
+class ACS_State {
+friend class ACS_Constructor;
+
+public:
+ ACS_State(uint32 id): _id(id), _pattern_idx(-1), _depth(0),
+ _is_terminal(false), _fail_link(0){}
+ ~ACS_State() {};
+
+ void Set_Goto(InputTy c, ACS_State* s) { _goto_map[c] = s; }
+ ACS_State *Get_Goto(InputTy c) const {
+ ACS_Goto_Map::const_iterator iter = _goto_map.find(c);
+ return iter != _goto_map.end() ? (*iter).second : 0;
+ }
+
+ // Return all transitions sorted in the ascending order of their input.
+ void Get_Sorted_Gotos(GotoVect& Gotos) const {
+ const ACS_Goto_Map& m = _goto_map;
+ Gotos.clear();
+ for (ACS_Goto_Map::const_iterator i = m.begin(), e = m.end();
+ i != e; i++) {
+ Gotos.push_back(GotoPair(i->first, i->second));
+ }
+ sort(Gotos.begin(), Gotos.end(), GotoSort());
+ }
+
+ ACS_State* Get_FailLink() const { return _fail_link; }
+ uint32 Get_GotoNum() const { return _goto_map.size(); }
+ uint32 Get_ID() const { return _id; }
+ uint32 Get_Depth() const { return _depth; }
+ const ACS_Goto_Map& Get_Goto_Map(void) const { return _goto_map; }
+ bool is_Terminal() const { return _is_terminal; }
+ int get_Pattern_Idx() const {
+ ASSERT(is_Terminal() && _pattern_idx >= 0);
+ return _pattern_idx;
+ }
+
+private:
+ void set_Pattern_Idx(int idx) {
+ ASSERT(is_Terminal());
+ _pattern_idx = idx;
+ }
+
+private:
+ uint32 _id;
+ int _pattern_idx;
+ short _depth;
+ bool _is_terminal;
+ ACS_Goto_Map _goto_map;
+ ACS_State* _fail_link;
+};
+
+class ACS_Constructor {
+public:
+ ACS_Constructor();
+ ~ACS_Constructor();
+
+ void Construct(const char** strv, unsigned int* strlenv,
+ unsigned int strnum);
+
+ Match_Result Match(const char* s, uint32 len) const {
+ Match_Result r = MatchHelper(s, len);
+ Verify_Result(s, &r);
+ return r;
+ }
+
+ Match_Result Match(const char* s) const { return Match(s, strlen(s)); }
+
+#ifdef DEBUG
+ void dump_text(const char* = "ac.txt") const;
+ void dump_dot(const char* = "ac.dot") const;
+#endif
+ const ACS_State *Get_Root_State() const { return _root; }
+ const vector<ACS_State*>& Get_All_States() const {
+ return _all_states;
+ }
+
+ uint32 Get_Next_Node_Id() const { return _next_node_id; }
+ uint32 Get_State_Num() const { return _next_node_id - 1; }
+
+private:
+ void Add_Pattern(const char* str, unsigned int str_len, int pattern_idx);
+ ACS_State* new_state();
+ void Propagate_faillink();
+
+ Match_Result MatchHelper(const char*, uint32 len) const;
+
+#ifdef VERIFY
+ void Verify_Result(const char* subject, const Match_Result* r) const;
+ void Save_Patterns(const char** strv, unsigned int* strlenv, int vect_len);
+ const char* get_ith_Pattern(unsigned i) const {
+ ASSERT(i < _pattern_vect.size());
+ return _pattern_vect.at(i);
+ }
+ unsigned get_ith_Pattern_Len(unsigned i) const {
+ ASSERT(i < _pattern_lens.size());
+ return _pattern_lens.at(i);
+ }
+#else
+ void Verify_Result(const char* subject, const Match_Result* r) const {
+ (void)subject; (void)r;
+ }
+ void Save_Patterns(const char** strv, unsigned int* strlenv, int vect_len) {
+ (void)strv; (void)strlenv;
+ }
+#endif
+
+private:
+ ACS_State* _root;
+ vector<ACS_State*> _all_states;
+ unsigned char* _root_char;
+ uint32 _next_node_id;
+
+#ifdef VERIFY
+ char* _pattern_buf;
+ vector<int> _pattern_lens;
+ vector<char*> _pattern_vect;
+#endif
+};
+
+#endif
diff --git a/modules/policy/lua-aho-corasick/ac_util.hpp b/modules/policy/lua-aho-corasick/ac_util.hpp
new file mode 100644
index 0000000..56fd46c
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/ac_util.hpp
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2014 CloudFlare, Inc. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of CloudFlare, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ OWNER 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.
+*/
+#ifndef AC_UTIL_H
+#define AC_UTIL_H
+
+#ifdef DEBUG
+#include <stdio.h> // for fprintf
+#include <stdlib.h> // for abort
+#endif
+
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned long uint64;
+typedef unsigned char InputTy;
+
+#ifdef DEBUG
+ // Usage examples: ASSERT(a > b), ASSERT(foo() && "Opps, foo() reutrn 0");
+ #define ASSERT(c) if (!(c))\
+ { fprintf(stderr, "%s:%d Assert: %s\n", __FILE__, __LINE__, #c); abort(); }
+#else
+ #define ASSERT(c) ((void)0)
+#endif
+
+#define likely(x) __builtin_expect((x),1)
+#define unlikely(x) __builtin_expect((x),0)
+
+#ifndef offsetof
+#define offsetof(st, m) ((size_t)(&((st *)0)->m))
+#endif
+
+typedef enum {
+ IMPL_SLOW_VARIANT = 1,
+ IMPL_FAST_VARIANT = 2,
+} impl_var_t;
+
+#define AC_MAGIC_NUM 0x5a
+typedef struct {
+ unsigned char magic_num;
+ unsigned char impl_variant;
+} buf_header_t;
+
+#endif //AC_UTIL_H
diff --git a/modules/policy/lua-aho-corasick/load_ac.lua b/modules/policy/lua-aho-corasick/load_ac.lua
new file mode 100644
index 0000000..eb70446
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/load_ac.lua
@@ -0,0 +1,90 @@
+-- Helper wrappring script for loading shared object libac.so (FFI interface)
+-- from package.cpath instead of LD_LIBRARTY_PATH.
+--
+
+local ffi = require 'ffi'
+ffi.cdef[[
+ void* ac_create(const char** str_v, unsigned int* strlen_v,
+ unsigned int v_len);
+ int ac_match2(void*, const char *str, int len);
+ void ac_free(void*);
+]]
+
+local _M = {}
+
+local string_gmatch = string.gmatch
+local string_match = string.match
+
+local ac_lib = nil
+local ac_create = nil
+local ac_match = nil
+local ac_free = nil
+
+--[[ Find shared object file package.cpath, obviating the need of setting
+ LD_LIBRARY_PATH
+]]
+local function find_shared_obj(cpath, so_name)
+ for k, v in string_gmatch(cpath, "[^;]+") do
+ local so_path = string_match(k, "(.*/)")
+ if so_path then
+ -- "so_path" could be nil. e.g, the dir path component is "."
+ so_path = so_path .. so_name
+
+ -- Don't get me wrong, the only way to know if a file exist is
+ -- trying to open it.
+ local f = io.open(so_path)
+ if f ~= nil then
+ io.close(f)
+ return so_path
+ end
+ end
+ end
+end
+
+function _M.load_ac_lib()
+ if ac_lib ~= nil then
+ return ac_lib
+ else
+ local so_path = find_shared_obj(package.cpath, "libac.so")
+ if so_path ~= nil then
+ ac_lib = ffi.load(so_path)
+ ac_create = ac_lib.ac_create
+ ac_match = ac_lib.ac_match2
+ ac_free = ac_lib.ac_free
+ return ac_lib
+ end
+ end
+end
+
+-- Create an Aho-Corasick instance, and return the instance if it was
+-- successful.
+function _M.create_ac(dict)
+ local strnum = #dict
+ if ac_lib == nil then
+ _M.load_ac_lib()
+ end
+
+ local str_v = ffi.new("const char *[?]", strnum)
+ local strlen_v = ffi.new("unsigned int [?]", strnum)
+
+ for i = 1, strnum do
+ local s = dict[i]
+ str_v[i - 1] = s
+ strlen_v[i - 1] = #s
+ end
+
+ local ac = ac_create(str_v, strlen_v, strnum);
+ if ac ~= nil then
+ return ffi.gc(ac, ac_free)
+ end
+end
+
+-- Return nil if str doesn't match the dictionary, else return non-nil.
+function _M.match(ac, str)
+ local r = ac_match(ac, str, #str);
+ if r >= 0 then
+ return r
+ end
+end
+
+return _M
diff --git a/modules/policy/lua-aho-corasick/mytest.cxx b/modules/policy/lua-aho-corasick/mytest.cxx
new file mode 100644
index 0000000..ef3dc87
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/mytest.cxx
@@ -0,0 +1,200 @@
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+#include "ac.h"
+
+using namespace std;
+
+/////////////////////////////////////////////////////////////////////////
+//
+// Test using strings from input files
+//
+/////////////////////////////////////////////////////////////////////////
+//
+class BigFileTester {
+public:
+ BigFileTester(const char* filepath);
+
+private:
+ void Genector
+privaete:
+ const char* _msg;
+ int _msg_len;
+ int _key_num; // number of strings in dictionary
+ int _key_len_idx;
+};
+
+/////////////////////////////////////////////////////////////////////////
+//
+// Simple (yet maybe tricky) testings
+//
+/////////////////////////////////////////////////////////////////////////
+//
+typedef struct {
+ const char* str;
+ const char* match;
+} StrPair;
+
+typedef struct {
+ const char* name;
+ const char** dict;
+ StrPair* strpairs;
+ int dict_len;
+ int strpair_num;
+} TestingCase;
+
+class Tests {
+public:
+ Tests(const char* name,
+ const char* dict[], int dict_len,
+ StrPair strpairs[], int strpair_num) {
+ if (!_tests)
+ _tests = new vector<TestingCase>;
+
+ TestingCase tc;
+ tc.name = name;
+ tc.dict = dict;
+ tc.strpairs = strpairs;
+ tc.dict_len = dict_len;
+ tc.strpair_num = strpair_num;
+ _tests->push_back(tc);
+ }
+
+ static vector<TestingCase>* Get_Tests() { return _tests; }
+ static void Erase_Tests() { delete _tests; _tests = 0; }
+
+private:
+ static vector<TestingCase> *_tests;
+};
+
+vector<TestingCase>* Tests::_tests = 0;
+
+static void
+simple_test(void) {
+ int total = 0;
+ int fail = 0;
+
+ vector<TestingCase> *tests = Tests::Get_Tests();
+ if (!tests)
+ return 0;
+
+ for (vector<TestingCase>::iterator i = tests->begin(), e = tests->end();
+ i != e; i++) {
+ TestingCase& t = *i;
+ fprintf(stdout, ">Testing %s\nDictionary:[ ", t.name);
+ for (int i = 0, e = t.dict_len, need_break=0; i < e; i++) {
+ fprintf(stdout, "%s, ", t.dict[i]);
+ if (need_break++ == 16) {
+ fputs("\n ", stdout);
+ need_break = 0;
+ }
+ }
+ fputs("]\n", stdout);
+
+ /* Create the dictionary */
+ int dict_len = t.dict_len;
+ ac_t* ac = ac_create(t.dict, dict_len);
+
+ for (int ii = 0, ee = t.strpair_num; ii < ee; ii++, total++) {
+ const StrPair& sp = t.strpairs[ii];
+ const char *str = sp.str; // the string to be matched
+ const char *match = sp.match;
+
+ fprintf(stdout, "[%3d] Testing '%s' : ", total, str);
+
+ int len = strlen(str);
+ ac_result_t r = ac_match(ac, str, len);
+ int m_b = r.match_begin;
+ int m_e = r.match_end;
+
+ // The return value per se is insane.
+ if (m_b > m_e ||
+ ((m_b < 0 || m_e < 0) && (m_b != -1 || m_e != -1))) {
+ fprintf(stdout, "Insane return value (%d, %d)\n", m_b, m_e);
+ fail ++;
+ continue;
+ }
+
+ // If the string is not supposed to match the dictionary.
+ if (!match) {
+ if (m_b != -1 || m_e != -1) {
+ fail ++;
+ fprintf(stdout, "Not Supposed to match (%d, %d) \n",
+ m_b, m_e);
+ } else
+ fputs("Pass\n", stdout);
+ continue;
+ }
+
+ // The string or its substring is match the dict.
+ if (m_b >= len || m_b >= len) {
+ fail ++;
+ fprintf(stdout,
+ "Return value >= the length of the string (%d, %d)\n",
+ m_b, m_e);
+ continue;
+ } else {
+ int mlen = strlen(match);
+ if ((mlen != m_e - m_b + 1) ||
+ strncmp(str + m_b, match, mlen)) {
+ fail ++;
+ fprintf(stdout, "Fail\n");
+ } else
+ fprintf(stdout, "Pass\n");
+ }
+ }
+ fputs("\n", stdout);
+ ac_free(ac);
+ }
+
+ fprintf(stdout, "Total : %d, Fail %d\n", total, fail);
+
+ return fail ? -1 : 0;
+}
+
+int
+main (int argc, char** argv) {
+ int res = simple_test();
+ return res;
+};
+
+/* test 1*/
+const char *dict1[] = {"he", "she", "his", "her"};
+StrPair strpair1[] = {
+ {"he", "he"}, {"she", "she"}, {"his", "his"},
+ {"hers", "he"}, {"ahe", "he"}, {"shhe", "he"},
+ {"shis2", "his"}, {"ahhe", "he"}
+};
+Tests test1("test 1",
+ dict1, sizeof(dict1)/sizeof(dict1[0]),
+ strpair1, sizeof(strpair1)/sizeof(strpair1[0]));
+
+/* test 2*/
+const char *dict2[] = {"poto", "poto"}; /* duplicated strings*/
+StrPair strpair2[] = {{"The pot had a handle", 0}};
+Tests test2("test 2", dict2, 2, strpair2, 1);
+
+/* test 3*/
+const char *dict3[] = {"The"};
+StrPair strpair3[] = {{"The pot had a handle", "The"}};
+Tests test3("test 3", dict3, 1, strpair3, 1);
+
+/* test 4*/
+const char *dict4[] = {"pot"};
+StrPair strpair4[] = {{"The pot had a handle", "pot"}};
+Tests test4("test 4", dict4, 1, strpair4, 1);
+
+/* test 5*/
+const char *dict5[] = {"pot "};
+StrPair strpair5[] = {{"The pot had a handle", "pot "}};
+Tests test5("test 5", dict5, 1, strpair5, 1);
+
+/* test 6*/
+const char *dict6[] = {"ot h"};
+StrPair strpair6[] = {{"The pot had a handle", "ot h"}};
+Tests test6("test 6", dict6, 1, strpair6, 1);
+
+/* test 7*/
+const char *dict7[] = {"andle"};
+StrPair strpair7[] = {{"The pot had a handle", "andle"}};
+Tests test7("test 7", dict7, 1, strpair7, 1);
diff --git a/modules/policy/lua-aho-corasick/tests/Makefile b/modules/policy/lua-aho-corasick/tests/Makefile
new file mode 100644
index 0000000..54fd90f
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/Makefile
@@ -0,0 +1,65 @@
+OS := $(shell uname)
+ifeq ($(OS), Darwin)
+ SO_EXT := dylib
+else
+ SO_EXT := so
+endif
+
+.PHONY = all clean test runtest benchmark
+
+PROGRAM = ac_test
+BENCHMARK = ac_bench
+all: runtest
+
+CXXFLAGS = -O3 -g -march=native -Wall -DDEBUG
+MYCXXFLAGS = -MMD -I.. $(CXXFLAGS)
+%.o : %.cxx
+ $(CXX) $< -c $(MYCXXFLAGS)
+
+-include dep.cxx
+SRC = test_main.cxx ac_test_simple.cxx ac_test_aggr.cxx test_bigfile.cxx
+
+OBJ = ${SRC:.cxx=.o}
+
+-include test_dep.txt
+-include bench_dep.txt
+
+$(PROGRAM) $(BENCHMARK) : testinput/text.tar testinput/image.bin
+$(PROGRAM) : $(OBJ) ../libac.$(SO_EXT)
+ $(CXX) $(OBJ) -L.. -lac -o $@
+ -cat *.d > test_dep.txt
+
+$(BENCHMARK) : ac_bench.o ../libac.$(SO_EXT)
+ $(CXX) ac_bench.o -L.. -lac -o $@
+ -cat *.d > bench_dep.txt
+
+ifneq ($(OS), Darwin)
+runtest:$(PROGRAM)
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):.. ./$(PROGRAM) testinput/*
+
+benchmark:$(BENCHMARK)
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):.. ./ac_bench
+
+else
+runtest:$(PROGRAM)
+ DYLD_LIBRARY_PATH=$(DYLD_LIBRARY_PATH):.. ./$(PROGRAM) testinput/*
+
+benchmark:$(BENCHMARK)
+ DYLD_LIBRARY_PATH=$(DYLD_LIBRARY_PATH):.. ./ac_bench
+
+endif
+
+testinput/text.tar:
+ echo "download testing files (gcc tarball)..."
+ if [ ! -d testinput ] ; then mkdir testinput; fi
+ cd testinput && \
+ curl ftp://ftp.gnu.org/gnu/gcc/gcc-1.42.tar.gz -o text.tar.gz 2>/dev/null \
+ && gzip -d text.tar.gz
+
+testinput/image.bin:
+ echo "download testing files.."
+ if [ ! -d testinput ] ; then mkdir testinput; fi
+ curl http://www.3dvisionlive.com/sites/default/files/Curiosity_render_hiresb.jpg -o $@ 2>/dev/null
+
+clean:
+ -rm -f *.o *.d dep.txt $(PROGRAM) $(BENCHMARK)
diff --git a/modules/policy/lua-aho-corasick/tests/ac_bench.cxx b/modules/policy/lua-aho-corasick/tests/ac_bench.cxx
new file mode 100644
index 0000000..421322c
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/ac_bench.cxx
@@ -0,0 +1,519 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <string>
+#include <vector>
+#include "ac.h"
+#include "ac_util.hpp"
+
+using namespace std;
+
+static bool SomethingWrong = false;
+
+static int iteration = 300;
+static string dict_dir;
+static string obj_file_dir;
+static bool print_help = false;
+static int piece_size = 1024;
+
+class PatternSet {
+public:
+ PatternSet(const char* filepath);
+ ~PatternSet() { Cleanup(); }
+
+ int getPatternNum() const { return _pat_num; }
+ const char** getPatternVector() const { return _patterns; }
+ unsigned int* getPatternLenVector() const { return _pat_len; }
+
+ const char* getErrMessage() const { return _errmsg; }
+ static bool isDictFile(const char* filepath) {
+ if (strncmp(basename(const_cast<char*>(filepath)), "dict", 4))
+ return false;
+ return true;
+ }
+
+private:
+ bool ExtractPattern(const char* filepath);
+ void Cleanup();
+
+ const char** _patterns;
+ unsigned int* _pat_len;
+ char* _mmap;
+ int _fd;
+ size_t _mmap_size;
+ int _pat_num;
+
+ const char* _errmsg;
+};
+
+bool
+PatternSet::ExtractPattern(const char* filepath) {
+ if (!isDictFile(filepath))
+ return false;
+
+ struct stat filestat;
+ if (stat(filepath, &filestat)) {
+ _errmsg = "fail to call stat()";
+ return false;
+ }
+
+ if (filestat.st_size > 4096 * 1024) {
+ /* It dosen't seem to be a dictionary file*/
+ _errmsg = "file too big?";
+ return false;
+ }
+
+ _fd = open(filepath, 0);
+ if (_fd == -1) {
+ _errmsg = "fail to open dictionary file";
+ return false;
+ }
+
+ _mmap_size = filestat.st_size;
+ _mmap = (char*)mmap(0, filestat.st_size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE, _fd, 0);
+ if (_mmap == MAP_FAILED) {
+ _errmsg = "fail to call mmap";
+ return false;
+ }
+
+ const char* pat = _mmap;
+ vector<const char*> pat_vect;
+ vector<unsigned> pat_len_vect;
+
+ for (size_t i = 0, e = filestat.st_size; i < e; i++) {
+ if (_mmap[i] == '\r' || _mmap[i] == '\n') {
+ _mmap[i] = '\0';
+ int len = _mmap + i - pat;
+ if (len > 0) {
+ pat_vect.push_back(pat);
+ pat_len_vect.push_back(len);
+ }
+ pat = _mmap + i + 1;
+ }
+ }
+
+ ASSERT(pat_vect.size() == pat_len_vect.size());
+
+ int pat_num = pat_vect.size();
+ if (pat_num > 0) {
+ const char** p = _patterns = new const char*[pat_num];
+ int i = 0;
+ for (vector<const char*>::iterator iter = pat_vect.begin(),
+ iter_e = pat_vect.end(); iter != iter_e; ++iter) {
+ p[i++] = *iter;
+ }
+
+ i = 0;
+ unsigned int* q = _pat_len = new unsigned int[pat_num];
+ for (vector<unsigned>::iterator iter = pat_len_vect.begin(),
+ iter_e = pat_len_vect.end(); iter != iter_e; ++iter) {
+ q[i++] = *iter;
+ }
+ }
+
+ _pat_num = pat_num;
+ if (pat_num <= 0) {
+ _errmsg = "no pattern at all";
+ return false;
+ }
+
+ return true;
+}
+
+void
+PatternSet::Cleanup() {
+ if (_mmap != MAP_FAILED) {
+ munmap(_mmap, _mmap_size);
+ _mmap = (char*)MAP_FAILED;
+ _mmap_size = 0;
+ }
+
+ delete[] _patterns;
+ delete[] _pat_len;
+ if (_fd != -1)
+ close(_fd);
+ _pat_num = -1;
+}
+
+PatternSet::PatternSet(const char* filepath) {
+ _patterns = 0;
+ _pat_len = 0;
+ _mmap = (char*)MAP_FAILED;
+ _mmap_size = 0;
+ _pat_num = -1;
+ _errmsg = "";
+
+ if (!ExtractPattern(filepath))
+ Cleanup();
+}
+
+bool
+getFilesUnderDir(vector<string>& files, const char* path) {
+ files.clear();
+
+ DIR* dir = opendir(path);
+ if (!dir)
+ return false;
+
+ string path_dir = path;
+ path_dir += "/";
+
+ for (;;) {
+ struct dirent* entry = readdir(dir);
+ if (entry) {
+ string filepath = path_dir + entry->d_name;
+ struct stat file_stat;
+ if (stat(filepath.c_str(), &file_stat)) {
+ closedir(dir);
+ return false;
+ }
+
+ if (S_ISREG(file_stat.st_mode))
+ files.push_back(filepath);
+
+ continue;
+ }
+
+ if (errno) {
+ return false;
+ }
+ break;
+ }
+ closedir(dir);
+ return true;
+}
+
+class Timer {
+public:
+ Timer() {
+ my_clock_gettime(&_start);
+ _stop = _start;
+ _acc.tv_sec = 0;
+ _acc.tv_nsec = 0;
+ }
+
+ const Timer& operator += (const Timer& that) {
+ time_t sec = _acc.tv_sec + that._acc.tv_sec;
+ long nsec = _acc.tv_nsec + that._acc.tv_nsec;
+ if (nsec > 1000000000) {
+ nsec -= 1000000000;
+ sec += 1;
+ }
+ _acc.tv_sec = sec;
+ _acc.tv_nsec = nsec;
+ return *this;
+ }
+
+ // return duration in us
+ size_t getDuration() const {
+ return _acc.tv_sec * (size_t)1000000 + _acc.tv_nsec/1000;
+ }
+
+ void Start(bool acc=true) {
+ my_clock_gettime(&_start);
+ }
+
+ void Stop() {
+ my_clock_gettime(&_stop);
+ struct timespec t = CalcDuration();
+ _acc = add_duration(_acc, t);
+ }
+
+private:
+ int my_clock_gettime(struct timespec* t) {
+#ifdef __linux
+ return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, t);
+#else
+ struct timeval tv;
+ int rc = gettimeofday(&tv, 0);
+ t->tv_sec = tv.tv_sec;
+ t->tv_nsec = tv.tv_usec * 1000;
+ return rc;
+#endif
+ }
+
+ struct timespec add_duration(const struct timespec& dur1,
+ const struct timespec& dur2) {
+ time_t sec = dur1.tv_sec + dur2.tv_sec;
+ long nsec = dur1.tv_nsec + dur2.tv_nsec;
+ if (nsec > 1000000000) {
+ nsec -= 1000000000;
+ sec += 1;
+ }
+ timespec t;
+ t.tv_sec = sec;
+ t.tv_nsec = nsec;
+
+ return t;
+ }
+
+ struct timespec CalcDuration() const {
+ timespec diff;
+ if ((_stop.tv_nsec - _start.tv_nsec)<0) {
+ diff.tv_sec = _stop.tv_sec - _start.tv_sec - 1;
+ diff.tv_nsec = 1000000000 + _stop.tv_nsec - _start.tv_nsec;
+ } else {
+ diff.tv_sec = _stop.tv_sec - _start.tv_sec;
+ diff.tv_nsec = _stop.tv_nsec - _start.tv_nsec;
+ }
+ return diff;
+ }
+
+ struct timespec _start;
+ struct timespec _stop;
+ struct timespec _acc;
+};
+
+class Benchmark {
+public:
+ Benchmark(const PatternSet& pat_set, const char* infile):
+ _pat_set(pat_set), _infile(infile) {
+ _mmap = (char*)MAP_FAILED;
+ _file_sz = 0;
+ _fd = -1;
+ }
+
+ ~Benchmark() {
+ if (_mmap != MAP_FAILED)
+ munmap(_mmap, _file_sz);
+ if (_fd != -1)
+ close(_fd);
+ }
+
+ bool Run(int iteration);
+ const Timer& getTimer() const { return _timer; }
+
+private:
+ const PatternSet& _pat_set;
+ const char* _infile;
+ char* _mmap;
+ int _fd;
+ size_t _file_sz; // input file size
+ Timer _timer;
+};
+
+bool
+Benchmark::Run(int iteration) {
+ if (_pat_set.getPatternNum() <= 0) {
+ SomethingWrong = true;
+ return false;
+ }
+
+ if (_mmap == MAP_FAILED) {
+ struct stat filestat;
+ if (stat(_infile, &filestat)) {
+ SomethingWrong = true;
+ return false;
+ }
+
+ if (!S_ISREG(filestat.st_mode)) {
+ SomethingWrong = true;
+ return false;
+ }
+
+ _fd = open(_infile, 0);
+ if (_fd == -1)
+ return false;
+
+ _mmap = (char*)mmap(0, filestat.st_size, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE, _fd, 0);
+
+ if (_mmap == MAP_FAILED) {
+ SomethingWrong = true;
+ return false;
+ }
+
+ _file_sz = filestat.st_size;
+ }
+
+ ac_t* ac = ac_create(_pat_set.getPatternVector(),
+ _pat_set.getPatternLenVector(),
+ _pat_set.getPatternNum());
+ if (!ac) {
+ SomethingWrong = true;
+ return false;
+ }
+
+ int piece_num = _file_sz/piece_size;
+
+ _timer.Start(false);
+
+ /* Stupid compiler may not be able to promote piece_size into register.
+ * Do it manually.
+ */
+ int piece_sz = piece_size;
+ for (int i = 0; i < iteration; i++) {
+ size_t match_ofst = 0;
+ for (int piece_idx = 0; piece_idx < piece_num; piece_idx ++) {
+ ac_match2(ac, _mmap + match_ofst, piece_sz);
+ match_ofst += piece_sz;
+ }
+ if (match_ofst != _file_sz)
+ ac_match2(ac, _mmap + match_ofst, _file_sz - match_ofst);
+ }
+ _timer.Stop();
+ return true;
+}
+
+const char* short_opt = "hd:f:i:p:";
+const struct option long_opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"iteration", required_argument, 0, 'i'},
+ {"dictionary-dir", required_argument, 0, 'd'},
+ {"obj-file-dir", required_argument, 0, 'f'},
+ {"piece-size", required_argument, 0, 'p'},
+};
+
+static void
+PrintHelp(const char* prog_name) {
+ const char* msg =
+"Usage %s [OPTIONS]\n"
+" -d, --dictionary-dir : specify the dictionary directory (./dict by default)\n"
+" -f, --obj-file-dir : specify the object file directory\n"
+" (./testinput by default)\n"
+" -i, --iteration : Run this many iteration for each pattern match\n"
+" -p, --piece-size : The size of 'piece' in byte. The input file is\n"
+" divided into pieces, and match function is working\n"
+" on one piece at a time. The default size of piece\n"
+" is 1k byte.\n";
+
+ fprintf(stdout, msg, prog_name);
+}
+
+static bool
+getOptions(int argc, char** argv) {
+ bool dict_dir_set = false;
+ bool objfile_dir_set = false;
+ int opt_index;
+
+ while (1) {
+ if (print_help) break;
+
+ int c = getopt_long(argc, argv, short_opt, long_opts, &opt_index);
+
+ if (c == -1) break;
+ if (c == 0) { c = long_opts[opt_index].val; }
+
+ switch(c) {
+ case 'h':
+ print_help = true;
+ break;
+
+ case 'i':
+ iteration = atol(optarg);
+ break;
+
+ case 'd':
+ dict_dir = optarg;
+ dict_dir_set = true;
+ break;
+
+ case 'f':
+ obj_file_dir = optarg;
+ objfile_dir_set = true;
+ break;
+
+ case 'p':
+ piece_size = atol(optarg);
+ break;
+
+ case '?':
+ default:
+ return false;
+ }
+ }
+
+ if (print_help)
+ return true;
+
+ string basedir(dirname(argv[0]));
+ if (!dict_dir_set)
+ dict_dir = basedir + "/dict";
+
+ if (!objfile_dir_set)
+ obj_file_dir = basedir + "/testinput";
+
+ return true;
+}
+
+int
+main(int argc, char** argv) {
+ if (!getOptions(argc, argv))
+ return -1;
+
+ if (print_help) {
+ PrintHelp(argv[0]);
+ return 0;
+ }
+
+#ifndef __linux
+ fprintf(stdout, "\n!!!WARNING: On this OS, the execution time is measured"
+ " by gettimeofday(2) which is imprecise!!!\n\n");
+#endif
+
+ fprintf(stdout, "Test with iteration = %d, piece size = %d, and",
+ iteration, piece_size);
+ fprintf(stdout, "\n dictionary dir = %s\n object file dir = %s\n\n",
+ dict_dir.c_str(), obj_file_dir.c_str());
+
+ vector<string> dict_files;
+ vector<string> input_files;
+
+ if (!getFilesUnderDir(dict_files, dict_dir.c_str())) {
+ fprintf(stdout, "fail to find dictionary files\n");
+ return -1;
+ }
+
+ if (!getFilesUnderDir(input_files, obj_file_dir.c_str())) {
+ fprintf(stdout, "fail to find test input files\n");
+ return -1;
+ }
+
+ for (vector<string>::iterator diter = dict_files.begin(),
+ diter_e = dict_files.end(); diter != diter_e; ++diter) {
+
+ const char* dict_name = diter->c_str();
+ if (!PatternSet::isDictFile(dict_name))
+ continue;
+
+ PatternSet ps(dict_name);
+ if (ps.getPatternNum() <= 0) {
+ fprintf(stdout, "fail to open dictionary file %s : %s\n",
+ dict_name, ps.getErrMessage());
+ SomethingWrong = true;
+ continue;
+ }
+
+ fprintf(stdout, "Using dictionary %s\n", dict_name);
+ Timer timer;
+ for (vector<string>::iterator iter = input_files.begin(),
+ iter_e = input_files.end(); iter != iter_e; ++iter) {
+ fprintf(stdout, " testing %s ... ", iter->c_str());
+ fflush(stdout);
+ Benchmark bm(ps, iter->c_str());
+ bm.Run(iteration);
+ const Timer& t = bm.getTimer();
+ timer += bm.getTimer();
+ fprintf(stdout, "elapsed %.3f\n", t.getDuration() / 1000000.0);
+ }
+
+ fprintf(stdout,
+ "\n==========================================================\n"
+ " Total Elapse %.3f\n\n", timer.getDuration() / 1000000.0);
+ }
+
+ return SomethingWrong ? -1 : 0;
+}
diff --git a/modules/policy/lua-aho-corasick/tests/ac_test_aggr.cxx b/modules/policy/lua-aho-corasick/tests/ac_test_aggr.cxx
new file mode 100644
index 0000000..4ea02bc
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/ac_test_aggr.cxx
@@ -0,0 +1,135 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+#include <string>
+
+#include "ac.h"
+#include "ac_util.hpp"
+#include "test_base.hpp"
+
+using namespace std;
+
+namespace {
+class ACBigFileTester : public BigFileTester {
+public:
+ ACBigFileTester(const char* filepath) : BigFileTester(filepath){};
+
+private:
+ virtual buf_header_t* PM_Create(const char** strv, uint32* strlenv,
+ uint32 vect_len) {
+ return (buf_header_t*)ac_create(strv, strlenv, vect_len);
+ }
+
+ virtual void PM_Free(buf_header_t* PM) { ac_free(PM); }
+ virtual bool Run_Helper(buf_header_t* PM);
+};
+
+class ACTestAggressive: public ACTestBase {
+public:
+ ACTestAggressive(const vector<const char*>& files, const char* banner)
+ : ACTestBase(banner), _files(files) {}
+ virtual bool Run();
+
+private:
+ void PrintSummary(int total, int fail) {
+ fprintf(stdout, "Test count : %d, fail: %d\n", total, fail);
+ fflush(stdout);
+ }
+ vector<const char*> _files;
+};
+
+} // end of anonymous namespace
+
+bool
+ACBigFileTester::Run_Helper(buf_header_t* PM) {
+ int fail = 0;
+ // advance one chunk at a time.
+ int len = _msg_len;
+ int chunk_sz = _chunk_sz;
+
+ vector<const char*> c_style_keys;
+ for (int i = 0, e = _keys.size(); i != e; i++) {
+ const char* key = _keys[i].first;
+ int len = _keys[i].second;
+ char *t = new char[len+1];
+ memcpy(t, key, len);
+ t[len] = '\0';
+ c_style_keys.push_back(t);
+ }
+
+ for (int ofst = 0, chunk_idx = 0, chunk_num = _chunk_num;
+ chunk_idx < chunk_num; ofst += chunk_sz, chunk_idx++) {
+ const char* substring = _msg + ofst;
+ ac_result_t r = ac_match((ac_t*)(void*)PM, substring , len - ofst);
+ int m_b = r.match_begin;
+ int m_e = r.match_end;
+
+ if (m_b < 0 || m_e < 0 || m_e <= m_b || m_e >= len) {
+ fprintf(stdout, "fail to find match substring[%d:%d])\n",
+ ofst, len - 1);
+ fail ++;
+ continue;
+ }
+
+ const char* match_str = _msg + len;
+ int strstr_len = 0;
+ int key_idx = -1;
+
+ for (int i = 0, e = c_style_keys.size(); i != e; i++) {
+ const char* key = c_style_keys[i];
+ if (const char *m = strstr(substring, key)) {
+ if (m < match_str) {
+ match_str = m;
+ strstr_len = _keys[i].second;
+ key_idx = i;
+ }
+ }
+ }
+ ASSERT(key_idx != -1);
+ if ((match_str - substring != m_b)) {
+ fprintf(stdout,
+ "Fail to find match substring[%d:%d]),"
+ " expected to find match at offset %d instead of %d\n",
+ ofst, len - 1,
+ (int)(match_str - _msg), ofst + m_b);
+ fprintf(stdout, "%d vs %d (key idx %d)\n", strstr_len, m_e - m_b + 1, key_idx);
+ PrintStr(stdout, match_str, strstr_len);
+ fprintf(stdout, "\n");
+ PrintStr(stdout, _msg + ofst + m_b,
+ m_e - m_b + 1);
+ fprintf(stdout, "\n");
+ fail ++;
+ }
+ }
+ for (vector<const char*>::iterator i = c_style_keys.begin(),
+ e = c_style_keys.end(); i != e; i++) {
+ delete[] *i;
+ }
+
+ return fail == 0;
+}
+
+bool
+ACTestAggressive::Run() {
+ int fail = 0;
+ for (vector<const char*>::iterator i = _files.begin(), e = _files.end();
+ i != e; i++) {
+ ACBigFileTester bft(*i);
+ if (!bft.Run())
+ fail ++;
+ }
+ return fail == 0;
+}
+
+bool
+Run_AC_Aggressive_Test(const vector<const char*>& files) {
+ ACTestAggressive t(files, "AC Aggressive test");
+ t.PrintBanner();
+ return t.Run();
+}
diff --git a/modules/policy/lua-aho-corasick/tests/ac_test_simple.cxx b/modules/policy/lua-aho-corasick/tests/ac_test_simple.cxx
new file mode 100644
index 0000000..fa2d7fd
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/ac_test_simple.cxx
@@ -0,0 +1,275 @@
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+#include <string>
+
+#include "ac.h"
+#include "ac_util.hpp"
+#include "test_base.hpp"
+
+using namespace std;
+
+namespace {
+typedef struct {
+ const char* str;
+ const char* match;
+} StrPair;
+
+typedef enum {
+ MV_FIRST_MATCH = 0,
+ MV_LEFT_LONGEST = 1,
+} MatchVariant;
+
+typedef struct {
+ const char* name;
+ const char** dict;
+ StrPair* strpairs;
+ int dict_len;
+ int strpair_num;
+ MatchVariant match_variant;
+} TestingCase;
+
+class Tests {
+public:
+ Tests(const char* name,
+ const char* dict[], int dict_len,
+ StrPair strpairs[], int strpair_num,
+ MatchVariant mv = MV_FIRST_MATCH) {
+ if (!_tests)
+ _tests = new vector<TestingCase>;
+
+ TestingCase tc;
+ tc.name = name;
+ tc.dict = dict;
+ tc.strpairs = strpairs;
+ tc.dict_len = dict_len;
+ tc.strpair_num = strpair_num;
+ tc.match_variant = mv;
+ _tests->push_back(tc);
+ }
+
+ static vector<TestingCase>* Get_Tests() { return _tests; }
+ static void Erase_Tests() { delete _tests; _tests = 0; }
+
+private:
+ static vector<TestingCase> *_tests;
+};
+
+class LeftLongestTests : public Tests {
+public:
+ LeftLongestTests (const char* name, const char* dict[], int dict_len,
+ StrPair strpairs[], int strpair_num):
+ Tests(name, dict, dict_len, strpairs, strpair_num, MV_LEFT_LONGEST) {
+ }
+};
+
+vector<TestingCase>* Tests::_tests = 0;
+
+class ACTestSimple: public ACTestBase {
+public:
+ ACTestSimple(const char* banner) : ACTestBase(banner) {}
+ virtual bool Run();
+
+private:
+ void PrintSummary(int total, int fail) {
+ fprintf(stdout, "Test count : %d, fail: %d\n", total, fail);
+ fflush(stdout);
+ }
+};
+}
+
+bool
+ACTestSimple::Run() {
+ int total = 0;
+ int fail = 0;
+
+ vector<TestingCase> *tests = Tests::Get_Tests();
+ if (!tests) {
+ PrintSummary(0, 0);
+ return true;
+ }
+
+ for (vector<TestingCase>::iterator i = tests->begin(), e = tests->end();
+ i != e; i++) {
+ TestingCase& t = *i;
+ int dict_len = t.dict_len;
+ unsigned int* strlen_v = new unsigned int[dict_len];
+
+ fprintf(stdout, ">Testing %s\nDictionary:[ ", t.name);
+ for (int i = 0, need_break=0; i < dict_len; i++) {
+ const char* s = t.dict[i];
+ fprintf(stdout, "%s, ", s);
+ strlen_v[i] = strlen(s);
+ if (need_break++ == 16) {
+ fputs("\n ", stdout);
+ need_break = 0;
+ }
+ }
+ fputs("]\n", stdout);
+
+ /* Create the dictionary */
+ ac_t* ac = ac_create(t.dict, strlen_v, dict_len);
+ delete[] strlen_v;
+
+ for (int ii = 0, ee = t.strpair_num; ii < ee; ii++, total++) {
+ const StrPair& sp = t.strpairs[ii];
+ const char *str = sp.str; // the string to be matched
+ const char *match = sp.match;
+
+ fprintf(stdout, "[%3d] Testing '%s' : ", total, str);
+
+ int len = strlen(str);
+ ac_result_t r;
+ if (t.match_variant == MV_FIRST_MATCH)
+ r = ac_match(ac, str, len);
+ else if (t.match_variant == MV_LEFT_LONGEST)
+ r = ac_match_longest_l(ac, str, len);
+ else {
+ ASSERT(false && "Unknown variant");
+ }
+
+ int m_b = r.match_begin;
+ int m_e = r.match_end;
+
+ // The return value per se is insane.
+ if (m_b > m_e ||
+ ((m_b < 0 || m_e < 0) && (m_b != -1 || m_e != -1))) {
+ fprintf(stdout, "Insane return value (%d, %d)\n", m_b, m_e);
+ fail ++;
+ continue;
+ }
+
+ // If the string is not supposed to match the dictionary.
+ if (!match) {
+ if (m_b != -1 || m_e != -1) {
+ fail ++;
+ fprintf(stdout, "Not Supposed to match (%d, %d) \n",
+ m_b, m_e);
+ } else
+ fputs("Pass\n", stdout);
+ continue;
+ }
+
+ // The string or its substring is match the dict.
+ if (m_b >= len || m_b >= len) {
+ fail ++;
+ fprintf(stdout,
+ "Return value >= the length of the string (%d, %d)\n",
+ m_b, m_e);
+ continue;
+ } else {
+ int mlen = strlen(match);
+ if ((mlen != m_e - m_b + 1) ||
+ strncmp(str + m_b, match, mlen)) {
+ fail ++;
+ fprintf(stdout, "Fail\n");
+ } else
+ fprintf(stdout, "Pass\n");
+ }
+ }
+ fputs("\n", stdout);
+ ac_free(ac);
+ }
+
+ PrintSummary(total, fail);
+ return fail == 0;
+}
+
+bool
+Run_AC_Simple_Test() {
+ ACTestSimple t("AC Simple test");
+ t.PrintBanner();
+ return t.Run();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Testing cases for first-match variant (i.e. test ac_match())
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+
+/* test 1*/
+const char *dict1[] = {"he", "she", "his", "her"};
+StrPair strpair1[] = {
+ {"he", "he"}, {"she", "she"}, {"his", "his"},
+ {"hers", "he"}, {"ahe", "he"}, {"shhe", "he"},
+ {"shis2", "his"}, {"ahhe", "he"}
+};
+Tests test1("test 1",
+ dict1, sizeof(dict1)/sizeof(dict1[0]),
+ strpair1, sizeof(strpair1)/sizeof(strpair1[0]));
+
+/* test 2*/
+const char *dict2[] = {"poto", "poto"}; /* duplicated strings*/
+StrPair strpair2[] = {{"The pot had a handle", 0}};
+Tests test2("test 2", dict2, 2, strpair2, 1);
+
+/* test 3*/
+const char *dict3[] = {"The"};
+StrPair strpair3[] = {{"The pot had a handle", "The"}};
+Tests test3("test 3", dict3, 1, strpair3, 1);
+
+/* test 4*/
+const char *dict4[] = {"pot"};
+StrPair strpair4[] = {{"The pot had a handle", "pot"}};
+Tests test4("test 4", dict4, 1, strpair4, 1);
+
+/* test 5*/
+const char *dict5[] = {"pot "};
+StrPair strpair5[] = {{"The pot had a handle", "pot "}};
+Tests test5("test 5", dict5, 1, strpair5, 1);
+
+/* test 6*/
+const char *dict6[] = {"ot h"};
+StrPair strpair6[] = {{"The pot had a handle", "ot h"}};
+Tests test6("test 6", dict6, 1, strpair6, 1);
+
+/* test 7*/
+const char *dict7[] = {"andle"};
+StrPair strpair7[] = {{"The pot had a handle", "andle"}};
+Tests test7("test 7", dict7, 1, strpair7, 1);
+
+const char *dict8[] = {"aaab"};
+StrPair strpair8[] = {{"aaaaaaab", "aaab"}};
+Tests test8("test 8", dict8, 1, strpair8, 1);
+
+const char *dict9[] = {"haha", "z"};
+StrPair strpair9[] = {{"aaaaz", "z"}, {"z", "z"}};
+Tests test9("test 9", dict9, 2, strpair9, 2);
+
+/* test the case when input string dosen't contain even a single char
+ * of the pattern in dictionary.
+ */
+const char *dict10[] = {"abc"};
+StrPair strpair10[] = {{"cde", 0}};
+Tests test10("test 10", dict10, 1, strpair10, 1);
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Testing cases for first longest match variant (i.e.
+// test ac_match_longest_l())
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+
+// This was actually first motivation for left-longest-match
+const char *dict100[] = {"Mozilla", "Mozilla Mobile"};
+StrPair strpair100[] = {{"User Agent containing string Mozilla Mobile", "Mozilla Mobile"}};
+LeftLongestTests test100("l_test 100", dict100, 2, strpair100, 1);
+
+// Dict with single char is tricky
+const char *dict101[] = {"a", "abc"};
+StrPair strpair101[] = {{"abcdef", "abc"}};
+LeftLongestTests test101("l_test 101", dict101, 2, strpair101, 1);
+
+// Testing case with partially overlapping patterns. The purpose is to
+// check if the fail-link leading from terminal state is correct.
+//
+// The fail-link leading from terminal-state does not matter in
+// match-first-occurrence variant, as it stop when a terminal is hit.
+//
+const char *dict102[] = {"abc", "bcdef"};
+StrPair strpair102[] = {{"abcdef", "bcdef"}};
+LeftLongestTests test102("l_test 102", dict102, 2, strpair102, 1);
diff --git a/modules/policy/lua-aho-corasick/tests/dict/README.txt b/modules/policy/lua-aho-corasick/tests/dict/README.txt
new file mode 100644
index 0000000..cd50b41
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/dict/README.txt
@@ -0,0 +1 @@
+This directory contains pattern set of benchmark purpose.
diff --git a/modules/policy/lua-aho-corasick/tests/dict/dict1.txt b/modules/policy/lua-aho-corasick/tests/dict/dict1.txt
new file mode 100644
index 0000000..94085a9
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/dict/dict1.txt
@@ -0,0 +1,11 @@
+false_return@
+forloop#haha
+wtfprogram
+mmaporunmap
+ThIs?Module!IsEssential
+struct rtlwtf
+gettIMEOfdayWrong
+edistribution_and_use_in_@source
+Copyright~#@
+while {!
+!%SQLinje
diff --git a/modules/policy/lua-aho-corasick/tests/load_ac_test.lua b/modules/policy/lua-aho-corasick/tests/load_ac_test.lua
new file mode 100644
index 0000000..7fb7db9
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/load_ac_test.lua
@@ -0,0 +1,82 @@
+-- This script is to test load_ac.lua
+--
+-- Some notes:
+-- 1. The purpose of this script is not to check if the libac.so work
+-- properly, it is to check if there are something stupid in load_ac.lua
+--
+-- 2. There are bunch of collectgarbage() calls, the purpose is to make
+-- sure the shared lib is not unloaded after GC.
+
+-- load_ac.lua looks up libac.so via package.cpath rather than LD_LIBRARY_PATH,
+-- prepend (instead of appending) some insane paths here to see if it quit
+-- prematurely.
+--
+package.cpath = ".;./?.so;" .. package.cpath
+
+local ac = require "load_ac"
+
+local ac_create = ac.create_ac
+local ac_match = ac.match
+local string_fmt = string.format
+local string_sub = string.sub
+
+local err_cnt = 0
+local function mytest(testname, dict, match, notmatch)
+ print(">Testing ", testname)
+
+ io.write(string_fmt("Dictionary: "));
+ for i=1, #dict do
+ io.write(string_fmt("%s, ", dict[i]))
+ end
+ print ""
+
+ local ac_inst = ac_create(dict);
+ collectgarbage()
+ for i=1, #match do
+ local str = match[i]
+ io.write(string_fmt("Matching %s, ", str))
+ local b = ac_match(ac_inst, str)
+ if b then
+ print "pass"
+ else
+ err_cnt = err_cnt + 1
+ print "fail"
+ end
+ collectgarbage()
+ end
+
+ if notmatch == nil then
+ return
+ end
+
+ collectgarbage()
+
+ for i = 1, #notmatch do
+ local str = notmatch[i]
+ io.write(string_fmt("*Matching %s, ", str))
+ local r = ac_match(ac_inst, str)
+ if r then
+ err_cnt = err_cnt + 1
+ print("fail")
+ else
+ print("succ")
+ end
+ collectgarbage()
+ end
+ ac_inst = nil
+ collectgarbage()
+end
+
+print("")
+print("====== Test to see if load_ac.lua works properly ========")
+
+mytest("test1",
+ {"he", "she", "his", "her", "str\0ing"},
+ -- matching cases
+ { "he", "she", "his", "hers", "ahe", "shhe", "shis2", "ahhe", "str\0ing" },
+
+ -- not matching case
+ {"str\0", "str"}
+ )
+
+os.exit((err_cnt == 0) and 0 or 1)
diff --git a/modules/policy/lua-aho-corasick/tests/lua_test.lua b/modules/policy/lua-aho-corasick/tests/lua_test.lua
new file mode 100644
index 0000000..cfe178f
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/lua_test.lua
@@ -0,0 +1,67 @@
+-- This script is to test ahocorasick.so not libac.so
+--
+local ac = require "ahocorasick"
+
+local ac_create = ac.create
+local ac_match = ac.match
+local string_fmt = string.format
+local string_sub = string.sub
+
+local err_cnt = 0
+local function mytest(testname, dict, match, notmatch)
+ print(">Testing ", testname)
+
+ io.write(string_fmt("Dictionary: "));
+ for i=1, #dict do
+ io.write(string_fmt("%s, ", dict[i]))
+ end
+ print ""
+
+ local ac_inst = ac_create(dict);
+ for i=1, #match do
+ local str = match[i][1]
+ local substr = match[i][2]
+ io.write(string_fmt("Matching %s, ", str))
+ local b, e = ac_match(ac_inst, str)
+ if b and e and (string_sub(str, b+1, e+1) == substr) then
+ print "pass"
+ else
+ err_cnt = err_cnt + 1
+ print "fail"
+ end
+ --print("gc is called")
+ collectgarbage()
+ end
+
+ if notmatch == nil then
+ return
+ end
+
+ for i = 1, #notmatch do
+ local str = notmatch[i]
+ io.write(string_fmt("*Matching %s, ", str))
+ local r = ac_match(ac_inst, str)
+ if r then
+ err_cnt = err_cnt + 1
+ print("fail")
+ else
+ print("succ")
+ end
+ collectgarbage()
+ end
+end
+
+mytest("test1",
+ {"he", "she", "his", "her", "str\0ing"},
+ -- matching cases
+ { {"he", "he"}, {"she", "she"}, {"his", "his"}, {"hers", "he"},
+ {"ahe", "he"}, {"shhe", "he"}, {"shis2", "his"}, {"ahhe", "he"},
+ {"str\0ing", "str\0ing"}
+ },
+
+ -- not matching case
+ {"str\0", "str"}
+
+ )
+
+os.exit((err_cnt == 0) and 0 or 1)
diff --git a/modules/policy/lua-aho-corasick/tests/test_base.hpp b/modules/policy/lua-aho-corasick/tests/test_base.hpp
new file mode 100644
index 0000000..7758371
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/test_base.hpp
@@ -0,0 +1,60 @@
+#ifndef TEST_BASE_H
+#define TEST_BASE_H
+
+#include <stdio.h>
+#include <string>
+#include <stdint.h>
+
+using namespace std;
+class ACTestBase {
+public:
+ ACTestBase(const char* name) :_banner(name) {}
+ virtual void PrintBanner() {
+ fprintf(stdout, "\n===== %s ====\n", _banner.c_str());
+ }
+
+ virtual bool Run() = 0;
+private:
+ string _banner;
+};
+
+typedef std::pair<const char*, int> StrInfo;
+class BigFileTester {
+public:
+ BigFileTester(const char* filepath);
+ virtual ~BigFileTester() { Cleanup(); }
+
+ bool Run();
+
+protected:
+ virtual buf_header_t* PM_Create(const char** strv, uint32_t* strlenv,
+ uint32_t vect_len) = 0;
+ virtual void PM_Free(buf_header_t*) = 0;
+ virtual bool Run_Helper(buf_header_t* PM) = 0;
+
+ // Return true if the '\0' is valid char of a string.
+ virtual bool Str_C_Style() { return true; }
+
+ bool GenerateKeys();
+ void Cleanup();
+ void PrintStr(FILE*, const char* str, int len);
+
+protected:
+ const char* _filepath;
+ int _fd;
+ vector<StrInfo> _keys;
+ char* _msg;
+ int _msg_len;
+ int _key_num; // number of strings in dictionary
+ int _chunk_sz;
+ int _chunk_num;
+
+ int _max_key_num;
+ int _key_min_len;
+ int _key_max_len;
+};
+
+extern bool Run_AC_Simple_Test();
+extern bool Run_AC_Aggressive_Test(const vector<const char*>& files);
+
+#endif
diff --git a/modules/policy/lua-aho-corasick/tests/test_bigfile.cxx b/modules/policy/lua-aho-corasick/tests/test_bigfile.cxx
new file mode 100644
index 0000000..f189d8d
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/test_bigfile.cxx
@@ -0,0 +1,167 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+#include <string>
+
+#include "ac.h"
+#include "ac_util.hpp"
+#include "test_base.hpp"
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Implementation of BigFileTester
+//
+///////////////////////////////////////////////////////////////////////////
+//
+BigFileTester::BigFileTester(const char* filepath) {
+ _filepath = filepath;
+ _fd = -1;
+ _msg = (char*)MAP_FAILED;
+ _msg_len = 0;
+ _key_num = 0;
+ _chunk_sz = 0;
+ _chunk_num = 0;
+
+ _max_key_num = 100;
+ _key_min_len = 20;
+ _key_max_len = 80;
+}
+
+void
+BigFileTester::Cleanup() {
+ if (_msg != MAP_FAILED) {
+ munmap((void*)_msg, _msg_len);
+ _msg = (char*)MAP_FAILED;
+ _msg_len = 0;
+ }
+
+ if (_fd != -1) {
+ close(_fd);
+ _fd = -1;
+ }
+}
+
+bool
+BigFileTester::GenerateKeys() {
+ int chunk_sz = 4096;
+ int max_key_num = _max_key_num;
+ int key_min_len = _key_min_len;
+ int key_max_len = _key_max_len;
+
+ int t = _msg_len / chunk_sz;
+ int keynum = t > max_key_num ? max_key_num : t;
+
+ if (keynum <= 4) {
+ // file is too small
+ return false;
+ }
+ chunk_sz = _msg_len / keynum;
+ _chunk_sz = chunk_sz;
+
+ // For each chunck, "randomly" grab a sub-string searving
+ // as key.
+ int random_ofst[] = { 12, 30, 23, 15 };
+ int rofstsz = sizeof(random_ofst)/sizeof(random_ofst[0]);
+ int ofst = 0;
+ const char* msg = _msg;
+ _chunk_num = keynum - 1;
+ for (int idx = 0, e = _chunk_num; idx < e; idx++) {
+ const char* key = msg + ofst + idx % rofstsz;
+ int key_len = key_min_len + idx % (key_max_len - key_min_len);
+ _keys.push_back(StrInfo(key, key_len));
+ ofst += chunk_sz;
+ }
+ return true;
+}
+
+bool
+BigFileTester::Run() {
+ // Step 1: Bring the file into memory
+ fprintf(stdout, "Testing using file '%s'...\n", _filepath);
+
+ int fd = _fd = ::open(_filepath, O_RDONLY);
+ if (fd == -1) {
+ perror("open");
+ return false;
+ }
+
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ perror("fstat");
+ return false;
+ }
+
+ if (!S_ISREG (sb.st_mode)) {
+ fprintf(stderr, "%s is not regular file\n", _filepath);
+ return false;
+ }
+
+ int ten_M = 1024 * 1024 * 10;
+ int map_sz = _msg_len = sb.st_size > ten_M ? ten_M : sb.st_size;
+ char* p = _msg =
+ (char*)mmap (0, map_sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (p == MAP_FAILED) {
+ perror("mmap");
+ return false;
+ }
+
+ // Get rid of '\0' if we are picky at it.
+ if (Str_C_Style()) {
+ for (int i = 0; i < map_sz; i++) { if (!p[i]) p[i] = 'a'; }
+ p[map_sz - 1] = 0;
+ }
+
+ // Step 2: "Fabricate" some keys from the file.
+ if (!GenerateKeys()) {
+ close(fd);
+ return false;
+ }
+
+ // Step 3: Create PM instance
+ const char** keys = new const char*[_keys.size()];
+ unsigned int* keylens = new unsigned int[_keys.size()];
+
+ int i = 0;
+ for (vector<StrInfo>::iterator si = _keys.begin(), se = _keys.end();
+ si != se; si++, i++) {
+ const StrInfo& strinfo = *si;
+ keys[i] = strinfo.first;
+ keylens[i] = strinfo.second;
+ }
+
+ buf_header_t* PM = PM_Create(keys, keylens, i);
+ delete[] keys;
+ delete[] keylens;
+
+ // Step 4: Run testing
+ bool res = Run_Helper(PM);
+ PM_Free(PM);
+
+ // Step 5: Clanup
+ munmap(p, map_sz);
+ _msg = (char*)MAP_FAILED;
+ close(fd);
+ _fd = -1;
+
+ fprintf(stdout, "%s\n", res ? "succ" : "fail");
+ return res;
+}
+
+void
+BigFileTester::PrintStr(FILE* f, const char* str, int len) {
+ fprintf(f, "{");
+ for (int i = 0; i < len; i++) {
+ unsigned char c = str[i];
+ if (isprint(c))
+ fprintf(f, "'%c', ", c);
+ else
+ fprintf(f, "%#x, ", c);
+ }
+ fprintf(f, "}");
+};
diff --git a/modules/policy/lua-aho-corasick/tests/test_main.cxx b/modules/policy/lua-aho-corasick/tests/test_main.cxx
new file mode 100644
index 0000000..b4f5225
--- /dev/null
+++ b/modules/policy/lua-aho-corasick/tests/test_main.cxx
@@ -0,0 +1,33 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+#include <string>
+#include "ac.h"
+#include "ac_util.hpp"
+#include "test_base.hpp"
+
+using namespace std;
+
+
+/////////////////////////////////////////////////////////////////////////
+//
+// Simple (yet maybe tricky) testings
+//
+/////////////////////////////////////////////////////////////////////////
+//
+int
+main (int argc, char** argv) {
+ bool succ = Run_AC_Simple_Test();
+
+ vector<const char*> files;
+ for (int i = 1; i < argc; i++) { files.push_back(argv[i]); }
+ succ = Run_AC_Aggressive_Test(files) && succ;
+
+ return succ ? 0 : -1;
+};
diff --git a/modules/policy/noipv6.test.integr/broken-ipv6.rpl b/modules/policy/noipv6.test.integr/broken-ipv6.rpl
new file mode 100644
index 0000000..499974d
--- /dev/null
+++ b/modules/policy/noipv6.test.integr/broken-ipv6.rpl
@@ -0,0 +1,46 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test that IPv6 is not used by kresd.
+
+RANGE_BEGIN 0 100
+ ADDRESS ::1:2:3:4
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.test.org A
+SECTION ANSWER
+www.test.org 3600 A 4.3.2.1
+ENTRY_END
+
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.test.org A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.test.org A
+SECTION ANSWER
+www.test.org 3600 A 4.3.2.1
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/policy/noipv6.test.integr/deckard.yaml b/modules/policy/noipv6.test.integr/deckard.yaml
new file mode 100644
index 0000000..c353b1c
--- /dev/null
+++ b/modules/policy/noipv6.test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/policy/noipv6.test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/policy/noipv6.test.integr/kresd_config.j2 b/modules/policy/noipv6.test.integr/kresd_config.j2
new file mode 100644
index 0000000..56cdb01
--- /dev/null
+++ b/modules/policy/noipv6.test.integr/kresd_config.j2
@@ -0,0 +1,50 @@
+{% raw %}
+net.ipv6 = false
+policy.add(policy.all(policy.STUB({ '::1:2:3:4', '1.2.3.4' })))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/policy/noipvx.test.integr/broken-ipvx.rpl b/modules/policy/noipvx.test.integr/broken-ipvx.rpl
new file mode 100644
index 0000000..9bb9a8c
--- /dev/null
+++ b/modules/policy/noipvx.test.integr/broken-ipvx.rpl
@@ -0,0 +1,34 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test that neither IPv6 nor IPv4 is used by kresd :-)
+
+RANGE_BEGIN 0 100
+ ADDRESS ::1:2:3:4
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.test.org A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.test.org A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/policy/noipvx.test.integr/deckard.yaml b/modules/policy/noipvx.test.integr/deckard.yaml
new file mode 100644
index 0000000..a71a56e
--- /dev/null
+++ b/modules/policy/noipvx.test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/policy/noipvx.test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/policy/noipvx.test.integr/kresd_config.j2 b/modules/policy/noipvx.test.integr/kresd_config.j2
new file mode 100644
index 0000000..4b5b576
--- /dev/null
+++ b/modules/policy/noipvx.test.integr/kresd_config.j2
@@ -0,0 +1,51 @@
+{% raw %}
+net.ipv4 = false
+net.ipv6 = false
+policy.add(policy.all(policy.STUB({ '::1:2:3:4', '1.2.3.4' })))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/policy/policy.lua b/modules/policy/policy.lua
new file mode 100644
index 0000000..6e9492f
--- /dev/null
+++ b/modules/policy/policy.lua
@@ -0,0 +1,756 @@
+local kres = require('kres')
+local ffi = require('ffi')
+
+local todname = kres.str2dname -- not available during module load otherwise
+
+-- Counter of unique rules
+local nextid = 0
+local function getruleid()
+ local newid = nextid
+ nextid = nextid + 1
+ return newid
+end
+
+-- Support for client sockets from inside policy actions
+local socket_client = function () return error("missing luasocket, can't create socket client") end
+local has_socket, socket = pcall(require, 'socket')
+if has_socket then
+ socket_client = function (host, port)
+ local s, err, status
+ if host:find(':') then
+ s, err = socket.udp6()
+ else
+ s, err = socket.udp()
+ end
+ if not s then
+ return nil, err
+ end
+ status, err = s:setpeername(host, port)
+ if not status then
+ return nil, err
+ end
+ return s
+ end
+end
+
+local function addr_split_port(target, default_port)
+ assert(default_port)
+ assert(type(default_port) == 'number')
+ local addr, port = target:match '([^@]*)@?(.*)'
+ local nport
+ if port ~= "" then
+ nport = tonumber(port)
+ if not nport or nport < 1 or nport > 65535 then
+ error('port "'.. port ..'" is not valid')
+ end
+ end
+ return addr, nport or default_port
+end
+
+-- String address@port -> sockaddr.
+local function addr2sock(target, default_port)
+ local addr, port = addr_split_port(target, default_port)
+ local sock = ffi.gc(ffi.C.kr_straddr_socket(addr, port), ffi.C.free);
+ if sock == nil then
+ error("target '"..target..'" is not a valid IP address')
+ end
+ return sock
+end
+
+-- policy functions are defined below
+local policy = {}
+
+function policy.PASS(state, _)
+ return state
+end
+
+-- Mirror request elsewhere, and continue solving
+function policy.MIRROR(target)
+ local addr, port = addr_split_port(target, 53)
+ local sink, err = socket_client(addr, port)
+ if not sink then panic('MIRROR target %s is not a valid: %s', target, err) end
+ return function(state, req)
+ if state == kres.FAIL then return state end
+ local query = req.qsource.packet
+ if query ~= nil then
+ sink:send(ffi.string(query.wire, query.size))
+ end
+ return -- Chain action to next
+ end
+end
+
+-- Override the list of nameservers (forwarders)
+local function set_nslist(qry, list)
+ local ns_i = 0
+ for _, ns in ipairs(list) do
+ -- kr_nsrep_set() can return kr_error(ENOENT), it's OK
+ if ffi.C.kr_nsrep_set(qry, ns_i, ns) == 0 then
+ ns_i = ns_i + 1
+ end
+ end
+ -- If less than maximum NSs, insert guard to terminate the list
+ if ns_i < 3 then
+ assert(ffi.C.kr_nsrep_set(qry, ns_i, nil) == 0);
+ end
+ if ns_i == 0 then
+ -- would use assert() but don't want to compose the message if not triggered
+ error('no usable address in NS set (check net.ipv4 and '
+ .. 'net.ipv6 config):\n' .. table_print(list, 2))
+ end
+end
+
+-- Forward request, and solve as stub query
+function policy.STUB(target)
+ local list = {}
+ if type(target) == 'table' then
+ for _, v in pairs(target) do
+ table.insert(list, addr2sock(v, 53))
+ assert(#list <= 4, 'at most 4 STUB targets are supported')
+ end
+ else
+ table.insert(list, addr2sock(target, 53))
+ end
+ return function(state, req)
+ local qry = req:current()
+ -- Switch mode to stub resolver, do not track origin zone cut since it's not real authority NS
+ qry.flags.STUB = true
+ qry.flags.ALWAYS_CUT = false
+ set_nslist(qry, list)
+ return state
+ end
+end
+
+-- Forward request and all subrequests to upstream; validate answers
+function policy.FORWARD(target)
+ local list = {}
+ if type(target) == 'table' then
+ for _, v in pairs(target) do
+ table.insert(list, addr2sock(v, 53))
+ assert(#list <= 4, 'at most 4 FORWARD targets are supported')
+ end
+ else
+ table.insert(list, addr2sock(target, 53))
+ end
+ return function(state, req)
+ local qry = req:current()
+ req.options.FORWARD = true
+ req.options.NO_MINIMIZE = true
+ qry.flags.FORWARD = true
+ qry.flags.ALWAYS_CUT = false
+ qry.flags.NO_MINIMIZE = true
+ qry.flags.AWAIT_CUT = true
+ set_nslist(qry, list)
+ return state
+ end
+end
+
+-- object must be non-empty string or non-empty table of non-empty strings
+local function is_nonempty_string_or_table(object)
+ if type(object) == 'string' then
+ return #object ~= 0
+ elseif type(object) ~= 'table' or not next(object) then
+ return false
+ end
+ for _, val in pairs(object) do
+ if type(val) ~= 'string' or #val == 0 then
+ return false
+ end
+ end
+ return true
+end
+
+local function insert_from_string_or_table(source, destination)
+ if type(source) == 'table' then
+ for _, v in pairs(source) do
+ table.insert(destination, v)
+ end
+ else
+ table.insert(destination, source)
+ end
+end
+
+-- Check for allowed authentication types and return type for the current target
+local function tls_forward_target_authtype(idx, target)
+ if (target.pin_sha256 and not (target.ca_file or target.hostname or target.insecure)) then
+ if not is_nonempty_string_or_table(target.pin_sha256) then
+ error('TLS_FORWARD target authentication is invalid at position '
+ .. idx .. '; pin_sha256 must be string or list of strings')
+ end
+ return 'pin_sha256'
+ elseif (target.insecure and not (target.ca_file or target.hostname or target.pin_sha256)) then
+ return 'insecure'
+ elseif (target.hostname and not (target.insecure or target.pin_sha256)) then
+ if not (is_nonempty_string_or_table(target.hostname)) then
+ error('TLS_FORWARD target authentication is invalid at position '
+ .. idx .. '; hostname must be string or list of strings')
+ end
+ -- if target.ca_file is empty, system CA will be used
+ return 'cert'
+ else
+ error('TLS_FORWARD authentication options at position ' .. idx
+ .. ' are invalid; specify one of: pin_sha256 / hostname [+ca_file] / insecure')
+ end
+end
+
+local function tls_forward_target_check_syntax(idx, list_entry)
+ if type(list_entry) ~= 'table' then
+ error('TLS_FORWARD target must be a non-empty table (found '
+ .. type(list_entry) .. ' at position ' .. idx .. ')')
+ end
+ if type(list_entry[1]) ~= 'string' then
+ error('TLS_FORWARD target must start with an IP address (found '
+ .. type(list_entry[1]) .. ' at the beginning of target position ' .. idx .. ')')
+ end
+end
+
+-- Forward request and all subrequests to upstream over TLS; validate answers
+function policy.TLS_FORWARD(target)
+ local sockaddr_c_list = {}
+ local sockaddr_config = {} -- items: { string_addr=<addr string>, auth_type=<auth type> }
+ local ca_files = {}
+ local hostnames = {}
+ local pins = {}
+ if type(target) ~= 'table' or #target < 1 then
+ error('TLS_FORWARD argument must be a non-empty table')
+ end
+ for idx, upstream_list_entry in pairs(target) do
+ tls_forward_target_check_syntax(idx, upstream_list_entry)
+ local auth_type = tls_forward_target_authtype(idx, upstream_list_entry)
+ local string_addr = upstream_list_entry[1]
+ local sockaddr_c = addr2sock(string_addr, 853)
+ local sockaddr_lua = ffi.string(sockaddr_c, ffi.C.kr_sockaddr_len(sockaddr_c))
+ if sockaddr_config[sockaddr_lua] then
+ error('TLS_FORWARD configuration cannot declare two configs for IP address ' .. string_addr)
+ end
+ table.insert(sockaddr_c_list, sockaddr_c)
+ sockaddr_config[sockaddr_lua] = {string_addr=string_addr, auth_type=auth_type}
+ if auth_type == 'cert' then
+ ca_files[sockaddr_lua] = {}
+ hostnames[sockaddr_lua] = {}
+ insert_from_string_or_table(upstream_list_entry.ca_file, ca_files[sockaddr_lua])
+ insert_from_string_or_table(upstream_list_entry.hostname, hostnames[sockaddr_lua])
+ elseif auth_type == 'pin_sha256' then
+ pins[sockaddr_lua] = {}
+ insert_from_string_or_table(upstream_list_entry.pin_sha256, pins[sockaddr_lua])
+ elseif auth_type ~= 'insecure' then
+ -- insecure does nothing, user does not want authentication
+ assert(false, 'unsupported auth_type')
+ end
+ end
+
+ -- Update the global table of authentication data only if all checks above passed
+ for sockaddr_lua, config in pairs(sockaddr_config) do
+ assert(#config.string_addr > 0)
+ if config.auth_type == 'insecure' then
+ net.tls_client(config.string_addr)
+ elseif config.auth_type == 'pin_sha256' then
+ assert(#pins[sockaddr_lua] > 0)
+ net.tls_client(config.string_addr, pins[sockaddr_lua])
+ elseif config.auth_type == 'cert' then
+ assert(#hostnames[sockaddr_lua] > 0)
+ net.tls_client(config.string_addr, ca_files[sockaddr_lua], hostnames[sockaddr_lua])
+ else
+ assert(false, 'unsupported auth_type')
+ end
+ end
+
+ return function(state, req)
+ local qry = req:current()
+ req.options.FORWARD = true
+ req.options.NO_MINIMIZE = true
+ qry.flags.FORWARD = true
+ qry.flags.ALWAYS_CUT = false
+ qry.flags.NO_MINIMIZE = true
+ qry.flags.AWAIT_CUT = true
+ req.options.TCP = true
+ qry.flags.TCP = true
+ set_nslist(qry, sockaddr_c_list)
+ return state
+ end
+end
+
+-- Rewrite records in packet
+function policy.REROUTE(tbl, names)
+ -- Import renumbering rules
+ local ren = require('renumber')
+ local prefixes = {}
+ for from, to in pairs(tbl) do
+ table.insert(prefixes, names and ren.name(from, to) or ren.prefix(from, to))
+ end
+ -- Return rule closure
+ return ren.rule(prefixes)
+end
+
+-- Set and clear some query flags
+function policy.FLAGS(opts_set, opts_clear)
+ return function(_, req)
+ local qry = req:current()
+ ffi.C.kr_qflags_set (qry.flags, kres.mk_qflags(opts_set or {}))
+ ffi.C.kr_qflags_clear(qry.flags, kres.mk_qflags(opts_clear or {}))
+ return nil -- chain rule
+ end
+end
+
+local function mkauth_soa(answer, dname, mname)
+ if mname == nil then
+ mname = dname
+ end
+ return answer:put(dname, 10800, answer:qclass(), kres.type.SOA,
+ mname .. '\6nobody\7invalid\0\0\0\0\1\0\0\14\16\0\0\4\176\0\9\58\128\0\0\42\48')
+end
+
+local dname_localhost = todname('localhost.')
+
+-- Rule for localhost. zone; see RFC6303, sec. 3
+local function localhost(_, req)
+ local qry = req:current()
+ local answer = req.answer
+ ffi.C.kr_pkt_make_auth_header(answer)
+
+ local is_exact = ffi.C.knot_dname_is_equal(qry.sname, dname_localhost)
+
+ answer:rcode(kres.rcode.NOERROR)
+ answer:begin(kres.section.ANSWER)
+ if qry.stype == kres.type.AAAA then
+ answer:put(qry.sname, 900, answer:qclass(), kres.type.AAAA,
+ '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1')
+ elseif qry.stype == kres.type.A then
+ answer:put(qry.sname, 900, answer:qclass(), kres.type.A, '\127\0\0\1')
+ elseif is_exact and qry.stype == kres.type.SOA then
+ mkauth_soa(answer, dname_localhost)
+ elseif is_exact and qry.stype == kres.type.NS then
+ answer:put(dname_localhost, 900, answer:qclass(), kres.type.NS, dname_localhost)
+ else
+ answer:begin(kres.section.AUTHORITY)
+ mkauth_soa(answer, dname_localhost)
+ end
+ return kres.DONE
+end
+
+local dname_rev4_localhost = todname('1.0.0.127.in-addr.arpa');
+local dname_rev4_localhost_apex = todname('127.in-addr.arpa');
+
+-- Rule for reverse localhost.
+-- Answer with locally served minimal 127.in-addr.arpa domain, only having
+-- a PTR record in 1.0.0.127.in-addr.arpa, and with 1.0...0.ip6.arpa. zone.
+-- TODO: much of this would better be left to the hints module (or coordinated).
+local function localhost_reversed(_, req)
+ local qry = req:current()
+ local answer = req.answer
+
+ -- classify qry.sname:
+ local is_exact -- exact dname for localhost
+ local is_apex -- apex of a locally-served localhost zone
+ local is_nonterm -- empty non-terminal name
+ if ffi.C.knot_dname_in_bailiwick(qry.sname, todname('ip6.arpa.')) > 0 then
+ -- exact ::1 query (relying on the calling rule)
+ is_exact = true
+ is_apex = true
+ else
+ -- within 127.in-addr.arpa.
+ local labels = ffi.C.knot_dname_labels(qry.sname, nil)
+ if labels == 3 then
+ is_exact = false
+ is_apex = true
+ elseif labels == 4+2 and ffi.C.knot_dname_is_equal(
+ qry.sname, dname_rev4_localhost) then
+ is_exact = true
+ else
+ is_exact = false
+ is_apex = false
+ is_nonterm = ffi.C.knot_dname_in_bailiwick(dname_rev4_localhost, qry.sname) > 0
+ end
+ end
+
+ ffi.C.kr_pkt_make_auth_header(answer)
+ answer:rcode(kres.rcode.NOERROR)
+ answer:begin(kres.section.ANSWER)
+ if is_exact and qry.stype == kres.type.PTR then
+ answer:put(qry.sname, 900, answer:qclass(), kres.type.PTR, dname_localhost)
+ elseif is_apex and qry.stype == kres.type.SOA then
+ mkauth_soa(answer, dname_rev4_localhost_apex, dname_localhost)
+ elseif is_apex and qry.stype == kres.type.NS then
+ answer:put(dname_rev4_localhost_apex, 900, answer:qclass(), kres.type.NS,
+ dname_localhost)
+ else
+ if not is_nonterm then
+ answer:rcode(kres.rcode.NXDOMAIN)
+ end
+ answer:begin(kres.section.AUTHORITY)
+ mkauth_soa(answer, dname_rev4_localhost_apex, dname_localhost)
+ end
+ return kres.DONE
+end
+
+-- All requests
+function policy.all(action)
+ return function(_, _) return action end
+end
+
+-- Requests which QNAME matches given zone list (i.e. suffix match)
+function policy.suffix(action, zone_list)
+ local AC = require('ahocorasick')
+ local tree = AC.create(zone_list)
+ return function(_, query)
+ local match = AC.match(tree, query:name(), false)
+ if match ~= nil then
+ return action
+ end
+ return nil
+ end
+end
+
+-- Check for common suffix first, then suffix match (specialized version of suffix match)
+function policy.suffix_common(action, suffix_list, common_suffix)
+ local common_len = string.len(common_suffix)
+ local suffix_count = #suffix_list
+ return function(_, query)
+ -- Preliminary check
+ local qname = query:name()
+ if not string.find(qname, common_suffix, -common_len, true) then
+ return nil
+ end
+ -- String match
+ for i = 1, suffix_count do
+ local zone = suffix_list[i]
+ if string.find(qname, zone, -string.len(zone), true) then
+ return action
+ end
+ end
+ return nil
+ end
+end
+
+-- Filter QNAME pattern
+function policy.pattern(action, pattern)
+ return function(_, query)
+ if string.find(query:name(), pattern) then
+ return action
+ end
+ return nil
+ end
+end
+
+local function rpz_parse(action, path)
+ local rules = {}
+ local action_map = {
+ -- RPZ Policy Actions
+ ['\0'] = action,
+ ['\1*\0'] = action, -- deviates from RPZ spec
+ ['\012rpz-passthru\0'] = policy.PASS, -- the grammar...
+ ['\008rpz-drop\0'] = policy.DROP,
+ ['\012rpz-tcp-only\0'] = policy.TC,
+ -- Policy triggers @NYI@
+ }
+ local parser = require('zonefile').new()
+ if not parser:open(path) then error(string.format('failed to parse "%s"', path)) end
+ while parser:parse() do
+ local name = ffi.string(parser.r_owner, parser.r_owner_length)
+ local name_action = ffi.string(parser.r_data, parser.r_data_length)
+ rules[name] = action_map[name_action]
+ -- Warn when NYI
+ if #name > 1 and not action_map[name_action] then
+ print(string.format('[ rpz ] %s:%d: unsupported policy action', path, tonumber(parser.line_counter)))
+ end
+ end
+ return rules
+end
+
+-- RPZ policy set
+-- Create RPZ from zone file
+function policy.rpz(action, path)
+ local rules = rpz_parse(action, path)
+ collectgarbage()
+ return function(_, query)
+ local label = query:name()
+ local rule = rules[label]
+ while rule == nil and string.len(label) > 0 do
+ label = string.sub(label, string.byte(label) + 2)
+ rule = rules['\1*'..label]
+ end
+ return rule
+ end
+end
+
+function policy.DENY_MSG(msg)
+ if msg and (type(msg) ~= 'string' or #msg >= 255) then
+ error('DENY_MSG: optional msg must be string shorter than 256 characters')
+ end
+
+ return function (_, req)
+ -- Write authority information
+ local answer = req.answer
+ ffi.C.kr_pkt_make_auth_header(answer)
+ answer:rcode(kres.rcode.NXDOMAIN)
+ answer:begin(kres.section.AUTHORITY)
+ mkauth_soa(answer, answer:qname())
+ if msg then
+ answer:begin(kres.section.ADDITIONAL)
+ answer:put('\11explanation\7invalid', 10800, answer:qclass(), kres.type.TXT,
+ string.char(#msg) .. msg)
+
+ end
+ return kres.DONE
+ end
+end
+policy.DENY = policy.DENY_MSG() -- compatibility with < 2.0
+
+function policy.DROP(_, _)
+ return kres.FAIL
+end
+
+function policy.REFUSE(_, req)
+ local answer = req.answer
+ answer:rcode(kres.rcode.REFUSED)
+ answer:ad(false)
+ return kres.DONE
+end
+
+function policy.TC(state, req)
+ local answer = req.answer
+ if answer.max_size ~= 65535 then
+ answer:tc(1) -- ^ Only UDP queries
+ answer:ad(false)
+ return kres.DONE
+ else
+ return state
+ end
+end
+
+function policy.QTRACE(_, req)
+ local qry = req:current()
+ req.options.TRACE = true
+ qry.flags.TRACE = true
+ return -- this allows to continue iterating over policy list
+end
+
+-- Evaluate packet in given rules to determine policy action
+function policy.evaluate(rules, req, query, state)
+ for i = 1, #rules do
+ local rule = rules[i]
+ if not rule.suspended then
+ local action = rule.cb(req, query)
+ if action ~= nil then
+ rule.count = rule.count + 1
+ local next_state = action(state, req)
+ if next_state then -- Not a chain rule,
+ return next_state -- stop on first match
+ end
+ end
+ end
+ end
+ return
+end
+
+-- Top-down policy list walk until we hit a match
+-- the caller is responsible for reordering policy list
+-- from most specific to least specific.
+-- Some rules may be chained, in this case they are evaluated
+-- as a dependency chain, e.g. r1,r2,r3 -> r3(r2(r1(state)))
+policy.layer = {
+ begin = function(state, req)
+ -- Don't act on "resolved" cases.
+ if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
+
+ req = kres.request_t(req)
+ return policy.evaluate(policy.rules, req, req:current(), state) or
+ policy.evaluate(policy.special_names, req, req:current(), state) or
+ state
+ end,
+ finish = function(state, req)
+ -- Don't act on "resolved" cases.
+ if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
+
+ req = kres.request_t(req)
+ return policy.evaluate(policy.postrules, req, req:current(), state) or state
+ end
+}
+
+-- Add rule to policy list
+function policy.add(rule, postrule)
+ -- Compatibility with 1.0.0 API
+ -- it will be dropped in 1.2.0
+ if rule == policy then
+ rule = postrule
+ postrule = nil
+ end
+ -- End of compatibility shim
+ local desc = {id=getruleid(), cb=rule, count=0}
+ table.insert(postrule and policy.postrules or policy.rules, desc)
+ return desc
+end
+
+-- Remove rule from a list
+local function delrule(rules, id)
+ for i, r in ipairs(rules) do
+ if r.id == id then
+ table.remove(rules, i)
+ return true
+ end
+ end
+ return false
+end
+
+-- Delete rule from policy list
+function policy.del(id)
+ if not delrule(policy.rules, id) then
+ if not delrule(policy.postrules, id) then
+ return false
+ end
+ end
+ return true
+end
+
+-- Convert list of string names to domain names
+function policy.todnames(names)
+ for i, v in ipairs(names) do
+ names[i] = kres.str2dname(v)
+ end
+ return names
+end
+
+-- RFC1918 Private, local, broadcast, test and special zones
+-- Considerations: RFC6761, sec 6.1.
+-- https://www.iana.org/assignments/locally-served-dns-zones
+local private_zones = {
+ -- RFC6303
+ '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.',
+ '0.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.',
+ -- RFC7793
+ '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.',
+
+ -- RFC6303
+ -- localhost_reversed handles ::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.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.',
+}
+policy.todnames(private_zones)
+
+-- @var Default rules
+policy.rules = {}
+policy.postrules = {}
+policy.special_names = {
+ {
+ cb=policy.suffix_common(policy.DENY_MSG(
+ 'Blocking is mandated by standards, see references on '
+ .. 'https://www.iana.org/assignments/'
+ .. 'locally-served-dns-zones/locally-served-dns-zones.xhtml'),
+ private_zones, todname('arpa.')),
+ count=0
+ },
+ {
+ cb=policy.suffix(policy.DENY_MSG(
+ 'Blocking is mandated by standards, see references on '
+ .. 'https://www.iana.org/assignments/'
+ .. 'special-use-domain-names/special-use-domain-names.xhtml'),
+ {
+ todname('test.'),
+ todname('onion.'),
+ todname('invalid.'),
+ }),
+ count=0
+ },
+ {
+ cb=policy.suffix(localhost, {dname_localhost}),
+ count=0
+ },
+ {
+ cb=policy.suffix_common(localhost_reversed, {
+ todname('127.in-addr.arpa.'),
+ todname('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.')},
+ todname('arpa.')),
+ count=0
+ },
+}
+
+return policy
diff --git a/modules/policy/policy.mk b/modules/policy/policy.mk
new file mode 100644
index 0000000..98c9f88
--- /dev/null
+++ b/modules/policy/policy.mk
@@ -0,0 +1,15 @@
+AHOCORASICK_DIR = modules/policy/lua-aho-corasick/
+
+policy_SOURCES := policy.lua
+policy_DEPEND := $(AHOCORASICK_DIR)ahocorasick$(LIBEXT)
+$(call make_lua_module,policy)
+
+policy-clean:
+ $(MAKE) -C $(AHOCORASICK_DIR) clean
+$(AHOCORASICK_DIR)ahocorasick$(LIBEXT): $(AHOCORASICK_DIR)Makefile
+ $(MAKE) -C $(AHOCORASICK_DIR) ahocorasick$(LIBEXT) CXXFLAGS="$(lua_CFLAGS)"
+
+policy-install: ahocorasick-install
+ahocorasick-install: $(AHOCORASICK_DIR)ahocorasick$(LIBEXT) $(DESTDIR)$(MODULEDIR)
+ $(INSTALL) -m 755 $(AHOCORASICK_DIR)ahocorasick$(LIBEXT) $(DESTDIR)$(MODULEDIR)
+
diff --git a/modules/policy/policy.test.lua b/modules/policy/policy.test.lua
new file mode 100644
index 0000000..8780caa
--- /dev/null
+++ b/modules/policy/policy.test.lua
@@ -0,0 +1,52 @@
+-- setup resolver
+-- policy module should be loaded by default, do not load it explicitly
+
+-- test for default configuration
+local function test_tls_forward()
+ boom(policy.TLS_FORWARD, {}, 'TLS_FORWARD without arguments')
+ boom(policy.TLS_FORWARD, {'1'}, 'TLS_FORWARD with non-table argument')
+ boom(policy.TLS_FORWARD, {{}}, 'TLS_FORWARD with empty table')
+ boom(policy.TLS_FORWARD, {{{}}}, 'TLS_FORWARD with empty target table')
+ boom(policy.TLS_FORWARD, {{{bleble=''}}}, 'TLS_FORWARD with invalid parameters in table')
+
+ boom(policy.TLS_FORWARD, {{'1'}}, 'TLS_FORWARD with invalid IP address')
+ -- boom(policy.TLS_FORWARD, {{{'::1', bleble=''}}}, 'TLS_FORWARD with valid IP and invalid parameters')
+ boom(policy.TLS_FORWARD, {{{'127.0.0.1'}}}, 'TLS_FORWARD with missing auth parameters')
+
+ ok(policy.TLS_FORWARD({{'127.0.0.1', insecure=true}}), 'TLS_FORWARD with no authentication')
+ boom(policy.TLS_FORWARD, {{{'100:dead::', insecure=true},
+ {'100:DEAD:0::', insecure=true}
+ }}, 'TLS_FORWARD with duplicate IP addresses is not allowed')
+ ok(policy.TLS_FORWARD({{'100:dead::', insecure=true},
+ {'100:dead::@443', insecure=true}
+ }), 'TLS_FORWARD with duplicate IP addresses but different ports is allowed')
+ ok(policy.TLS_FORWARD({{'100:dead::', insecure=true},
+ {'100:beef::', insecure=true}
+ }), 'TLS_FORWARD with different IPv6 addresses is allowed')
+ ok(policy.TLS_FORWARD({{'127.0.0.1', insecure=true},
+ {'127.0.0.2', insecure=true}
+ }), 'TLS_FORWARD with different IPv4 addresses is allowed')
+
+ boom(policy.TLS_FORWARD, {{{'::1', pin_sha256=''}}}, 'TLS_FORWARD with empty pin_sha256')
+ -- boom(policy.TLS_FORWARD, {{{'::1', pin_sha256='Ä'}}}, 'TLS_FORWARD with bad pin_sha256')
+ ok(policy.TLS_FORWARD({
+ {'::1', pin_sha256='ZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NQ=='}
+ }), 'TLS_FORWARD with base64 pin_sha256')
+ ok(policy.TLS_FORWARD({
+ {'::1', pin_sha256={
+ 'ZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NQ==',
+ 'MTcwYWUzMGNjZDlmYmE2MzBhZjhjZGE2ODQxZTAwYzZiNjU3OWNlYzc3NmQ0MTllNzAyZTIwYzY5YzQ4OGZmOA=='
+ }}}), 'TLS_FORWARD with table of pins')
+
+ -- ok(policy.TLS_FORWARD({{'::1', hostname='test.', ca_file='/tmp/ca.crt'}}), 'TLS_FORWARD with hostname + CA cert')
+ ok(policy.TLS_FORWARD({{'::1', hostname='test.'}}), 'TLS_FORWARD with just hostname (use system CA store)')
+ boom(policy.TLS_FORWARD, {{{'::1', ca_file='/tmp/ca.crt'}}}, 'TLS_FORWARD with just CA cert')
+ boom(policy.TLS_FORWARD, {{{'::1', hostname='', ca_file='/tmp/ca.crt'}}}, 'TLS_FORWARD with empty hostname + CA cert')
+ boom(policy.TLS_FORWARD, {{{'::1', hostname='test.', ca_file='/dev/a_file_which_surely_does_NOT_exist!'}}},
+ 'TLS_FORWARD with hostname + unreadable CA cert')
+
+end
+
+return {
+ test_tls_forward
+}
diff --git a/modules/policy/test.integr/deckard.yaml b/modules/policy/test.integr/deckard.yaml
new file mode 100644
index 0000000..be60e97
--- /dev/null
+++ b/modules/policy/test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/policy/test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/policy/test.integr/kresd_config.j2 b/modules/policy/test.integr/kresd_config.j2
new file mode 100644
index 0000000..9274363
--- /dev/null
+++ b/modules/policy/test.integr/kresd_config.j2
@@ -0,0 +1,49 @@
+{% raw %}
+policy.add(policy.suffix(policy.REFUSE, {todname('refuse.example.com')}))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/policy/test.integr/refuse.rpl b/modules/policy/test.integr/refuse.rpl
new file mode 100644
index 0000000..1d1372b
--- /dev/null
+++ b/modules/policy/test.integr/refuse.rpl
@@ -0,0 +1,24 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test refuse policy
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.refuse.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer
+; AD must not be set in the answer
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+www.refuse.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/predict/README.rst b/modules/predict/README.rst
new file mode 100644
index 0000000..6c4b442
--- /dev/null
+++ b/modules/predict/README.rst
@@ -0,0 +1,51 @@
+.. _mod-predict:
+
+Prefetching records
+-------------------
+
+The module refreshes records that are about to expire when they're used (having less than 1% of original TTL).
+This improves latency for frequently used records, as they are fetched in advance.
+
+It is also able to learn usage patterns and repetitive queries that the server makes. For example, if
+it makes a query every day at 18:00, the resolver expects that it is needed by that time and prefetches it
+ahead of time. This is helpful to minimize the perceived latency and keeps the cache hot.
+
+.. tip:: The tracking window and period length determine memory requirements. If you have a server with relatively fast query turnover, keep the period low (hour for start) and shorter tracking window (5 minutes). For personal slower resolver, keep the tracking window longer (i.e. 30 minutes) and period longer (a day), as the habitual queries occur daily. Experiment to get the best results.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ modules = {
+ predict = {
+ window = 15, -- 15 minutes sampling window
+ period = 6*(60/15) -- track last 6 hours
+ }
+ }
+
+Defaults are 15 minutes window, 6 hours period.
+
+.. tip:: Use period 0 to turn off prediction and just do prefetching of expiring records.
+ That works even without the :ref:`stats <mod-stats>` module.
+
+.. note:: Otherwise this module requires :ref:`stats <mod-stats>` module and loads it if not present.
+
+Exported metrics
+^^^^^^^^^^^^^^^^
+
+To visualize the efficiency of the predictions, the module exports following statistics.
+
+* ``predict.epoch`` - current prediction epoch (based on time of day and sampling window)
+* ``predict.queue`` - number of queued queries in current window
+* ``predict.learned`` - number of learned queries in current window
+
+
+Properties
+^^^^^^^^^^
+
+.. function:: predict.config({ window = 15, period = 24})
+
+ Reconfigure the predictor to given tracking window and period length. Both parameters are optional.
+ Window length is in minutes, period is a number of windows that can be kept in memory.
+ e.g. if a ``window`` is 15 minutes, a ``period`` of "24" means 6 hours.
diff --git a/modules/predict/predict.lua b/modules/predict/predict.lua
new file mode 100644
index 0000000..846d4ef
--- /dev/null
+++ b/modules/predict/predict.lua
@@ -0,0 +1,186 @@
+-- Speculative prefetching for repetitive and soon-expiring records to reduce latency.
+-- @module predict
+-- @field queue queue of scheduled queries
+-- @field queue_len number of scheduled queries
+-- @field period length of prediction history (number of windows)
+-- @field window length of the prediction window
+local predict = {
+ queue = {},
+ queue_len = 0,
+ batch = 0,
+ period = 24,
+ window = 15,
+ log = {},
+}
+
+
+-- Calculate next sample with jitter [1-2/5 of window]
+local function next_event()
+ local jitter = (predict.window * minute) / 5;
+ return math.random(jitter, 2 * jitter)
+end
+
+-- Calculate current epoch (which window fits current time)
+function predict.epoch()
+ if not predict.period or predict.period <= 1 then return nil end
+ return (os.date('%H')*(60/predict.window) +
+ math.floor(os.date('%M')/predict.window)) % predict.period + 1
+end
+
+-- Resolve queued records and flush the queue
+function predict.drain()
+ local deleted = 0
+ for key, _ in pairs(predict.queue) do
+ local qtype, qname = key:match('(%S*)%s(.*)')
+ resolve(qname, kres.type[qtype], kres.class.IN, {'NO_CACHE'})
+ predict.queue[key] = nil
+ deleted = deleted + 1
+ -- Resolve smaller batches at a time
+ if predict.batch > 0 and deleted >= predict.batch then
+ break
+ end
+ end
+ -- Schedule prefetch of another batch if not complete
+ if predict.ev_drain then event.cancel(predict.ev_drain) end
+ predict.ev_drain = nil
+ if deleted > 0 then
+ predict.ev_drain = event.after((predict.window * 3) * sec, predict.drain)
+ end
+ predict.queue_len = predict.queue_len - deleted
+ stats['predict.queue'] = predict.queue_len
+ collectgarbage('step')
+ return 0
+end
+
+-- Enqueue queries from same format as predict.queue or predict.log
+local function enqueue_from_log(current)
+ if not current then return 0 end
+ local queued = 0
+ for key, val in pairs(current) do
+ if val and not predict.queue[key] then
+ predict.queue[key] = val
+ queued = queued + 1
+ end
+ end
+ return queued
+end
+
+-- Sample current epoch, return number of sampled queries
+function predict.sample(epoch_now)
+ if not epoch_now then return 0, 0 end
+ local current = predict.log[epoch_now] or {}
+ local queries = stats.frequent()
+ stats.clear_frequent()
+ local nr_samples = #queries
+ for i = 1, nr_samples do
+ local entry = queries[i]
+ local key = string.format('%s %s', entry.type, entry.name)
+ current[key] = 1
+ end
+ predict.log[epoch_now] = current
+ return nr_samples
+end
+
+-- Predict queries for the upcoming epoch
+local function generate(epoch_now)
+ if not epoch_now then return 0 end
+ local queued = 0
+ for i = 1, predict.period / 2 - 1 do
+ local current = predict.log[(epoch_now - i - 1) % predict.period + 1]
+ local past = predict.log[(epoch_now - 2*i - 1) % predict.period + 1]
+ if current and past then
+ for k, _ in pairs(current) do
+ if past[k] ~= nil and not predict.queue[k] then
+ queued = queued + 1
+ predict.queue[k] = 1
+ end
+ end
+ end
+ end
+ return queued
+end
+
+function predict.process()
+ -- Start a new epoch, or continue sampling
+ local epoch_now = predict.epoch()
+ local nr_queued = 0
+
+ -- End of epoch
+ if predict.current_epoch ~= epoch_now then
+ stats['predict.epoch'] = epoch_now
+ predict.current_epoch = epoch_now
+ -- enqueue records from upcoming epoch
+ nr_queued = enqueue_from_log(predict.log[epoch_now])
+ -- predict next epoch
+ nr_queued = nr_queued + generate(epoch_now)
+ -- clear log for new epoch
+ predict.log[epoch_now] = {}
+ end
+
+ -- Sample current epoch
+ local nr_learned = predict.sample(epoch_now)
+
+ -- Dispatch predicted queries
+ if nr_queued > 0 then
+ predict.queue_len = predict.queue_len + nr_queued
+ predict.batch = predict.queue_len / 5
+ if not predict.ev_drain then
+ predict.ev_drain = event.after(0, predict.drain)
+ end
+ end
+
+ if predict.ev_sample then event.cancel(predict.ev_sample) end
+ predict.ev_sample = event.after(next_event(), predict.process)
+ if stats then
+ stats['predict.queue'] = predict.queue_len
+ stats['predict.learned'] = nr_learned
+ end
+ collectgarbage()
+end
+
+function predict.init()
+ if predict.window > 0 then
+ predict.current_epoch = predict.epoch()
+ predict.ev_sample = event.after(next_event(), predict.process)
+ end
+end
+
+function predict.deinit()
+ if predict.ev_sample then event.cancel(predict.ev_sample) end
+ if predict.ev_drain then event.cancel(predict.ev_drain) end
+ predict.ev_sample = nil
+ predict.ev_drain = nil
+ predict.log = {}
+ predict.queue = {}
+ predict.queue_len = 0
+ collectgarbage()
+end
+
+function predict.config(config)
+ -- Reconfigure
+ if type(config) ~= 'table' then return end
+ if config.window then predict.window = config.window end
+ if config.period then predict.period = config.period end
+ -- Load dependent modules
+ if (predict.period or 0) ~= 0 and not stats then modules.load('stats') end
+ -- Reinitialize to reset timers
+ predict.deinit()
+ predict.init()
+end
+
+predict.layer = {
+ -- Prefetch all expiring (sub-)queries immediately after the request finishes.
+ -- Doing that immediately is simplest and avoids creating (new) large bursts of activity.
+ finish = function (_, req)
+ req = kres.request_t(req)
+ local qrys = req.rplan.resolved
+ for i = 0, (tonumber(qrys.len) - 1) do -- size_t doesn't work for some reason
+ local qry = qrys.at[i]
+ if qry.flags.EXPIRING == true then
+ resolve(kres.dname2str(qry.sname), qry.stype, qry.sclass, {'NO_CACHE'})
+ end
+ end
+ end
+}
+
+return predict
diff --git a/modules/predict/predict.mk b/modules/predict/predict.mk
new file mode 100644
index 0000000..51a1a6b
--- /dev/null
+++ b/modules/predict/predict.mk
@@ -0,0 +1,2 @@
+predict_SOURCES := predict.lua
+$(call make_lua_module,predict)
diff --git a/modules/predict/tests/predict.test.lua b/modules/predict/tests/predict.test.lua
new file mode 100644
index 0000000..1043104
--- /dev/null
+++ b/modules/predict/tests/predict.test.lua
@@ -0,0 +1,60 @@
+-- setup resolver
+modules = { 'predict', 'stats' }
+
+-- mock global functions
+local resolve_count = 0
+local current_epoch = 0
+
+resolve = function ()
+ resolve_count = resolve_count + 1
+end
+
+stats.frequent = function ()
+ return {
+ {name = 'example.com', type = 'TYPE65535'},
+ {name = 'example.com', type = 'SOA'},
+ }
+end
+
+predict.epoch = function ()
+ return current_epoch % predict.period + 1
+end
+
+-- test if draining of prefetch queue works
+local function test_predict_drain()
+ resolve_count = 0
+ predict.queue_len = 2
+ predict.queue['TYPE65535 example.com'] = 1
+ predict.queue['SOA example.com'] = 1
+ predict.drain()
+ -- test that it attempted to prefetch
+ same(resolve_count, 2, 'attempted to prefetch on drain')
+ same(predict.queue_len, 0, 'prefetch queue empty after drain')
+end
+
+-- test if prediction process works
+local function test_predict_process()
+ -- start new epoch
+ predict.process()
+ same(predict.queue_len, 0, 'first epoch, empty prefetch queue')
+ -- next epoch, still no period for frequent queries
+ current_epoch = current_epoch + 1
+ predict.process()
+ same(predict.queue_len, 0, 'second epoch, empty prefetch queue')
+ -- next epoch, found period
+ current_epoch = current_epoch + 1
+ predict.process()
+ same(predict.queue_len, 2, 'third epoch, prefetching')
+ -- drain works with scheduled prefetches (two batches)
+ resolve_count = 0
+ predict.drain()
+ predict.drain()
+ same(resolve_count, 2, 'attempted to resolve queries in queue')
+ same(predict.queue_len, 0, 'prefetch queue is empty')
+end
+
+-- return test set
+return {
+ test_predict_drain,
+ test_predict_process
+}
diff --git a/modules/prefill/README.rst b/modules/prefill/README.rst
new file mode 100644
index 0000000..e30e0c3
--- /dev/null
+++ b/modules/prefill/README.rst
@@ -0,0 +1,41 @@
+.. _mod-prefill:
+
+Cache prefilling
+----------------
+
+This module provides ability to periodically prefill DNS cache by importing root zone data obtained over HTTPS.
+
+Intended users of this module are big resolver operators which will benefit from decreased latencies and smaller amount of traffic towards DNS root servets.
+
+Example configuration is:
+
+.. code-block:: lua
+
+ modules.load('prefill')
+ prefill.config({
+ ['.'] = {
+ url = 'https://www.internic.net/domain/root.zone',
+ ca_file = '/etc/pki/tls/certs/ca-bundle.crt',
+ interval = 86400 -- seconds
+ }
+ })
+
+This configuration downloads zone file from URL `https://www.internic.net/domain/root.zone` and imports it into cache every 86400 seconds (1 day). The HTTPS connection is authenticated using CA certificate from file `/etc/pki/tls/certs/ca-bundle.crt` and signed zone content is validated using DNSSEC.
+
+Root zone to import must be signed using DNSSEC and the resolver must have valid DNSSEC configuration. (For further details please see :ref:`enabling-dnssec`.)
+
+.. csv-table::
+ :header: "Parameter", "Description"
+
+ "ca_file", "path to CA certificate bundle used to authenticate the HTTPS connection"
+ "interval", "number of seconds between zone data refresh attempts"
+ "url", "URL of a file in :rfc:`1035` zone file format"
+
+Only root zone import is supported at the moment.
+
+Dependencies
+^^^^^^^^^^^^
+
+Depends on the luasec_ library.
+
+.. _luasec: https://luarocks.org/modules/brunoos/luasec
diff --git a/modules/prefill/prefill.lua b/modules/prefill/prefill.lua
new file mode 100644
index 0000000..c573ed9
--- /dev/null
+++ b/modules/prefill/prefill.lua
@@ -0,0 +1,208 @@
+local https = require('ssl.https')
+local ltn12 = require('ltn12')
+local lfs = require('lfs')
+
+local rz_url = "https://www.internic.net/domain/root.zone"
+local rz_local_fname = "root.zone"
+local rz_ca_file = nil
+local rz_event_id = nil
+
+local rz_default_interval = 86400
+local rz_https_fail_interval = 600
+local rz_no_ta_interval = 600
+local rz_cur_interval = rz_default_interval
+local rz_interval_randomizator_limit = 10
+local rz_interval_threshold = 5
+local rz_interval_min = 3600
+
+local prefill = {
+}
+
+
+-- Fetch over HTTPS with peert cert checked
+local function https_fetch(url, ca_file)
+ assert(string.match(url, '^https://'))
+ assert(ca_file)
+
+ local resp = {}
+ local r, c = https.request{
+ url = url,
+ verify = {'peer', 'fail_if_no_peer_cert' },
+ cafile = ca_file,
+ protocol = 'tlsv1_2',
+ sink = ltn12.sink.table(resp),
+ }
+ if r == nil then
+ return r, c
+ end
+ return resp, "[prefill] "..url.." downloaded"
+end
+
+-- Write zone to a file
+local function zone_write(zone, fname)
+ local file, errmsg = io.open(fname, 'w')
+ if not file then
+ error(string.format("[prefill] unable to open file %s (%s)",
+ fname, errmsg))
+ end
+ for i = 1, #zone do
+ local zone_chunk = zone[i]
+ file:write(zone_chunk)
+ end
+ file:close()
+end
+
+local function display_delay(time)
+ local days = math.floor(time / 86400)
+ local hours = math.floor((time % 86400) / 3600)
+ local minutes = math.floor((time % 3600) / 60)
+ local seconds = math.floor(time % 60)
+ if days > 0 then
+ return string.format("%d days %02d hours", days, hours)
+ elseif hours > 0 then
+ return string.format("%02d hours %02d minutes", hours, minutes)
+ elseif minutes > 0 then
+ return string.format("%02d minutes %02d seconds", minutes, seconds)
+ end
+ return string.format("%02d seconds", seconds)
+end
+
+-- returns: number of seconds the file is valid for
+-- 0 indicates immediate download
+local function get_file_ttl(fname)
+ local attrs = lfs.attributes(fname)
+ if attrs then
+ local age = os.time() - attrs.modification
+ return math.max(
+ rz_cur_interval - age,
+ 0)
+ else
+ return 0 -- file does not exist, download now
+ end
+end
+
+local function download(url, fname)
+ log("[prefill] downloading root zone...")
+ local rzone, err = https_fetch(url, rz_ca_file)
+ if rzone == nil then
+ error(string.format("[prefill] fetch of `%s` failed: %s", url, err))
+ end
+
+ log("[prefill] saving root zone...")
+ zone_write(rzone, fname)
+end
+
+local function import(fname)
+ local res = cache.zone_import(fname)
+ if res.code == 1 then -- no TA found, wait
+ error("[prefill] no trust anchor found for root zone, import aborted")
+ elseif res.code == 0 then
+ log("[prefill] root zone successfully parsed, import started")
+ else
+ error(string.format("[prefill] root zone import failed (%s)", res.msg))
+ end
+end
+
+local function timer()
+ local file_ttl = get_file_ttl(rz_local_fname)
+
+ if file_ttl > rz_interval_threshold then
+ log("[prefill] root zone file valid for %s, reusing data from disk",
+ display_delay(file_ttl))
+ else
+ local ok, errmsg = pcall(download, rz_url, rz_local_fname)
+ if not ok then
+ rz_cur_interval = rz_https_fail_interval
+ - math.random(rz_interval_randomizator_limit)
+ log("[prefill] cannot download new zone (%s), "
+ .. "will retry root zone download in %s",
+ errmsg, display_delay(rz_cur_interval))
+ event.reschedule(rz_event_id, rz_cur_interval * sec)
+ return
+ end
+ file_ttl = rz_default_interval
+ end
+ -- file is up to date, import
+ -- import/filter function gets executed after resolver/module
+ local ok, errmsg = pcall(import, rz_local_fname)
+ if not ok then
+ rz_cur_interval = rz_no_ta_interval
+ - math.random(rz_interval_randomizator_limit)
+ log("[prefill] root zone import failed (%s), retry in %s",
+ errmsg, display_delay(rz_cur_interval))
+ else
+ -- re-download before TTL expires
+ rz_cur_interval = (file_ttl - rz_interval_threshold
+ - math.random(rz_interval_randomizator_limit))
+ log("[prefill] root zone refresh in %s",
+ display_delay(rz_cur_interval))
+ end
+ event.reschedule(rz_event_id, rz_cur_interval * sec)
+end
+
+function prefill.init()
+ math.randomseed(os.time())
+end
+
+function prefill.deinit()
+ if rz_event_id then
+ event.cancel(rz_event_id)
+ rz_event_id = nil
+ end
+end
+
+-- process one item from configuration table
+-- right now it supports only root zone because
+-- prefill module uses global variables
+local function config_zone(zone_cfg)
+ if zone_cfg.interval then
+ zone_cfg.interval = tonumber(zone_cfg.interval)
+ if zone_cfg.interval < rz_interval_min then
+ error(string.format('[prefill] refresh interval %d s is too short, '
+ .. 'minimal interval is %d s',
+ zone_cfg.interval, rz_interval_min))
+ end
+ rz_default_interval = zone_cfg.interval
+ rz_cur_interval = zone_cfg.interval
+ end
+
+ if not zone_cfg.ca_file then
+ error('[prefill] option ca_file must point '
+ .. 'to a file with CA certificate(s) in PEM format')
+ end
+ rz_ca_file = zone_cfg.ca_file
+
+ if not zone_cfg.url or not string.match(zone_cfg.url, '^https://') then
+ error('[prefill] option url must contain a '
+ .. 'https:// URL of a zone file')
+ else
+ rz_url = zone_cfg.url
+ end
+end
+
+function prefill.config(config)
+ local root_configured = false
+ if not config or type(config) ~= 'table' then
+ error('[prefill] configuration must be in table '
+ .. '{owner name = {per-zone config}}')
+ end
+ for owner, zone_cfg in pairs(config) do
+ if owner ~= '.' then
+ error('[prefill] only root zone can be imported '
+ .. 'at the moment')
+ else
+ config_zone(zone_cfg)
+ root_configured = true
+ end
+ end
+ if not root_configured then
+ error('[prefill] this module version requires configuration '
+ .. 'for root zone')
+ end
+
+ -- ability to change intervals
+ prefill.deinit()
+ rz_event_id = event.after(0, timer)
+end
+
+return prefill
diff --git a/modules/prefill/prefill.mk b/modules/prefill/prefill.mk
new file mode 100644
index 0000000..7b10ba9
--- /dev/null
+++ b/modules/prefill/prefill.mk
@@ -0,0 +1,2 @@
+prefill_SOURCES := prefill.lua
+$(call make_lua_module,prefill)
diff --git a/modules/priming/README.rst b/modules/priming/README.rst
new file mode 100644
index 0000000..2913684
--- /dev/null
+++ b/modules/priming/README.rst
@@ -0,0 +1,17 @@
+.. _mod-priming:
+
+Priming module
+--------------
+
+The module for Initializing a DNS Resolver with Priming Queries implemented
+according to :rfc:`8109`. Purpose of the module is to keep up-to-date list of
+root DNS servers and associated IP addresses.
+
+Result of successful priming query replaces root hints distributed with
+the resolver software. Unlike other DNS resolvers, Knot Resolver caches
+result of priming query on disk and keeps the data between restarts until
+TTL expires.
+
+This module is enabled by default and it is not recommended to disable it.
+For debugging purposes you may disable the module by appending
+``modules.unload('priming')`` to your configuration.
diff --git a/modules/priming/priming.lua b/modules/priming/priming.lua
new file mode 100644
index 0000000..fed7b9b
--- /dev/null
+++ b/modules/priming/priming.lua
@@ -0,0 +1,129 @@
+-- Module interface
+local ffi = require('ffi')
+
+local priming = {}
+priming.retry_time = 10 * sec -- retry time when priming fail
+
+-- internal state variables and functions
+local internal = {}
+internal.nsset = {} -- set of resolved nameservers
+internal.min_ttl = 0 -- minimal TTL of NS records
+internal.to_resolve = 0 -- number of pending queries to A or AAAA
+internal.prime = {} -- function triggering priming query
+internal.event = nil -- stores event id
+
+-- Copy hints from nsset table to resolver engine
+-- These addresses replace root hints loaded by default from file.
+-- They are stored outside cache and cache flush will not affect them.
+local function publish_hints(nsset)
+ local roothints = kres.context().root_hints
+ -- reset zone cut and clear address list
+ ffi.C.kr_zonecut_set(roothints, kres.str2dname("."))
+ for dname, addrsets in pairs(nsset) do
+ for i = 0, addrsets:rdcount() - 1 do
+ local rdpt = addrsets:rdata_pt(i)
+ ffi.C.kr_zonecut_add(roothints, dname, rdpt.data, rdpt.len)
+ end
+ end
+end
+
+-- Count A and AAAA addresses in nsset
+local function count_addresses(nsset)
+ local count = 0
+ for _, addrset in pairs(nsset) do
+ count = count + addrset:rdcount()
+ end
+ return count
+end
+
+-- Callback for response from A or AAAA query for root nameservers
+-- address is added to table internal.nsset.
+-- When all response is processed internal.nsset is published in resolver engine
+-- luacheck: no unused args
+local function address_callback(pkt, req)
+ pkt = kres.pkt_t(pkt)
+ -- req = kres.request_t(req)
+ if pkt:rcode() ~= kres.rcode.NOERROR then
+ warn("[priming] cannot resolve address '%s', type: %d", kres.dname2str(pkt:qname()), pkt:qtype())
+ else
+ local section = pkt:rrsets(kres.section.ANSWER)
+ for i = 1, #section do
+ local rrset_new = section[i]
+ if rrset_new.type == kres.type.A or rrset_new.type == kres.type.AAAA then
+ local owner = rrset_new:owner()
+ local rrset_comb = internal.nsset[owner]
+ if rrset_comb == nil then
+ rrset_comb = kres.rrset(nil, rrset_new.type)
+ internal.nsset[owner] = rrset_comb
+ end
+ assert(ffi.istype(kres.rrset, rrset_new))
+ rrset_comb:merge_rdata(rrset_new)
+ end
+ end
+ end
+ internal.to_resolve = internal.to_resolve - 1
+ if internal.to_resolve == 0 then
+ if count_addresses(internal.nsset) == 0 then
+ warn("[priming] cannot resolve any root server address, next priming query in %d seconds", priming.retry_time / sec)
+ internal.event = event.after(priming.retry_time, internal.prime)
+ else
+ publish_hints(internal.nsset)
+ if verbose() then
+ log("[priming] triggered priming query, next in %d seconds", internal.min_ttl)
+ end
+ internal.event = event.after(internal.min_ttl * sec, internal.prime)
+ end
+ end
+end
+
+-- Callback for priming query ('.' NS)
+-- For every NS record creates two separate queries for A and AAAA.
+-- These new queries should be resolved from cache.
+-- luacheck: no unused args
+local function priming_callback(pkt, req)
+ pkt = kres.pkt_t(pkt)
+ -- req = kres.request_t(req)
+ if pkt:rcode() ~= kres.rcode.NOERROR then
+ warn("[priming] cannot resolve '.' NS, next priming query in %d seconds", priming.retry_time / sec)
+ internal.event = event.after(priming.retry_time, internal.prime)
+ return nil
+ end
+ local section = pkt:rrsets(kres.section.ANSWER)
+ for i = 1, #section do
+ local rr = section[i]
+ if rr.type == kres.type.NS then
+ internal.min_ttl = math.min(internal.min_ttl, rr:ttl())
+ internal.to_resolve = internal.to_resolve + 2 * rr.rrs.count
+ for k = 0, rr.rrs.count-1 do
+ local nsname_text = rr:tostring(k)
+ resolve(nsname_text, kres.type.A, kres.class.IN, 0, address_callback)
+ resolve(nsname_text, kres.type.AAAA, kres.class.IN, 0, address_callback)
+ end
+ end
+ end
+end
+
+-- trigger priming query
+function internal.prime()
+ internal.min_ttl = math.max(1, cache.max_ttl()) -- sanity check for disabled cache
+ internal.nsset = {}
+ internal.to_resolve = 0
+ resolve(".", kres.type.NS, kres.class.IN, 0, priming_callback)
+end
+
+function priming.init()
+ if internal.event then
+ error("Priming module is already loaded.")
+ else
+ internal.event = event.after(0 , internal.prime)
+ end
+end
+
+function priming.deinit()
+ if internal.event then
+ event.cancel(internal.event)
+ internal.event = nil
+ end
+end
+
+return priming
diff --git a/modules/priming/priming.mk b/modules/priming/priming.mk
new file mode 100644
index 0000000..b5043b1
--- /dev/null
+++ b/modules/priming/priming.mk
@@ -0,0 +1,2 @@
+priming_SOURCES := priming.lua
+$(call make_lua_module,priming)
diff --git a/modules/rebinding/README.rst b/modules/rebinding/README.rst
new file mode 100644
index 0000000..26432e6
--- /dev/null
+++ b/modules/rebinding/README.rst
@@ -0,0 +1,25 @@
+.. _mod-rebinding:
+
+Rebinding protection
+--------------------
+
+This module provides protection from `DNS Rebinding attack`_ by blocking
+answers which cointain IPv4_ or IPv6_ addresses for private use
+(or some other special-use addresses).
+
+To enable this module insert following line into your configuration file:
+
+.. code-block:: lua
+
+ modules.load('rebinding < iterate')
+
+Please note that this module does not offer stable configuration interface
+yet. For this reason it is suitable mainly for public resolver operators
+who do not need to whitelist certain subnets.
+
+.. warning:: Some like to "misuse" such addresses, e.g. `127.*.*.*`
+ in blacklists served over DNS, and this module will block such uses.
+
+.. _`DNS Rebinding attack`: https://en.wikipedia.org/wiki/DNS_rebinding
+.. _IPv4: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+.. _IPv6: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
diff --git a/modules/rebinding/rebinding.lua b/modules/rebinding/rebinding.lua
new file mode 100644
index 0000000..dc90d20
--- /dev/null
+++ b/modules/rebinding/rebinding.lua
@@ -0,0 +1,112 @@
+-- Protection from DNS rebinding attacks
+local kres = require('kres')
+local renumber = require('renumber')
+
+local M = {}
+M.layer = {}
+M.blacklist = {
+ -- https://www.iana.org/assignments/iana-ipv4-special-registry
+ -- + IPv4-to-IPv6 mapping
+ renumber.prefix('0.0.0.0/8', '0.0.0.0'),
+ renumber.prefix('::ffff:0.0.0.0/104', '::'),
+ renumber.prefix('10.0.0.0/8', '0.0.0.0'),
+ renumber.prefix('::ffff:10.0.0.0/104', '::'),
+ renumber.prefix('100.64.0.0/10', '0.0.0.0'),
+ renumber.prefix('::ffff:100.64.0.0/106', '::'),
+ renumber.prefix('127.0.0.0/8', '0.0.0.0'),
+ renumber.prefix('::ffff:127.0.0.0/104', '::'),
+ renumber.prefix('169.254.0.0/16', '0.0.0.0'),
+ renumber.prefix('::ffff:169.254.0.0/112', '::'),
+ renumber.prefix('172.16.0.0/12', '0.0.0.0'),
+ renumber.prefix('::ffff:172.16.0.0/108', '::'),
+ renumber.prefix('192.168.0.0/16', '0.0.0.0'),
+ renumber.prefix('::ffff:192.168.0.0/112', '::'),
+ -- https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+ renumber.prefix('::/128', '::'),
+ renumber.prefix('::1/128', '::'),
+ renumber.prefix('fc00::/7', '::'),
+ renumber.prefix('fe80::/10', '::'),
+} -- second parameter for renumber module is ignored except for being v4 or v6
+
+local function is_rr_blacklisted(rr)
+ for i = 1, #M.blacklist do
+ local prefix = M.blacklist[i]
+ -- Match record type to address family and record address to given subnet
+ if renumber.match_subnet(prefix[1], prefix[2], prefix[4], rr) then
+ return true
+ end
+ end
+ return false
+end
+
+local function check_section(pkt, section)
+ local records = pkt:section(section)
+ local count = #records
+ if count == 0 then
+ return nil end
+ for i = 1, count do
+ local rr = records[i]
+ if rr.type == kres.type.A or rr.type == kres.type.AAAA then
+ local result = is_rr_blacklisted(rr)
+ if result then
+ return rr end
+ end
+ end
+end
+
+local function check_pkt(pkt)
+ for _, section in ipairs({kres.section.ANSWER,
+ kres.section.AUTHORITY,
+ kres.section.ADDITIONAL}) do
+ local bad_rr = check_section(pkt, section)
+ if bad_rr then
+ return bad_rr
+ end
+ end
+end
+
+local function refuse(req)
+ -- we are deleting packet in consume() phase so other modules
+ -- might have chosen some RRs from the original packet already
+ req.answ_selected.len = 0
+ req.auth_selected.len = 0
+ req.add_selected.len = 0
+
+ -- construct brand new answer packet
+ local pkt = req.answer
+ pkt:clear_payload()
+ pkt:rcode(kres.rcode.REFUSED)
+ pkt:ad(false)
+ pkt:aa(false)
+ pkt:begin(kres.section.ADDITIONAL)
+
+ local msg = 'blocked by DNS rebinding protection'
+ pkt:put('\11explanation\7invalid\0', 10800, pkt:qclass(), kres.type.TXT,
+ string.char(#msg) .. msg)
+end
+
+-- act on DNS queries which were not answered from cache
+function M.layer.consume(state, req, pkt)
+ if state == kres.FAIL then
+ return state end
+
+ req = kres.request_t(req)
+ local qry = req:current()
+ if qry.flags.CACHED then -- do not slow down cached queries
+ return state end
+
+ pkt = kres.pkt_t(pkt)
+ local bad_rr = check_pkt(pkt)
+ if not bad_rr then
+ return state end
+
+ qry.flags.RESOLVED = 1 -- stop iteration
+ qry.flags.CACHED = 1 -- do not cache
+ refuse(req)
+ log('[' .. string.format('%5d', qry.id) .. '][rebinding] '
+ .. 'blocking blacklisted IP \'' .. kres.rr2str(bad_rr)
+ .. '\' received from IP ' .. tostring(kres.sockaddr_t(req.upstream.addr)))
+ return kres.FAIL
+end
+
+return M
diff --git a/modules/rebinding/rebinding.mk b/modules/rebinding/rebinding.mk
new file mode 100644
index 0000000..560d910
--- /dev/null
+++ b/modules/rebinding/rebinding.mk
@@ -0,0 +1,2 @@
+rebinding_SOURCES := rebinding.lua
+$(call make_lua_module,rebinding)
diff --git a/modules/rebinding/test.integr/deckard.yaml b/modules/rebinding/test.integr/deckard.yaml
new file mode 100644
index 0000000..58a2cee
--- /dev/null
+++ b/modules/rebinding/test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/rebinding/test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/rebinding/test.integr/kresd_config.j2 b/modules/rebinding/test.integr/kresd_config.j2
new file mode 100644
index 0000000..742f8d3
--- /dev/null
+++ b/modules/rebinding/test.integr/kresd_config.j2
@@ -0,0 +1,49 @@
+{% raw %}
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+modules.load('rebinding < iterate')
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/rebinding/test.integr/module_rebinding.rpl b/modules/rebinding/test.integr/module_rebinding.rpl
new file mode 100644
index 0000000..bfaf273
--- /dev/null
+++ b/modules/rebinding/test.integr/module_rebinding.rpl
@@ -0,0 +1,833 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; module-config: "iterator"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test protection from DNS rebinding
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 1000
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 1000
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; NS with address pointing into a private range must not be followed
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+attacker.com. IN A
+SECTION AUTHORITY
+attacker.com. IN NS ns.attacker.com.
+SECTION ADDITIONAL
+ns.attacker.com. IN A 192.168.3.5
+ENTRY_END
+RANGE_END
+
+; ns.attacker.com.
+RANGE_BEGIN 0 1000
+ ADDRESS 19.168.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attacker.com. IN NS
+SECTION ANSWER
+attacker.com. IN NS ns.attacker.com.
+SECTION ADDITIONAL
+ns.attacker.com. IN A 192.168.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.attacker.com. IN A
+SECTION ANSWER
+www.attacker.com. IN A 192.0.2.55
+ENTRY_END
+RANGE_END
+
+
+; ns.example.com.
+RANGE_BEGIN 0 1000
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 192.0.2.40
+ENTRY_END
+
+; blacklisted IP addresses
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-0-0-0-0.example.com. IN A
+SECTION ANSWER
+attack-ipv4-0-0-0-0.example.com. IN A 0.0.0.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-0-0-0-0.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-0-0-0-0.example.com. IN AAAA ::ffff:0.0.0.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-10-1-2-3.example.com. IN A
+SECTION ANSWER
+attack-ipv4-10-1-2-3.example.com. IN A 10.1.2.3
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-10-2-3-4.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-10-2-3-4.example.com. IN AAAA ::ffff:10.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-100-127-255-254.example.com. IN A
+SECTION ANSWER
+attack-ipv4-100-127-255-254.example.com. IN A 100.127.255.254
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-100-127-255-255.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-100-127-255-255.example.com. IN AAAA ::ffff:100.127.255.255
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-127-0-0-1.example.com. IN A
+SECTION ANSWER
+attack-ipv4-127-0-0-1.example.com. IN A 127.0.0.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-127-0-0-1.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-127-0-0-1.example.com. IN AAAA ::ffff:127.0.0.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-169-254-255-255.example.com. IN A
+SECTION ANSWER
+attack-ipv4-169-254-255-255.example.com. IN A 169.254.255.255
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-169-254-0-0.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-169-254-0-0.example.com. IN AAAA ::ffff:169.254.0.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-172-16-0-0.example.com. IN A
+SECTION ANSWER
+attack-ipv4-172-16-0-0.example.com. IN A 172.16.0.0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-172-31-255-255.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-172-31-255-255.example.com. IN AAAA ::ffff:172.31.255.255
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4-192-168-3-8.example.com. IN A
+SECTION ANSWER
+attack-ipv4-192-168-3-8.example.com. IN A 192.168.3.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv4over6-192-168-254-210.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv4over6-192-168-254-210.example.com. IN AAAA ::ffff:192.168.254.210
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv6-.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv6-.example.com. IN AAAA ::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv6-1.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv6-1.example.com. IN AAAA ::1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv6-fc00.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv6-fc00.example.com. IN AAAA fc00::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+attack-ipv6-fe80.example.com. IN AAAA
+SECTION ANSWER
+attack-ipv6-fe80.example.com. IN AAAA fe80::
+ENTRY_END
+
+RANGE_END
+
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here, no blacklisted IP address is present
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 192.0.2.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; test that 0.0.0.0 is blacklisted
+STEP 201 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-0-0-0-0.example.com. IN A
+ENTRY_END
+
+STEP 202 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-0-0-0-0.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:0.0.0.0 is blacklisted
+STEP 211 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-0-0-0-0.example.com. IN AAAA
+ENTRY_END
+
+STEP 212 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-0-0-0-0.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 10.1.2.3 is blacklisted
+STEP 221 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-10-1-2-3.example.com. IN A
+ENTRY_END
+
+STEP 222 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-10-1-2-3.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:10.2.3.4 is blacklisted
+STEP 231 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-10-2-3-4.example.com. IN AAAA
+ENTRY_END
+
+STEP 232 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-10-2-3-4.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 100.127.255.254 is blacklisted
+STEP 241 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-100-127-255-254.example.com. IN A
+ENTRY_END
+
+STEP 242 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-100-127-255-254.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:100.127.255.255 is blacklisted
+STEP 251 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-100-127-255-255.example.com. IN AAAA
+ENTRY_END
+
+STEP 252 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-100-127-255-255.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 127.0.0.1 is blacklisted
+STEP 261 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-127-0-0-1.example.com. IN A
+ENTRY_END
+
+STEP 262 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-127-0-0-1.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:127.0.0.1 is blacklisted
+STEP 271 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-127-0-0-1.example.com. IN AAAA
+ENTRY_END
+
+STEP 272 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-127-0-0-1.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 169.254.255.255 is blacklisted
+STEP 281 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-169-254-255-255.example.com. IN A
+ENTRY_END
+
+STEP 282 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-169-254-255-255.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:169.254.0.0 is blacklisted
+STEP 291 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-169-254-0-0.example.com. IN AAAA
+ENTRY_END
+
+STEP 292 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-169-254-0-0.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 172.16.0.0 is blacklisted
+STEP 301 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-172-16-0-0.example.com. IN A
+ENTRY_END
+
+STEP 302 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-172-16-0-0.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:172.31.255.255 is blacklisted
+STEP 311 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-172-31-255-255.example.com. IN AAAA
+ENTRY_END
+
+STEP 312 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-172-31-255-255.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that 192.168.3.8 is blacklisted
+STEP 321 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4-192-168-3-8.example.com. IN A
+ENTRY_END
+
+STEP 322 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4-192-168-3-8.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::ffff:192.168.254.210 is blacklisted
+STEP 331 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv4over6-192-168-254-210.example.com. IN AAAA
+ENTRY_END
+
+STEP 332 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv4over6-192-168-254-210.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that :: is blacklisted
+STEP 341 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv6-.example.com. IN AAAA
+ENTRY_END
+
+STEP 342 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv6-.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that ::1 is blacklisted
+STEP 351 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv6-1.example.com. IN AAAA
+ENTRY_END
+
+STEP 352 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv6-1.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that fc00:: is blacklisted
+STEP 361 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv6-fc00.example.com. IN AAAA
+ENTRY_END
+
+STEP 362 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv6-fc00.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+; test that fe80:: is blacklisted
+STEP 371 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+attack-ipv6-fe80.example.com. IN AAAA
+ENTRY_END
+
+STEP 372 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+attack-ipv6-fe80.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+STEP 401 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; it still works if no blacklisted IP address is present
+STEP 402 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 192.0.2.40
+ENTRY_END
+
+STEP 501 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.attacker.com. IN A
+ENTRY_END
+
+; NS for attacker.com. has IP address from private range, it must fail
+STEP 502 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all answer authority
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+www.attacker.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+explanation.invalid. TXT "blocked by DNS rebinding protection"
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/renumber/README.rst b/modules/renumber/README.rst
new file mode 100644
index 0000000..07a4a35
--- /dev/null
+++ b/modules/renumber/README.rst
@@ -0,0 +1,25 @@
+.. _mod-renumber:
+
+Renumber
+--------
+
+The module renumbers addresses in answers to different address space.
+e.g. you can redirect malicious addresses to a blackhole, or use private address ranges
+in local zones, that will be remapped to real addresses by the resolver.
+
+
+.. warning:: While requests are still validated using DNSSEC, the signatures are stripped from final answer. The reason is that the address synthesis breaks signatures. You can see whether an answer was valid or not based on the AD flag.
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ modules = {
+ renumber = {
+ -- Source subnet, destination subnet
+ {'10.10.10.0/24', '192.168.1.0'},
+ -- Remap /16 block to localhost address range
+ {'166.66.0.0/16', '127.0.0.0'}
+ }
+ }
diff --git a/modules/renumber/renumber.lua b/modules/renumber/renumber.lua
new file mode 100644
index 0000000..ca77b94
--- /dev/null
+++ b/modules/renumber/renumber.lua
@@ -0,0 +1,126 @@
+-- Module interface
+local ffi = require('ffi')
+local prefixes = {}
+
+-- Create subnet prefix rule
+local function matchprefix(subnet, addr)
+ local target = kres.str2ip(addr)
+ if target == nil then error('[renumber] invalid address: '..addr) end
+ local addrtype = string.find(addr, ':', 1, true) and kres.type.AAAA or kres.type.A
+ local subnet_cd = ffi.new('char[16]')
+ local bitlen = ffi.C.kr_straddr_subnet(subnet_cd, subnet)
+ -- Mask unspecified, renumber whole IP
+ if bitlen == 0 then
+ bitlen = #target * 8
+ end
+ return {subnet_cd, bitlen, target, addrtype}
+end
+
+-- Create name match rule
+local function matchname(name, addr)
+ local target = kres.str2ip(addr)
+ if target == nil then error('[renumber] invalid address: '..addr) end
+ local owner = todname(name)
+ if not name then error('[renumber] invalid name: '..name) end
+ local addrtype = string.find(addr, ':', 1, true) and kres.type.AAAA or kres.type.A
+ return {owner, nil, target, addrtype}
+end
+
+-- Add subnet prefix rewrite rule
+local function add_prefix(subnet, addr)
+ table.insert(prefixes, matchprefix(subnet, addr))
+end
+
+-- Match IP against given subnet or record owner
+local function match_subnet(subnet, bitlen, addrtype, rr)
+ local addr = rr.rdata
+ return addrtype == rr.type and
+ ((bitlen and (#addr >= bitlen / 8) and (ffi.C.kr_bitcmp(subnet, addr, bitlen) == 0)) or subnet == rr.owner)
+end
+
+-- Renumber address record
+local addr_buf = ffi.new('char[16]')
+local function renumber_record(tbl, rr)
+ for i = 1, #tbl do
+ local prefix = tbl[i]
+ -- Match record type to address family and record address to given subnet
+ -- If provided, compare record owner to prefix name
+ if match_subnet(prefix[1], prefix[2], prefix[4], rr) then
+ -- Replace part or whole address
+ local to_copy = prefix[2] or (#prefix[3] * 8)
+ local chunks = to_copy / 8
+ local rdlen = #rr.rdata
+ if rdlen < chunks then return rr end -- Address length mismatch
+ ffi.copy(addr_buf, rr.rdata, rdlen)
+ ffi.copy(addr_buf, prefix[3], chunks) -- Rewrite prefix
+ rr.rdata = ffi.string(addr_buf, rdlen)
+ return rr
+ end
+ end
+ return nil
+end
+
+-- Renumber addresses based on config
+local function rule()
+ return function (state, req)
+ if state == kres.FAIL then return state end
+ req = kres.request_t(req)
+ local pkt = kres.pkt_t(req.answer)
+ -- Only successful answers
+ local records = pkt:section(kres.section.ANSWER)
+ local ancount = #records
+ if ancount == 0 then return state end
+ -- Find renumber candidates
+ local changed = false
+ for i = 1, ancount do
+ local rr = records[i]
+ if rr.type == kres.type.A or rr.type == kres.type.AAAA then
+ local new_rr = renumber_record(prefixes, rr)
+ if new_rr ~= nil then
+ records[i] = new_rr
+ changed = true
+ end
+ end
+ end
+ -- If not rewritten, chain action
+ if not changed then return end
+ -- Replace section if renumbering
+ local qname = pkt:qname()
+ local qclass = pkt:qclass()
+ local qtype = pkt:qtype()
+ pkt:recycle()
+ pkt:question(qname, qclass, qtype)
+ for i = 1, ancount do
+ local rr = records[i]
+ -- Strip signatures as rewritten data cannot be validated
+ if rr.type ~= kres.type.RRSIG then
+ pkt:put(rr.owner, rr.ttl, rr.class, rr.type, rr.rdata)
+ end
+ end
+ return state
+ end
+end
+
+-- Export module interface
+local M = {
+ prefix = matchprefix,
+ name = matchname,
+ rule = rule,
+ match_subnet = match_subnet,
+}
+
+-- Config
+function M.config (conf)
+ if conf == nil then return end
+ if type(conf) ~= 'table' or type(conf[1]) ~= 'table' then
+ error('[renumber] expected { {prefix, target}, ... }')
+ end
+ for i = 1, #conf do add_prefix(conf[i][1], conf[1][2]) end
+end
+
+-- Layers
+M.layer = {
+ finish = rule(),
+}
+
+return M
diff --git a/modules/renumber/renumber.mk b/modules/renumber/renumber.mk
new file mode 100644
index 0000000..1e0eaee
--- /dev/null
+++ b/modules/renumber/renumber.mk
@@ -0,0 +1,2 @@
+renumber_SOURCES := renumber.lua
+$(call make_lua_module,renumber)
diff --git a/modules/rfc7706.rst b/modules/rfc7706.rst
new file mode 100644
index 0000000..d66fd82
--- /dev/null
+++ b/modules/rfc7706.rst
@@ -0,0 +1,3 @@
+Root on loopback (RFC 7706)
+---------------------------
+Knot Resolver developers decided that pure implementation of :rfc:`7706` is a bad idea so it is not implemented in the form envisioned by the RFC. You can get the very similar effect without its downsides by combining :ref:`prefill <mod-prefill>` and :ref:`serve_stale <mod-serve_stale>` modules with Aggressive Use of DNSSEC-Validated Cache (:rfc:`8198`) behavior which is enabled automatically together with DNSSEC validation.
diff --git a/modules/serve_stale/README.rst b/modules/serve_stale/README.rst
new file mode 100644
index 0000000..5c681fa
--- /dev/null
+++ b/modules/serve_stale/README.rst
@@ -0,0 +1,21 @@
+.. _mod-serve_stale:
+
+Serve stale
+-----------
+
+Demo module that allows using timed-out records in case kresd is
+unable to contact upstream servers.
+
+By default it allows stale-ness by up to one day,
+after roughly four seconds trying to contact the servers.
+It's quite configurable/flexible; see the beginning of the module source for details.
+See also the RFC draft_ (not fully followed) and :any:`cache.ns_tout`.
+
+Running
+^^^^^^^
+.. code-block:: lua
+
+ modules = { 'serve_stale < cache' }
+
+.. _draft: https://tools.ietf.org/html/draft-ietf-dnsop-serve-stale-00
+
diff --git a/modules/serve_stale/serve_stale.lua b/modules/serve_stale/serve_stale.lua
new file mode 100644
index 0000000..cf19be1
--- /dev/null
+++ b/modules/serve_stale/serve_stale.lua
@@ -0,0 +1,44 @@
+local M = {} -- the module
+
+local ffi = require('ffi')
+
+-- Beware that the timeout is only considered at certain points in time;
+-- approximately at multiples of KR_CONN_RTT_MAX.
+M.timeout = 3*sec
+
+M.callback = ffi.cast("kr_stale_cb",
+ function (ttl) --, name, type, qry)
+ --log('[ ][stal] => called back with TTL: ' .. tostring(ttl))
+ if ttl + 3600 * 24 > 0 then -- at most one day stale
+ return 1
+ else
+ return -1
+ end
+ end)
+
+M.layer = {
+ produce = function (state, req)
+ req = kres.request_t(req)
+ local qry = req:current()
+ -- Don't do anything for priming, prefetching, etc.
+ -- TODO: not all cases detected ATM.
+ if qry.flags.NO_CACHE then return state end
+
+ local now = ffi.C.kr_now()
+ local deadline = qry.creation_time_mono + M.timeout
+ if now > deadline or qry.flags.NO_NS_FOUND then
+ if verbose() then
+ log('[ ][stal] => no reachable NS, using stale data')
+ end
+ qry.stale_cb = M.callback
+ -- TODO: probably start the same request that doesn't stale-serve,
+ -- but first we need some detection of non-interactive / internal requests.
+ -- resolve(kres.dname2str(qry.sname), qry.stype, qry.sclass)
+ end
+
+ return state
+ end,
+}
+
+return M
+
diff --git a/modules/serve_stale/serve_stale.mk b/modules/serve_stale/serve_stale.mk
new file mode 100644
index 0000000..46c6f64
--- /dev/null
+++ b/modules/serve_stale/serve_stale.mk
@@ -0,0 +1,2 @@
+serve_stale_SOURCES := serve_stale.lua
+$(call make_lua_module,serve_stale)
diff --git a/modules/serve_stale/test.integr/deckard.yaml b/modules/serve_stale/test.integr/deckard.yaml
new file mode 100644
index 0000000..aae0d51
--- /dev/null
+++ b/modules/serve_stale/test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/serve_stale/test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/serve_stale/test.integr/kresd_config.j2 b/modules/serve_stale/test.integr/kresd_config.j2
new file mode 100644
index 0000000..50f2b6f
--- /dev/null
+++ b/modules/serve_stale/test.integr/kresd_config.j2
@@ -0,0 +1,49 @@
+{% raw %}
+modules = { 'serve_stale < cache' }
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/serve_stale/test.integr/module_serve_stale.rpl b/modules/serve_stale/test.integr/module_serve_stale.rpl
new file mode 100644
index 0000000..c4c522c
--- /dev/null
+++ b/modules/serve_stale/test.integr/module_serve_stale.rpl
@@ -0,0 +1,278 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Modified iter_resolve.rpl to test serve_stale module.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. 30 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. 30 IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. 30 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 30 IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. 30 IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. 30 IN SOA . . 0 0 0 0 0
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 30 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 30 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 30 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 30 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 30 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; K.ROOT-SERVERS.NET.
+; return REFUSED to all queries
+RANGE_BEGIN 101 200
+ ADDRESS 193.0.14.129
+ ADDRESS 192.5.6.30
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 101 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Must be resolved from cache
+STEP 110 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; Expire cached records (TTL is 30)
+STEP 120 TIME_PASSES ELAPSE 60
+
+STEP 121 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Must be resolved from expired cache by serve_stale module
+STEP 130 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/stats/README.rst b/modules/stats/README.rst
new file mode 100644
index 0000000..2d7dbcd
--- /dev/null
+++ b/modules/stats/README.rst
@@ -0,0 +1,163 @@
+.. _mod-stats:
+
+Statistics collector
+--------------------
+
+This modules gathers various counters from the query resolution and server internals,
+and offers them as a key-value storage. Any module may update the metrics or simply hook
+in new ones.
+
+.. code-block:: none
+
+ -- Enumerate metrics
+ > stats.list()
+ [answer.cached] => 486178
+ [iterator.tcp] => 490
+ [answer.noerror] => 507367
+ [answer.total] => 618631
+ [iterator.udp] => 102408
+ [query.concurrent] => 149
+
+ -- Query metrics by prefix
+ > stats.list('iter')
+ [iterator.udp] => 105104
+ [iterator.tcp] => 490
+
+ -- Set custom metrics from modules
+ > stats['filter.match'] = 5
+ > stats['filter.match']
+ 5
+
+ -- Fetch most common queries
+ > stats.frequent()
+ [1] => {
+ [type] => 2
+ [count] => 4
+ [name] => cz.
+ }
+
+ -- Fetch most common queries (sorted by frequency)
+ > table.sort(stats.frequent(), function (a, b) return a.count > b.count end)
+
+ -- Show recently contacted authoritative servers
+ > stats.upstreams()
+ [2a01:618:404::1] => {
+ [1] => 26 -- RTT
+ }
+ [128.241.220.33] => {
+ [1] => 31 - RTT
+ }
+
+Properties
+^^^^^^^^^^
+
+.. function:: stats.get(key)
+
+ :param string key: i.e. ``"answer.total"``
+ :return: ``number``
+
+Return nominal value of given metric.
+
+.. function:: stats.set(key, val)
+
+ :param string key: i.e. ``"answer.total"``
+ :param number val: i.e. ``5``
+
+Set nominal value of given metric.
+
+.. function:: stats.list([prefix])
+
+ :param string prefix: optional metric prefix, i.e. ``"answer"`` shows only metrics beginning with "answer"
+
+Outputs collected metrics as a JSON dictionary.
+
+.. function:: stats.upstreams()
+
+Outputs a list of recent upstreams and their RTT. It is sorted by time and stored in a ring buffer of
+a fixed size. This means it's not aggregated and readable by multiple consumers, but also that
+you may lose entries if you don't read quickly enough. The default ring size is 512 entries, and may be overriden on compile time by ``-DUPSTREAMS_COUNT=X``.
+
+.. function:: stats.frequent()
+
+Outputs list of most frequent iterative queries as a JSON array. The queries are sampled probabilistically,
+and include subrequests. The list maximum size is 5000 entries, make diffs if you want to track it over time.
+
+.. function:: stats.clear_frequent()
+
+Clear the list of most frequent iterative queries.
+
+
+Built-in statistics
+^^^^^^^^^^^^^^^^^^^
+
+Built-in counters keep track of number of queries and answers matching specific criteria.
+
++----------------------------------------------------+
+| **Global answer counters** |
++-----------------+----------------------------------+
+| answer.total | total number of answered queries |
++-----------------+----------------------------------+
+| answer.cached | queries answered from cache |
++-----------------+----------------------------------+
+
++-----------------+----------------------------------+
+| **Answers categorized by RCODE** |
++-----------------+----------------------------------+
+| answer.noerror | NOERROR answers |
++-----------------+----------------------------------+
+| answer.nodata | NOERROR, but empty answers |
++-----------------+----------------------------------+
+| answer.nxdomain | NXDOMAIN answers |
++-----------------+----------------------------------+
+| answer.servfail | SERVFAIL answers |
++-----------------+----------------------------------+
+
++-----------------+----------------------------------+
+| **Answer latency** |
++-----------------+----------------------------------+
+| answer.1ms | completed in 1ms |
++-----------------+----------------------------------+
+| answer.10ms | completed in 10ms |
++-----------------+----------------------------------+
+| answer.50ms | completed in 50ms |
++-----------------+----------------------------------+
+| answer.100ms | completed in 100ms |
++-----------------+----------------------------------+
+| answer.250ms | completed in 250ms |
++-----------------+----------------------------------+
+| answer.500ms | completed in 500ms |
++-----------------+----------------------------------+
+| answer.1000ms | completed in 1000ms |
++-----------------+----------------------------------+
+| answer.1500ms | completed in 1500ms |
++-----------------+----------------------------------+
+| answer.slow | completed in more than 1500ms |
++-----------------+----------------------------------+
+
++-----------------+----------------------------------+
+| **Answer flags** |
++-----------------+----------------------------------+
+| answer.aa | authoritative answer |
++-----------------+----------------------------------+
+| answer.tc | truncated answer |
++-----------------+----------------------------------+
+| answer.ra | recursion available |
++-----------------+----------------------------------+
+| answer.rd | recursion desired (in answer!) |
++-----------------+----------------------------------+
+| answer.ad | authentic data (DNSSEC) |
++-----------------+----------------------------------+
+| answer.cd | checking disabled (DNSSEC) |
++-----------------+----------------------------------+
+| answer.do | DNSSEC answer OK |
++-----------------+----------------------------------+
+| answer.edns0 | EDNS0 present |
++-----------------+----------------------------------+
+
++-----------------+----------------------------------+
+| **Query flags** |
++-----------------+----------------------------------+
+| query.edns | queries with EDNS present |
++-----------------+----------------------------------+
+| query.dnssec | queries with DNSSEC DO=1 |
++-----------------+----------------------------------+
diff --git a/modules/stats/stats.c b/modules/stats/stats.c
new file mode 100644
index 0000000..a2cf78e
--- /dev/null
+++ b/modules/stats/stats.c
@@ -0,0 +1,502 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file stats.c
+ * @brief Storage for various counters and metrics from query resolution.
+ *
+ * You can either reuse this module to compute statistics or store custom metrics
+ * in it via the extensions.
+ */
+
+#include <libknot/packet/pkt.h>
+#include <libknot/packet/wire.h>
+#include <libknot/descriptor.h>
+#include <ccan/json/json.h>
+#include <contrib/cleanup.h>
+#include <arpa/inet.h>
+
+#include "lib/layer/iterate.h"
+#include "lib/rplan.h"
+#include "lib/module.h"
+#include "lib/layer.h"
+#include "lib/resolve.h"
+
+/** @internal Compatibility wrapper for Lua < 5.2 */
+#if LUA_VERSION_NUM < 502
+#define lua_rawlen(L, obj) lua_objlen((L), (obj))
+#endif
+
+/* Defaults */
+#define VERBOSE_MSG(qry, ...) QRVERBOSE(qry, "stat", __VA_ARGS__)
+#define FREQUENT_PSAMPLE 10 /* Sampling rate, 1 in N */
+#ifdef LRU_REP_SIZE
+ #define FREQUENT_COUNT LRU_REP_SIZE /* Size of frequent tables */
+#else
+ #define FREQUENT_COUNT 5000 /* Size of frequent tables */
+#endif
+#ifndef UPSTREAMS_COUNT
+ #define UPSTREAMS_COUNT 512 /* Size of recent upstreams */
+#endif
+
+/** @cond internal Fixed-size map of predefined metrics. */
+#define CONST_METRICS(X) \
+ X(answer,total) X(answer,noerror) X(answer,nodata) X(answer,nxdomain) X(answer,servfail) \
+ X(answer,cached) X(answer,1ms) X(answer,10ms) X(answer,50ms) X(answer,100ms) \
+ X(answer,250ms) X(answer,500ms) X(answer,1000ms) X(answer,1500ms) X(answer,slow) \
+ X(answer,aa) X(answer,tc) X(answer,rd) X(answer,ra) X(answer, ad) X(answer,cd) \
+ X(answer,edns0) X(answer,do) \
+ X(query,edns) X(query,dnssec) \
+ X(const,end)
+
+enum const_metric {
+ #define X(a,b) metric_ ## a ## _ ## b,
+ CONST_METRICS(X)
+ #undef X
+};
+struct const_metric_elm {
+ const char *key;
+ size_t val;
+};
+static struct const_metric_elm const_metrics[] = {
+ #define X(a,b) [metric_ ## a ## _ ## b] = { #a "." #b, 0 },
+ CONST_METRICS(X)
+ #undef X
+};
+/** @endcond */
+
+/** @internal LRU hash of most frequent names. */
+typedef lru_t(unsigned) namehash_t;
+typedef array_t(struct sockaddr_in6) addrlist_t;
+
+/** @internal Stats data structure. */
+struct stat_data {
+ map_t map;
+ struct {
+ namehash_t *frequent;
+ } queries;
+ struct {
+ addrlist_t q;
+ size_t head;
+ } upstreams;
+};
+
+/** @internal We don't store/publish port, repurpose it for RTT instead. */
+#define sin6_rtt sin6_port
+
+/** @internal Add to const map counter */
+static inline void stat_const_add(struct stat_data *data, enum const_metric key, ssize_t incr)
+{
+ const_metrics[key].val += incr;
+}
+
+static int collect_answer(struct stat_data *data, knot_pkt_t *pkt)
+{
+ stat_const_add(data, metric_answer_total, 1);
+ /* Count per-rcode */
+ switch(knot_wire_get_rcode(pkt->wire)) {
+ case KNOT_RCODE_NOERROR:
+ if (knot_wire_get_ancount(pkt->wire) > 0)
+ stat_const_add(data, metric_answer_noerror, 1);
+ else
+ stat_const_add(data, metric_answer_nodata, 1);
+ break;
+ case KNOT_RCODE_NXDOMAIN: stat_const_add(data, metric_answer_nxdomain, 1); break;
+ case KNOT_RCODE_SERVFAIL: stat_const_add(data, metric_answer_servfail, 1); break;
+ default: break;
+ }
+
+ return kr_ok();
+}
+
+static inline int collect_key(char *key, const knot_dname_t *name, uint16_t type)
+{
+ memcpy(key, &type, sizeof(type));
+ int key_len = knot_dname_to_wire((uint8_t *)key + sizeof(type), name, KNOT_DNAME_MAXLEN);
+ if (key_len < 0) {
+ return kr_error(key_len);
+ }
+ return key_len + sizeof(type);
+}
+
+static void collect_sample(struct stat_data *data, struct kr_rplan *rplan, knot_pkt_t *pkt)
+{
+ /* Sample key = {[2] type, [1-255] owner} */
+ char key[sizeof(uint16_t) + KNOT_DNAME_MAXLEN];
+ for (size_t i = 0; i < rplan->resolved.len; ++i) {
+ /* Sample queries leading to iteration */
+ struct kr_query *qry = rplan->resolved.at[i];
+ if (qry->flags.CACHED) {
+ continue;
+ }
+ /* Consider 1 in N for frequent sampling.
+ * TODO: redesign the sampling approach. */
+ if (kr_rand_coin(1, FREQUENT_PSAMPLE)) {
+ int key_len = collect_key(key, qry->sname, qry->stype);
+ if (key_len < 0) {
+ assert(false);
+ continue;
+ }
+ unsigned *count = lru_get_new(data->queries.frequent, key, key_len, NULL);
+ if (count)
+ *count += 1;
+ }
+ }
+}
+
+static int collect_rtt(kr_layer_t *ctx, knot_pkt_t *pkt)
+{
+ struct kr_request *req = ctx->req;
+ struct kr_query *qry = req->current_query;
+ if (qry->flags.CACHED || !req->upstream.addr) {
+ return ctx->state;
+ }
+
+ /* Push address and RTT to the ring buffer head */
+ struct kr_module *module = ctx->api->data;
+ struct stat_data *data = module->data;
+
+ /* Socket address is encoded into sockaddr_in6 struct that
+ * unions with sockaddr_in and differ in sa_family */
+ struct sockaddr_in6 *e = &data->upstreams.q.at[data->upstreams.head];
+ const struct sockaddr *src = req->upstream.addr;
+ switch (src->sa_family) {
+ case AF_INET: memcpy(e, src, sizeof(struct sockaddr_in)); break;
+ case AF_INET6: memcpy(e, src, sizeof(struct sockaddr_in6)); break;
+ default: return ctx->state;
+ }
+ /* Replace port number with the RTT information (cap is UINT16_MAX milliseconds) */
+ e->sin6_rtt = req->upstream.rtt;
+
+ /* Advance ring buffer head */
+ data->upstreams.head = (data->upstreams.head + 1) % UPSTREAMS_COUNT;
+ return ctx->state;
+}
+
+static int collect(kr_layer_t *ctx)
+{
+ struct kr_request *param = ctx->req;
+ struct kr_module *module = ctx->api->data;
+ struct kr_rplan *rplan = &param->rplan;
+ struct stat_data *data = module->data;
+
+ /* Collect data on final answer */
+ collect_answer(data, param->answer);
+ collect_sample(data, rplan, param->answer);
+ /* Count cached and unresolved */
+ if (rplan->resolved.len > 0) {
+ /* Histogram of answer latency. */
+ struct kr_query *first = rplan->resolved.at[0];
+ uint64_t elapsed = kr_now() - first->timestamp_mono;
+ if (elapsed <= 1) {
+ stat_const_add(data, metric_answer_1ms, 1);
+ } else if (elapsed <= 10) {
+ stat_const_add(data, metric_answer_10ms, 1);
+ } else if (elapsed <= 50) {
+ stat_const_add(data, metric_answer_50ms, 1);
+ } else if (elapsed <= 100) {
+ stat_const_add(data, metric_answer_100ms, 1);
+ } else if (elapsed <= 250) {
+ stat_const_add(data, metric_answer_250ms, 1);
+ } else if (elapsed <= 500) {
+ stat_const_add(data, metric_answer_500ms, 1);
+ } else if (elapsed <= 1000) {
+ stat_const_add(data, metric_answer_1000ms, 1);
+ } else if (elapsed <= 1500) {
+ stat_const_add(data, metric_answer_1500ms, 1);
+ } else {
+ stat_const_add(data, metric_answer_slow, 1);
+ }
+ /* Observe the final query. */
+ struct kr_query *last = kr_rplan_last(rplan);
+ stat_const_add(data, metric_answer_cached, last->flags.CACHED);
+ }
+
+ /* Keep stats of all response header flags;
+ * these don't return bool, so that's why we use !! */
+ stat_const_add(data, metric_answer_aa, !!knot_wire_get_aa(param->answer->wire));
+ stat_const_add(data, metric_answer_tc, !!knot_wire_get_tc(param->answer->wire));
+ stat_const_add(data, metric_answer_rd, !!knot_wire_get_rd(param->answer->wire));
+ stat_const_add(data, metric_answer_ra, !!knot_wire_get_ra(param->answer->wire));
+ stat_const_add(data, metric_answer_ad, !!knot_wire_get_ad(param->answer->wire));
+ stat_const_add(data, metric_answer_cd, !!knot_wire_get_cd(param->answer->wire));
+
+ /* EDNS0 stats */
+ stat_const_add(data, metric_answer_edns0, knot_pkt_has_edns(param->answer));
+ stat_const_add(data, metric_answer_do, knot_pkt_has_dnssec(param->answer));
+
+ /* Query parameters and transport mode */
+ /*
+ DEPRECATED
+ use new names metric_answer_edns0 and metric_answer_do
+ */
+ stat_const_add(data, metric_query_edns, knot_pkt_has_edns(param->answer));
+ stat_const_add(data, metric_query_dnssec, knot_pkt_has_dnssec(param->answer));
+
+ return ctx->state;
+}
+
+/**
+ * Set nominal value of a key.
+ *
+ * Input: { key, val }
+ *
+ */
+static char* stats_set(void *env, struct kr_module *module, const char *args)
+{
+ if (args == NULL)
+ return NULL;
+
+ struct stat_data *data = module->data;
+
+ auto_free char *pair = strdup(args);
+ char *val = strchr(pair, ' ');
+ if (val) {
+ *val = '\0';
+ size_t number = strtoul(val + 1, NULL, 10);
+ for (unsigned i = 0; i < metric_const_end; ++i) {
+ if (strcmp(const_metrics[i].key, pair) == 0) {
+ const_metrics[i].val = number;
+ return NULL;
+ }
+ }
+ map_set(&data->map, pair, (void *)number);
+ }
+
+ return NULL;
+}
+
+/**
+ * Retrieve metrics by key.
+ *
+ * Input: string key
+ * Output: number value
+ */
+static char* stats_get(void *env, struct kr_module *module, const char *args)
+{
+ if (args == NULL)
+ return NULL;
+
+ struct stat_data *data = module->data;
+
+ /* Expecting CHAR_BIT to be 8, this is a safe bet */
+ char *ret = malloc(3 * sizeof(size_t) + 2);
+ if (!ret) {
+ return NULL;
+ }
+
+ /* Check if it exists in const map. */
+ for (unsigned i = 0; i < metric_const_end; ++i) {
+ if (strcmp(const_metrics[i].key, args) == 0) {
+ sprintf(ret, "%zu", const_metrics[i].val);
+ return ret;
+ }
+ }
+ /* Check in variable map */
+ if (!map_contains(&data->map, args)) {
+ free(ret);
+ return NULL;
+ }
+ void *val = map_get(&data->map, args);
+ sprintf(ret, "%zu", (size_t) val);
+ return ret;
+}
+
+static int list_entry(const char *key, void *val, void *baton)
+{
+ JsonNode *root = baton;
+ size_t number = (size_t) val;
+ json_append_member(root, key, json_mknumber(number));
+ return 0;
+}
+
+/**
+ * List observed metrics.
+ *
+ * Output: { key: val, ... }
+ */
+static char* stats_list(void *env, struct kr_module *module, const char *args)
+{
+ struct stat_data *data = module->data;
+ JsonNode *root = json_mkobject();
+ /* Walk const metrics map */
+ size_t args_len = args ? strlen(args) : 0;
+ for (unsigned i = 0; i < metric_const_end; ++i) {
+ struct const_metric_elm *elm = &const_metrics[i];
+ if (!args || strncmp(elm->key, args, args_len) == 0) {
+ json_append_member(root, elm->key, json_mknumber(elm->val));
+ }
+ }
+ map_walk_prefixed(&data->map, (args_len > 0) ? args : "", list_entry, root);
+ char *ret = json_encode(root);
+ json_delete(root);
+ return ret;
+}
+
+/** @internal Helper for dump_list: add a single namehash_t item to JSON. */
+static enum lru_apply_do dump_value(const char *key, uint len, unsigned *val, void *baton)
+{
+ uint16_t key_type = 0;
+ /* Extract query name, type and counter */
+ memcpy(&key_type, key, sizeof(key_type));
+ KR_DNAME_GET_STR(key_name, (uint8_t *)key + sizeof(key_type));
+ KR_RRTYPE_GET_STR(type_str, key_type);
+
+ /* Convert to JSON object */
+ JsonNode *json_val = json_mkobject();
+ json_append_member(json_val, "count", json_mknumber(*val));
+ json_append_member(json_val, "name", json_mkstring(key_name));
+ json_append_member(json_val, "type", json_mkstring(type_str));
+ json_append_element((JsonNode *)baton, json_val);
+ return LRU_APPLY_DO_NOTHING; // keep the item
+}
+/**
+ * List frequent names.
+ *
+ * Output: [{ count: <counter>, name: <qname>, type: <qtype>}, ... ]
+ */
+static char* dump_list(void *env, struct kr_module *module, const char *args, namehash_t *table)
+{
+ if (!table) {
+ return NULL;
+ }
+ JsonNode *root = json_mkarray();
+ lru_apply(table, dump_value, root);
+ char *ret = json_encode(root);
+ json_delete(root);
+ return ret;
+}
+
+static char* dump_frequent(void *env, struct kr_module *module, const char *args)
+{
+ struct stat_data *data = module->data;
+ return dump_list(env, module, args, data->queries.frequent);
+}
+
+static char* clear_frequent(void *env, struct kr_module *module, const char *args)
+{
+ struct stat_data *data = module->data;
+ lru_reset(data->queries.frequent);
+ return NULL;
+}
+
+static char* dump_upstreams(void *env, struct kr_module *module, const char *args)
+{
+ struct stat_data *data = module->data;
+ if (!data) {
+ return NULL;
+ }
+
+ /* Walk the ring backwards until AF_UNSPEC or we hit head. */
+ JsonNode *root = json_mkobject();
+ size_t head = data->upstreams.head;
+ for (size_t i = 1; i < UPSTREAMS_COUNT; ++i) {
+ size_t h = (UPSTREAMS_COUNT + head - i) % UPSTREAMS_COUNT;
+ struct sockaddr_in6 *e = &data->upstreams.q.at[h];
+ if (e->sin6_family == AF_UNSPEC) {
+ break;
+ }
+ /* Convert address to string */
+ char addr_str[INET6_ADDRSTRLEN];
+ const char *ret = inet_ntop(e->sin6_family, kr_inaddr((const struct sockaddr *)e), addr_str, sizeof(addr_str));
+ if (!ret) {
+ break;
+ }
+ /* Append to map with an array encoding RTTs */
+ JsonNode *json_val = json_find_member(root, addr_str);
+ if (!json_val) {
+ json_val = json_mkarray();
+ json_append_member(root, addr_str, json_val);
+ }
+ json_append_element(json_val, json_mknumber(e->sin6_rtt));
+ }
+
+ /* Encode and return */
+ char *ret = json_encode(root);
+ json_delete(root);
+ return ret;
+}
+
+/*
+ * Module implementation.
+ */
+
+KR_EXPORT
+const kr_layer_api_t *stats_layer(struct kr_module *module)
+{
+ static kr_layer_api_t _layer = {
+ .consume = &collect_rtt,
+ .finish = &collect,
+ };
+ /* Store module reference */
+ _layer.data = module;
+ return &_layer;
+}
+
+KR_EXPORT
+int stats_init(struct kr_module *module)
+{
+ struct stat_data *data = malloc(sizeof(*data));
+ if (!data) {
+ return kr_error(ENOMEM);
+ }
+ memset(data, 0, sizeof(*data));
+ data->map = map_make(NULL);
+ module->data = data;
+ lru_create(&data->queries.frequent, FREQUENT_COUNT, NULL, NULL);
+ /* Initialize ring buffer of recently visited upstreams */
+ array_init(data->upstreams.q);
+ if (array_reserve(data->upstreams.q, UPSTREAMS_COUNT) != 0) {
+ return kr_error(ENOMEM);
+ }
+ for (size_t i = 0; i < UPSTREAMS_COUNT; ++i) {
+ struct sockaddr *sa = (struct sockaddr *)&data->upstreams.q.at[i];
+ sa->sa_family = AF_UNSPEC;
+ }
+ return kr_ok();
+}
+
+KR_EXPORT
+int stats_deinit(struct kr_module *module)
+{
+ struct stat_data *data = module->data;
+ if (data) {
+ map_clear(&data->map);
+ lru_free(data->queries.frequent);
+ array_clear(data->upstreams.q);
+ free(data);
+ }
+ return kr_ok();
+}
+
+KR_EXPORT
+struct kr_prop *stats_props(void)
+{
+ static struct kr_prop prop_list[] = {
+ { &stats_set, "set", "Set {key, val} metrics.", },
+ { &stats_get, "get", "Get metrics for given key.", },
+ { &stats_list, "list", "List observed metrics.", },
+ { &dump_frequent, "frequent", "List most frequent queries.", },
+ { &clear_frequent,"clear_frequent", "Clear frequent queries log.", },
+ { &dump_upstreams, "upstreams", "List recently seen authoritatives.", },
+ { NULL, NULL, NULL }
+ };
+ return prop_list;
+}
+
+KR_MODULE_EXPORT(stats)
+
+#undef VERBOSE_MSG
diff --git a/modules/stats/stats.mk b/modules/stats/stats.mk
new file mode 100644
index 0000000..491fe18
--- /dev/null
+++ b/modules/stats/stats.mk
@@ -0,0 +1,5 @@
+stats_CFLAGS := -fPIC
+stats_SOURCES := modules/stats/stats.c
+stats_DEPEND := $(libkres)
+stats_LIBS := $(contrib_TARGET) $(libkres_TARGET) $(libkres_LIBS)
+$(call make_c_module,stats)
diff --git a/modules/stats/test.integr/deckard.yaml b/modules/stats/test.integr/deckard.yaml
new file mode 100644
index 0000000..1284740
--- /dev/null
+++ b/modules/stats/test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/stats/test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/stats/test.integr/kresd_config.j2 b/modules/stats/test.integr/kresd_config.j2
new file mode 100644
index 0000000..22e4077
--- /dev/null
+++ b/modules/stats/test.integr/kresd_config.j2
@@ -0,0 +1,99 @@
+{% raw %}
+modules.load('stats')
+
+FWD_TARGET = policy.FORWARD('192.0.2.1')
+
+function check_stats(got)
+ log('checking if stat values match expected values:')
+ local expected = {
+ ['answer.cd'] = 2,
+ ['answer.cached'] = 1,
+ ['answer.nodata'] = 1,
+ ['answer.noerror'] = 2,
+ ['answer.nxdomain'] = 1,
+ ['answer.servfail'] = 2,
+ ['answer.edns0'] = 6,
+ ['answer.ra'] = 6,
+ ['answer.rd'] = 5,
+ ['answer.do'] = 1,
+ ['answer.ad'] = 0,
+ ['answer.tc'] = 0,
+ ['answer.aa'] = 0,
+ ['answer.total'] = 6
+ }
+ print(table_print(expected))
+
+ local ok = true
+ for key, expval in pairs(expected) do
+ if got[key] ~= expval then
+ log('ERROR: stats key ' .. key
+ .. ' has unexpected value'
+ .. ' (expected ' .. tostring(expval)
+ .. ' got ' .. tostring(got[key] .. ')'))
+ ok = false
+ end
+ end
+ if ok then
+ log('no problem found')
+ return FWD_TARGET
+ else
+ return policy.DENY_MSG('Stats test failure')
+ end
+end
+
+function reply_result(state, req)
+ local got = stats.list()
+ log('current stats.list() values:')
+ print(table_print(got))
+ local result = check_stats(got)
+ return result(state, req)
+end
+policy.add(policy.pattern(reply_result, 'stats.test.'))
+policy.add(policy.all(FWD_TARGET)) -- avoid iteration
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/stats/test.integr/stats.rpl b/modules/stats/test.integr/stats.rpl
new file mode 100644
index 0000000..2a16272
--- /dev/null
+++ b/modules/stats/test.integr/stats.rpl
@@ -0,0 +1,193 @@
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+CONFIG_END
+
+SCENARIO_BEGIN Test stats module
+
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+
+ENTRY_BEGIN
+REPLY QR RA RD CD NOERROR
+MATCH opcode question rcode
+ADJUST copy_id
+SECTION QUESTION
+cd.test. IN TXT
+SECTION ANSWER
+cd.test. IN TXT "CD is set"
+ENTRY_END
+
+ENTRY_BEGIN
+REPLY QR RA RD CD NOERROR
+MATCH opcode question rcode
+ADJUST copy_id
+SECTION QUESTION
+nodata.test. IN TXT
+ENTRY_END
+
+ENTRY_BEGIN
+REPLY QR RA RD CD NXDOMAIN
+MATCH opcode question
+ADJUST copy_id
+SECTION QUESTION
+nxdomain.test. IN TXT
+ENTRY_END
+
+; failing DNSSEC-signed subdomain
+ENTRY_BEGIN
+REPLY QR RA RD CD SERVFAIL
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+SECTION QUESTION
+bogus.test. IN TXT
+ENTRY_END
+
+; query for this name triggers check in Lua config
+ENTRY_BEGIN
+REPLY QR RA RD CD NOERROR
+MATCH opcode question rcode
+ADJUST copy_id
+SECTION QUESTION
+stats.test. IN TXT
+SECTION ANSWER
+stats.test. IN TXT "Ok, trigger query was not intercepted!"
+ENTRY_END
+
+ENTRY_BEGIN
+REPLY QR RD RA CD TC NOERROR
+MATCH opcode question rcode
+ADJUST copy_id
+SECTION QUESTION
+tc.test. IN URI
+ENTRY_END
+
+RANGE_END
+
+
+; +cd +rd
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD CD NOERROR
+SECTION QUESTION
+cd.test. IN TXT
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA CD NOERROR
+SECTION QUESTION
+cd.test. IN TXT
+SECTION ANSWER
+cd.test. IN TXT "CD is set"
+ENTRY_END
+
+; +cd +cached +rd
+STEP 12 QUERY
+ENTRY_BEGIN
+REPLY RD CD NOERROR
+SECTION QUESTION
+cd.test. IN TXT
+ENTRY_END
+
+STEP 13 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA CD NOERROR
+SECTION QUESTION
+cd.test. IN TXT
+SECTION ANSWER
+cd.test. IN TXT "CD is set"
+ENTRY_END
+
+; +nodata +rd
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD NOERROR
+SECTION QUESTION
+nodata.test. IN TXT
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH all
+SECTION QUESTION
+nodata.test. IN TXT
+ENTRY_END
+
+; +nxdomain +rd
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD NOERROR
+SECTION QUESTION
+nxdomain.test. IN TXT
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NXDOMAIN
+MATCH all
+SECTION QUESTION
+nxdomain.test. IN TXT
+ENTRY_END
+
+; +servfail +do +rd
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD DO NOERROR
+SECTION QUESTION
+bogus.test. IN TXT
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 41 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA DO SERVFAIL
+MATCH all
+SECTION QUESTION
+bogus.test. IN TXT
+ENTRY_END
+
+; no rd
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY NOERROR
+SECTION QUESTION
+bogus.test. IN TXT
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 51 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RA SERVFAIL
+MATCH all
+SECTION QUESTION
+bogus.test. IN TXT
+ENTRY_END
+
+
+
+
+STEP 100 QUERY
+ENTRY_BEGIN
+REPLY RD NOERROR
+SECTION QUESTION
+stats.test. IN TXT
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 101 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY NOERROR
+MATCH opcode question additional rcode answer
+; AD must not be set in the answer
+SECTION QUESTION
+stats.test. IN TXT
+SECTION ANSWER
+stats.test. IN TXT "Ok, trigger query was not intercepted!"
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/modules/ta_sentinel/README.rst b/modules/ta_sentinel/README.rst
new file mode 100644
index 0000000..c3b17a4
--- /dev/null
+++ b/modules/ta_sentinel/README.rst
@@ -0,0 +1,17 @@
+.. _mod-ta_sentinel:
+
+Sentinel for Detecting Trusted Root Keys
+----------------------------------------
+
+The module implementing A Root Key Trust Anchor Sentinel for DNSSEC
+according to `draft-ietf-dnsop-kskroll-sentinel-12`_.
+
+This feature allows users of validating resolver to detect which root keys
+are configured in their chain of trust. The data from such
+signaling are necessary to monitor the progress of the DNSSEC root key rollover.
+
+This module is enabled by default and we urge users not to disable it.
+If it is absolutely necessary you may add ``modules.unload('ta_sentinel')``
+to your configuration to disable it.
+
+.. _`draft-ietf-dnsop-kskroll-sentinel-12`: https://tools.ietf.org/html/draft-ietf-dnsop-kskroll-sentinel-12
diff --git a/modules/ta_sentinel/ta_sentinel.lua b/modules/ta_sentinel/ta_sentinel.lua
new file mode 100644
index 0000000..4ee6348
--- /dev/null
+++ b/modules/ta_sentinel/ta_sentinel.lua
@@ -0,0 +1,88 @@
+local M = {}
+M.layer = {}
+local ffi = require('ffi')
+
+function M.layer.finish(state, req, pkt)
+ local kreq = kres.request_t(req)
+
+ if bit.band(state, kres.DONE) == 0 then
+ return state end -- not resolved yet, exit
+
+ local qry = kreq:resolved()
+ if qry.parent ~= nil then
+ return state end -- an internal query, exit
+
+ local kpkt = kres.pkt_t(pkt)
+ if not (kpkt:qtype() == kres.type.A or kpkt:qtype() == kres.type.AAAA) then
+ return state end
+
+ -- fast filter by the length of the first label
+ local label_len = qry:name():byte(1)
+ if label_len ~= 29 and label_len ~= 30 then
+ return state end
+ -- end of hot path
+ -- check the label name
+ local qname = kres.dname2str(qry:name()):lower()
+ local sentype, keytag
+ if label_len == 29 then
+ sentype = true
+ keytag = qname:match('^root%-key%-sentinel%-is%-ta%-(%x+)%.')
+ elseif label_len == 30 then
+ sentype = false
+ keytag = qname:match('^root%-key%-sentinel%-not%-ta%-(%x+)%.')
+ end
+ if not keytag then return state end
+
+ if kreq.rank ~= ffi.C.KR_RANK_SECURE or kreq.answer:cd() then
+ if verbose() then
+ log('[ta_sentinel] name+type OK but not AD+CD conditions')
+ end
+ return state
+ end
+
+ -- check keytag from the label
+ keytag = tonumber(keytag)
+ if not keytag or math.floor(keytag) ~= keytag then
+ return state end -- pattern did not match, exit
+ if keytag < 0 or keytag > 0xffff then
+ return state end -- invalid keytag?!, exit
+
+ if verbose() then
+ log('[ta_sentinel] key tag: ' .. keytag .. ', sentinel: ' .. tostring(sentype))
+ end
+
+ local found = false
+ local ds_set = ffi.C.kr_ta_get(kres.context().trust_anchors, '\0')
+ if ds_set ~= nil then
+ for i = 0, ds_set:rdcount() - 1 do
+ -- Find the key tag in rdata and compare
+ -- https://tools.ietf.org/html/rfc4034#section-5.1
+ local rdata = ds_set:rdata_pt(i)
+ local tag = rdata.data[0] * 256 + rdata.data[1]
+ if tag == keytag then
+ found = true
+ end
+ end
+ end
+ if verbose() then
+ log('[ta_sentinel] matching trusted TA found: ' .. tostring(found))
+ if not found then -- print matching TAs in *other* states than Valid
+ for i = 1, #(trust_anchors.keysets['\0'] or {}) do
+ local key = trust_anchors.keysets['\0'][i]
+ if key.key_tag == keytag and key.state ~= 'Valid' then
+ log('[ta_sentinel] matching UNtrusted TA found in state: '
+ .. key.state)
+ end
+ end
+ end
+ end
+
+ if sentype ~= found then -- expected key is not there, or unexpected key is there
+ kpkt:clear_payload()
+ kpkt:rcode(kres.rcode.SERVFAIL)
+ kpkt:ad(false)
+ end
+ return state -- do not break resolution process
+end
+
+return M
diff --git a/modules/ta_sentinel/ta_sentinel.mk b/modules/ta_sentinel/ta_sentinel.mk
new file mode 100644
index 0000000..2441ce0
--- /dev/null
+++ b/modules/ta_sentinel/ta_sentinel.mk
@@ -0,0 +1,2 @@
+ta_sentinel_SOURCES := ta_sentinel.lua
+$(call make_lua_module,ta_sentinel)
diff --git a/modules/ta_signal_query/README.rst b/modules/ta_signal_query/README.rst
new file mode 100644
index 0000000..04ee1ed
--- /dev/null
+++ b/modules/ta_signal_query/README.rst
@@ -0,0 +1,22 @@
+.. _mod-ta_signal_query:
+
+Signaling Trust Anchor Knowledge in DNSSEC
+------------------------------------------
+
+The module for Signaling Trust Anchor Knowledge in DNSSEC Using Key Tag Query,
+implemented according to :rfc:`8145#section-5`.
+
+This feature allows validating resolvers to signal to authoritative servers
+which keys are referenced in their chain of trust. The data from such
+signaling allow zone administrators to monitor the progress of rollovers
+in a DNSSEC-signed zone.
+
+This mechanism serve to measure the acceptance and use of new DNSSEC
+trust anchors and key signing keys (KSKs). This signaling data can be
+used by zone administrators as a gauge to measure the successful deployment
+of new keys. This is of particular interest for the DNS root zone in the event
+of key and/or algorithm rollovers that rely on :rfc:`5011` to automatically
+update a validating DNS resolver’s trust anchor.
+
+This module is enabled by default. You may use ``modules.unload('ta_signal_query')``
+in your configuration.
diff --git a/modules/ta_signal_query/ta_signal_query.lua b/modules/ta_signal_query/ta_signal_query.lua
new file mode 100644
index 0000000..413015d
--- /dev/null
+++ b/modules/ta_signal_query/ta_signal_query.lua
@@ -0,0 +1,62 @@
+-- Module implementing RFC 8145 section 5
+-- Signaling Trust Anchor Knowledge in DNS using Key Tag Query
+local kres = require('kres')
+
+local M = {}
+M.layer = {}
+
+-- transform trust anchor keyset structure for one domain name (in wire format)
+-- to signalling query name like _ta-keytag1-keytag2.example.com.
+-- Returns:
+-- string constructed from valid keytags
+-- nil if no valid keytag is present in keyset
+local function prepare_query_name(keyset, name)
+ if not keyset then return nil end
+ local keytags = {}
+ for _, key in ipairs(keyset) do
+ if key.state == "Valid" then
+ table.insert(keytags, key.key_tag)
+ end
+ end
+ if next(keytags) == nil then return nil end
+
+ table.sort(keytags)
+ local query = "_ta"
+ for _, tag in pairs(keytags) do
+ query = string.format("%s-%04x", query, tag)
+ end
+ if name == "\0" then
+ return query .. "."
+ else
+ return query .. "." .. kres.dname2str(name)
+ end
+end
+
+-- construct keytag query for valid keys and send it as asynchronous query
+-- (does nothing if no valid keys are present at given domain name)
+local function send_ta_query(domain)
+ local keyset = trust_anchors.keysets[domain]
+ local qname = prepare_query_name(keyset, domain)
+ if qname ~= nil then
+ if verbose() then
+ log("[ta_signal_query] signalling query trigered: %s", qname)
+ end
+ -- asynchronous query
+ -- we do not care about result or from where it was obtained
+ event.after(0, function ()
+ resolve(qname, kres.type.NULL, kres.class.IN, "NONAUTH")
+ end)
+ end
+end
+
+-- act on DNSKEY queries which were not answered from cache
+function M.layer.consume(state, req, _)
+ req = kres.request_t(req)
+ local qry = req:current()
+ if qry.stype == kres.type.DNSKEY and not qry.flags.CACHED then
+ send_ta_query(qry:name())
+ end
+ return state -- do not interfere with normal query processing
+end
+
+return M
diff --git a/modules/ta_signal_query/ta_signal_query.mk b/modules/ta_signal_query/ta_signal_query.mk
new file mode 100644
index 0000000..0adf179
--- /dev/null
+++ b/modules/ta_signal_query/ta_signal_query.mk
@@ -0,0 +1,2 @@
+ta_signal_query_SOURCES := ta_signal_query.lua
+$(call make_lua_module,ta_signal_query)
diff --git a/modules/view/README.rst b/modules/view/README.rst
new file mode 100644
index 0000000..3fa043a
--- /dev/null
+++ b/modules/view/README.rst
@@ -0,0 +1,89 @@
+.. _mod-view:
+
+Views and ACLs
+--------------
+
+The :ref:`policy <mod-policy>` module implements policies for global query matching, e.g. solves "how to react to certain query".
+This module combines it with query source matching, e.g. "who asked the query". This allows you to create personalized blacklists, filters and ACLs.
+
+There are two identification mechanisms:
+
+* ``addr``
+ - identifies the client based on his subnet
+* ``tsig``
+ - identifies the client based on a TSIG key name (only for testing purposes, TSIG signature is not verified!)
+
+View module allows you to combine query source information with :ref:`policy <mod-policy>` rules.
+
+.. code-block:: lua
+
+ view:addr('10.0.0.1', policy.suffix(policy.TC, policy.todnames({'example.com'})))
+
+This example will force given client to TCP for names in ``example.com`` subtree.
+You can combine view selectors with RPZ_ to create personalized filters for example.
+
+.. warning::
+
+ Beware that cache is shared by *all* requests. For example, it is safe
+ to refuse answer based on who asks the resolver, but trying to serve
+ different data to different clients will result in unexpected behavior.
+ Setups like **split-horizon** which depend on isolated DNS caches
+ are explicitly not supported.
+
+
+Example configuration
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: lua
+
+ -- Load modules
+ modules = { 'view' }
+ -- Whitelist queries identified by TSIG key
+ view:tsig('\5mykey', policy.all(policy.PASS))
+ -- Block local clients (ACL like)
+ view:addr('127.0.0.1', policy.all(policy.DENY))
+ -- Drop queries with suffix match for remote client
+ view:addr('10.0.0.0/8', policy.suffix(policy.DROP, policy.todnames({'xxx'})))
+ -- RPZ for subset of clients
+ view:addr('192.168.1.0/24', policy.rpz(policy.PASS, 'whitelist.rpz'))
+ -- Do not try this - it will pollute cache and surprise you!
+ -- view:addr('10.0.0.0/8', policy.all(policy.FORWARD('2001:DB8::1')))
+ -- Drop everything that hasn't matched
+ view:addr('0.0.0.0/0', policy.all(policy.DROP))
+
+
+Rule order
+^^^^^^^^^^
+
+The current implementation is best understood as three separate rule chains:
+vanilla ``policy.add``, ``view:tsig`` and ``view:addr``.
+For each request the rules in these chains get tried one by one until a :ref:`non-chain policy action <mod-policy-actions>` gets executed.
+
+By default :ref:`policy module <mod-policy>` acts before ``view`` module due to ``policy`` being loaded by default. If you want to intermingle universal rules with ``view:addr``, you may simply wrap the universal policy rules in view closure like this:
+
+.. code-block:: lua
+
+ view:addr('0.0.0.0/0', policy.<rule>) -- and
+ view:addr('::0/0', policy.<rule>)
+
+
+Properties
+^^^^^^^^^^
+
+.. function:: view:addr(subnet, rule)
+
+ :param subnet: client subnet, i.e. ``10.0.0.1``
+ :param rule: added rule, i.e. ``policy.pattern(policy.DENY, '[0-9]+\2cz')``
+
+ Apply rule to clients in given subnet.
+
+.. function:: view:tsig(key, rule)
+
+ :param key: client TSIG key domain name, i.e. ``\5mykey``
+ :param rule: added rule, i.e. ``policy.pattern(policy.DENY, '[0-9]+\2cz')``
+
+ Apply rule to clients with given TSIG key.
+
+ .. warning:: This just selects rule based on the key name, it doesn't verify the key or signature yet.
+
+.. _RPZ: https://dnsrpz.info/
diff --git a/modules/view/addr.test.integr/deckard.yaml b/modules/view/addr.test.integr/deckard.yaml
new file mode 100644
index 0000000..ac2792d
--- /dev/null
+++ b/modules/view/addr.test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/view/addr.test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/view/addr.test.integr/kresd_config.j2 b/modules/view/addr.test.integr/kresd_config.j2
new file mode 100644
index 0000000..f56430a
--- /dev/null
+++ b/modules/view/addr.test.integr/kresd_config.j2
@@ -0,0 +1,53 @@
+{% raw %}
+modules.load('view < policy')
+
+view:addr('127.0.0.0/24', policy.suffix(policy.DENY_MSG("addr 127.0.0.0/24 matched com"),{"\3com\0"}))
+view:addr('127.0.0.0/24', policy.suffix(policy.DENY_MSG("addr 127.0.0.0/24 matched net"),{"\3net\0"}))
+policy.add(policy.all(policy.FORWARD('1.2.3.4')))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/view/addr.test.integr/module_view_addr.rpl b/modules/view/addr.test.integr/module_view_addr.rpl
new file mode 100644
index 0000000..9e65d28
--- /dev/null
+++ b/modules/view/addr.test.integr/module_view_addr.rpl
@@ -0,0 +1,78 @@
+; config options
+ stub-addr: 1.2.3.4
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN view:addr test
+
+RANGE_BEGIN 0 110
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+RANGE_END
+
+; policy module loaded before view module must take precedence before view
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+; blocked by view:addr + inner policy.suffix com
+; NXDOMAIN expected
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode question rcode additional
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.com. IN A
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "addr 127.0.0.0/24 matched com"
+ENTRY_END
+
+; blocked by view:addr + inner policy.suffix net
+; second view rule gets executed if policy in preceding view rule did not match
+STEP 32 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.net. IN A
+ENTRY_END
+
+STEP 33 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode question rcode additional
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.net. IN A
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "addr 127.0.0.0/24 matched net"
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/view/tsig.test.integr/deckard.yaml b/modules/view/tsig.test.integr/deckard.yaml
new file mode 100644
index 0000000..bc89906
--- /dev/null
+++ b/modules/view/tsig.test.integr/deckard.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - modules/view/tsig.test.integr/kresd_config.j2
+ - tests/hints_zone.j2
+ configs:
+ - config
+ - hints
diff --git a/modules/view/tsig.test.integr/kresd_config.j2 b/modules/view/tsig.test.integr/kresd_config.j2
new file mode 100644
index 0000000..6a0952e
--- /dev/null
+++ b/modules/view/tsig.test.integr/kresd_config.j2
@@ -0,0 +1,55 @@
+{% raw %}
+modules.load('view')
+print(table_print(modules.list()))
+
+view:tsig('\8testkey1\0', policy.suffix(policy.DENY_MSG("TSIG key testkey1 matched com"),{"\3com\0"}))
+view:tsig('\8testkey1\0', policy.suffix(policy.DENY_MSG("TSIG key testkey1 matched net"),{"\3net\0"}))
+view:tsig('\7testkey\0', policy.suffix(policy.DENY_MSG("TSIG key testkey matched example"),{"\7example\0"}))
+policy.add(policy.all(policy.FORWARD('1.2.3.4')))
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected answers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected answers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+_hint_root_file('hints')
+cache.size = 2*MB
+verbose(true)
+{% endraw %}
+
+net = { '{{SELF_ADDR}}' }
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/modules/view/tsig.test.integr/module_view_tsig.rpl b/modules/view/tsig.test.integr/module_view_tsig.rpl
new file mode 100644
index 0000000..8abceb5
--- /dev/null
+++ b/modules/view/tsig.test.integr/module_view_tsig.rpl
@@ -0,0 +1,113 @@
+; config options
+ stub-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN view:tsig test
+
+RANGE_BEGIN 0 110
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+RANGE_END
+
+RANGE_BEGIN 0 110
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION ANSWER
+example.net. IN A 6.6.6.6
+ENTRY_END
+RANGE_END
+
+; policy fallback (no view matched, policy is behind view module)
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+TSIG testkey +Cdjlkef9ZTSeixERZ433Q==
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+; blocked by view:tsig testkey1 + inner policy.suffix com
+; NXDOMAIN expected
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+TSIG testkey1 +Cdjlkef9ZTSeixERZ433Q==
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode question rcode additional
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.com. IN A
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "TSIG key testkey1 matched com"
+ENTRY_END
+
+; blocked by view:tsig testkey1 + inner policy.suffix net
+; second view rule gets executed if policy in preceding view rule did not match
+STEP 32 QUERY
+ENTRY_BEGIN
+REPLY RD
+TSIG testkey1 +Cdjlkef9ZTSeixERZ433Q==
+SECTION QUESTION
+example.net. IN A
+ENTRY_END
+
+STEP 33 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode question rcode additional
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.net. IN A
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "TSIG key testkey1 matched net"
+ENTRY_END
+
+; blocked by view:tsig testkey + inner policy.suffix example (different key)
+; third view rule gets executed if policy in preceding view rule did not match
+STEP 34 QUERY
+ENTRY_BEGIN
+REPLY RD
+TSIG testkey +Cdjlkef9ZTSeixERZ433Q==
+SECTION QUESTION
+example. IN A
+ENTRY_END
+
+STEP 35 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode question rcode additional
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example. IN A
+SECTION ADDITIONAL
+explanation.invalid. 10800 IN TXT "TSIG key testkey matched example"
+ENTRY_END
+
+SCENARIO_END
diff --git a/modules/view/view.lua b/modules/view/view.lua
new file mode 100644
index 0000000..41157eb
--- /dev/null
+++ b/modules/view/view.lua
@@ -0,0 +1,118 @@
+local kres = require('kres')
+local ffi = require('ffi')
+local C = ffi.C
+
+-- Module declaration
+local view = {
+ key = {}, -- map from :owner() to list of policy rules
+ src = {},
+ dst = {},
+}
+
+-- @function View based on TSIG key name.
+function view.tsig(_, tsig, rule)
+ if view.key[tsig] == nil then
+ view.key[tsig] = { rule }
+ else
+ table.insert(view.key[tsig], rule)
+ end
+end
+
+-- @function View based on source IP subnet.
+function view.addr(_, subnet, rules, dst)
+ local subnet_cd = ffi.new('char[16]')
+ local family = C.kr_straddr_family(subnet)
+ local bitlen = C.kr_straddr_subnet(subnet_cd, subnet)
+ local t = {family, subnet_cd, bitlen, rules}
+ table.insert(dst and view.dst or view.src, t)
+ return t
+end
+
+-- @function Match IP against given subnet
+local function match_subnet(family, subnet, bitlen, addr)
+ return (family == addr:family()) and (C.kr_bitcmp(subnet, addr:ip(), bitlen) == 0)
+end
+
+-- @function Execute a policy callback (may be nil);
+-- return boolean: whether to continue trying further rules.
+local function execute(state, req, match_cb)
+ if match_cb == nil then return false end
+ local action = match_cb(req, req:current())
+ if action == nil then return false end
+ local next_state = action(state, req)
+ if next_state then -- Not a chain rule,
+ req.state = next_state
+ return true
+ else
+ return false
+ end
+end
+
+-- @function Try all the rules in order, until a non-chain rule gets executed.
+local function evaluate(state, req)
+ -- Try :tsig rules first.
+ local client_key = req.qsource.packet.tsig_rr
+ local match_cbs = (client_key ~= nil) and view.key[client_key:owner()] or {}
+ for _, match_cb in ipairs(match_cbs) do
+ if execute(state, req, match_cb) then return end
+ end
+ -- Then try :addr by the source.
+ if req.qsource.addr ~= nil then
+ for i = 1, #view.src do
+ local pair = view.src[i]
+ if match_subnet(pair[1], pair[2], pair[3], req.qsource.addr) then
+ local match_cb = pair[4]
+ if execute(state, req, match_cb) then return end
+ end
+ end
+ -- Finally try :addr by the destination.
+ elseif req.qsource.dst_addr ~= nil then
+ for i = 1, #view.dst do
+ local pair = view.dst[i]
+ if match_subnet(pair[1], pair[2], pair[3], req.qsource.dst_addr) then
+ local match_cb = pair[4]
+ if execute(state, req, match_cb) then return end
+ end
+ end
+ end
+end
+
+-- @function Return policy based on source address
+function view.rule_src(action, subnet)
+ local subnet_cd = ffi.new('char[16]')
+ local family = C.kr_straddr_family(subnet)
+ local bitlen = C.kr_straddr_subnet(subnet_cd, subnet)
+ return function(req, _)
+ local addr = req.qsource.addr
+ if addr ~= nil and match_subnet(family, subnet_cd, bitlen, addr) then
+ return action
+ end
+ end
+end
+
+-- @function Return policy based on destination address
+function view.rule_dst(action, subnet)
+ local subnet_cd = ffi.new('char[16]')
+ local family = C.kr_straddr_family(subnet)
+ local bitlen = C.kr_straddr_subnet(subnet_cd, subnet)
+ return function(req, _)
+ local addr = req.qsource.dst_addr
+ if addr ~= nil and match_subnet(family, subnet_cd, bitlen, addr) then
+ return action
+ end
+ end
+end
+
+-- @function Module layers
+view.layer = {
+ begin = function(state, req)
+ -- Don't act on "resolved" cases.
+ if bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0 then return state end
+
+ req = kres.request_t(req)
+ evaluate(state, req)
+ return req.state
+ end
+}
+
+return view
diff --git a/modules/view/view.mk b/modules/view/view.mk
new file mode 100644
index 0000000..47b752d
--- /dev/null
+++ b/modules/view/view.mk
@@ -0,0 +1,2 @@
+view_SOURCES := view.lua
+$(call make_lua_module,view)
diff --git a/modules/workarounds/README.rst b/modules/workarounds/README.rst
new file mode 100644
index 0000000..5aa8970
--- /dev/null
+++ b/modules/workarounds/README.rst
@@ -0,0 +1,14 @@
+.. _mod-workarounds:
+
+Workarounds
+-----------
+
+A simple module that alters resolver behavior on specific broken sub-domains.
+Currently it mainly disables case randomization on them.
+
+Running
+^^^^^^^
+.. code-block:: lua
+
+ modules = { 'workarounds < iterate' }
+
diff --git a/modules/workarounds/workarounds.lua b/modules/workarounds/workarounds.lua
new file mode 100644
index 0000000..9766782
--- /dev/null
+++ b/modules/workarounds/workarounds.lua
@@ -0,0 +1,54 @@
+-- Load dependent module
+if not policy then modules.load('policy') end
+
+local M = {} -- the module
+
+function M.config()
+ policy.add(policy.suffix(policy.FLAGS('NO_0X20'), {
+ -- https://github.com/DNS-OARC/dns-violations/blob/master/2017/DVE-2017-0003.md
+ todname('avqs.mcafee.com'), todname('avts.mcafee.com'),
+
+ -- https://github.com/DNS-OARC/dns-violations/blob/master/2017/DVE-2017-0006.md
+ -- Obtained via a reverse search on {ns1,ns3}.panthercdn.com.
+ todname('cdnga.com'), todname('cdngc.com'), todname('cdngd.com'),
+ todname('cdngl.com'), todname('cdngm.com'),
+ todname('cdngc.net'), todname('panthercdn.com'),
+
+ todname('magazine-fashion.net.'),
+ }))
+end
+
+-- Issue #139: When asking certain nameservers for PTR, disable 0x20.
+-- Just listing the *.in-addr.arpa suffixes would be tedious, as there are many.
+M.layer = {
+ produce = function (state, req)
+ req = kres.request_t(req)
+ local qry = req:current()
+ if qry.stype ~= kres.type.PTR
+ or bit.band(state, bit.bor(kres.FAIL, kres.DONE)) ~= 0
+ then return state -- quick exit in most cases
+ end
+ if qry.flags.AWAIT_CUT or qry.ns.name == nil
+ then return state end
+ local name = kres.dname2str(qry.ns.name)
+ if not name then return state end
+
+ -- The problematic nameservers:
+ -- (1) rdnsN.turktelekom.com.tr.
+ if string.sub(name, 6) == '.turktelekom.com.tr.' then
+ qry.flags.NO_0X20 = true
+ qry.flags.NO_MINIMIZE = true
+ -- ^ NO_MINIMIZE isn't required for success, as kresd will retry
+ -- after getting refused, but it will speed things up.
+
+ -- (2)
+ elseif name == 'dns1.edatel.net.co.' then
+ qry.flags.NO_0X20 = true
+ end
+
+ return state
+ end,
+}
+
+return M
+
diff --git a/modules/workarounds/workarounds.mk b/modules/workarounds/workarounds.mk
new file mode 100644
index 0000000..6b0493e
--- /dev/null
+++ b/modules/workarounds/workarounds.mk
@@ -0,0 +1,2 @@
+workarounds_SOURCES := workarounds.lua
+$(call make_lua_module,workarounds)
diff --git a/platform.mk b/platform.mk
new file mode 100644
index 0000000..5498fec
--- /dev/null
+++ b/platform.mk
@@ -0,0 +1,230 @@
+# Platform-specific stuff
+# Don't touch this unless you're changing the way targets are compiled
+# You have been warned
+
+# Platform-dependent stuff checks
+CCLD := $(CC)
+CLANG_TIDY ?= clang-tidy -quiet
+CGO := go tool cgo
+GO := go
+CAT := cat
+SED := sed
+LCOV := lcov
+GENHTML := genhtml
+LIBEXT := .so
+AREXT := .a
+LIBTYPE := shared
+MODTYPE := shared
+ARTYPE := static
+BINEXT :=
+PLATFORM = Linux
+ARCH := $(word 1, $(subst -, ,$(shell $(CC) -dumpmachine)))
+# Library versioning flags (platform-specific)
+comma := ,
+SOVER = $(if $(1),-Wl$(comma)-soname$(comma)$(3)$(call SOVER_EXT,$(1)))
+# Library versioned extension (platform-specific)
+SOVER_EXT = $(LIBEXT).$(1)
+ifeq ($(OS),Windows_NT)
+ PLATFORM := Windows
+ RM := del
+ LN := link
+ LIBEXT := .lib
+ BINEXT := .exe
+else
+ UNAME := $(shell uname -s)
+ ifeq ($(UNAME),Darwin)
+ PLATFORM := Darwin
+ LIBEXT := .dylib
+ MODTYPE := dynamiclib
+ LDFLAGS += -Wl,-export_dynamic
+ # OS X specific hardening since -pie doesn't work
+ ifneq ($(HARDENING),no)
+ BINFLAGS += -Wl,-pie
+ endif
+ # Version is prepended to dylib
+ SOVER_EXT = .$(1)$(LIBEXT)
+ SOVER = $(if $(1), -compatibility_version $(2) -current_version $(1),)
+ else
+ PLATFORM := POSIX
+ LDFLAGS += -pthread -lm -Wl,--export-dynamic
+ # ELF hardening options
+ ifneq ($(HARDENING),no)
+ BINFLAGS += -pie
+ LDFLAGS += -Wl,-z,relro,-z,now
+ endif
+ ifeq ($(UNAME),Linux)
+ LDFLAGS += -ldl
+ endif
+ ifeq (GCC,$(shell $(CC) --version | grep -q -i '\<gcc\>' && echo GCC))
+ # Otherwise Fedora is making kresd symbols inaccessible for modules.
+ # Clang doesn't support this flag, so we hackily detect gcc.
+ BUILD_CFLAGS += -rdynamic
+ endif
+ endif
+endif
+
+# Silent compilation
+ifeq ($(V),1)
+ quiet = $($1)
+else
+ quiet = @echo " $1 $2"; $($1)
+endif
+
+# Make objects and depends (name)
+define make_objs
+$(1)_OBJ := $$($(1)_SOURCES:.c=.o)
+$(1)_DEP := $$($(1)_SOURCES:.c=.d)
+-include $$($(1)_DEP)
+endef
+define make_objrule
+$(1): $(1:.o=.c)
+ $$(call quiet,CC,$$<) $(2) -MMD -MP -c $$< -o $$@
+endef
+
+# Make target (name,path,ext,ldflags, 5:dst,amalgable,abiver)
+define make_target
+ifeq ($(AMALG)|$(6), yes|yes)
+$(1).amalg.c: $$($(1)_SOURCES)
+ $(call quiet,CAT,$$@) $$($(1)_SOURCES) > $$@
+# AR requires .o compiled
+$(1)_OBJ := $(1).amalg.c
+ifeq ($(4),-$(ARTYPE))
+$(1)_OBJ := $(1).amalg.o
+endif
+else
+$$(eval $$(call make_objs,$(1)))
+endif
+# Rules to generate objects with custom CFLAGS and binary/library
+$$(foreach obj,$$($(1)_OBJ),$$(eval $$(call make_objrule,$$(obj),$$(BUILD_CFLAGS) $$($(1)_CFLAGS))))
+$(1) := $(2)/$(1)$(3)
+$(2)/$(1)$(3): $$($(1)_OBJ) $$($(1)_DEPEND)
+ifeq ($(4),-$(ARTYPE))
+ $(call quiet,AR,$$@) rcs $$@ $$($(1)_OBJ)
+else
+ifneq ($(strip $(7)),)
+ $(call quiet,CCLD,$$@) $$($(1)_CFLAGS) $(BUILD_CFLAGS) $$($(1)_OBJ) $(call SOVER,$(7),$(7),$(1)) -o $(2)/$(1)$(call SOVER_EXT,$(7)) $(4) $$($(1)_LIBS) $(BUILD_LDFLAGS) $$($(1)_LDFLAGS)
+ $(LN) -f $(1)$(call SOVER_EXT,$(7)) $$@
+else
+ $(call quiet,CCLD,$$@) $$($(1)_CFLAGS) $(BUILD_CFLAGS) $$($(1)_OBJ) $(call SOVER,$(7),$(7),$(1)) -o $$@ $(4) $$($(1)_LIBS) $(BUILD_LDFLAGS) $$($(1)_LDFLAGS)
+endif
+endif
+# Linter rules
+$(1)-lint: $$($(1)_SOURCES)
+ $(call quiet,CLANG_TIDY,$(1)) $$($(1)_SOURCES) -- $(BUILD_CFLAGS) $$($(1)_CFLAGS) -DMP_FREELIST_SIZE=0 -D__clang_analyzer__
+# Additional rules
+$(1)-clean:
+ $(RM) $$($(1)_OBJ) $$($(1)_DEP) $(2)/$(1)$(3)
+ifeq ($(6), yes)
+ $(RM) $(1).amalg.c $(1).amalg.o
+endif
+$(1)-install: $(2)/$(1)$(3)
+# Modules install to special path
+ifneq ($(5),$(MODULEDIR))
+ $(INSTALL) -d $(DESTDIR)$(5)
+endif
+# Versioned library install
+ifneq ($(strip $(7)),)
+ $(INSTALL) $(2)/$(1)$(call SOVER_EXT,$(7)) $(DESTDIR)$(5)/
+ $(LN) -f $(1)$(call SOVER_EXT,$(7)) $(DESTDIR)$(5)/$(1)$(3)
+else
+ $(INSTALL) $(2)/$(1)$(3) $(DESTDIR)$(5)
+endif
+ifneq ($$(strip $$($(1)_HEADERS)),)
+ $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)/$(1)
+ $(INSTALL) -m 644 $$($(1)_HEADERS) $(DESTDIR)$(INCLUDEDIR)/$(1)
+endif
+.PHONY: $(1)-clean $(1)-install
+endef
+
+# Make targets (name,path,amalgable yes|no,abiver)
+make_bin = $(call make_target,$(1),$(2),$(BINEXT),$(BINFLAGS),$(BINDIR),$(3))
+make_sbin = $(call make_target,$(1),$(2),$(BINEXT),$(BINFLAGS),$(SBINDIR),$(3))
+make_lib = $(call make_target,$(1),$(2),$(LIBEXT),-$(LIBTYPE),$(LIBDIR),$(3),$(4))
+make_module = $(call make_target,$(1),$(2),$(LIBEXT),-$(LIBTYPE),$(MODULEDIR),$(3))
+make_static = $(call make_target,$(1),$(2),$(AREXT),-$(ARTYPE),$(LIBDIR),$(3))
+
+# Find library (pkg-config)
+define find_lib
+ $(call find_alt,$(1),$(1),$(2))
+endef
+
+# Find library alternative (pkg-config)
+define find_alt
+ ifeq ($$(strip $$($(1)_LIBS)),)
+ ifneq ($(strip $(3)),)
+ $(1)_VER := $(shell pkg-config --atleast-version=$(3) $(2) && echo $(3))
+ endif
+ ifeq ($(strip $(3)),$$($(1)_VER))
+ $(1)_CFLAGS := $(shell pkg-config --cflags $(2) --silence-errors)
+ $(1)_LIBS := $(shell pkg-config --libs $(2) --silence-errors)
+ endif
+ endif
+ ifeq ($$(strip $$($(1)_LIBS)),)
+ HAS_$(1) := no
+ else
+ HAS_$(1) := yes
+ endif
+endef
+
+# Find binary
+define find_bin
+ ifeq ($$(strip $$($(1)_BIN)),)
+ $(1)_BIN := $(shell which $(1))
+ endif
+ ifeq ($$(strip $$($(1)_BIN)),)
+ HAS_$(1) := no
+ else
+ HAS_$(1) := yes
+ $(1) := $$($(1)_BIN)
+ endif
+endef
+
+# Find version
+define find_ver
+ ifeq ($(shell test $(2) -ge $(3); echo $$?),0)
+ HAS_$(1) := yes
+ else
+ HAS_$(1) := no
+ endif
+endef
+
+# Find Go package
+define find_gopkg
+ HAS_$(1) := $(shell go list $(2) > /dev/null 2>&1 && echo yes || echo no)
+endef
+
+# Find Lua package
+define find_luapkg
+ HAS_$(1) := $(shell luajit -l $(1) -e "os.exit(0)"> /dev/null 2>&1 && echo yes || echo no)
+endef
+
+# Find Python package
+define find_pythonpkg
+ HAS_$(1) := $(shell python3 -c "import $(1)" > /dev/null 2>&1 && echo yes || echo no)
+endef
+
+define find_soname
+
+# N/A on Windows
+ifeq ($(PLATFORM),Windows)
+ $(1)_SONAME = $(1).dll
+endif
+
+# Use otool -D on OS X
+ifeq ($(PLATFORM),Darwin)
+ $(1)_SONAME = $$(shell otool -D $$$$(pkg-config --variable=libdir $(1))/$(1)$(LIBEXT) | sed -ne 's,.*/\($(1)\.[0-9]*.$(LIBEXT)\),\1,p')
+endif
+
+# Use objdump -p on Linux and BSDs
+ifeq ($(PLATFORM),POSIX)
+ifeq ($(UNAME),OpenBSD)
+ $(1)_SONAME = $$(shell basename $$$$(readlink -f $$$$(pkg-config --variable=libdir $(1))/$(1)$(LIBEXT)) | cut -f 1-3 -d .)
+else
+ $(1)_SONAME = $$(shell objdump -p $$$$(pkg-config --variable=libdir $(1))/$(1)$(LIBEXT) | sed -ne 's/[[:space:]]*SONAME[[:space:]]*\($(1)\.so\.[0-4]*\)/\1/p')
+endif
+endif
+
+endef # find_soname
+
+# Use this on OpenBSD
+#
diff --git a/scripts/build-in-obs.sh b/scripts/build-in-obs.sh
new file mode 100755
index 0000000..7aea0d3
--- /dev/null
+++ b/scripts/build-in-obs.sh
@@ -0,0 +1,29 @@
+#!/bin/bash -e
+
+# Example usage:
+# 1. place tarball to be released in git root dir
+# 2. scripts/make-distrofiles.sh -s
+# 3. scripts/build-in-obs.sh knot-resolver-latest
+
+project=home:CZ-NIC:$1
+package=knot-resolver
+
+if ! [[ "$1" == *-devel || "$1" == *-testing ]]; then
+ read -p "Pushing to '$project', are you sure? [y/N]: " yn
+ case $yn in
+ [Yy]* )
+ ;;
+ * )
+ exit 1
+ esac
+fi
+
+osc co "${project}" "${package}"
+pushd "${project}/${package}"
+osc del * ||:
+cp -L ../../*.orig.tar.xz ../../*.debian.tar.xz ../../*.dsc ./
+cp -rL ../../distro/rpm/* ./
+cp -rL ../../distro/arch/* ./
+osc addremove
+osc ci -n
+popd
diff --git a/scripts/coverage_c_combine.sh b/scripts/coverage_c_combine.sh
new file mode 100755
index 0000000..23006c1
--- /dev/null
+++ b/scripts/coverage_c_combine.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# $1 = top source directory
+# $2 = coverage data directory path
+# $3 = output directory for *.info files
+
+set -o errexit -o nounset
+shopt -s nullglob
+IFS=$'\n'
+
+TOPSRCDIR="$1"
+DATAROOT="$2"
+OUTDIR="$3"
+
+cd "${TOPSRCDIR}"
+for COVNAME in $(find "${DATAROOT}" -name .topdir_kresd_coverage)
+do
+ find "${DATAROOT}" -name '*.gcda' -not -path "${DATAROOT}/*" -delete
+ COVDIR="$(dirname "${COVNAME}")"
+ COVDATA_FILENAMES=("${COVDIR}"/*) # filenames in BASH array
+ (( ${#COVDATA_FILENAMES[*]} )) || continue # skip empty dirs
+
+ cp -r -t ${TOPSRCDIR} "${COVDIR}"/*
+ ${LCOV} -q --no-external --capture -d lib -d daemon -d modules -o "$(mktemp -p "${OUTDIR}" -t XXXXXXXX.c.info)" > /dev/null
+done
diff --git a/scripts/coverage_env.sh b/scripts/coverage_env.sh
new file mode 100755
index 0000000..bb85649
--- /dev/null
+++ b/scripts/coverage_env.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# generate variables for coverage testing
+# $1 = top source directory
+# $2 = coverage data directory path
+# $3 = name of test/new subdirectory name
+# $4 = [optional] --export to generate export commands
+
+set -o errexit -o nounset
+shopt -s nullglob
+
+test -z "${COVERAGE:-}" && exit 0 # not enabled, do nothing
+test ! -z "${V:-}" && set -o xtrace # verbose mode
+
+EXPORT=""
+test "${4:-}" == "--export" && EXPORT="export "
+TOPSRCDIR="$1"
+DATAROOT="$2"
+OUTPATH="$2/$3"
+
+# check that output directory is empty
+# beware: Makefile will always call coverage_env.sh for all targets
+# so directories get created but not populated
+# i.e. test -d is not sufficient check
+OUTPATH_FILENAMES=("${OUTPATH}"/*) # filenames in BASH array
+(( ${#OUTPATH_FILENAMES[*]} )) && echo "false" && >&2 echo "fatal: output directory ${OUTPATH} must be empty (or non-existent)" && exit 1
+
+mkdir -p "${OUTPATH}"
+# convert paths to absolute
+pushd "${OUTPATH}" &> /dev/null
+touch .topdir_kresd_coverage
+OUTPATH="$(pwd -P)"
+popd &> /dev/null
+
+# determine GCOV_PREFIX_STRIP value for current source directory
+TOPSRCDIR_SLASHES="${TOPSRCDIR//[^\/]/}" # remove everything except /
+GCOV_PREFIX_STRIP="${#TOPSRCDIR_SLASHES}" # numer of / == number of components
+
+KRESD_COVERAGE_STATS="${OUTPATH}/luacov.stats.out"
+GCOV_PREFIX="${OUTPATH}"
+echo "${EXPORT}KRESD_COVERAGE_STATS=\"${KRESD_COVERAGE_STATS}\" ${EXPORT}GCOV_PREFIX=\"${GCOV_PREFIX}\" ${EXPORT}GCOV_PREFIX_STRIP=\"${GCOV_PREFIX_STRIP}\""
diff --git a/scripts/embed-lua.sh b/scripts/embed-lua.sh
new file mode 100755
index 0000000..80f6cba
--- /dev/null
+++ b/scripts/embed-lua.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -e
+# Clean unnecessary stuff from the lua file; note the significant tabulator.
+alias strip="sed -e 's/^[ ]*//g; s/ */ /g; /^--/d; /^$/d'"
+if command -v xxd > /dev/null 2>&1; then
+ strip < "$1" | xxd -i -
+else
+ strip < "$1" | hexdump -v -e '/1 "0x%02X, " " "'
+fi
+exit $?
diff --git a/scripts/gen-cdefs.sh b/scripts/gen-cdefs.sh
new file mode 100755
index 0000000..0627fa4
--- /dev/null
+++ b/scripts/gen-cdefs.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+set -o pipefail -o errexit
+
+if [ "$2" != types ] && [ "$2" != functions ]; then
+ echo "Usage: $0 libkres (types|functions)" >&2
+ echo " and input identifiers, one per line." >&2
+ echo " You need debug symbols in the library." >&2
+ exit 1
+fi
+
+if ! command -v gdb >/dev/null; then
+ echo "Failed to find gdb" >&2
+ exit 1
+fi
+
+if ! command -v sed >/dev/null; then
+ echo "Failed to find GNU sed" >&2
+ exit 1
+fi
+
+if ! sed --version | head -1 | grep -q "GNU sed"; then
+ echo "GNU sed required to run this script" >&2
+fi
+
+# be very precise with the directories for libraries to not pick wrong library
+case "$1" in
+ libknot) library="$(PATH="$(pkg-config libknot --variable=libdir)" command -v "$1.so")" ;;
+ libzscanner) library="$(PATH="$(pkg-config libzscanner --variable=libdir)" command -v "$1.so")" ;;
+ *) library="$(PATH="$(pwd)/lib" command -v "$1.so")"
+esac
+
+if [ -z "$library" ]; then
+ echo "$1 not found. Note: only .so platforms work currently." >&2
+ exit 1
+fi
+
+# Let's use an array to hold command-line arguments, to simplify quoting.
+GDB=(gdb)
+GDB+=(-n -quiet -batch "-symbols=$library")
+GDB+=(-iex "set width unlimited" -iex "set max-value-size unlimited")
+
+grep -v '^#\|^$' | while read -r ident; do
+ if [ "$2" = functions ]; then
+ output="$("${GDB[@]}" --ex "info functions ^$ident\$" \
+ | sed '0,/^All functions/ d; /^File .*:$/ d')"
+ else # types
+ case "$ident" in
+ struct\ *|union\ *|enum\ *)
+ output="$("${GDB[@]}" --ex "ptype $ident" \
+ | sed '0,/^type = /s/^type = /\n/; $ s/$/;/')"
+ ;;
+ *)
+ output="$("${GDB[@]}" --ex "info types ^$ident\$" \
+ | sed -e '0,/^File .*:$/ d' -e '/^File .*:$/,$ d')"
+ # we need to stop early to remove ^^ multiple matches
+ ;;
+ esac
+ fi
+ # LuaJIT FFI blows up on "uint" type
+ output="$(echo "$output" | sed 's/\buint\b/unsigned int/g')"
+ # GDB 8.2+ added source line prefix to output
+ output="$(echo "$output" | sed 's/^[0-9]\+:[[:space:]]*//g')"
+
+ # abort on empty output
+ if [ -z "$(echo "$output" | tr -d "\n;")" ]; then
+ echo "Failed to find cdef of $ident" >&2
+ exit 1
+ fi
+ echo "$output" | grep -v '^$'
+done
+
+exit 0
diff --git a/scripts/kresd-host.lua b/scripts/kresd-host.lua
new file mode 100755
index 0000000..9348716
--- /dev/null
+++ b/scripts/kresd-host.lua
@@ -0,0 +1,114 @@
+#!/usr/bin/env luajit
+-- Work around OS X stripping dyld variables
+cli_bin = 'luajit scripts/kresd-query.lua'
+libdir = os.getenv('DYLD_LIBRARY_PATH')
+if libdir then
+ cli_bin = string.format('DYLD_LIBRARY_PATH="%s" %s', libdir, cli_bin)
+end
+-- Parse CLI arguments
+local function help(rc)
+ print(string.format([[
+Usage: %s [-vdh46D] [-c class] [-t type]
+ [-f keyfile] hostname
+ Queries the DNS for information.
+ The hostname is looked up for IP4, IP6 and mail.
+ Use the -v option to see DNSSEC security information.
+ -t type what type to look for.
+ -c class what class to look for, if not class IN.
+ -C confstr additional kresd-style configuration.
+ -D DNSSEC enable with default root anchor
+ -f keyfile read trust anchors from file, with lines as -y.
+ -v be more verbose, shows nodata and security.
+ -d debug, traces the action, -d -d shows more.
+ -4 use ipv4 network, avoid ipv6.
+ -6 use ipv6 network, avoid ipv4.
+ -h show this usage help.]],
+ arg[0]))
+ return rc
+end
+
+-- Parse CLI arguments
+if #arg < 1 then
+ return help(1)
+end
+local qtypes, qclass, qname = {}, 'IN', nil
+local verbose, config = false, {}
+k = 1 while k <= #arg do
+ local v = arg[k]
+ if v == '-h' or v == '--help' then
+ return help(0)
+ elseif v == '-C' then
+ k = k + 1
+ table.insert(config, arg[k])
+ elseif v == '-D' then
+ table.insert(config, 'trust_anchors.file = "root.keys"')
+ elseif v == '-f' then
+ k = k + 1
+ table.insert(config, string.format('trust_anchors.file = "%s"', arg[k]))
+ elseif v == '-v' then
+ verbose = true
+ elseif v == '-d' then
+ verbose = true
+ table.insert(config, 'verbose(true)')
+ elseif v == '-4' then
+ table.insert(config, 'net.ipv6 = false')
+ elseif v == '-6' then
+ table.insert(config, 'net.ipv4 = false')
+ elseif v == '-c' then
+ k = k + 1
+ qclass = arg[k]:upper()
+ elseif v == '-t' then
+ k = k + 1
+ table.insert(qtypes, arg[k]:upper())
+ elseif v:byte() == string.byte('-') then
+ return help(1)
+ else
+ qname = v
+ -- Check if name is an IP addresses
+ -- @TODO: convert to domain name and make a PTR lookup
+ end
+ k = k + 1
+end
+if not qname then
+ return help(1)
+end
+if #qtypes == 0 then
+ qtypes = {'A', 'AAAA', 'MX'}
+end
+-- Assemble config/query
+for _, qtype in ipairs(qtypes) do
+ query = string.format('-t %s -c %s %s', qtype, qclass, qname)
+ capture = string.format([[
+ local qname = "%s"
+ local qtype = "%s"
+ local qverbose = %s]], qname, qtype, tostring(verbose))..[[
+ local qry = req:resolved()
+ local section = pkt:rrsets(kres.section.ANSWER)
+ for i = 1, #section do
+ local rr = section[i]
+ for k = 1, rr.rrs.count do
+ local rdata = rr:tostring(k - 1)
+ local owner = kres.dname2str(rr:owner())
+ if qverbose then
+ if not qry.flags.DNSSEC_WANT or qry.flags.DNSSEC_INSECURE then
+ rdata = rdata .. " (insecure)"
+ else
+ rdata = rdata .. " (secure)"
+ end
+ end
+ if rr.type == kres.type.A then
+ print(string.format("%s has address %s", owner, rdata))
+ elseif rr.type == kres.type.AAAA then
+ print(string.format("%s has IPv6 address %s", owner, rdata))
+ elseif rr.type == kres.type.MX then
+ print(string.format("%s mail is handled by %s", owner, rdata))
+ elseif rr.type == kres.type.CNAME then
+ print(string.format("%s is an alias for %s", owner, rdata))
+ else
+ print(string.format("%s has %s record %s", owner, qtype, rdata))
+ end
+ end
+ end
+ ]]
+ os.execute(string.format('%s -C \'%s\' %s \'%s\'', cli_bin, table.concat(config, ' '), query, capture))
+end
diff --git a/scripts/kresd-query.lua b/scripts/kresd-query.lua
new file mode 100755
index 0000000..c2d5468
--- /dev/null
+++ b/scripts/kresd-query.lua
@@ -0,0 +1,64 @@
+#!/usr/bin/env luajit
+cli_bin = 'kresd -q -c -'
+-- Work around OS X stripping dyld variables
+libdir = os.getenv('DYLD_LIBRARY_PATH')
+if libdir then
+ cli_bin = string.format('DYLD_LIBRARY_PATH="%s" %s', libdir, cli_bin)
+end
+cli_cmd = [[echo '
+option("ALWAYS_CUT", true)
+%s
+return resolve("%s", kres.type.%s, kres.class.%s, 0,
+function (pkt, req)
+ pkt = kres.pkt_t(pkt)
+ req = kres.request_t(req)
+ local ok, err = pcall(function () %s end)
+ if not ok then
+ print(err)
+ end
+ quit()
+end)']]
+-- Parse CLI arguments
+local function help()
+ name = 'kresd-query.lua'
+ print(string.format('Usage: %s [-t type] [-c class] [-C config] <name> <script>', name))
+ print('Execute a single-shot query and run a script on the result.')
+ print('There are two variables available: pkt (kres.pkt_t), req (kres.request_t)')
+ print('See modules README to learn about their APIs.')
+ print('')
+ print('Options:')
+ print('\t-h,--help ... print this help')
+ print('\t-t TYPE ... query for given type (default: A)')
+ print('\t-c CLASS ... query in given class (default: IN)')
+ print('\t-C config_str ... kresd-style config (default: -)')
+ print('Examples:')
+ print('\t'..name..' -t SOA cz "print(pkt:qname())" ... print response QNAME')
+end
+-- Parse CLI arguments
+if #arg < 2 then help() return 1 end
+local qtype, qclass, qname = 'A', 'IN', nil
+local config, scripts = '', {}
+k = 1 while k <= #arg do
+ local v = arg[k]
+ if v == '-h' or v == '--help' then
+ return help()
+ elseif v == '-C' then
+ k = k + 1
+ config = arg[k]
+ elseif v == '-c' then
+ k = k + 1
+ qclass = arg[k]:upper()
+ elseif v == '-t' then
+ k = k + 1
+ qtype = arg[k]:upper()
+ elseif v:byte() == string.byte('-') then
+ return help()
+ elseif not qname then
+ qname = v
+ else
+ table.insert(scripts, v)
+ end
+ k = k + 1
+end
+cli_cmd = string.format(cli_cmd, config, qname, qtype, qclass, table.concat(scripts, ' '))
+return os.execute(cli_cmd..' | '..cli_bin)
diff --git a/scripts/kresd.apparmor b/scripts/kresd.apparmor
new file mode 100644
index 0000000..ad6f911
--- /dev/null
+++ b/scripts/kresd.apparmor
@@ -0,0 +1,29 @@
+#include <tunables/global>
+
+/usr/sbin/kresd {
+ #include <abstractions/base>
+ #include <abstractions/p11-kit>
+ #include <abstractions/nameservice>
+ capability net_bind_service,
+ capability setgid,
+ capability setuid,
+ # seems to be needed during start to read /var/lib/knot-resolver
+ # while we still run as root.
+ capability dac_override,
+
+ network tcp,
+ network udp,
+
+ /proc/sys/net/core/somaxconn r,
+ /etc/knot-resolver/* r,
+ /var/lib/knot-resolver/ r,
+ /var/lib/knot-resolver/** rwlk,
+
+ # modules
+ /usr/lib{,64}/kdns_modules/*.lua r,
+ /usr/lib{,64}/kdns_modules/*.so rm,
+
+ # Site-specific additions and overrides. See local/README for details.
+ #include <local/usr.sbin.kresd>
+}
+
diff --git a/scripts/launch-test-instance.sh b/scripts/launch-test-instance.sh
new file mode 100755
index 0000000..8a93328
--- /dev/null
+++ b/scripts/launch-test-instance.sh
@@ -0,0 +1,26 @@
+#!/bin/sh -e
+export PATH="/usr/lib/ccache:$PATH"
+
+PORT=${1:-$((32767+$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -d' ' -f1) % 32768))}
+
+JOBS=$(cat /proc/cpuinfo | grep processor | wc -l)
+
+WORKDIR=${2:-$(mktemp -d /tmp/knot-resolver.XXXXXX)}
+
+PREFIX=${PREFIX:-$WORKDIR} make clean
+
+CFLAGS=${CFLAGS:-"-O2 -g3"} PREFIX=${PREFIX:-$WORKDIR} make -j ${JOBS} V=1
+
+PREFIX=${PREFIX:-$WORKDIR} make install
+
+install -d -m 0700 ${WORKDIR}/run/kresd
+
+echo "Launching Knot Resolver on port: ${PORT}"
+echo "To debug, use:"
+echo "dig +dnssec +multi +time=60 +retry=1 -p ${PORT} @::1"
+
+LD_LIBRARY_PATH=${WORKDIR}/lib ${WORKDIR}/sbin/kresd -a 127.0.0.1#${PORT} -a ::1#${PORT} -v -k ${ROOT_KEY:-/usr/share/dns/root.key} ${WORKDIR}/run/kresd
+
+if [ "${WORKDIR}" != "${2}" -a "${KEEP_WORKDIR}" != "yes" ]; then
+ rm -r ${WORKDIR}
+fi
diff --git a/scripts/luacov_gen_empty.sh b/scripts/luacov_gen_empty.sh
new file mode 100755
index 0000000..a224081
--- /dev/null
+++ b/scripts/luacov_gen_empty.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Generate stats file in luacov format indicating that files named on stdin
+# were not processed.
+#
+# Normally luacov does not know about files which were not loaded so
+# without this manual addition the files are missing in coverage report.
+
+# Usage:
+# $ luacov_gen_empty.sh < list_of_lua_files > luacov.empty_stats.out
+
+set -o errexit -o nounset
+IFS=$'\n'
+
+while read FILENAME
+do
+ echo -e "0:${FILENAME}\n "
+done
diff --git a/scripts/luacov_to_info.lua b/scripts/luacov_to_info.lua
new file mode 100755
index 0000000..372f5c0
--- /dev/null
+++ b/scripts/luacov_to_info.lua
@@ -0,0 +1,56 @@
+#!/usr/bin/env luajit
+
+local luacov = require('luacov')
+local ReporterBase = require('luacov.reporter').ReporterBase
+local LcovReporter = setmetatable({}, ReporterBase)
+LcovReporter.__index = LcovReporter
+
+function LcovReporter:on_new_file(filename)
+ self.finfo = self.current_files[filename] or {name=filename, coverage={}}
+end
+
+function LcovReporter:on_mis_line(_, lineno, _)
+ self.finfo.coverage[lineno] = self.finfo.coverage[lineno] or 0
+end
+
+function LcovReporter:on_hit_line(_, lineno, _, hits)
+ self.finfo.coverage[lineno] = (self.finfo.coverage[lineno] or 0) + hits
+end
+
+function LcovReporter:on_end_file()
+ self.current_files[self.finfo.name] = self.finfo
+ self.finfo = nil
+end
+
+-- Write out results in lcov format
+local function write_lcov_info(files)
+ for fname, finfo in pairs(files) do
+ local instrumented, nonzero = 0, 0
+ print('TN:')
+ print(string.format('SF:%s', fname))
+ for i, hits in pairs(finfo.coverage) do
+ print(string.format('DA:%d,%d', i, hits))
+ instrumented = instrumented + 1
+ if hits > 0 then
+ nonzero = nonzero + 1
+ end
+ end
+ print(string.format('LH:%d', nonzero))
+ print(string.format('LF:%d', instrumented))
+ print('end_of_record')
+ end
+end
+
+-- Accumulate total coverage
+local all_files = {}
+for _, fname in ipairs(arg) do
+ local conf = luacov.load_config()
+ conf.statsfile = fname
+ local reporter = assert(LcovReporter:new(conf))
+ reporter.current_files = all_files
+ reporter:run()
+ reporter:close()
+end
+
+-- Write results
+write_lcov_info(all_files)
diff --git a/scripts/make-archive.sh b/scripts/make-archive.sh
new file mode 100755
index 0000000..e3b1a97
--- /dev/null
+++ b/scripts/make-archive.sh
@@ -0,0 +1,15 @@
+#!/bin/sh -e
+# Create a distribution tarball, like 'make dist' from autotools.
+cd "$(git rev-parse --show-toplevel)"
+ver=$(git describe | sed 's/^v//' | sed 's/-/\./g')
+test 0 -ne $(git status --porcelain | wc -l) && \
+ echo "Git working tree is dirty, make it clean first" && \
+ exit 1
+git submodule status --recursive | grep -q '^[^ ]' && \
+ echo "Git submodules are dirty, run: git submodule update --recursive --init" && \
+ exit 2
+
+# 'git ls-files --recurse-submodules' works only if modules are initialized
+name="knot-resolver-$ver"
+tar caf "$name.tar.xz" -h --no-recursion --transform "s|^|$name/|" -- $(git ls-files --recurse-submodules)
+echo "$name.tar.xz"
diff --git a/scripts/make-distrofiles.sh b/scripts/make-distrofiles.sh
new file mode 100755
index 0000000..957c067
--- /dev/null
+++ b/scripts/make-distrofiles.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+set -o errexit -o nounset -o xtrace
+
+# Run with -s to include *.symbols files.
+
+package=knot-resolver
+withsymbols=false
+
+while getopts "s" o; do
+ case "${o}" in
+ s)
+ withsymbols=true
+ ;;
+ *)
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+
+cd "$(git rev-parse --show-toplevel)"
+version=$(ls ${package}*.tar.xz | sed "s/${package}-\(.*\).tar.xz/\1/")
+
+# Check version for invalid characters
+if [[ $(echo "${version}" | grep '^[[:alnum:].]$') -ne 0 ]]; then
+ echo "Invalid version number: may contain only alphanumeric characters and dots"
+ exit 1
+fi
+
+# Fill in VERSION field in distribution specific files
+files="distro/rpm/${package}.spec distro/deb/changelog distro/arch/PKGBUILD"
+for file in ${files}; do
+ sed -i "s/__VERSION__/${version}/g" "${file}"
+done
+
+# Rename archive to debian format
+pkgname="${package}-${version}"
+debname="${package}_${version}.orig"
+mv "${pkgname}.tar.xz" "${debname}.tar.xz"
+
+# Prepare clean debian-specific directory
+tar -xf "${debname}.tar.xz"
+pushd "${pkgname}" > /dev/null
+cp -arL ../distro/deb debian
+
+# Optionally remove symbols file
+if [ "$withsymbols" = false ]; then
+ rm -f debian/*.symbols
+fi
+
+# Create debian archive and dsc
+dpkg-source -b .
+popd > /dev/null
diff --git a/scripts/make-srpm.sh b/scripts/make-srpm.sh
new file mode 100755
index 0000000..29fc8b3
--- /dev/null
+++ b/scripts/make-srpm.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -o errexit -o nounset -o xtrace
+
+# Create a source rpm for Fedora/EPEL
+
+cd "$(git rev-parse --show-toplevel)"
+scripts/make-archive.sh
+scripts/make-distrofiles.sh
+mv knot-resolver_*.orig.tar.xz distro/rpm/
+cd distro/rpm
+rpkg srpm --outdir .
+mv *.src.rpm ../../
+mv *.tar.xz ../../
diff --git a/scripts/map_install_src.lua b/scripts/map_install_src.lua
new file mode 100755
index 0000000..f4f0ed3
--- /dev/null
+++ b/scripts/map_install_src.lua
@@ -0,0 +1,167 @@
+#!/usr/bin/env luajit
+
+-- parse install commands from stdin
+-- input: PREFIX=... make install --dry-run --always-make
+-- output: <install path> <source path>
+-- (or sed commands if --sed was specified)
+
+output = 'list'
+if #arg > 1 or arg[1] == '-h' or arg[1] == '--help' then
+ print(string.format([[
+Read install commands and map install paths to paths in source directory.
+
+Usage:
+$ PREFIX=... make install --dry-run --always-make | %s
+
+Example output:
+/kresd/git/.local/lib/kdns_modules/policy.lua modules/policy/policy.lua
+
+Option --sed will produce output suitable as input suitable for sed.]],
+ arg[0]))
+ os.exit(1)
+elseif #arg == 0 then
+ output = 'list'
+elseif arg[1] == '--sed' then
+ output = 'sed'
+else
+ print('Invalid arguments. See --help.')
+ os.exit(2)
+end
+
+-- remove double // from paths and remove trailing /
+function normalize_path(path)
+ assert(path)
+ repeat
+ path, changes = path:gsub('//', '/')
+ until changes == 0
+ return path:gsub('/$', '')
+end
+
+function is_opt(word)
+ return word:match('^-')
+end
+
+-- opts requiring additional argument to be skipped
+local ignored_opts_with_arg = {
+ ['--backup'] = true,
+ ['-g'] = true,
+ ['--group'] = true,
+ ['-m'] = true,
+ ['--mode'] = true,
+ ['-o'] = true,
+ ['--owner'] = true,
+ ['--strip-program'] = true,
+ ['--suffix'] = true,
+}
+
+-- state machine junctions caused by --opts
+-- returns: new state (expect, mode) and target name if any
+function parse_opts(word, expect, mode)
+ if word == '--' then
+ return 'names', mode, nil -- no options anymore
+ elseif word == '-d' or word == '--directory' then
+ return 'opt_or_name', 'newdir', nil
+ elseif word == '-t' or word == '--target-directory' then
+ return 'targetdir', mode, nil
+ elseif word:match('^--target-directory=') then
+ return 'opt_or_name', mode, string.sub(word, 20)
+ elseif ignored_opts_with_arg[word] then
+ return 'ignore', mode, nil -- ignore next word
+ else
+ return expect, mode, nil -- unhandled opt
+ end
+end
+
+
+-- cmd: complete install command line: install -m 0644 -t dest src1 src2
+-- dirs: names known to be directories: name => true
+-- returns: updated dirs
+function process_cmd(cmd, dirs)
+ -- print('# ' .. cmd)
+ sanity_check(cmd)
+ local expect = 'install'
+ local mode = 'copy' -- copy or newdir
+ local target -- last argument or argument for install -t
+ local names = {} -- non-option arguments
+
+ for word in cmd:gmatch('%S+') do
+ if expect == 'install' then -- parsing 'install'
+ assert(word == 'install')
+ expect = 'opt_or_name'
+ elseif expect == 'opt_or_name' then
+ if is_opt(word) then
+ expect, mode, newtarget = parse_opts(word, expect, mode)
+ target = newtarget or target
+ else
+ if mode == 'copy' then
+ table.insert(names, word)
+ elseif mode == 'newdir' then
+ local path = normalize_path(word)
+ dirs[path] = true
+ else
+ assert(false, 'bad mode')
+ end
+ end
+ elseif expect == 'targetdir' then
+ local path = normalize_path(word)
+ dirs[path] = true
+ target = word
+ expect = 'opt_or_name'
+ elseif expect == 'names' then
+ table.insert(names, word)
+ elseif expect == 'ignore' then
+ expect = 'opt_or_name'
+ else
+ assert(false, 'bad expect')
+ end
+ end
+ if mode == 'newdir' then
+ -- no mapping to print, this cmd just created directory
+ return dirs
+ end
+
+ if not target then -- last argument is the target
+ target = table.remove(names)
+ end
+ assert(target, 'fatal: no target in install cmd')
+ target = normalize_path(target)
+
+ for _, name in pairs(names) do
+ basename = string.gsub(name, "(.*/)(.*)", "%2")
+ if not dirs[target] then
+ print('fatal: target directory "' .. target .. '" was not created yet!')
+ os.exit(2)
+ end
+ -- mapping installed name -> source name
+ if output == 'list' then
+ print(target .. '/' .. basename, name)
+ elseif output == 'sed' then
+ print(string.format([[s`%s`%s`g]],
+ target .. '/' .. basename, name))
+ else
+ assert(false, 'unsupported output')
+ end
+ end
+ return dirs
+end
+
+function sanity_check(cmd)
+ -- shell quotation is not supported
+ assert(not cmd:match('"'), 'quotes " are not supported')
+ assert(not cmd:match("'"), "quotes ' are not supported")
+ assert(not cmd:match('\\'), "escapes like \\ are not supported")
+ assert(cmd:match('^install%s'), 'not an install command')
+end
+
+-- remember directories created by install -d so we can expand relative paths
+local dirs = {}
+while true do
+ local cmd = io.read("*line")
+ if not cmd then
+ break
+ end
+ local isinstall = cmd:match('^install%s')
+ if isinstall then
+ dirs = process_cmd(cmd, dirs)
+ end
+end
diff --git a/scripts/obs-testbuild.sh b/scripts/obs-testbuild.sh
new file mode 100755
index 0000000..f44cecc
--- /dev/null
+++ b/scripts/obs-testbuild.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# Builds the checked out version in knot-dns-testing OBS repository
+
+set -o errexit -o nounset -o xtrace
+
+force=false
+
+# Read options
+while getopts "f" o; do
+ case "${o}" in
+ f)
+ force=true
+ ;;
+ *)
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+# Clean working tree
+if [[ $(git status --porcelain | wc -l) -ne 0 ]]; then
+ if [ "$force" = false ]; then
+ echo "working tree dirty. force clean with '-f'"
+ exit 1
+ fi
+ git clean -dfx
+ git reset --hard
+fi
+
+# Create tarball
+scripts/make-archive.sh
+
+# Submit to OBS
+scripts/make-distrofiles.sh -s
+scripts/build-in-obs.sh knot-resolver-testing
+
+echo "Check results at https://build.opensuse.org/package/show/home:CZ-NIC:knot-resolver-testing/knot-resolver"
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 0000000..ee3d88a
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1,6 @@
+*.pyc
+tmp*
+test_cache
+test_context
+test_resolve
+test_rplan
diff --git a/tests/README.rst b/tests/README.rst
new file mode 100644
index 0000000..502347c
--- /dev/null
+++ b/tests/README.rst
@@ -0,0 +1,29 @@
+Unit tests
+==========
+
+The unit tests depend on cmocka_.
+
+.. code-block:: bash
+
+ $ make check
+
+.. todo:: Writing tests.
+
+Integration tests
+=================
+
+The integration tests are using Deckard, the `DNS test harness <deckard>`_.
+It requires Jinja2_ and Python, `socket_wrapper`_, libfaketime_ are embedded in the build (cmake is required for `socket_wrapper`_).
+
+Execute the tests by:
+
+.. code-block:: bash
+
+ $ make check-integration
+
+See deckard_ documentation on how to write additional tests.
+
+.. _cmocka: https://cmocka.org/
+.. _`socket_wrapper`: https://cwrap.org/socket_wrapper.html
+.. _`libfaketime`: https://github.com/wolfcw/libfaketime
+.. _deckard: https://gitlab.labs.nic.cz/knot/deckard
diff --git a/tests/clang_scan_build.sh b/tests/clang_scan_build.sh
new file mode 100755
index 0000000..8d7398f
--- /dev/null
+++ b/tests/clang_scan_build.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+# following checkers are disabled on purpose:
+# Clann does not suppor attribute cleanup and this is causing false positives in following checkers:
+# unix.Malloc
+# alpha.unix.SimpleStream
+# alpha.unix.Stream
+# https://bugs.llvm.org/show_bug.cgi?id=3888
+
+# These are disabled for other reasons:
+# alpha.clone.CloneChecker # way too many false positives
+# alpha.core.CastToStruct # we use this pattern too much, hard to avoid in many cases
+# alpha.deadcode.UnreachableCode # false positives/flags sanity checks depending on implementation details
+# alpha.security.MallocOverflow # not smart enough to infer max values from data types
+
+${SCAN_BUILD:-scan-build} \
+-disable-checker unix.Malloc \
+-enable-checker alpha.core.BoolAssignment \
+-enable-checker alpha.core.CallAndMessageUnInitRefArg \
+-enable-checker alpha.core.CastSize \
+-enable-checker alpha.core.Conversion \
+-enable-checker alpha.core.DynamicTypeChecker \
+-enable-checker alpha.core.FixedAddr \
+-enable-checker alpha.core.IdenticalExpr \
+-enable-checker alpha.core.PointerArithm \
+-enable-checker alpha.core.PointerSub \
+-enable-checker alpha.core.SizeofPtr \
+-enable-checker alpha.core.TestAfterDivZero \
+-enable-checker alpha.cplusplus.IteratorRange \
+-enable-checker alpha.cplusplus.MisusedMovedObject \
+-enable-checker alpha.security.ArrayBound \
+-enable-checker alpha.security.ArrayBoundV2 \
+-enable-checker alpha.security.ReturnPtrRange \
+-enable-checker alpha.security.taint.TaintPropagation \
+-enable-checker alpha.unix.BlockInCriticalSection \
+-enable-checker alpha.unix.Chroot \
+-enable-checker alpha.unix.PthreadLock \
+-enable-checker alpha.unix.cstring.BufferOverlap \
+-enable-checker alpha.unix.cstring.NotNullTerminated \
+-enable-checker alpha.unix.cstring.OutOfBounds \
+-enable-checker nullability.NullableDereferenced \
+-enable-checker nullability.NullablePassedToNonnull \
+-enable-checker nullability.NullableReturnedFromNonnull \
+-enable-checker optin.performance.Padding \
+-enable-checker optin.portability.UnixAPI \
+-enable-checker security.FloatLoopCounter \
+-enable-checker valist.CopyToSelf \
+-enable-checker valist.Uninitialized \
+-enable-checker valist.Unterminated \
+make
diff --git a/tests/config/basic.test.lua b/tests/config/basic.test.lua
new file mode 100644
index 0000000..520f63e
--- /dev/null
+++ b/tests/config/basic.test.lua
@@ -0,0 +1,202 @@
+local ffi = require('ffi')
+
+-- test if constants work properly
+local function test_constants()
+ same(kres.class.IN, 1, 'class constants work')
+ same(kres.type.NS, 2, 'record type constants work')
+ same(kres.type.TYPE2, 2, 'unnamed record type constants work')
+ same(kres.type.BADTYPE, nil, 'non-existent type constants are checked')
+ same(kres.section.ANSWER, 0, 'section constants work')
+ same(kres.rcode.SERVFAIL, 2, 'rcode constants work')
+ same(kres.opcode.UPDATE, 5, 'opcode constants work')
+ -- Test inverset tables to convert constants to text
+ same(kres.tostring.class[1], 'IN', 'text class constants work')
+ same(kres.tostring.type[2], 'NS', 'text record type constants work')
+ same(kres.tostring.type[65535], 'TYPE65535', 'text record type undefined constants work')
+ same(kres.tostring.section[0], 'ANSWER', 'text section constants work')
+ same(kres.tostring.rcode[2], 'SERVFAIL', 'text rcode constants work')
+ same(kres.tostring.opcode[5], 'UPDATE', 'text opcode constants work')
+end
+
+-- test globals
+local function test_globals()
+ ok(mode('strict'), 'changing strictness mode')
+ boom(mode, {'badmode'}, 'changing to non-existent strictness mode')
+ same(reorder_RR(true), true, 'answer section reordering')
+ same(option('REORDER_RR', false), false, 'generic option call')
+ boom(option, {'REORDER_RR', 'potato'}, 'generic option call argument check')
+ boom(option, {'MARS_VACATION', false}, 'generic option check name')
+ same(table_print('crabdiary'), 'crabdiary\n', 'table print works')
+ same(table_print({fakepizza=1}), '[fakepizza] => 1\n', 'table print works on tables')
+end
+
+-- test if dns library functions work
+local function test_rrset_functions()
+ local rr = {owner = '\3com\0', ttl = 1, type = kres.type.TXT, rdata = '\5hello'}
+ local rr_text = tostring(kres.rr2str(rr))
+ same(rr_text:gsub('%s+', ' '), 'com. 1 TXT "hello"', 'rrset to text works')
+ same(kres.dname2str(todname('com.')), 'com.', 'domain name conversion works')
+ -- test creating rrset
+ rr = kres.rrset(todname('com.'), kres.type.A, kres.class.IN, 66)
+ ok(ffi.istype(kres.rrset, rr), 'created an empty RR')
+ same(rr:owner(), '\3com\0', 'created RR has correct owner')
+ same(rr:class(), kres.class.IN, 'created RR has correct class')
+ same(rr:class(kres.class.CH), kres.class.CH, 'can set a different class')
+ same(rr:class(kres.class.IN), kres.class.IN, 'can restore a class')
+ same(rr.type, kres.type.A, 'created RR has correct type')
+ -- test adding rdata
+ same(rr:wire_size(), 0, 'empty RR wire size is zero')
+ ok(rr:add_rdata('\1\2\3\4', 4), 'adding RDATA works')
+ same(rr:wire_size(), 5 + 4 + 4 + 2 + 4, 'RR wire size works after adding RDATA')
+ -- test conversion to text
+ local expect = 'com. 66 A 1.2.3.4\n'
+ same(rr:txt_dump(), expect, 'RR to text works')
+ -- create a dummy rrsig
+ local rrsig = kres.rrset(todname('com.'), kres.type.RRSIG, kres.class.IN, 0)
+ rrsig:add_rdata('\0\1', 2)
+ same(rr:rdcount(), 1, 'add_rdata really added RDATA')
+ -- check rrsig matching
+ same(rr.type, rrsig:type_covered(), 'rrsig type covered matches covered RR type')
+ ok(rr:is_covered_by(rrsig), 'rrsig is covering a record')
+ -- test rrset merging
+ local copy = kres.rrset(rr:owner(), rr.type, kres.class.IN, 66)
+ ok(copy:add_rdata('\4\3\2\1', 4), 'adding second RDATA works')
+ ok(rr:merge_rdata(copy), 'merge_rdata works')
+ same(rr:rdcount(), 2, 'RDATA count is correct after merge_rdata')
+ expect = 'com. 66 A 1.2.3.4\n' ..
+ 'com. 66 A 4.3.2.1\n'
+ same(rr:txt_dump(), expect, 'merge_rdata actually merged RDATA')
+end
+
+-- test dns library packet interface
+local function test_packet_functions()
+ local pkt = kres.packet(512)
+ isnt(pkt, nil, 'creating packets works')
+ -- Test manipulating header
+ ok(pkt:rcode(kres.rcode.NOERROR), 'setting rcode works')
+ same(pkt:rcode(), 0, 'getting rcode works')
+ same(pkt:opcode(), 0, 'getting opcode works')
+ is(pkt:aa(), false, 'packet is created without AA')
+ is(pkt:ra(), false, 'packet is created without RA')
+ is(pkt:ad(), false, 'packet is created without AD')
+ ok(pkt:rd(true), 'setting RD bit works')
+ is(pkt:rd(), true, 'getting RD bit works')
+ ok(pkt:tc(true), 'setting TC bit works')
+ is(pkt:tc(), true, 'getting TC bit works')
+ ok(pkt:tc(false), 'disabling TC bit works')
+ is(pkt:tc(), false, 'getting TC bit after disable works')
+ is(pkt:cd(), false, 'getting CD bit works')
+ is(pkt:id(1234), 1234, 'setting MSGID works')
+ is(pkt:id(), 1234, 'getting MSGID works')
+ -- Test manipulating question
+ is(pkt:qname(), nil, 'reading name from empty question')
+ is(pkt:qtype(), 0, 'reading type from empty question')
+ is(pkt:qclass(), 0, 'reading class from empty question')
+ ok(pkt:question(todname('hello'), kres.class.IN, kres.type.A), 'setting question section works')
+ same(pkt:qname(), todname('hello'), 'reading QNAME works')
+ same(pkt:qtype(), kres.type.A, 'reading QTYPE works')
+ same(pkt:qclass(), kres.class.IN, 'reading QCLASS works')
+ -- Test manipulating sections
+ ok(pkt:begin(kres.section.ANSWER), 'switching sections works')
+ local res, err = pkt:put(nil, 0, 0, 0, '')
+ isnt(res, true, 'inserting nil entry doesnt work')
+ isnt(err.code, 0, 'error code is non-zero')
+ isnt(tostring(res), '', 'inserting nil returns invalid parameter')
+ ok(pkt:put(pkt:qname(), 900, pkt:qclass(), kres.type.A, '\1\2\3\4'), 'adding rrsets works')
+ boom(pkt.begin, {pkt, 10}, 'switching to invalid section doesnt work')
+ ok(pkt:begin(kres.section.ADDITIONAL), 'switching to different section works')
+ boom(pkt.begin, {pkt, 0}, 'rewinding sections doesnt work')
+ local before_insert = pkt:remaining_bytes()
+ ok(pkt:put(pkt:qname(), 900, pkt:qclass(), kres.type.A, '\4\3\2\1'), 'adding rrsets to different section works')
+ same(pkt:remaining_bytes(), before_insert - (2 + 4 + 4 + 2 + 4), 'remaining bytes count goes down with insertions')
+ -- Test conversions to text
+ like(pkt:tostring(), '->>HEADER<<-', 'packet to text works')
+ -- Test deserialization
+ local wire = pkt:towire()
+ same(#wire, 55, 'packet serialization works')
+ local parsed = kres.packet(#wire, wire)
+ isnt(parsed, nil, 'creating packet from wire works')
+ ok(parsed:parse(), 'parsing packet from wire works')
+ same(parsed:qname(), pkt:qname(), 'parsed packet has same QNAME')
+ same(parsed:qtype(), pkt:qtype(), 'parsed packet has same QTYPE')
+ same(parsed:qclass(), pkt:qclass(), 'parsed packet has same QCLASS')
+ same(parsed:opcode(), pkt:opcode(), 'parsed packet has same opcode')
+ same(parsed:rcode(), pkt:rcode(), 'parsed packet has same rcode')
+ same(parsed:rd(), pkt:rd(), 'parsed packet has same RD')
+ same(parsed:id(), pkt:id(), 'parsed packet has same MSGID')
+ same(parsed:qdcount(), pkt:qdcount(), 'parsed packet has same question count')
+ same(parsed:ancount(), pkt:ancount(), 'parsed packet has same answer count')
+ same(parsed:nscount(), pkt:nscount(), 'parsed packet has same authority count')
+ same(parsed:arcount(), pkt:arcount(), 'parsed packet has same additional count')
+ same(parsed:tostring(), pkt:tostring(), 'parsed packet is equal to source packet')
+
+ -- Test adding RR sets directly
+ local copy = kres.packet(23)
+ copy:question(todname('hello'), kres.class.IN, kres.type.A)
+ copy:begin(kres.section.ANSWER)
+ local rr = kres.rrset(pkt:qname(), kres.type.A, kres.class.IN, 66)
+ rr:add_rdata('\4\3\2\1', 4)
+ ok(not copy:put_rr(rr), 'adding RR sets checks for available space')
+ ok(copy:resize(512), 'resizing packet works')
+ ok(copy:put_rr(rr), 'adding RR sets directly works')
+ ok(copy:recycle(), 'recycling packet works')
+
+ -- Test recycling of packets
+ -- Clear_payload keeps header + question intact
+ local cleared = kres.packet(#wire, wire) -- same as "parsed" above
+ ok(cleared:parse(), 'parsing packet from wire works')
+ ok(cleared:clear_payload(), 'clear_payload works')
+ same(cleared:id(), pkt:id(), 'cleared packet has same MSGID')
+ same(cleared:qr(), pkt:qr(), 'cleared packet has same QR')
+ same(cleared:opcode(), pkt:opcode(), 'cleared packet has same OPCODE')
+ same(cleared:aa(), pkt:aa(), 'cleared packet has same AA')
+ same(cleared:tc(), pkt:tc(), 'cleared packet has same TC')
+ same(cleared:rd(), pkt:rd(), 'cleared packet has same RD')
+ same(cleared:ra(), pkt:ra(), 'cleared packet has same RA')
+ same(cleared:ad(), pkt:ad(), 'cleared packet has same AD')
+ same(cleared:cd(), pkt:cd(), 'cleared packet has same CD')
+ same(cleared:rcode(), pkt:rcode(), 'cleared packet has same RCODE')
+ same(cleared:qdcount(), pkt:qdcount(), 'cleared packet has same question count')
+ same(cleared:ancount(), 0, 'cleared packet has no answers')
+ same(cleared:nscount(), 0, 'cleared packet has no authority')
+ same(cleared:arcount(), 0, 'cleared packet has no additional')
+ same(cleared:qname(), pkt:qname(), 'cleared packet has same QNAME')
+ same(cleared:qtype(), pkt:qtype(), 'cleared packet has same QTYPE')
+ same(cleared:qclass(), pkt:qclass(), 'cleared packet has same QCLASS')
+
+ -- Recycle clears question as well
+ ok(pkt:recycle(), 'recycle() works')
+ is(pkt:ancount(), 0, 'recycle() clears records')
+ is(pkt:qname(), nil, 'recycle() clears question')
+ is(#pkt:towire(), 12, 'recycle() clears the packet wireformat')
+end
+
+-- test JSON encode/decode functions
+local function test_json_functions()
+ for msg, obj in pairs({
+ ['number'] = 0,
+ ['string'] = 'ok',
+ ['list'] = {1, 2, 3},
+ ['map'] = {foo='bar'},
+ ['nest structure'] = {foo='bar', baz={1,2,3}},
+ }) do
+ same(fromjson(tojson(obj)), obj, 'json test: ' .. msg)
+ end
+
+ for _, str in ipairs({
+ '{', '}',
+ '[', ']',
+ 'x,',
+ '[1,2,3,]',
+ }) do
+ boom(fromjson, {'{'}, 'json test: invalid \'' .. str .. '\'')
+ end
+end
+
+return {
+ test_constants,
+ test_globals,
+ test_rrset_functions,
+ test_packet_functions,
+ test_json_functions,
+}
diff --git a/tests/config/cache.test.lua b/tests/config/cache.test.lua
new file mode 100644
index 0000000..6e6e7e5
--- /dev/null
+++ b/tests/config/cache.test.lua
@@ -0,0 +1,59 @@
+-- test if cache module properties work
+local function test_properties()
+ is(type(cache), 'table', 'cache module is loaded')
+ is(cache.count(), 0, 'cache is empty on startup')
+ local backends = cache.backends()
+ is(type(backends), 'table', 'cache provides a list of backends')
+ ok(backends['lmdb'], 'cache provides built-in lmdb backend')
+ is(cache.current_storage, 'lmdb://', 'cache starts with lmdb backend')
+ is(cache.current_size, 100 * MB, 'cache starts with default size limit')
+ is(cache.max_ttl(10), 10, 'allows setting maximum TTL')
+ is(cache.max_ttl(), 10, 'stored maximum TTL')
+ is(cache.min_ttl(1), 1, 'allows setting minimum TTL')
+ is(cache.min_ttl(), 1, 'stored minimum TTL')
+end
+
+-- test if the stats work with reopening the cache and operations fail with closed cache
+local function test_stats()
+ ok(cache.close(), 'cache can be closed')
+ boom(cache.open, {100 * MB, 'invalid://'}, 'cache cannot be opened with invalid backend')
+
+ boom(cache.clear, {}, '.clear() does not work on closed cache')
+ boom(cache.count, {}, '.count() does not work on closed cache')
+ boom(cache.get, { 'key' }, '.get(...) does not work on closed cache')
+
+ ok(cache.open(100 * MB), 'cache can be reopened')
+ local s = cache.stats()
+ is(type(s), 'table', 'stats returns a table')
+ same({s.hit, s.miss, s.insert, s.delete}, {0, 0, 0, 0}, 'stats returns correct fields')
+end
+
+-- test if cache can be resized or shrunk
+local function test_resize()
+ ok(cache.open(200 * MB, 'lmdb://'), 'cache can be resized')
+ is(cache.current_size, 200 * MB, 'cache was resized')
+ ok(cache.open(50 * MB), 'cache can be shrunk')
+ is(cache.current_size, 50 * MB, 'cache was shrunk')
+end
+
+-- test access to cache through context
+local function test_context_cache()
+ local c = kres.context().cache
+ is(type(c), 'cdata', 'context has a cache object')
+ local s = c.stats
+ same({s.hit, s.miss, s.insert, s.delete}, {0, 0, 0, 0}, 'context cache stats works')
+ -- insert a record into cache
+ local rdata = '\1\2\3\4'
+ local rr = kres.rrset('\3com\0', kres.type.A, kres.class.IN, 66)
+ rr:add_rdata(rdata, #rdata)
+ ok(c:insert(rr, nil, 0, 0), 'cache insertion works')
+ ok(c:sync(), 'cache sync works')
+ same(s.insert, 1, 'cache insertion increments counters')
+end
+
+return {
+ test_properties,
+ test_stats,
+ test_resize,
+ test_context_cache,
+}
diff --git a/tests/config/keyfile/bad_args.args b/tests/config/keyfile/bad_args.args
new file mode 100644
index 0000000..6661ce0
--- /dev/null
+++ b/tests/config/keyfile/bad_args.args
@@ -0,0 +1 @@
+--keyfile-ro root.keys --keyfile root.keys \ No newline at end of file
diff --git a/tests/config/keyfile/bad_args.returncode b/tests/config/keyfile/bad_args.returncode
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/tests/config/keyfile/bad_args.returncode
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/tests/config/keyfile/bad_args.test.lua b/tests/config/keyfile/bad_args.test.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/config/keyfile/bad_args.test.lua
diff --git a/tests/config/keyfile/load_ta.args b/tests/config/keyfile/load_ta.args
new file mode 100644
index 0000000..2d1897d
--- /dev/null
+++ b/tests/config/keyfile/load_ta.args
@@ -0,0 +1 @@
+--keyfile-ro root2.keys \ No newline at end of file
diff --git a/tests/config/keyfile/load_ta.test.lua b/tests/config/keyfile/load_ta.test.lua
new file mode 100644
index 0000000..bfe851b
--- /dev/null
+++ b/tests/config/keyfile/load_ta.test.lua
@@ -0,0 +1,37 @@
+-- test fixtures
+
+-- count warning message, fail with other than allowed message
+warn_msg = {}
+overriding_msg="[ ta ] warning: overriding previously set trust anchors for ."
+warn_msg[overriding_msg] = 0
+function warn(fmt, ...)
+ msg = string.format(fmt, ...)
+ if warn_msg[msg] == nil then
+ fail(string.format("Not allowed warn message: %s", msg))
+ else
+ warn_msg[msg] = warn_msg[msg] + 1
+ end
+end
+
+-- tests
+
+boom(trust_anchors.add_file, {'nonwriteable/root.keys', false},
+ "Managed trust anchor in non-writeable directory")
+
+boom(trust_anchors.add_file, {'nonexist.keys', true},
+ "Nonexist unmanaged trust anchor file")
+
+trust_anchors.add_file('root2.keys', true)
+trust_anchors.add_file('root1.keys', true)
+is(warn_msg[overriding_msg], 1, "Warning message when override trust anchors")
+
+is(trust_anchors.keysets['\0'][1].key_tag, 19036,
+ "Loaded KeyTag from root1.keys")
+
+local function test_loading_from_cmdline()
+ is(trust_anchors.keysets['\0'][1].key_tag , 20326,
+ "Loaded KeyTag from cmdline file root2.keys")
+ is(warn_msg[overriding_msg], 2, "Warning message when override trust anchors")
+end
+
+return {test_loading_from_cmdline}
diff --git a/tests/config/keyfile/nonexist_keyfile1.args b/tests/config/keyfile/nonexist_keyfile1.args
new file mode 100644
index 0000000..6fead68
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile1.args
@@ -0,0 +1 @@
+--keyfile-ro nonexist \ No newline at end of file
diff --git a/tests/config/keyfile/nonexist_keyfile1.returncode b/tests/config/keyfile/nonexist_keyfile1.returncode
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile1.returncode
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/tests/config/keyfile/nonexist_keyfile1.test.lua b/tests/config/keyfile/nonexist_keyfile1.test.lua
new file mode 100644
index 0000000..be73f32
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile1.test.lua
@@ -0,0 +1,2 @@
+-- simulate building without KEYFILE_DEFAULT
+trust_anchors.keyfile_default = nil
diff --git a/tests/config/keyfile/nonexist_keyfile2.args b/tests/config/keyfile/nonexist_keyfile2.args
new file mode 100644
index 0000000..6fead68
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile2.args
@@ -0,0 +1 @@
+--keyfile-ro nonexist \ No newline at end of file
diff --git a/tests/config/keyfile/nonexist_keyfile2.returncode b/tests/config/keyfile/nonexist_keyfile2.returncode
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile2.returncode
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/tests/config/keyfile/nonexist_keyfile2.test.lua b/tests/config/keyfile/nonexist_keyfile2.test.lua
new file mode 100644
index 0000000..bb2f98b
--- /dev/null
+++ b/tests/config/keyfile/nonexist_keyfile2.test.lua
@@ -0,0 +1,2 @@
+-- simulate building with KEYFILE_DEFAULT
+trust_anchors.keyfile_default = "root1.keys"
diff --git a/tests/config/keyfile/root1.keys b/tests/config/keyfile/root1.keys
new file mode 100644
index 0000000..c734337
--- /dev/null
+++ b/tests/config/keyfile/root1.keys
@@ -0,0 +1 @@
+. 172800 DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= ; Valid: ; KeyTag:19036
diff --git a/tests/config/keyfile/root2.keys b/tests/config/keyfile/root2.keys
new file mode 100644
index 0000000..5e9d6ac
--- /dev/null
+++ b/tests/config/keyfile/root2.keys
@@ -0,0 +1 @@
+. 172800 DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU= ; Valid: ; KeyTag:20326
diff --git a/tests/config/lru.test.lua b/tests/config/lru.test.lua
new file mode 100644
index 0000000..0dbf1ce
--- /dev/null
+++ b/tests/config/lru.test.lua
@@ -0,0 +1,83 @@
+local ffi = require('ffi')
+
+-- Test LRU interface
+local function test_lru()
+ local capacity = 1024
+ local lru = kres.lru(capacity)
+ local dict = {
+ "catagmatic", "prevaricator", "statoscope", "workhand", "benzamide",
+ "alluvia", "fanciful", "bladish", "Tarsius", "unfast", "appropriative",
+ "seraphically", "monkeypod", "deflectometer", "tanglesome", "zodiacal",
+ "physiologically", "economizer", "forcepslike", "betrumpet",
+ "Danization", "broadthroat", "randir", "usherette", "nephropyosis",
+ "hematocyanin", "chrysohermidin", "uncave", "mirksome", "podophyllum",
+ "siphonognathous", "indoor", "featheriness", "forwardation",
+ "archruler", "soricoid", "Dailamite", "carmoisin", "controllability",
+ "unpragmatical", "childless", "transumpt", "productive",
+ "thyreotoxicosis", "oversorrow", "disshadow", "osse", "roar",
+ "pantomnesia", "talcer", "hydrorrhoea", "Satyridae", "undetesting",
+ "smoothbored", "widower", "sivathere", "pendle", "saltation",
+ "autopelagic", "campfight", "unexplained", "Macrorhamphosus",
+ "absconsa", "counterflory", "interdependent", "triact", "reconcentration",
+ "oversharpness", "sarcoenchondroma", "superstimulate", "assessory",
+ "pseudepiscopacy", "telescopically", "ventriloque", "politicaster",
+ "Caesalpiniaceae", "inopportunity", "Helion", "uncompatible",
+ "cephaloclasia", "oversearch", "Mahayanistic", "quarterspace",
+ "bacillogenic", "hamartite", "polytheistical", "unescapableness",
+ "Pterophorus", "cradlemaking", "Hippoboscidae", "overindustrialize",
+ "perishless", "cupidity", "semilichen", "gadge", "detrimental",
+ "misencourage", "toparchia", "lurchingly", "apocatastasis"
+ }
+
+ -- Check that key insertion works
+ local inserted = 0
+ for i, word in ipairs(dict) do
+ if lru:set(word, i) then
+ if lru:get(word) == i then
+ inserted = inserted + 1
+ end
+ end
+ end
+
+ is(inserted, #dict, 'all inserted keys can be retrieved')
+
+ -- Check that using binary data as keys works
+ local badinserts = 0
+ for i, word in ipairs(dict) do
+ local word_len = #word
+ word = ffi.cast('char *', word)
+ if lru:set(word, i, word_len) then
+ if lru:get(word, word_len) ~= i then
+ badinserts = badinserts + 1
+ end
+ end
+ end
+
+ is(badinserts, 0, 'insertion works for binary keys')
+
+ -- Sanity check that non-existent keys cannot be retrieved
+ local missing = "not in lru"
+ is(lru:get(missing, #missing, false), nil, 'key that wasnt inserted cannot be retrieved')
+
+ -- Test whether key eviction works and LRU is able to insert past the capacity
+ badinserts = 0
+ for i = 0, capacity do
+ local word = dict[1] .. tostring(i)
+ if lru:set(word, i) then
+ if lru:get(word) ~= i then
+ badinserts = badinserts + 1
+ end
+ end
+ end
+
+ is(badinserts, 0, 'insertion works for more keys than LRU capacity')
+
+ -- Delete and GC
+ lru = nil -- luacheck: ignore 311
+ collectgarbage()
+ collectgarbage()
+end
+
+return {
+ test_lru,
+} \ No newline at end of file
diff --git a/tests/config/runtest.sh b/tests/config/runtest.sh
new file mode 100755
index 0000000..11d9b46
--- /dev/null
+++ b/tests/config/runtest.sh
@@ -0,0 +1,23 @@
+#!/bin/bash -e
+export SOURCE_PATH="$(cd "$(dirname "$0")" && pwd -P)"
+export TEST_FILE="${2}"
+TEST_DIR="$(dirname $TEST_FILE)"
+export TMP_RUNDIR="$(mktemp -d)"
+export KRESD_NO_LISTEN=1
+function finish {
+ rm -rf "${TMP_RUNDIR}"
+}
+trap finish EXIT
+
+
+echo "# $(basename ${TEST_FILE})"
+cp -a "${TEST_DIR}/"* "${TMP_RUNDIR}/"
+CMDLINE_ARGS="$(cat "${TEST_FILE%.test.lua}.args" 2>/dev/null || echo "")"
+EXPECTED_RETURNCODE="$(cat "${TEST_FILE%.test.lua}.returncode" 2>/dev/null || echo 0)"
+set +e
+${DEBUGGER} ${1} -f 1 -c ${SOURCE_PATH}/test.cfg $CMDLINE_ARGS "${TMP_RUNDIR}"
+RETCODE="$?"
+if [ "$RETCODE" -ne "$EXPECTED_RETURNCODE" ]; then
+ echo "Expected return code '$EXPECTED_RETURNCODE' got '$RETCODE'."
+fi
+test "$RETCODE" -eq "$EXPECTED_RETURNCODE"
diff --git a/tests/config/tapered/.travis.yml b/tests/config/tapered/.travis.yml
new file mode 100644
index 0000000..77135af
--- /dev/null
+++ b/tests/config/tapered/.travis.yml
@@ -0,0 +1,40 @@
+language: c
+
+sudo: false
+
+env:
+ global:
+ - LUAROCKS=2.4.3
+ matrix:
+ - LUA=lua5.1
+ - LUA=lua5.2
+ - LUA=lua5.3
+ - LUA=luajit # latest stable version (2.0.4)
+ - LUA=luajit2.0 # current head of 2.0 branch
+ - LUA=luajit2.1 # current head of 2.1 branch
+
+branches:
+ only:
+ - bugfix
+ - master
+
+before_install:
+ - source .travis/setenv_lua.sh
+ - lua -v
+ - luarocks install luacov
+
+script:
+ - cd test
+ - git clone https://github.com/sstephenson/bats.git
+ - ./bats/bin/bats runner.bash
+
+after_success:
+ - luacov
+ - cp -v luacov.report.out ../
+ - cd ..
+ - bash <(curl -s https://codecov.io/bash)
+
+notifications:
+ email:
+ on_success: change
+ on_failure: always
diff --git a/tests/config/tapered/.travis/platform.sh b/tests/config/tapered/.travis/platform.sh
new file mode 100644
index 0000000..7259a7d
--- /dev/null
+++ b/tests/config/tapered/.travis/platform.sh
@@ -0,0 +1,15 @@
+if [ -z "${PLATFORM:-}" ]; then
+ PLATFORM=$TRAVIS_OS_NAME;
+fi
+
+if [ "$PLATFORM" == "osx" ]; then
+ PLATFORM="macosx";
+fi
+
+if [ -z "$PLATFORM" ]; then
+ if [ "$(uname)" == "Linux" ]; then
+ PLATFORM="linux";
+ else
+ PLATFORM="macosx";
+ fi;
+fi
diff --git a/tests/config/tapered/.travis/setenv_lua.sh b/tests/config/tapered/.travis/setenv_lua.sh
new file mode 100644
index 0000000..8d8c825
--- /dev/null
+++ b/tests/config/tapered/.travis/setenv_lua.sh
@@ -0,0 +1,3 @@
+export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin
+bash .travis/setup_lua.sh
+eval `$HOME/.lua/luarocks path`
diff --git a/tests/config/tapered/.travis/setup_lua.sh b/tests/config/tapered/.travis/setup_lua.sh
new file mode 100644
index 0000000..a72b6d2
--- /dev/null
+++ b/tests/config/tapered/.travis/setup_lua.sh
@@ -0,0 +1,122 @@
+#! /bin/bash
+
+# A script for setting up environment for travis-ci testing.
+# Sets up Lua and Luarocks.
+# LUA must be "lua5.1", "lua5.2" or "luajit".
+# luajit2.0 - master v2.0
+# luajit2.1 - master v2.1
+
+set -eufo pipefail
+
+LUAJIT_VERSION="2.0.4"
+LUAJIT_BASE="LuaJIT-$LUAJIT_VERSION"
+
+source .travis/platform.sh
+
+LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua
+
+LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks
+
+mkdir $HOME/.lua
+
+LUAJIT="no"
+
+if [ "$PLATFORM" == "macosx" ]; then
+ if [ "$LUA" == "luajit" ]; then
+ LUAJIT="yes";
+ fi
+ if [ "$LUA" == "luajit2.0" ]; then
+ LUAJIT="yes";
+ fi
+ if [ "$LUA" == "luajit2.1" ]; then
+ LUAJIT="yes";
+ fi;
+elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then
+ LUAJIT="yes";
+fi
+
+mkdir -p "$LUA_HOME_DIR"
+
+if [ "$LUAJIT" == "yes" ]; then
+
+ if [ "$LUA" == "luajit" ]; then
+ curl --location https://github.com/LuaJIT/LuaJIT/archive/v$LUAJIT_VERSION.tar.gz | tar xz;
+ else
+ git clone https://github.com/LuaJIT/LuaJIT.git $LUAJIT_BASE;
+ fi
+
+ cd $LUAJIT_BASE
+
+ if [ "$LUA" == "luajit2.1" ]; then
+ git checkout v2.1;
+ # force the INSTALL_TNAME to be luajit
+ perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile
+ fi
+
+ make && make install PREFIX="$LUA_HOME_DIR"
+
+ ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit
+ ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua;
+
+else
+
+ if [ "$LUA" == "lua5.1" ]; then
+ curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz
+ cd lua-5.1.5;
+ elif [ "$LUA" == "lua5.2" ]; then
+ curl http://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz
+ cd lua-5.2.4;
+ elif [ "$LUA" == "lua5.3" ]; then
+ curl http://www.lua.org/ftp/lua-5.3.4.tar.gz | tar xz
+ cd lua-5.3.4;
+ fi
+
+ # Build Lua without backwards compatibility for testing
+ perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile
+ make $PLATFORM
+ make INSTALL_TOP="$LUA_HOME_DIR" install;
+
+ ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua
+ ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac;
+
+fi
+
+cd $TRAVIS_BUILD_DIR
+
+lua -v
+
+LUAROCKS_BASE=luarocks-$LUAROCKS
+
+curl --location http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz
+
+cd $LUAROCKS_BASE
+
+if [ "$LUA" == "luajit" ]; then
+ ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR";
+elif [ "$LUA" == "luajit2.0" ]; then
+ ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR";
+elif [ "$LUA" == "luajit2.1" ]; then
+ ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" --prefix="$LR_HOME_DIR";
+else
+ ./configure --with-lua="$LUA_HOME_DIR" --prefix="$LR_HOME_DIR"
+fi
+
+make build && make install
+
+ln -s $LR_HOME_DIR/bin/luarocks $HOME/.lua/luarocks
+
+cd $TRAVIS_BUILD_DIR
+
+luarocks --version
+
+rm -rf $LUAROCKS_BASE
+
+if [ "$LUAJIT" == "yes" ]; then
+ rm -rf $LUAJIT_BASE;
+elif [ "$LUA" == "lua5.1" ]; then
+ rm -rf lua-5.1.5;
+elif [ "$LUA" == "lua5.2" ]; then
+ rm -rf lua-5.2.4;
+elif [ "$LUA" == "lua5.3" ]; then
+ rm -rf lua-5.3.4;
+fi
diff --git a/tests/config/tapered/CHANGES.md b/tests/config/tapered/CHANGES.md
new file mode 100644
index 0000000..63b19b0
--- /dev/null
+++ b/tests/config/tapered/CHANGES.md
@@ -0,0 +1,70 @@
+# tapered version history
+
+## *1.0-0* (July 10, 2015)
+
++ Initial public release
+
+## *1.0-1* (July 10, 2015)
+
++ Fix rockspec: the URL for Bitbucket was wrong.
+
+## *1.1-0* (July 13, 2015)
+
++ Improve organization and coverage of tests
++ Refactor the `same` method
++ Remove `same_mt`
++ Meaningful exit statuses via `done`
++ Add CI via [drone.io][dio]
+
+[dio]: https://drone.io/bitbucket.org/telemachus/tapered/latest
+
+## *1.2.0-1* (July 19, 2015)
+
++ Clean up code using luacheck and luacov
++ Small tweaks to README and CHANGES
++ Fix version number: the previous two digit number was a mistake, based on
+ a misunderstanding of LuaRocks conventions. This is an annoying switch, but
+ better now than later. And better to do it than to live with a versioning
+ pattern I dislike.
+
+## *1.2.1-1* (December 5, 2015)
+
++ Test coverage stats are now thanks to [codecov][codecov].
++ Latest stable Lua in the 5.3 series is 5.3.2, so we test against that now.
+
+[codecov]: https://codecov.io
+
+## *2.0.0-1* (May 1, 2016)
+
++ The informational fields are now functions that return strings. This is to prevent them from violating Lua recommendations about variables such as `_VERSION`. (I've bumped the major version number since this is technically an API change, though for most users it will not require any changes on their end.)
+
+## *2.0.1-1* (May 2, 2016)
+
++ Fix a typo in the documentation.
++ Adjust the `version()` return value to show only software version, not the rockspec version as well.
+
+## *2.1.0-1* (July 21, 2016)
+
++ Update to test against Lua 5.3.3
+
+## *2.2.0-1* (February 11, 2017)
+
++ Update to test against Lua 5.3.4
++ The repo is now housed on [Github](https://github.com/telemachus/tapered)
++ CI is now provided by [Travis.ci](https://travis-ci.org/telemachus/tapered)
+
+## *2.3.0-1* (October 15, 2017)
+
++ Remove `setup()` and `teardown()`
++ Update to use luarocks 2.4.3 for testing on Travis
+
+Would you rather view the [documentation][d]?
+
+[d]: /README.md
+
+---
+
+(c) 2012-2017 Peter Aronoff. BSD 3-Clause license; see [LICENSE.md][l] for
+details.
+
+[l]: /LICENSE.md
diff --git a/tests/config/tapered/LICENSE.md b/tests/config/tapered/LICENSE.md
new file mode 100644
index 0000000..bcaacde
--- /dev/null
+++ b/tests/config/tapered/LICENSE.md
@@ -0,0 +1,27 @@
+Copyright (c) 2012-2017, Peter Aronoff 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
diff --git a/tests/config/tapered/README.md b/tests/config/tapered/README.md
new file mode 100644
index 0000000..bafb2e7
--- /dev/null
+++ b/tests/config/tapered/README.md
@@ -0,0 +1,116 @@
+# tapered [![Build Status](https://travis-ci.org/telemachus/tapered.svg?branch=master)](https://travis-ci.org/telemachus/tapered) [![Coverage](https://codecov.io/gh/telemachus/tapered/branch/master/graph/badge.svg)](https://codecov.io/gh/telemachus/tapered)
+
+## Synopsis
+
+Very minimal tap testing for Lua. Arguably too minimal.
+
+## Assertions
+
+The `message` parameter is always optional. Brief messages help make test output
+clearer to readers, but are not needed if the output goes straight to another
+program for parsing.
+
++ `ok(expression, [message])` Tests whether `expression` returns a truthy
+ value.
+
++ `nok(expression, [message])` Tests whether `expression` returns a falsy
+ value.
+
++ `is(actual, expected, [message])` Tests whether `actual` is equal to
+ `expected`. The test uses `==` internally.
+
++ `isnt(actual, expected, [message])` Tests whether `actual` is not equal to
+ `actual`. The test uses `~=` internally.
+
++ `same(actual, expected, [message])` Tests whether `actual` is a deep copy
+ of `expected`. The test uses an `__eq` metamethod if one is found. Useful
+ for comparing tables.
+
++ `like(string, pattern, [message])` Tests whether `string` matches the given
+ `pattern`.
+
++ `unlike(string, pattern, [message])` Tests whether `string` does not match
+ the given `pattern`.
+
++ `pass([message])` A test that always passes. Useful as a quasi-skip with a
+ message.
+
++ `fail([message])` A test that always fails. Useful as a quasi-TODO with a
+ message.
+
++ `boom(function, args, [message])` Calls `function` with `args` as
+ parameters and checks to see if an exception is raised. Passes if an
+ exception is raised; fails otherwise. (The exception is swallowed.) The
+ `args` parameter expects a table. The table can be empty but not `nil`.
+
+## Helper method
+
+A method is available to show how many tests were run. (This output
+is required for [TAP compliance][tap], which may matter in some cases.)
+
+[tap]: http://testanything.org/tap-specification.html
+
++ `done([number])` Call this function (optionally) at the end of your test file.
+ It will print out a line in the form `1..n` where `n` is the total number
+ of tests run. This secures TAP compliance when needed. The call to `done`
+ is not otherwise required. If you don't care about TAP compliance, neither does
+ the library. If you pass the optional parameter to the method, it will check
+ whether the number of tests you expected matches the number of actual tests.
+ Thus, if can function like a traditional `plan` method. However, this method
+ should always be called *last* in your tap file, unlike `plan` methods which
+ normally start the test file.
+
+ Another reason to use `done` is if you care about the exit status of the
+ tests. Many continuous integration tools rely on tests signalling success or
+ failure via their exit status. After `done` is called, the script will exit
+ with a status of 0, indicating success, if all tests passed. If some tests
+ failed, the script will exit with a status equal to the number of failed
+ tests, indicating failure. A script will also exit with an error status if
+ there is a mismatch between the actual number of tests run and the number
+ passed to `done` as a parameter.
+
+## Varia
+
+The module provides four informational functions that return strings. They
+should be self-explanatory.
+
++ `version() -- 2.3.0`
+
++ `author() -- Peter Aronoff`
+
++ `url() -- https://github.com/telemachus/tapered.git`
+
++ `license() -- BSD 3-Clause`
+
+## Credits
+
+For the `same` method I took ideas and code from [Penlight][p], [Underscore][u],
+[luassert][l], and [cwtest][cw]. I thank all the people who worked on those.
+
+Indirect inspirations include [knock][k], [Test::More][tm], and [bats][b]—not so
+much for code as for ideas about testing and simplicity.
+
+Thanks in particular to [Pierre Chapuis][pchapuis] for help with ideas and
+getting continuous integration for tapered.
+
+An anonymous email showed me that my setup and teardown methods had a logical
+flaw. As a result, I've removed those methods. I appreciate the report.
+
+All the mistakes are mine. See [version history][c] for release details.
+
+[p]: https://github.com/stevedonovan/Penlight
+[u]: https://github.com/mirven/underscore.lua
+[l]: https://github.com/Olivine-Labs/luassert
+[cw]: https://github.com/catwell/cwtest
+[k]: https://github.com/chneukirchen/knock
+[tm]: http://search.cpan.org/perldoc?Test::More
+[b]: https://github.com/sstephenson/bats
+[c]: /CHANGES.md
+[pchapuis]: https://twitter.com/pchapuis
+
+---
+
+(c) 2012-2017 Peter Aronoff. BSD 3-Clause license; see [LICENSE.md][li] for
+details.
+
+[li]: /LICENSE.md
diff --git a/tests/config/tapered/doc/changes.html b/tests/config/tapered/doc/changes.html
new file mode 100644
index 0000000..a4f7034
--- /dev/null
+++ b/tests/config/tapered/doc/changes.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="author" content="Peter Aronoff">
+<title>tapered version history</title>
+<link rel="stylesheet" href="normalize.css" media="screen,projection">
+<link rel="stylesheet" href="screen.css" media="screen,projection">
+</head>
+<body>
+<h1>tapered version history</h1>
+
+<h2><em>1.0-0</em> (July 10, 2015)</h2>
+
+<ul>
+<li>Initial public release</li>
+</ul>
+
+
+<h2><em>1.0-1</em> (July 10, 2015)</h2>
+
+<ul>
+<li>Fix rockspec: the URL for Bitbucket was wrong.</li>
+</ul>
+
+
+<h2><em>1.1-0</em> (July 13, 2015)</h2>
+
+<ul>
+<li>Improve organization and coverage of tests</li>
+<li>Refactor the <code>same</code> method</li>
+<li>Remove <code>same_mt</code></li>
+<li>Meaningful exit statuses via <code>done</code></li>
+<li>Add CI via <a href="https://drone.io/bitbucket.org/telemachus/tapered/latest">drone.io</a></li>
+</ul>
+
+
+<h2><em>1.2.0-1</em> (July 19, 2015)</h2>
+
+<ul>
+<li>Clean up code using luacheck and luacov</li>
+<li>Small tweaks to README and CHANGES</li>
+<li>Fix version number: the previous two digit number was a mistake, based on
+a misunderstanding of LuaRocks conventions. This is an annoying switch, but
+better now than later. And better to do it than to live with a versioning
+pattern I dislike.</li>
+</ul>
+
+
+<h2><em>1.2.1-1</em> (December 5, 2015)</h2>
+
+<ul>
+<li>Test coverage stats are now thanks to <a href="https://codecov.io">codecov</a>.</li>
+<li>Latest stable Lua in the 5.3 series is 5.3.2, so we test against that now.</li>
+</ul>
+
+
+<h2><em>2.0.0-1</em> (May 1, 2016)</h2>
+
+<ul>
+<li>The informational fields are now functions that return strings. This is to prevent them from violating Lua recommendations about variables such as <code>_VERSION</code>. (I&rsquo;ve bumped the major version number since this is technically an API change, though for most users it will not require any changes on their end.)</li>
+</ul>
+
+
+<h2><em>2.0.1-1</em> (May 2, 2016)</h2>
+
+<ul>
+<li>Fix a typo in the documentation.</li>
+<li>Adjust the <code>version()</code> return value to show only software version, not the rockspec version as well.</li>
+</ul>
+
+
+<h2><em>2.1.0-1</em> (July 21, 2016)</h2>
+
+<ul>
+<li>Update to test against Lua 5.3.3</li>
+</ul>
+
+
+<h2><em>2.2.0-1</em> (February 11, 2017)</h2>
+
+<ul>
+<li>Update to test against Lua 5.3.4</li>
+<li>The repo is now housed on <a href="https://github.com/telemachus/tapered">Github</a></li>
+<li>CI is now provided by <a href="https://travis-ci.org/telemachus/tapered">Travis.ci</a></li>
+</ul>
+
+
+<h2><em>2.3.0-1</em> (October 15, 2017)</h2>
+
+<ul>
+<li>Remove <code>setup()</code> and <code>teardown()</code></li>
+<li>Update to use luarocks 2.4.3 for testing on Travis</li>
+</ul>
+
+
+<p>Would you rather view the <a href="index.html">documentation</a>?</p>
+
+<hr />
+
+<p>&copy; 2012-2017 Peter Aronoff. BSD 3-Clause license; see <a href="license.html">the license</a> for
+details.</p>
+</body>
+</html>
diff --git a/tests/config/tapered/doc/index.html b/tests/config/tapered/doc/index.html
new file mode 100644
index 0000000..69d6b24
--- /dev/null
+++ b/tests/config/tapered/doc/index.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="author" content="Peter Aronoff">
+<title>tapered documentation</title>
+<link rel="stylesheet" href="normalize.css" media="screen,projection">
+<link rel="stylesheet" href="screen.css" media="screen,projection">
+</head>
+<body>
+<h1>tapered <a href="https://travis-ci.org/telemachus/tapered"><img src="https://travis-ci.org/telemachus/tapered.svg?branch=master" alt="Build Status" /></a> <a href="https://codecov.io/gh/telemachus/tapered"><img src="https://codecov.io/gh/telemachus/tapered/branch/master/graph/badge.svg" alt="Coverage" /></a></h1>
+
+<h2>Synopsis</h2>
+
+<p>Very minimal tap testing for Lua. Arguably too minimal.</p>
+
+<h2>Assertions</h2>
+
+<p>The <code>message</code> parameter is always optional. Brief messages help make test output
+clearer to readers, but are not needed if the output goes straight to another
+program for parsing.</p>
+
+<ul>
+<li><p><code>ok(expression, [message])</code> Tests whether <code>expression</code> returns a truthy
+value.</p></li>
+<li><p><code>nok(expression, [message])</code> Tests whether <code>expression</code> returns a falsy
+value.</p></li>
+<li><p><code>is(actual, expected, [message])</code> Tests whether <code>actual</code> is equal to
+<code>expected</code>. The test uses <code>==</code> internally.</p></li>
+<li><p><code>isnt(actual, expected, [message])</code> Tests whether <code>actual</code> is not equal to
+<code>actual</code>. The test uses <code>~=</code> internally.</p></li>
+<li><p><code>same(actual, expected, [message])</code> Tests whether <code>actual</code> is a deep copy
+of <code>expected</code>. The test uses an <code>__eq</code> metamethod if one is found. Useful
+for comparing tables.</p></li>
+<li><p><code>like(string, pattern, [message])</code> Tests whether <code>string</code> matches the given
+<code>pattern</code>.</p></li>
+<li><p><code>unlike(string, pattern, [message])</code> Tests whether <code>string</code> does not match
+the given <code>pattern</code>.</p></li>
+<li><p><code>pass([message])</code> A test that always passes. Useful as a quasi-skip with a
+message.</p></li>
+<li><p><code>fail([message])</code> A test that always fails. Useful as a quasi-TODO with a
+message.</p></li>
+<li><p><code>boom(function, args, [message])</code> Calls <code>function</code> with <code>args</code> as
+parameters and checks to see if an exception is raised. Passes if an
+exception is raised; fails otherwise. (The exception is swallowed.) The
+<code>args</code> parameter expects a table. The table can be empty but not <code>nil</code>.</p></li>
+</ul>
+
+
+<h2>Helper method</h2>
+
+<p>A method is available to show how many tests were run. (This output
+is required for <a href="http://testanything.org/tap-specification.html">TAP compliance</a>, which may matter in some cases.)</p>
+
+<ul>
+<li><p><code>done([number])</code> Call this function (optionally) at the end of your test file.
+It will print out a line in the form <code>1..n</code> where <code>n</code> is the total number
+of tests run. This secures TAP compliance when needed. The call to <code>done</code>
+is not otherwise required. If you don&rsquo;t care about TAP compliance, neither does
+the library. If you pass the optional parameter to the method, it will check
+whether the number of tests you expected matches the number of actual tests.
+Thus, if can function like a traditional <code>plan</code> method. However, this method
+should always be called <em>last</em> in your tap file, unlike <code>plan</code> methods which
+normally start the test file.</p>
+
+<p>Another reason to use <code>done</code> is if you care about the exit status of the
+tests. Many continuous integration tools rely on tests signalling success or
+failure via their exit status. After <code>done</code> is called, the script will exit
+with a status of 0, indicating success, if all tests passed. If some tests
+failed, the script will exit with a status equal to the number of failed
+tests, indicating failure. A script will also exit with an error status if
+there is a mismatch between the actual number of tests run and the number
+passed to <code>done</code> as a parameter.</p></li>
+</ul>
+
+
+<h2>Varia</h2>
+
+<p>The module provides four informational functions that return strings. They
+should be self-explanatory.</p>
+
+<ul>
+<li><p><code>version() -- 2.3.0</code></p></li>
+<li><p><code>author() -- Peter Aronoff</code></p></li>
+<li><p><code>url() -- https://github.com/telemachus/tapered.git</code></p></li>
+<li><p><code>license() -- BSD 3-Clause</code></p></li>
+</ul>
+
+
+<h2>Credits</h2>
+
+<p>For the <code>same</code> method I took ideas and code from <a href="https://github.com/stevedonovan/Penlight">Penlight</a>, <a href="https://github.com/mirven/underscore.lua">Underscore</a>,
+<a href="https://github.com/Olivine-Labs/luassert">luassert</a>, and <a href="https://github.com/catwell/cwtest">cwtest</a>. I thank all the people who worked on those.</p>
+
+<p>Indirect inspirations include <a href="https://github.com/chneukirchen/knock">knock</a>, <a href="http://search.cpan.org/perldoc?Test::More">Test::More</a>, and <a href="https://github.com/sstephenson/bats">bats</a>—not so
+much for code as for ideas about testing and simplicity.</p>
+
+<p>Thanks in particular to <a href="https://twitter.com/pchapuis">Pierre Chapuis</a> for help with ideas and
+getting continuous integration for tapered.</p>
+
+<p>An anonymous email showed me that my setup and teardown methods had a logical
+flaw. As a result, I&rsquo;ve removed those methods. I appreciate the report.</p>
+
+<p>All the mistakes are mine. See <a href="changes.html">version history</a> for release details.</p>
+
+<hr />
+
+<p>&copy; 2012-2017 Peter Aronoff. BSD 3-Clause license; see <a href="license.html">the license</a> for
+details.</p>
+</body>
+</html>
diff --git a/tests/config/tapered/doc/license.html b/tests/config/tapered/doc/license.html
new file mode 100644
index 0000000..7c8ae8c
--- /dev/null
+++ b/tests/config/tapered/doc/license.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="author" content="Peter Aronoff">
+<title>tapered license</title>
+<link rel="stylesheet" href="normalize.css" media="screen,projection">
+<link rel="stylesheet" href="screen.css" media="screen,projection">
+</head>
+<body>
+<p>Copyright &copy; 2012-2017, Peter Aronoff All rights reserved.</p>
+
+<p>Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:</p>
+
+<ol>
+<li><p>Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.</p></li>
+<li><p>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.</p></li>
+<li><p>Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.</p></li>
+</ol>
+
+
+<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &ldquo;AS IS&rdquo;
+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 COPYRIGHT HOLDER 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.</p>
+</body>
+</html>
diff --git a/tests/config/tapered/doc/normalize.css b/tests/config/tapered/doc/normalize.css
new file mode 100644
index 0000000..9fc7ae4
--- /dev/null
+++ b/tests/config/tapered/doc/normalize.css
@@ -0,0 +1,439 @@
+/*! normalize.css 2011-08-12T17:28 UTC · http://github.com/necolas/normalize.css */
+
+/* =============================================================================
+ HTML5 display definitions
+ ========================================================================== */
+
+/*
+ * Corrects block display not defined in IE6/7/8/9 & FF3
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+ display: block;
+}
+
+/*
+ * Corrects inline-block display not defined in IE6/7/8/9 & FF3
+ */
+
+audio,
+canvas,
+video {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+}
+
+/*
+ * Prevents modern browsers from displaying 'audio' without controls
+ */
+
+audio:not([controls]) {
+ display: none;
+}
+
+/*
+ * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
+ * Known issue: no IE6 support
+ */
+
+[hidden] {
+ display: none;
+}
+
+
+/* =============================================================================
+ Base
+ ========================================================================== */
+
+/*
+ * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
+ * http://clagnut.com/blog/348/#c790
+ * 2. Keeps page centred in all browsers regardless of content height
+ * 3. Prevents iOS text size adjust after orientation change, without disabling user zoom
+ * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
+ */
+
+html {
+ font-size: 100%; /* 1 */
+ overflow-y: scroll; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 3 */
+ -ms-text-size-adjust: 100%; /* 3 */
+}
+
+/*
+ * Addresses margins handled incorrectly in IE6/7
+ */
+
+body {
+ margin: 0;
+}
+
+/*
+ * Addresses font-family inconsistency between 'textarea' and other form elements.
+ */
+
+body,
+button,
+input,
+select,
+textarea {
+ font-family: sans-serif;
+}
+
+
+/* =============================================================================
+ Links
+ ========================================================================== */
+
+a {
+ color: #00e;
+}
+
+a:visited {
+ color: #551a8b;
+}
+
+/*
+ * Addresses outline displayed oddly in Chrome
+ */
+
+a:focus {
+ outline: thin dotted;
+}
+
+/*
+ * Improves readability when focused and also mouse hovered in all browsers
+ * people.opera.com/patrickl/experiments/keyboard/test
+ */
+
+a:hover,
+a:active {
+ outline: 0;
+}
+
+
+/* =============================================================================
+ Typography
+ ========================================================================== */
+
+/*
+ * Addresses styling not present in IE7/8/9, S5, Chrome
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/*
+ * Addresses style set to 'bolder' in FF3/4, S4/5, Chrome
+*/
+
+b,
+strong {
+ font-weight: bold;
+}
+
+blockquote {
+ margin: 1em 40px;
+}
+
+/*
+ * Addresses styling not present in S5, Chrome
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/*
+ * Addresses styling not present in IE6/7/8/9
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/*
+ * Corrects font family set oddly in IE6, S4/5, Chrome
+ * en.wikipedia.org/wiki/User:Davidgothberg/Test59
+ */
+
+pre,
+code,
+kbd,
+samp {
+ font-family: monospace, serif;
+ _font-family: 'courier new', monospace;
+ font-size: 1em;
+}
+
+/*
+ * Improves readability of pre-formatted text in all browsers
+ */
+
+pre {
+ white-space: pre;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+/*
+ * 1. Addresses CSS quotes not supported in IE6/7
+ * 2. Addresses quote property not supported in S4
+ */
+
+/* 1 */
+
+q {
+ quotes: none;
+}
+
+/* 2 */
+
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
+
+small {
+ font-size: 75%;
+}
+
+/*
+ * Prevents sub and sup affecting line-height in all browsers
+ * gist.github.com/413930
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+
+/* =============================================================================
+ Lists
+ ========================================================================== */
+
+ul,
+ol {
+ margin: 1em 0;
+ padding: 0 0 0 40px;
+}
+
+dd {
+ margin: 0 0 0 40px;
+}
+
+nav ul,
+nav ol {
+ list-style: none;
+ list-style-image: none;
+}
+
+
+/* =============================================================================
+ Embedded content
+ ========================================================================== */
+
+/*
+ * 1. Removes border when inside 'a' element in IE6/7/8/9
+ * 2. Improves image quality when scaled in IE7
+ * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
+ */
+
+img {
+ border: 0; /* 1 */
+ -ms-interpolation-mode: bicubic; /* 2 */
+}
+
+/*
+ * Corrects overflow displayed oddly in IE9
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+
+/* =============================================================================
+ Figures
+ ========================================================================== */
+
+/*
+ * Addresses margin not present in IE6/7/8/9, S5, O11
+ */
+
+figure {
+ margin: 0;
+}
+
+
+/* =============================================================================
+ Forms
+ ========================================================================== */
+
+/*
+ * Corrects margin displayed oddly in IE6/7
+ */
+
+form {
+ margin: 0;
+}
+
+/*
+ * Define consistent margin and padding
+ */
+
+fieldset {
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/*
+ * 1. Corrects color not being inherited in IE6/7/8/9
+ * 2. Corrects alignment displayed oddly in IE6/7
+ */
+
+legend {
+ border: 0; /* 1 */
+ *margin-left: -7px; /* 2 */
+}
+
+/*
+ * 1. Corrects font size not being inherited in all browsers
+ * 2. Addresses margins set differently in IE6/7, F3/4, S5, Chrome
+ * 3. Improves appearance and consistency in all browsers
+ */
+
+button,
+input,
+select,
+textarea {
+ font-size: 100%; /* 1 */
+ margin: 0; /* 2 */
+ vertical-align: baseline; /* 3 */
+ *vertical-align: middle; /* 3 */
+}
+
+/*
+ * 1. Addresses FF3/4 setting line-height using !important in the UA stylesheet
+ * 2. Corrects inner spacing displayed oddly in IE6/7
+ */
+
+button,
+input {
+ line-height: normal; /* 1 */
+ *overflow: visible; /* 2 */
+}
+
+/*
+ * Corrects overlap and whitespace issue for buttons and inputs in IE6/7
+ * Known issue: reintroduces inner spacing
+ */
+
+table button,
+table input {
+ *overflow: auto;
+}
+
+/*
+ * 1. Improves usability and consistency of cursor style between image-type 'input' and others
+ * 2. Corrects inability to style clickable 'input' types in iOS
+ */
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ cursor: pointer; /* 1 */
+ -webkit-appearance: button; /* 2 */
+}
+
+/*
+ * 1. Addresses box sizing set to content-box in IE8/9
+ * 2. Addresses excess padding in IE8/9
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/*
+ * 1. Addresses appearance set to searchfield in S5, Chrome
+ * 2. Addresses box sizing set to border-box in S5, Chrome (include -moz to future-proof)
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/*
+ * Corrects inner padding displayed oddly in S5, Chrome on OSX
+ */
+
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+ * Corrects inner padding and border displayed oddly in FF3/4
+ * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/*
+ * 1. Removes default vertical scrollbar in IE6/7/8/9
+ * 2. Improves readability and alignment in all browsers
+ */
+
+textarea {
+ overflow: auto; /* 1 */
+ vertical-align: top; /* 2 */
+}
+
+
+/* =============================================================================
+ Tables
+ ========================================================================== */
+
+/*
+ * Remove most spacing between table cells
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
diff --git a/tests/config/tapered/doc/screen.css b/tests/config/tapered/doc/screen.css
new file mode 100644
index 0000000..2583183
--- /dev/null
+++ b/tests/config/tapered/doc/screen.css
@@ -0,0 +1,109 @@
+body {
+ margin: 10px auto;
+ width: 820px;
+ font-size: 18px;
+ font-family: "DejaVuSerifBook", "Palatino", "Palatino Linotype", serif;
+ color: #333;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: "DejaVuSansBook", "Lucida Grande", "Helvetica Neue", sans-serif;
+ font-weight: bold;
+ line-height: 1.6;
+ margin-bottom: 5px;
+ color: #111;
+}
+
+h1 {
+ margin-top: 10px;
+}
+
+h2, h3, h4, h5, h6 { margin-top: 20px; }
+
+h1 { font-size: 28px; }
+
+h2 { font-size: 24px; border-bottom: solid 4px; }
+h3 { font-size: 20px; }
+
+p {
+ line-height: 1.3;
+ margin: 12px auto;
+
+}
+
+code {
+ font-family: "DejaVuSansMono", Inconsolata, Consolas, Menlo, monospace;
+}
+
+blockquote {
+ margin: 10px 30px 10px 20px;
+}
+
+blockquote p {
+ line-height: 1.2;
+}
+
+ul, ol, ul p, ol p {
+ margin-left: 0;
+ line-height: 1.3;
+}
+
+ul ul, ol ol {
+ font-size: 100%;
+}
+
+ul {
+ list-style-type: disc;
+}
+
+ul ul {
+ list-style-type: circle;
+}
+
+ul ul ul {
+ list-style-type: square;
+}
+
+ul ul ul ul {
+ list-style-type: disc;
+}
+
+h2 + p {
+ margin-top: 15px;
+}
+
+a:link, a:visited {
+ text-decoration: underline;
+ color: #336891;
+}
+
+a:hover, a:focus {
+ text-decoration: none;
+ color: #336891;
+}
+
+pre {
+ margin: 30px 15px;
+ padding: 10px 5px 10px 15px;
+ border: solid black 5px;
+ border-left: solid black 30px;
+ font-size: 14px;
+ line-height: 1.3;
+ background: #FFF;
+ color: #000;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+}
+
+ins {
+ text-decoration: none;
+}
+
+ins:before {
+ content: "〈";
+}
+
+ins:after {
+ content: "〉";
+}
diff --git a/tests/config/tapered/make-doc.bash b/tests/config/tapered/make-doc.bash
new file mode 100755
index 0000000..4ceb65d
--- /dev/null
+++ b/tests/config/tapered/make-doc.bash
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+{
+ printf "<!DOCTYPE html>\n"
+ printf "<html lang=\"en\">\n"
+ printf "<head>\n"
+ printf "<meta charset=\"utf-8\">\n"
+ printf "<meta name=\"author\" content=\"Peter Aronoff\">\n"
+ printf "<title>tapered documentation</title>\n"
+ printf "<link rel=\"stylesheet\" href=\"normalize.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "<link rel=\"stylesheet\" href=\"screen.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "</head>\n"
+ printf "<body>\n"
+ markdown README.md | sed -e 's/\/CHANGES.md/changes.html/' -e 's/\/LICENSE.md/license.html/' -e 's/LICENSE.md/the license/'
+ printf "</body>\n"
+ printf "</html>\n"
+} > doc/index.html
+
+{
+ printf "<!DOCTYPE html>\n"
+ printf "<html lang=\"en\">\n"
+ printf "<head>\n"
+ printf "<meta charset=\"utf-8\">\n"
+ printf "<meta name=\"author\" content=\"Peter Aronoff\">\n"
+ printf "<title>tapered version history</title>\n"
+ printf "<link rel=\"stylesheet\" href=\"normalize.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "<link rel=\"stylesheet\" href=\"screen.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "</head>\n"
+ printf "<body>\n"
+ markdown CHANGES.md | sed -e 's/\/README.md/index.html/' -e 's/\/LICENSE.md/license.html/' -e 's/LICENSE.md/the license/'
+ printf "</body>\n"
+ printf "</html>\n"
+} > doc/changes.html
+
+{
+ printf "<!DOCTYPE html>\n"
+ printf "<html lang=\"en\">\n"
+ printf "<head>\n"
+ printf "<meta charset=\"utf-8\">\n"
+ printf "<meta name=\"author\" content=\"Peter Aronoff\">\n"
+ printf "<title>tapered license</title>\n"
+ printf "<link rel=\"stylesheet\" href=\"normalize.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "<link rel=\"stylesheet\" href=\"screen.css\" "
+ printf "media=\"screen,projection\">\n"
+ printf "</head>\n"
+ printf "<body>\n"
+ markdown LICENSE.md
+ printf "</body>\n"
+ printf "</html>\n"
+} > doc/license.html
diff --git a/tests/config/tapered/src/tapered.lua b/tests/config/tapered/src/tapered.lua
new file mode 100644
index 0000000..5bcb331
--- /dev/null
+++ b/tests/config/tapered/src/tapered.lua
@@ -0,0 +1,189 @@
+-- Helper variables and functions
+local get_info = debug.getinfo
+local pcall = pcall
+local slice = string.sub
+local sprintf = string.format
+local str_find = string.find
+local tonumber = tonumber
+-- Lua 5.3 moved unpack to table.unpack
+local unpack = unpack or table.unpack
+local write = io.write
+local rawget = rawget
+local getmetatable = getmetatable
+local exit = os.exit
+
+---- Helper methods
+
+--- C-like printf method
+local printf = function(fmt, ...)
+ write(sprintf(fmt, ...))
+end
+
+--- Compare potentially complex tables or objects
+--
+-- Ideas here are taken from [Penlight][p], [Underscore][u], [cwtest][cw], and
+-- [luassert][l].
+-- [p]: https://github.com/stevedonovan/Penlight
+-- [u]: https://github.com/mirven/underscore.lua
+-- [cw]: https://github.com/catwell/cwtest
+-- [l]: https://github.com/Olivine-Labs/luassert
+--
+-- Predeclare both function names
+local keyvaluesame
+local deepsame
+--
+--- keyvaluesame(table, table) => true or false
+-- Helper method to compare all the keys and values of a table
+keyvaluesame = function (t1, t2)
+ for k1, v1 in pairs(t1) do
+ local v2 = t2[k1]
+ if v2 == nil or not deepsame(v1, v2) then return false end
+ end
+
+ -- Check for any keys present in t2 but not t1
+ for k2, _ in pairs(t2) do
+ if t1[k2] == nil then return false end
+ end
+
+ return true
+end
+--
+--- deepsame(item, item) => true or false
+-- Compare two items of any type for identity
+deepsame = function (t1, t2)
+ local ty1, ty2 = type(t1), type(t2)
+ if ty1 ~= ty2 then return false end
+ if ty1 ~= 'table' then return t1 == t2 end
+
+ -- If ._eq is found, use == and end quickly.
+ -- As of Lua 5.3 == only cares if **one** of the two items has a __eq
+ -- metamethod. Penlight, underscore and cwtest take the same approach,
+ -- so I will as well.
+ local eq = rawget(getmetatable(t1) or {}, '__eq')
+ if (type(eq) == 'function') then
+ return not not eq(t1, t2)
+ else
+ return keyvaluesame(t1, t2)
+ end
+end
+
+---- tapered test suite
+
+local exit_status = 0
+local test_count = 0
+local debug_level = 3
+
+-- All other tests are defined in terms of this primitive, which is
+-- kept private.
+local _test = function (exp, msg)
+ test_count = test_count + 1
+
+ if msg then
+ msg = sprintf(" - %s", msg)
+ else
+ msg = ''
+ end
+
+ if exp then
+ printf("ok %s%s\n", test_count, msg)
+ else
+ exit_status = 1 + exit_status
+ printf("not ok %s%s\n", test_count, msg)
+ local info = get_info(debug_level)
+ printf("# Trouble in %s around line %s\n",
+ slice(info.source, 2), info.currentline)
+ end
+end
+
+local ok = function (expression, msg)
+ _test(expression, msg)
+end
+
+local nok = function (expression, msg)
+ _test(not expression, msg)
+end
+
+local is = function (actual, expected, msg)
+ _test(actual == expected, msg)
+end
+
+local isnt = function (actual, expected, msg)
+ _test(actual ~= expected, msg)
+end
+
+local same = function (actual, expected, msg)
+ _test(deepsame(actual, expected), msg)
+end
+
+local like = function (str, pattern, msg)
+ _test(str_find(str, pattern), msg)
+end
+
+local unlike = function (str, pattern, msg)
+ _test(not str_find(str, pattern), msg)
+end
+
+local pass = function (msg)
+ _test(true, msg)
+end
+
+local fail = function (msg)
+ _test(false, msg)
+end
+
+local boom = function (func, args, msg)
+ local err, errmsg
+ err, errmsg = pcall(func, unpack(args))
+ _test(not err, msg)
+ if not err and type(errmsg) == 'string' then
+ printf('# Got this error: "%s"\n', errmsg)
+ end
+end
+
+local done = function (n)
+ local expected = tonumber(n)
+ if not expected or test_count == expected then
+ printf('1..%d\n', test_count)
+ elseif expected ~= test_count then
+ exit_status = 1 + exit_status
+ local s
+ if expected == 1 then s = '' else s = 's' end
+ printf("# Bad plan. You planned %d test%s but ran %d\n",
+ expected, s, test_count)
+ end
+ exit(exit_status)
+end
+
+local version = function ()
+ return "2.3.0"
+end
+
+local author = function ()
+ return "Peter Aronoff"
+end
+
+local url = function ()
+ return "https://github.com/telemachus/tapered"
+end
+
+local license = function ()
+ return "BSD 3-Clause"
+end
+
+return {
+ ok = ok,
+ nok = nok,
+ is = is,
+ isnt = isnt,
+ same = same,
+ like = like,
+ unlike = unlike,
+ pass = pass,
+ fail = fail,
+ boom = boom,
+ done = done,
+ version = version,
+ author = author,
+ url = url,
+ license = license
+}
diff --git a/tests/config/tapered/tapered-1.1-0.rockspec b/tests/config/tapered/tapered-1.1-0.rockspec
new file mode 100644
index 0000000..d6dea7d
--- /dev/null
+++ b/tests/config/tapered/tapered-1.1-0.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '1.1-0'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v1.1-0.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-1.2.0-1.rockspec b/tests/config/tapered/tapered-1.2.0-1.rockspec
new file mode 100644
index 0000000..5e6c364
--- /dev/null
+++ b/tests/config/tapered/tapered-1.2.0-1.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '1.2.0-1'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v1.2.0-1.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-1.2.1-1.rockspec b/tests/config/tapered/tapered-1.2.1-1.rockspec
new file mode 100644
index 0000000..673e1af
--- /dev/null
+++ b/tests/config/tapered/tapered-1.2.1-1.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '1.2.1-1'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v1.2.1-1.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-2.0.0-1.rockspec b/tests/config/tapered/tapered-2.0.0-1.rockspec
new file mode 100644
index 0000000..5e5484a
--- /dev/null
+++ b/tests/config/tapered/tapered-2.0.0-1.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '2.0.0-1'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v2.0.0-1.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-2.0.1-1.rockspec b/tests/config/tapered/tapered-2.0.1-1.rockspec
new file mode 100644
index 0000000..1127375
--- /dev/null
+++ b/tests/config/tapered/tapered-2.0.1-1.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '2.0.1-1'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v2.0.1-1.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-2.1.0-1.rockspec b/tests/config/tapered/tapered-2.1.0-1.rockspec
new file mode 100644
index 0000000..f14c756
--- /dev/null
+++ b/tests/config/tapered/tapered-2.1.0-1.rockspec
@@ -0,0 +1,21 @@
+package = 'tapered'
+version = '2.1.0-1'
+source = {
+ url = 'https://bitbucket.org/telemachus/tapered/downloads/tapered-v2.1.0-1.tar.gz',
+ dir = 'tapered',
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-2.2.0-1.rockspec b/tests/config/tapered/tapered-2.2.0-1.rockspec
new file mode 100644
index 0000000..cfb8b51
--- /dev/null
+++ b/tests/config/tapered/tapered-2.2.0-1.rockspec
@@ -0,0 +1,22 @@
+package = 'tapered'
+version = '2.2.0-1'
+source = {
+ url = 'git://github.com/telemachus/tapered.git',
+ branch = 'master',
+ tag = 'v2.2.0-1'
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/tapered-2.3.0-1.rockspec b/tests/config/tapered/tapered-2.3.0-1.rockspec
new file mode 100644
index 0000000..b3060fb
--- /dev/null
+++ b/tests/config/tapered/tapered-2.3.0-1.rockspec
@@ -0,0 +1,22 @@
+package = 'tapered'
+version = '2.3.0-1'
+source = {
+ url = 'git://github.com/telemachus/tapered.git',
+ branch = 'master',
+ tag = 'v2.3.0-1'
+}
+description = {
+ summary = 'Very minimal tap testing for Lua.',
+ detailed = [[
+ Very minimal tap testing for Lua. Arguably too minimal.
+ ]],
+ license = 'BSD 3-Clause'
+}
+dependencies = {
+ 'lua >= 5.1'
+}
+build = {
+ type = 'builtin',
+ modules = { tapered = 'src/tapered.lua' },
+ copy_directories = { 'doc' }
+}
diff --git a/tests/config/tapered/test/.luacov b/tests/config/tapered/test/.luacov
new file mode 100644
index 0000000..7d3205e
--- /dev/null
+++ b/tests/config/tapered/test/.luacov
@@ -0,0 +1,55 @@
+--- Global configuration file. Copy, customize and store in your
+-- project folder as '.luacov' for project specific configuration.
+-- If some options are missing, their default values from this file
+-- will be used.
+-- @class module
+-- @name luacov.defaults
+return {
+
+ -- default filename to load for config options if not provided
+ -- only has effect in 'luacov.defaults.lua'
+ ["configfile"] = ".luacov",
+
+ -- filename to store stats collected
+ ["statsfile"] = "luacov.stats.out",
+
+ -- filename to store report
+ ["reportfile"] = "luacov.report.out",
+
+ -- luacov.stats file updating frequency.
+ -- The lower this value - the more frequenty results will be written out to luacov.stats
+ -- You may want to reduce this value for short lived scripts (to for example 2) to avoid losing coverage data.
+ ["savestepsize"] = 100,
+
+ -- Run reporter on completion? (won't work for ticks)
+ runreport = false,
+
+ -- Delete stats file after reporting?
+ deletestats = false,
+
+ -- Process Lua code loaded from raw strings
+ -- (that is, when the 'source' field in the debug info
+ -- does not start with '@')
+ codefromstrings = false,
+
+ -- Patterns for files to include when reporting
+ -- all will be included if nothing is listed
+ -- (exclude overrules include, do not include
+ -- the .lua extension, path separator is always '/')
+ ["include"] = { 'src/tapered' },
+
+ -- Patterns for files to exclude when reporting
+ -- all will be included if nothing is listed
+ -- (exclude overrules include, do not include
+ -- the .lua extension, path separator is always '/')
+ ["exclude"] = {
+ "luacov$",
+ "luacov/reporter$",
+ "luacov/defaults$",
+ "luacov/runner$",
+ "luacov/stats$",
+ "luacov/tick$",
+ },
+
+
+}
diff --git a/tests/config/tapered/test/boom-result.txt b/tests/config/tapered/test/boom-result.txt
new file mode 100644
index 0000000..871b509
--- /dev/null
+++ b/tests/config/tapered/test/boom-result.txt
@@ -0,0 +1,7 @@
+ok 1 - ok - return nada.__eq
+# Got this error: "boom-test.lua:13: attempt to index local 'x' (a nil value)"
+not ok 2 - not ok - Test boom with a method that throws no exception
+# Trouble in boom-test.lua around line 16
+ok 3 - ok - Test boom with a method that throws an exception "Kaboom!"
+# Got this error: "Kaboom!"
+1..3
diff --git a/tests/config/tapered/test/boom-test.lua b/tests/config/tapered/test/boom-test.lua
new file mode 100755
index 0000000..f2b585a
--- /dev/null
+++ b/tests/config/tapered/test/boom-test.lua
@@ -0,0 +1,19 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+local error = error
+
+--- boom
+-- boom(method, arguments, [msg]) tests if the function throws an exception when
+-- given the arguments supplied. The arguments parameter must be a table. It can
+-- be empty if the given method takes no arguments, but it cannot be nil.
+--
+-- Note that boom expects an exception. It passes if an exception is throw, and
+-- fails if one is not. The exception, however, will be swallowed by boom so
+-- that test execution continues.
+local broken = function (x) return x.__eq end
+local add = function (x, y) return x+y end
+tap.boom(broken, {}, 'ok - return nada.__eq')
+tap.boom(add, {2, 3}, 'not ok - Test boom with a method that throws no exception')
+tap.boom(error, {'Kaboom!'},
+ 'ok - Test boom with a method that throws an exception "Kaboom!"')
+tap.done()
diff --git a/tests/config/tapered/test/done-failure-result.txt b/tests/config/tapered/test/done-failure-result.txt
new file mode 100644
index 0000000..ce29e24
--- /dev/null
+++ b/tests/config/tapered/test/done-failure-result.txt
@@ -0,0 +1,2 @@
+ok 1
+# Bad plan. You planned 10 tests but ran 1
diff --git a/tests/config/tapered/test/done-failure-test.lua b/tests/config/tapered/test/done-failure-test.lua
new file mode 100644
index 0000000..40603d4
--- /dev/null
+++ b/tests/config/tapered/test/done-failure-test.lua
@@ -0,0 +1,5 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+tap.ok(true)
+tap.done(10)
diff --git a/tests/config/tapered/test/done-success-result.txt b/tests/config/tapered/test/done-success-result.txt
new file mode 100644
index 0000000..45541bc
--- /dev/null
+++ b/tests/config/tapered/test/done-success-result.txt
@@ -0,0 +1,2 @@
+ok 1
+1..1
diff --git a/tests/config/tapered/test/done-success-test.lua b/tests/config/tapered/test/done-success-test.lua
new file mode 100644
index 0000000..9e58ddd
--- /dev/null
+++ b/tests/config/tapered/test/done-success-test.lua
@@ -0,0 +1,5 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+tap.ok(true)
+tap.done(1)
diff --git a/tests/config/tapered/test/dynamic-setup-teardown-result.txt b/tests/config/tapered/test/dynamic-setup-teardown-result.txt
new file mode 100644
index 0000000..7130f99
--- /dev/null
+++ b/tests/config/tapered/test/dynamic-setup-teardown-result.txt
@@ -0,0 +1,10 @@
+# I'm a little teapot.
+ok 1 - setup() only with '# I'm a little teapot.'
+# This is my handle and this is my spout.
+ok 2 - setup() handle and spout, teardown() cleanup on aisle 9
+# Cleanup on aisle 9!
+# This is my handle and this is my spout.
+ok 3 - setup() again handle and spout, teardown() changed
+# I changed this.
+ok 4 - Both setup and teardown should be gone now: redefined as nil.
+1..4
diff --git a/tests/config/tapered/test/dynamic-setup-teardown-test.lua b/tests/config/tapered/test/dynamic-setup-teardown-test.lua
new file mode 100755
index 0000000..c7abb9d
--- /dev/null
+++ b/tests/config/tapered/test/dynamic-setup-teardown-test.lua
@@ -0,0 +1,27 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+-- luacheck: globals setup teardown
+function setup()
+ print("# I'm a little teapot.")
+end
+tap.ok(true, "setup() only with '# I'm a little teapot.'")
+
+function setup()
+ print('# This is my handle and this is my spout.')
+end
+function teardown()
+ print('# Cleanup on aisle 9!')
+end
+tap.ok(true, 'setup() handle and spout, teardown() cleanup on aisle 9')
+
+function teardown()
+ print('# I changed this.')
+end
+tap.ok(true, 'setup() again handle and spout, teardown() changed')
+
+setup = nil
+teardown = nil
+tap.ok(true, 'Both setup and teardown should be gone now: redefined as nil.')
+
+tap.done()
diff --git a/tests/config/tapered/test/exit-failure-test.lua b/tests/config/tapered/test/exit-failure-test.lua
new file mode 100755
index 0000000..18339c2
--- /dev/null
+++ b/tests/config/tapered/test/exit-failure-test.lua
@@ -0,0 +1,6 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+-- Test exit status with a failed test. Call `fail` and we're done!
+tap.fail('not ok - No test: just fail')
+tap.done()
diff --git a/tests/config/tapered/test/exit-success-test.lua b/tests/config/tapered/test/exit-success-test.lua
new file mode 100755
index 0000000..b588b64
--- /dev/null
+++ b/tests/config/tapered/test/exit-success-test.lua
@@ -0,0 +1,6 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+-- Testing exit status. Call `pass` and then we're out.
+tap.pass('ok - No test: just pass')
+tap.done()
diff --git a/tests/config/tapered/test/informational-fields-result.txt b/tests/config/tapered/test/informational-fields-result.txt
new file mode 100644
index 0000000..4d0ebc1
--- /dev/null
+++ b/tests/config/tapered/test/informational-fields-result.txt
@@ -0,0 +1,4 @@
+ok 1 - author() should be 'Peter Aronoff'
+ok 2 - version() should be '2.3.0'
+ok 3 - license() should be 'BSD 3-Clause'
+ok 4 - url() should be 'https://github.com/telemachus/tapered'
diff --git a/tests/config/tapered/test/informational-fields-test.lua b/tests/config/tapered/test/informational-fields-test.lua
new file mode 100755
index 0000000..35ef7d8
--- /dev/null
+++ b/tests/config/tapered/test/informational-fields-test.lua
@@ -0,0 +1,8 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+tap.is(tap.author(), 'Peter Aronoff', "author() should be 'Peter Aronoff'")
+tap.is(tap.version(), '2.3.0', "version() should be '2.3.0'")
+tap.is(tap.license(), 'BSD 3-Clause', "license() should be 'BSD 3-Clause'")
+tap.is(tap.url(), "https://github.com/telemachus/tapered",
+ "url() should be 'https://github.com/telemachus/tapered'")
diff --git a/tests/config/tapered/test/is-isnt-result.txt b/tests/config/tapered/test/is-isnt-result.txt
new file mode 100644
index 0000000..583a9a7
--- /dev/null
+++ b/tests/config/tapered/test/is-isnt-result.txt
@@ -0,0 +1,43 @@
+ok 1 - ok - is(2+1, 3)
+not ok 2 - not ok - is(2+2, 3)
+# Trouble in is-isnt-test.lua around line 8
+ok 3 - ok - is(print, print)
+not ok 4 - not ok - is(print, 3)
+# Trouble in is-isnt-test.lua around line 10
+ok 5 - ok - is("hello", "hello")
+not ok 6 - not ok - is("goodbye", "hello")
+# Trouble in is-isnt-test.lua around line 12
+ok 7 - ok - is(nil, nil)
+not ok 8 - not ok - is(nil, false)
+# Trouble in is-isnt-test.lua around line 14
+ok 9 - ok - is(false, false)
+ok 10 - ok - is(true, true)
+not ok 11 - not ok - is(true, false)
+# Trouble in is-isnt-test.lua around line 17
+not ok 12 - not ok - is(false, true)
+# Trouble in is-isnt-test.lua around line 18
+ok 13 - ok - isnt(2+2, 3)
+not ok 14 - not ok - isnt(2+2, 4)
+# Trouble in is-isnt-test.lua around line 20
+ok 15 - ok - isnt(3, print)
+ok 16 - ok - isnt(print, os.exit)
+ok 17 - ok - isnt("hello", "goodbye")
+not ok 18 - not ok - isnt("hello", "hello")
+# Trouble in is-isnt-test.lua around line 24
+not ok 19 - not ok - isnt(nil, nil)
+# Trouble in is-isnt-test.lua around line 25
+ok 20 - ok - isnt(nil, false)
+not ok 21 - not ok - isnt(false, false)
+# Trouble in is-isnt-test.lua around line 27
+not ok 22 - not ok - isnt(true, true)
+# Trouble in is-isnt-test.lua around line 28
+ok 23 - ok - isnt(true, false)
+ok 24 - ok - isnt(false, true)
+ok 25 - ok - isnt(nil, false)
+not ok 26 - not ok - isnt(false, false)
+# Trouble in is-isnt-test.lua around line 32
+not ok 27 - not ok - isnt(true, true)
+# Trouble in is-isnt-test.lua around line 33
+ok 28 - ok - isnt(true, false)
+ok 29 - ok - isnt(false, true)
+1..29
diff --git a/tests/config/tapered/test/is-isnt-test.lua b/tests/config/tapered/test/is-isnt-test.lua
new file mode 100755
index 0000000..d1c7636
--- /dev/null
+++ b/tests/config/tapered/test/is-isnt-test.lua
@@ -0,0 +1,36 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+--- is and isnt
+-- is(actual, expected, [msg]) tests if actual == expected
+-- isnt(actual, expected, [msg]) tests if actual ~= expected
+tap.is(2+1, 3, 'ok - is(2+1, 3)')
+tap.is(2+2, 3, 'not ok - is(2+2, 3)')
+tap.is(print, print, 'ok - is(print, print)')
+tap.is(print, 3, 'not ok - is(print, 3)')
+tap.is('hello', 'hello', 'ok - is("hello", "hello")')
+tap.is('goodbye', 'hello', 'not ok - is("goodbye", "hello")')
+tap.is(nil, nil, 'ok - is(nil, nil)')
+tap.is(nil, false, 'not ok - is(nil, false)')
+tap.is(false, false, 'ok - is(false, false)')
+tap.is(true, true, 'ok - is(true, true)')
+tap.is(true, false, 'not ok - is(true, false)')
+tap.is(false, true, 'not ok - is(false, true)')
+tap.isnt(2+2, 3, 'ok - isnt(2+2, 3)')
+tap.isnt(2+2, 4, 'not ok - isnt(2+2, 4)')
+tap.isnt(3, print, 'ok - isnt(3, print)')
+tap.isnt(print, os.exit, 'ok - isnt(print, os.exit)')
+tap.isnt('hello', 'goodbye', 'ok - isnt("hello", "goodbye")')
+tap.isnt('hello', 'hello', 'not ok - isnt("hello", "hello")')
+tap.isnt(nil, nil, 'not ok - isnt(nil, nil)')
+tap.isnt(nil, false, 'ok - isnt(nil, false)')
+tap.isnt(false, false, 'not ok - isnt(false, false)')
+tap.isnt(true, true, 'not ok - isnt(true, true)')
+tap.isnt(true, false, 'ok - isnt(true, false)')
+tap.isnt(false, true, 'ok - isnt(false, true)')
+tap.isnt(nil, false, 'ok - isnt(nil, false)')
+tap.isnt(false, false, 'not ok - isnt(false, false)')
+tap.isnt(true, true, 'not ok - isnt(true, true)')
+tap.isnt(true, false, 'ok - isnt(true, false)')
+tap.isnt(false, true, 'ok - isnt(false, true)')
+tap.done()
diff --git a/tests/config/tapered/test/like-unlike-result.txt b/tests/config/tapered/test/like-unlike-result.txt
new file mode 100644
index 0000000..f61aac2
--- /dev/null
+++ b/tests/config/tapered/test/like-unlike-result.txt
@@ -0,0 +1,13 @@
+ok 1 - ok - like('sat', 'sat')
+not ok 2 - not ok - like('sat', 'bbb')
+# Trouble in like-unlike-test.lua around line 8
+ok 3 - ok - unlike('sat', 'q')
+not ok 4 - not ok - unlike('q', 'q')
+# Trouble in like-unlike-test.lua around line 10
+ok 5 - ok - like(' sat', '%s+sat')
+ok 6 - ok - like('934', '%d%d%d')
+ok 7 - ok - like('934', '%d%d')
+not ok 8 - not ok - like('934', '%d%s')
+# Trouble in like-unlike-test.lua around line 14
+ok 9 - ok - unlike('934', '%d%s')
+1..9
diff --git a/tests/config/tapered/test/like-unlike-test.lua b/tests/config/tapered/test/like-unlike-test.lua
new file mode 100755
index 0000000..ab48ca7
--- /dev/null
+++ b/tests/config/tapered/test/like-unlike-test.lua
@@ -0,0 +1,16 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+--- like and unlike
+-- like(string, pattern, [msg]) tests if the pattern matches the string
+-- unlike(string, pattern, [msg]) tests if the pattern does not match the string
+tap.like('sat', 'sat', "ok - like('sat', 'sat')")
+tap.like('sat', 'bbb', "not ok - like('sat', 'bbb')")
+tap.unlike('sat', 'q', "ok - unlike('sat', 'q')")
+tap.unlike('q', 'q', "not ok - unlike('q', 'q')")
+tap.like(' sat', '%s+sat', "ok - like(' sat', '%s+sat')")
+tap.like('934', '%d%d%d', "ok - like('934', '%d%d%d')")
+tap.like('934', '%d%d', "ok - like('934', '%d%d')")
+tap.like('934', '%d%s', "not ok - like('934', '%d%s')")
+tap.unlike('934', '%d%s', "ok - unlike('934', '%d%s')")
+tap.done()
diff --git a/tests/config/tapered/test/ok-nok-result.txt b/tests/config/tapered/test/ok-nok-result.txt
new file mode 100644
index 0000000..ef45c6a
--- /dev/null
+++ b/tests/config/tapered/test/ok-nok-result.txt
@@ -0,0 +1,7 @@
+ok 1 - ok - ok(true)
+not ok 2 - not ok - ok(false)
+# Trouble in ok-nok-test.lua around line 8
+ok 3 - ok - nok(false)
+not ok 4 - not ok - nok(true)
+# Trouble in ok-nok-test.lua around line 10
+1..4
diff --git a/tests/config/tapered/test/ok-nok-test.lua b/tests/config/tapered/test/ok-nok-test.lua
new file mode 100755
index 0000000..c2a0b4d
--- /dev/null
+++ b/tests/config/tapered/test/ok-nok-test.lua
@@ -0,0 +1,11 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+--- ok and nok
+-- ok(exp, [msg]) tests if exp returns (or is) a truthy value.
+-- nok(exp, [msg]) tests if exp returns (or is) a falsey value.
+tap.ok(true, 'ok - ok(true)')
+tap.ok(false, 'not ok - ok(false)')
+tap.nok(false, 'ok - nok(false)')
+tap.nok(true, 'not ok - nok(true)')
+tap.done()
diff --git a/tests/config/tapered/test/pass-fail-result.txt b/tests/config/tapered/test/pass-fail-result.txt
new file mode 100644
index 0000000..8c29e66
--- /dev/null
+++ b/tests/config/tapered/test/pass-fail-result.txt
@@ -0,0 +1,4 @@
+ok 1 - ok - No test: just pass
+not ok 2 - not ok - No test: just fail
+# Trouble in pass-fail-test.lua around line 10
+1..2
diff --git a/tests/config/tapered/test/pass-fail-test.lua b/tests/config/tapered/test/pass-fail-test.lua
new file mode 100755
index 0000000..0f2418a
--- /dev/null
+++ b/tests/config/tapered/test/pass-fail-test.lua
@@ -0,0 +1,11 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+--- pass and fail
+-- pass([msg]) is not a test. It always passes.
+-- fail([msg]) is not a test. It always fails.
+-- These two methods are useful for checking the basic setup of a test suite.
+-- Also, pass can be used as a quasi-skip and fail as a quasi-TODO.
+tap.pass('ok - No test: just pass')
+tap.fail('not ok - No test: just fail')
+tap.done()
diff --git a/tests/config/tapered/test/result_test03.txt b/tests/config/tapered/test/result_test03.txt
new file mode 100644
index 0000000..58c066c
--- /dev/null
+++ b/tests/config/tapered/test/result_test03.txt
@@ -0,0 +1,55 @@
+ok 1 - Test ok on true
+not ok 2 - Test ok on false
+# Trouble in test03-allfuncs.lua around line 9
+ok 3 - Test nok on false
+not ok 4 - Test nok on true
+# Trouble in test03-allfuncs.lua around line 11
+ok 5 - Test is on 2 + 1 = 3
+not ok 6 - Test is on 2 + 2 = 3
+# Trouble in test03-allfuncs.lua around line 17
+ok 7 - Test isnt on 2 + 2 = 3
+not ok 8 - Test isnt on 2 + 2 = 4
+# Trouble in test03-allfuncs.lua around line 19
+ok 9 - Test same on two empty tables
+ok 10 - Test same on two identical, simple tables
+not ok 11 - Test same on two simple non-identical tables
+# Trouble in test03-allfuncs.lua around line 36
+ok 12 - Test same on two identical, nested tables
+ok 13 - Test same on identical, array-like tables
+not ok 14 - Test same on two non-identical, array-like tables
+# Trouble in test03-allfuncs.lua around line 43
+ok 15 - Test same on two identical, hash-like tables
+not ok 16 - Test same on two non-identical, hash-like tables
+# Trouble in test03-allfuncs.lua around line 65
+ok 17 - Test same on two identical tables with functions as values
+not ok 18 - Test same on two non-identical tables with functions as values
+# Trouble in test03-allfuncs.lua around line 74
+ok 19 - Test same on two dissimilar tables that share .__eq => true
+not ok 20 - Test same: first table .__eq => true, second => false
+# Trouble in test03-allfuncs.lua around line 89
+not ok 21 - Test same: first table .__eq => false, second => true
+# Trouble in test03-allfuncs.lua around line 90
+not ok 22 - Test same on two similar tables where first .__eq => true
+# Trouble in test03-allfuncs.lua around line 91
+not ok 23 - Test same on two similar tables where second .__eq => true
+# Trouble in test03-allfuncs.lua around line 92
+ok 24 - Test like with string 'sat' and pattern 'sat'
+not ok 25 - Test like with string 'sat' and pattern 'bbb'
+# Trouble in test03-allfuncs.lua around line 98
+ok 26 - Test unlike with string 'sat' and pattern 'q'
+not ok 27 - Test unlike with string 'q' and pattern 'q'
+# Trouble in test03-allfuncs.lua around line 100
+ok 28 - Test like with string ' sat' and pattern '%s+sat'
+ok 29 - Test like with string '934' and pattern '%d%d%d'
+ok 30 - Test like with string '934' and pattern '%d%d'
+ok 31 - Test unlike with string '934' and pattern '%d%s'
+ok 32 - No test: just pass
+not ok 33 - No test: just fail
+# Trouble in test03-allfuncs.lua around line 112
+not ok 34 - Test boom with a method that throws no exception
+# Trouble in test03-allfuncs.lua around line 123
+ok 35 - Test boom with a method that throws an exception "Kaboom!"
+# Got this error:
+# Kaboom!
+1..35
+# Bad plan. You planned 43 tests but ran 35
diff --git a/tests/config/tapered/test/runner.bash b/tests/config/tapered/test/runner.bash
new file mode 100755
index 0000000..f7f38fc
--- /dev/null
+++ b/tests/config/tapered/test/runner.bash
@@ -0,0 +1,71 @@
+#!/usr/bin/env bats
+
+@test "ignition!" {
+ run true
+ [ "$status" -eq 0 ]
+ [ "$output" = "" ]
+}
+
+@test "ok and nok" {
+ run lua -lluacov ok-nok-test.lua
+ [ "$status" -eq 2 ]
+ [ "$output" = "$(cat ok-nok-result.txt)" ]
+}
+
+@test "is and isnt" {
+ run lua -lluacov is-isnt-test.lua
+ [ "$status" -eq 13 ]
+ [ "$output" = "$(cat is-isnt-result.txt)" ]
+}
+
+@test "same" {
+ run lua -lluacov same-test.lua
+ [ "$status" -eq 10 ]
+ [ "$output" = "$(cat same-result.txt)" ]
+}
+
+@test "like and unlike" {
+ run lua -lluacov like-unlike-test.lua
+ [ "$status" -eq 3 ]
+ [ "$output" = "$(cat like-unlike-result.txt)" ]
+}
+
+@test "pass and fail" {
+ run lua -lluacov pass-fail-test.lua
+ [ "$status" -eq 1 ]
+ [ "$output" = "$(cat pass-fail-result.txt)" ]
+}
+
+@test "boom" {
+ run lua -lluacov boom-test.lua
+ [ "$status" -eq 1 ]
+ # This is foul, but choices are limited. Error messages for Lua 5.3
+ # are different, so I need to look at the output but NOT the errors.
+ [ "$(grep -v '^#' <<< "$output")" = "$(cat boom-result.txt | grep -v '^#')" ]
+}
+
+@test "done success" {
+ run lua -lluacov done-success-test.lua
+ [ "$status" -eq 0 ]
+ [ "$output" = "$(cat done-success-result.txt)" ]
+}
+
+@test "done failure" {
+ run lua -lluacov done-failure-test.lua
+ [ "$status" -eq 1 ]
+ [ "$output" = "$(cat done-failure-result.txt)" ]
+}
+
+@test "exit status" {
+ run lua -lluacov exit-success-test.lua
+ [ "$status" -eq 0 ]
+
+ run lua -lluacov exit-failure-test.lua
+ [ "$status" -eq 1 ]
+}
+
+@test "informational fields" {
+ run lua -lluacov informational-fields-test.lua
+ [ "$status" -eq 0 ]
+ [ "$output" = "$(cat informational-fields-result.txt)" ]
+}
diff --git a/tests/config/tapered/test/same-result.txt b/tests/config/tapered/test/same-result.txt
new file mode 100644
index 0000000..c77a5a4
--- /dev/null
+++ b/tests/config/tapered/test/same-result.txt
@@ -0,0 +1,31 @@
+ok 1 - ok - same({}, {}
+ok 2 - ok - same({1,2,3}, {1,2,3})
+not ok 3 - not ok - same({1}, {})
+# Trouble in same-test.lua around line 7
+ok 4 - ok - same({{1}, 2, {3,4}}, {{1}, 2, {3,4})
+ok 5 - ok - same({"Monday", "Tuesday"}, {"Monday", "Tuesday"})
+not ok 6 - not ok - same({"Monday", "Tuesday"}, {"Monday", "Tuesday", "Wednesday"})
+# Trouble in same-test.lua around line 15
+ok 7 - ok - same({Monday = 1}, {Monday = 1})
+not ok 8 - not ok - same({Monday = 1}, {Monday = 1, Tuesday = 2})
+# Trouble in same-test.lua around line 29
+ok 9 - ok - same({m = {1,2}, n = {1,2}}, {m = {1,2}, n = {1,2}})
+not ok 10 - not ok - same({m = {1,2}, n = {1,2}}, {m = {1,2}, n = {1,2,3}})
+# Trouble in same-test.lua around line 36
+not ok 11 - not ok - same({m = {1,2}, n = {1,2,3}}, {m = {1,2}, n = {1,2}})
+# Trouble in same-test.lua around line 37
+ok 12 - ok - same({p = print, a = assert}, {p = print, a = assert})
+not ok 13 - not ok - same({p = print, a = assert}, {p = print, a = assert, e = error})
+# Trouble in same-test.lua around line 44
+ok 14 - ok - same({4, s=4}, {6, s=4},__eq => x[s] and y[s] are even)
+ok 15 - ok - same({6, s=8}, {4, s=4},__eq => x[s] and y[s] are even)
+not ok 16 - not ok - same({4, s=4}, {4, s=3},__eq => x[s] and y[s] are even)
+# Trouble in same-test.lua around line 61
+not ok 17 - not ok - same({4, s=4}, {4, s=3},__eq => x[s] and y[s] are even)
+# Trouble in same-test.lua around line 63
+not ok 18 - not ok - same({4, s=4}, {6, s=4},__eq => x[s] is even, y[s] odd)
+# Trouble in same-test.lua around line 68
+ok 19 - ok - same({4, s=4}, {4, s=3},__eq => x[s] is even, y[s] odd)
+not ok 20 - not ok - same({4, s=3}, {4, s=4},__eq => x[s] is even, y[s] odd)
+# Trouble in same-test.lua around line 72
+1..20
diff --git a/tests/config/tapered/test/same-test.lua b/tests/config/tapered/test/same-test.lua
new file mode 100644
index 0000000..68c3574
--- /dev/null
+++ b/tests/config/tapered/test/same-test.lua
@@ -0,0 +1,74 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+-- luacheck: compat
+
+tap.same({},{}, 'ok - same({}, {}')
+tap.same({1,2,3}, {1,2,3}, 'ok - same({1,2,3}, {1,2,3})')
+tap.same({1},{}, 'not ok - same({1}, {})')
+tap.same({{1}, 2, {3,4}},{{1}, 2, {3,4}},
+ 'ok - same({{1}, 2, {3,4}}, {{1}, 2, {3,4})')
+
+local days1 = { 'Monday', 'Tuesday' }
+local days2 = { 'Monday', 'Tuesday' }
+tap.same(days1, days2, 'ok - same({"Monday", "Tuesday"}, {"Monday", "Tuesday"})')
+local days3 = { 'Monday', 'Tuesday', 'Wednesday', }
+tap.same(days2, days3,
+ 'not ok - same({"Monday", "Tuesday"}, {"Monday", "Tuesday", "Wednesday"})')
+
+local hash1 = {
+ Monday = 1,
+}
+local hash2 = {
+ Monday = 1,
+}
+local hash3 = {
+ Monday = 1,
+ Tuesday = 2,
+}
+tap.same(hash1, hash2, 'ok - same({Monday = 1}, {Monday = 1})')
+tap.same(hash1, hash3,
+ 'not ok - same({Monday = 1}, {Monday = 1, Tuesday = 2})')
+
+local n1 = { m = { 1, 2 }, n = { 1, 2 } }
+local n2 = { m = { 1, 2 }, n = { 1, 2 } }
+local n3 = { m = { 1, 2 }, n = { 1, 2, 3 } }
+tap.same(n1, n2, 'ok - same({m = {1,2}, n = {1,2}}, {m = {1,2}, n = {1,2}})')
+tap.same(n1, n3, 'not ok - same({m = {1,2}, n = {1,2}}, {m = {1,2}, n = {1,2,3}})')
+tap.same(n3, n1, 'not ok - same({m = {1,2}, n = {1,2,3}}, {m = {1,2}, n = {1,2}})')
+
+local method_table1 = { p = print, a = assert }
+local method_table2 = { p = print, a = assert }
+local method_table3 = { p = print, a = assert, e = error }
+tap.same(method_table1, method_table2,
+ 'ok - same({p = print, a = assert}, {p = print, a = assert})')
+tap.same(method_table1, method_table3,
+ 'not ok - same({p = print, a = assert}, {p = print, a = assert, e = error})')
+
+local foo = {4, s = 4}
+local bar = {6, s = 8}
+local oof = {4, s = 3}
+local mt1 = {}
+local mt2 = {}
+local evens = function (x, y) return x['s'] % 2 == 0 and y['s'] % 2 == 0 end
+local even_odd = function (x, y) return x['s'] % 2 == 0 and y['s'] % 2 ~= 0 end
+mt1.__eq = evens
+mt2.__eq = even_odd
+setmetatable(foo, mt1)
+setmetatable(bar, mt1)
+setmetatable(oof, mt1)
+tap.same(foo, bar, 'ok - same({4, s=4}, {6, s=4},__eq => x[s] and y[s] are even)')
+tap.same(bar, foo, 'ok - same({6, s=8}, {4, s=4},__eq => x[s] and y[s] are even)')
+tap.same(foo, oof,
+ 'not ok - same({4, s=4}, {4, s=3},__eq => x[s] and y[s] are even)')
+tap.same(oof, foo,
+ 'not ok - same({4, s=4}, {4, s=3},__eq => x[s] and y[s] are even)')
+setmetatable(foo, mt2)
+setmetatable(bar, mt2)
+setmetatable(oof, mt2)
+tap.same(foo, bar,
+ 'not ok - same({4, s=4}, {6, s=4},__eq => x[s] is even, y[s] odd)')
+tap.same(foo, oof,
+ 'ok - same({4, s=4}, {4, s=3},__eq => x[s] is even, y[s] odd)')
+tap.same(oof, foo,
+ 'not ok - same({4, s=3}, {4, s=4},__eq => x[s] is even, y[s] odd)')
+tap.done()
diff --git a/tests/config/tapered/test/setup-teardown-result.txt b/tests/config/tapered/test/setup-teardown-result.txt
new file mode 100644
index 0000000..c5d5668
--- /dev/null
+++ b/tests/config/tapered/test/setup-teardown-result.txt
@@ -0,0 +1,4 @@
+# I'm a little teapot.
+ok 1 - Short and stout.
+# Here is my handle, and here is my spout.
+1..1
diff --git a/tests/config/tapered/test/setup-teardown-test.lua b/tests/config/tapered/test/setup-teardown-test.lua
new file mode 100755
index 0000000..974a4aa
--- /dev/null
+++ b/tests/config/tapered/test/setup-teardown-test.lua
@@ -0,0 +1,14 @@
+package.path = '../src/?.lua;' .. package.path
+local tap = require 'tapered'
+
+-- luacheck: globals setup teardown
+function setup()
+ print("# I'm a little teapot.")
+end
+
+function teardown()
+ print("# Here is my handle, and here is my spout.")
+end
+
+tap.ok(true, "Short and stout.")
+tap.done()
diff --git a/tests/config/test.cfg b/tests/config/test.cfg
new file mode 100644
index 0000000..a49c0f4
--- /dev/null
+++ b/tests/config/test.cfg
@@ -0,0 +1,27 @@
+package.path = package.path .. ';' .. env.SOURCE_PATH .. '/?.lua'
+TEST_DIR = env.TEST_FILE:match('(.*/)')
+
+-- export testing module in globals
+local tapered = require('tapered.src.tapered')
+for k, v in pairs(tapered) do
+ _G[k] = v
+end
+
+-- don't send priming queries etc.
+modules.unload 'priming'
+modules.unload 'ta_signal_query'
+
+-- load test
+local tests = dofile(env.TEST_FILE)
+
+-- run test after processed config file
+-- default config will be used and we can test it.
+if tests then
+ local runtest = require('test_utils').test
+ worker.coroutine(function ()
+ for _, t in ipairs(tests) do
+ runtest(t)
+ end
+ done()
+ end)
+end \ No newline at end of file
diff --git a/tests/config/test_config.mk b/tests/config/test_config.mk
new file mode 100644
index 0000000..92c3543
--- /dev/null
+++ b/tests/config/test_config.mk
@@ -0,0 +1,24 @@
+#
+# Configuration tests
+#
+# Copy test folder and test_utils.lua to temp directory
+# Run kresd in temp directory and use config test.cfg
+# Check return code of kresd. Passed test have to call quit().
+
+tests_config := \
+ $(wildcard daemon/*/*.test.lua) \
+ $(wildcard daemon/*/*/*.test.lua) \
+ $(wildcard modules/*/*.test.lua) \
+ $(wildcard modules/*/*/*.test.lua) \
+ $(wildcard tests/config/*.test.lua) \
+ $(wildcard tests/config/*/*.test.lua)
+
+define make_config_test
+$(1): check-install-precond
+ @$(shell ./scripts/coverage_env.sh "$(TOPSRCDIR)" "$(COVERAGE_STATSDIR)/tests_config" "$(1)") $(preload_syms) ./tests/config/runtest.sh $(abspath $(SBINDIR)/kresd) $(abspath $(1))
+.PHONY: $(1)
+endef
+
+$(foreach test,$(tests_config),$(eval $(call make_config_test,$(test))))
+check-config: $(tests_config)
+.PHONY: check-config
diff --git a/tests/config/test_utils.lua b/tests/config/test_utils.lua
new file mode 100644
index 0000000..edec11f
--- /dev/null
+++ b/tests/config/test_utils.lua
@@ -0,0 +1,41 @@
+local M = {}
+
+function M.test(f, ...)
+ local res, exception = pcall(f, ...)
+ if not res then
+ local trace = debug.getinfo(2)
+ io.stderr:write(string.format('%s:%d %s\n', trace.source, trace.currentline, exception))
+ os.exit(2)
+ end
+ return res
+end
+
+function M.table_keys_to_lower(table)
+ local res = {}
+ for k, v in pairs(table) do
+ res[k:lower()] = v
+ end
+ return res
+end
+
+local function contains(pass, fail, table, value, message)
+ message = message or string.format('table contains "%s"', value)
+ for _, v in pairs(table) do
+ if v == value then
+ pass(message)
+ return
+ end
+ end
+ fail(message)
+ return
+end
+
+function M.contains(table, value, message)
+ return contains(pass, fail, table, value, message)
+end
+
+function M.not_contains(table, value, message)
+ return contains(fail, pass, table, value, message)
+end
+
+return M
diff --git a/tests/config/tls.test.lua b/tests/config/tls.test.lua
new file mode 100644
index 0000000..d02d55f
--- /dev/null
+++ b/tests/config/tls.test.lua
@@ -0,0 +1,24 @@
+local function test_session_config()
+ ok(net.tls_sticket_secret(),
+ 'net.tls_sticket_secret() to trigger key regeneration')
+ -- There is no sufficiently new stable release of GnuTLS.
+ -- ok(net.tls_sticket_secret('0123456789ABCDEF0123456789ABCDEF'),
+ -- 'net.tls_sticket_secret with valid key')
+ boom(net.tls_sticket_secret, {{}},
+ 'net.tls_sticket_secret({}) is invalid')
+ boom(net.tls_sticket_secret, {'0123456789ABCDEF0123456789ABCDE'},
+ 'net.tls_sticket_secret with too short key')
+
+ boom(net.tls_sticket_secret_file, {},
+ 'net.tls_sticket_secret_file without filename')
+ boom(net.tls_sticket_secret_file, {{}},
+ 'net.tls_sticket_secret_file with non-string filename')
+ boom(net.tls_sticket_secret_file, {'/tmp/a_non_existent_file_REALLY_1528898130'},
+ 'net.tls_sticket_secret_file with non-existent filename')
+ boom(net.tls_sticket_secret_file, {'/dev/null'},
+ 'net.tls_sticket_secret_file with empty file')
+end
+
+return {
+ test_session_config
+}
diff --git a/tests/config/worker_test.lua b/tests/config/worker_test.lua
new file mode 100644
index 0000000..47cc485
--- /dev/null
+++ b/tests/config/worker_test.lua
@@ -0,0 +1,64 @@
+-- check prerequisites
+if not worker.bg_worker then
+ pass('skipping worker test because it doesnt support background worker')
+ done()
+else
+ -- import primitives for synchronisation
+ local monotime = require('cqueues').monotime
+
+ -- test whether sleeping works
+ local function test_worker_sleep()
+ local now = monotime()
+ ok(pcall(worker.sleep, 0.1), 'sleep works')
+ local elapsed = monotime() - now
+ ok(elapsed > 0, 'sleep takes non-zero time')
+ end
+
+ -- helper to track number of executions
+ local cv = require('cqueues.condition').new()
+ local tasks = 0
+ local function work ()
+ worker.sleep(0.1)
+ tasks = tasks - 1
+ if tasks == 0 then
+ cv:signal()
+ elseif tasks < 0 then
+ error('too many executions')
+ end
+ end
+
+ -- test whether coroutines work
+ local function test_worker_coroutine()
+ tasks = 2
+ worker.coroutine(work)
+ worker.coroutine(work)
+ -- Check if coroutines finish
+ local status = cv:wait(1)
+ same(tasks, 0, 'all coroutines finish')
+ ok(status, 'coroutines finish successfully')
+ -- Check if nesting coroutines works
+ local now = monotime()
+ tasks = 100
+ worker.coroutine(function ()
+ for _ = 1, 100 do
+ worker.coroutine(work)
+ end
+ end)
+ status = cv:wait(1)
+ local elapsed = monotime() - now
+ same(tasks, 0, 'all nested coroutines finish')
+ ok(status, 'nested coroutines finish successfully')
+ -- Test if 100 coroutines didnt execute synchronously
+ -- (the wait time would be 100 * 0.1 = 10s sleep time)
+ -- Concurrent sleep time should still be ~0.1s (added some safe margin)
+ ok(elapsed < 0.5, 'coroutines didnt block while sleeping')
+ end
+
+ -- plan tests
+ local tests = {
+ test_worker_sleep,
+ test_worker_coroutine
+ }
+
+ return tests
+end \ No newline at end of file
diff --git a/tests/deckard/.gitignore b/tests/deckard/.gitignore
new file mode 100644
index 0000000..f8109bf
--- /dev/null
+++ b/tests/deckard/.gitignore
@@ -0,0 +1,20 @@
+*.swp
+/env.sh
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+.mypy_cache/
diff --git a/tests/deckard/.gitlab-ci.yml b/tests/deckard/.gitlab-ci.yml
new file mode 100644
index 0000000..b1ec808
--- /dev/null
+++ b/tests/deckard/.gitlab-ci.yml
@@ -0,0 +1,116 @@
+image: $CI_REGISTRY/knot/knot-resolver/ci/debian-stable:knot-2.7
+variables:
+ LC_ALL: C.UTF-8
+
+stages:
+ - test
+
+.test: &test
+ stage: test
+ tags:
+ - docker
+ - linux
+ - amd64
+
+test:augeas:
+ <<: *test
+ script:
+ - augparse pydnstest/deckard.aug
+
+test:flake8:
+ <<: *test
+ script:
+ - python3 -m flake8 --max-line-length=100 . && echo "OK, no flake8 errors detected"
+
+test:mypy:
+ <<: *test
+ script:
+ - ci/mypy-run.sh && echo "OK, no mypy error detected"
+
+test:pylint:
+ <<: *test
+ script:
+ - ci/pylint-run.sh
+
+test:rplint:
+ <<: *test
+ script:
+ - cp ci/common.sh /tmp
+ - cp ci/compare-rplint.sh /tmp
+ - /tmp/compare-rplint.sh
+
+test:unittests:
+ <<: *test
+ script:
+ - make check
+
+# changes in Deckard itself must not change result of tests
+test:comparative:kresd:
+ <<: *test
+ script:
+ # test kresd binary
+ - git clone --depth=1 https://gitlab.labs.nic.cz/knot/knot-resolver.git /tmp/kresd-local-build
+ - GIT_DIR=/tmp/kresd-local-build/.git git log -1
+ - ( cd /tmp/kresd-local-build ; git submodule update --init --recursive )
+ - PREFIX=/tmp/.local make -C /tmp/kresd-local-build -k all
+ - PREFIX=/tmp/.local make -C /tmp/kresd-local-build install
+ # compare results from latest Deckard with results from merge base
+ - cp ci/common.sh /tmp
+ - cp ci/compare-tests.sh /tmp
+ - cp ci/junit-compare.py /tmp
+ - LD_LIBRARY_PATH=/tmp/.local/lib PATH=/tmp/.local/sbin:$PATH /tmp/compare-tests.sh $(pwd)/kresd_run.sh
+ artifacts:
+ when: always
+ expire_in: '1 hour'
+ paths:
+ - modified_tests
+ - base.xml
+ - head.xml
+
+# Run all tests on the latest kresd version to ensure that we not push tests
+# which do not work on latest kresd. It would lead to breakage in kresd CI.
+test:latest:kresd:
+ <<: *test
+ script:
+ - git clone --depth=1 https://gitlab.labs.nic.cz/knot/knot-resolver.git kresd-local-build
+ - GIT_DIR=$(pwd)/kresd-local-build/.git git log -1
+ - ( cd kresd-local-build ; git submodule update --init --recursive )
+ - PREFIX=$(pwd)/.local make -C kresd-local-build -k all
+ - PREFIX=$(pwd)/.local make -C kresd-local-build install
+ - TMPDIR=$(pwd) LD_LIBRARY_PATH=$(pwd)/.local/lib PATH=$(pwd)/.local/sbin:$PATH ./kresd_run.sh -n $(nproc)
+ artifacts:
+ when: on_failure
+ expire_in: 1 week
+ paths:
+ - tmpdeckard*
+
+# sanity check that Unbound under Deckard still works
+# I've selected the only tests which are working
+# on kresd and Unbound 1.5.8 as well as 1.6.0
+test:sanity:unbound:
+ <<: *test
+ script:
+ - TMPDIR=$(pwd) ./unbound_run.sh -k sets/resolver/iter_hint_lame.rpl
+ - TMPDIR=$(pwd) ./unbound_run.sh -k sets/resolver/iter_lame_root.rpl
+ # these do not work with Unbound 1.5.8 which is in CI container
+ #- TESTS=sets/resolver/nsec_wildcard_answer_response.rpl ./unbound_run.sh
+ #- TESTS=sets/resolver/world_cz_lidovky_www.rpl ./unbound_run.sh
+ artifacts:
+ when: on_failure
+ expire_in: 1 week
+ paths:
+ - tmpdeckard*
+
+# sanity check that PowerDNS recursor under Deckard still works
+# I've selected couple tests which are working
+# on kresd and PowerDNS recursor 4.0.0~alpha2 as well as 4.0.4
+test:sanity:pdnsrecursor:
+ <<: *test
+ script:
+ - TMPDIR=$(pwd) ./pdns_run.sh -k sets/resolver/iter_recurse.rpl
+ - TMPDIR=$(pwd) ./pdns_run.sh -k sets/resolver/iter_tcbit.rpl
+ artifacts:
+ when: on_failure
+ expire_in: 1 week
+ paths:
+ - tmpdeckard*
diff --git a/tests/deckard/.gitmodules b/tests/deckard/.gitmodules
new file mode 100644
index 0000000..d503253
--- /dev/null
+++ b/tests/deckard/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "contrib/libfaketime"]
+ path = contrib/libfaketime
+ url = git://github.com/wolfcw/libfaketime.git
+[submodule "contrib/libswrap"]
+ path = contrib/libswrap
+ url = https://gitlab.labs.nic.cz/labs/socket_wrapper.git
diff --git a/tests/deckard/LICENSE b/tests/deckard/LICENSE
new file mode 100644
index 0000000..7f30d4f
--- /dev/null
+++ b/tests/deckard/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2016, CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
diff --git a/tests/deckard/Makefile b/tests/deckard/Makefile
new file mode 100644
index 0000000..675aa42
--- /dev/null
+++ b/tests/deckard/Makefile
@@ -0,0 +1,58 @@
+# Defaults
+PYTHON ?= python3
+LIBEXT := .so
+PLATFORM := $(shell uname -s)
+ifeq ($(PLATFORM),Darwin)
+ LIBEXT := .dylib
+endif
+
+# Dependencies
+include platform.mk
+libcwrap_DIR := contrib/libswrap
+libcwrap_cmake_DIR := $(libcwrap_DIR)/obj
+libcwrap=$(abspath $(libcwrap_cmake_DIR))/src/libsocket_wrapper$(LIBEXT).0
+ifeq ($(PLATFORM),Darwin)
+ libcwrap=$(abspath $(libcwrap_cmake_DIR))/src/libsocket_wrapper.0$(LIBEXT)
+endif
+libfaketime_DIR := contrib/libfaketime
+libfaketime := $(abspath $(libfaketime_DIR))/src/libfaketime$(LIBEXT).1
+
+# Platform-specific targets
+ifeq ($(PLATFORM),Darwin)
+ libfaketime := $(abspath $(libfaketime_DIR))/src/libfaketime.1$(LIBEXT)
+ preload_syms := DYLD_LIBRARY_PATH=$(DYLD_LIBRARY_PATH) DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES="$(libfaketime):$(libcwrap)"
+else
+ preload_syms := LD_PRELOAD="$(libfaketime):$(libcwrap)"
+endif
+
+
+# Targets
+all:
+ @echo "Deckard is now run using *run.sh scripts in its root directory."
+ @echo "To build the dependencies (libfaketime and libcwrap) run 'make depend'."
+ exit 1
+depend: $(libfaketime) $(libcwrap)
+ @echo "export DONT_FAKE_MONOTONIC=1" > env.sh
+ @echo "export $(preload_syms)" >> env.sh
+
+# Synchronize submodules
+submodules: .gitmodules
+ @git submodule update --init
+# indirection through submodules target is necessary
+# to prevent make from running "git submodule" commands in parallel
+$(libfaketime_DIR)/Makefile $(libcwrap_DIR)/CMakeLists.txt: submodules
+$(libfaketime): $(libfaketime_DIR)/Makefile
+ @CFLAGS="-O0 -g" $(MAKE) -s -C $(libfaketime_DIR)
+$(libcwrap_cmake_DIR):$(libcwrap_DIR)/CMakeLists.txt
+ @mkdir -p $(libcwrap_cmake_DIR)
+$(libcwrap_cmake_DIR)/Makefile: $(libcwrap_cmake_DIR)
+ @cd $(libcwrap_cmake_DIR); cmake ..
+$(libcwrap): $(libcwrap_cmake_DIR)/Makefile
+ @CFLAGS="-O0 -g" $(MAKE) -s -C $(libcwrap_cmake_DIR)
+
+
+.PHONY: submodules depend all
+
+check:
+ @echo Running unittests using pytest
+ ${PYTHON} -m pytest
diff --git a/tests/deckard/README.rst b/tests/deckard/README.rst
new file mode 100644
index 0000000..c24156a
--- /dev/null
+++ b/tests/deckard/README.rst
@@ -0,0 +1,98 @@
+DNS test harness (Deckard)
+==========================
+
+Deckard is a DNS software testing tool that creates a controlled network environment for reproducible tests.
+
+In essence, it works like this:
+
+- Deckard runs given binaries as subprocesses in an isolated network environment.
+- When binaries are up, Deckard sends scripted queries and checks replies.
+- When a binary attempts to contact another server, Deckard intercepts the communication and replies with scripted answer.
+- Deckard can simulate network issues, DNS environment changes, and fake time (for DNSSEC validation tests).
+
+No changes to real network setup are required because all network communications are redirected over UNIX sockets (and recorded to PCAP).
+
+Test cases are described by `scenarios <doc/scenario_guide.rst>`_ that contain:
+
+- A declarative description of the environment (e.g. what queries can the binary under test make and what Deckard should answer)
+- A sequence of queries (and expected answers), and other events (e.g. time jumps forward)
+
+
+Requirements
+------------
+
+Deckard requires following software to be installed:
+
+- Python >= 3.5
+- augeas_ - library for editing configuration files
+- dnspython_ - DNS library for Python
+- Jinja2_ - template engine for generating config files
+- PyYAML_ - YAML parser for Python
+- python-augeas_ - Python bindings for augeas API
+- pytest_ - testing framework for Python, used for running the test cases
+- pytest-xdist_ - module for pytest for distributed testing
+- custom C libraries (installed automatically, see below)
+
+For convenient use it is strongly recommended to have a C compiler, Git, and ``make`` available.
+First execution of ``make`` will automatically download and compile following libraries:
+
+- libfaketime_ - embedded because Deckard requires a rather recent version
+- `modified socket_wrapper`_ - custom modification of `original socket_wrapper`_ library (part of the cwrap_ tool set for creating an isolated networks)
+
+
+Compatibility
+-------------
+
+Works well on Linux, Mac OS X [#]_ and probably all BSDs. Tested with `Knot DNS Resolver`_, `Unbound`_, and `PowerDNS Recursor`_. It should work with other software as well as long as all functions used by the binary under test are supported by our `modified socket_wrapper`_.
+
+.. [#] Python from Homebrew must be used, as the built-in Python is protected by the CSR_ from OS X 10.11 and prevents library injection.
+
+
+Usage
+-----
+
+- `User guide <doc/user_guide.rst>`_ describes how to run tests on a binary.
+- `Scenario guide <doc/scenario_guide.rst>`_ describes how to write a new test.
+- `Devel guide <doc/devel_guide.rst>`_ contains some tips for Deckard developers.
+
+
+License
+-------
+
+See `LICENSE <LICENSE>`_ file.
+
+
+Acknowledgments
+---------------
+
+The test scenario design and a lot of tests were written by `NLnet Labs`_ for ``testbound`` suite used by `Unbound`_ (BSD licensed). We are grateful that ``testbound`` authors are `willing to discuss <https://unbound.nlnetlabs.nl/pipermail/unbound-users/2017-March/004699.html>`_ further Deckard development.
+
+The original test case format is described in the `header file replay.h <http://unbound.net/documentation/doxygen/replay_8h.html#a6f204646f02cc4debbaf8a9b3fdb59a7>`_ distributed with `Unbound`_.
+
+
+Contacting us
+-------------
+
+Please report problems to our GitLab: https://gitlab.labs.nic.cz/knot/deckard/issues
+
+If you have any comments feel free to send e-mail to knot-dns@labs.nic.cz! Do not get confused by the name, we are happy if you want to use Deckard with any software.
+
+Happy testing.
+
+
+.. _`augeas`: http://augeas.net/
+.. _`CSR`: http://apple.stackexchange.com/questions/193368/what-is-the-rootless-feature-in-el-capitan-really
+.. _`Jinja2`: http://jinja.pocoo.org/
+.. _`Knot DNS Resolver`: https://gitlab.labs.nic.cz/knot/resolver/blob/master/README.md
+.. _`NLnet Labs`: https://www.nlnetlabs.nl/
+.. _`PowerDNS Recursor`: https://doc.powerdns.com/md/recursor/
+.. _`PyYAML`: http://pyyaml.org/
+.. _`Unbound`: https://www.unbound.net/
+.. _`cwrap`: https://cwrap.org/
+.. _`dnspython`: http://www.dnspython.org/
+.. _`libfaketime`: https://github.com/wolfcw/libfaketime
+.. _`modified socket_wrapper`: https://gitlab.labs.nic.cz/labs/socket_wrapper
+.. _`original socket_wrapper`: https://cwrap.org/socket_wrapper.html
+.. _`python-augeas`: https://pypi.org/project/python-augeas/
+.. _`pytest`: https://pytest.org/
+.. _`pytest-xdist`: https://pypi.python.org/pypi/pytest-xdist
diff --git a/tests/deckard/ci/README.rst b/tests/deckard/ci/README.rst
new file mode 100644
index 0000000..39955f9
--- /dev/null
+++ b/tests/deckard/ci/README.rst
@@ -0,0 +1,4 @@
+Deckard CI
+==========
+
+For testing with Deckard in Docker use kresd ci image: registry.labs.nic.cz/knot/knot-resolver/ci:debian-stable
diff --git a/tests/deckard/ci/common.sh b/tests/deckard/ci/common.sh
new file mode 100644
index 0000000..5430e64
--- /dev/null
+++ b/tests/deckard/ci/common.sh
@@ -0,0 +1,17 @@
+set -o errexit -o nounset
+
+HEAD="$(git log -1 --format="%H" HEAD)"
+MERGEBASE="$(git merge-base origin/master "${HEAD}")"
+LOGDIR="$(pwd)"
+PYTHON=${PYTHON:-"python3"}
+CIDIR="$(dirname "${0}")"
+
+# workaround for Gitlab's missing support for absolute paths in artifacts:
+# https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/1011
+declare -a LOGS
+LOGS[0]="" # avoid unbound variable error if user does not specify own logs
+function collect_logs {
+ set +o errexit
+ test -n "${LOGS[*]}" && cp "--target-directory=${LOGDIR}" ${LOGS[*]}
+}
+trap collect_logs EXIT
diff --git a/tests/deckard/ci/compare-rplint.sh b/tests/deckard/ci/compare-rplint.sh
new file mode 100755
index 0000000..0146dc9
--- /dev/null
+++ b/tests/deckard/ci/compare-rplint.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+set -o nounset -o xtrace -o errexit
+source "$(dirname "$(readlink -f "$0")")/common.sh"
+
+
+function find_new_tests {
+ : detect tests affected by current merge request
+ : store list of modified tests in ${NEW_TESTS_FILE}
+ git diff --name-only --diff-filter=AM ${MERGEBASE} ${HEAD} | fgrep .rpl > "${NEW_TESTS_FILE}" || : no new tests detected
+}
+
+NEW_TESTS_FILE="/tmp/new_tests"
+find_new_tests
+
+truncate -s0 /tmp/rplint_fails
+
+: run rplint of all new tests
+FAIL=0
+cat /tmp/new_tests
+for test in $(cat ${NEW_TESTS_FILE})
+do
+ ${PYTHON} -m rplint $test >> /tmp/rplint_fails || FAIL=1
+done
+
+: if even one of the test does not pass rplint, fail
+if [ "$FAIL" -eq 1 ]
+then
+ cat /tmp/rplint_fails
+ exit 1
+fi
+exit 0
diff --git a/tests/deckard/ci/compare-tests.sh b/tests/deckard/ci/compare-tests.sh
new file mode 100755
index 0000000..63d8c67
--- /dev/null
+++ b/tests/deckard/ci/compare-tests.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -o nounset -o xtrace -o errexit
+source "$(dirname "$0")/common.sh"
+TESTRUNNER="$1"
+: comparing results from test script "${TESTRUNNER}"
+
+# Run specified test runner on HEAD and again on merge base for master..HEAD
+# Fail if result of any test not modified between master..HEAD changed
+# (i.e. any change in Deckard should not change results of non-modified tests)
+
+function find_modified_tests {
+ : detect tests affected by current merge request
+ : store list of modified tests in ${MODIFIED_TESTS_FILE}
+ git diff --numstat "${MERGEBASE}..${HEAD}" | cut -f 3 | fgrep .rpl > "${MODIFIED_TESTS_FILE}" || : no modified tests detected
+}
+
+MODIFIED_TESTS_FILE="/tmp/modified_tests"
+find_modified_tests
+LOGS[0]="${MODIFIED_TESTS_FILE}"
+LOGS[1]="/tmp/base.xml"
+LOGS[2]="/tmp/head.xml"
+
+: get test results from version under test
+"${TESTRUNNER}" -n $(nproc) --junit-xml=/tmp/head.xml || : some tests on HEAD ${HEAD} failed
+
+: get test results from common ancestor with master branch
+git checkout --force --detach "${MERGEBASE}"
+git clean -xdf
+"${TESTRUNNER}" -n $(nproc) --junit-xml=/tmp/base.xml || : some tests on merge base ${MERGEBASE} failed
+"${CIDIR}/junit-compare.py" /tmp/head.xml /tmp/base.xml /tmp/modified_tests && echo "OK, no differences found"
diff --git a/tests/deckard/ci/junit-compare.py b/tests/deckard/ci/junit-compare.py
new file mode 100755
index 0000000..54ca71a
--- /dev/null
+++ b/tests/deckard/ci/junit-compare.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python3
+
+import sys
+
+import xml.etree.ElementTree as xml
+
+
+def parse_junit_xml(filename):
+ """
+ Transform junit XML file into set of tuples:
+ (test description, file name, test result)
+ """
+ results = set()
+ root = xml.parse(filename).getroot()
+ for case in root:
+ if case.find("failure") is not None: # Because empty XML elements are falsey
+ results.add((case.get("name"), case.get("name").split("'")[1], "FAILED"))
+ elif case.find("skipped") is not None:
+ results.add((case.get("name"), case.get("name").split("'")[1], "SKIPPED"))
+ else:
+ results.add((case.get("name"), case.get("name").split("'")[1], "PASSED"))
+
+ return results
+
+
+new = sys.argv[1]
+old = sys.argv[2]
+modified_tests = [line.strip() for line in open(sys.argv[3]).readlines()]
+
+test_diffs = parse_junit_xml(old) ^ parse_junit_xml(new)
+errorneous_rpls = [diff[1] for diff in test_diffs
+ if diff[1] not in modified_tests]
+if errorneous_rpls:
+ print('FAIL! Following tests changed their result without test modification:')
+ for rpl in sorted(set(errorneous_rpls)):
+ print(rpl)
+ sys.exit(1)
diff --git a/tests/deckard/ci/mypy-run.sh b/tests/deckard/ci/mypy-run.sh
new file mode 100755
index 0000000..d99e256
--- /dev/null
+++ b/tests/deckard/ci/mypy-run.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+set -o nounset -o errexit
+source "$(dirname "$0")/common.sh"
+
+PYFILES=$(find . \
+ -path ./.git -prune -o \
+ -path ./contrib -o \
+ -type d -exec test -e '{}/__init__.py' \; -print -prune -o \
+ -name '*.py' -print -o \
+ -type f -exec grep -qsm1 '^#!.*\bpython' '{}' \; -print)
+set -e
+
+${PYTHON} -m mypy --ignore-missing-imports ${PYFILES}
diff --git a/tests/deckard/ci/pylint-run.sh b/tests/deckard/ci/pylint-run.sh
new file mode 100755
index 0000000..2df40ef
--- /dev/null
+++ b/tests/deckard/ci/pylint-run.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -o nounset -o errexit
+source "$(dirname "$0")/common.sh"
+
+PYFILES=$(find . \
+ -path ./.git -prune -o \
+ -path ./contrib -o \
+ -type d -exec test -e '{}/__init__.py' \; -print -prune -o \
+ -name '*.py' -print -o \
+ -type f -exec grep -qsm1 '^#!.*\bpython' '{}' \; -print)
+
+${PYTHON} -m pylint -j 0 --rcfile pylintrc ${PYFILES}
diff --git a/tests/deckard/ci/runlocally.sh b/tests/deckard/ci/runlocally.sh
new file mode 100755
index 0000000..25bf0c9
--- /dev/null
+++ b/tests/deckard/ci/runlocally.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -o nounset -o errexit
+CIDIR="$(dirname "$0")"
+ORIGNAME="$(git symbolic-ref -q --short HEAD || git describe --all --always HEAD)"
+FAILURE_DETECTED="?"
+
+function checkout_back {
+ git checkout --force "${ORIGNAME}" || { echo "Warning: unable to checkout back!"; exit 5; }
+
+ test "${FAILURE_DETECTED}" "==" "0" && echo "All tests passed, good work!"
+ test "${FAILURE_DETECTED}" "!=" "0" && echo "Problem found, go fix it!"
+}
+
+STATUS=$(git status --untracked-files=normal --porcelain)
+test -n "${STATUS}" && echo "Working tree is dirty, commit your changes now." && exit 2
+
+# return back to whatever branch we were on the beginning
+# to avoid need for git checkout before fixing reported bugs
+trap checkout_back EXIT
+trap "{ FAILURE_DETECTED=1; }" ERR
+
+"${CIDIR}"/compare-rplint.sh
+checkout_back
+git clean -xdf
+
+"${CIDIR}"/compare-pylint.sh
+checkout_back
+git clean -xdf
+
+"${CIDIR}"/compare-pep8.sh
+checkout_back
+git clean -xdf
+
+"${CIDIR}"/compare-tests.sh "${CIDIR}/../kresd_run.sh"
+checkout_back
+git clean -xdf
+
+# at this point all the tests passed so we can clean up
+git clean -xdf
+FAILURE_DETECTED=0
+trap - ERR
diff --git a/tests/deckard/configs/getdns.yaml b/tests/deckard/configs/getdns.yaml
new file mode 100644
index 0000000..a5d1a2e
--- /dev/null
+++ b/tests/deckard/configs/getdns.yaml
@@ -0,0 +1,12 @@
+programs:
+- name: getdns
+ binary: getdns_query
+ additional:
+ - -C
+ - getdns.conf
+ templates:
+ - template/getdns.j2
+ - template/dnssec_getdns.j2
+ configs:
+ - getdns.conf
+ - getdns-root.key
diff --git a/tests/deckard/configs/knotd_master.yaml b/tests/deckard/configs/knotd_master.yaml
new file mode 100644
index 0000000..2e08b72
--- /dev/null
+++ b/tests/deckard/configs/knotd_master.yaml
@@ -0,0 +1,10 @@
+programs:
+- name: knotd
+ binary: knotd
+ additional:
+ - -c
+ - ./knotd.conf
+ templates:
+ - "template/knotd_master.j2"
+ configs:
+ - "knotd.conf"
diff --git a/tests/deckard/configs/knotd_slave.yaml b/tests/deckard/configs/knotd_slave.yaml
new file mode 100644
index 0000000..4655ded
--- /dev/null
+++ b/tests/deckard/configs/knotd_slave.yaml
@@ -0,0 +1,10 @@
+programs:
+- name: knotd
+ binary: knotd
+ additional:
+ - -c
+ - ./knotd.conf
+ templates:
+ - "template/knotd_slave.j2"
+ configs:
+ - "knotd.conf" \ No newline at end of file
diff --git a/tests/deckard/configs/kresd.yaml b/tests/deckard/configs/kresd.yaml
new file mode 100644
index 0000000..b36a232
--- /dev/null
+++ b/tests/deckard/configs/kresd.yaml
@@ -0,0 +1,10 @@
+programs:
+- name: kresd
+ binary: kresd
+ additional:
+ - -f
+ - "1"
+ templates:
+ - template/kresd.j2
+ configs:
+ - config
diff --git a/tests/deckard/configs/pdns.yaml b/tests/deckard/configs/pdns.yaml
new file mode 100644
index 0000000..c9a3d23
--- /dev/null
+++ b/tests/deckard/configs/pdns.yaml
@@ -0,0 +1,15 @@
+programs:
+- name: pdns
+ binary: pdns_recursor
+ additional:
+ - --config-dir=./
+ templates:
+ - template/pdns_recursor.j2
+ - template/hints_zone.j2
+ - template/pdns_dnssec.j2
+ configs:
+ - recursor.conf
+ - hints.pdns
+ - dnssec.lua
+ # SIGTERM leads to return code -15 instead of clean 0 so we have to ignore it
+ ignore_exit_code: true
diff --git a/tests/deckard/configs/unbound.yaml b/tests/deckard/configs/unbound.yaml
new file mode 100644
index 0000000..3c200db
--- /dev/null
+++ b/tests/deckard/configs/unbound.yaml
@@ -0,0 +1,13 @@
+programs:
+- name: unbound
+ binary: unbound
+ additional:
+ - -d
+ - -c
+ - unbound.conf
+ templates:
+ - template/unbound.j2
+ - template/hints_zone.j2
+ configs:
+ - unbound.conf
+ - hints.zone
diff --git a/tests/deckard/conftest.py b/tests/deckard/conftest.py
new file mode 100644
index 0000000..c9c5bb2
--- /dev/null
+++ b/tests/deckard/conftest.py
@@ -0,0 +1,156 @@
+from collections import namedtuple, OrderedDict
+import glob
+import logging
+import os
+import re
+import yaml
+
+import pytest
+
+
+Scenario = namedtuple("Scenario", ["path", "qmin", "config"])
+
+
+def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
+ """Make YaML load to OrderedDict.
+ This is done to ensure compability with Python versions prior to 3.6.
+ See docs.python.org/3.6/whatsnew/3.6.html#new-dict-implementation for more information.
+
+ repr(config) is a part of testcase's name in pytest.
+ We need to ensure that it is ordered in the same way.
+ See https://github.com/pytest-dev/pytest/issues/1075.
+ """
+ class OrderedLoader(Loader): # pylint: disable=too-many-ancestors
+ pass
+
+ def construct_mapping(loader, node):
+ loader.flatten_mapping(node)
+ return object_pairs_hook(loader.construct_pairs(node))
+
+ OrderedLoader.add_constructor(
+ yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
+ construct_mapping)
+
+ return yaml.load(stream, OrderedLoader)
+
+
+def config_sanity_check(config_dict, config_name):
+ """Checks if parsed configuration is valid"""
+ mandatory_keys = {'name', 'binary', 'templates', 'configs', 'additional'}
+ for cfg in config_dict['programs']:
+ missing_keys = mandatory_keys - set(cfg.keys())
+ assert not missing_keys, 'Mandatory fields in configuration are missing: %s' % missing_keys
+
+ # sanity check templates vs. configs
+ assert len(cfg['templates']) == len(cfg['configs']),\
+ ('Number of jinja2 template files is not equal '
+ 'to number of config files to be generated for '
+ 'program "%s" (%s), i.e. len(templates) != len(configs)'
+ % (cfg['name'], config_name))
+
+ for additional in cfg["additional"]:
+ assert isinstance(additional, str),\
+ "All additional arguments in yaml should be strings. (%s, %s)"\
+ % (cfg['name'], config_name)
+
+
+def get_qmin_config(path):
+ """Reads configuration from the *.rpl file and determines query-minimization setting."""
+ with open(path) as f:
+ for line in f:
+ if re.search(r"^CONFIG_END", line) or re.search(r"^SCENARIO_BEGIN", line):
+ return None
+ if re.search(r"^\s*query-minimization:\s*(on|yes)", line):
+ return True
+ if re.search(r"^\s*query-minimization:\s*(off|no)", line):
+ return False
+ return None
+
+
+def scenarios(paths, configs):
+ """Returns list of *.rpl files from given path and packs them with their minimization setting"""
+
+ assert len(paths) == len(configs),\
+ "Number of --config has to be equal to number of --scenarios arguments."
+
+ scenario_list = []
+
+ for path, config in zip(paths, configs):
+ config_dict = ordered_load(open(config), yaml.SafeLoader)
+ config_sanity_check(config_dict, config)
+
+ if os.path.isfile(path):
+ filelist = [path] # path to single file, accept it
+ else:
+ filelist = sorted(glob.glob(os.path.join(path, "*.rpl")))
+
+ if not filelist:
+ raise ValueError('no *.rpl files found in path "{}"'.format(path))
+
+ for file in filelist:
+ scenario_list.append(Scenario(file, get_qmin_config(file), config_dict))
+
+ return scenario_list
+
+
+def rpls(paths):
+ for path in paths:
+ if os.path.isfile(path):
+ filelist = [path] # path to single file, accept it
+ else:
+ filelist = sorted(glob.glob(os.path.join(path, "*.rpl")))
+
+ return filelist
+
+
+def pytest_addoption(parser):
+ parser.addoption("--config", action="append", help="path to Deckard configuration .yaml file")
+ parser.addoption("--scenarios", action="append", help="directory with .rpl files")
+ parser.addoption("--retries", action="store", help=("number of retries per"
+ "test when Deckard is under load"))
+
+
+def pytest_generate_tests(metafunc):
+ """This is pytest weirdness to parametrize the test over all the *.rpl files.
+ See https://docs.pytest.org/en/latest/parametrize.html#basic-pytest-generate-tests-example
+ for more info."""
+
+ if 'scenario' in metafunc.fixturenames:
+ if metafunc.config.option.config is None:
+ configs = []
+ else:
+ configs = metafunc.config.option.config
+
+ if metafunc.config.option.scenarios is None:
+ paths = ["sets/resolver"] * len(configs)
+ else:
+ paths = metafunc.config.option.scenarios
+
+ metafunc.parametrize("scenario", scenarios(paths, configs), ids=str)
+ if 'rpl_path' in metafunc.fixturenames:
+ paths = metafunc.config.option.scenarios
+ metafunc.parametrize("rpl_path", rpls(paths), ids=str)
+ if 'max_retries' in metafunc.fixturenames:
+ max_retries = metafunc.config.option.retries
+ if max_retries is None:
+ max_retries = 3
+ metafunc.parametrize("max_retries", [max_retries], ids=lambda id: "max-retries-"+str(id))
+
+
+def check_log_level_xdist(level):
+ if level < logging.ERROR:
+ pytest.exit("Advanced logging not available while running with xdist "
+ "(try ommiting -n option)")
+
+
+def pytest_configure(config):
+ # This means pytest-xdist is installed and enabled
+ if hasattr(config.option, "dist") and config.option.dist == "load":
+ log_level = config.option.log_level
+ if log_level is None:
+ return
+ try:
+ log_level = int(log_level)
+ except ValueError:
+ log_level = logging.getLevelName(log_level)
+ check_log_level_xdist(log_level)
diff --git a/tests/deckard/contrib/deckard.vim b/tests/deckard/contrib/deckard.vim
new file mode 100644
index 0000000..3ae687a
--- /dev/null
+++ b/tests/deckard/contrib/deckard.vim
@@ -0,0 +1,26 @@
+" Deckard syntax highlighting & folding
+"
+" Usage: Put following lines into ~/.vim/ftdetect/deckard.vim
+" au BufRead,BufNewFile *.rpl set filetype=deckard
+" au BufRead,BufNewFile *.stc set foldmethod=syntax
+
+syntax keyword Keyword MATCH STEP ADJUST MANDATORY RAW
+syntax keyword Structure CONFIG_END
+syntax keyword Function CHECK_ANSWER QUERY TIME_PASSES
+
+syntax region deckardEntry matchgroup=Structure start="ENTRY_BEGIN" end="ENTRY_END" fold transparent
+syntax region deckardRange matchgroup=Structure start="RANGE_BEGIN" end="RANGE_END" fold transparent
+syntax region deckardScenario matchgroup=Structure start="SCENARIO_BEGIN" end="SCENARIO_END" fold transparent
+
+syntax match deckardSection 'SECTION \+[^ ]\+'
+syntax match deckardReply 'REPLY.*'
+
+syntax match Comment ';.*$'
+
+hi def link deckardEntry Folded
+hi def link deckardRange Folded
+hi def link deckardScenario Folded
+hi def link deckardSection Special
+hi def link deckardReply String
+
+let b:current_syntax = 'deckard'
diff --git a/tests/deckard/contrib/libfaketime/.gitignore b/tests/deckard/contrib/libfaketime/.gitignore
new file mode 100644
index 0000000..d45f99a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/.gitignore
@@ -0,0 +1,9 @@
+*.o
+*.so.1
+timetest
+
+src/libfaketime.dylib.1
+src/libfaketime.1.dylib
+src/core
+src/faketime
+
diff --git a/tests/deckard/contrib/libfaketime/COPYING b/tests/deckard/contrib/libfaketime/COPYING
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/tests/deckard/contrib/libfaketime/Makefile b/tests/deckard/contrib/libfaketime/Makefile
new file mode 100644
index 0000000..d88e35a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/Makefile
@@ -0,0 +1,34 @@
+INSTALL ?= install
+
+UNAME=$(shell uname)
+SELECTOR:=$(shell if test "${UNAME}" = "Darwin" ; then echo "-f Makefile.OSX" ; fi)
+
+all:
+ $(MAKE) $(SELECTOR) -C src all
+
+test:
+ $(MAKE) $(SELECTOR) -C test all
+
+install:
+ $(MAKE) $(SELECTOR) -C src install
+ $(MAKE) $(SELECTOR) -C man install
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/doc/faketime/"
+ $(INSTALL) -m0644 README "${DESTDIR}${PREFIX}/share/doc/faketime/README"
+ $(INSTALL) -m0644 NEWS "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
+
+uninstall:
+ $(MAKE) $(SELECTOR) -C src uninstall
+ $(MAKE) $(SELECTOR) -C man uninstall
+ rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/README"
+ rm -f "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
+ rmdir "${DESTDIR}${PREFIX}/share/doc/faketime"
+
+clean:
+ $(MAKE) $(SELECTOR) -C src clean
+ $(MAKE) $(SELECTOR) -C test clean
+
+distclean:
+ $(MAKE) $(SELECTOR) -C src distclean
+ $(MAKE) $(SELECTOR) -C test distclean
+
+.PHONY: all test install uninstall clean distclean
diff --git a/tests/deckard/contrib/libfaketime/NEWS b/tests/deckard/contrib/libfaketime/NEWS
new file mode 100644
index 0000000..8836d80
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/NEWS
@@ -0,0 +1,134 @@
+Since 0.9.6:
+ - Julien Gilli added an option to disable monotonic time faking
+ - Azat Khuzhin added support for COARSE clocks
+ - Preliminary support for CLOCK_BOOTTIME (Linux)
+ - Fixed compilation on macOS (High) Sierra and various compiler warnings
+ - Support for select() call added by Hitoshi Harada (umitanuki)
+ - Updated documentation
+
+Since 0.9.5:
+ - fixed crashes that happened when other LD_PRELOAD libraries were used
+ - fixed passing through of return values when using the faketime wrapper
+ - fixed compile-time issues with CLOCK_MONOTONIC_RAW on some platforms
+ - rbalint added Filter commands: FAKETIME_ONLY_CMDS and
+ FAKETIME_SKIP_CMDS control which (sub-)processes libfaketime
+ is applied to.
+
+Since 0.9:
+ - ryandesign at MacPorts provided a Portfile for MacPorts and
+ fixed various build issues on OSX.
+ - Balint Reczey added support for nanosecond resolution, saving
+ timestamps to files, speeding up and slowing down per-process
+ timers, CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW, faketime
+ support for system calls such as sleep() and alarm().
+ - Applied a patch by Gerardo Malazdrewicz and Toni G to restore
+ compatibility with newer versions of glibc.
+ - Balint Reczey added an option to use the same global clock setting
+ for all libfaketime-spawned processes.
+ - Balint Reczey has rewritten the faketime wrapper shell script in C
+ and refactored libfaketime.
+ - Balint Reczey added support for advancing the time with each time-
+ related system call ("deterministic time").
+ - Added "timeprivacy" wrapper by adrelanos; it ensures that programs
+ are started with unique timestamps.
+ - Code and documentation cleanup by Tomi Ollila.
+ - Reworked Makefiles for more flexible installation, including fixes
+ by Lukas Fleischner, Daniel Kahm Gillmor, and Hugues Andreux.
+ - Fixed license issues as pointed out by Paul Wouters.
+ - Mac OS X support has been improved for OS X 10.7 and 10.8; due to
+ changes to the underlying libraries on OS X, libfaketime 0.9.5 will
+ no longer work with OS X < 10.6; use libfaketime 0.9(.1) for older
+ OS X installations.
+ - Don Fong has contributed a new framework for functional tests.
+ Petr Salinger ensured its compatibility with GNU/kFreeBSD.
+
+Since 0.8.2:
+ - Added support for "limited faking".
+ You can optionally specify when libfaketime starts to fake the
+ returned timestamps and when it shall stop doing so. For example,
+ a program can be started regularly, and after 5 minutes run-time
+ it will be sent two years into the future. Those limiting
+ start and stop times can be specified in seconds or as the
+ number of any time-related function calls within the program.
+ - Added a feature to spawn an external process after x seconds
+ or y time-related system calls. This can, for example, be used
+ to execute an arbitrary shell script x seconds after a program
+ has been started.
+
+Since 0.8.1:
+ - Added a MacOS port.
+ Thanks to Daria Phoebe Brashear!
+ - Added a functional test framework that aids in automatically
+ determining whether libfaketime works properly on the current
+ machine. Thanks to Don Fong!
+
+Since 0.8:
+ - Changed directory layout and Makefile structure.
+ Thanks to Lukas Fleischer!
+
+Since 0.7:
+ - Added support for fstatat() and fstatat64() which were introduced in
+ Linux kernel 2.6.16 and used in recent coreutils.
+ Thanks to Daniel Kahn Gillmor for the report!
+ This can be disabled by passing -DNO_ATFILE in the Makefile.
+ - Added a simple wrapper shell script and a man page for it. Makes it
+ easier to run commands under faked system times. It assumes that the
+ libraries will be copied to /usr/lib/faketime during installation,
+ please adjust this path if necessary. The "install" target in the
+ Makefile has been adapted accordingly.
+ - Added support for fractional time offsets, such as FAKETIME="+1,5h".
+ Please note that either , or . has to be used as a delimiter
+ depending on your locale. Thanks to Karl Chen!
+ - Added support for speeding the clock up or slowing it down. For
+ example, FAKETIME="+5d x2,0" will set the faked time 5 days into
+ the future and make the clock run twice as fast for the specified
+ program. Slowing it down can be done e.g. by using FAKETIME="+0 x0,5".
+ Again, the delimiter to use for the fraction depends on your locale.
+ Thanks to Karl Chen!
+
+Since 0.6:
+ Main version 0.7 contributions by David North, TDI:
+ - Added ability to 'start clock at' a specific time.
+ - Added pthread synchronization support
+ - Added a 2 second delay to timetest.c so one can observe if the
+ clock is relative or absolute
+ - Added test.sh example of 'start clock at'
+ - Added ability to disable the FAKE_STAT functionality at library-start
+ in the case that the library was compiled -DFAKE_STAT, and added another
+ test case for demonstrating this
+ - Repaired a bug w.r.t. strptime/mktime wherein 'isdst' was uninitialized
+ which led to pseudorandom +/- 1 hour results being returned in 'start at'
+ or absolute time modes
+
+ Other enhancements:
+ - Fixed missing interceptions to libc-internal functions and added notes
+ about a workaround for running Java programs with faked times in the
+ future (they worked properly, but often locked up at exiting). Thanks to
+ Jamie Cameron of Google for in-depth analysis and prototype solution!
+
+Since 0.5:
+ - Performance enhancements by means of caching the data read
+ e.g. from $HOME/.faketimerc for 10 seconds.
+ - Several file timestamp related system calls such as fstat() will be
+ intercepted now. See the README file on how to turn this off if you
+ do not need it. Thanks to Philipp Hachtmann!
+ - A system-wide /etc/faketimerc file will now be used if no FAKETIME
+ environment variable has been set and no $HOME/.faketimerc is present.
+ Thanks to David Burley, Jacob Moorman, and Wayne Davison of
+ SourceForge, Inc.!
+ - Added trivial Makefile targets clean/distclean/install
+ - Changed Makefile target test to run new test.sh script
+ - Added new test cases to timetest.c
+
+Since 0.4:
+ - Allow "y" for years of offset specification. Thanks to Bas ten Berge!
+
+Since 0.3:
+ - Support for FAKETIME_FMT environment variable. Thanks to Moreno Baricevic!
+
+Since 0.2:
+ - Intercept clock_gettime(). Thanks to Andreas Thienemann!
+
+Since 0.1:
+ - Fixed segfault when calling time(NULL). Thanks to Andres Ojamaa!
+ - Added additional sanity checks.
diff --git a/tests/deckard/contrib/libfaketime/README b/tests/deckard/contrib/libfaketime/README
new file mode 100644
index 0000000..248bc92
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/README
@@ -0,0 +1,534 @@
+libfaketime, version 0.9.7 (November 2017)
+==========================================
+
+
+Content of this file:
+---------------------
+
+1. Introduction
+2. Compatibility issues
+3. Installation
+4. Usage
+ a) Basics
+ b) Using absolute dates
+ c) Using 'start at' dates
+ d) Using offsets for relative dates
+ e) Advanced features and caveats
+ f) Faking the date and time system-wide
+ g) Using the "faketime" wrapper script
+ h) "Limiting" libfaketime based on elapsed time or number of calls
+ i) "Limiting" libfaketime per process
+ j) Spawning an external process
+ k) Saving timestamps to file, loading them from file
+5. License
+6. Contact
+
+
+1. Introduction
+---------------
+
+libfaketime intercepts various system calls that programs use to retrieve the
+current date and time. It then reports modified (faked) dates and times (as
+specified by you, the user) to these programs. This means you can modify the
+system time a program sees without having to change the time system-wide.
+
+libfaketime allows you to specify both absolute dates (e.g., 01/01/2004) and
+relative dates (e.g., 10 days ago).
+
+libfaketime might be used for various purposes, for example
+
+- deterministic build processes
+- debugging time-related issues, such as expired SSL certificates
+- testing software for year-2038 compliance
+
+libfaketime ships with a command line wrapper called "faketime" that makes it
+easier to use, but does not expose all of libfaketime's functionality. If your
+use case is not covered by the faketime command, make sure to look in this
+documentation whether it can be achieved by using libfaketime directly.
+
+
+2. Compatibility issues
+-----------------------
+
+- libfaketime is supposed to work on Linux and macOS.
+ Your mileage may vary; some other *NIXes have been reported to work as well.
+
+- libfaketime uses the library preload mechanism of your operating system's
+ linker (which is involved in starting programs) and thus cannot work with
+ statically linked binaries or binaries that have the setuid-flag set (e.g.,
+ suidroot programs like "ping" or "passwd"). Please see you system linker's
+ manpage for further details.
+
+- libfaketime supports the pthreads environment. A separate library is built
+ (libfaketimeMT.so.1), which contains the pthread synchronization calls. This
+ library also single-threads calls through the time() intercept because
+ several variables are statically cached by the library and could cause issues
+ when accessed without synchronization.
+
+ However, the performance penalty for this might be an issue for some
+ applications. If this is the case, you can try using an unsynchronized time()
+ intercept by removing the -DPTHREAD_SINGLETHREADED_TIME from the Makefile and
+ rebuilding libfaketimeMT.so.1
+
+* Java-/JVM-based applications work but you need to pass in an extra argument
+ (DONT_FAKE_MONOTONIC). See usage basics below for details. Without this
+ argument the java command usually hangs.
+
+* libfaketime will eventually be bypassed by applications that dynamically load
+ system libraries, such as librt, explicitly themselves instead of relying on
+ the linker to do so at application start time. libfaketime will not work with
+ those applications unless you can modify them.
+
+* Applications can explicitly be designed to prevent libfaketime from working,
+ e.g., by checking whether certain environment variables are set or whether
+ libfaketime-specific files are present.
+
+
+3. Installation
+---------------
+
+Running "make" compiles both library versions and a test program, which it then
+also executes.
+
+If the test works fine, you should copy the libfaketime libraries
+(libfaketime.so.1, and libfaketimeMT.so.1) to the place you want them in.
+Running "make install" will attempt to place them in /usr/local/lib/faketime
+and will install the wrapper shell script "faketime" in /usr/local/bin, both of
+which most likely will require root privileges. However, from a technical point
+of view, there is no necessity for a system-wide installation, so you can use
+libfaketime also on machines where you do not have root privileges. You may
+want to adjust the PREFIX variable in the Makefiles accordingly.
+
+By default, the Makefile compiles/links libfaketime for your default system
+architecture. If you need to build, e.g., 32-bit files on a 64-bit platform,
+please see the notes about CFLAGS and LDFLAGS in src/Makefile.
+
+Since version 0.6, system calls to file timestamps are also intercepted,
+thanks to a contribution by Philipp Hachtmann. This is especially useful in
+combination with relative time offsets as explained in section 4d) below, if a
+program writes and reads files whose timestamps also shall be faked. If you do
+not need this feature or if it confuses the application you want to use FTPL
+with, define the environment variable NO_FAKE_STAT, and the intercepted stat
+calls will be passed through unaltered.
+
+On macOS, it is necessary to compile differently, due to the different
+behavior dyld has. Use the Makefile.OSX file provided to compile
+libfaketime.1.dylib. Additionally, instead of using LD_PRELOAD,
+the variable DYLD_INSERT_LIBRARIES should be set to the path to
+libfaketime.1.dylib, and the variable DYLD_FORCE_FLAT_NAMESPACE should be
+set (to anything). macOS users should read README.OSX for additional
+details.
+
+
+4. Usage
+--------
+
+4a) Usage basics
+----------------
+
+Using libfaketime on a program of your choice consists of two steps:
+
+1. Making sure libfaketime gets loaded by the system's linker.
+2. Specify the faked time.
+
+As an example, we want the "date" command to report our faked time. To do so,
+we could use the following command line on Linux:
+
+user@host> date
+Tue Nov 23 12:01:05 CEST 2016
+
+user@host> LD_PRELOAD=/usr/local/lib/libfaketime.so.1 FAKETIME="-15d" date
+Mon Nov 8 12:01:12 CEST 2016
+
+user@host> LD_PRELOAD=/usr/local/lib/libfaketime.so.1 FAKETIME="-15d"
+DONT_FAKE_MONOTONIC=1 java -version
+java version "1.8.0_111"
+Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
+Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
+
+The basic way of running any command/program with libfaketime enabled is to
+make sure the environment variable LD_PRELOAD contains the path and
+filename of the libfaketime library. This can either be done by setting it once
+beforehand:
+
+export LD_PRELOAD=/path/to/libfaketime.so.1
+(now run any command you want)
+
+Or it can be done by specifying it on the command line itself:
+
+LD_PRELOAD=/path/to/libfaketime.so.1 your_command_here
+
+(These examples are for the bash shell; how environment variables are set may
+vary on your system.)
+
+On Linux, library search paths can be set as part of the linker configuration.
+LD_PRELOAD then also works with relative paths. For example, when libfaketime.so.1
+is installed as /path/to/libfaketime.so.1, you can add /path/to to an appropriate
+linker configuration file, e.g., /etc/ld.so.conf.d/local.conf, and then run
+the "ldconfig" command. Afterwards, using LD_PRELOAD=libfaketime.so.1 suffices.
+
+However, also the faked time should be specified; otherwise, libfaketime will
+be loaded, but just report the real system time. There are three ways to
+specify the faked time:
+
+a) By setting the environment variable FAKETIME.
+b) By using the file given in the environment variable FAKETIME_TIMESTAMP_FILE
+c) By using the file .faketimerc in your home directory.
+d) By using the file /etc/faketimerc for a system-wide default.
+
+If you want to use b) c) or d), $HOME/.faketimerc or /etc/faketimerc consist of
+only one line of text with exactly the same content as the FAKETIME environment
+variable, which is described below. Note that /etc/faketimerc will only be used
+if there is no $HOME/.faketimerc and no FAKETIME_TIMESTAMP_FILE file exists.
+Also, the FAKETIME environment variable _always_ has priority over the files.
+
+
+4b) Using absolute dates
+------------------------
+
+The format that _must_ be used for _absolute_ dates is "YYYY-MM-DD hh:mm:ss".
+For example, the 24th of December, 2020, 8:30 PM would have to be specified as
+FAKETIME="2020-12-24 20:30:00".
+
+
+4c) Using 'start at' dates
+--------------------------
+
+(Thanks to a major contribution by David North, TDI in version 0.7)
+
+The format that _must_ be used for _start_at_ dates is "@YYYY-MM-DD hh:mm:ss".
+For example, the 24th of December, 2020, 8:30 PM would have to be specified as
+FAKETIME="@2020-12-24 20:30:00".
+
+The absolute dates described in 4b) simulate a STOPPED system clock at the
+specified absolute time. The 'start at' format allows a 'relative' clock
+operation as described below in section 4d), but using a 'start at' time
+instead of an offset time.
+
+
+4d) Using offsets for relative dates
+------------------------------------
+
+Relative date offsets can be positive or negative, thus what you put into
+FAKETIME _must_ either start with a + or a -, followed by a number, and
+optionally followed by a multiplier:
+
+- By default, the offset you specify is in seconds. Example:
+
+ export FAKETIME="-120" will set the faked time 2 minutes (120 seconds) behind
+ the real time.
+
+- The multipliers "m", "h", "d" and "y" can be used to specify the offset in
+ minutes, hours, days and years (365 days each), respectively. Examples:
+
+ export FAKETIME="-10m" sets the faked time 10 minutes behind the real time.
+ export FAKETIME="+14d" sets the faked time to 14 days in the future.
+
+You now should understand the complete example we've used before:
+
+LD_PRELOAD=/usr/local/lib/libfaketime.so.1 FAKETIME="-15d" date
+
+This command line makes sure libfaketime gets loaded and sets the faked time to
+15 days in the past.
+
+Moreno Baricevic has contributed support for the FAKETIME_FMT environment
+variable, which allows you to optionally set the strptime() format:
+
+Some simple examples:
+LD_PRELOAD=./libfaketime.so.1 FAKETIME_FMT=%s FAKETIME="`date +%s -d'1 year ago'`" date
+LD_PRELOAD=./libfaketime.so.1 FAKETIME_FMT=%s FAKETIME="`stat -c %Y somefile`" date
+LD_PRELOAD=./libfaketime.so.1 FAKETIME_FMT=%c FAKETIME="`date`" date
+
+
+4e) Advanced features and caveats
+---------------------------------
+
+Advanced time specification options:
+------------------------------------
+
+Since version 0.8, thanks to a contribution by Karl Chen, fractions can be used
+in the specification of time offsets. For example,
+
+FAKETIME="+1,5h"
+
+is equivalent to FAKETIME="+90m". Please be aware that the fraction delimiter
+depends on your locale settings, so actually you might need to use
+
+FAKETIME="+1.5h"
+
+You should figure out the proper delimiter, e.g., by using libfaketime on
+a command like /bin/date where you immediately can verify whether it worked as
+expected.
+
+Also contributed by Karl Chen in v0.8 is the option to speed up or slow
+down the wall clock time for the program which is executed using libfaketime.
+For example,
+
+FAKETIME="+1y x2"
+
+will set the faked time one year into the future and will make the clock run
+twice as fast. Similarly,
+
+FAKETIME="+1y x0,5"
+
+will make the clock run only half as fast. As stated above, the fraction
+delimiter depends on your locale. Furthermore,
+
+FAKETIME="+1y i2,0"
+
+will make the clock step two seconds per each time(), etc. call, being
+completely independently of the system clock. It helps running programs
+with some determinism. In this single case all spawned processes will use
+the same global clock without restarting it at the start of each process.
+
+For testing, your should run a command like
+
+LD_PRELOAD=./libfaketime.so.1 FAKETIME="+1,5y x10,0" \
+/bin/bash -c 'while true; do echo $SECONDS ; sleep 1 ; done'
+
+For each second that the endless loop sleeps, the executed bash shell will
+think that 10 seconds have passed ($SECONDS is a bash-internal variable
+measuring the time since the shell was started).
+
+(Please note that replacing "echo $SECONDS" e.g. with a call to "/bin/date"
+will not give the expected result, since /bin/date will always be started as a
+new process for which also libfaketime will be re-initialized. It will show the
+correct offset (1.5 years in the future), but no speed-ups or slow-downs.)
+
+For applications that should use a different date & time each time they are
+run, consider using the included timeprivacy wrapper shellscript (contributed
+by adrelanos at riseup dot net).
+
+
+Caveats:
+--------
+
+Whenever possible, you should use relative offsets or 'start at' dates,
+and not use absolute dates.
+
+Why? Because the absolute date/time you set is fixed, i.e., if a program
+retrieves the current time, and retrieves the current time again 5 minutes
+later, it will still get the same result twice. This is likely to break
+programs which measure the time passing by (e.g., a mail program which checks
+for new mail every X minutes).
+
+Using relative offsets or 'start at' dates solves this problem.
+libfaketime then will always report the faked time based on the real
+current time and the offset you've specified.
+
+Please also note that your default specification of the fake time is cached for
+10 seconds in order to enhance the library's performance. Thus, if you change the
+content of $HOME/.faketimerc or /etc/faketimerc while a program is running, it
+may take up to 10 seconds before the new fake time is applied. If this is a
+problem in your scenario, you can change number of seconds before the file is read
+again with environment variable FAKETIME_CACHE_DURATION, or disable caching at all
+with FAKETIME_NO_CACHE=1. Remember that disabling the cache may negatively
+influence the performance.
+
+
+4f) Faking the date and time system-wide
+----------------------------------------
+
+David Burley of SourceForge, Inc. reported an interesting use case of applying
+libfaketime system-wide: Currently, all virtual machines running inside
+an OpenVZ host have the same system date and time. In order to use multiple
+sandboxes with different system dates, the libfaketime library can be put into
+/etc/ld.so.preload; it will then be applied to all commands and programs
+automatically. This is of course best used with a system-wide /etc/faketimerc
+file. Kudos to SourceForge, Inc. for providing the patch!
+
+Caveat: If you run a virtual machine, its real-time clock might be reset to the
+real world date & time when you reboot. Depending on your FAKETIME setting,
+this may lead to side effects, such as forced file system checks on each reboot.
+System-wide faked time may also lead to unexpected side effects with software
+auto-update tools, if the offset between real world time and faked system time
+is too large. If in doubt, set your system's date to the faked time and try out
+whether everything still works as expected before applying libfaketime
+system-wide.
+
+
+4g) Using the "faketime" wrapper
+--------------------------------
+
+As of version 0.8, libfaketime provides a command named "faketime", which is
+placed into /usr/bin by "make install". It spares the hassle of setting
+the LD_PRELOAD and FAKETIME environment variables manually, but only exposes
+a subset of libfaketime's functionality. On the other hand, it uses the date
+interpretation function by /bin/date in order to provide higher flexibility
+regarding the specification of the faked date and time. For example, you
+can use
+
+faketime 'last Friday 5 pm' /your/command/here
+
+Of course, also absolute dates can be used, such as in
+
+faketime '2018-12-24 08:15:42' /bin/date
+
+Thanks to Daniel Kahn Gillmor for providing these suggestions!
+
+Balint Reczey has rewritten the wrapper in 0.9.5 from a simple shell script
+to an efficient wrapper application.
+
+
+4h) "Limiting" libfaketime based on elapsed time or number of calls
+-------------------------------------------------------------------
+
+Starting with version 0.9, libfaketime can be configured to not be continuously
+active, but only during a certain time interval.
+
+For example, you might want to start a program with the real current time, but
+after 5 minutes of usage, you might want it to see a faked time, e.g., a year
+in the future.
+
+Dynamic changes to the faked time are alternatively possible by
+
+- changing the FAKETIME environment variable at run-time; this is the preferred
+ way if you use libfaketime for debugging and testing as a programmer, as it
+ gives you the most direct control of libfaketime without any performance
+ penalties.
+
+- not using the FAKETIME environment variable, but specifying the fake time in
+ a file (such as ~/.faketimerc). You can change the content of this file at
+ run-time. This works best with caching disabled, but comes at a performance
+ cost because this file has to be read and evaluated each time.
+
+The feature described here works based on two pairs of environment variables,
+
+ FAKETIME_START_AFTER_SECONDS and FAKETIME_STOP_AFTER_SECONDS, and
+ FAKETIME_START_AFTER_NUMCALLS and FAKETIME_STOP_AFTER_NUMCALLS
+
+The default value for each of these environment variables is -1, which means
+"ignore this value".
+
+If you want libfaketime to be only active during the run-time minutes 2 to 5
+of your application, you would set
+
+ FAKETIME_START_AFTER_SECONDS=60
+ FAKETIME_STOP_AFTER_SECONDS=300
+
+This means that your application will work with the real time from start (second
+0) up to second 60. It will then see a faked time from run-time seconds 60 to
+300 (minutes 2, 3, 4, and 5). After run-time second 600, it will again see the
+real (not-faked) time.
+
+This approach is not as flexible as changing the FAKETIME environment variable
+during runtime, but may be easier to use, works on a per-program (and not a
+per-user or system-wide) scope, and has only a minor performance overhead.
+
+Using the other pair of environment variables, you can limit the activity time
+of libfaketime not based on wall-clock seconds, but on the number of
+time-related function calls the started program performs. This alternative is
+probably only suitable for programmers who either know the code of the program
+in order to determine useful start/stop values or want to perform fuzzing
+tests.
+
+Both pairs of environment variables can be combined to further restrict
+libfaketime activity, although this is only useful in very few scenarios.
+
+Limiting libfaketime activity in this way is not recommended in general. Many
+programs will break when they are subject to sudden changes in time, especially
+if they are started using the current (real) time and are then sent back into
+the past after, e.g., 5 minutes. For example, they may appear to be frozen or
+stuck because they are waiting until a certain point in time that, however, is
+never reached due to the delayed libfaketime activity. Avoid using this
+functionality unless you are sure you really need it and know what you are
+doing.
+
+
+4i) "Limiting" libfaketime per process
+--------------------------------------
+
+faketime can be instructed to fake time related calls only for selected
+commands or to fake time for each command except for a certain subset of
+commands.
+
+The environment variables are FAKETIME_ONLY_CMDS and FAKETIME_SKIP_CMDS
+respectively.
+
+Example:
+ FAKETIME_ONLY_CMDS=javadoc faketime '2008-12-24 08:15:42' make
+will run the "make" command but the time faking will only be applied
+to javadoc processes.
+
+Multiple commands are separated by commas.
+
+Example:
+ FAKETIME_SKIP_CMDS="javadoc,ctags" faketime '2008-12-24 08:15:42' make
+will run the "make" command and apply time faking for everything "make"
+does except for javadoc and ctags processes.
+
+FAKETIME_ONLY_CMDS and FAKETIME_SKIP_CMDS are mutually exclusive, i.e.,
+you cannot set them both at the same time. faketime will terminate with
+an error message if both environment variables are set.
+
+
+4j) Spawning an external process
+--------------------------------
+
+From version 0.9 on, libfaketime can execute a shell command once after a) an
+arbitrary number of seconds has passed or b) a number of time-related system
+calls has been made by the program since it started. This has two limitations
+one needs to be aware of:
+
+* Spawning the external process happens during a time-related system call
+ of the original program. If you want the external process to be started
+ 5 seconds after program start, but this program does not make any time-
+ related system calls before run-time second 8, the start of your external
+ process will be delayed until run-time second 8.
+
+* The original program is blocked until the external process is finished,
+ because the intercepting time-related system call will not return earlier. If
+ you need to start a long-running external process, make sure it forks into the
+ background.
+
+Spawning the external process is controlled using three environment variables:
+FAKETIME_SPAWN_TARGET, FAKETIME_SPAWN_SECONDS, FAKETIME_SPAWN_NUMCALLS.
+
+Example (using bash on Linux):
+
+(... usual libfaketime setup here, setting LD_PRELOAD and FAKETIME ...)
+export FAKETIME_SPAWN_TARGET="/bin/echo 'Hello world'"
+export FAKETIME_SPAWN_SECONDS=5
+/opt/local/bin/myprogram
+
+This will run the "echo" command with the given parameter during the first
+time-related system function call that "myprogram" performs after running for 5
+seconds.
+
+
+4k) Saving timestamps to file, loading them from file
+-----------------------------------------------------
+
+faketime can save faked timestamps to a file specified by FAKETIME_SAVE_FILE
+environment variable. It can also use the file specified by FAKETIME_LOAD_FILE
+to replay timestamps from it. After consuming the whole file, libfaketime
+returns to using the rule set in FAKETIME variable, but the timestamp processes
+will start counting from will be the last timestamp in the file.
+
+The file stores each timestamp in a stream of saved_timestamp structs
+without any metadata or padding:
+
+/* Storage format for timestamps written to file. Big endian. */
+struct saved_timestamp {
+ int64_t sec;
+ uint64_t nsec;
+};
+
+faketime needs to be run using the faketime wrapper to use these files. This
+functionality has been added by Balint Reczey in v0.9.5.
+
+
+5. License
+----------
+
+libfaketime has been released under the GNU General Public License, GPL.
+Please see the included COPYING file.
+
+
+6. Contact
+-----------
+
+Bug reports, feature suggestions, success reports, and patches/pull
+requests are highly appreciated:
+
+ https://github.com/wolfcw/libfaketime
diff --git a/tests/deckard/contrib/libfaketime/README.OSX b/tests/deckard/contrib/libfaketime/README.OSX
new file mode 100644
index 0000000..7f17a63
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/README.OSX
@@ -0,0 +1,144 @@
+README file for libfaketime on macOS
+====================================
+
+Support for macOS has meanwhile matured and many command line and
+GUI applications will run stable.
+
+Developments and tests are done on High Sierra currently.
+Use libfaketime 0.9.6 or earlier on OS X (i.e., before Sierra).
+
+Version 0.9.5 and higher no longer works with OSX <= 10.6 due to
+changes in the underlying system libraries. If you need libfaketime
+on OSX <= 10.6, please use libfaketime version 0.9.
+
+
+Installing and using libfaketime on OS X is slightly different than
+on Linux. Please make sure to read the README file for general
+setup and usage, and refer to this file only about OS X specifics.
+
+
+1) Installing libfaketime on macOS
+----------------------------------
+
+If you use MacPorts, libfaketime can be installed on the command line
+as follows:
+
+ sudo port install libfaketime
+
+Or, if you use Fink, install using:
+
+ fink install libfaketime
+
+Or, if you use Homebrew, install using:
+
+ brew install libfaketime
+
+Otherwise, you have to compile and install libfaketime manually; this
+will require a working installation of Xcode and its command line tools
+on your machine.
+
+You can compile libfaketime by running the command
+
+ make
+
+in libfaketime's top-level directory.
+
+The resulting library will be named libfaketime.1.dylib ; to check
+whether it works properly, run the test suite and verify whether its
+output is correct:
+
+ cd test
+ make -f Makefile.OSX
+
+
+2) Using libfaketime from the command line on macOS
+---------------------------------------------------
+
+You will need to set three environment variables. In a Terminal.app
+or iTerm2 session, the following commands can be used:
+
+export DYLD_FORCE_FLAT_NAMESPACE=1
+export DYLD_INSERT_LIBRARIES=/path/to/libfaketime.1.dylib
+export FAKETIME="your favorite faketime-spec here"
+
+Please refer to the general README file concerning the format
+of the FAKETIME environment variable value and other environment
+variables that are related to it.
+
+The "faketime" wrapper application has been adapted to macOS;
+it offers the same limited libfaketime functionality as on Linux
+in a simple-to-use manner without the need to manually set
+those environment variables. Run "faketime" without parameters
+for help and use "man faketime" for details.
+
+
+3) Integrating libfaketime with applications
+--------------------------------------------
+
+Given the limited number of system calls libfaketime intercepts,
+it may not work too well with specific GUI applications on OS X.
+This can result in crashes after a seemingly random time, or an
+application will not or at least not always see the faked time,
+and so on.
+
+A safe way to try out whether a specific application works fine
+with libfaketime is to start it from the command line. Perform
+the steps outlined above and run the application by issuing the
+following command:
+
+/Applications/ApplicationName.app/Contents/MacOS/ApplicationName
+
+(Make sure to replace "ApplicationName" twice in that command with
+the name of your actual application.)
+
+If it works fine, you can configure the application to permanently
+run with libfaketime by editing its Info.plist file. Add the
+LSEnvironment key unless it is already there and add a dictionary
+with the three keys like this:
+
+ <key>LSEnvironment</key>
+ <dict>
+ <key>DYLD_FORCE_FLAT_NAMESPACE</key>
+ <string>1</string>
+ <key>DYLD_INSERT_LIBRARIES</key>
+ <string>/path/to/libfaketime.1.dylib</string>
+ <key>FAKETIME</key>
+ <string>value of FAKETIME here</string>
+ </dict>
+
+(If the application is installed in /Applications instead of in
+$HOME/Applications, you eventually will need root privileges. If
+the application's Info.plist is not in XML, but in binary format,
+use appropriate editing or conversion tools.)
+
+Afterwards, you will probably need to run
+
+ /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -v -f /Applications/ApplicationName.app
+
+to make sure the change to Info.plist does not go unnoticed.
+
+Please note that modifications to Info.plist will be lost when the
+application is updated, so this process needs to be repeated after
+such updates, including own new builds when using Xcode.
+
+Please feel free to report non-working applications on the Github
+libfaketime issues website. This may help us to identify further
+time-related system calls that need to be intercepted on macOS.
+
+ https://github.com/wolfcw/libfaketime/issues
+
+Important: When reporting non-working applications, please make
+sure that your issue is not related to SIP (system integrity
+protection). For example, on a SIP-enabled, default macOS installation,
+libfaketime will not work for programs like /bin/bash because
+the path /bin is SIP-protected. Copy your application to a
+non-SIP-protected path, and if libfaketime still does not work,
+feel free to report it.
+
+
+4) Notes for developers of macOS applications
+---------------------------------------------
+
+The environment variable FAKETIME can be changed at application run-time
+and always takes precedence over other user-controlled settings. It can
+be re-set to 0 (zero) to work around potential incompatibilities.
diff --git a/tests/deckard/contrib/libfaketime/README.developers b/tests/deckard/contrib/libfaketime/README.developers
new file mode 100644
index 0000000..b8df57f
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/README.developers
@@ -0,0 +1,106 @@
+This file contains information for libfaketime developers and contributors.
+
+
+GENERAL
+=======
+
+Starting with libfaketime v0.9.5, development and issue handling is
+completely done via Github:
+
+ https://github.com/wolfcw/libfaketime
+
+- Official releases are tagged.
+- Code contributions and bugfixes are merged into the "development" branch,
+ which is considered unstable and may contain code that is not yet fully
+ tested.
+- The "master" branch is updated with tested code only; it is ensured that
+ it compiles and works cleanly at least on current Linux and OS X systems.
+
+Code contributions are highly welcome, preferably via pull requests on Github.
+
+
+CODE STYLE
+==========
+
+Please try to stick to the following code formatting style guidelines:
+
+- No tabs, only spaces for indentation.
+- Avoid trailing whitespace.
+- Indentation is 2 spaces for each level.
+- Opening and closing curly brackets have to be on lines of their own.
+- Use under_score_names for function and variable names; avoid using camelCase.
+- // and /*...*/ style comments may and shall be used.
+
+Example:
+
+/* This function will do nothing */
+void do_nothing(int how_often)
+{
+ int counter;
+ for (counter = 0; counter < how_often; counter++)
+ {
+ counter = counter; // our do-nothing algorithm
+ }
+}
+
+- Use -DDEBUG and #ifdef DEBUG for development and testing. Avoid printing
+ to stdout or stderr outside "#ifdef DEBUG"; if it is necessary to inform
+ the user a run-time, prefix your output with "faketime" or make otherwise
+ sure that the user knows where the message is coming from.
+
+- If you add new functions to libfaketime.c, try placing them somewhere
+ where they fit will: Usually, functions are grouped by functionality
+ (e.g., all functions related to faking file timestamps). If that's not
+ possible, group them by contributor, or document your placement strategy
+ in the commit message.
+
+
+DEVELOPMENT, BUILDING, AND TESTING
+==================================
+
+- Don't break existing behaviour. Backward compatibility matters (unless
+ the modification fixes bugs :-)).
+
+- Add tests for new features. Extend test/timetest.c appropriately and
+ try to use the functional testing framework wherever possible.
+
+- Compiler and linker warnings are treated as errors and not acceptable.
+
+- If you cannot test the code on both Linux and OS X yourself, please
+ let us know and consider wrapping your code in #ifdef / #ifndef __APPLE__
+ statements.
+
+
+DOCUMENTATION
+=============
+
+For anything more than small bugfixes, please update the user documentation
+and credits appropriately:
+
+- The NEWS file should mention the change and your credits.
+- The README and README.OSX files should be updated whenever functionality
+ is added or modified.
+- The manpage man/faketime.1 should be updated when the wrapper application
+ is modified.
+
+For credits, please either mention your real name, your Github username, or
+your email address.
+
+In your own interest, please be verbose on user documentation and comments
+in the source code. Users will not know about new features unless they are
+documented. Other authors and maintainers will need to understand your code
+easily.
+
+
+RELEASES
+========
+
+Official new releases are created whenever a significant amount of changes
+(bugfixes or new functionality) has piled up; on average, there is one new
+official release per year. Users who need to stick to the bleeding edge
+are supposed to use the current state of the "master" branch at any time.
+
+libfaketime maintainers for several Linux distributions are informed about
+release candidates and new releases by email. Contact wolfcw on Github if
+you are interested in receiving notifications, or use Github functionality
+to get informed about updates.
diff --git a/tests/deckard/contrib/libfaketime/TODO b/tests/deckard/contrib/libfaketime/TODO
new file mode 100644
index 0000000..b8c801c
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/TODO
@@ -0,0 +1,9 @@
+Open issues / next steps for libfaketime development
+
+- add more functional tests that check more than the basic functionality
+- use the testing framework to also implement unit tests
+- fake timer_create and friends
+- work around thread local storage issue, e.g., by using pthreads
+- add autoconf/automake support to get rid of separate Makefile.OSX
+- improve pthread support
+
diff --git a/tests/deckard/contrib/libfaketime/man/Makefile b/tests/deckard/contrib/libfaketime/man/Makefile
new file mode 100644
index 0000000..807c157
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/man/Makefile
@@ -0,0 +1,14 @@
+INSTALL ?= install
+
+PREFIX ?= /usr/local
+
+all:
+
+install:
+ $(INSTALL) -Dm0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
+ gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
+
+uninstall:
+ rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
+
+.PHONY: all install uninstall
diff --git a/tests/deckard/contrib/libfaketime/man/Makefile.OSX b/tests/deckard/contrib/libfaketime/man/Makefile.OSX
new file mode 100644
index 0000000..5451acd
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/man/Makefile.OSX
@@ -0,0 +1,15 @@
+INSTALL ?= install
+
+PREFIX ?= /usr/local
+
+all:
+
+install:
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/man/man1"
+ $(INSTALL) -m0644 faketime.1 "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
+ gzip -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1"
+
+uninstall:
+ rm -f "${DESTDIR}${PREFIX}/share/man/man1/faketime.1.gz"
+
+.PHONY: all install uninstall
diff --git a/tests/deckard/contrib/libfaketime/man/faketime.1 b/tests/deckard/contrib/libfaketime/man/faketime.1
new file mode 100644
index 0000000..89c279d
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/man/faketime.1
@@ -0,0 +1,82 @@
+.TH FAKETIME "1" "November 2017" "faketime 0.9.7" wolfcw
+.SH NAME
+faketime \- manipulate the system time for a given command
+.SH SYNOPSIS
+.B faketime
+\fI[options] timestamp program [arguments...]\fR
+.SH DESCRIPTION
+.\" \fIfaketime\fR will trick the given program into seeing the specified timestamp as its starting date and time.
+.PP
+The given command will be tricked into believing that the current system time is the one specified in the timestamp. Filesystem timestamps will also be
+reported relative to this timestamp. The wall clock will continue to run from this date and time unless specified otherwise (see advanced options).
+Actually, faketime is a simple wrapper for libfaketime, which uses the LD_PRELOAD mechanism to load a small library which intercepts system calls to
+functions such as \fItime(2)\fR and \fIfstat(2)\fR. This wrapper exposes only a subset of libfaketime's functionality; please refer to the README file
+that came with faketime for more details and advanced options, or have a look at http://github.com/wolfcw/libfaketime
+.SH OPTIONS
+.TP
+\fB\-\-help\fR
+show usage information and quit.
+.TP
+\fB\-\-version\fR
+show version information and quit.
+.TP
+\fB\-m\fR
+use the multi-threading variant of libfaketime.
+.TP
+\fB\-f\fR
+use the advanced timestamp specification format.
+.TP
+\fB\--exclude-monotonic\fR
+Do not fake time when the program makes a call to clock_gettime with a CLOCK_MONOTONIC clock.
+
+.SH EXAMPLES
+.nf
+faketime 'last Friday 5 pm' /bin/date
+faketime '2008-12-24 08:15:42' /bin/date
+faketime -f '+2,5y x10,0' /bin/bash -c 'date; while true; do echo $SECONDS ; sleep 1 ; done'
+faketime -f '+2,5y x0,50' /bin/bash -c 'date; while true; do echo $SECONDS ; sleep 1 ; done'
+faketime -f '+2,5y i2,0' /bin/bash -c 'while true; do date ; sleep 1 ; done'
+In this single case all spawned processes will use the same global clock without restarting it at the start of each process.
+
+(Please note that it depends on your locale settings whether . or , has to be used for fractional offsets)
+.fi
+.SH ADVANCED TIMESTAMP FORMAT
+The simple timestamp format used by default applies the \fB/bin/date -d\fR command to parse user-friendly specifications such as 'last friday'. When using
+the faketime option \fB\-f\fR, the timestamp specified on the command line is directly passed to libfaketime, which enables a couple of additional features
+such as speeding the clock up or slowing it down for the target program. It is strongly recommended that you have a look at the libfaketime documentation. Summary:
+.TP
+Freeze clock at absolute timestamp: \fB"YYYY-MM-DD hh:mm:ss"\fR
+If you want to specify an absolute point in time, exactly this format must be used. Please note that freezing the clock is usually not what you want and may break the application. Only use if you know what you're doing!
+.TP
+Relative time offset: \fB"[+/-]123[m/h/d/y]\fR, e.g. "+60m", "+2y"
+This is the most often used format and specifies the faked time relatively to the current real time. The first character of the format string \fBmust\fR be a + or a -. The numeric value by default represents seconds, but the modifiers m, h, d, and y can be used to specify minutes, hours, days, or years, respectively. For example, "-2y" means "two years ago". Fractional time offsets can be used, e.g. "+2,5y", which means "two and a half years in the future". Please note that the fraction delimiter depends on your locale settings, so if "+2,5y" does not work, you might want to try "+2.5y".
+.TP
+Start-at timestamps: \fB"@YYYY-MM-DD hh:mm:ss"\fR
+The wall clock will start counting at the given timestamp for the program. This can be used for specifying absolute timestamps without freezing the clock.
+.SH ADVANCED USAGE
+When using relative time offsets or start-at timestamps (see ADVANCED TIMESTAMP FORMAT above and option \fB\-f\fR), the clock speed can be adjusted, i.e. time may run faster or slower for the executed program. For example, \fB"+5y x10"\fR will set the faked time 5 years into the future and make the time pass 10 times as fast (one real second equals 10 seconds measured by the program). Similarly, the flow of time can be slowed, e.g. using \fB"-7d x0,2"\fR, which will set the faked time 7 days in the past and set the clock speed to 20 percent, i.e. it takes five real world seconds for one second measured by the program. Again, depending on your locale, either "x2.0" or "x2,0" may be required regarding the delimiter. You can also make faketime to advance the reported time by a preset interval upon each time() call independently from the system's time using \fB"-7d i2,0"\fR, where
+\fB"i"\fR is followed by the increase interval in seconds.
+.PP
+Faking times for multiple programs or even system-wide can be simplified by using ~/.faketimerc files and /etc/faketimerc. Please refer to the README that came with faketime for warnings and details.
+.PP
+Faking of filesystem timestamps may be disabled by setting the NO_FAKE_STAT environment variable to a non-empty value.
+.SH AUTHOR
+Please see the README and NEWS files for contributors.
+.SH BUGS
+Due to limitations of the LD_PRELOAD mechanism, faketime will not work with suidroot and statically linked programs.
+While timestamps and time offsets will work for child processes, speeding the clock up or slowing it down might not
+work for child processes spawned by the executed program as expected; a new instance of libfaketime is used for each
+child process, which means that the libfaketime start time, which is used in speed adjustments, will also be
+re-initialized. Some programs may dynamically load system libraries, such as librt, at run-time and therefore bypass libfaketime. You may report programs that do not work with libfaketime, but only if they are available as open source.
+.SH "REPORTING BUGS"
+Please use https://github.com/wolfcw/libfaketime/issues
+.SH COPYRIGHT
+Copyright \(co 2003-2013 by the libfaketime authors.
+.PP
+There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. You may redistribute copies of faketime under the
+terms of the GNU General Public License.
+.br
+For more information about these matters, see the file named COPYING.
+.SH "SEE ALSO"
+ld.so(1), time(2), fstat(2)
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Arch/PKGBUILD-32bit.txt b/tests/deckard/contrib/libfaketime/packaging/Linux/Arch/PKGBUILD-32bit.txt
new file mode 100644
index 0000000..a87dc35
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Arch/PKGBUILD-32bit.txt
@@ -0,0 +1,25 @@
+# Maintainer: Robert Orzanna <orschiro@gmail.com>
+
+_pkgbasename=libfaketime
+pkgname=lib32-$_pkgbasename
+pkgver=0.9.5
+pkgrel=1
+pkgdesc='Report fake dates and times to programs without having to change the system-wide time.'
+arch=('x86_64')
+url='http://www.code-wizards.com/projects/libfaketime/'
+license=('GPL2')
+source=("http://www.code-wizards.com/projects/${_pkgbasename}/${_pkgbasename}-${pkgver}.tar.gz"
+ 'lib32.patch')
+md5sums=('89b5c71e6c6a93b1c6feba374ac37719'
+ '0a01f842df4c8acbd2b081be046e8d67')
+
+build() {
+ cd "${_pkgbasename}-${pkgver}"
+ patch -p1 -i ../lib32.patch
+ make
+}
+
+package() {
+ cd "${_pkgbasename}-${pkgver}"
+ make PREFIX=/usr DESTDIR="${pkgdir}" install
+} \ No newline at end of file
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/avoid-spurious-lrt.patch b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/avoid-spurious-lrt.patch
new file mode 100644
index 0000000..c2f3f3f
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/avoid-spurious-lrt.patch
@@ -0,0 +1,30 @@
+Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+
+On i386 systems, for some reason if i do not clean up this extra -lrt, i get the following error:
+
+ [...]
+make[1]: Entering directory `/home/dkg/src/faketime/faketime/src'
+cc -o libfaketime.o -c -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -std=gnu99 -Wall -Wextra -Werror -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'/usr/local'"' -DLIBDIRNAME='"'/lib/faketime'"' -DMULTI_ARCH libfaketime.c
+cc -o libfaketime.so.1 -Wl,-soname,libfaketime.so.1 -Wl,-z,relro -Wl,--version-script=libfaketime.map -lrt -shared libfaketime.o -ldl -lm -lpthread -lrt
+libfaketime.o: In function `ft_cleanup':
+/home/dkg/src/faketime/faketime/src/libfaketime.c:1277: multiple definition of `timer_gettime'
+/home/dkg/src/faketime/faketime/src/libfaketime.c:1277: multiple definition of `timer_settime'
+collect2: error: ld returned 1 exit status
+make[1]: *** [libfaketime.so.1] Error 1
+ [...]
+
+I confess i don't really understand why removing this would fix
+things, but i also don't see the need to have multiple attempts to
+link to librt.
+
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -69,7 +69,7 @@
+
+ CFLAGS += -std=gnu99 -Wall -Wextra -Werror -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"'
+ LIB_LDFLAGS += -shared
+-LDFLAGS += -Wl,--version-script=libfaketime.map -lrt
++LDFLAGS += -Wl,--version-script=libfaketime.map
+ LDADD += -ldl -lm -lpthread -lrt
+
+ SRC = libfaketime.c
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/control b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/control
new file mode 100644
index 0000000..e8291a8
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/control
@@ -0,0 +1,40 @@
+Source: faketime
+Section: utils
+Priority: extra
+Maintainer: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Build-Depends:
+ debhelper (>= 9),
+ dh-exec (>= 0.3)
+Standards-Version: 3.9.4
+Homepage: http://www.code-wizards.com/projects/libfaketime/
+Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/faketime.git
+Vcs-Git: git://anonscm.debian.org/collab-maint/faketime.git
+
+Package: faketime
+Architecture: any
+Pre-Depends: multiarch-support
+Depends: ${shlibs:Depends}, ${misc:Depends}, libfaketime (= ${binary:Version})
+Multi-Arch: foreign
+Description: report faked system time to programs
+ The Fake Time Preload Library (FTPL, a.k.a. libfaketime) intercepts
+ various system calls which programs use to retrieve the current date
+ and time. It can then report faked dates and times (as specified by
+ you, the user) to these programs. This means you can modify the
+ system time a program sees without having to change the time
+ system-wide. FTPL allows you to specify both absolute dates (e.g.,
+ 2004-01-01) and relative dates (e.g., 10 days ago).
+
+Package: libfaketime
+Architecture: any
+Pre-Depends: multiarch-support
+Multi-Arch: same
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: report faked system time to programs
+ The Fake Time Preload Library (FTPL, a.k.a. libfaketime) intercepts
+ various system calls which programs use to retrieve the current date
+ and time. It can then report faked dates and times (as specified by
+ you, the user) to these programs. This means you can modify the
+ system time a program sees without having to change the time
+ system-wide. FTPL allows you to specify both absolute dates (e.g.,
+ 2004-01-01) and relative dates (e.g., 10 days ago).
+
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/fix-infinite-recursion-on-real_clock_gettime.patch b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/fix-infinite-recursion-on-real_clock_gettime.patch
new file mode 100644
index 0000000..2fd64f5
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/fix-infinite-recursion-on-real_clock_gettime.patch
@@ -0,0 +1,29 @@
+From: Gerardo Malazdrewicz <gerardo@malazdrewicz.com.ar>
+To: 699559@bugs.debian.org
+Subject: Avoiding loop (very dirty patch)
+Date: Tue, 26 Mar 2013 01:18:05 +0100
+
+[Message part 1 (text/plain, inline)]
+
+Attached patch works for me, but it is very very dirty.
+
+Possibly side effects.
+
+Alternative seems to be to protect the call to real_clock_gettime so it is
+executed just once (to validate the parameters). Subsequent calls are not
+needed (parameters have been validated).
+
+Thanks,
+ Gerardo
+
+--- a/src/libfaketime.c
++++ b/src/libfaketime.c
+@@ -1380,7 +1380,7 @@ void __attribute__ ((constructor)) ftpl_init(void)
+ real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
+ real_clock_gettime = apple_clock_gettime;
+ #else
+- real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
++ real_clock_gettime = dlsym(RTLD_NEXT, "__clock_gettime");
+ #ifdef FAKE_TIMERS
+ real_timer_settime_22 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2");
+ real_timer_settime_233 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3");
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/libfaketime.install b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/libfaketime.install
new file mode 100755
index 0000000..0c2fb6b
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/libfaketime.install
@@ -0,0 +1,3 @@
+#!/usr/bin/dh-exec
+src/libfaketime.so.1 usr/lib/${DEB_HOST_MULTIARCH}/faketime/
+src/libfaketimeMT.so.1 usr/lib/${DEB_HOST_MULTIARCH}/faketime/
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/rules b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/rules
new file mode 100755
index 0000000..cf3813a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Debian/rules
@@ -0,0 +1,17 @@
+#!/usr/bin/make -f
+
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# Date: Tue, 26 Aug 2008 14:24:50 -0400
+
+export DEB_CFLAGS_MAINT_APPEND=-DMULTI_ARCH
+
+# make sure dh_makeshlibs does not modify post{inst,rm} scripts:
+# (avoids lintian's postinst-has-useless-call-to-ldconfig)
+override_dh_makeshlibs:
+ dh_makeshlibs --noscripts
+
+override_dh_installchangelogs:
+ dh_installchangelogs NEWS
+
+%:
+ PREFIX=/usr dh $@
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime-fix-infinite-recursion-on-real_clock_gettime.patch b/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime-fix-infinite-recursion-on-real_clock_gettime.patch
new file mode 100644
index 0000000..9d81e5e
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime-fix-infinite-recursion-on-real_clock_gettime.patch
@@ -0,0 +1,13 @@
+diff --git a/src/libfaketime.c b/src/libfaketime.c
+index 3ec372b..f70283b 100644
+--- a/src/libfaketime.c
++++ b/src/libfaketime.c
+@@ -1380,7 +1380,7 @@ void __attribute__ ((constructor)) ftpl_init(void)
+ real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
+ real_clock_gettime = apple_clock_gettime;
+ #else
+- real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
++ real_clock_gettime = dlsym(RTLD_NEXT, "__clock_gettime");
+ #ifdef FAKE_TIMERS
+ real_timer_settime_22 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2");
+ real_timer_settime_233 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3");
diff --git a/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime.spec.txt b/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime.spec.txt
new file mode 100644
index 0000000..48f3305
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/Linux/Redhat/libfaketime.spec.txt
@@ -0,0 +1,55 @@
+Summary: Manipulate system time per process for testing purposes
+Name: libfaketime
+Version: 0.9.5
+Release: 4%{?dist}
+License: GPLv2+
+Url: http://www.code-wizards.com/projects/%{name}/
+Source: http://www.code-wizards.com/projects/%{name}/%{name}-%{version}.tar.gz
+Group: System Environment/Libraries
+Patch1: libfaketime-0.9.5-fix-infinite-recursion-on-real_clock_gettime.patch
+
+%description
+libfaketime intercepts various system calls which programs use to
+retrieve the current date and time. It can then report faked dates and
+times (as specified by you, the user) to these programs. This means you
+can modify the system time a program sees without having to change the
+time system- wide.
+
+%prep
+%setup -q
+%patch1 -p1
+# work around from upstream for autodetecting glibc version bug on i686
+sed -i -e 's/__asm__(".symver timer_gettime_22/\/\/__asm__(".symver timer_gettime_22/' src/libfaketime.c
+sed -i -e 's/__asm__(".symver timer_settime_22/\/\/__asm__(".symver timer_settime_22/' src/libfaketime.c
+
+
+%build
+cd src ; CFLAGS="$RPM_OPT_FLAGS -Wno-strict-aliasing" make %{?_smp_mflags} \
+ PREFIX="%{_prefix}" LIBDIRNAME="/%{_lib}/faketime" all
+
+%check
+make %{?_smp_mflags} -C test all
+
+%install
+make PREFIX="%{_prefix}" DESTDIR=%{buildroot} LIBDIRNAME="/%{_lib}/faketime" install
+rm -r %{buildroot}/%{_docdir}/faketime
+
+%files
+%{_bindir}/faketime
+%{_libdir}/faketime/libfaketime*so.*
+%doc README COPYING NEWS README README.developers
+%{_mandir}/man1/*
+
+%changelog
+* Tue Oct 15 2013 Paul Wouters <pwouters@redhat.com> - 0.9.5-4
+- Infinite recursion patch is still needed, make test causes
+ segfaults otherwise.
+
+* Mon Oct 14 2013 Paul Wouters <pwouters@redhat.com> - 0.9.5-3
+- Work around from upstream for autodetecting glibc version bug on i686
+
+* Mon Oct 14 2013 Paul Wouters <pwouters@redhat.com> - 0.9.5-2
+- Remove use of ifarch for _lib macro for multilib
+
+* Sun Oct 13 2013 Paul Wouters <pwouters@redhat.com> - 0.9.5-1
+- Initial package
diff --git a/tests/deckard/contrib/libfaketime/packaging/OSX/Fink/libfaketime.info b/tests/deckard/contrib/libfaketime/packaging/OSX/Fink/libfaketime.info
new file mode 100644
index 0000000..9f1b3ba
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/OSX/Fink/libfaketime.info
@@ -0,0 +1,53 @@
+Package: libfaketime
+Version: 0.9.7
+Revision: 1
+
+Source: http://www.code-wizards.com/projects/%n/%n-%v.tar.gz
+Source-MD5: 8617e2c6caf0977b3ce9a271f867302c
+
+Maintainer: Wolfgang Hommel <wolf@fink.code-wizards.com>
+HomePage: https://github.com/wolfcw/libfaketime
+License: GPL
+
+Description: Modify system time for single applications
+
+DescDetail: <<
+libfaketime is a library that is dynamically linked to applications
+or system commands at run-time by using the DYLD_INSERT_LIBRARIES
+mechanism. It then intercepts various system calls, which programs
+use to retrieve the current date and time. libfaketime can then
+report faked dates and times to these programs. This means you can
+modify the system time a program uses without having to change the
+date and time system-wide.
+<<
+
+DescUsage: <<
+libfaketime includes a simple wrapper called faketime. Run the
+command faketime without any parameters for usage information.
+For information on how to use libfaketime without the wrapper
+and access its full raw functionality, please see
+%p/share/doc/libfaketime/README*
+<<
+
+BuildDepends: fink (>= 0.28)
+Distribution: 10.7, 10.8, 10.9, 10.10, 10.11, 10.12
+
+CompileScript: <<
+#! /bin/sh -ev
+make -f Makefile.OSX -C src PREFIX=%{p}
+<<
+
+InfoTest: <<
+ TestScript: make -f Makefile.OSX test || exit 2
+<<
+
+InstallScript: <<
+#! /bin/sh -ev
+make -f Makefile.OSX -C src install PREFIX=%{i}
+<<
+
+DocFiles: COPYING README README.OSX
+
+Shlibs: <<
+ !%p/lib/faketime/%N.1.dylib
+<<
diff --git a/tests/deckard/contrib/libfaketime/packaging/OSX/Homebrew/libfaketime.rb b/tests/deckard/contrib/libfaketime/packaging/OSX/Homebrew/libfaketime.rb
new file mode 100644
index 0000000..8d92b76
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/OSX/Homebrew/libfaketime.rb
@@ -0,0 +1,21 @@
+require 'formula'
+
+class Libfaketime < Formula
+ homepage 'https://github.com/wolfcw/libfaketime'
+ url 'https://github.com/wolfcw/libfaketime/archive/v0.9.7.tar.gz'
+ sha1 'eb1cbacf548aefa36214bea1345f35b8763027a1'
+
+ depends_on :macos => :sierra
+
+ fails_with :llvm do
+ build 2336
+ cause 'No thread local storage support'
+ end
+
+ def install
+ system "make", "-C", "src", "-f", "Makefile.OSX", "PREFIX=#{prefix}"
+ bin.install 'src/faketime'
+ (lib/'faketime').install 'src/libfaketime.1.dylib'
+ man1.install 'man/faketime.1'
+ end
+end
diff --git a/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/Portfile b/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/Portfile
new file mode 100644
index 0000000..d4104ad
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/Portfile
@@ -0,0 +1,45 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id: Portfile 112093 2013-10-11 19:57:13Z ryandesign@macports.org $
+
+PortSystem 1.0
+PortGroup github 1.0
+
+github.setup wolfcw libfaketime 0.9.7 v
+
+checksums rmd160 8874d43bb212976d929c3007db0cf978311b3596 \
+ sha256 4d65f368b2d53ee2f93a25d5e9541ce27357f2b95e5e5afff210e0805042811e
+
+categories sysutils
+platforms darwin
+maintainers code-wizards.com:wolf openmaintainer
+license GPL-2
+
+description libfaketime modifies the system time for a single application
+
+long_description libfaketime intercepts various system calls that applications use to \
+ retrieve the current date and time. It can then report user-specified \
+ faked dates and times to these applications. This allows us to modify \
+ the system time an application sees without having to change the time \
+ system-wide. The faketime wrapper can be used from command line. \
+ Check the documentation on how to integrate into installed applications.
+
+patchfiles patch-test-Makefile.OSX.diff
+
+use_configure no
+
+variant universal {}
+
+compiler.blacklist *cc* *dragonegg*
+
+build.args -f Makefile.OSX
+build.env CC="${configure.cc}" \
+ CFLAGS="[get_canonical_archflags cc]" \
+ LDFLAGS="[get_canonical_archflags ld]" \
+ PREFIX=${prefix}
+
+test.run yes
+test.args ${build.args}
+eval test.env ${build.env}
+
+destroot.args ${build.args}
+eval destroot.env ${build.env}
diff --git a/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/patch-test-Makefile.OSX.diff b/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/patch-test-Makefile.OSX.diff
new file mode 100644
index 0000000..f60968a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/OSX/MacPorts/patch-test-Makefile.OSX.diff
@@ -0,0 +1,12 @@
+--- test/Makefile.OSX.orig 2013-10-11 09:42:38.000000000 -0500
++++ test/Makefile.OSX 2013-10-11 14:46:11.000000000 -0500
+@@ -1,7 +1,6 @@
+-CC = gcc
++CC ?= clang
+
+-CFLAGS = -std=gnu99 -Wall -DFAKE_STAT
+-LDFLAGS =
++CFLAGS += -std=gnu99 -Wall -DFAKE_STAT
+
+ SRC = timetest.c
+ OBJ = ${SRC:.c=.o}
diff --git a/tests/deckard/contrib/libfaketime/packaging/OSX/README b/tests/deckard/contrib/libfaketime/packaging/OSX/README
new file mode 100644
index 0000000..03b43fa
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/OSX/README
@@ -0,0 +1,65 @@
+# Packaging for OS X
+
+Several software tools assist with the installation of open source software
+on OS X. The authors of libfaketime maintain the libfaketime build spec files
+for MacPorts, Homebrew, and Fink.
+
+
+## MacPorts
+
+Installing libfaketime via MacPorts is based on the provided Portfile, which
+has been included in the official MacPorts distribution since October, 2013.
+Users therefore can use "sudo port install libfaketime" as installation
+command.
+
+Some libfaketime Portfile caveats:
+
+- Github-based source file distribution
+- Non-clang-compilers need to be blacklisted
+- MacPorts folks have requested to avoid a platform-specific Makefile.OSX in
+ the future
+
+Portfile submission is documented in https://www.macports.org/guide/#project.contributing
+and handled via a ticketing system:
+
+- https://trac.macports.org/ticket/40662
+- https://trac.macports.org/ticket/40748
+
+
+## Homebrew
+
+The libfaketime 'formula' for Homebrew is available since November, 2013.
+Homebrew users can use 'brew install libfaketime' as installation command.
+
+Some libfaketime formula caveats:
+
+- "depends_on :macos => :lion" must be set for libfaketime >=0.9.5
+- :llvm builds <= 2336 must be blacklisted because libfaketime =0.9.5
+ requires a compiler with thread local storage support.
+
+Formula submission is handled via pull request on Github following the
+"one formula per commit, one commit per formula" rule, which necessitates
+squashing commits and forced pushes when applying fixes. Style issues
+complementary to the documentation have been discussed in
+
+ https://github.com/mxcl/homebrew/pull/23245
+
+
+## Fink
+
+A libfaketime.info file is included in the Fink 10.7 tree since October,
+2013, and installed using
+
+ fink install libfaketime
+
+Some libfaketime fink info file caveats:
+
+- The dynamic library must be declared as private Shlib; this also necessitates
+ BuildDepends: fink (>= 0.28)
+- "Distribution: 10.7, 10.8, 10.9" is required because libfaketime >=0.9.5 does
+ not work on OS X 10.6 or before anymore.
+- When compiling, PREFIX=%{p} needs to be used because this path is hardcoded
+ into the wrapper. However, "make install" needs to deploy into PREFIX=%{i} to
+ make packaging work.
+
+Submission is via https://sourceforge.net/p/fink/package-submissions/
diff --git a/tests/deckard/contrib/libfaketime/packaging/README b/tests/deckard/contrib/libfaketime/packaging/README
new file mode 100644
index 0000000..7dc6152
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/packaging/README
@@ -0,0 +1,14 @@
+# libfaketime packaging
+
+Not everyone feels comfortable with installing tools and libraries manually
+by downloading and building them from source. Luckily enough, voluntary
+maintainers prepare new libfaketime releases for various platforms and make
+them available as binary packages or otherwise automatically installable
+software.
+
+In this directory, we collect build specification files for the platforms
+that we are aware of being actively supported. They help us to analyze
+build issues, create awareness for platform-specific patches that had to
+be applied and might be merged with our code, and provide the contact
+information for future "early release warnings".
+
diff --git a/tests/deckard/contrib/libfaketime/src/Makefile b/tests/deckard/contrib/libfaketime/src/Makefile
new file mode 100644
index 0000000..e2f047a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/Makefile
@@ -0,0 +1,118 @@
+#
+# Notes:
+#
+# * Compilation Defines:
+#
+# FAKE_STAT
+# - Enables time faking also for files' timestamps.
+#
+# NO_ATFILE
+# - Disables support for the fstatat() group of functions
+#
+# PTHREAD_SINGLETHREADED_TIME
+# - Define this if you want to single-thread time() ... there ARE
+# possible caching side-effects in a multithreaded environment
+# without this, but the performance impact may require you to
+# try it unsynchronized.
+#
+# FAKE_INTERNAL_CALLS
+# - Also intercept libc internal __functions, e.g. not just time(),
+# but also __time(). Enhances compatibility with applications
+# that make use of low-level system calls, such as Java Virtual
+# Machines.
+#
+# FAKE_SLEEP
+# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll()
+#
+# FAKE_TIMERS
+# - Also intercept timer_settime() and timer_gettime()
+#
+# FAKE_PTHREAD
+# - Intercept pthread_cond_timedwait
+#
+# MULTI_ARCH
+# - If MULTI_ARCH is set, the faketime wrapper program will put a literal
+# $LIB into the LD_PRELOAD environment variable it creates, which makes
+# ld automatically choose the correct library version to use for the
+# target binary. Use for Linux platforms with Multi-Arch support only!
+#
+# * Compilation addition: second libMT target added for building the pthread-
+# enabled library as a separate library
+#
+# * Compilation switch change: previous versions compiled using '-nostartfiles'
+# This is no longer the case since there is a 'startup' constructor for the library
+# which is used to activate the start-at times when specified. This also initializes
+# the dynamic disabling of the FAKE_STAT calls.
+#
+# By default, libfaketime will be compiled for your system's default architecture.
+# To build 32-bit libraries and binaries, add -m32 to CFLAGS and LDFLAGS.
+#
+# Change PREFIX to where you want libfaketime (libraries and wrapper binary) installed.
+# LIBDIRNAME is relative to PREFIX. The default is to install into $PREFIX/lib/faketime,
+# but you can set LIBDIRNAME to, e.g., /lib64 if you want to install it elsewhere.
+# LIBDIRNAME has been introduced to support MultiLib systems. Please do not change the
+# default value on MultiArch systems.
+#
+# For testing in the current directory without installation, try make PREFIX= LIBDIRNAME='.'
+
+CC ?= gcc
+INSTALL ?= install
+
+PREFIX ?= /usr/local
+LIBDIRNAME ?= /lib/faketime
+PLATFORM ?=$(shell uname)
+
+CFLAGS += -std=gnu99 -Wall -Wextra -Werror -Wno-nonnull-compare -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"'
+ifeq ($(PLATFORM),SunOS)
+CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
+endif
+
+LIB_LDFLAGS += -shared
+
+LDFLAGS += -lpthread
+ifneq ($(PLATFORM),SunOS)
+LDFLAGS += -Wl,--version-script=libfaketime.map
+endif
+
+LDADD += -ldl -lm -lrt
+BIN_LDFLAGS += -lrt
+
+SRC = libfaketime.c
+LIBS_OBJ = libfaketime.o libfaketimeMT.o
+BINS = faketime
+
+SONAME = 1
+LIBS = libfaketime.so.${SONAME} libfaketimeMT.so.${SONAME}
+
+all: ${LIBS} ${BINS}
+
+libfaketimeMT.o: EXTRA_FLAGS := -DPTHREAD_SINGLETHREADED_TIME
+
+${LIBS_OBJ}: libfaketime.c
+ ${CC} -o $@ -c ${CFLAGS} ${CPPFLAGS} ${EXTRA_FLAGS} $<
+
+%.so.${SONAME}: %.o libfaketime.map
+ ${CC} -o $@ -Wl,-soname,$@ ${LDFLAGS} ${LIB_LDFLAGS} $< ${LDADD}
+
+${BINS}: faketime.c
+ ${CC} -o $@ ${CFLAGS} ${CPPFLAGS} ${EXTRA_FLAGS} $< ${LDFLAGS} ${BIN_LDFLAGS}
+
+clean:
+ @rm -f ${LIBS_OBJ} ${LIBS} ${BINS}
+
+distclean: clean
+ @echo
+
+install: ${LIBS} ${BINS}
+ @echo
+ @echo "Copying the faketime libraries to ${DESTDIR}${PREFIX}${LIBDIRNAME} and the faketime wrapper script to ${DESTDIR}${PREFIX}/bin ..."
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}${LIBDIRNAME}/"
+ $(INSTALL) -m0644 ${LIBS} "${DESTDIR}${PREFIX}${LIBDIRNAME}/"
+ $(INSTALL) -Dm0755 faketime "${DESTDIR}${PREFIX}/bin/faketime"
+
+uninstall:
+ for f in ${LIBS}; do rm -f "${DESTDIR}${PREFIX}${LIBDIRNAME}/$$f"; done
+ rmdir "${DESTDIR}${PREFIX}${LIBDIRNAME}"
+ rm -f "${DESTDIR}${PREFIX}/bin/faketime"
+
+.PHONY: all clean distclean install uninstall
diff --git a/tests/deckard/contrib/libfaketime/src/Makefile.OSX b/tests/deckard/contrib/libfaketime/src/Makefile.OSX
new file mode 100644
index 0000000..683ad04
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/Makefile.OSX
@@ -0,0 +1,75 @@
+#
+# Notes:
+#
+# * Compilation Defines:
+#
+# FAKE_STAT
+# - Enables time faking also for files' timestamps.
+#
+# NO_ATFILE
+# - Disables support for the fstatat() group of functions
+#
+# PTHREAD
+# - Define this to enable multithreading support.
+#
+# PTHREAD_SINGLETHREADED_TIME
+# - Define this if you want to single-thread time() ... there ARE
+# possible caching side-effects in a multithreaded environment
+# without this, but the performance impact may require you to
+# try it unsynchronized.
+#
+# FAKE_SLEEP
+# - Also intercept sleep(), nanosleep(), usleep(), alarm(), [p]poll()
+#
+# * Compilation addition: second libMT target added for building the pthread-
+# enabled library as a separate library
+#
+# * Compilation switch change: previous versions compiled using '-nostartfiles'
+# This is no longer the case since there is a 'startup' constructor for the library
+# which is used to activate the start-at times when specified. This also initializes
+# the dynamic disabling of the FAKE_STAT calls.
+#
+# By default, libfaketime will be compiled for your system's default architecture.
+# To build for a different architecture, add -arch flags to CFLAGS and LDFLAGS.
+#
+# default to clang to support thread local variables
+CC ?= clang
+INSTALL ?= install
+
+PREFIX ?= /usr/local
+
+CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"'
+LIB_LDFLAGS += -dynamiclib -current_version 0.9.7 -compatibility_version 0.7
+
+SONAME = 1
+LIBS = libfaketime.${SONAME}.dylib
+BINS = faketime
+
+all: ${LIBS} ${BINS}
+
+libfaketime.${SONAME}.dylib: libfaketime.c
+ ${CC} -o $@ ${CFLAGS} ${LDFLAGS} ${LIB_LDFLAGS} -install_name ${PREFIX}/lib/faketime/$@ $<
+
+faketime: faketime.c
+ ${CC} -o $@ ${CFLAGS} ${LDFLAGS} $<
+
+clean:
+ @rm -f ${OBJ} ${LIBS} ${BINS}
+
+distclean: clean
+ @echo
+
+install: ${LIBS} ${BINS}
+ @echo
+ @echo "Copying the faketime libraries to ${DESTDIR}${PREFIX}/lib/faketime and the faketime wrapper script to ${DESTDIR}${PREFIX}/bin ..."
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/lib/faketime/"
+ $(INSTALL) -m0644 ${LIBS} "${DESTDIR}${PREFIX}/lib/faketime/"
+ $(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/bin"
+ $(INSTALL) -m0755 faketime "${DESTDIR}${PREFIX}/bin/faketime"
+
+uninstall:
+ for f in ${LIBS}; do rm -f "${DESTDIR}${PREFIX}/lib/faketime/$$f"; done
+ rmdir "${DESTDIR}${PREFIX}/lib/faketime"
+ rm -f "${DESTDIR}${PREFIX}/bin/faketime"
+
+.PHONY: all clean distclean install uninstall
diff --git a/tests/deckard/contrib/libfaketime/src/faketime.c b/tests/deckard/contrib/libfaketime/src/faketime.c
new file mode 100644
index 0000000..037d749
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/faketime.c
@@ -0,0 +1,385 @@
+/*
+ * libfaketime wrapper command
+ *
+ * This file is part of libfaketime, version 0.9.7
+ *
+ * libfaketime is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * libfaketime is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License v2 along
+ * with the libfaketime; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Converted from shell script by Balint Reczey with the following credits
+ * and comments:
+ *
+ * Thanks to Daniel Kahn Gillmor for improvement suggestions.
+
+ * This wrapper exposes only a small subset of the libfaketime functionality.
+ * Please see libfaketime's README file and man page for more details.
+
+ * Acknowledgment: Parts of the functionality of this wrapper have been
+ * inspired by Matthias Urlichs' datefudge 1.14.
+
+ * Compile time configuration: Path where the libfaketime libraries can be found
+ * on Linux/UNIX
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <semaphore.h>
+
+#include "faketime_common.h"
+
+const char version[] = "0.9.7";
+
+#ifdef __APPLE__
+static const char *date_cmd = "gdate";
+#else
+static const char *date_cmd = "date";
+#endif
+
+#define PATH_BUFSIZE 4096
+
+/* semaphore and shared memory names */
+char sem_name[PATH_BUFSIZE] = {0}, shm_name[PATH_BUFSIZE] = {0};
+
+void usage(const char *name)
+{
+ printf("\n"
+ "Usage: %s [switches] <timestamp> <program with arguments>\n"
+ "\n"
+ "This will run the specified 'program' with the given 'arguments'.\n"
+ "The program will be tricked into seeing the given 'timestamp' as its starting date and time.\n"
+ "The clock will continue to run from this timestamp. Please see the manpage (man faketime)\n"
+ "for advanced options, such as stopping the wall clock and make it run faster or slower.\n"
+ "\n"
+ "The optional switches are:\n"
+ " -m : Use the multi-threaded version of libfaketime\n"
+ " -f : Use the advanced timestamp specification format (see manpage)\n"
+ " --exclude-monotonic : Prevent monotonic clock from drifting (not the raw monotonic one)\n"
+ "\n"
+ "Examples:\n"
+ "%s 'last friday 5 pm' /bin/date\n"
+ "%s '2008-12-24 08:15:42' /bin/date\n"
+ "%s -f '+2,5y x10,0' /bin/bash -c 'date; while true; do echo $SECONDS ; sleep 1 ; done'\n"
+ "%s -f '+2,5y x0,50' /bin/bash -c 'date; while true; do echo $SECONDS ; sleep 1 ; done'\n"
+ "%s -f '+2,5y i2,0' /bin/bash -c 'date; while true; do date; sleep 1 ; done'\n"
+ "In this single case all spawned processes will use the same global clock\n"
+ "without restarting it at the start of each process.\n\n"
+ "(Please note that it depends on your locale settings whether . or , has to be used for fractions)\n"
+ "\n", name, name, name, name, name, name);
+}
+
+/** Clean up shared objects */
+static void cleanup_shobjs()
+{
+ if (-1 == sem_unlink(sem_name))
+ {
+ perror("sem_unlink");
+ }
+ if (-1 == shm_unlink(shm_name))
+ {
+ perror("shm_unlink");
+ }
+}
+
+int main (int argc, char **argv)
+{
+ pid_t child_pid;
+ int curr_opt = 1;
+ bool use_mt = false, use_direct = false;
+ long offset;
+
+ while(curr_opt < argc)
+ {
+ if (0 == strcmp(argv[curr_opt], "-m"))
+ {
+ use_mt = true;
+ curr_opt++;
+ continue;
+ }
+ else if (0 == strcmp(argv[curr_opt], "-f"))
+ {
+ use_direct = true;
+ curr_opt++;
+ continue;
+ }
+ else if (0 == strcmp(argv[curr_opt], "--exclude-monotonic"))
+ {
+ setenv("DONT_FAKE_MONOTONIC", "1", true);
+ curr_opt++;
+ continue;
+ }
+ else if ((0 == strcmp(argv[curr_opt], "-v")) ||
+ (0 == strcmp(argv[curr_opt], "--version")))
+ {
+ printf("\n%s: Version %s\n"
+ "For usage information please use '%s --help'.\n",
+ argv[0], version, argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ else if ((0 == strcmp(argv[curr_opt], "-h")) ||
+ (0 == strcmp(argv[curr_opt], "-?")) ||
+ (0 == strcmp(argv[curr_opt], "--help")))
+ {
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ else
+ {
+ /* we parsed all options */
+ break;
+ }
+ }
+
+ /* we need at least a timestamp string and a command to run */
+ if (argc - curr_opt < 2)
+ {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (!use_direct)
+ {
+ // TODO get seconds
+ int pfds[2];
+ (void) (pipe(pfds) + 1);
+ int ret = EXIT_SUCCESS;
+
+ if (0 == (child_pid = fork()))
+ {
+ close(1); /* close normal stdout */
+ (void) (dup(pfds[1]) + 1); /* make stdout same as pfds[1] */
+ close(pfds[0]); /* we don't need this */
+ if (EXIT_SUCCESS != execlp(date_cmd, date_cmd, "-d", argv[curr_opt], "+%s",(char *) NULL))
+ {
+ perror("Running (g)date failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ char buf[256] = {0}; /* e will have way less than 256 digits */
+ close(pfds[1]); /* we won't write to this */
+ (void) (read(pfds[0], buf, 256) + 1);
+ waitpid(child_pid, &ret, 0);
+ if (ret != EXIT_SUCCESS)
+ {
+ printf("Error: Timestamp to fake not recognized, please re-try with a "
+ "different timestamp.\n");
+ exit(EXIT_FAILURE);
+ }
+ offset = atol(buf) - time(NULL);
+ ret = snprintf(buf, sizeof(buf), "%s%ld", (offset >= 0)?"+":"", offset);
+ setenv("FAKETIME", buf, true);
+ close(pfds[0]); /* finished reading */
+ }
+ }
+ else
+ {
+ /* simply pass format string along */
+ setenv("FAKETIME", argv[curr_opt], true);
+ }
+ int keepalive_fds[2];
+ (void) (pipe(keepalive_fds) + 1);
+
+ /* we just consumed the timestamp option */
+ curr_opt++;
+
+ {
+ /* create semaphores and shared memory */
+ int shm_fd;
+ sem_t *sem;
+ struct ft_shared_s *ft_shared;
+ char shared_objs[PATH_BUFSIZE * 2 + 1];
+
+ /*
+ * Casting of getpid() return value to long needed to make GCC on SmartOS
+ * happy, since getpid's return value's type on SmartOS is long. Since
+ * getpid's return value's type is int on most other systems, and that
+ * sizeof(long) always >= sizeof(int), this works on all platforms without
+ * the need for crazy #ifdefs.
+ */
+ snprintf(sem_name, PATH_BUFSIZE -1 ,"/faketime_sem_%ld", (long)getpid());
+ snprintf(shm_name, PATH_BUFSIZE -1 ,"/faketime_shm_%ld", (long)getpid());
+
+ if (SEM_FAILED == (sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IWUSR|S_IRUSR, 1)))
+ {
+ perror("sem_open");
+ exit(EXIT_FAILURE);
+ }
+
+ /* create shm */
+ if (-1 == (shm_fd = shm_open(shm_name, O_CREAT|O_EXCL|O_RDWR, S_IWUSR|S_IRUSR)))
+ {
+ perror("shm_open");
+ if (-1 == sem_unlink(argv[2]))
+ {
+ perror("sem_unlink");
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ /* set shm size */
+ if (-1 == ftruncate(shm_fd, sizeof(uint64_t)))
+ {
+ perror("ftruncate");
+ cleanup_shobjs();
+ exit(EXIT_FAILURE);
+ }
+
+ /* map shm */
+ if (MAP_FAILED == (ft_shared = mmap(NULL, sizeof(struct ft_shared_s), PROT_READ|PROT_WRITE,
+ MAP_SHARED, shm_fd, 0)))
+ {
+ perror("mmap");
+ cleanup_shobjs();
+ exit(EXIT_FAILURE);
+ }
+
+ if (sem_wait(sem) == -1)
+ {
+ perror("sem_wait");
+ cleanup_shobjs();
+ exit(EXIT_FAILURE);
+ }
+
+ /* init elapsed time ticks to zero */
+ ft_shared->ticks = 0;
+ ft_shared->file_idx = 0;
+ ft_shared->start_time.real.tv_sec = 0;
+ ft_shared->start_time.real.tv_nsec = -1;
+ ft_shared->start_time.mon.tv_sec = 0;
+ ft_shared->start_time.mon.tv_nsec = -1;
+ ft_shared->start_time.mon_raw.tv_sec = 0;
+ ft_shared->start_time.mon_raw.tv_nsec = -1;
+
+ if (-1 == munmap(ft_shared, (sizeof(struct ft_shared_s))))
+ {
+ perror("munmap");
+ cleanup_shobjs();
+ exit(EXIT_FAILURE);
+ }
+
+ if (sem_post(sem) == -1)
+ {
+ perror("semop");
+ cleanup_shobjs();
+ exit(EXIT_FAILURE);
+ }
+
+ snprintf(shared_objs, sizeof(shared_objs), "%s %s", sem_name, shm_name);
+ setenv("FAKETIME_SHARED", shared_objs, true);
+ sem_close(sem);
+ }
+
+ {
+ char *ftpl_path;
+#ifdef __APPLE__
+ ftpl_path = PREFIX "/libfaketime.1.dylib";
+ FILE *check;
+ check = fopen(ftpl_path, "ro");
+ if (check == NULL)
+ {
+ ftpl_path = PREFIX "/lib/faketime/libfaketime.1.dylib";
+ }
+ else
+ {
+ fclose(check);
+ }
+ setenv("DYLD_INSERT_LIBRARIES", ftpl_path, true);
+ setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", true);
+#else
+ {
+ char *ld_preload_new, *ld_preload = getenv("LD_PRELOAD");
+ size_t len;
+ if (use_mt)
+ {
+ /*
+ * on MultiArch platforms, such as Debian, we put a literal $LIB into LD_PRELOAD.
+ */
+#ifndef MULTI_ARCH
+ ftpl_path = PREFIX LIBDIRNAME "/libfaketimeMT.so.1";
+#else
+ ftpl_path = PREFIX "/$LIB/faketime/libfaketimeMT.so.1";
+#endif
+ }
+ else
+ {
+#ifndef MULTI_ARCH
+ ftpl_path = PREFIX LIBDIRNAME "/libfaketime.so.1";
+#else
+ ftpl_path = PREFIX "/$LIB/faketime/libfaketime.so.1";
+#endif
+ }
+ len = ((ld_preload)?strlen(ld_preload) + 1: 0) + 1 + strlen(ftpl_path);
+ ld_preload_new = malloc(len);
+ snprintf(ld_preload_new, len ,"%s%s%s", (ld_preload)?ld_preload:"",
+ (ld_preload)?":":"", ftpl_path);
+ setenv("LD_PRELOAD", ld_preload_new, true);
+ free(ld_preload_new);
+ }
+#endif
+ }
+
+ /* run command and clean up shared objects */
+ if (0 == (child_pid = fork()))
+ {
+ close(keepalive_fds[0]); /* only parent needs to read this */
+ if (EXIT_SUCCESS != execvp(argv[curr_opt], &argv[curr_opt]))
+ {
+ perror("Running specified command failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ int ret;
+ char buf;
+ close(keepalive_fds[1]); /* only children need keep this open */
+ waitpid(child_pid, &ret, 0);
+ (void) (read(keepalive_fds[0], &buf, 1) + 1); /* reads 0B when all children exit */
+ cleanup_shobjs();
+ if (WIFSIGNALED(ret))
+ {
+ fprintf(stderr, "Caught %s\n", strsignal(WTERMSIG(ret)));
+ exit(EXIT_FAILURE);
+ }
+ exit(WEXITSTATUS(ret));
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 2
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=2 expandtab:
+ * :indentSize=2:tabSize=2:noTabs=true:
+ */
+
+/* eof */
diff --git a/tests/deckard/contrib/libfaketime/src/faketime_common.h b/tests/deckard/contrib/libfaketime/src/faketime_common.h
new file mode 100644
index 0000000..9fda6a7
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/faketime_common.h
@@ -0,0 +1,61 @@
+/*
+ * Faketime's common definitions
+ *
+ * Copyright 2013 Balint Reczey <balint@balintreczey.hu>
+ *
+ * This file is part of the libfaketime.
+ *
+ * libfaketime is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License v2 as published by the Free
+ * Software Foundation.
+ *
+ * libfaketime is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License v2 along
+ * with libfaketime; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef FAKETIME_COMMON_H
+#define FAKETIME_COMMON_H
+
+#include <stdint.h>
+
+struct system_time_s
+{
+ /* System time according to CLOCK_REALTIME */
+ struct timespec real;
+ /* System time according to CLOCK_MONOTONIC */
+ struct timespec mon;
+ /* System time according to CLOCK_MONOTONIC_RAW */
+ struct timespec mon_raw;
+#ifdef CLOCK_BOOTTIME
+ /* System time according to CLOCK_BOOTTIME */
+ struct timespec boot;
+#endif
+};
+
+/* Data shared among faketime-spawned processes */
+struct ft_shared_s
+{
+ /*
+ * When advancing time linearly with each time(), etc. call, the calls are
+ * counted here */
+ uint64_t ticks;
+ /* Index of timstamp to be loaded from file */
+ uint64_t file_idx;
+ /* System time Faketime started at */
+ struct system_time_s start_time;
+};
+
+/* These are all needed in order to properly build on OSX */
+#ifdef __APPLE__
+#include <mach/clock.h>
+#include <mach/mach_host.h>
+#include <mach/mach_port.h>
+#endif
+
+#endif
diff --git a/tests/deckard/contrib/libfaketime/src/libfaketime.c b/tests/deckard/contrib/libfaketime/src/libfaketime.c
new file mode 100644
index 0000000..5823701
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/libfaketime.c
@@ -0,0 +1,2646 @@
+/*
+ * This file is part of libfaketime, version 0.9.7
+ *
+ * libfaketime is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * libfaketime is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License v2 along
+ * with the libfaketime; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * =======================================================================
+ * Global settings, includes, and macros === HEAD
+ * =======================================================================
+ */
+
+#define _GNU_SOURCE /* required to get RTLD_NEXT defined */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <time.h>
+#include <math.h>
+#include <errno.h>
+#include <string.h>
+#include <semaphore.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <limits.h>
+
+#include "uthash.h"
+
+#include "time_ops.h"
+#include "faketime_common.h"
+
+
+/* pthread-handling contributed by David North, TDI in version 0.7 */
+#if defined PTHREAD_SINGLETHREADED_TIME || defined FAKE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <sys/timeb.h>
+#include <dlfcn.h>
+
+#define BUFFERLEN 256
+
+#ifndef __APPLE__
+extern char *__progname;
+#ifdef __sun
+#include "sunos_endian.h"
+#else
+#include <endian.h>
+#endif
+#else
+/* endianness related macros */
+#ifndef OSSwapHostToBigInt64
+#define OSSwapHostToBigInt64(x) ((uint64_t)(x))
+#endif
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#ifndef OSSwapHostToLittleInt64
+#define OSSwapHostToLittleInt64(x) OSSwapInt64(x)
+#endif
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#ifndef OSSwapBigToHostInt64
+#define OSSwapBigToHostInt64(x) ((uint64_t)(x))
+#endif
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#ifndef OSSwapLittleToHostInt64
+#define OSSwapLittleToHostInt64(x) OSSwapInt64(x)
+#endif
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+
+/* clock_gettime() and related clock definitions are missing on __APPLE__ */
+#ifndef CLOCK_REALTIME
+/* from GNU C Library time.h */
+/* Identifier for system-wide realtime clock. ( == 1) */
+#define CLOCK_REALTIME CALENDAR_CLOCK
+/* Monotonic system-wide clock. (== 0) */
+#define CLOCK_MONOTONIC SYSTEM_CLOCK
+/* High-resolution timer from the CPU. */
+#define CLOCK_PROCESS_CPUTIME_ID 2
+/* Thread-specific CPU-time clock. */
+#define CLOCK_THREAD_CPUTIME_ID 3
+/* Monotonic system-wide clock, not adjusted for frequency scaling. */
+#define CLOCK_MONOTONIC_RAW 4
+typedef int clockid_t;
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
+#endif
+
+/* some systems lack raw clock */
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW (CLOCK_MONOTONIC + 1)
+#endif
+
+/*
+ * Per thread variable, which we turn on inside real_* calls to avoid modifying
+ * time multiple times of for the whole process to prevent faking time
+ */
+static __thread bool dont_fake = false;
+
+/* Wrapper for function calls, which we want to return system time */
+#define DONT_FAKE_TIME(call) \
+ { \
+ bool dont_fake_orig = dont_fake; \
+ if (!dont_fake) \
+ { \
+ dont_fake = true; \
+ } \
+ call; \
+ dont_fake = dont_fake_orig; \
+ } while (0)
+
+/* pointers to real (not faked) functions */
+static int (*real_stat) (int, const char *, struct stat *);
+static int (*real_fstat) (int, int, struct stat *);
+static int (*real_fstatat) (int, int, const char *, struct stat *, int);
+static int (*real_lstat) (int, const char *, struct stat *);
+static int (*real_stat64) (int, const char *, struct stat64 *);
+static int (*real_fstat64) (int, int , struct stat64 *);
+static int (*real_fstatat64) (int, int , const char *, struct stat64 *, int);
+static int (*real_lstat64) (int, const char *, struct stat64 *);
+static time_t (*real_time) (time_t *);
+static int (*real_ftime) (struct timeb *);
+static int (*real_gettimeofday) (struct timeval *, void *);
+static int (*real_clock_gettime) (clockid_t clk_id, struct timespec *tp);
+#ifdef FAKE_INTERNAL_CALLS
+static int (*real___ftime) (struct timeb *);
+static int (*real___gettimeofday) (struct timeval *, void *);
+static int (*real___clock_gettime) (clockid_t clk_id, struct timespec *tp);
+#endif
+#ifdef FAKE_PTHREAD
+static int (*real_pthread_cond_timedwait_225) (pthread_cond_t *, pthread_mutex_t*, struct timespec *);
+static int (*real_pthread_cond_timedwait_232) (pthread_cond_t *, pthread_mutex_t*, struct timespec *);
+static int (*real_pthread_cond_init_232) (pthread_cond_t *restrict, const pthread_condattr_t *restrict);
+static int (*real_pthread_cond_destroy_232) (pthread_cond_t *);
+#endif
+
+#ifndef __APPLEOSX__
+#ifdef FAKE_TIMERS
+static int (*real_timer_settime_22) (int timerid, int flags, const struct itimerspec *new_value,
+ struct itimerspec * old_value);
+static int (*real_timer_settime_233) (timer_t timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec * old_value);
+static int (*real_timer_gettime_22) (int timerid,
+ struct itimerspec *curr_value);
+static int (*real_timer_gettime_233) (timer_t timerid,
+ struct itimerspec *curr_value);
+#endif
+#endif
+#ifdef FAKE_SLEEP
+static int (*real_nanosleep) (const struct timespec *req, struct timespec *rem);
+static int (*real_usleep) (useconds_t usec);
+static unsigned int (*real_sleep) (unsigned int seconds);
+static unsigned int (*real_alarm) (unsigned int seconds);
+static int (*real_poll) (struct pollfd *, nfds_t, int);
+static int (*real_ppoll) (struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
+static int (*real_select) (int nfds, fd_set *restrict readfds,
+ fd_set *restrict writefds,
+ fd_set *restrict errorfds,
+ struct timeval *restrict timeout);
+static int (*real_sem_timedwait) (sem_t*, const struct timespec*);
+#endif
+#ifdef __APPLEOSX__
+static int (*real_clock_get_time) (clock_serv_t clock_serv, mach_timespec_t *cur_timeclockid_t);
+static int apple_clock_gettime (clockid_t clk_id, struct timespec *tp);
+static clock_serv_t clock_serv_real;
+#endif
+
+static int initialized = 0;
+
+/* prototypes */
+static int fake_gettimeofday(struct timeval *tv);
+static int fake_clock_gettime(clockid_t clk_id, struct timespec *tp);
+
+/** Semaphore protecting shared data */
+static sem_t *shared_sem = NULL;
+
+/** Data shared among faketime-spawned processes */
+static struct ft_shared_s *ft_shared = NULL;
+
+/** Storage format for timestamps written to file. Big endian.*/
+struct saved_timestamp
+{
+ int64_t sec;
+ uint64_t nsec;
+};
+
+static inline void timespec_from_saved (struct timespec *tp,
+ struct saved_timestamp *saved)
+{
+ /* read as big endian */
+ tp->tv_sec = be64toh(saved->sec);
+ tp->tv_nsec = be64toh(saved->nsec);
+}
+
+/** Saved timestamps */
+static struct saved_timestamp *stss = NULL;
+static size_t infile_size;
+static bool infile_set = false;
+
+/** File fd to save timestamps to */
+static int outfile = -1;
+
+static bool limited_faking = false;
+static long callcounter = 0;
+static long ft_start_after_secs = -1;
+static long ft_stop_after_secs = -1;
+static long ft_start_after_ncalls = -1;
+static long ft_stop_after_ncalls = -1;
+
+static bool spawnsupport = false;
+static int spawned = 0;
+static char ft_spawn_target[1024];
+static long ft_spawn_secs = -1;
+static long ft_spawn_ncalls = -1;
+
+static int fake_monotonic_clock = 1;
+static int cache_enabled = 1;
+static int cache_duration = 10; /* cache fake time input for 10 seconds */
+
+/*
+ * Static timespec to store our startup time, followed by a load-time library
+ * initialization declaration.
+ */
+#ifndef CLOCK_BOOTTIME
+static struct system_time_s ftpl_starttime = {{0, -1}, {0, -1}, {0, -1}};
+#else
+static struct system_time_s ftpl_starttime = {{0, -1}, {0, -1}, {0, -1}, {0, -1}};
+#endif
+
+static char user_faked_time_fmt[BUFSIZ] = {0};
+
+/* User supplied base time to fake */
+static struct timespec user_faked_time_timespec = {0, -1};
+/* User supplied base time is set */
+static bool user_faked_time_set = false;
+static char user_faked_time_saved[BUFFERLEN] = {0};
+
+/* Fractional user offset provided through FAKETIME env. var.*/
+static struct timespec user_offset = {0, -1};
+/* Speed up or slow down clock */
+static double user_rate = 1.0;
+static bool user_rate_set = false;
+static struct timespec user_per_tick_inc = {0, -1};
+static bool user_per_tick_inc_set = false;
+
+enum ft_mode_t {FT_FREEZE, FT_START_AT, FT_NOOP} ft_mode = FT_FREEZE;
+
+/* Time to fake is not provided through FAKETIME env. var. */
+static bool parse_config_file = true;
+
+static void ft_cleanup (void) __attribute__ ((destructor));
+static void ftpl_init (void) __attribute__ ((constructor));
+
+
+/*
+ * =======================================================================
+ * Shared memory related functions === SHM
+ * =======================================================================
+ */
+
+static void ft_shm_init (void)
+{
+ int ticks_shm_fd;
+ char sem_name[256], shm_name[256], *ft_shared_env = getenv("FAKETIME_SHARED");
+
+ if (ft_shared_env != NULL)
+ {
+ if (sscanf(ft_shared_env, "%255s %255s", sem_name, shm_name) < 2)
+ {
+ printf("Error parsing semaphore name and shared memory id from string: %s", ft_shared_env);
+ exit(1);
+ }
+
+ if (SEM_FAILED == (shared_sem = sem_open(sem_name, 0)))
+ {
+ perror("sem_open");
+ exit(1);
+ }
+
+ if (-1 == (ticks_shm_fd = shm_open(shm_name, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)))
+ {
+ perror("shm_open");
+ exit(1);
+ }
+
+ if (MAP_FAILED == (ft_shared = mmap(NULL, sizeof(struct ft_shared_s), PROT_READ|PROT_WRITE,
+ MAP_SHARED, ticks_shm_fd, 0)))
+ {
+ perror("mmap");
+ exit(1);
+ }
+ }
+}
+
+static void ft_cleanup (void)
+{
+ /* detach from shared memory */
+ if (ft_shared != NULL)
+ {
+ munmap(ft_shared, sizeof(uint64_t));
+ }
+ if (stss != NULL)
+ {
+ munmap(stss, infile_size);
+ }
+ if (shared_sem != NULL)
+ {
+ sem_close(shared_sem);
+ }
+}
+
+
+/*
+ * =======================================================================
+ * Internal time retrieval === INTTIME
+ * =======================================================================
+ */
+
+/* Get system time from system for all clocks */
+static void system_time_from_system (struct system_time_s * systime)
+{
+#ifdef __APPLEOSX__
+ /* from http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x */
+ clock_serv_t cclock;
+ mach_timespec_t mts;
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clock_serv_real);
+ (*real_clock_get_time)(clock_serv_real, &mts);
+ systime->real.tv_sec = mts.tv_sec;
+ systime->real.tv_nsec = mts.tv_nsec;
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
+ (*real_clock_get_time)(cclock, &mts);
+ mach_port_deallocate(mach_task_self(), cclock);
+ systime->mon.tv_sec = mts.tv_sec;
+ systime->mon.tv_nsec = mts.tv_nsec;
+ systime->mon_raw.tv_sec = mts.tv_sec;
+ systime->mon_raw.tv_nsec = mts.tv_nsec;
+#else
+ DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_REALTIME, &systime->real))
+ ;
+ DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_MONOTONIC, &systime->mon))
+ ;
+ DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_MONOTONIC_RAW, &systime->mon_raw))
+ ;
+#ifdef CLOCK_BOOTTIME
+ DONT_FAKE_TIME((*real_clock_gettime)(CLOCK_BOOTTIME, &systime->boot))
+ ;
+#endif
+#endif
+}
+
+static void next_time(struct timespec *tp, struct timespec *ticklen)
+{
+ if (shared_sem != NULL)
+ {
+ struct timespec inc;
+ /* lock */
+ if (sem_wait(shared_sem) == -1)
+ {
+ perror("sem_wait");
+ exit(1);
+ }
+ /* calculate and update elapsed time */
+ timespecmul(ticklen, ft_shared->ticks, &inc);
+ timespecadd(&user_faked_time_timespec, &inc, tp);
+ (ft_shared->ticks)++;
+ /* unlock */
+ if (sem_post(shared_sem) == -1)
+ {
+ perror("sem_post");
+ exit(1);
+ }
+ }
+}
+
+
+/*
+ * =======================================================================
+ * Saving & loading time === SAVE
+ * =======================================================================
+ */
+
+static void save_time(struct timespec *tp)
+{
+ if ((shared_sem != NULL) && (outfile != -1))
+ {
+ struct saved_timestamp time_write;
+ ssize_t written;
+ size_t n = 0;
+
+ time_write.sec = htobe64(tp->tv_sec);
+ time_write.nsec = htobe64(tp->tv_nsec);
+
+ /* lock */
+ if (sem_wait(shared_sem) == -1)
+ {
+ perror("sem_wait");
+ exit(1);
+ }
+
+ lseek(outfile, 0, SEEK_END);
+ do
+ {
+ written = write(outfile, &(((char*)&time_write)[n]), sizeof(time_write) - n);
+ }
+ while (((written == -1) && (errno == EINTR)) ||
+ (sizeof(time_write) < (n += written)));
+
+ if ((written == -1) || (n < sizeof(time_write)))
+ {
+ perror("Saving timestamp to file failed");
+ }
+
+ /* unlock */
+ if (sem_post(shared_sem) == -1)
+ {
+ perror("sem_post");
+ exit(1);
+ }
+ }
+}
+
+/*
+ * Provide faked time from file.
+ * @return time is set from filen
+ */
+static bool load_time(struct timespec *tp)
+{
+ bool ret = false;
+ if ((shared_sem != NULL) && (infile_set))
+ {
+ /* lock */
+ if (sem_wait(shared_sem) == -1)
+ {
+ perror("sem_wait");
+ exit(1);
+ }
+
+ if ((sizeof(stss[0]) * (ft_shared->file_idx + 1)) > infile_size)
+ {
+ /* we are out of timstamps to replay, return to faking time by rules
+ * using last timestamp from file as the user provided timestamp */
+ timespec_from_saved(&user_faked_time_timespec, &stss[(infile_size / sizeof(stss[0])) - 1 ]);
+
+ if (ft_shared->ticks == 0)
+ {
+ /* we set shared memory to stop using infile */
+ ft_shared->ticks = 1;
+ system_time_from_system(&ftpl_starttime);
+ ft_shared->start_time = ftpl_starttime;
+ }
+ else
+ {
+ ftpl_starttime = ft_shared->start_time;
+ }
+
+ munmap(stss, infile_size);
+ infile_set = false;
+ }
+ else
+ {
+ timespec_from_saved(tp, &stss[ft_shared->file_idx]);
+ ft_shared->file_idx++;
+ ret = true;
+ }
+
+ /* unlock */
+ if (sem_post(shared_sem) == -1)
+ {
+ perror("sem_post");
+ exit(1);
+ }
+ }
+ return ret;
+}
+
+
+/*
+ * =======================================================================
+ * Faked system functions: file related === FAKE(FILE)
+ * =======================================================================
+ */
+
+#ifdef FAKE_STAT
+
+#ifndef NO_ATFILE
+#ifndef _ATFILE_SOURCE
+#define _ATFILE_SOURCE
+#endif
+#include <fcntl.h> /* Definition of AT_* constants */
+#endif
+
+#include <sys/stat.h>
+
+static int fake_stat_disabled = 0;
+
+#define FAKE_STRUCT_STAT_TIME(which) { \
+ struct timespec t = {buf->st_##which##time, \
+ buf->st_##which##timensec}; \
+ fake_clock_gettime(CLOCK_REALTIME, &t); \
+ buf->st_##which##time = t.tv_sec; \
+ buf->st_##which##timensec = t.tv_nsec; \
+ } while (0)
+
+static inline void fake_statbuf (struct stat *buf) {
+#ifndef st_atime
+ FAKE_STRUCT_STAT_TIME(c);
+ FAKE_STRUCT_STAT_TIME(a);
+ FAKE_STRUCT_STAT_TIME(m);
+#else
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
+#endif
+}
+
+static inline void fake_stat64buf (struct stat64 *buf) {
+#ifndef st_atime
+ FAKE_STRUCT_STAT_TIME(c);
+ FAKE_STRUCT_STAT_TIME(a);
+ FAKE_STRUCT_STAT_TIME(m);
+#else
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_ctim);
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_atim);
+ fake_clock_gettime(CLOCK_REALTIME, &buf->st_mtim);
+#endif
+}
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __xstat (int ver, const char *path, struct stat *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_stat)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original stat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_stat(ver, path, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_statbuf(buf);
+ }
+ }
+
+ return result;
+}
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __fxstat (int ver, int fildes, struct stat *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_fstat)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original fstat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_fstat(ver, fildes, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_statbuf(buf);
+ }
+ }
+ return result;
+}
+
+/* Added in v0.8 as suggested by Daniel Kahn Gillmor */
+#ifndef NO_ATFILE
+int __fxstatat(int ver, int fildes, const char *filename, struct stat *buf, int flag)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_fstatat)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original fstatat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_fstatat(ver, fildes, filename, buf, flag));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_statbuf(buf);
+ }
+ }
+ return result;
+}
+#endif
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __lxstat (int ver, const char *path, struct stat *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_lstat)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original lstat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_lstat(ver, path, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_statbuf(buf);
+ }
+ }
+ return result;
+}
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __xstat64 (int ver, const char *path, struct stat64 *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_stat64)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original stat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_stat64(ver, path, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_stat64buf(buf);
+ }
+ }
+ return result;
+}
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __fxstat64 (int ver, int fildes, struct stat64 *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_fstat64)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original fstat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_fstat64(ver, fildes, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_stat64buf(buf);
+ }
+ }
+ return result;
+}
+
+/* Added in v0.8 as suggested by Daniel Kahn Gillmor */
+#ifndef NO_ATFILE
+int __fxstatat64 (int ver, int fildes, const char *filename, struct stat64 *buf, int flag)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_fstatat64)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original fstatat64() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_fstatat64(ver, fildes, filename, buf, flag));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_stat64buf(buf);
+ }
+ }
+ return result;
+}
+#endif
+
+/* Contributed by Philipp Hachtmann in version 0.6 */
+int __lxstat64 (int ver, const char *path, struct stat64 *buf)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (NULL == real_lstat64)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original lstat() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ int result;
+ DONT_FAKE_TIME(result = real_lstat64(ver, path, buf));
+ if (result == -1)
+ {
+ return -1;
+ }
+
+ if (buf != NULL)
+ {
+ if (!fake_stat_disabled)
+ {
+ fake_stat64buf(buf);
+ }
+ }
+ return result;
+}
+#endif
+
+/*
+ * =======================================================================
+ * Faked system functions: sleep/alarm/poll/timer related === FAKE(SLEEP)
+ * =======================================================================
+ * Contributed by Balint Reczey in v0.9.5
+ */
+
+#ifdef FAKE_SLEEP
+/*
+ * Faked nanosleep()
+ */
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+ int result;
+ struct timespec real_req;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_nanosleep == NULL)
+ {
+ return -1;
+ }
+ if (req != NULL)
+ {
+ if (user_rate_set && !dont_fake)
+ {
+ timespecmul(req, 1.0 / user_rate, &real_req);
+ }
+ else
+ {
+ real_req = *req;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, rem));
+ if (result == -1)
+ {
+ return result;
+ }
+
+ /* fake returned parts */
+ if ((rem != NULL) && ((rem->tv_sec != 0) || (rem->tv_nsec != 0)))
+ {
+ if (user_rate_set && !dont_fake)
+ {
+ timespecmul(rem, user_rate, rem);
+ }
+ }
+ /* return the result to the caller */
+ return result;
+}
+
+/*
+ * Faked usleep()
+ */
+int usleep(useconds_t usec)
+{
+ int result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (user_rate_set && !dont_fake)
+ {
+ struct timespec real_req;
+
+ if (real_nanosleep == NULL)
+ {
+ /* fall back to usleep() */
+ if (real_usleep == NULL)
+ {
+ return -1;
+ }
+ DONT_FAKE_TIME(result = (*real_usleep)((1.0 / user_rate) * usec));
+ return result;
+ }
+
+ real_req.tv_sec = usec / 1000000;
+ real_req.tv_nsec = (usec % 1000000) * 1000;
+ timespecmul(&real_req, 1.0 / user_rate, &real_req);
+ DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, NULL));
+ }
+ else
+ {
+ DONT_FAKE_TIME(result = (*real_usleep)(usec));
+ }
+ return result;
+}
+
+/*
+ * Faked sleep()
+ */
+unsigned int sleep(unsigned int seconds)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (user_rate_set && !dont_fake)
+ {
+ if (real_nanosleep == NULL)
+ {
+ /* fall back to sleep */
+ unsigned int ret;
+ if (real_sleep == NULL)
+ {
+ return 0;
+ }
+ DONT_FAKE_TIME(ret = (*real_sleep)((1.0 / user_rate) * seconds));
+ return (user_rate_set && !dont_fake)?(user_rate * ret):ret;
+ }
+ else
+ {
+ int result;
+ struct timespec real_req = {seconds, 0}, rem;
+ timespecmul(&real_req, 1.0 / user_rate, &real_req);
+ DONT_FAKE_TIME(result = (*real_nanosleep)(&real_req, &rem));
+ if (result == -1)
+ {
+ return 0;
+ }
+
+ /* fake returned parts */
+ if ((rem.tv_sec != 0) || (rem.tv_nsec != 0))
+ {
+ timespecmul(&rem, user_rate, &rem);
+ }
+ /* return the result to the caller */
+ return rem.tv_sec;
+ }
+ }
+ else
+ {
+ /* no need to fake anything */
+ unsigned int ret;
+ DONT_FAKE_TIME(ret = (*real_sleep)(seconds));
+ return ret;
+ }
+}
+
+/*
+ * Faked alarm()
+ * @note due to rounding alarm(2) with faketime -f '+0 x7' won't wait 2/7
+ * wall clock seconds but 0 seconds
+ */
+unsigned int alarm(unsigned int seconds)
+{
+ unsigned int ret;
+ unsigned int seconds_real = (user_rate_set && !dont_fake)?((1.0 / user_rate) * seconds):seconds;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_alarm == NULL)
+ {
+ return -1;
+ }
+
+ DONT_FAKE_TIME(ret = (*real_alarm)(seconds_real));
+ return (user_rate_set && !dont_fake)?(user_rate * ret):ret;
+}
+
+/*
+ * Faked ppoll()
+ */
+int ppoll(struct pollfd *fds, nfds_t nfds,
+ const struct timespec *timeout_ts, const sigset_t *sigmask)
+{
+ struct timespec real_timeout, *real_timeout_pt;
+ int ret;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_ppoll == NULL)
+ {
+ return -1;
+ }
+ if (timeout_ts != NULL)
+ {
+ if (user_rate_set && !dont_fake && (timeout_ts->tv_sec > 0))
+ {
+ timespecmul(timeout_ts, 1.0 / user_rate, &real_timeout);
+ real_timeout_pt = &real_timeout;
+ }
+ else
+ {
+ /* cast away constness */
+ real_timeout_pt = (struct timespec *)timeout_ts;
+ }
+ }
+ else
+ {
+ real_timeout_pt = NULL;
+ }
+
+ DONT_FAKE_TIME(ret = (*real_ppoll)(fds, nfds, real_timeout_pt, sigmask));
+ return ret;
+}
+
+/*
+ * Faked poll()
+ */
+int poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ int ret, timeout_real = (user_rate_set && !dont_fake && (timeout > 0))?(timeout / user_rate):timeout;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_poll == NULL)
+ {
+ return -1;
+ }
+
+ DONT_FAKE_TIME(ret = (*real_poll)(fds, nfds, timeout_real));
+ return ret;
+}
+
+/*
+ * Faked select()
+ */
+int select(int nfds, fd_set *readfds,
+ fd_set *writefds,
+ fd_set *errorfds,
+ struct timeval *timeout)
+{
+ int ret;
+ struct timeval timeout_real;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+
+ if (real_select == NULL)
+ {
+ return -1;
+ }
+
+ if (timeout != NULL)
+ {
+ if (user_rate_set && !dont_fake && (timeout->tv_sec > 0 || timeout->tv_usec > 0))
+ {
+ struct timespec ts;
+
+ ts.tv_sec = timeout->tv_sec;
+ ts.tv_nsec = timeout->tv_usec * 1000;
+
+ timespecmul(&ts, 1.0 / user_rate, &ts);
+
+ timeout_real.tv_sec = ts.tv_sec;
+ timeout_real.tv_usec = ts.tv_nsec / 1000;
+ }
+ else
+ {
+ timeout_real.tv_sec = timeout->tv_sec;
+ timeout_real.tv_usec = timeout->tv_usec;
+ }
+ }
+
+ DONT_FAKE_TIME(ret = (*real_select)(nfds, readfds, writefds, errorfds, timeout == NULL ? timeout : &timeout_real));
+ return ret;
+}
+
+int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
+{
+ int result;
+ struct timespec real_abs_timeout, *real_abs_timeout_pt;
+
+ /* sanity check */
+ if (abs_timeout == NULL)
+ {
+ return -1;
+ }
+
+ if (NULL == real_sem_timedwait)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original sem_timedwait() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ if (!dont_fake)
+ {
+ struct timespec tdiff, timeadj;
+
+ timespecsub(abs_timeout, &user_faked_time_timespec, &tdiff);
+
+ if (user_rate_set)
+ {
+ timespecmul(&tdiff, user_rate, &timeadj);
+ }
+ else
+ {
+ timeadj = tdiff;
+ }
+ timespecadd(&ftpl_starttime.real, &timeadj, &real_abs_timeout);
+ real_abs_timeout_pt = &real_abs_timeout;
+ }
+ else
+ {
+ /* cast away constness */
+ real_abs_timeout_pt = (struct timespec *)abs_timeout;
+ }
+
+ DONT_FAKE_TIME(result = (*real_sem_timedwait)(sem, real_abs_timeout_pt));
+ return result;
+}
+#endif
+
+#ifndef __APPLE__
+#ifdef FAKE_TIMERS
+
+/* timer related functions and structures */
+typedef union {
+ int int_member;
+ timer_t timer_t_member;
+} timer_t_or_int;
+
+/*
+ * Faketime's function implementation's compatibility mode
+ */
+typedef enum {FT_COMPAT_GLIBC_2_2, FT_COMPAT_GLIBC_2_3_3} ft_lib_compat_timer;
+
+
+/*
+ * Faked timer_settime()
+ * Does not affect timer speed when stepping clock with each time() call.
+ */
+static int
+timer_settime_common(timer_t_or_int timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec *old_value, ft_lib_compat_timer compat)
+{
+ int result;
+ struct itimerspec new_real;
+ struct itimerspec *new_real_pt = &new_real;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (new_value == NULL)
+ {
+ new_real_pt = NULL;
+ }
+ else if (dont_fake)
+ {
+ /* cast away constness*/
+ new_real_pt = (struct itimerspec *)new_value;
+ }
+ else
+ {
+ /* set it_value */
+ if ((new_value->it_value.tv_sec != 0) ||
+ (new_value->it_value.tv_nsec != 0))
+ {
+ if (flags & TIMER_ABSTIME)
+ {
+ struct timespec tdiff, timeadj;
+ timespecsub(&new_value->it_value, &user_faked_time_timespec, &timeadj);
+ if (user_rate_set)
+ {
+ timespecmul(&timeadj, 1.0/user_rate, &tdiff);
+ }
+ else
+ {
+ tdiff = timeadj;
+ }
+ /* only CLOCK_REALTIME is handled */
+ timespecadd(&ftpl_starttime.real, &tdiff, &new_real.it_value);
+ }
+ else
+ {
+ if (user_rate_set)
+ {
+ timespecmul(&new_value->it_value, 1.0/user_rate, &new_real.it_value);
+ }
+ else
+ {
+ new_real.it_value = new_value->it_value;
+ }
+ }
+ }
+ else
+ {
+ new_real.it_value = new_value->it_value;
+ }
+ /* set it_interval */
+ if (user_rate_set && ((new_value->it_interval.tv_sec != 0) ||
+ (new_value->it_interval.tv_nsec != 0)))
+ {
+ timespecmul(&new_value->it_interval, 1.0/user_rate, &new_real.it_interval);
+ }
+ else
+ {
+ new_real.it_interval = new_value->it_interval;
+ }
+ }
+
+ switch (compat)
+ {
+ case FT_COMPAT_GLIBC_2_2:
+ DONT_FAKE_TIME(result = (*real_timer_settime_22)(timerid.int_member, flags,
+ new_real_pt, old_value));
+ break;
+ case FT_COMPAT_GLIBC_2_3_3:
+ DONT_FAKE_TIME(result = (*real_timer_settime_233)(timerid.timer_t_member,
+ flags, new_real_pt, old_value));
+ break;
+ default:
+ result = -1;
+ break;
+ }
+
+ if (result == -1)
+ {
+ return result;
+ }
+
+ /* fake returned parts */
+ if ((old_value != NULL) && !dont_fake)
+ {
+ if ((old_value->it_value.tv_sec != 0) ||
+ (old_value->it_value.tv_nsec != 0))
+ {
+ result = fake_clock_gettime(CLOCK_REALTIME, &old_value->it_value);
+ }
+ if (user_rate_set && ((old_value->it_interval.tv_sec != 0) ||
+ (old_value->it_interval.tv_nsec != 0)))
+ {
+ timespecmul(&old_value->it_interval, user_rate, &old_value->it_interval);
+ }
+ }
+
+ /* return the result to the caller */
+ return result;
+}
+
+/*
+ * Faked timer_settime() compatible with implementation in GLIBC 2.2
+ */
+int timer_settime_22(int timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec *old_value)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_timer_settime_22 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
+ FT_COMPAT_GLIBC_2_2));
+ }
+}
+
+/*
+ * Faked timer_settime() compatible with implementation in GLIBC 2.3.3
+ */
+int timer_settime_233(timer_t timerid, int flags,
+ const struct itimerspec *new_value,
+ struct itimerspec *old_value)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_timer_settime_233 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_settime_common((timer_t_or_int)timerid, flags, new_value, old_value,
+ FT_COMPAT_GLIBC_2_3_3));
+ }
+}
+
+/*
+ * Faked timer_gettime()
+ * Does not affect timer speed when stepping clock with each time() call.
+ */
+int timer_gettime_common(timer_t_or_int timerid, struct itimerspec *curr_value, ft_lib_compat_timer compat)
+{
+ int result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_timer_gettime_233 == NULL)
+ {
+ return -1;
+ }
+
+ switch (compat)
+ {
+ case FT_COMPAT_GLIBC_2_2:
+ DONT_FAKE_TIME(result = (*real_timer_gettime_22)(timerid.int_member, curr_value));
+ break;
+ case FT_COMPAT_GLIBC_2_3_3:
+ DONT_FAKE_TIME(result = (*real_timer_gettime_233)(timerid.timer_t_member, curr_value));
+ break;
+ default:
+ result = -1;
+ break;
+ }
+
+ if (result == -1)
+ {
+ return result;
+ }
+
+ /* fake returned parts */
+ if (curr_value != NULL)
+ {
+ if (user_rate_set && !dont_fake)
+ {
+ timespecmul(&curr_value->it_interval, user_rate, &curr_value->it_interval);
+ timespecmul(&curr_value->it_value, user_rate, &curr_value->it_value);
+ }
+ }
+ /* return the result to the caller */
+ return result;
+}
+
+/*
+ * Faked timer_gettime() compatible with implementation in GLIBC 2.2
+ */
+int timer_gettime_22(timer_t timerid, struct itimerspec *curr_value)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_timer_gettime_22 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
+ FT_COMPAT_GLIBC_2_2));
+ }
+}
+
+/*
+ * Faked timer_gettime() compatible with implementation in GLIBC 2.3.3
+ */
+int timer_gettime_233(timer_t timerid, struct itimerspec *curr_value)
+{
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ if (real_timer_gettime_233 == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return (timer_gettime_common((timer_t_or_int)timerid, curr_value,
+ FT_COMPAT_GLIBC_2_3_3));
+ }
+}
+
+__asm__(".symver timer_gettime_22, timer_gettime@GLIBC_2.2");
+__asm__(".symver timer_gettime_233, timer_gettime@@GLIBC_2.3.3");
+__asm__(".symver timer_settime_22, timer_settime@GLIBC_2.2");
+__asm__(".symver timer_settime_233, timer_settime@@GLIBC_2.3.3");
+
+#endif
+#endif
+
+
+/*
+ * =======================================================================
+ * Faked system functions: basic time functions === FAKE(TIME)
+ * =======================================================================
+ */
+
+/*
+ * time() implementation using clock_gettime()
+ * @note Does not check for EFAULT, see man 2 time
+ */
+time_t time(time_t *time_tptr)
+{
+ struct timespec tp;
+ time_t result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
+ if (result == -1) return -1;
+
+ /* pass the real current time to our faking version, overwriting it */
+ (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
+
+ if (time_tptr != NULL)
+ {
+ *time_tptr = tp.tv_sec;
+ }
+ return tp.tv_sec;
+}
+
+int ftime(struct timeb *tb)
+{
+ struct timespec tp;
+ int result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ /* sanity check */
+ if (tb == NULL)
+ return 0; /* ftime() always returns 0, see manpage */
+
+ /* Check whether we've got a pointer to the real ftime() function yet */
+ if (NULL == real_ftime)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original ftime() not found.\n");
+#endif
+ return 0; /* propagate error to caller */
+ }
+
+ /* initialize our TZ result with the real current time */
+ DONT_FAKE_TIME(result = (*real_ftime)(tb));
+ if (result == -1)
+ {
+ return result;
+ }
+
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
+ if (result == -1) return -1;
+
+ /* pass the real current time to our faking version, overwriting it */
+ (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
+
+ tb->time = tp.tv_sec;
+ tb->millitm = tp.tv_nsec / 1000000;
+
+ /* return the result to the caller */
+ return result; /* will always be 0 (see manpage) */
+}
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+ int result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ /* sanity check */
+ if (tv == NULL)
+ {
+ return -1;
+ }
+
+ /* Check whether we've got a pointer to the real ftime() function yet */
+ if (NULL == real_gettimeofday)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original gettimeofday() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ /* initialize our result with the real current time */
+ DONT_FAKE_TIME(result = (*real_gettimeofday)(tv, tz));
+ if (result == -1) return result; /* original function failed */
+
+ /* pass the real current time to our faking version, overwriting it */
+ result = fake_gettimeofday(tv);
+
+ /* return the result to the caller */
+ return result;
+}
+
+int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ int result;
+
+ if (!initialized)
+ {
+ ftpl_init();
+ }
+ /* sanity check */
+ if (tp == NULL)
+ {
+ return -1;
+ }
+
+ if (NULL == real_clock_gettime)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original clock_gettime() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ /* initialize our result with the real current time */
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(clk_id, tp));
+ if (result == -1) return result; /* original function failed */
+
+ /* pass the real current time to our faking version, overwriting it */
+ if (fake_monotonic_clock || (clk_id != CLOCK_MONOTONIC && clk_id != CLOCK_MONOTONIC_RAW
+#ifdef CLOCK_MONOTONIC_COARSE
+ && clk_id != CLOCK_MONOTONIC_COARSE
+#endif
+#ifdef CLOCK_BOOTTIME
+ && clk_id != CLOCK_BOOTTIME
+#endif
+ ))
+ {
+ result = fake_clock_gettime(clk_id, tp);
+ }
+
+ /* return the result to the caller */
+ return result;
+}
+
+
+/*
+ * =======================================================================
+ * Parsing the user's faketime requests === PARSE
+ * =======================================================================
+ */
+
+static void parse_ft_string(const char *user_faked_time)
+{
+ struct tm user_faked_time_tm;
+ char * tmp_time_fmt;
+
+ if (!strncmp(user_faked_time, user_faked_time_saved, BUFFERLEN))
+ {
+ /* No change */
+ return;
+ }
+
+ /* check whether the user gave us an absolute time to fake */
+ switch (user_faked_time[0])
+ {
+
+ default: /* Try and interpret this as a specified time */
+ if (ft_mode != FT_NOOP) ft_mode = FT_FREEZE;
+ user_faked_time_tm.tm_isdst = -1;
+ if (NULL != strptime(user_faked_time, user_faked_time_fmt, &user_faked_time_tm))
+ {
+ user_faked_time_timespec.tv_sec = mktime(&user_faked_time_tm);
+ user_faked_time_timespec.tv_nsec = 0;
+ user_faked_time_set = true;
+ }
+ else
+ {
+ perror("Failed to parse FAKETIME timestamp");
+ fprintf(stderr, "Please check specification %s with format %s\n", user_faked_time, user_faked_time_fmt);
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case '+':
+ case '-': /* User-specified offset */
+ if (ft_mode != FT_NOOP) ft_mode = FT_START_AT;
+ /* fractional time offsets contributed by Karl Chen in v0.8 */
+ double frac_offset = atof(user_faked_time);
+
+ /* offset is in seconds by default, but the string may contain
+ * multipliers...
+ */
+ if (strchr(user_faked_time, 'm') != NULL) frac_offset *= 60;
+ else if (strchr(user_faked_time, 'h') != NULL) frac_offset *= 60 * 60;
+ else if (strchr(user_faked_time, 'd') != NULL) frac_offset *= 60 * 60 * 24;
+ else if (strchr(user_faked_time, 'y') != NULL) frac_offset *= 60 * 60 * 24 * 365;
+
+ user_offset.tv_sec = floor(frac_offset);
+ user_offset.tv_nsec = (frac_offset - user_offset.tv_sec) * SEC_TO_nSEC;
+ timespecadd(&ftpl_starttime.real, &user_offset, &user_faked_time_timespec);
+ goto parse_modifiers;
+ break;
+
+ /* Contributed by David North, TDI in version 0.7 */
+ case '@': /* Specific time, but clock along relative to that starttime */
+ ft_mode = FT_START_AT;
+ user_faked_time_tm.tm_isdst = -1;
+ (void) strptime(&user_faked_time[1], user_faked_time_fmt, &user_faked_time_tm);
+
+ user_faked_time_timespec.tv_sec = mktime(&user_faked_time_tm);
+ user_faked_time_timespec.tv_nsec = 0;
+
+ /* Reset starttime */
+ system_time_from_system(&ftpl_starttime);
+ goto parse_modifiers;
+ break;
+
+ case 'i':
+ case 'x': /* Only modifiers are passed, don't fall back to strptime */
+parse_modifiers:
+ /* Speed-up / slow-down contributed by Karl Chen in v0.8 */
+ if (strchr(user_faked_time, 'x') != NULL)
+ {
+ user_rate = atof(strchr(user_faked_time, 'x')+1);
+ user_rate_set = true;
+ }
+ else if (NULL != (tmp_time_fmt = strchr(user_faked_time, 'i')))
+ {
+ double tick_inc = atof(tmp_time_fmt + 1);
+ /* increment time with every time() call*/
+ user_per_tick_inc.tv_sec = floor(tick_inc);
+ user_per_tick_inc.tv_nsec = (tick_inc - user_per_tick_inc.tv_sec) * SEC_TO_nSEC ;
+ user_per_tick_inc_set = true;
+ }
+ break;
+ } // end of switch
+
+ strncpy(user_faked_time_saved, user_faked_time, BUFFERLEN-1);
+ user_faked_time_saved[BUFFERLEN-1] = 0;
+#ifdef DEBUG
+ fprintf(stderr, "new FAKETIME: %s\n", user_faked_time_saved);
+#endif
+}
+
+
+/*
+ * =======================================================================
+ * Initialization === INIT
+ * =======================================================================
+ */
+
+static void ftpl_init(void)
+{
+ char *tmp_env;
+ bool dont_fake_final;
+
+#ifdef __APPLE__
+ const char *progname = getprogname();
+#else
+ const char *progname = __progname;
+#endif
+
+ /* Look up all real_* functions. NULL will mark missing ones. */
+ real_stat = dlsym(RTLD_NEXT, "__xstat");
+ real_fstat = dlsym(RTLD_NEXT, "__fxstat");
+ real_fstatat = dlsym(RTLD_NEXT, "__fxstatat");
+ real_lstat = dlsym(RTLD_NEXT, "__lxstat");
+ real_stat64 = dlsym(RTLD_NEXT,"__xstat64");
+ real_fstat64 = dlsym(RTLD_NEXT, "__fxstat64");
+ real_fstatat64 = dlsym(RTLD_NEXT, "__fxstatat64");
+ real_lstat64 = dlsym(RTLD_NEXT, "__lxstat64");
+ real_time = dlsym(RTLD_NEXT, "time");
+ real_ftime = dlsym(RTLD_NEXT, "ftime");
+#if defined(__alpha__) && defined(__GLIBC__)
+ real_gettimeofday = dlvsym(RTLD_NEXT, "gettimeofday", "GLIBC_2.1");
+#else
+ real_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday");
+#endif
+#ifdef FAKE_SLEEP
+ real_nanosleep = dlsym(RTLD_NEXT, "nanosleep");
+ real_usleep = dlsym(RTLD_NEXT, "usleep");
+ real_sleep = dlsym(RTLD_NEXT, "sleep");
+ real_alarm = dlsym(RTLD_NEXT, "alarm");
+ real_poll = dlsym(RTLD_NEXT, "poll");
+ real_ppoll = dlsym(RTLD_NEXT, "ppoll");
+ real_select = dlsym(RTLD_NEXT, "select");
+ real_sem_timedwait = dlsym(RTLD_NEXT, "sem_timedwait");
+#endif
+#ifdef FAKE_INTERNAL_CALLS
+ real___ftime = dlsym(RTLD_NEXT, "__ftime");
+# if defined(__alpha__) && defined(__GLIBC__)
+ real___gettimeofday = dlvsym(RTLD_NEXT, "__gettimeofday", "GLIBC_2.1");
+# else
+ real___gettimeofday = dlsym(RTLD_NEXT, "__gettimeofday");
+# endif
+ real___clock_gettime = dlsym(RTLD_NEXT, "__clock_gettime");
+#endif
+#ifdef FAKE_PTHREAD
+
+#ifdef __GLIBC__
+ real_pthread_cond_timedwait_225 = dlvsym(RTLD_NEXT, "pthread_cond_timedwait", "GLIBC_2.2.5");
+
+ real_pthread_cond_timedwait_232 = dlvsym(RTLD_NEXT, "pthread_cond_timedwait", "GLIBC_2.3.2");
+ real_pthread_cond_init_232 = dlvsym(RTLD_NEXT, "pthread_cond_init", "GLIBC_2.3.2");
+ real_pthread_cond_destroy_232 = dlvsym(RTLD_NEXT, "pthread_cond_destroy", "GLIBC_2.3.2");
+#endif
+
+ if (NULL == real_pthread_cond_timedwait_232)
+ {
+ real_pthread_cond_timedwait_232 = dlsym(RTLD_NEXT, "pthread_cond_timedwait");
+ }
+ if (NULL == real_pthread_cond_init_232)
+ {
+ real_pthread_cond_init_232 = dlsym(RTLD_NEXT, "pthread_cond_init");
+ }
+ if (NULL == real_pthread_cond_destroy_232)
+ {
+ real_pthread_cond_destroy_232 = dlsym(RTLD_NEXT, "pthread_cond_destroy");
+ }
+#endif
+#ifdef __APPLEOSX__
+ real_clock_get_time = dlsym(RTLD_NEXT, "clock_get_time");
+ real_clock_gettime = apple_clock_gettime;
+#else
+ real_clock_gettime = dlsym(RTLD_NEXT, "__clock_gettime");
+ if (NULL == real_clock_gettime)
+ {
+ real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
+ }
+#ifdef FAKE_TIMERS
+#if defined(__sun)
+ real_timer_gettime_233 = dlsym(RTLD_NEXT, "timer_gettime");
+ real_timer_settime_233 = dlsym(RTLD_NEXT, "timer_settime");
+#else
+#ifdef __GLIBC__
+ real_timer_settime_22 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.2");
+ real_timer_settime_233 = dlvsym(RTLD_NEXT, "timer_settime","GLIBC_2.3.3");
+#endif
+ if (NULL == real_timer_settime_233)
+ {
+ real_timer_settime_233 = dlsym(RTLD_NEXT, "timer_settime");
+ }
+#ifdef __GLIBC__
+ real_timer_gettime_22 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.2");
+ real_timer_gettime_233 = dlvsym(RTLD_NEXT, "timer_gettime","GLIBC_2.3.3");
+#endif
+ if (NULL == real_timer_gettime_233)
+ {
+ real_timer_gettime_233 = dlsym(RTLD_NEXT, "timer_gettime");
+ }
+#endif
+#endif
+#endif
+
+ dont_fake = true; // Do not fake times during initialization
+ dont_fake_final = false;
+ initialized = 1;
+
+ ft_shm_init();
+#ifdef FAKE_STAT
+ if (getenv("NO_FAKE_STAT")!=NULL)
+ {
+ fake_stat_disabled = 1; //Note that this is NOT re-checked
+ }
+#endif
+
+ if ((tmp_env = getenv("FAKETIME_CACHE_DURATION")) != NULL)
+ {
+ cache_duration = atoi(tmp_env);
+ }
+ if ((tmp_env = getenv("FAKETIME_NO_CACHE")) != NULL)
+ {
+ if (0 == strcmp(tmp_env, "1"))
+ {
+ cache_enabled = 0;
+ }
+ }
+ if ((tmp_env = getenv("DONT_FAKE_MONOTONIC")) != NULL)
+ {
+ if (0 == strcmp(tmp_env, "1"))
+ {
+ fake_monotonic_clock = 0;
+ }
+ }
+ /* Check whether we actually should be faking the returned timestamp. */
+
+ /* We can prevent faking time for specified commands */
+ if ((tmp_env = getenv("FAKETIME_SKIP_CMDS")) != NULL)
+ {
+ char *skip_cmd, *saveptr, *tmpvar;
+ /* Don't mess with the env variable directly. */
+ tmpvar = strdup(tmp_env);
+ if (tmpvar != NULL)
+ {
+ skip_cmd = strtok_r(tmpvar, ",", &saveptr);
+ while (skip_cmd != NULL)
+ {
+ if (0 == strcmp(progname, skip_cmd))
+ {
+ ft_mode = FT_NOOP;
+ dont_fake_final = true;
+ break;
+ }
+ skip_cmd = strtok_r(NULL, ",", &saveptr);
+ }
+ free(tmpvar);
+ tmpvar = NULL;
+ }
+ else
+ {
+ fprintf(stderr, "Error: Could not copy the environment variable value.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* We can limit faking time to specified commands */
+ if ((tmp_env = getenv("FAKETIME_ONLY_CMDS")) != NULL)
+ {
+ char *only_cmd, *saveptr, *tmpvar;
+ bool cmd_matched = false;
+
+ if (getenv("FAKETIME_SKIP_CMDS") != NULL)
+ {
+ fprintf(stderr, "Error: Both FAKETIME_SKIP_CMDS and FAKETIME_ONLY_CMDS can't be set.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Don't mess with the env variable directly. */
+ tmpvar = strdup(tmp_env);
+ if (tmpvar != NULL) {
+ only_cmd = strtok_r(tmpvar, ",", &saveptr);
+ while (only_cmd != NULL)
+ {
+ if (0 == strcmp(progname, only_cmd))
+ {
+ cmd_matched = true;
+ break;
+ }
+ only_cmd = strtok_r(NULL, ",", &saveptr);
+ }
+
+ if (!cmd_matched)
+ {
+ ft_mode = FT_NOOP;
+ dont_fake_final = true;
+ }
+ free(tmpvar);
+ } else {
+ fprintf(stderr, "Error: Could not copy the environment variable value.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if ((tmp_env = getenv("FAKETIME_START_AFTER_SECONDS")) != NULL)
+ {
+ ft_start_after_secs = atol(tmp_env);
+ limited_faking = true;
+ }
+ if ((tmp_env = getenv("FAKETIME_STOP_AFTER_SECONDS")) != NULL)
+ {
+ ft_stop_after_secs = atol(tmp_env);
+ limited_faking = true;
+ }
+ if ((tmp_env = getenv("FAKETIME_START_AFTER_NUMCALLS")) != NULL)
+ {
+ ft_start_after_ncalls = atol(tmp_env);
+ limited_faking = true;
+ }
+ if ((tmp_env = getenv("FAKETIME_STOP_AFTER_NUMCALLS")) != NULL)
+ {
+ ft_stop_after_ncalls = atol(tmp_env);
+ limited_faking = true;
+ }
+
+ /* check whether we should spawn an external command */
+ if ((tmp_env = getenv("FAKETIME_SPAWN_TARGET")) != NULL)
+ {
+ spawnsupport = true;
+ (void) strncpy(ft_spawn_target, getenv("FAKETIME_SPAWN_TARGET"), sizeof(ft_spawn_target) - 1);
+ ft_spawn_target[sizeof(ft_spawn_target) - 1] = 0;
+ if ((tmp_env = getenv("FAKETIME_SPAWN_SECONDS")) != NULL)
+ {
+ ft_spawn_secs = atol(tmp_env);
+ }
+ if ((tmp_env = getenv("FAKETIME_SPAWN_NUMCALLS")) != NULL)
+ {
+ ft_spawn_ncalls = atol(tmp_env);
+ }
+ }
+
+ if ((tmp_env = getenv("FAKETIME_SAVE_FILE")) != NULL)
+ {
+ if (-1 == (outfile = open(tmp_env, O_RDWR | O_APPEND | O_CLOEXEC | O_CREAT,
+ S_IWUSR | S_IRUSR)))
+ {
+ perror("Opening file for saving timestamps failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* load file only if reading timstamps from it is not finished yet */
+ if ((tmp_env = getenv("FAKETIME_LOAD_FILE")) != NULL)
+ {
+ int infile = -1;
+ struct stat sb;
+ if (-1 == (infile = open(tmp_env, O_RDONLY|O_CLOEXEC)))
+ {
+ perror("Opening file for loading timestamps failed");
+ exit(EXIT_FAILURE);
+ }
+
+ fstat(infile, &sb);
+ if (sizeof(stss[0]) > (infile_size = sb.st_size))
+ {
+ printf("There are no timestamps in the provided file to load timestamps from");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((infile_size % sizeof(stss[0])) != 0)
+ {
+ printf("File size is not multiple of timestamp size. It is probably damaged.");
+ exit(EXIT_FAILURE);
+ }
+
+ stss = mmap(NULL, infile_size, PROT_READ, MAP_SHARED, infile, 0);
+ if (stss == MAP_FAILED)
+ {
+ perror("Mapping file for loading timestamps failed");
+ exit(EXIT_FAILURE);
+ }
+ infile_set = true;
+ }
+
+ tmp_env = getenv("FAKETIME_FMT");
+ if (tmp_env == NULL)
+ {
+ strcpy(user_faked_time_fmt, "%Y-%m-%d %T");
+ }
+ else
+ {
+ strncpy(user_faked_time_fmt, tmp_env, BUFSIZ - 1);
+ user_faked_time_fmt[BUFSIZ - 1] = 0;
+ }
+
+ if (shared_sem != 0)
+ {
+ if (sem_wait(shared_sem) == -1)
+ {
+ perror("sem_wait");
+ exit(1);
+ }
+ if (ft_shared->start_time.real.tv_nsec == -1)
+ {
+ /* set up global start time */
+ system_time_from_system(&ftpl_starttime);
+ ft_shared->start_time = ftpl_starttime;
+ }
+ else
+ {
+ /** get preset start time */
+ ftpl_starttime = ft_shared->start_time;
+ }
+ if (sem_post(shared_sem) == -1)
+ {
+ perror("sem_post");
+ exit(1);
+ }
+ }
+ else
+ {
+ system_time_from_system(&ftpl_starttime);
+ }
+ /* fake time supplied as environment variable? */
+ if (NULL != (tmp_env = getenv("FAKETIME")))
+ {
+ parse_config_file = false;
+ parse_ft_string(tmp_env);
+ }
+
+ dont_fake = dont_fake_final;
+}
+
+
+/*
+ * =======================================================================
+ * Helper functions === HELPER
+ * =======================================================================
+ */
+
+static void remove_trailing_eols(char *line)
+{
+ char *endp = line + strlen(line);
+ /*
+ * erase the last char if it's a newline
+ * or carriage return, and back up.
+ * keep doing this, but don't back up
+ * past the beginning of the string.
+ */
+# define is_eolchar(c) ((c) == '\n' || (c) == '\r')
+ while (endp > line && is_eolchar(endp[-1]))
+ {
+ *--endp = '\0';
+ }
+}
+
+
+/*
+ * =======================================================================
+ * Implementation of faked functions === FAKE(FAKE)
+ * =======================================================================
+ */
+
+#ifdef PTHREAD_SINGLETHREADED_TIME
+static void pthread_cleanup_mutex_lock(void *data)
+{
+ pthread_mutex_t *mutex = data;
+ pthread_mutex_unlock(mutex);
+}
+#endif
+
+int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ /* variables used for caching, introduced in version 0.6 */
+ static time_t last_data_fetch = 0; /* not fetched previously at first call */
+ static int cache_expired = 1; /* considered expired at first call */
+
+ if (dont_fake) return 0;
+ /* Per process timers are only sped up or slowed down */
+ if ((clk_id == CLOCK_PROCESS_CPUTIME_ID ) || (clk_id == CLOCK_THREAD_CPUTIME_ID))
+ {
+ if (user_rate_set)
+ {
+ timespecmul(tp, user_rate, tp);
+ }
+ return 0;
+ }
+
+ /* Sanity check by Karl Chan since v0.8 */
+ if (tp == NULL) return -1;
+
+#ifdef PTHREAD_SINGLETHREADED_TIME
+ static pthread_mutex_t time_mutex=PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&time_mutex);
+ pthread_cleanup_push(pthread_cleanup_mutex_lock, &time_mutex);
+#endif
+
+ if ((limited_faking &&
+ ((ft_start_after_ncalls != -1) || (ft_stop_after_ncalls != -1))) ||
+ (spawnsupport && ft_spawn_ncalls))
+ {
+ if (callcounter < LONG_MAX) callcounter++;
+ }
+
+ if (limited_faking || spawnsupport)
+ {
+ struct timespec tmp_ts;
+ /* For debugging, output #seconds and #calls */
+ switch (clk_id)
+ {
+ case CLOCK_REALTIME:
+#ifdef CLOCK_REALTIME_COARSE
+ case CLOCK_REALTIME_COARSE:
+#endif
+ timespecsub(tp, &ftpl_starttime.real, &tmp_ts);
+ break;
+ case CLOCK_MONOTONIC:
+#ifdef CLOCK_MONOTONIC_COARSE
+ case CLOCK_MONOTONIC_COARSE:
+#endif
+ timespecsub(tp, &ftpl_starttime.mon, &tmp_ts);
+ break;
+ case CLOCK_MONOTONIC_RAW:
+ timespecsub(tp, &ftpl_starttime.mon_raw, &tmp_ts);
+ break;
+#ifdef CLOCK_BOOTTIME
+ case CLOCK_BOOTTIME:
+ timespecsub(tp, &ftpl_starttime.boot, &tmp_ts);
+ break;
+#endif
+ default:
+ timespecsub(tp, &ftpl_starttime.real, &tmp_ts);
+ break;
+ }
+
+ if (limited_faking)
+ {
+ /* Check whether we actually should be faking the returned timestamp. */
+ /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
+ if ((ft_start_after_secs != -1) && (tmp_ts.tv_sec < ft_start_after_secs)) return 0;
+ if ((ft_stop_after_secs != -1) && (tmp_ts.tv_sec >= ft_stop_after_secs)) return 0;
+ if ((ft_start_after_ncalls != -1) && (callcounter < ft_start_after_ncalls)) return 0;
+ if ((ft_stop_after_ncalls != -1) && (callcounter >= ft_stop_after_ncalls)) return 0;
+ /* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu continues\n", (*time_tptr - ftpl_starttime), callcounter); */
+ }
+
+ if (spawnsupport)
+ {
+ /* check whether we should spawn an external command */
+ if (spawned == 0)
+ { /* exec external command once only */
+ if (((tmp_ts.tv_sec == ft_spawn_secs) || (callcounter == ft_spawn_ncalls)) && (spawned == 0))
+ {
+ spawned = 1;
+ (void) (system(ft_spawn_target) + 1);
+ }
+ }
+ }
+ }
+
+ if (last_data_fetch > 0)
+ {
+ if ((tp->tv_sec - last_data_fetch) > cache_duration)
+ {
+ cache_expired = 1;
+ }
+ else
+ {
+ cache_expired = 0;
+ }
+ }
+
+ if (cache_enabled == 0)
+ {
+ cache_expired = 1;
+ }
+
+ if (cache_expired == 1)
+ {
+ static char user_faked_time[BUFFERLEN]; /* changed to static for caching in v0.6 */
+ /* initialize with default or env. variable */
+ char *tmp_env;
+
+ /* Can be enabled for testing ...
+ fprintf(stderr, "***************++ Cache expired ++**************\n");
+ */
+
+ if (NULL != (tmp_env = getenv("FAKETIME")))
+ {
+ strncpy(user_faked_time, tmp_env, BUFFERLEN - 1);
+ user_faked_time[BUFFERLEN - 1] = 0;
+ }
+ else
+ {
+ snprintf(user_faked_time, BUFFERLEN, "+0");
+ }
+
+ last_data_fetch = tp->tv_sec;
+ /* fake time supplied as environment variable? */
+ if (parse_config_file)
+ {
+ char custom_filename[BUFSIZ];
+ char filename[BUFSIZ];
+ FILE *faketimerc;
+ /* check whether there's a .faketimerc in the user's home directory, or
+ * a system-wide /etc/faketimerc present.
+ * The /etc/faketimerc handling has been contributed by David Burley,
+ * Jacob Moorman, and Wayne Davison of SourceForge, Inc. in version 0.6 */
+ (void) snprintf(custom_filename, BUFSIZ, "%s", getenv("FAKETIME_TIMESTAMP_FILE"));
+ (void) snprintf(filename, BUFSIZ, "%s/.faketimerc", getenv("HOME"));
+ if ((faketimerc = fopen(custom_filename, "rt")) != NULL ||
+ (faketimerc = fopen(filename, "rt")) != NULL ||
+ (faketimerc = fopen("/etc/faketimerc", "rt")) != NULL)
+ {
+ char line[BUFFERLEN];
+ while(fgets(line, BUFFERLEN, faketimerc) != NULL)
+ {
+ if ((strlen(line) > 1) && (line[0] != ' ') &&
+ (line[0] != '#') && (line[0] != ';'))
+ {
+ remove_trailing_eols(line);
+ strncpy(user_faked_time, line, BUFFERLEN-1);
+ user_faked_time[BUFFERLEN-1] = 0;
+ break;
+ }
+ }
+ fclose(faketimerc);
+ }
+ } /* read fake time from file */
+ parse_ft_string(user_faked_time);
+ } /* cache had expired */
+
+ if (infile_set)
+ {
+ if (load_time(tp))
+ {
+ return 0;
+ }
+ }
+
+ /* check whether the user gave us an absolute time to fake */
+ switch (ft_mode)
+ {
+ case FT_FREEZE: /* a specified time */
+ if (user_faked_time_set)
+ {
+ *tp = user_faked_time_timespec;
+ }
+ break;
+
+ case FT_START_AT: /* User-specified offset */
+ if (user_per_tick_inc_set)
+ {
+ /* increment time with every time() call*/
+ next_time(tp, &user_per_tick_inc);
+ }
+ else
+ {
+ /* Speed-up / slow-down contributed by Karl Chen in v0.8 */
+ struct timespec tdiff, timeadj;
+ switch (clk_id)
+ {
+ case CLOCK_REALTIME:
+#ifdef CLOCK_REALTIME_COARSE
+ case CLOCK_REALTIME_COARSE:
+#endif
+ timespecsub(tp, &ftpl_starttime.real, &tdiff);
+ break;
+ case CLOCK_MONOTONIC:
+#ifdef CLOCK_MONOTONIC_COARSE
+ case CLOCK_MONOTONIC_COARSE:
+#endif
+ timespecsub(tp, &ftpl_starttime.mon, &tdiff);
+ break;
+ case CLOCK_MONOTONIC_RAW:
+ timespecsub(tp, &ftpl_starttime.mon_raw, &tdiff);
+ break;
+#ifdef CLOCK_BOOTTIME
+ case CLOCK_BOOTTIME:
+ timespecsub(tp, &ftpl_starttime.boot, &tdiff);
+ break;
+#endif
+ default:
+ timespecsub(tp, &ftpl_starttime.real, &tdiff);
+ break;
+ } // end of switch (clk_id)
+ if (user_rate_set)
+ {
+ timespecmul(&tdiff, user_rate, &timeadj);
+ }
+ else
+ {
+ timeadj = tdiff;
+ }
+ timespecadd(&user_faked_time_timespec, &timeadj, tp);
+ }
+ break;
+
+ default:
+ return -1;
+ } // end of switch(ft_mode)
+
+#ifdef PTHREAD_SINGLETHREADED_TIME
+ pthread_cleanup_pop(1);
+#endif
+ save_time(tp);
+ return 0;
+}
+
+int fake_gettimeofday(struct timeval *tv)
+{
+ struct timespec ts;
+ int ret;
+ ts.tv_sec = tv->tv_sec;
+ ts.tv_nsec = tv->tv_usec * 1000 + ftpl_starttime.real.tv_nsec % 1000;
+
+ ret = fake_clock_gettime(CLOCK_REALTIME, &ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec =ts.tv_nsec / 1000;
+
+ return ret;
+}
+
+
+/*
+ * =======================================================================
+ * Faked system functions: Apple Mac OS X specific === FAKE(OSX)
+ * =======================================================================
+ */
+
+#ifdef __APPLEOSX__
+/*
+ * clock_gettime implementation for __APPLE__
+ * @note It always behave like being called with CLOCK_REALTIME.
+ */
+static int apple_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ int result;
+ mach_timespec_t cur_timeclockid_t;
+ (void) clk_id; /* unused */
+
+ if (NULL == real_clock_get_time)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original clock_get_time() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ DONT_FAKE_TIME(result = (*real_clock_get_time)(clock_serv_real, &cur_timeclockid_t));
+ tp->tv_sec = cur_timeclockid_t.tv_sec;
+ tp->tv_nsec = cur_timeclockid_t.tv_nsec;
+ return result;
+}
+
+int clock_get_time(clock_serv_t clock_serv, mach_timespec_t *cur_timeclockid_t)
+{
+ int result;
+ struct timespec ts;
+
+ /*
+ * Initialize our result with the real current time from CALENDAR_CLOCK.
+ * This is a bit of cheating, but we don't keep track of obtained clock
+ * services.
+ */
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &ts));
+ if (result == -1) return result; /* original function failed */
+
+ /* pass the real current time to our faking version, overwriting it */
+ result = fake_clock_gettime(CLOCK_REALTIME, &ts);
+ cur_timeclockid_t->tv_sec = ts.tv_sec;
+ cur_timeclockid_t->tv_nsec = ts.tv_nsec;
+
+ /* return the result to the caller */
+ return result;
+}
+#endif
+
+
+/*
+ * =======================================================================
+ * Faked system-internal functions === FAKE(INT)
+ * =======================================================================
+ */
+
+#ifdef FAKE_INTERNAL_CALLS
+int __gettimeofday(struct timeval *tv, void *tz)
+{
+ int result;
+
+ /* sanity check */
+ if (tv == NULL)
+ {
+ return -1;
+ }
+
+ /* Check whether we've got a pointer to the real ftime() function yet */
+ if (NULL == real___gettimeofday)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original __gettimeofday() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ /* initialize our result with the real current time */
+ DONT_FAKE_TIME(result = (*real___gettimeofday)(tv, tz));
+ if (result == -1) return result; /* original function failed */
+
+ /* pass the real current time to our faking version, overwriting it */
+ result = fake_gettimeofday(tv);
+
+ /* return the result to the caller */
+ return result;
+}
+
+int __clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ int result;
+
+ /* sanity check */
+ if (tp == NULL)
+ {
+ return -1;
+ }
+
+ if (NULL == real___clock_gettime)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original __clock_gettime() not found.\n");
+#endif
+ return -1; /* propagate error to caller */
+ }
+
+ /* initialize our result with the real current time */
+ DONT_FAKE_TIME(result = (*real___clock_gettime)(clk_id, tp));
+ if (result == -1) return result; /* original function failed */
+
+ /* pass the real current time to our faking version, overwriting it */
+ if (fake_monotonic_clock || (clk_id != CLOCK_MONOTONIC && clk_id != CLOCK_MONOTONIC_RAW
+#ifdef CLOCK_MONOTONIC_COARSE
+ && clk_id != CLOCK_MONOTONIC_COARSE
+#endif
+#ifdef CLOCK_BOOTTIME
+ && clk_id != CLOCK_BOOTTIME
+#endif
+ ))
+
+ {
+ result = fake_clock_gettime(clk_id, tp);
+ }
+
+ /* return the result to the caller */
+ return result;
+}
+
+time_t __time(time_t *time_tptr)
+{
+ struct timespec tp;
+ time_t result;
+
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
+ if (result == -1) return -1;
+
+ /* pass the real current time to our faking version, overwriting it */
+ (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
+
+ if (time_tptr != NULL)
+ {
+ *time_tptr = tp.tv_sec;
+ }
+ return tp.tv_sec;
+}
+
+int __ftime(struct timeb *tb)
+{
+ struct timespec tp;
+ int result;
+
+ /* sanity check */
+ if (tb == NULL)
+ return 0; /* ftime() always returns 0, see manpage */
+
+ /* Check whether we've got a pointer to the real ftime() function yet */
+ if (NULL == real___ftime)
+ { /* dlsym() failed */
+#ifdef DEBUG
+ (void) fprintf(stderr, "faketime problem: original ftime() not found.\n");
+#endif
+ return 0; /* propagate error to caller */
+ }
+
+ /* initialize our TZ result with the real current time */
+ DONT_FAKE_TIME(result = (*real___ftime)(tb));
+ if (result == -1)
+ {
+ return result;
+ }
+
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, &tp));
+ if (result == -1) return -1;
+
+ /* pass the real current time to our faking version, overwriting it */
+ (void)fake_clock_gettime(CLOCK_REALTIME, &tp);
+
+ tb->time = tp.tv_sec;
+ tb->millitm = tp.tv_nsec / 1000000;
+
+ /* return the result to the caller */
+ return result; /* will always be 0 (see manpage) */
+}
+
+#endif
+
+/*
+ * =======================================================================
+ * Faked pthread_cond_timedwait === FAKE(pthread)
+ * =======================================================================
+ */
+
+/* pthread_cond_timedwait
+
+ The specified absolute time in pthread_cond_timedwait is directly
+ passed to the kernel via the futex syscall. The kernel, however,
+ does not know about the fake time. In 99.9% of cases, the time
+ until this function should wait is calculated by an application
+ relatively to the current time, which has been faked in the
+ application. Hence, we should convert the waiting time back to real
+ time.
+
+ pthread_cond_timedwait in GLIBC_2_2_5 only supports
+ CLOCK_REALTIME. Since the init and destroy functions are not
+ redefined for GLIBC_2_2_5, a corresponding cond will never be
+ added to monotonic_conds and hence the correct branch will
+ always be taken.
+*/
+
+
+#ifdef FAKE_PTHREAD
+
+typedef enum {FT_COMPAT_GLIBC_2_2_5, FT_COMPAT_GLIBC_2_3_2} ft_lib_compat_pthread;
+
+struct pthread_cond_monotonic {
+ pthread_cond_t *ptr;
+ UT_hash_handle hh;
+};
+
+static struct pthread_cond_monotonic *monotonic_conds = NULL;
+
+int pthread_cond_init_232(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr)
+{
+ clockid_t clock_id;
+ int result;
+
+ result = real_pthread_cond_init_232(cond, attr);
+
+ if (result != 0 || attr == NULL)
+ return result;
+
+ pthread_condattr_getclock(attr, &clock_id);
+
+ if (clock_id == CLOCK_MONOTONIC) {
+ struct pthread_cond_monotonic *e = (struct pthread_cond_monotonic*)malloc(sizeof(struct pthread_cond_monotonic));
+ e->ptr = cond;
+ HASH_ADD_PTR(monotonic_conds, ptr, e);
+ }
+
+ return result;
+}
+
+int pthread_cond_destroy_232(pthread_cond_t *cond)
+{
+ struct pthread_cond_monotonic* e;
+ HASH_FIND_PTR(monotonic_conds, &cond, e);
+ if (e) {
+ HASH_DEL(monotonic_conds, e);
+ free(e);
+ }
+
+ return real_pthread_cond_destroy_232(cond);
+}
+
+int pthread_cond_timedwait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, ft_lib_compat_pthread compat)
+{
+ struct timespec tp, tdiff_actual, realtime, faketime;
+ struct timespec *tf = NULL;
+ struct pthread_cond_monotonic* e;
+ char *tmp_env;
+ int wait_ms;
+ clockid_t clk_id;
+ int result = 0;
+
+ if (abstime != NULL)
+ {
+ HASH_FIND_PTR(monotonic_conds, &cond, e);
+ if (e != NULL)
+ clk_id = CLOCK_MONOTONIC;
+ else
+ clk_id = CLOCK_REALTIME;
+
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(clk_id, &realtime));
+ if (result == -1)
+ {
+ return EINVAL;
+ }
+ faketime = realtime;
+ (void)fake_clock_gettime(clk_id, &faketime);
+
+ if ((tmp_env = getenv("FAKETIME_WAIT_MS")) != NULL)
+ {
+ wait_ms = atol(tmp_env);
+ DONT_FAKE_TIME(result = (*real_clock_gettime)(clk_id, &realtime));
+ if (result == -1)
+ {
+ return EINVAL;
+ }
+
+ tdiff_actual.tv_sec = wait_ms / 1000;
+ tdiff_actual.tv_nsec = (wait_ms % 1000) * 1000000;
+ timespecadd(&realtime, &tdiff_actual, &tp);
+
+ tf = &tp;
+ }
+ else
+ {
+ timespecsub(abstime, &faketime, &tp);
+ if (user_rate_set)
+ {
+ timespecmul(&tp, 1.0 / user_rate, &tdiff_actual);
+ }
+ else
+ {
+ tdiff_actual = tp;
+ }
+ }
+
+ /* For CLOCK_MONOTONIC, pthread_cond_timedwait uses clock_gettime
+ internally to calculate the appropriate duration for the
+ waiting time. This already uses the faked functions, hence, the
+ fake time needs to be passed to pthread_cond_timedwait for
+ CLOCK_MONOTONIC. */
+ if(clk_id == CLOCK_MONOTONIC)
+ timespecadd(&faketime, &tdiff_actual, &tp);
+ else
+ timespecadd(&realtime, &tdiff_actual, &tp);
+
+ tf = &tp;
+ }
+
+ switch (compat) {
+ case FT_COMPAT_GLIBC_2_3_2:
+ result = real_pthread_cond_timedwait_232(cond, mutex, tf);
+ break;
+ case FT_COMPAT_GLIBC_2_2_5:
+ result = real_pthread_cond_timedwait_225(cond, mutex, tf);
+ break;
+ }
+ return result;
+}
+
+int pthread_cond_timedwait_225(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+ return pthread_cond_timedwait_common(cond, mutex, abstime, FT_COMPAT_GLIBC_2_2_5);
+}
+
+int pthread_cond_timedwait_232(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+ return pthread_cond_timedwait_common(cond, mutex, abstime, FT_COMPAT_GLIBC_2_3_2);
+}
+
+__asm__(".symver pthread_cond_timedwait_225, pthread_cond_timedwait@GLIBC_2.2.5");
+__asm__(".symver pthread_cond_timedwait_232, pthread_cond_timedwait@@GLIBC_2.3.2");
+__asm__(".symver pthread_cond_init_232, pthread_cond_init@@GLIBC_2.3.2");
+__asm__(".symver pthread_cond_destroy_232, pthread_cond_destroy@@GLIBC_2.3.2");
+
+#endif
+
+
+/*
+ * Editor modelines
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 2
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=2 expandtab:
+ * :indentSize=2:tabSize=2:noTabs=true:
+ */
+
+/* eof */
diff --git a/tests/deckard/contrib/libfaketime/src/libfaketime.map b/tests/deckard/contrib/libfaketime/src/libfaketime.map
new file mode 100644
index 0000000..eb873e7
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/libfaketime.map
@@ -0,0 +1,21 @@
+GLIBC_2.2 {
+ global:
+
+ timer_gettime; timer_settime;
+ local: timer_settime_*; timer_gettime_*;
+};
+
+GLIBC_2.3.3 {
+ # Changed timer_t.
+ timer_gettime; timer_settime;
+} GLIBC_2.2;
+
+GLIBC_2.2.5 {
+ global: pthread_cond_timedwait;
+ local: pthread_cond_timedwait_*; pthread_cond_init_*; pthread_cond_destroy*;
+};
+
+GLIBC_2.3.2 {
+ pthread_cond_timedwait; pthread_cond_init; pthread_cond_destroy;
+} GLIBC_2.2.5;
+
diff --git a/tests/deckard/contrib/libfaketime/src/sunos_endian.h b/tests/deckard/contrib/libfaketime/src/sunos_endian.h
new file mode 100644
index 0000000..b15996a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/sunos_endian.h
@@ -0,0 +1,12 @@
+
+#ifndef SUN_OS_ENDIAN_H
+#define SUN_OS_ENDIAN_H
+
+#include <sys/byteorder.h>
+
+#define htobe64(x) BE_64(x)
+#define be64toh(x) BE_64(x)
+#define htole64(x) LE_64(x)
+#define le64toh(x) LE_64(x)
+
+#endif /* SUN_OS_ENDIAN_H */ \ No newline at end of file
diff --git a/tests/deckard/contrib/libfaketime/src/time_ops.h b/tests/deckard/contrib/libfaketime/src/time_ops.h
new file mode 100644
index 0000000..59ab1ee
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/time_ops.h
@@ -0,0 +1,104 @@
+/*
+ * Time operation macros based on sys/time.h
+ * Copyright 2013 Balint Reczey <balint@balintreczey.hu>
+ *
+ * This file is part of libfaketime.
+ *
+ * libfaketime is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License v2 as published by the Free
+ * Software Foundation.
+ *
+ * libfaketime is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License v2 along
+ * with libfaketime; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TIME_OPS_H
+#define TIME_OPS_H
+#include <time.h>
+
+#define SEC_TO_uSEC 1000000
+#define SEC_TO_nSEC 1000000000
+
+/* Convenience macros for operations on timevals.
+ NOTE: `timercmp' does not work for >= or <=. */
+#define timerisset2(tvp, prefix) ((tvp)->tv_sec || (tvp)->tv_##prefix##sec)
+#define timerclear2(tvp, prefix) ((tvp)->tv_sec = (tvp)->tv_##prefix##sec = 0)
+#define timercmp2(a, b, CMP, prefix) \
+ (((a)->tv_sec == (b)->tv_sec) ? \
+ ((a)->tv_##prefix##sec CMP (b)->tv_##prefix##sec) : \
+ ((a)->tv_sec CMP (b)->tv_sec))
+#define timeradd2(a, b, result, prefix) \
+ do \
+ { \
+ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+ (result)->tv_##prefix##sec = (a)->tv_##prefix##sec + \
+ (b)->tv_##prefix##sec; \
+ if ((result)->tv_##prefix##sec >= SEC_TO_##prefix##SEC) \
+ { \
+ ++(result)->tv_sec; \
+ (result)->tv_##prefix##sec -= SEC_TO_##prefix##SEC; \
+ } \
+ } while (0)
+#define timersub2(a, b, result, prefix) \
+ do \
+ { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_##prefix##sec = (a)->tv_##prefix##sec - \
+ (b)->tv_##prefix##sec; \
+ if ((result)->tv_##prefix##sec < 0) \
+ { \
+ --(result)->tv_sec; \
+ (result)->tv_##prefix##sec += SEC_TO_##prefix##SEC; \
+ } \
+ } while (0)
+#define timermul2(tvp, c, result, prefix) \
+ do \
+ { \
+ long long tmp_time; \
+ tmp_time = (c) * ((tvp)->tv_sec * SEC_TO_##prefix##SEC + \
+ (tvp)->tv_##prefix##sec); \
+ (result)->tv_##prefix##sec = tmp_time % SEC_TO_##prefix##SEC; \
+ (result)->tv_sec = (tmp_time - (result)->tv_##prefix##sec) / \
+ SEC_TO_##prefix##SEC; \
+ if ((result)->tv_##prefix##sec < 0) \
+ { \
+ (result)->tv_##prefix##sec += SEC_TO_##prefix##SEC; \
+ (result)->tv_sec -= 1; \
+ } \
+ } while (0)
+
+/* ops for microsecs */
+#ifndef timerisset
+#define timerisset(tvp) timerisset2(tvp,u)
+#endif
+#ifndef timerclear
+#define timerclear(tvp) timerclear2(tvp, u)
+#endif
+#ifndef timercmp
+#define timercmp(a, b, CMP) timercmp2(a, b, CMP, u)
+#endif
+#ifndef timeradd
+#define timeradd(a, b, result) timeradd2(a, b, result, u)
+#endif
+#ifndef timersub
+#define timersub(a, b, result) timersub2(a, b, result, u)
+#endif
+#ifndef timersub
+#define timermul(a, c, result) timermul2(a, c, result, u)
+#endif
+
+/* ops for nanosecs */
+#define timespecisset(tvp) timerisset2(tvp,n)
+#define timespecclear(tvp) timerclear2(tvp, n)
+#define timespeccmp(a, b, CMP) timercmp2(a, b, CMP, n)
+#define timespecadd(a, b, result) timeradd2(a, b, result, n)
+#define timespecsub(a, b, result) timersub2(a, b, result, n)
+#define timespecmul(a, c, result) timermul2(a, c, result, n)
+
+#endif
diff --git a/tests/deckard/contrib/libfaketime/src/timeprivacy b/tests/deckard/contrib/libfaketime/src/timeprivacy
new file mode 100644
index 0000000..5fd6fd7
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/timeprivacy
@@ -0,0 +1,270 @@
+#!/bin/bash
+
+## Copyright (c) 2013, adrelanos at riseup dot net
+## 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+#set -x
+
+SCRIPTNAME="$(basename $0)"
+
+usage() {
+ echo "$SCRIPTNAME
+
+Usage: $SCRIPTNAME [-h help] [-d day] [-m month] [-y year] [-i increment in seconds (0-60)] [-r random increment in seconds (0-60)] [-f history folder]
+Example: $SCRIPTNAME -d 30 -m 12 -y 2013 -i 10 -f /tmp/$SCRIPTNAMEtest
+ sudo $SCRIPTNAME -d 30 -m 12 -y 2013 -r -f /tmp/$SCRIPTNAMEtest"
+}
+
+_randomincrement="none"
+_increment="none"
+
+while [ -n "$1" ]; do
+ case "$1" in
+ -h)
+ usage
+ exit 0
+ ;;
+ -d)
+ _day="$2"
+ shift
+ ;;
+ -m)
+ _month="$2"
+ shift
+ ;;
+ -y)
+ _year="$2"
+ shift
+ ;;
+ -i)
+ _increment="$2"
+ shift
+ ;;
+ -r)
+ _randomincrement="$2"
+ shift
+ ;;
+ -f)
+ TIMEDIR="$2"
+ shift
+ ;;
+ *)
+ command="$(which $1)"
+ ## From now on the complete to-be wrapped command + its args
+ ## are stored in $@, which will expand like we want it for
+ ## handling quoted arguments with whitespaces in it, etc.
+ break
+ esac
+ shift
+done
+
+if [ -z "$_day" ]; then
+ _day="$(date +"%d")"
+fi
+
+if [ -z "$_month" ]; then
+ _month="$(date +"%m")"
+fi
+
+if [ -z "$_year" ]; then
+ _year="$(date +"%Y")"
+fi
+
+if [ "$_randomincrement" = "none" ] && [ "$_increment" = "none" ]; then
+ _increment="1"
+fi
+
+if [ "$_randomincrement" = "none" ]; then
+ if [ -z "$_increment" ]; then
+ _increment="1"
+ fi
+elif [ "$_increment" = "none" ]; then
+ if [ "$_randomincrement" = "" ]; then
+ echo "randomincrement must be a positive number."
+ exit 1
+ else
+ ## random number between 1 and $_randomincrement
+ random_number="$(( 0+($(od -An -N2 -i /dev/random) )%($_randomincrement-0+1) ))"
+ _increment="$random_number"
+ fi
+else
+ echo "You can not combine -r and -i."
+ exit 1
+fi
+
+if [ -z "$TIMEDIR" ]; then
+ TIMEDIR=~/.timeprivacy
+fi
+
+nodigits="$(echo $_increment | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "increment is not a digit."
+ exit 1
+fi
+
+nodigits="$(echo $_year | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "_day is not a digit."
+ exit 1
+fi
+
+nodigits="$(echo $_year | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "year is not a digit."
+ exit 1
+fi
+
+nodigits="$(echo $_month | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "month is not a digit."
+ exit 1
+fi
+
+nodigits="$(echo $_day | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "day is not a digit."
+ exit 1
+fi
+
+nodigits="$(echo $_increment | sed 's/[[:digit:]]//g')"
+if [ ! -z "$nodigits" ]; then
+ echo "increment is not a digit."
+ exit 1
+fi
+
+SECONDS_FILE="$TIMEDIR/seconds_file"
+MINUTES_FILE="$TIMEDIR/minutes_file"
+HOURS_FILE="$TIMEDIR/hours_file"
+
+#DAYS_FILE="$TIMEDIR/days_file"
+#MONTHS_FILE="$TIMEDIR/months_file"
+#YEARS_FILE="$TIMEDIR/years_file"
+
+#true "TIMEDIR: $TIMEDIR"
+#true "year: $_year"
+#true "month: $_month"
+#true "day: $_day"
+#true "_randomincrement: $_randomincrement"
+#true "_increment: $_increment"
+
+read_date_file() {
+ if [ ! -d "$TIMEDIR" ]; then
+ mkdir -p "$TIMEDIR"
+ fi
+
+ if [ ! -f "$SECONDS_FILE" ]; then
+ echo "0" > "$SECONDS_FILE"
+ fi
+
+ if [ ! -f "$MINUTES_FILE" ]; then
+ echo "0" > "$MINUTES_FILE"
+ fi
+
+ if [ ! -f "$HOURS_FILE" ]; then
+ echo "0" > "$HOURS_FILE"
+ fi
+
+ #if [ ! -f "$DAYS_FILE" ]; then
+ #echo "1" > "$DAYS_FILE"
+ #fi
+
+ #if [ ! -f "$MONTHS_FILE" ]; then
+ #echo "1" > "$MONTHS_FILE"
+ #fi
+
+ #if [ ! -f "$YEARS_FILE" ]; then
+ #echo "2013" > "$YEARS_FILE"
+ #fi
+
+ SECONDS="$(cat "$SECONDS_FILE")"
+ MINUTES="$(cat "$MINUTES_FILE")"
+ HOURS="$(cat "$HOURS_FILE")"
+
+ if [ -z "$SECONDS" ]; then
+ SECONDS="0"
+ fi
+
+ if [ -z "$MINUTES" ]; then
+ MINUTES="0"
+ fi
+
+ if [ -z "$HOURS" ]; then
+ HOURS="0"
+ fi
+
+ local nodigits="$(echo $SECONDS | sed 's/[[:digit:]]//g')"
+ if [ ! -z "$nodigits" ]; then
+ SECONDS="0"
+ fi
+
+ local nodigits="$(echo $MINUTES | sed 's/[[:digit:]]//g')"
+ if [ ! -z "$nodigits" ]; then
+ MINUTES="0"
+ fi
+
+ local nodigits="$(echo $HOURS | sed 's/[[:digit:]]//g')"
+ if [ ! -z "$nodigits" ]; then
+ HOURS="0"
+ fi
+
+ SECONDS="$(expr "$SECONDS" + "$_increment")" || true
+ if [ "$SECONDS" -ge "60" ]; then
+ SECONDS="0"
+
+ MINUTES="$(expr "$MINUTES" + "1")" || true
+ if [ "$MINUTES" -ge "60" ]; then
+ MINUTES="0"
+
+ HOURS="$(expr "$HOURS" + "1")" || true
+ if [ "$HOURS" -ge "24" ]; then
+ HOURS="0"
+ fi
+ echo "$HOURS" > "$HOURS_FILE"
+
+ fi
+ echo "$MINUTES" > "$MINUTES_FILE"
+
+ fi
+
+ echo "$SECONDS" > "$SECONDS_FILE"
+
+ #echo "$HOURS $MINUTES $SECONDS"
+}
+
+need_new_date() {
+ ## Testing
+ #while [ 1 ]; do
+ # read_date_file
+ #done
+
+ read_date_file
+
+ ## Testing
+ #echo "faketime '$_year-$_month-$_day $HOURS:$MINUTES:$SECONDS' /bin/date"
+ #faketime "$_year-$_month-$_day $HOURS:$MINUTES:$SECONDS" /bin/date
+
+ echo "$_year-$_month-$_day $HOURS:$MINUTES:$SECONDS"
+}
+
+need_new_date
+
diff --git a/tests/deckard/contrib/libfaketime/src/uthash.h b/tests/deckard/contrib/libfaketime/src/uthash.h
new file mode 100644
index 0000000..7e64cac
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/src/uthash.h
@@ -0,0 +1,1208 @@
+/*
+Copyright (c) 2003-2017, Troy D. Hanson http://troydhanson.github.com/uthash/
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+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.
+*/
+
+#ifndef UTHASH_H
+#define UTHASH_H
+
+#define UTHASH_VERSION 2.0.2
+
+#include <string.h> /* memcmp, memset, strlen */
+#include <stddef.h> /* ptrdiff_t */
+#include <stdlib.h> /* exit */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+ when compiling c++ source) this code uses whatever method is needed
+ or, for VS2008 where neither is available, uses casting workarounds. */
+#if !defined(DECLTYPE) && !defined(NO_DECLTYPE)
+#if defined(_MSC_VER) /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#endif
+#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
+#define NO_DECLTYPE
+#else /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE(x)
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ char **_da_dst = (char**)(&(dst)); \
+ *_da_dst = (char*)(src); \
+} while (0)
+#else
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ (dst) = DECLTYPE(dst)(src); \
+} while (0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
+#if defined(_WIN32)
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+#include <stdint.h>
+#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
+#include <stdint.h>
+#else
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#endif
+#elif defined(__GNUC__) && !defined(__VXWORKS__)
+#include <stdint.h>
+#else
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#endif
+
+#ifndef uthash_malloc
+#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
+#endif
+#ifndef uthash_free
+#define uthash_free(ptr,sz) free(ptr) /* free fcn */
+#endif
+#ifndef uthash_bzero
+#define uthash_bzero(a,n) memset(a,'\0',n)
+#endif
+#ifndef uthash_memcmp
+#define uthash_memcmp(a,b,n) memcmp(a,b,n)
+#endif
+#ifndef uthash_strlen
+#define uthash_strlen(s) strlen(s)
+#endif
+
+#ifndef uthash_noexpand_fyi
+#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
+#endif
+#ifndef uthash_expand_fyi
+#define uthash_expand_fyi(tbl) /* can be defined to log expands */
+#endif
+
+#ifndef HASH_NONFATAL_OOM
+#define HASH_NONFATAL_OOM 0
+#endif
+
+#if HASH_NONFATAL_OOM
+/* malloc failures can be recovered from */
+
+#ifndef uthash_nonfatal_oom
+#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */
+#endif
+
+#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0)
+#define IF_HASH_NONFATAL_OOM(x) x
+
+#else
+/* malloc failures result in lost memory, hash tables are unusable */
+
+#ifndef uthash_fatal
+#define uthash_fatal(msg) exit(-1) /* fatal OOM error */
+#endif
+
+#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory")
+#define IF_HASH_NONFATAL_OOM(x)
+
+#endif
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhp */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+/* calculate the hash handle from element address elp */
+#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho)))
+
+#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \
+do { \
+ struct UT_hash_handle *_hd_hh_item = (itemptrhh); \
+ unsigned _hd_bkt; \
+ HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
+ (head)->hh.tbl->buckets[_hd_bkt].count++; \
+ _hd_hh_item->hh_next = NULL; \
+ _hd_hh_item->hh_prev = NULL; \
+} while (0)
+
+#define HASH_VALUE(keyptr,keylen,hashv) \
+do { \
+ HASH_FCN(keyptr, keylen, hashv); \
+} while (0)
+
+#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
+do { \
+ (out) = NULL; \
+ if (head) { \
+ unsigned _hf_bkt; \
+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
+ if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \
+ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
+ } \
+ } \
+} while (0)
+
+#define HASH_FIND(hh,head,keyptr,keylen,out) \
+do { \
+ unsigned _hf_hashv; \
+ HASH_VALUE(keyptr, keylen, _hf_hashv); \
+ HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)
+#define HASH_BLOOM_MAKE(tbl,oomed) \
+do { \
+ (tbl)->bloom_nbits = HASH_BLOOM; \
+ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
+ if (!(tbl)->bloom_bv) { \
+ HASH_RECORD_OOM(oomed); \
+ } else { \
+ uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
+ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
+ } \
+} while (0)
+
+#define HASH_BLOOM_FREE(tbl) \
+do { \
+ uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
+} while (0)
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
+
+#define HASH_BLOOM_ADD(tbl,hashv) \
+ HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
+
+#define HASH_BLOOM_TEST(tbl,hashv) \
+ HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl,oomed)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#define HASH_BLOOM_BYTELEN 0U
+#endif
+
+#define HASH_MAKE_TABLE(hh,head,oomed) \
+do { \
+ (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \
+ if (!(head)->hh.tbl) { \
+ HASH_RECORD_OOM(oomed); \
+ } else { \
+ uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \
+ (head)->hh.tbl->tail = &((head)->hh); \
+ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
+ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
+ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
+ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
+ HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
+ (head)->hh.tbl->signature = HASH_SIGNATURE; \
+ if (!(head)->hh.tbl->buckets) { \
+ HASH_RECORD_OOM(oomed); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ } else { \
+ uthash_bzero((head)->hh.tbl->buckets, \
+ HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
+ HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \
+ IF_HASH_NONFATAL_OOM( \
+ if (oomed) { \
+ uthash_free((head)->hh.tbl->buckets, \
+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ } \
+ ) \
+ } \
+ } \
+} while (0)
+
+#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \
+do { \
+ (replaced) = NULL; \
+ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \
+ if (replaced) { \
+ HASH_DELETE(hh, head, replaced); \
+ } \
+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \
+} while (0)
+
+#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \
+do { \
+ (replaced) = NULL; \
+ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \
+ if (replaced) { \
+ HASH_DELETE(hh, head, replaced); \
+ } \
+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \
+} while (0)
+
+#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
+do { \
+ unsigned _hr_hashv; \
+ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \
+ HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \
+} while (0)
+
+#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \
+do { \
+ unsigned _hr_hashv; \
+ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \
+ HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \
+} while (0)
+
+#define HASH_APPEND_LIST(hh, head, add) \
+do { \
+ (add)->hh.next = NULL; \
+ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
+ (head)->hh.tbl->tail->next = (add); \
+ (head)->hh.tbl->tail = &((add)->hh); \
+} while (0)
+
+#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \
+do { \
+ do { \
+ if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \
+ break; \
+ } \
+ } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \
+} while (0)
+
+#ifdef NO_DECLTYPE
+#undef HASH_AKBI_INNER_LOOP
+#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \
+do { \
+ char *_hs_saved_head = (char*)(head); \
+ do { \
+ DECLTYPE_ASSIGN(head, _hs_iter); \
+ if (cmpfcn(head, add) > 0) { \
+ DECLTYPE_ASSIGN(head, _hs_saved_head); \
+ break; \
+ } \
+ DECLTYPE_ASSIGN(head, _hs_saved_head); \
+ } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \
+} while (0)
+#endif
+
+#if HASH_NONFATAL_OOM
+
+#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \
+do { \
+ if (!(oomed)) { \
+ unsigned _ha_bkt; \
+ (head)->hh.tbl->num_items++; \
+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \
+ if (oomed) { \
+ HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \
+ HASH_DELETE_HH(hh, head, &(add)->hh); \
+ (add)->hh.tbl = NULL; \
+ uthash_nonfatal_oom(add); \
+ } else { \
+ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \
+ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \
+ } \
+ } else { \
+ (add)->hh.tbl = NULL; \
+ uthash_nonfatal_oom(add); \
+ } \
+} while (0)
+
+#else
+
+#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \
+do { \
+ unsigned _ha_bkt; \
+ (head)->hh.tbl->num_items++; \
+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \
+ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \
+ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \
+} while (0)
+
+#endif
+
+
+#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \
+do { \
+ IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
+ (add)->hh.hashv = (hashval); \
+ (add)->hh.key = (char*) (keyptr); \
+ (add)->hh.keylen = (unsigned) (keylen_in); \
+ if (!(head)) { \
+ (add)->hh.next = NULL; \
+ (add)->hh.prev = NULL; \
+ HASH_MAKE_TABLE(hh, add, _ha_oomed); \
+ IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \
+ (head) = (add); \
+ IF_HASH_NONFATAL_OOM( } ) \
+ } else { \
+ void *_hs_iter = (head); \
+ (add)->hh.tbl = (head)->hh.tbl; \
+ HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \
+ if (_hs_iter) { \
+ (add)->hh.next = _hs_iter; \
+ if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \
+ HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \
+ } else { \
+ (head) = (add); \
+ } \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \
+ } else { \
+ HASH_APPEND_LIST(hh, head, add); \
+ } \
+ } \
+ HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \
+ HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \
+} while (0)
+
+#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \
+do { \
+ unsigned _hs_hashv; \
+ HASH_VALUE(keyptr, keylen_in, _hs_hashv); \
+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \
+} while (0)
+
+#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \
+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn)
+
+#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \
+ HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn)
+
+#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \
+do { \
+ IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
+ (add)->hh.hashv = (hashval); \
+ (add)->hh.key = (char*) (keyptr); \
+ (add)->hh.keylen = (unsigned) (keylen_in); \
+ if (!(head)) { \
+ (add)->hh.next = NULL; \
+ (add)->hh.prev = NULL; \
+ HASH_MAKE_TABLE(hh, add, _ha_oomed); \
+ IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \
+ (head) = (add); \
+ IF_HASH_NONFATAL_OOM( } ) \
+ } else { \
+ (add)->hh.tbl = (head)->hh.tbl; \
+ HASH_APPEND_LIST(hh, head, add); \
+ } \
+ HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \
+ HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \
+} while (0)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
+do { \
+ unsigned _ha_hashv; \
+ HASH_VALUE(keyptr, keylen_in, _ha_hashv); \
+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \
+} while (0)
+
+#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \
+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
+ HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)
+
+#define HASH_TO_BKT(hashv,num_bkts,bkt) \
+do { \
+ bkt = ((hashv) & ((num_bkts) - 1U)); \
+} while (0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ * HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr) \
+ HASH_DELETE_HH(hh, head, &(delptr)->hh)
+
+#define HASH_DELETE_HH(hh,head,delptrhh) \
+do { \
+ struct UT_hash_handle *_hd_hh_del = (delptrhh); \
+ if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
+ HASH_BLOOM_FREE((head)->hh.tbl); \
+ uthash_free((head)->hh.tbl->buckets, \
+ (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ (head) = NULL; \
+ } else { \
+ unsigned _hd_bkt; \
+ if (_hd_hh_del == (head)->hh.tbl->tail) { \
+ (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \
+ } \
+ if (_hd_hh_del->prev != NULL) { \
+ HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \
+ } else { \
+ DECLTYPE_ASSIGN(head, _hd_hh_del->next); \
+ } \
+ if (_hd_hh_del->next != NULL) { \
+ HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \
+ } \
+ HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
+ HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
+ (head)->hh.tbl->num_items--; \
+ } \
+ HASH_FSCK(hh, head, "HASH_DELETE_HH"); \
+} while (0)
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out) \
+ HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add) \
+ HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add)
+#define HASH_REPLACE_STR(head,strfield,add,replaced) \
+ HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced)
+#define HASH_FIND_INT(head,findint,out) \
+ HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add) \
+ HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_REPLACE_INT(head,intfield,add,replaced) \
+ HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
+#define HASH_FIND_PTR(head,findptr,out) \
+ HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add) \
+ HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
+ HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
+#define HASH_DEL(head,delptr) \
+ HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head,where) \
+do { \
+ struct UT_hash_handle *_thh; \
+ if (head) { \
+ unsigned _bkt_i; \
+ unsigned _count = 0; \
+ char *_prev; \
+ for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \
+ unsigned _bkt_count = 0; \
+ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
+ _prev = NULL; \
+ while (_thh) { \
+ if (_prev != (char*)(_thh->hh_prev)) { \
+ HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \
+ (where), (void*)_thh->hh_prev, (void*)_prev); \
+ } \
+ _bkt_count++; \
+ _prev = (char*)(_thh); \
+ _thh = _thh->hh_next; \
+ } \
+ _count += _bkt_count; \
+ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
+ HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \
+ (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
+ } \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \
+ (where), (head)->hh.tbl->num_items, _count); \
+ } \
+ _count = 0; \
+ _prev = NULL; \
+ _thh = &(head)->hh; \
+ while (_thh) { \
+ _count++; \
+ if (_prev != (char*)_thh->prev) { \
+ HASH_OOPS("%s: invalid prev %p, actual %p\n", \
+ (where), (void*)_thh->prev, (void*)_prev); \
+ } \
+ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
+ _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("%s: invalid app item count %u, actual %u\n", \
+ (where), (head)->hh.tbl->num_items, _count); \
+ } \
+ } \
+} while (0)
+#else
+#define HASH_FSCK(hh,head,where)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
+do { \
+ unsigned _klen = fieldlen; \
+ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
+ write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
+#define HASH_BER(key,keylen,hashv) \
+do { \
+ unsigned _hb_keylen = (unsigned)keylen; \
+ const unsigned char *_hb_key = (const unsigned char*)(key); \
+ (hashv) = 0; \
+ while (_hb_keylen-- != 0U) { \
+ (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \
+ } \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,hashv) \
+do { \
+ unsigned _sx_i; \
+ const unsigned char *_hs_key = (const unsigned char*)(key); \
+ hashv = 0; \
+ for (_sx_i=0; _sx_i < keylen; _sx_i++) { \
+ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
+ } \
+} while (0)
+/* FNV-1a variation */
+#define HASH_FNV(key,keylen,hashv) \
+do { \
+ unsigned _fn_i; \
+ const unsigned char *_hf_key = (const unsigned char*)(key); \
+ (hashv) = 2166136261U; \
+ for (_fn_i=0; _fn_i < keylen; _fn_i++) { \
+ hashv = hashv ^ _hf_key[_fn_i]; \
+ hashv = hashv * 16777619U; \
+ } \
+} while (0)
+
+#define HASH_OAT(key,keylen,hashv) \
+do { \
+ unsigned _ho_i; \
+ const unsigned char *_ho_key=(const unsigned char*)(key); \
+ hashv = 0; \
+ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
+ hashv += _ho_key[_ho_i]; \
+ hashv += (hashv << 10); \
+ hashv ^= (hashv >> 6); \
+ } \
+ hashv += (hashv << 3); \
+ hashv ^= (hashv >> 11); \
+ hashv += (hashv << 15); \
+} while (0)
+
+#define HASH_JEN_MIX(a,b,c) \
+do { \
+ a -= b; a -= c; a ^= ( c >> 13 ); \
+ b -= c; b -= a; b ^= ( a << 8 ); \
+ c -= a; c -= b; c ^= ( b >> 13 ); \
+ a -= b; a -= c; a ^= ( c >> 12 ); \
+ b -= c; b -= a; b ^= ( a << 16 ); \
+ c -= a; c -= b; c ^= ( b >> 5 ); \
+ a -= b; a -= c; a ^= ( c >> 3 ); \
+ b -= c; b -= a; b ^= ( a << 10 ); \
+ c -= a; c -= b; c ^= ( b >> 15 ); \
+} while (0)
+
+#define HASH_JEN(key,keylen,hashv) \
+do { \
+ unsigned _hj_i,_hj_j,_hj_k; \
+ unsigned const char *_hj_key=(unsigned const char*)(key); \
+ hashv = 0xfeedbeefu; \
+ _hj_i = _hj_j = 0x9e3779b9u; \
+ _hj_k = (unsigned)(keylen); \
+ while (_hj_k >= 12U) { \
+ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ + ( (unsigned)_hj_key[2] << 16 ) \
+ + ( (unsigned)_hj_key[3] << 24 ) ); \
+ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ + ( (unsigned)_hj_key[6] << 16 ) \
+ + ( (unsigned)_hj_key[7] << 24 ) ); \
+ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ + ( (unsigned)_hj_key[10] << 16 ) \
+ + ( (unsigned)_hj_key[11] << 24 ) ); \
+ \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+ \
+ _hj_key += 12; \
+ _hj_k -= 12U; \
+ } \
+ hashv += (unsigned)(keylen); \
+ switch ( _hj_k ) { \
+ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \
+ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \
+ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \
+ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \
+ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \
+ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \
+ case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \
+ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
+ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
+ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
+ case 1: _hj_i += _hj_key[0]; \
+ } \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+} while (0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,hashv) \
+do { \
+ unsigned const char *_sfh_key=(unsigned const char*)(key); \
+ uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \
+ \
+ unsigned _sfh_rem = _sfh_len & 3U; \
+ _sfh_len >>= 2; \
+ hashv = 0xcafebabeu; \
+ \
+ /* Main loop */ \
+ for (;_sfh_len > 0U; _sfh_len--) { \
+ hashv += get16bits (_sfh_key); \
+ _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \
+ hashv = (hashv << 16) ^ _sfh_tmp; \
+ _sfh_key += 2U*sizeof (uint16_t); \
+ hashv += hashv >> 11; \
+ } \
+ \
+ /* Handle end cases */ \
+ switch (_sfh_rem) { \
+ case 3: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 16; \
+ hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \
+ hashv += hashv >> 11; \
+ break; \
+ case 2: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 11; \
+ hashv += hashv >> 17; \
+ break; \
+ case 1: hashv += *_sfh_key; \
+ hashv ^= hashv << 10; \
+ hashv += hashv >> 1; \
+ } \
+ \
+ /* Force "avalanching" of final 127 bits */ \
+ hashv ^= hashv << 3; \
+ hashv += hashv >> 5; \
+ hashv ^= hashv << 4; \
+ hashv += hashv >> 17; \
+ hashv ^= hashv << 25; \
+ hashv += hashv >> 6; \
+} while (0)
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ * gcc -m64 -dM -E - < /dev/null (on gcc)
+ * cc -## a.c (where a.c is a simple test file) (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
+#define MUR_GETBLOCK(p,i) p[i]
+#else /* non intel */
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
+#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
+#else /* assume little endian non-intel */
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
+#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
+#endif
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
+ (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
+ (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
+ MUR_ONE_THREE(p))))
+#endif
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+#define MUR_FMIX(_h) \
+do { \
+ _h ^= _h >> 16; \
+ _h *= 0x85ebca6bu; \
+ _h ^= _h >> 13; \
+ _h *= 0xc2b2ae35u; \
+ _h ^= _h >> 16; \
+} while (0)
+
+#define HASH_MUR(key,keylen,hashv) \
+do { \
+ const uint8_t *_mur_data = (const uint8_t*)(key); \
+ const int _mur_nblocks = (int)(keylen) / 4; \
+ uint32_t _mur_h1 = 0xf88D5353u; \
+ uint32_t _mur_c1 = 0xcc9e2d51u; \
+ uint32_t _mur_c2 = 0x1b873593u; \
+ uint32_t _mur_k1 = 0; \
+ const uint8_t *_mur_tail; \
+ const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \
+ int _mur_i; \
+ for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \
+ _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
+ _mur_k1 *= _mur_c1; \
+ _mur_k1 = MUR_ROTL32(_mur_k1,15); \
+ _mur_k1 *= _mur_c2; \
+ \
+ _mur_h1 ^= _mur_k1; \
+ _mur_h1 = MUR_ROTL32(_mur_h1,13); \
+ _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \
+ } \
+ _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \
+ _mur_k1=0; \
+ switch ((keylen) & 3U) { \
+ case 0: break; \
+ case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \
+ case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \
+ case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \
+ _mur_k1 *= _mur_c1; \
+ _mur_k1 = MUR_ROTL32(_mur_k1,15); \
+ _mur_k1 *= _mur_c2; \
+ _mur_h1 ^= _mur_k1; \
+ } \
+ _mur_h1 ^= (uint32_t)(keylen); \
+ MUR_FMIX(_mur_h1); \
+ hashv = _mur_h1; \
+} while (0)
+#endif /* HASH_USING_NO_STRICT_ALIASING */
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \
+do { \
+ if ((head).hh_head != NULL) { \
+ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \
+ } else { \
+ (out) = NULL; \
+ } \
+ while ((out) != NULL) { \
+ if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
+ if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \
+ break; \
+ } \
+ } \
+ if ((out)->hh.hh_next != NULL) { \
+ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \
+ } else { \
+ (out) = NULL; \
+ } \
+ } \
+} while (0)
+
+/* add an item to a bucket */
+#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \
+do { \
+ UT_hash_bucket *_ha_head = &(head); \
+ _ha_head->count++; \
+ (addhh)->hh_next = _ha_head->hh_head; \
+ (addhh)->hh_prev = NULL; \
+ if (_ha_head->hh_head != NULL) { \
+ _ha_head->hh_head->hh_prev = (addhh); \
+ } \
+ _ha_head->hh_head = (addhh); \
+ if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \
+ && !(addhh)->tbl->noexpand) { \
+ HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \
+ IF_HASH_NONFATAL_OOM( \
+ if (oomed) { \
+ HASH_DEL_IN_BKT(head,addhh); \
+ } \
+ ) \
+ } \
+} while (0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(head,delhh) \
+do { \
+ UT_hash_bucket *_hd_head = &(head); \
+ _hd_head->count--; \
+ if (_hd_head->hh_head == (delhh)) { \
+ _hd_head->hh_head = (delhh)->hh_next; \
+ } \
+ if ((delhh)->hh_prev) { \
+ (delhh)->hh_prev->hh_next = (delhh)->hh_next; \
+ } \
+ if ((delhh)->hh_next) { \
+ (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \
+ } \
+} while (0)
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ * ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \
+do { \
+ unsigned _he_bkt; \
+ unsigned _he_bkt_i; \
+ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
+ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
+ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
+ 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
+ if (!_he_new_buckets) { \
+ HASH_RECORD_OOM(oomed); \
+ } else { \
+ uthash_bzero(_he_new_buckets, \
+ 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
+ (tbl)->ideal_chain_maxlen = \
+ ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
+ ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
+ (tbl)->nonideal_items = 0; \
+ for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \
+ _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \
+ while (_he_thh != NULL) { \
+ _he_hh_nxt = _he_thh->hh_next; \
+ HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \
+ _he_newbkt = &(_he_new_buckets[_he_bkt]); \
+ if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \
+ (tbl)->nonideal_items++; \
+ _he_newbkt->expand_mult = _he_newbkt->count / (tbl)->ideal_chain_maxlen; \
+ } \
+ _he_thh->hh_prev = NULL; \
+ _he_thh->hh_next = _he_newbkt->hh_head; \
+ if (_he_newbkt->hh_head != NULL) { \
+ _he_newbkt->hh_head->hh_prev = _he_thh; \
+ } \
+ _he_newbkt->hh_head = _he_thh; \
+ _he_thh = _he_hh_nxt; \
+ } \
+ } \
+ uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
+ (tbl)->num_buckets *= 2U; \
+ (tbl)->log2_num_buckets++; \
+ (tbl)->buckets = _he_new_buckets; \
+ (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \
+ ((tbl)->ineff_expands+1U) : 0U; \
+ if ((tbl)->ineff_expands > 1U) { \
+ (tbl)->noexpand = 1; \
+ uthash_noexpand_fyi(tbl); \
+ } \
+ uthash_expand_fyi(tbl); \
+ } \
+} while (0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn) \
+do { \
+ unsigned _hs_i; \
+ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
+ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
+ if (head != NULL) { \
+ _hs_insize = 1; \
+ _hs_looping = 1; \
+ _hs_list = &((head)->hh); \
+ while (_hs_looping != 0U) { \
+ _hs_p = _hs_list; \
+ _hs_list = NULL; \
+ _hs_tail = NULL; \
+ _hs_nmerges = 0; \
+ while (_hs_p != NULL) { \
+ _hs_nmerges++; \
+ _hs_q = _hs_p; \
+ _hs_psize = 0; \
+ for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \
+ _hs_psize++; \
+ _hs_q = ((_hs_q->next != NULL) ? \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
+ if (_hs_q == NULL) { \
+ break; \
+ } \
+ } \
+ _hs_qsize = _hs_insize; \
+ while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \
+ if (_hs_psize == 0U) { \
+ _hs_e = _hs_q; \
+ _hs_q = ((_hs_q->next != NULL) ? \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
+ _hs_qsize--; \
+ } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \
+ _hs_e = _hs_p; \
+ if (_hs_p != NULL) { \
+ _hs_p = ((_hs_p->next != NULL) ? \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \
+ } \
+ _hs_psize--; \
+ } else if ((cmpfcn( \
+ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \
+ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \
+ )) <= 0) { \
+ _hs_e = _hs_p; \
+ if (_hs_p != NULL) { \
+ _hs_p = ((_hs_p->next != NULL) ? \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \
+ } \
+ _hs_psize--; \
+ } else { \
+ _hs_e = _hs_q; \
+ _hs_q = ((_hs_q->next != NULL) ? \
+ HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \
+ _hs_qsize--; \
+ } \
+ if ( _hs_tail != NULL ) { \
+ _hs_tail->next = ((_hs_e != NULL) ? \
+ ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \
+ } else { \
+ _hs_list = _hs_e; \
+ } \
+ if (_hs_e != NULL) { \
+ _hs_e->prev = ((_hs_tail != NULL) ? \
+ ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \
+ } \
+ _hs_tail = _hs_e; \
+ } \
+ _hs_p = _hs_q; \
+ } \
+ if (_hs_tail != NULL) { \
+ _hs_tail->next = NULL; \
+ } \
+ if (_hs_nmerges <= 1U) { \
+ _hs_looping = 0; \
+ (head)->hh.tbl->tail = _hs_tail; \
+ DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
+ } \
+ _hs_insize *= 2U; \
+ } \
+ HASH_FSCK(hh, head, "HASH_SRT"); \
+ } \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
+do { \
+ unsigned _src_bkt, _dst_bkt; \
+ void *_last_elt = NULL, *_elt; \
+ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
+ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
+ if ((src) != NULL) { \
+ for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
+ for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
+ _src_hh != NULL; \
+ _src_hh = _src_hh->hh_next) { \
+ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
+ if (cond(_elt)) { \
+ IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \
+ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
+ _dst_hh->key = _src_hh->key; \
+ _dst_hh->keylen = _src_hh->keylen; \
+ _dst_hh->hashv = _src_hh->hashv; \
+ _dst_hh->prev = _last_elt; \
+ _dst_hh->next = NULL; \
+ if (_last_elt_hh != NULL) { \
+ _last_elt_hh->next = _elt; \
+ } \
+ if ((dst) == NULL) { \
+ DECLTYPE_ASSIGN(dst, _elt); \
+ HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \
+ IF_HASH_NONFATAL_OOM( \
+ if (_hs_oomed) { \
+ uthash_nonfatal_oom(_elt); \
+ (dst) = NULL; \
+ continue; \
+ } \
+ ) \
+ } else { \
+ _dst_hh->tbl = (dst)->hh_dst.tbl; \
+ } \
+ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
+ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \
+ (dst)->hh_dst.tbl->num_items++; \
+ IF_HASH_NONFATAL_OOM( \
+ if (_hs_oomed) { \
+ HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \
+ HASH_DELETE_HH(hh_dst, dst, _dst_hh); \
+ _dst_hh->tbl = NULL; \
+ uthash_nonfatal_oom(_elt); \
+ continue; \
+ } \
+ ) \
+ HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \
+ _last_elt = _elt; \
+ _last_elt_hh = _dst_hh; \
+ } \
+ } \
+ } \
+ } \
+ HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \
+} while (0)
+
+#define HASH_CLEAR(hh,head) \
+do { \
+ if ((head) != NULL) { \
+ HASH_BLOOM_FREE((head)->hh.tbl); \
+ uthash_free((head)->hh.tbl->buckets, \
+ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ (head) = NULL; \
+ } \
+} while (0)
+
+#define HASH_OVERHEAD(hh,head) \
+ (((head) != NULL) ? ( \
+ (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
+ ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
+ sizeof(UT_hash_table) + \
+ (HASH_BLOOM_BYTELEN))) : 0U)
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp) \
+for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \
+ (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))
+#else
+#define HASH_ITER(hh,head,el,tmp) \
+for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \
+ (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)
+
+typedef struct UT_hash_bucket {
+ struct UT_hash_handle *hh_head;
+ unsigned count;
+
+ /* expand_mult is normally set to 0. In this situation, the max chain length
+ * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+ * the bucket's chain exceeds this length, bucket expansion is triggered).
+ * However, setting expand_mult to a non-zero value delays bucket expansion
+ * (that would be triggered by additions to this particular bucket)
+ * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+ * (The multiplier is simply expand_mult+1). The whole idea of this
+ * multiplier is to reduce bucket expansions, since they are expensive, in
+ * situations where we know that a particular bucket tends to be overused.
+ * It is better to let its chain length grow to a longer yet-still-bounded
+ * value, than to do an O(n) bucket expansion too often.
+ */
+ unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1u
+#define HASH_BLOOM_SIGNATURE 0xb12220f2u
+
+typedef struct UT_hash_table {
+ UT_hash_bucket *buckets;
+ unsigned num_buckets, log2_num_buckets;
+ unsigned num_items;
+ struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
+ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+ /* in an ideal situation (all buckets used equally), no bucket would have
+ * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+ unsigned ideal_chain_maxlen;
+
+ /* nonideal_items is the number of items in the hash whose chain position
+ * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+ * hash distribution; reaching them in a chain traversal takes >ideal steps */
+ unsigned nonideal_items;
+
+ /* ineffective expands occur when a bucket doubling was performed, but
+ * afterward, more than half the items in the hash had nonideal chain
+ * positions. If this happens on two consecutive expansions we inhibit any
+ * further expansion, as it's not helping; this happens when the hash
+ * function isn't a good fit for the key domain. When expansion is inhibited
+ * the hash will still work, albeit no longer in constant time. */
+ unsigned ineff_expands, noexpand;
+
+ uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+ uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+ uint8_t *bloom_bv;
+ uint8_t bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+ struct UT_hash_table *tbl;
+ void *prev; /* prev element in app order */
+ void *next; /* next element in app order */
+ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
+ struct UT_hash_handle *hh_next; /* next hh in bucket order */
+ void *key; /* ptr to enclosing struct's key */
+ unsigned keylen; /* enclosing struct's key len */
+ unsigned hashv; /* result of hash-fcn(key) */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
diff --git a/tests/deckard/contrib/libfaketime/test/Makefile b/tests/deckard/contrib/libfaketime/test/Makefile
new file mode 100644
index 0000000..94d1a2e
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/Makefile
@@ -0,0 +1,31 @@
+CC = gcc
+
+CFLAGS = -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra
+LDFLAGS = -lrt -lpthread
+
+SRC = timetest.c
+OBJ = ${SRC:.c=.o}
+
+all: timetest test
+
+.c.o:
+ ${CC} -c ${CFLAGS} $<
+
+timetest: ${OBJ}
+ ${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+test: timetest functest
+ @echo
+ @./test.sh
+
+# run functional tests
+functest:
+ ./testframe.sh functests
+
+clean:
+ @rm -f ${OBJ} timetest
+
+distclean: clean
+ @echo
+
+.PHONY: all test clean distclean
diff --git a/tests/deckard/contrib/libfaketime/test/Makefile.OSX b/tests/deckard/contrib/libfaketime/test/Makefile.OSX
new file mode 100644
index 0000000..209d19f
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/Makefile.OSX
@@ -0,0 +1,30 @@
+CC ?= clang
+
+CFLAGS += -std=gnu99 -Wall -DFAKE_STAT
+
+SRC = timetest.c
+OBJ = ${SRC:.c=.o}
+
+all: timetest test
+
+.c.o:
+ ${CC} -c ${CFLAGS} $<
+
+timetest: ${OBJ}
+ ${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+test: timetest functest
+ @echo
+ @./test_OSX.sh
+
+# run functional tests
+functest:
+ ./testframe.sh functests
+
+clean:
+ @rm -f ${OBJ} timetest
+
+distclean: clean
+ @echo
+
+.PHONY: all test clean distclean
diff --git a/tests/deckard/contrib/libfaketime/test/README-testframe.txt b/tests/deckard/contrib/libfaketime/test/README-testframe.txt
new file mode 100644
index 0000000..d6980c3
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/README-testframe.txt
@@ -0,0 +1,39 @@
+# here's how the testframe script works.
+#
+# Usage for testing:
+# usage: testframe.sh DIR
+# testframe.sh runs each testsuite script found within DIR.
+# (in the context of libfaketime, the DIR is functest.)
+# exits with status 0 if all tests succeed.
+#
+# Interface:
+# by convention, each testsuite script (within DIR) must be
+# a bash script named test_*.sh. the script must define a
+# function named "run". run takes no arguments. run is
+# expected to call the framework-provided function
+# run_testcase once for each test function. run_testcase
+# uses the global vars NFAIL and NSUCC to keep track of how
+# many testcases failed/succeeded.
+#
+# the test function is expected to call something like
+# asserteq or assertneq (again, framework-provided).
+#
+# fine print: for each testsuite, the framework creates a
+# subshell and dots in the script. also dotted in are
+# testframe.inc and DIR/common.inc (if it exists). the
+# testsuite script can make use of any functions defined
+# in these inc files. the environment variable
+# TESTSUITE_NAME is set to the filename of the testsuite
+# script, for possible use in warning or info messages.
+#
+# see functests/test_true.sh for a simple example of
+# a test suite script.
+#
+# Simple steps to add a new testsuite:
+# 1. decide its name - eg, XXX.
+# 2. choose a DIR of similar testsuites to put it in, or create a new one.
+# 3. create DIR/test_XXX.sh.
+# 4. write a run function and testcase functions in DIR/test_XXX.sh.
+# 5. within the run function, call run_testcase for each testcase function.
+# 6. within each testcase function, call assertneq or asserteq, or do
+# the equivalent.
diff --git a/tests/deckard/contrib/libfaketime/test/functests/common.inc b/tests/deckard/contrib/libfaketime/test/functests/common.inc
new file mode 100644
index 0000000..d184ae2
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/common.inc
@@ -0,0 +1,63 @@
+# libfaketime-specific common support routines for tests
+
+# say which *_fakecmd wrapper to use
+platform()
+{
+ # may want to expand the pattern for linuxlike
+ typeset out=$(uname)
+ case "$out" in
+ *Darwin*) echo "mac" ;;
+ *Linux*) echo "linuxlike" ;;
+ GNU|GNU/kFreeBSD) echo "linuxlike" ;;
+ *SunOS*) echo "sunos" ;;
+ *) echo 1>&2 unsupported platform, uname=\"$out\" ;;
+ esac
+}
+
+# run faked command on a mac
+# UNTESTED
+mac_fakecmd()
+{
+ typeset timestring="$1"; shift
+ typeset fakelib=../src/libfaketime.1.dylib
+ export DYLD_INSERT_LIBRARIES=$fakelib
+ export DYLD_FORCE_FLAT_NAMESPACE=1
+ FAKETIME="$timestring" \
+ "$@"
+}
+
+sunos_fakecmd()
+{
+ typeset timestring="$1"; shift
+ typeset fakelib=../src/libfaketime.so.1
+ export LD_PRELOAD=$fakelib
+ FAKETIME="$timestring" \
+ "$@"
+}
+
+# run faked command on linuxlike OS
+linuxlike_fakecmd()
+{
+ typeset timestring="$1"; shift
+ typeset fakelib=../src/libfaketime.so.1
+ export LD_PRELOAD=$fakelib
+ FAKETIME="$timestring" \
+ "$@"
+}
+
+# run a command with libfaketime using the given timestring
+fakecmd()
+{
+ ${PLATFORM}_fakecmd "$@"
+}
+
+# generate a sequence of numbers from a to b
+range()
+{
+ typeset a=$1 b=$2
+ typeset i=$a
+ while ((i <= b)); do
+ echo $i
+ ((i = i+1))
+ done
+}
diff --git a/tests/deckard/contrib/libfaketime/test/functests/dont_test_false.sh b/tests/deckard/contrib/libfaketime/test/functests/dont_test_false.sh
new file mode 100644
index 0000000..65457ef
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/dont_test_false.sh
@@ -0,0 +1,6 @@
+# a testsuite that will force failure - for testing purposes
+
+run()
+{
+ run_testcase false
+}
diff --git a/tests/deckard/contrib/libfaketime/test/functests/test_exclude_mono.sh b/tests/deckard/contrib/libfaketime/test/functests/test_exclude_mono.sh
new file mode 100644
index 0000000..f68fc20
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/test_exclude_mono.sh
@@ -0,0 +1,87 @@
+# Checks that setting DONT_FAKE_MONOTONIC actually prevent
+# libfaketime from faking monotonic clocks.
+#
+# We do this by freezing time at a specific and arbitrary date with faketime,
+# and making sure that if we set DONT_FAKE_MONOTONIC to 1, calling
+# clock_gettime(CLOCK_MONOTONIC) returns two different values.
+#
+# We also make sure that if we don't set DONT_FAKE_MONOTONIC to 1, in other
+# words when we use the default behavior, two subsequent calls to
+# clock_gettime(CLOCK_MONOTONIC) do return different values.
+
+init()
+{
+ typeset testsuite="$1"
+ PLATFORM=$(platform)
+ if [ -z "$PLATFORM" ]; then
+ echo "$testsuite: unknown platform! quitting"
+ return 1
+ fi
+ echo "# PLATFORM=$PLATFORM"
+ return 0
+}
+
+run()
+{
+ init
+
+ run_testcase dont_fake_mono
+ run_testcase fake_mono
+}
+
+get_token()
+{
+ string=$1
+ token_index=$2
+ separator=$3
+
+ echo $string | cut -d "$separator" -f $token_index
+}
+
+assert_timestamps_neq()
+{
+ timestamps=$1
+ msg=$2
+
+ first_timestamp=$(get_token "${timestamps}" 1 ' ')
+ second_timestamp=$(get_token "${timestamps}" 2 ' ')
+
+ assertneq "${first_timestamp}" "${second_timestamp}" "${msg}"
+}
+
+assert_timestamps_eq()
+{
+ timestamps=$1
+ msg=$2
+
+ first_timestamp=$(get_token "${timestamps}" 1 ' ')
+ second_timestamp=$(get_token "${timestamps}" 2 ' ')
+
+ asserteq "${first_timestamp}" "${second_timestamp}" "${msg}"
+}
+
+get_monotonic_time()
+{
+ dont_fake_mono=$1; shift;
+ clock_id=$1; shift;
+ DONT_FAKE_MONOTONIC=${dont_fake_mono} fakecmd "2014-07-21 09:00:00" \
+ /bin/bash -c "for i in 1 2; do \
+ perl -w -MTime::HiRes=clock_gettime,${clock_id} -E \
+ 'say clock_gettime(${clock_id})'; \
+ sleep 1; \
+ done"
+}
+
+dont_fake_mono()
+{
+ timestamps=$(get_monotonic_time 1 CLOCK_MONOTONIC)
+ msg="When not faking monotonic time, timestamps should be different"
+ assert_timestamps_neq "${timestamps}" "${msg}"
+}
+
+fake_mono()
+{
+ timestamps=$(get_monotonic_time 0 CLOCK_MONOTONIC)
+ msg="When faking monotonic, timestamps should be equal"
+ assert_timestamps_eq "${timestamps}" "${msg}"
+}
diff --git a/tests/deckard/contrib/libfaketime/test/functests/test_null.sh b/tests/deckard/contrib/libfaketime/test/functests/test_null.sh
new file mode 100644
index 0000000..09e7560
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/test_null.sh
@@ -0,0 +1,13 @@
+# check that the date doesn't happen to be 0.
+
+run()
+{
+ run_testcase nulltest
+}
+
+nulltest()
+{
+ typeset tdate=${I2DATES[0]}
+
+ assertneq 0 "$(date +%s)" "($tdate)"
+}
diff --git a/tests/deckard/contrib/libfaketime/test/functests/test_true.sh b/tests/deckard/contrib/libfaketime/test/functests/test_true.sh
new file mode 100644
index 0000000..0025bcf
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/test_true.sh
@@ -0,0 +1,7 @@
+# test suite that always succeeds - for testing framework
+
+run()
+{
+ run_testcase true
+ return 0
+}
diff --git a/tests/deckard/contrib/libfaketime/test/functests/test_walkone.sh b/tests/deckard/contrib/libfaketime/test/functests/test_walkone.sh
new file mode 100755
index 0000000..b27df9a
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/functests/test_walkone.sh
@@ -0,0 +1,67 @@
+# walking-1 test.
+# sourced in from testframe.sh.
+#
+# this script defines a suite of functional tests
+# that verifies the correct operation of libfaketime
+# with the date command.
+
+run()
+{
+ init
+
+ for i in $(range 0 30); do
+ run_testcase test_with_i $i
+ done
+}
+
+# ----- support routines
+init()
+{
+ typeset testsuite="$1"
+ PLATFORM=$(platform)
+ if [ -z "$PLATFORM" ]; then
+ echo "$testsuite: unknown platform! quitting"
+ return 1
+ fi
+ echo "# PLATFORM=$PLATFORM"
+ return 0
+}
+
+
+# run date cmd under faketime, print time in secs
+fakedate()
+{
+ #
+ # let the time format be raw seconds since Epoch
+ # for both input to libfaketime, and output of the date cmd.
+ #
+ typeset fmt='%s'
+ export FAKETIME_FMT=$fmt
+ fakecmd "$1" date +$fmt
+}
+
+#
+# compute x**n.
+# use only the shell, in case we need to run on machines
+# without bc, dc, perl, etc.
+#
+pow()
+{
+ typeset x="$1" n="$2"
+ typeset r=1
+ typeset i=0
+ while ((i < n)); do
+ ((r = r*x))
+ ((i++))
+ done
+ echo $r
+}
+
+# run a fakedate test with a given time t
+test_with_i()
+{
+ typeset i="$1"
+ typeset t=$(pow 2 $i)
+
+ asserteq $(fakedate $t) $t "(secs since Epoch)"
+}
diff --git a/tests/deckard/contrib/libfaketime/test/test.sh b/tests/deckard/contrib/libfaketime/test/test.sh
new file mode 100755
index 0000000..630cec6
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/test.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+if [ -f /etc/faketimerc ] ; then
+ echo "Running the test program with your system-wide default in /etc/faketimerc"
+ echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
+ LD_PRELOAD=../src/libfaketime.so.1 ./timetest
+ echo
+else
+ echo "Running the test program with no faked time specified"
+ echo "\$ LD_PRELOAD=../src/libfaketime.so.1 ./timetest"
+ LD_PRELOAD=../src/libfaketime.so.1 ./timetest
+ echo
+fi
+
+echo "============================================================================="
+echo
+
+echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
+echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="2003-01-01 10:00:05" ./timetest
+echo
+
+echo "============================================================================="
+echo
+
+echo "Running the test program with START date @2005-03-29 14:14:14 specified"
+echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="@2005-03-29 14:14:14" ./timetest
+echo
+
+echo "============================================================================="
+echo
+
+echo "Running the test program with 10 days negative offset specified"
+echo "LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" ./timetest"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" ./timetest
+echo
+
+echo "============================================================================="
+echo
+
+echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
+echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
+echo
+
+echo "============================================================================="
+echo
+
+echo "Running the test program with 10 days positive offset specified, and sped up 2 times"
+echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"+10d x2\" ./timetest"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="+10d x2" NO_FAKE_STAT=1 ./timetest
+echo
+
+echo "============================================================================="
+echo
+
+echo "Running the 'date' command with 15 days negative offset specified"
+echo "\$ LD_PRELOAD=../src/libfaketime.so.1 FAKETIME=\"-15d\" date"
+LD_PRELOAD=../src/libfaketime.so.1 FAKETIME="-15d" date
+echo
+
+echo "============================================================================="
+echo "Testing finished."
+
+exit 0
diff --git a/tests/deckard/contrib/libfaketime/test/test_OSX.sh b/tests/deckard/contrib/libfaketime/test/test_OSX.sh
new file mode 100755
index 0000000..a259275
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/test_OSX.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+export DYLD_FORCE_FLAT_NAMESPACE=1
+export DYLD_INSERT_LIBRARIES=../src/libfaketime.1.dylib
+
+if [ -f /etc/faketimerc ] ; then
+ echo "Running the test program with your system-wide default in /etc/faketimerc"
+ ./timetest
+ echo
+else
+ echo "Running the test program with no faked time specified"
+ ./timetest
+ echo
+fi
+
+echo "Running the test program with absolute date 2003-01-01 10:00:05 specified"
+echo "FAKETIME=\"2003-01-01 10:00:05\" ./timetest"
+FAKETIME="2003-01-01 10:00:05" ./timetest
+echo
+
+echo "Running the test program with START date @2005-03-29 14:14:14 specified"
+echo "FAKETIME=\"@2005-03-29 14:14:14\" ./timetest"
+FAKETIME="@2005-03-29 14:14:14" ./timetest
+echo
+
+echo "Running the test program with 10 days negative offset specified"
+echo "FAKETIME=\"-10d\" ./timetest"
+FAKETIME="-10d" ./timetest
+echo
+
+echo "Running the test program with 10 days negative offset specified, and FAKE_STAT disabled"
+echo "FAKETIME=\"-10d\" NO_FAKE_STAT=1 ./timetest"
+FAKETIME="-10d" NO_FAKE_STAT=1 ./timetest
+echo
+
+echo "Running the test program with 10 days positive offset specified, and sped up 2 times"
+echo "FAKETIME=\"+10d x2\" ./timetest"
+FAKETIME="+10d x2" NO_FAKE_STAT=1 ./timetest
+echo
+
+echo "Running the 'date' command with 15 days negative offset specified"
+echo "FAKETIME=\"-15d\" date"
+FAKETIME="-15d" date
+echo
+
+exit 0
diff --git a/tests/deckard/contrib/libfaketime/test/testframe.inc b/tests/deckard/contrib/libfaketime/test/testframe.inc
new file mode 100644
index 0000000..b5f66a3
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/testframe.inc
@@ -0,0 +1,55 @@
+# framework common functions for use in test suites and test cases
+
+#
+# run a test and keep stats on success/failure.
+# arguments: a command, possibly a shell function.
+# return value: 0 on success, 1 on failure.
+# side effects: increments global var NSUCC on success, NFAIL on failure.
+#
+run_testcase()
+{
+ if "$@"; then
+ ((NSUCC++))
+ return 0
+ else
+ ((NFAIL++))
+ return 1
+ fi
+}
+
+#
+# verbosely check that the test output matches the expected value.
+# arguments: the test output, the expected value, and a description.
+# return value: 0 on if test output equals expected value; 1 otherwise.
+# side effects: prints a descriptive message.
+#
+asserteq()
+{
+ typeset out="$1" expected="$2" desc="$3"
+ echo -n "out=$out $desc"
+ if [ "$out" = "$expected" ]; then
+ echo " - ok"
+ return 0
+ else
+ echo " expected=$expected - bad"
+ return 1
+ fi
+}
+
+#
+# verbosely check that the test output doesn't match the reference value.
+# return value: 1 on if test output equals expected value; 0 if not equal.
+# side effects: prints descriptive message.
+#
+assertneq()
+{
+ typeset out="$1" ref="$2" desc="$3"
+ echo -n "out=$out $desc"
+ if [ "$out" = "$ref" ]; then
+ echo " ref=$ref - bad"
+ return 1
+ else
+ echo " ref=$ref - ok"
+ return 0
+ fi
+}
diff --git a/tests/deckard/contrib/libfaketime/test/testframe.sh b/tests/deckard/contrib/libfaketime/test/testframe.sh
new file mode 100755
index 0000000..22975b6
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/testframe.sh
@@ -0,0 +1,99 @@
+#! /bin/bash
+# testframe.sh DIR
+# bare-bones testing framework.
+# run the test suites in the given DIR;
+# exit with nonzero status if any of them failed.
+# see README.testframe.txt for details.
+#
+
+# echo labelled error/warning message to stderr
+report()
+{
+ echo $PROG: $* 1>&2
+}
+
+# echo OK or BAD depending on argument (0 or not)
+status_word()
+{
+ if [ "$1" -eq 0 ]; then
+ echo OK
+ else
+ echo BAD
+ fi
+}
+
+# run the given testsuite, return nonzero if any testcase failed.
+run_testsuite()
+{
+ typeset testsuite="$1"
+
+ NFAIL=0
+ NSUCC=0
+
+ # add testsuite dir to PATH for convenience
+ typeset dir=$(dirname $testsuite)
+ PATH=$dir:$PATH
+ . testframe.inc
+ if [ -f $dir/common.inc ]; then
+ . $dir/common.inc
+ fi
+ . $testsuite
+ export TESTSUITE_NAME=$testsuite
+
+ echo ""
+ echo "# Begin $testsuite"
+
+ run
+ typeset runstat=$?
+
+ echo "# $testsuite summary: $NSUCC succeeded, $NFAIL failed"
+ if [ $runstat -ne 0 ]; then
+ ((NFAIL++))
+ report "error: $testsuite run exit_status=$runstat!"
+ fi
+ echo "# End $testsuite -" $(status_word $NFAIL)
+ [ $NFAIL -eq 0 ]
+}
+
+#
+# list all testsuite scripts in the given directories.
+# a testsuite file must be a bash script whose name is of the form test_*.sh .
+#
+list_testsuites()
+{
+ for dir in "$@"; do
+ ls $dir/test_*.sh 2>/dev/null
+ done
+}
+
+main()
+{
+ TS_NFAIL=0
+ TS_NSUCC=0
+
+ echo "# Begin Test Suites in $*"
+ typeset testsuites=$(list_testsuites "$@")
+
+ if [ -z "$testsuites" ]; then
+ report "error: no testsuites found"
+ exit 1
+ fi
+
+ for testsuite in $testsuites; do
+ if run_testsuite $testsuite; then
+ ((TS_NSUCC++))
+ else
+ ((TS_NFAIL++))
+ fi
+ done
+
+ echo ""
+ echo "# Test Suites summary: $TS_NSUCC succeeded, $TS_NFAIL failed"
+ echo "# End Test Suites -" $(status_word $TS_NFAIL)
+ [ $TS_NFAIL -eq 0 ]
+}
+
+# ----- start of mainline code
+PROG=${0##*/}
+
+main "${@:-.}"
diff --git a/tests/deckard/contrib/libfaketime/test/timetest.c b/tests/deckard/contrib/libfaketime/test/timetest.c
new file mode 100644
index 0000000..4e3515c
--- /dev/null
+++ b/tests/deckard/contrib/libfaketime/test/timetest.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2003,2007 Wolfgang Hommel
+ *
+ * This file is part of the FakeTime Preload Library.
+ *
+ * The FakeTime Preload Library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The FakeTime Preload Library is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the FakeTime Preload Library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+
+#ifdef FAKE_STAT
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
+#ifndef __APPLE__
+#include <pthread.h>
+#include <errno.h>
+#include <signal.h>
+
+#define VERBOSE 0
+
+#define SIG SIGUSR1
+
+static void
+handler(int sig, siginfo_t *si, void *uc)
+{
+ /* Note: calling printf() from a signal handler is not
+ strictly correct, since printf() is not async-signal-safe;
+ see signal(7) */
+
+ if ((si == NULL) || (si != uc))
+ {
+ printf("Caught signal %d\n", sig);
+ }
+}
+
+void* pthread_test(void* args)
+{
+ pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;
+
+ pthread_cond_t monotonic_cond;
+ pthread_condattr_t attr;
+
+ struct timespec timeToWait, now;
+ int rt;
+
+ args = args; // silence compiler warning about unused argument
+
+ clock_gettime(CLOCK_REALTIME, &now);
+ timeToWait.tv_sec = now.tv_sec+1;
+ timeToWait.tv_nsec = now.tv_nsec;
+
+ printf("pthread_cond_timedwait: CLOCK_REALTIME test\n");
+ printf("(Intentionally sleeping 1 second...)\n");
+ fflush(stdout);
+
+ pthread_mutex_lock(&fakeMutex);
+ rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
+ if (rt != ETIMEDOUT)
+ {
+ printf("pthread_cond_timedwait failed\n");
+ exit(EXIT_FAILURE);
+ }
+ pthread_mutex_unlock(&fakeMutex);
+
+
+ pthread_condattr_init(&attr);
+ pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+ pthread_cond_init(&monotonic_cond, &attr);
+
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ timeToWait.tv_sec = now.tv_sec+1;
+ timeToWait.tv_nsec = now.tv_nsec;
+
+ printf("pthread_cond_timedwait: CLOCK_MONOTONIC test\n");
+ printf("(Intentionally sleeping 1 second...)\n");
+ fflush(stdout);
+
+ pthread_mutex_lock(&fakeMutex);
+ rt = pthread_cond_timedwait(&monotonic_cond, &fakeMutex, &timeToWait);
+ if (rt != ETIMEDOUT)
+ {
+ printf("pthread_cond_timedwait failed\n");
+ exit(EXIT_FAILURE);
+ }
+ pthread_mutex_unlock(&fakeMutex);
+
+ pthread_cond_destroy(&monotonic_cond);
+
+ return NULL;
+}
+
+#endif
+
+int main (int argc, char **argv)
+{
+ time_t now;
+ struct timeb tb;
+ struct timeval tv;
+#ifndef __APPLE__
+ struct timespec ts;
+ timer_t timerid1 = 0, timerid2;
+ struct sigevent sev;
+ struct itimerspec its;
+ sigset_t mask;
+ struct sigaction sa;
+#endif
+#ifdef FAKE_STAT
+ struct stat buf;
+#endif
+
+#ifndef __APPLE__
+ pthread_t thread;
+ void *ret;
+
+ pthread_create(&thread, NULL, pthread_test, NULL);
+ pthread_join(thread, &ret);
+
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = handler;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGUSR1, &sa, NULL) == -1)
+ {
+ perror("sigaction");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Block timer signal temporarily */
+ printf("Blocking signal %d\n", SIGUSR1);
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+ if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
+ {
+ perror("sigaction");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create the timer */
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = SIGUSR1;
+ sev.sigev_value.sival_ptr = &timerid1;
+ if (timer_create(CLOCK_REALTIME, &sev, &timerid1) == -1)
+ {
+ perror("timer_create");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Start timer1 */
+
+ /* start timer ticking after one second */
+ its.it_value.tv_sec = 1;
+ its.it_value.tv_nsec = 0;
+ /* fire in every 0.3 seconds */
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 300000000;
+
+ if (timer_settime(timerid1, 0, &its, NULL) == -1)
+ {
+ perror("timer_settime");
+ exit(EXIT_FAILURE);
+ }
+
+ sev.sigev_value.sival_ptr = &timerid2;
+ if (timer_create(CLOCK_REALTIME, &sev, &timerid2) == -1)
+ {
+ perror("timer_create");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Start timer2 */
+
+ clock_gettime(CLOCK_REALTIME, &its.it_value);
+ /* start timer ticking after one second */
+ its.it_value.tv_sec += 3;
+ /* fire once */
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+
+ if (timer_settime(timerid2, TIMER_ABSTIME, &its, NULL) == -1)
+ {
+ perror("timer_settime");
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ time(&now);
+ printf("time() : Current date and time: %s", ctime(&now));
+ printf("time(NULL) : Seconds since Epoch : %u\n", (unsigned int)time(NULL));
+
+ ftime(&tb);
+ printf("ftime() : Current date and time: %s", ctime(&tb.time));
+
+ printf("(Intentionally sleeping 2 seconds...)\n");
+ fflush(stdout);
+ if (argc < 3)
+ {
+ sleep(1);
+ usleep(1000000);
+ }
+
+ gettimeofday(&tv, NULL);
+ printf("gettimeofday() : Current date and time: %s", ctime(&tv.tv_sec));
+
+#ifndef __APPLE__
+ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
+ {
+ perror("sigprocmask");
+ exit(EXIT_FAILURE);
+ }
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ printf("clock_gettime(): Current date and time: %s", ctime(&ts.tv_sec));
+
+ int timer_getoverrun_timerid1 = timer_getoverrun(timerid1);
+ if (timer_getoverrun_timerid1 != 3)
+ {
+ printf("timer_getoverrun(timerid1) FAILED, must be 3 but got: %d\n", timer_getoverrun_timerid1);
+ }
+
+ timer_gettime(timerid1, &its);
+ if (VERBOSE == 1)
+ {
+ printf("timer_gettime(timerid1, &its); its = {{%ld, %ld}, {%ld, %ld}}}\n",
+ (long)its.it_interval.tv_sec, (long)its.it_interval.tv_nsec,
+ (long)its.it_value.tv_sec, (long)its.it_value.tv_nsec);
+ }
+
+ int timer_getoverrun_timerid2 = timer_getoverrun(timerid2);
+ if (timer_getoverrun_timerid2 != 0)
+ {
+ printf("timer_getoverrun(timerid2) FAILED, must be 0 but got: %d\n", timer_getoverrun_timerid2);
+ }
+
+ timer_gettime(timerid2, &its);
+ if (VERBOSE == 1)
+ {
+ printf("timer_gettime(timerid2, &its); its = {{%ld, %ld}, {%ld, %ld}}}\n",
+ (long)its.it_interval.tv_sec, (long)its.it_interval.tv_nsec,
+ (long)its.it_value.tv_sec, (long)its.it_value.tv_nsec);
+ }
+#endif
+
+#ifdef FAKE_STAT
+ lstat(argv[0], &buf);
+ printf("stat(): mod. time of file '%s': %s", argv[0], ctime(&buf.st_mtime));
+#endif
+
+ return 0;
+}
+
+/*
+ * Editor modelines
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 2
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=2 expandtab:
+ * :indentSize=2:tabSize=2:noTabs=true:
+ */
+
+/* eof */
diff --git a/tests/deckard/contrib/libswrap/.gitignore b/tests/deckard/contrib/libswrap/.gitignore
new file mode 100644
index 0000000..5d8f581
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/.gitignore
@@ -0,0 +1,9 @@
+*.a
+*.o
+.*
+*.swp
+*~
+build
+obj
+cscope.*
+tags
diff --git a/tests/deckard/contrib/libswrap/AUTHORS b/tests/deckard/contrib/libswrap/AUTHORS
new file mode 100644
index 0000000..b29dad2
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/AUTHORS
@@ -0,0 +1,3 @@
+Jelmer Vernooij <jelmer@samba.org>
+Stefan Metzmacher <metze@samba.org>
+Andreas Schneider <asn@samba.org>
diff --git a/tests/deckard/contrib/libswrap/CMakeLists.txt b/tests/deckard/contrib/libswrap/CMakeLists.txt
new file mode 100644
index 0000000..4d7c12e
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/CMakeLists.txt
@@ -0,0 +1,86 @@
+project(socket_wrapper C)
+
+# Required cmake version
+cmake_minimum_required(VERSION 2.8.5)
+
+# global needed variables
+set(APPLICATION_NAME ${PROJECT_NAME})
+
+set(APPLICATION_VERSION_MAJOR "1")
+set(APPLICATION_VERSION_MINOR "1")
+set(APPLICATION_VERSION_PATCH "7")
+
+set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
+
+# SOVERSION scheme: CURRENT.AGE.REVISION
+# If there was an incompatible interface change:
+# Increment CURRENT. Set AGE and REVISION to 0
+# If there was a compatible interface change:
+# Increment AGE. Set REVISION to 0
+# If the source code was changed, but there were no interface changes:
+# Increment REVISION.
+set(LIBRARY_VERSION "0.1.7")
+set(LIBRARY_SOVERSION "0")
+
+# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
+set(CMAKE_MODULE_PATH
+ ${CMAKE_SOURCE_DIR}/cmake/Modules
+)
+
+# add definitions
+include(DefineCMakeDefaults)
+include(DefinePlatformDefaults)
+include(DefineCompilerFlags)
+include(DefineInstallationPaths)
+include(DefineOptions.cmake)
+include(CPackConfig.cmake)
+
+# disallow in-source build
+include(MacroEnsureOutOfSourceBuild)
+macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
+
+# Find out if we have threading available
+set(CMAKE_THREAD_PREFER_PTHREADS ON)
+find_package(Threads)
+
+# config.h checks
+include(ConfigureChecks.cmake)
+configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+# check subdirectories
+add_subdirectory(src)
+
+if (UNIT_TESTING)
+ find_package(cmocka 0.4.1 REQUIRED)
+
+ include(AddCMockaTest)
+ add_subdirectory(tests)
+endif (UNIT_TESTING)
+
+# pkg-config file
+get_filename_component(SOCKET_WRAPPER_LIB ${SOCKET_WRAPPER_LOCATION} NAME)
+
+configure_file(socket_wrapper.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper.pc @ONLY)
+install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper.pc
+ DESTINATION
+ ${LIB_INSTALL_DIR}/pkgconfig
+ COMPONENT
+ pkgconfig
+)
+
+# cmake config files
+configure_file(socket_wrapper-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper-config-version.cmake @ONLY)
+configure_file(socket_wrapper-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper-config.cmake @ONLY)
+install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper-config-version.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/socket_wrapper-config.cmake
+ DESTINATION
+ ${CMAKE_INSTALL_DIR}/socket_wrapper
+ COMPONENT
+ devel
+)
+
+add_subdirectory(doc)
diff --git a/tests/deckard/contrib/libswrap/COPYING b/tests/deckard/contrib/libswrap/COPYING
new file mode 100644
index 0000000..e6227e1
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/COPYING
@@ -0,0 +1,32 @@
+Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
+Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
+Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+
+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 author 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 AUTHOR 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 AUTHOR 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.
diff --git a/tests/deckard/contrib/libswrap/CPackConfig.cmake b/tests/deckard/contrib/libswrap/CPackConfig.cmake
new file mode 100644
index 0000000..dc74dfa
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/CPackConfig.cmake
@@ -0,0 +1,53 @@
+# For help take a look at:
+# http://www.cmake.org/Wiki/CMake:CPackConfiguration
+
+### general settings
+set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
+set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
+set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
+set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
+
+
+### versions
+set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}")
+set(CPACK_PACKAGE_VERSION_PATCH "${APPLICATION_VERSION_PATCH}")
+set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
+
+
+### source generator
+set(CPACK_SOURCE_GENERATOR "TGZ")
+set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*")
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
+
+if (WIN32)
+ set(CPACK_GENERATOR "ZIP")
+
+ ### nsis generator
+ find_package(NSIS)
+ if (NSIS_MAKE)
+ set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
+ set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
+ set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
+ set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
+ endif (NSIS_MAKE)
+endif (WIN32)
+
+set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
+
+set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
+
+set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
+set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers")
+set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
+ "Libraries used to build programs which use libssh")
+set(CPACK_COMPONENT_HEADERS_DESCRIPTION
+ "C/C++ header files for use with libssh")
+set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
+#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
+set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
+set(CPACK_COMPONENT_HEADERS_GROUP "Development")
+
+include(CPack)
diff --git a/tests/deckard/contrib/libswrap/CTestConfig.cmake b/tests/deckard/contrib/libswrap/CTestConfig.cmake
new file mode 100644
index 0000000..3c29af3
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/CTestConfig.cmake
@@ -0,0 +1,9 @@
+set(UPDATE_TYPE "true")
+
+set(CTEST_PROJECT_NAME "socketwrapper")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
+
+set(CTEST_DROP_METHOD "https")
+set(CTEST_DROP_SITE "mock.cryptomilk.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=socketwrapper")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/tests/deckard/contrib/libswrap/ChangeLog b/tests/deckard/contrib/libswrap/ChangeLog
new file mode 100644
index 0000000..dd03665
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/ChangeLog
@@ -0,0 +1,60 @@
+ChangeLog
+==========
+
+version 1.1.7 (released 2016-05-20)
+ * Added support for accept4()
+ * Added support for OpenBSD
+ * Fixed sendto() with UDP and a connected socket
+ * Fixed AF_RAWLINK sockets
+
+version 1.1.6 (released 2016-03-15)
+ * Added a wrapper for write()
+ * Added support for automatic binding of ephemeral ports
+ * Fixed recvmsg() with UDP
+ * Fixed AF_NETLINK sockets
+
+version 1.1.5 (released 2015-10-15)
+ * Added support for TCP_NODELAY in setsockopt/getsockopt
+ * Fixed cmsg space calculation
+
+version 1.1.4 (released 2015-08-25)
+ * Fixed handling of msg_name in recvmsg()
+ * Fixed sendmsg()/recvmsg() TCP support
+ * Fixed several compile warnings
+ * Added environment variable to change MTU
+
+version 1.1.3 (released 2015-02-23)
+ * Added support for address sanitizer.
+ * Fixed leaking of memory and fds of stale sockets.
+ * Fixed the library loading code.
+
+version 1.1.2 (released 2014-10-01)
+ * Added support for fnctl(F_DUPFD).
+ * Added support for glibc 2.20.90.
+
+version 1.1.1 (released 2014-06-05)
+ * Disable incomplete address in use check in bind().
+
+version 1.1.0 (released 2014-06-02)
+ * Added support for IP_PKTINFO in recvmsg().
+ * Added support for IPV6_PKTINFO in recvmsg().
+ * Added support for IP_RECVDSTADDR in recvmsg() on BSD.
+ * Added support for more socket options in getsockopt().
+ * Added support for bindresvport().
+ * Fixed rebinding on connect().
+ * Fixed sockaddr buffer truncation in getsockname() and getpeername().
+ * Fixed special cases in bind().
+ * Fixed loading libc on some platforms.
+
+version 1.0.2 (released 2014-05-05)
+ * Fixed memory leaks
+ * Fixed calling open from libc.
+ * Fixed loading libc functions on some platforms.
+
+version 1.0.1 (released 2014-02-04)
+ * Added --libs to pkg-config.
+ * Added socket_wrapper-config.cmake
+ * Fixed a bug packaging the obj directory.
+
+version 1.0.0 (released 2014-02-02)
+ * Initial release
diff --git a/tests/deckard/contrib/libswrap/ConfigureChecks.cmake b/tests/deckard/contrib/libswrap/ConfigureChecks.cmake
new file mode 100644
index 0000000..48455ef
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/ConfigureChecks.cmake
@@ -0,0 +1,232 @@
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckFunctionExists)
+include(CheckLibraryExists)
+include(CheckTypeSize)
+include(CheckStructHasMember)
+include(CheckPrototypeDefinition)
+include(TestBigEndian)
+
+set(PACKAGE ${APPLICATION_NAME})
+set(VERSION ${APPLICATION_VERSION})
+set(DATADIR ${DATA_INSTALL_DIR})
+set(LIBDIR ${LIB_INSTALL_DIR})
+set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
+set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
+
+set(BINARYDIR ${CMAKE_BINARY_DIR})
+set(SOURCEDIR ${CMAKE_SOURCE_DIR})
+
+function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
+ # Remove whitespaces from the argument.
+ # This is needed for CC="ccache gcc" cmake ..
+ string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
+
+ execute_process(
+ COMMAND
+ ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
+ OUTPUT_VARIABLE _COMPILER_VERSION
+ )
+
+ string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
+ _COMPILER_VERSION "${_COMPILER_VERSION}")
+
+ set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
+endfunction()
+
+if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
+ compiler_dumpversion(GNUCC_VERSION)
+ if (NOT GNUCC_VERSION EQUAL 34)
+ set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
+ check_c_source_compiles(
+"void __attribute__((visibility(\"default\"))) test() {}
+int main(void){ return 0; }
+" WITH_VISIBILITY_HIDDEN)
+ set(CMAKE_REQUIRED_FLAGS "")
+ endif (NOT GNUCC_VERSION EQUAL 34)
+endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
+
+# HEADERS
+check_include_file(sys/filio.h HAVE_SYS_FILIO_H)
+check_include_file(sys/signalfd.h HAVE_SYS_SIGNALFD_H)
+check_include_file(sys/eventfd.h HAVE_SYS_EVENTFD_H)
+check_include_file(sys/timerfd.h HAVE_SYS_TIMERFD_H)
+check_include_file(gnu/lib-names.h HAVE_GNU_LIB_NAMES_H)
+check_include_file(rpc/rpc.h HAVE_RPC_RPC_H)
+
+# FUNCTIONS
+check_function_exists(strncpy HAVE_STRNCPY)
+check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(snprintf HAVE_SNPRINTF)
+check_function_exists(signalfd HAVE_SIGNALFD)
+check_function_exists(eventfd HAVE_EVENTFD)
+check_function_exists(timerfd_create HAVE_TIMERFD_CREATE)
+check_function_exists(bindresvport HAVE_BINDRESVPORT)
+check_function_exists(accept4 HAVE_ACCEPT4)
+
+check_function_exists(pledge HAVE_PLEDGE)
+
+
+if (UNIX)
+ if (NOT LINUX)
+ # libsocket (Solaris)
+ check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
+ if (HAVE_LIBSOCKET)
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
+ endif (HAVE_LIBSOCKET)
+
+ # libnsl/inet_pton (Solaris)
+ check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
+ if (HAVE_LIBNSL)
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
+ endif (HAVE_LIBNSL)
+ endif (NOT LINUX)
+
+ check_function_exists(getaddrinfo HAVE_GETADDRINFO)
+endif (UNIX)
+
+set(SWRAP_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "socket_wrapper required system libraries")
+
+# STRUCTS
+check_struct_has_member("struct in_pktinfo" ipi_addr "sys/types.h;sys/socket.h;netinet/in.h" HAVE_STRUCT_IN_PKTINFO)
+set(CMAKE_REQUIRED_FLAGS -D_GNU_SOURCE)
+check_struct_has_member("struct in6_pktinfo" ipi6_addr "sys/types.h;sys/socket.h;netinet/in.h" HAVE_STRUCT_IN6_PKTINFO)
+set(CMAKE_REQUIRED_FLAGS)
+
+# STRUCT MEMBERS
+check_struct_has_member("struct sockaddr" sa_len "sys/types.h;sys/socket.h;netinet/in.h" HAVE_STRUCT_SOCKADDR_SA_LEN)
+check_struct_has_member("struct msghdr" msg_control "sys/types.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+
+# PROTOTYPES
+check_prototype_definition(gettimeofday
+ "int gettimeofday(struct timeval *tv, struct timezone *tz)"
+ "-1"
+ "sys/time.h"
+ HAVE_GETTIMEOFDAY_TZ)
+
+check_prototype_definition(gettimeofday
+ "int gettimeofday(struct timeval *tv, void *tzp)"
+ "-1"
+ "sys/time.h"
+ HAVE_GETTIMEOFDAY_TZ_VOID)
+
+check_prototype_definition(accept
+ "int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)"
+ "-1"
+ "sys/types.h;sys/socket.h"
+ HAVE_ACCEPT_PSOCKLEN_T)
+
+check_prototype_definition(ioctl
+ "int ioctl(int s, int r, ...)"
+ "-1"
+ "unistd.h;sys/ioctl.h"
+ HAVE_IOCTL_INT)
+
+if (HAVE_EVENTFD)
+ check_prototype_definition(eventfd
+ "int eventfd(unsigned int count, int flags)"
+ "-1"
+ "sys/eventfd.h"
+ HAVE_EVENTFD_UNSIGNED_INT)
+endif (HAVE_EVENTFD)
+
+# IPV6
+check_c_source_compiles("
+ #include <stdlib.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ #include <netinet/in.h>
+ #include <net/if.h>
+
+int main(void) {
+ struct sockaddr_storage sa_store;
+ struct addrinfo *ai = NULL;
+ struct in6_addr in6addr;
+ int idx = if_nametoindex(\"iface1\");
+ int s = socket(AF_INET6, SOCK_STREAM, 0);
+ int ret = getaddrinfo(NULL, NULL, NULL, &ai);
+ if (ret != 0) {
+ const char *es = gai_strerror(ret);
+ }
+
+ freeaddrinfo(ai);
+ {
+ int val = 1;
+#ifdef HAVE_LINUX_IPV6_V6ONLY_26
+#define IPV6_V6ONLY 26
+#endif
+ ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const void *)&val, sizeof(val));
+ }
+
+ return 0;
+}" HAVE_IPV6)
+
+check_c_source_compiles("
+#include <sys/socket.h>
+
+int main(void) {
+ struct sockaddr_storage s;
+
+ return 0;
+}" HAVE_SOCKADDR_STORAGE)
+
+check_c_source_compiles("
+void test_destructor_attribute(void) __attribute__ ((destructor));
+
+void test_destructor_attribute(void)
+{
+ return;
+}
+
+int main(void) {
+ return 0;
+}" HAVE_DESTRUCTOR_ATTRIBUTE)
+
+check_c_source_compiles("
+__thread int tls;
+
+int main(void) {
+ return 0;
+}" HAVE_GCC_THREAD_LOCAL_STORAGE)
+
+check_c_source_compiles("
+void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
+
+int main(void) {
+ return 0;
+}" HAVE_FUNCTION_ATTRIBUTE_FORMAT)
+
+# If this produces a warning treat it as error!
+set(CMAKE_REQUIRED_FLAGS "-Werror")
+check_c_source_compiles("
+void test_address_sanitizer_attribute(void) __attribute__((no_sanitize_address));
+
+void test_address_sanitizer_attribute(void)
+{
+ return;
+}
+
+int main(void) {
+ return 0;
+}" HAVE_ADDRESS_SANITIZER_ATTRIBUTE)
+set(CMAKE_REQUIRED_FLAGS)
+
+check_library_exists(dl dlopen "" HAVE_LIBDL)
+if (HAVE_LIBDL)
+ find_library(DLFCN_LIBRARY dl)
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${DLFCN_LIBRARY})
+endif (HAVE_LIBDL)
+
+if (OSX)
+ set(HAVE_APPLE 1)
+endif (OSX)
+
+# ENDIAN
+if (NOT WIN32)
+ test_big_endian(WORDS_BIGENDIAN)
+endif (NOT WIN32)
+
+check_type_size(pid_t SIZEOF_PID_T)
+
+set(SWRAP_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "swrap required system libraries")
diff --git a/tests/deckard/contrib/libswrap/DefineOptions.cmake b/tests/deckard/contrib/libswrap/DefineOptions.cmake
new file mode 100644
index 0000000..6030e79
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/DefineOptions.cmake
@@ -0,0 +1 @@
+option(UNIT_TESTING "Build with unit tests" OFF)
diff --git a/tests/deckard/contrib/libswrap/README b/tests/deckard/contrib/libswrap/README
new file mode 100644
index 0000000..fd08cc4
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/README
@@ -0,0 +1,21 @@
+SOCKET_WRAPPER
+==============
+
+This is a modification of initial socket_wrapper (https://cwrap.org/socket_wrapper.html) library.
+Essence : functionally both libraries are equal. But here implemented some minor changes intended
+to ensure the possibility of using arbitrary IP addresses instead of private-range IP addresses.
+
+DESCRIPTION
+-----------
+
+More details can be found in the manpage:
+
+ man -l ./doc/socket_wrapper.1
+
+or the raw text version:
+
+ less ./doc/socket_wrapper.1.txt
+
+For installation instructions please take a look at the README.install file.
+
+
diff --git a/tests/deckard/contrib/libswrap/README.install b/tests/deckard/contrib/libswrap/README.install
new file mode 100644
index 0000000..6fe012f
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/README.install
@@ -0,0 +1,78 @@
+Obtaining the sources
+=====================
+
+Source tarballs for socket_wrapper can be downloaded from
+
+ https://ftp.samba.org/pub/cwrap/
+
+The source code repository for socket wrapper is located under
+
+ git://git.samba.org/socket_wrapper.git
+
+To create a local copy, run
+
+ $ git clone git://git.samba.org/socket_wrapper.git
+ $ cd socket_wrapper
+
+Building from sources
+=====================
+
+socket_wrapper uses cmake (www.cmake.org) as its build system.
+
+In an unpacked sources base directory, create a directory to
+contain the build results, e.g.
+
+ $ mkdir obj
+ $ cd obj
+
+Note that "obj" is just an example. The directory can
+be named arbitrarily.
+
+Next, run cmake to configure the build, e.g.
+
+ $ cmake -DCMAKE_INSTALL_PREFIX=<prefix> ..
+
+or on a 64 bit red hat system:
+
+ $ cmake -DCMAKE_INSTALL_PREFIX=<prefix> -DLIB_SUFFIX=64 ..
+
+The "<prefix>" should be replaced by the intended installation
+target prefix directory, typically /usr or /usr/local.
+
+Note that the target directory does not have to be a direct
+or indirect subdirectory of the source base directory: It can
+be an arbitrary directory in the system. In the general case,
+".." has to be replaced by a relative or absolute path of the
+source base directory in the "cmake" command line.
+
+One can control the build type with "-DCMAKE_BUILD_TYPE=<mode>"
+where <mode> can be one of Debug, Release, RelWithDebInfo, and
+some more (see cmake.org). The default is "RelWithDebInfo".
+
+After configuring with cmake, run the build with
+
+ $ make
+
+Unit testing
+============
+
+In order to support running the test suite after building,
+the cmocka unit test framework needs to be installed (cmocka.org),
+and you need to specify
+
+ -DUNIT_TESTING=ON
+
+in the cmake run. After running "make",
+
+ $ make test
+
+runs the test suite.
+
+Installing
+==========
+
+socket_wrapper is installed into the prefix directory
+after running "cmake" and "make" with
+
+ $ make install
+
diff --git a/tests/deckard/contrib/libswrap/TODO b/tests/deckard/contrib/libswrap/TODO
new file mode 100644
index 0000000..147c166
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/TODO
@@ -0,0 +1,33 @@
+TODO
+=====
+
+This is the TODO list of this project. It should give you some hints of things
+which need to be implemented. If you can spend some time on this project, then
+look at the list below.
+
+
+Library:
+---------
+
+Goals:
+* Thread safety
+* The proposed way ==> - fd-passing for tcp sockets (for free)
+ Approach:
+ - tdb "in small". So a "db file".
+ - for each socket an entry in the db file
+ (file, mmap, robust mutex. e.g. one file per local ip addr)
+ - socket_info : structure in db. protected by pthread robust mutexes
+ - socket_info_fd : --> pointer into mmap area of db
+ - free-list
+ - fd-passing: pass index in array
+ - the last element we pass is not a fd but the index number in the
+ mmaped file
+* Use realpath() in socket_wrapper_dir().
+
+Testing:
+---------
+* Add a test to make sure detect stale file descriptors.
+* Add a test for sento() to broadcast 255.255.255.255.
+* Add a test to check that read/readv/send/ only work on connected sockets.
+* Add unit tests for conversion functions like convert_in_un_remote().
+* Add threaded tests.
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/AddCMockaTest.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/AddCMockaTest.cmake
new file mode 100644
index 0000000..b2d1ca8
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/AddCMockaTest.cmake
@@ -0,0 +1,23 @@
+# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
+
+# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
+# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+enable_testing()
+include(CTest)
+
+if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
+ set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
+ set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
+ set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
+ set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
+endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
+
+function (ADD_CMOCKA_TEST _testName _testSource)
+ add_executable(${_testName} ${_testSource})
+ target_link_libraries(${_testName} ${ARGN})
+ add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
+endfunction (ADD_CMOCKA_TEST)
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/COPYING-CMAKE-SCRIPTS b/tests/deckard/contrib/libswrap/cmake/Modules/COPYING-CMAKE-SCRIPTS
new file mode 100644
index 0000000..4b41776
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/COPYING-CMAKE-SCRIPTS
@@ -0,0 +1,22 @@
+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 copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+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.
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/CheckCCompilerFlagSSP.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/CheckCCompilerFlagSSP.cmake
new file mode 100644
index 0000000..2fe4395
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/CheckCCompilerFlagSSP.cmake
@@ -0,0 +1,26 @@
+# - Check whether the C compiler supports a given flag in the
+# context of a stack checking compiler option.
+
+# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
+#
+# FLAG - the compiler flag
+# VARIABLE - variable to store the result
+#
+# This actually calls check_c_source_compiles.
+# See help for CheckCSourceCompiles for a listing of variables
+# that can modify the build.
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+include(CheckCSourceCompiles)
+
+function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
+ set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+ set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+ check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
+ set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+endfunction(CHECK_C_COMPILER_FLAG_SSP)
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/DefineCMakeDefaults.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/DefineCMakeDefaults.cmake
new file mode 100644
index 0000000..a6cd47e
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/DefineCMakeDefaults.cmake
@@ -0,0 +1,30 @@
+# Always include srcdir and builddir in include path
+# This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in
+# about every subdir
+# since cmake 2.4.0
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# Put the include dirs which are in the source or build tree
+# before all other include dirs, so the headers in the sources
+# are preferred over the already installed ones
+# since cmake 2.4.1
+set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
+
+# Use colored output
+# since cmake 2.4.0
+set(CMAKE_COLOR_MAKEFILE ON)
+
+# Define the generic version of the libraries here
+set(GENERIC_LIB_VERSION "0.1.0")
+set(GENERIC_LIB_SOVERSION "0")
+
+# Set the default build type to release with debug info
+if (NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE RelWithDebInfo
+ CACHE STRING
+ "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+ )
+endif (NOT CMAKE_BUILD_TYPE)
+
+# Create the compile command database for clang by default
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/DefineCompilerFlags.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/DefineCompilerFlags.cmake
new file mode 100644
index 0000000..53481c3
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/DefineCompilerFlags.cmake
@@ -0,0 +1,93 @@
+# define system dependent compiler flags
+
+include(CheckCCompilerFlag)
+include(CheckCCompilerFlagSSP)
+
+if (UNIX AND NOT WIN32)
+ #
+ # Define GNUCC compiler flags
+ #
+ if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+
+ # add -Wconversion ?
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -Wcast-align -Wcast-qual")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers")
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=pointer-arith -Werror=declaration-after-statement")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=write-strings")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=int-to-pointer-cast -Werror=pointer-to-int-cast")
+ # -Werror=strict-aliasing is broken
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstrict-aliasing -Wstrict-aliasing=2")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstrict-overflow -Wstrict-overflow=5 -Werror=strict-overflow")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE")
+
+ if (OSX)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__APPLE_USE_RFC_3542")
+ endif (OSX)
+
+ # with -fPIC
+ check_c_compiler_flag("-fPIC" WITH_FPIC)
+ if (WITH_FPIC)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+ endif (WITH_FPIC)
+
+ check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
+ if (WITH_STACK_PROTECTOR)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
+ endif (WITH_STACK_PROTECTOR)
+
+ if (CMAKE_BUILD_TYPE)
+ string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
+ if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
+ check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
+ if (WITH_FORTIFY_SOURCE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
+ endif (WITH_FORTIFY_SOURCE)
+
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=uninitialized")
+ endif()
+ endif()
+ endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+
+ #
+ # Check for large filesystem support
+ #
+ if (CMAKE_SIZEOF_VOID_P MATCHES "8")
+ # with large file support
+ execute_process(
+ COMMAND
+ getconf LFS64_CFLAGS
+ OUTPUT_VARIABLE
+ _lfs_CFLAGS
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ else (CMAKE_SIZEOF_VOID_P MATCHES "8")
+ # with large file support
+ execute_process(
+ COMMAND
+ getconf LFS_CFLAGS
+ OUTPUT_VARIABLE
+ _lfs_CFLAGS
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
+ if (_lfs_CFLAGS)
+ string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
+ endif (_lfs_CFLAGS)
+
+endif (UNIX AND NOT WIN32)
+
+if (MSVC)
+ # Use secure functions by defaualt and suppress warnings about
+ #"deprecated" functions
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
+endif (MSVC)
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/DefineInstallationPaths.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/DefineInstallationPaths.cmake
new file mode 100644
index 0000000..a415f3d
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/DefineInstallationPaths.cmake
@@ -0,0 +1,109 @@
+if (UNIX OR OS2)
+ IF (NOT APPLICATION_NAME)
+ MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
+ SET(APPLICATION_NAME ${PROJECT_NAME})
+ ENDIF (NOT APPLICATION_NAME)
+
+ # Suffix for Linux
+ SET(LIB_SUFFIX
+ CACHE STRING "Define suffix of directory name (32/64)"
+ )
+
+ SET(EXEC_INSTALL_PREFIX
+ "${CMAKE_INSTALL_PREFIX}"
+ CACHE PATH "Base directory for executables and libraries"
+ )
+ SET(SHARE_INSTALL_PREFIX
+ "${CMAKE_INSTALL_PREFIX}/share"
+ CACHE PATH "Base directory for files which go to share/"
+ )
+ SET(DATA_INSTALL_PREFIX
+ "${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
+ CACHE PATH "The parent directory where applications can install their data")
+
+ # The following are directories where stuff will be installed to
+ SET(BIN_INSTALL_DIR
+ "${EXEC_INSTALL_PREFIX}/bin"
+ CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
+ )
+ SET(SBIN_INSTALL_DIR
+ "${EXEC_INSTALL_PREFIX}/sbin"
+ CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
+ )
+ SET(LIB_INSTALL_DIR
+ "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
+ CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
+ )
+ SET(LIBEXEC_INSTALL_DIR
+ "${EXEC_INSTALL_PREFIX}/libexec"
+ CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
+ )
+ SET(PLUGIN_INSTALL_DIR
+ "${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
+ CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
+ )
+ SET(INCLUDE_INSTALL_DIR
+ "${CMAKE_INSTALL_PREFIX}/include"
+ CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
+ )
+
+ set(CMAKE_INSTALL_DIR
+ "${LIB_INSTALL_DIR}/cmake"
+ CACHE PATH "The subdirectory to install cmake config files")
+
+ SET(DATA_INSTALL_DIR
+ "${DATA_INSTALL_PREFIX}"
+ CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
+ )
+ SET(HTML_INSTALL_DIR
+ "${DATA_INSTALL_PREFIX}/doc/HTML"
+ CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
+ )
+ SET(ICON_INSTALL_DIR
+ "${DATA_INSTALL_PREFIX}/icons"
+ CACHE PATH "The icon install dir (default data/icons/)"
+ )
+ SET(SOUND_INSTALL_DIR
+ "${DATA_INSTALL_PREFIX}/sounds"
+ CACHE PATH "The install dir for sound files (default data/sounds)"
+ )
+
+ SET(LOCALE_INSTALL_DIR
+ "${SHARE_INSTALL_PREFIX}/locale"
+ CACHE PATH "The install dir for translations (default prefix/share/locale)"
+ )
+
+ SET(XDG_APPS_DIR
+ "${SHARE_INSTALL_PREFIX}/applications/"
+ CACHE PATH "The XDG apps dir"
+ )
+ SET(XDG_DIRECTORY_DIR
+ "${SHARE_INSTALL_PREFIX}/desktop-directories"
+ CACHE PATH "The XDG directory"
+ )
+
+ SET(SYSCONF_INSTALL_DIR
+ "${EXEC_INSTALL_PREFIX}/etc"
+ CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)"
+ )
+ SET(MAN_INSTALL_DIR
+ "${SHARE_INSTALL_PREFIX}/man"
+ CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
+ )
+ SET(INFO_INSTALL_DIR
+ "${SHARE_INSTALL_PREFIX}/info"
+ CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
+ )
+else()
+ # Same same
+ set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
+ set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
+ set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
+ set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
+ set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
+ set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
+ set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
+ set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
+ set(SOUND_INSTALL_DIR "sounds" CACHE PATH "-")
+ set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
+endif ()
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/DefinePlatformDefaults.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/DefinePlatformDefaults.cmake
new file mode 100644
index 0000000..f36d9e6
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/DefinePlatformDefaults.cmake
@@ -0,0 +1,32 @@
+# Set system vars
+
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(LINUX TRUE)
+endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ set(FREEBSD TRUE)
+ set(BSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
+ set(OPENBSD TRUE)
+ set(BSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+ set(NETBSD TRUE)
+ set(BSD TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+
+if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+ set(SOLARIS TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
+
+if (CMAKE_SYSTEM_NAME MATCHES "OS2")
+ set(OS2 TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
+
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ set(OSX TRUE)
+endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
diff --git a/tests/deckard/contrib/libswrap/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake b/tests/deckard/contrib/libswrap/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake
new file mode 100644
index 0000000..a2e9480
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake
@@ -0,0 +1,17 @@
+# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
+# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage)
+
+ string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource)
+ if (_insource)
+ message(SEND_ERROR "${_errorMessage}")
+ message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.")
+ endif (_insource)
+
+endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD)
diff --git a/tests/deckard/contrib/libswrap/config.h.cmake b/tests/deckard/contrib/libswrap/config.h.cmake
new file mode 100644
index 0000000..a9b8ce8
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/config.h.cmake
@@ -0,0 +1,74 @@
+/* Name of package */
+#cmakedefine PACKAGE "${APPLICATION_NAME}"
+
+/* Version number of package */
+#cmakedefine VERSION "${APPLICATION_VERSION}"
+
+#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
+#cmakedefine DATADIR "${DATADIR}"
+#cmakedefine LIBDIR "${LIBDIR}"
+#cmakedefine PLUGINDIR "${PLUGINDIR}"
+#cmakedefine SYSCONFDIR "${SYSCONFDIR}"
+#cmakedefine BINARYDIR "${BINARYDIR}"
+#cmakedefine SOURCEDIR "${SOURCEDIR}"
+
+/************************** HEADER FILES *************************/
+
+#cmakedefine HAVE_SYS_FILIO_H 1
+#cmakedefine HAVE_SYS_SIGNALFD_H 1
+#cmakedefine HAVE_SYS_EVENTFD_H 1
+#cmakedefine HAVE_SYS_TIMERFD_H 1
+#cmakedefine HAVE_GNU_LIB_NAMES_H 1
+#cmakedefine HAVE_RPC_RPC_H 1
+
+/**************************** STRUCTS ****************************/
+
+#cmakedefine HAVE_STRUCT_IN_PKTINFO 1
+#cmakedefine HAVE_STRUCT_IN6_PKTINFO 1
+
+/************************ STRUCT MEMBERS *************************/
+
+#cmakedefine HAVE_STRUCT_SOCKADDR_SA_LEN 1
+#cmakedefine HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+
+/*************************** FUNCTIONS ***************************/
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#cmakedefine HAVE_GETADDRINFO 1
+#cmakedefine HAVE_SIGNALFD 1
+#cmakedefine HAVE_EVENTFD 1
+#cmakedefine HAVE_TIMERFD_CREATE 1
+#cmakedefine HAVE_BINDRESVPORT 1
+#cmakedefine HAVE_ACCEPT4 1
+#cmakedefine HAVE_PLEDGE 1
+
+#cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1
+#cmakedefine HAVE_IOCTL_INT 1
+#cmakedefine HAVE_EVENTFD_UNSIGNED_INT 1
+
+/*************************** LIBRARIES ***************************/
+
+#cmakedefine HAVE_GETTIMEOFDAY_TZ 1
+#cmakedefine HAVE_GETTIMEOFDAY_TZ_VOID 1
+
+/*************************** DATA TYPES***************************/
+
+#cmakedefine SIZEOF_PID_T @SIZEOF_PID_T@
+
+/**************************** OPTIONS ****************************/
+
+#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
+#cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
+#cmakedefine HAVE_ADDRESS_SANITIZER_ATTRIBUTE 1
+#cmakedefine HAVE_SOCKADDR_STORAGE 1
+#cmakedefine HAVE_IPV6 1
+#cmakedefine HAVE_FUNCTION_ATTRIBUTE_FORMAT 1
+
+#cmakedefine HAVE_APPLE 1
+#cmakedefine HAVE_LIBSOCKET 1
+
+/*************************** ENDIAN *****************************/
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#cmakedefine WORDS_BIGENDIAN 1
diff --git a/tests/deckard/contrib/libswrap/doc/CMakeLists.txt b/tests/deckard/contrib/libswrap/doc/CMakeLists.txt
new file mode 100644
index 0000000..57552d6
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/doc/CMakeLists.txt
@@ -0,0 +1,4 @@
+install(FILES
+ socket_wrapper.1
+ DESTINATION
+ ${MAN_INSTALL_DIR}/man1)
diff --git a/tests/deckard/contrib/libswrap/doc/README b/tests/deckard/contrib/libswrap/doc/README
new file mode 100644
index 0000000..dbe07f7
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/doc/README
@@ -0,0 +1,3 @@
+The manpage is written with asciidoc. To generate the manpage use:
+
+a2x --doctype manpage --format manpage doc/socket_wrapper.1.txt
diff --git a/tests/deckard/contrib/libswrap/doc/socket_wrapper.1 b/tests/deckard/contrib/libswrap/doc/socket_wrapper.1
new file mode 100644
index 0000000..c3cf835
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/doc/socket_wrapper.1
@@ -0,0 +1,204 @@
+'\" t
+.\" Title: socket_wrapper
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2015-08-11
+.\" Manual: \ \&
+.\" Source: \ \&
+.\" Language: English
+.\"
+.TH "SOCKET_WRAPPER" "1" "2015\-08\-11" "\ \&" "\ \&"
+.\" -----------------------------------------------------------------
+.\" * 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"
+socket_wrapper \- A library passing all socket communications through unix sockets\&.
+.SH "SYNOPSIS"
+.sp
+LD_PRELOAD=libsocket_wrapper\&.so SOCKET_WRAPPER_DIR=/tmp/tmp\&.bQRELqDrhM SOCKET_WRAPPER_DEFAULT_IFACE=10 \fB\&./myapplication\fR
+.SH "DESCRIPTION"
+.sp
+socket_wrapper aims to help client/server software development teams willing to gain full functional test coverage\&. It makes possible to run several instances of the full software stack on the same machine and perform locally functional testing of complex network configurations\&.
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Redirects all network communication to happen over unix sockets\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Support for IPv4 and IPv6 socket and addressing emulation\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Ablility to capture network traffic in pcap format\&.
+.RE
+.SH "ENVIRONMENT VARIABLES"
+.PP
+\fBSOCKET_WRAPPER_DIR\fR
+.RS 4
+The user defines a directory where to put all the unix sockets using the envionment variable "SOCKET_WRAPPER_DIR=/path/to/socket_dir"\&. When a server opens a port or a client wants to connect, socket_wrapper will translate IP addresses to a special socket_wrapper name and look for the relevant unix socket in the SOCKET_WRAPPER_DIR\&.
+.RE
+.PP
+\fBSOCKET_WRAPPER_DEFAULT_IFACE\fR
+.RS 4
+Additionally, the default interface to be used by an application is defined with "SOCKET_WRAPPER_DEFAULT_IFACE=<ID>" where <ID> is between 2 and 254\&. This is analogous to use the IPv4 addresses "127\&.0\&.0\&.<ID>" or IPv6 addresses "fd00::5357:5f<IDx>" (where <IDx> is a hexadecimal presentation of <ID>)\&. You should always set the default interface\&. If you listen on INADDR_ANY then it will use the default interface to listen on\&.
+.RE
+.PP
+\fBSOCKET_WRAPPER_PCAP_FILE\fR
+.RS 4
+When debugging, it is often interesting to investigate the network traffic between the client and server within your application\&. If you define SOCKET_WRAPPER_PCAP_FILE=/path/to/file\&.pcap, socket_wrapper will dump all your network traffic to the specified file\&. After the test has been finished you\(cqre able to open the file for example with Wireshark\&.
+.RE
+.PP
+\fBSOCKET_WRAPPER_MTU\fR
+.RS 4
+With this variable you can change the MTU size\&. However we do not recomment to do that as the default size of 1500 byte is best for formatting PCAP files\&.
+.RE
+.sp
+The minimum value you can set is 512 and the maximum 32768\&.
+.PP
+\fBSOCKET_WRAPPER_DEBUGLEVEL\fR
+.RS 4
+If you need to see what is going on in socket_wrapper itself or try to find a bug, you can enable logging support in socket_wrapper if you built it with debug symbols\&.
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+0 = ERROR
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+1 = WARNING
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+2 = DEBUG
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+3 = TRACE
+.RE
+.RE
+.SH "EXAMPLE"
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# Open a console and create a directory for the unix sockets\&.
+$ mktemp \-d
+/tmp/tmp\&.bQRELqDrhM
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# Then start nc to listen for network traffic using the temporary directory\&.
+$ LD_PRELOAD=libsocket_wrapper\&.so \e
+ SOCKET_WRAPPER_DIR=/tmp/tmp\&.bQRELqDrhM \e
+ SOCKET_WRAPPER_DEFAULT_IFACE=10 nc \-v \-l 127\&.0\&.0\&.10 7
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# (If nc, listens on 0\&.0\&.0\&.0 then listener will be open on 127\&.0\&.0\&.10 because
+# it is the default interface)
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# Now open another console and start \*(Aqnc\*(Aq as a client to connect to the server:
+$ LD_PRELOAD=libsocket_wrapper\&.so \e
+ SOCKET_WRAPPER_DIR=/tmp/tmp\&.bQRELqDrhM \e
+ SOCKET_WRAPPER_DEFAULT_IFACE=100 nc \-v 127\&.0\&.0\&.10 7
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# (The client will use the address 127\&.0\&.0\&.100 when connecting to the server)
+# Now you can type \*(AqHello!\*(Aq which will be sent to the server and should appear
+# in the console output of the server\&.
+.fi
+.if n \{\
+.RE
+.\}
diff --git a/tests/deckard/contrib/libswrap/doc/socket_wrapper.1.txt b/tests/deckard/contrib/libswrap/doc/socket_wrapper.1.txt
new file mode 100644
index 0000000..f4e82a8
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/doc/socket_wrapper.1.txt
@@ -0,0 +1,95 @@
+socket_wrapper(1)
+=================
+:revdate: 2015-08-11
+
+NAME
+----
+
+socket_wrapper - A library passing all socket communications through unix sockets.
+
+SYNOPSIS
+--------
+
+LD_PRELOAD=libsocket_wrapper.so SOCKET_WRAPPER_DIR=/tmp/tmp.bQRELqDrhM SOCKET_WRAPPER_DEFAULT_IFACE=10 *./myapplication*
+
+DESCRIPTION
+-----------
+
+socket_wrapper aims to help client/server software development teams willing to
+gain full functional test coverage. It makes possible to run several instances
+of the full software stack on the same machine and perform locally functional
+testing of complex network configurations.
+
+- Redirects all network communication to happen over unix sockets.
+- Support for IPv4 and IPv6 socket and addressing emulation.
+- Ablility to capture network traffic in pcap format.
+
+ENVIRONMENT VARIABLES
+---------------------
+
+*SOCKET_WRAPPER_DIR*::
+
+The user defines a directory where to put all the unix sockets using the
+envionment variable "SOCKET_WRAPPER_DIR=/path/to/socket_dir". When a server
+opens a port or a client wants to connect, socket_wrapper will translate IP
+addresses to a special socket_wrapper name and look for the relevant unix
+socket in the SOCKET_WRAPPER_DIR.
+
+*SOCKET_WRAPPER_DEFAULT_IFACE*::
+
+Additionally, the default interface to be used by an application is defined
+with "SOCKET_WRAPPER_DEFAULT_IFACE=<ID>" where <ID> is between 2 and 254. This
+is analogous to use the IPv4 addresses "127.0.0.<ID>" or IPv6 addresses
+"fd00::5357:5f<IDx>" (where <IDx> is a hexadecimal presentation of <ID>). You
+should always set the default interface. If you listen on INADDR_ANY then it
+will use the default interface to listen on.
+
+*SOCKET_WRAPPER_PCAP_FILE*::
+
+When debugging, it is often interesting to investigate the network traffic
+between the client and server within your application. If you define
+SOCKET_WRAPPER_PCAP_FILE=/path/to/file.pcap, socket_wrapper will dump all your
+network traffic to the specified file. After the test has been finished you're
+able to open the file for example with Wireshark.
+
+*SOCKET_WRAPPER_MTU*::
+
+With this variable you can change the MTU size. However we do not recomment to
+do that as the default size of 1500 byte is best for formatting PCAP files.
+
+The minimum value you can set is 512 and the maximum 32768.
+
+*SOCKET_WRAPPER_DEBUGLEVEL*::
+
+If you need to see what is going on in socket_wrapper itself or try to find a
+bug, you can enable logging support in socket_wrapper if you built it with
+debug symbols.
+
+- 0 = ERROR
+- 1 = WARNING
+- 2 = DEBUG
+- 3 = TRACE
+
+EXAMPLE
+-------
+
+ # Open a console and create a directory for the unix sockets.
+ $ mktemp -d
+ /tmp/tmp.bQRELqDrhM
+
+ # Then start nc to listen for network traffic using the temporary directory.
+ $ LD_PRELOAD=libsocket_wrapper.so \
+ SOCKET_WRAPPER_DIR=/tmp/tmp.bQRELqDrhM \
+ SOCKET_WRAPPER_DEFAULT_IFACE=10 nc -v -l 127.0.0.10 7
+
+ # (If nc, listens on 0.0.0.0 then listener will be open on 127.0.0.10 because
+ # it is the default interface)
+
+ # Now open another console and start 'nc' as a client to connect to the server:
+ $ LD_PRELOAD=libsocket_wrapper.so \
+ SOCKET_WRAPPER_DIR=/tmp/tmp.bQRELqDrhM \
+ SOCKET_WRAPPER_DEFAULT_IFACE=100 nc -v 127.0.0.10 7
+
+ # (The client will use the address 127.0.0.100 when connecting to the server)
+ # Now you can type 'Hello!' which will be sent to the server and should appear
+ # in the console output of the server.
diff --git a/tests/deckard/contrib/libswrap/example/openssh.sh b/tests/deckard/contrib/libswrap/example/openssh.sh
new file mode 100755
index 0000000..bb74f03
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/example/openssh.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+SSH_DIRECTORY=$(mktemp -d /tmp/tmp.swrap.XXXXXXXX)
+SERVER_ADDRESS="127.0.0.10"
+mkdir ${SSH_DIRECTORY}/swrap
+
+cleanup_and_exit () {
+ trap EXIT
+ test -z "$1" && set 0
+
+ echo
+ echo "CLEANING UP"
+ echo
+
+ kill -TERM $(< ${SSH_DIRECTORY}/sshd.pid)
+ rm -rf ${SSH_DIRECTORY}
+
+ exit $1
+}
+
+# Setup exit handler
+trap cleanup_and_exit SIGINT SIGTERM
+
+echo Generating ${SSH_DIRECTORY}/ssh_host_key.
+ssh-keygen -t rsa1 -b 2048 -f ${SSH_DIRECTORY}/ssh_host_key -N '' 2>/dev/null
+echo Generating ${SSH_DIRECTORY}/ssh_host_dsa_key.
+ssh-keygen -t dsa -f ${SSH_DIRECTORY}/ssh_host_dsa_key -N '' 2>/dev/null
+echo Generating ${SSH_DIRECTORY}/ssh_host_rsa_key.
+ssh-keygen -t rsa -b 2048 -f ${SSH_DIRECTORY}/ssh_host_rsa_key -N '' 2>/dev/null
+#echo Generating ${SSH_DIRECTORY}/ssh_host_ecdsa_key.
+#ssh-keygen -t ecdsa -b 256 -f ${SSH_DIRECTORY}/ssh_host_ecdsa_key -N '' 2>/dev/null
+
+# Create sshd_config file
+cat > ${SSH_DIRECTORY}/sshd_config << EOT
+Port 22
+ListenAddress ${SERVER_ADDRESS}
+HostKey ${SSH_DIRECTORY}/ssh_host_key
+HostKey ${SSH_DIRECTORY}/ssh_host_rsa_key
+HostKey ${SSH_DIRECTORY}/ssh_host_dsa_key
+#HostKey ${SSH_DIRECTORY}/ssh_host_ecdsa_key
+Subsystem sftp /usr/lib/ssh/sftp-server
+
+LogLevel DEBUG1
+
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL
+
+PidFile ${SSH_DIRECTORY}/sshd.pid
+EOT
+
+export SOCKET_WRAPPER_DIR="${SSH_DIRECTORY}/swrap"
+export SOCKET_WRAPPER_DEFAULT_IFACE=11
+
+echo
+echo "Starting SSHD with SOCKET_WRAPPER_DIR=${SSH_DIRECTORY}/swrap ..."
+DYLD_INSERT_LIBRARIES=libsocket_wrapper.dylib LD_PRELOAD=libsocket_wrapper.so /usr/sbin/sshd -f ${SSH_DIRECTORY}/sshd_config -e 2> ${SSH_DIRECTORY}/sshd_log || cleanup_and_exit 1
+echo "done"
+
+echo
+echo "Connecting to the ${SERVER_ADDRESS} ssh server using ssh binary."
+echo "You can check the sshd log file at ${SSH_DIRECTORY}/sshd_log."
+echo "If you logout sshd will be stopped and the environment cleaned up."
+DYLD_INSERT_LIBRARIES=libsocket_wrapper.dylib LD_PRELOAD=libsocket_wrapper.so ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${SERVER_ADDRESS}
+
+cleanup_and_exit 0
diff --git a/tests/deckard/contrib/libswrap/socket_wrapper-config-version.cmake.in b/tests/deckard/contrib/libswrap/socket_wrapper-config-version.cmake.in
new file mode 100644
index 0000000..98f292c
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/socket_wrapper-config-version.cmake.in
@@ -0,0 +1,11 @@
+set(PACKAGE_VERSION @APPLICATION_VERSION@)
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+endif()
diff --git a/tests/deckard/contrib/libswrap/socket_wrapper-config.cmake.in b/tests/deckard/contrib/libswrap/socket_wrapper-config.cmake.in
new file mode 100644
index 0000000..7bedd79
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/socket_wrapper-config.cmake.in
@@ -0,0 +1 @@
+set(SOCKET_WRAPPER_LIBRARY @LIB_INSTALL_DIR@/@SOCKET_WRAPPER_LIB@)
diff --git a/tests/deckard/contrib/libswrap/socket_wrapper.pc.cmake b/tests/deckard/contrib/libswrap/socket_wrapper.pc.cmake
new file mode 100644
index 0000000..6dc71f7
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/socket_wrapper.pc.cmake
@@ -0,0 +1,4 @@
+Name: @APPLICATION_NAME@
+Description: The socket_wrapper library
+Version: @APPLICATION_VERSION@
+Libs: @LIB_INSTALL_DIR@/@SOCKET_WRAPPER_LIB@
diff --git a/tests/deckard/contrib/libswrap/src/CMakeLists.txt b/tests/deckard/contrib/libswrap/src/CMakeLists.txt
new file mode 100644
index 0000000..e5f2fbb
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/src/CMakeLists.txt
@@ -0,0 +1,26 @@
+project(libsocket_wrapper C)
+
+include_directories(${CMAKE_BINARY_DIR})
+
+add_library(socket_wrapper SHARED socket_wrapper.c)
+
+target_link_libraries(socket_wrapper ${SWRAP_REQUIRED_LIBRARIES})
+
+install(
+ TARGETS
+ socket_wrapper
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
+
+set_target_properties(
+ socket_wrapper
+ PROPERTIES
+ VERSION
+ ${LIBRARY_VERSION}
+ SOVERSION
+ ${LIBRARY_SOVERSION}
+)
+
+set(SOCKET_WRAPPER_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}socket_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}" PARENT_SCOPE)
diff --git a/tests/deckard/contrib/libswrap/src/socket_wrapper.c b/tests/deckard/contrib/libswrap/src/socket_wrapper.c
new file mode 100644
index 0000000..bc4f4ab
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/src/socket_wrapper.c
@@ -0,0 +1,5475 @@
+/*
+ * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
+ * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
+ * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
+ *
+ * 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 author 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 AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+/*
+ Socket wrapper library. Passes all socket communication over
+ unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
+ is set.
+*/
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_SIGNALFD_H
+#include <sys/signalfd.h>
+#endif
+#ifdef HAVE_SYS_EVENTFD_H
+#include <sys/eventfd.h>
+#endif
+#ifdef HAVE_SYS_TIMERFD_H
+#include <sys/timerfd.h>
+#endif
+#include <sys/uio.h>
+#include <errno.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <unistd.h>
+#ifdef HAVE_GNU_LIB_NAMES_H
+#include <gnu/lib-names.h>
+#endif
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
+#include <dirent.h>
+
+enum swrap_dbglvl_e {
+ SWRAP_LOG_ERROR = 0,
+ SWRAP_LOG_WARN,
+ SWRAP_LOG_DEBUG,
+ SWRAP_LOG_TRACE
+};
+
+/* GCC have printf type attribute check. */
+#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define PRINTF_ATTRIBUTE(a,b)
+#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
+
+#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
+#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
+#else
+#define DESTRUCTOR_ATTRIBUTE
+#endif
+
+#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
+#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
+#else
+#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+#endif
+
+#ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
+# define SWRAP_THREAD __thread
+#else
+# define SWRAP_THREAD
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef ZERO_STRUCT
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
+
+#ifndef ZERO_STRUCTP
+#define ZERO_STRUCTP(x) do { \
+ if ((x) != NULL) \
+ memset((char *)(x), 0, sizeof(*(x))); \
+ } while(0)
+#endif
+
+#ifndef discard_const
+#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
+#endif
+
+#ifndef discard_const_p
+#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
+#endif
+
+#ifdef IPV6_PKTINFO
+# ifndef IPV6_RECVPKTINFO
+# define IPV6_RECVPKTINFO IPV6_PKTINFO
+# endif /* IPV6_RECVPKTINFO */
+#endif /* IPV6_PKTINFO */
+
+/*
+ * On BSD IP_PKTINFO has a different name because during
+ * the time when they implemented it, there was no RFC.
+ * The name for IPv6 is the same as on Linux.
+ */
+#ifndef IP_PKTINFO
+# ifdef IP_RECVDSTADDR
+# define IP_PKTINFO IP_RECVDSTADDR
+# endif
+#endif
+
+
+#define SWRAP_DLIST_ADD(list,item) do { \
+ if (!(list)) { \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+ (list) = (item); \
+ } else { \
+ (item)->prev = NULL; \
+ (item)->next = (list); \
+ (list)->prev = (item); \
+ (list) = (item); \
+ } \
+} while (0)
+
+#define SWRAP_DLIST_REMOVE(list,item) do { \
+ if ((list) == (item)) { \
+ (list) = (item)->next; \
+ if (list) { \
+ (list)->prev = NULL; \
+ } \
+ } else { \
+ if ((item)->prev) { \
+ (item)->prev->next = (item)->next; \
+ } \
+ if ((item)->next) { \
+ (item)->next->prev = (item)->prev; \
+ } \
+ } \
+ (item)->prev = NULL; \
+ (item)->next = NULL; \
+} while (0)
+
+#if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
+#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
+#else
+#define swrapGetTimeOfDay(tval) gettimeofday(tval)
+#endif
+
+/* we need to use a very terse format here as IRIX 6.4 silently
+ truncates names to 16 chars, so if we use a longer name then we
+ can't tell which port a packet came from with recvfrom()
+
+ with this format we have 8 chars left for the directory name
+*/
+#define SOCKET_FORMAT "%c%02X%04X"
+#define SOCKET_TYPE_CHAR_TCP 'T'
+#define SOCKET_TYPE_CHAR_UDP 'U'
+#define SOCKET_TYPE_CHAR_TCP_V6 'X'
+#define SOCKET_TYPE_CHAR_UDP_V6 'Y'
+
+
+#define SOCKET_FORMAT_LONG "%c%08X%04X"
+#define SOCKET_FORMAT_V6_LONG "%c%08X%08X%08X%08X%04X"
+
+#define SOCKET_TYPE_CHAR_TCP_LONG 'Q'
+#define SOCKET_TYPE_CHAR_UDP_LONG 'W'
+#define SOCKET_TYPE_CHAR_TCP_V6_LONG 'E'
+#define SOCKET_TYPE_CHAR_UDP_V6_LONG 'R'
+
+/*
+ * Set the packet MTU to 1500 bytes for stream sockets to make it it easier to
+ * format PCAP capture files (as the caller will simply continue from here).
+ */
+#define SOCKET_WRAPPER_MTU_DEFAULT 1500
+#define SOCKET_WRAPPER_MTU_MIN 512
+#define SOCKET_WRAPPER_MTU_MAX 32768
+
+#define SOCKET_MAX_SOCKETS 1024
+
+/* This limit is to avoid broadcast sendto() needing to stat too many
+ * files. It may be raised (with a performance cost) to up to 254
+ * without changing the format above */
+#define MAX_WRAPPED_INTERFACES 40
+
+struct swrap_address {
+ socklen_t sa_socklen;
+ union {
+ struct sockaddr s;
+ struct sockaddr_in in;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr_un un;
+ struct sockaddr_storage ss;
+ } sa;
+};
+
+struct socket_info_fd {
+ struct socket_info_fd *prev, *next;
+ int fd;
+};
+
+struct socket_info
+{
+ struct socket_info_fd *fds;
+
+ int family;
+ int type;
+ int protocol;
+ int bound;
+ int bcast;
+ int is_server;
+ int connected;
+ int defer_connect;
+ int pktinfo;
+ int tcp_nodelay;
+
+ /* The unix path so we can unlink it on close() */
+ struct sockaddr_un un_addr;
+
+ struct swrap_address bindname;
+ struct swrap_address myname;
+ struct swrap_address peername;
+
+ struct {
+ unsigned long pck_snd;
+ unsigned long pck_rcv;
+ } io;
+
+ struct socket_info *prev, *next;
+};
+
+/*
+ * File descriptors are shared between threads so we should share socket
+ * information too.
+ */
+struct socket_info *sockets;
+
+/* Function prototypes */
+
+bool socket_wrapper_enabled(void);
+void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
+
+#ifdef NDEBUG
+# define SWRAP_LOG(...)
+#else
+
+static void swrap_log(enum swrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
+# define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
+
+static void swrap_log(enum swrap_dbglvl_e dbglvl,
+ const char *func,
+ const char *format, ...)
+{
+ char buffer[1024];
+ va_list va;
+ const char *d;
+ unsigned int lvl = 0;
+
+ d = getenv("SOCKET_WRAPPER_DEBUGLEVEL");
+ if (d != NULL) {
+ lvl = atoi(d);
+ }
+
+ va_start(va, format);
+ vsnprintf(buffer, sizeof(buffer), format, va);
+ va_end(va);
+
+ if (lvl >= dbglvl) {
+ switch (dbglvl) {
+ case SWRAP_LOG_ERROR:
+ fprintf(stderr,
+ "SWRAP_ERROR(%d) - %s: %s\n",
+ (int)getpid(), func, buffer);
+ break;
+ case SWRAP_LOG_WARN:
+ fprintf(stderr,
+ "SWRAP_WARN(%d) - %s: %s\n",
+ (int)getpid(), func, buffer);
+ break;
+ case SWRAP_LOG_DEBUG:
+ fprintf(stderr,
+ "SWRAP_DEBUG(%d) - %s: %s\n",
+ (int)getpid(), func, buffer);
+ break;
+ case SWRAP_LOG_TRACE:
+ fprintf(stderr,
+ "SWRAP_TRACE(%d) - %s: %s\n",
+ (int)getpid(), func, buffer);
+ break;
+ }
+ }
+}
+#endif
+
+/*********************************************************
+ * SWRAP LOADING LIBC FUNCTIONS
+ *********************************************************/
+
+#include <dlfcn.h>
+
+struct swrap_libc_fns {
+#ifdef HAVE_ACCEPT4
+ int (*libc_accept4)(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen,
+ int flags);
+#else
+ int (*libc_accept)(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen);
+#endif
+ int (*libc_bind)(int sockfd,
+ const struct sockaddr *addr,
+ socklen_t addrlen);
+ int (*libc_close)(int fd);
+ int (*libc_connect)(int sockfd,
+ const struct sockaddr *addr,
+ socklen_t addrlen);
+ int (*libc_dup)(int fd);
+ int (*libc_dup2)(int oldfd, int newfd);
+ int (*libc_fcntl)(int fd, int cmd, ...);
+ FILE *(*libc_fopen)(const char *name, const char *mode);
+#ifdef HAVE_EVENTFD
+ int (*libc_eventfd)(int count, int flags);
+#endif
+ int (*libc_getpeername)(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen);
+ int (*libc_getsockname)(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen);
+ int (*libc_getsockopt)(int sockfd,
+ int level,
+ int optname,
+ void *optval,
+ socklen_t *optlen);
+ int (*libc_ioctl)(int d, unsigned long int request, ...);
+ int (*libc_listen)(int sockfd, int backlog);
+ int (*libc_open)(const char *pathname, int flags, mode_t mode);
+ int (*libc_pipe)(int pipefd[2]);
+ int (*libc_read)(int fd, void *buf, size_t count);
+ ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt);
+ int (*libc_recv)(int sockfd, void *buf, size_t len, int flags);
+ int (*libc_recvfrom)(int sockfd,
+ void *buf,
+ size_t len,
+ int flags,
+ struct sockaddr *src_addr,
+ socklen_t *addrlen);
+ int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
+ int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
+ int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
+ int (*libc_sendto)(int sockfd,
+ const void *buf,
+ size_t len,
+ int flags,
+ const struct sockaddr *dst_addr,
+ socklen_t addrlen);
+ int (*libc_setsockopt)(int sockfd,
+ int level,
+ int optname,
+ const void *optval,
+ socklen_t optlen);
+#ifdef HAVE_SIGNALFD
+ int (*libc_signalfd)(int fd, const sigset_t *mask, int flags);
+#endif
+ int (*libc_socket)(int domain, int type, int protocol);
+ int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]);
+#ifdef HAVE_TIMERFD_CREATE
+ int (*libc_timerfd_create)(int clockid, int flags);
+#endif
+ ssize_t (*libc_write)(int fd, const void *buf, size_t count);
+ ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt);
+};
+
+struct swrap {
+ void *libc_handle;
+ void *libsocket_handle;
+
+ bool initialised;
+ bool enabled;
+
+ char *socket_dir;
+
+ struct swrap_libc_fns fns;
+};
+
+static struct swrap swrap;
+
+/* prototypes */
+static const char *socket_wrapper_dir(void);
+
+#define LIBC_NAME "libc.so"
+
+enum swrap_lib {
+ SWRAP_LIBC,
+ SWRAP_LIBNSL,
+ SWRAP_LIBSOCKET,
+};
+
+#ifndef NDEBUG
+static const char *swrap_str_lib(enum swrap_lib lib)
+{
+ switch (lib) {
+ case SWRAP_LIBC:
+ return "libc";
+ case SWRAP_LIBNSL:
+ return "libnsl";
+ case SWRAP_LIBSOCKET:
+ return "libsocket";
+ }
+
+ /* Compiler would warn us about unhandled enum value if we get here */
+ return "unknown";
+}
+#endif
+
+static void *swrap_load_lib_handle(enum swrap_lib lib)
+{
+ int flags = RTLD_LAZY;
+ void *handle = NULL;
+ int i;
+
+#ifdef RTLD_DEEPBIND
+ flags |= RTLD_DEEPBIND;
+#endif
+
+ switch (lib) {
+ case SWRAP_LIBNSL:
+ /* FALL TROUGH */
+ case SWRAP_LIBSOCKET:
+#ifdef HAVE_LIBSOCKET
+ handle = swrap.libsocket_handle;
+ if (handle == NULL) {
+ for (i = 10; i >= 0; i--) {
+ char soname[256] = {0};
+
+ snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
+ handle = dlopen(soname, flags);
+ if (handle != NULL) {
+ break;
+ }
+ }
+
+ swrap.libsocket_handle = handle;
+ }
+ break;
+#endif
+ /* FALL TROUGH */
+ case SWRAP_LIBC:
+ handle = swrap.libc_handle;
+#ifdef LIBC_SO
+ if (handle == NULL) {
+ handle = dlopen(LIBC_SO, flags);
+
+ swrap.libc_handle = handle;
+ }
+#endif
+ if (handle == NULL) {
+ for (i = 10; i >= 0; i--) {
+ char soname[256] = {0};
+
+ snprintf(soname, sizeof(soname), "libc.so.%d", i);
+ handle = dlopen(soname, flags);
+ if (handle != NULL) {
+ break;
+ }
+ }
+
+ swrap.libc_handle = handle;
+ }
+ break;
+ }
+
+ if (handle == NULL) {
+#ifdef RTLD_NEXT
+ handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT;
+#else
+ SWRAP_LOG(SWRAP_LOG_ERROR,
+ "Failed to dlopen library: %s\n",
+ dlerror());
+ exit(-1);
+#endif
+ }
+
+ return handle;
+}
+
+static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name)
+{
+ void *handle;
+ void *func;
+
+ handle = swrap_load_lib_handle(lib);
+
+ func = dlsym(handle, fn_name);
+ if (func == NULL) {
+ SWRAP_LOG(SWRAP_LOG_ERROR,
+ "Failed to find %s: %s\n",
+ fn_name, dlerror());
+ exit(-1);
+ }
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "Loaded %s from %s",
+ fn_name, swrap_str_lib(lib));
+ return func;
+}
+
+#define swrap_load_lib_function(lib, fn_name) \
+ if (swrap.fns.libc_##fn_name == NULL) { \
+ void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \
+ *(void **) (&swrap.fns.libc_##fn_name) = \
+ swrap_cast_ptr; \
+ }
+
+
+/*
+ * IMPORTANT
+ *
+ * Functions especially from libc need to be loaded individually, you can't load
+ * all at once or gdb will segfault at startup. The same applies to valgrind and
+ * has probably something todo with with the linker.
+ * So we need load each function at the point it is called the first time.
+ */
+#ifdef HAVE_ACCEPT4
+static int libc_accept4(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen,
+ int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, accept4);
+
+ return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags);
+}
+
+#else /* HAVE_ACCEPT4 */
+
+static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, accept);
+
+ return swrap.fns.libc_accept(sockfd, addr, addrlen);
+}
+#endif /* HAVE_ACCEPT4 */
+
+static int libc_bind(int sockfd,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, bind);
+
+ return swrap.fns.libc_bind(sockfd, addr, addrlen);
+}
+
+static int libc_close(int fd)
+{
+ swrap_load_lib_function(SWRAP_LIBC, close);
+
+ return swrap.fns.libc_close(fd);
+}
+
+static int libc_connect(int sockfd,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, connect);
+
+ return swrap.fns.libc_connect(sockfd, addr, addrlen);
+}
+
+static int libc_dup(int fd)
+{
+ swrap_load_lib_function(SWRAP_LIBC, dup);
+
+ return swrap.fns.libc_dup(fd);
+}
+
+static int libc_dup2(int oldfd, int newfd)
+{
+ swrap_load_lib_function(SWRAP_LIBC, dup2);
+
+ return swrap.fns.libc_dup2(oldfd, newfd);
+}
+
+#ifdef HAVE_EVENTFD
+static int libc_eventfd(int count, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBC, eventfd);
+
+ return swrap.fns.libc_eventfd(count, flags);
+}
+#endif
+
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static int libc_vfcntl(int fd, int cmd, va_list ap)
+{
+ long int args[4];
+ int rc;
+ int i;
+
+ swrap_load_lib_function(SWRAP_LIBC, fcntl);
+
+ for (i = 0; i < 4; i++) {
+ args[i] = va_arg(ap, long int);
+ }
+
+ rc = swrap.fns.libc_fcntl(fd,
+ cmd,
+ args[0],
+ args[1],
+ args[2],
+ args[3]);
+
+ return rc;
+}
+
+static int libc_getpeername(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, getpeername);
+
+ return swrap.fns.libc_getpeername(sockfd, addr, addrlen);
+}
+
+static int libc_getsockname(int sockfd,
+ struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, getsockname);
+
+ return swrap.fns.libc_getsockname(sockfd, addr, addrlen);
+}
+
+static int libc_getsockopt(int sockfd,
+ int level,
+ int optname,
+ void *optval,
+ socklen_t *optlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, getsockopt);
+
+ return swrap.fns.libc_getsockopt(sockfd, level, optname, optval, optlen);
+}
+
+DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
+static int libc_vioctl(int d, unsigned long int request, va_list ap)
+{
+ long int args[4];
+ int rc;
+ int i;
+
+ swrap_load_lib_function(SWRAP_LIBC, ioctl);
+
+ for (i = 0; i < 4; i++) {
+ args[i] = va_arg(ap, long int);
+ }
+
+ rc = swrap.fns.libc_ioctl(d,
+ request,
+ args[0],
+ args[1],
+ args[2],
+ args[3]);
+
+ return rc;
+}
+
+static int libc_listen(int sockfd, int backlog)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, listen);
+
+ return swrap.fns.libc_listen(sockfd, backlog);
+}
+
+static FILE *libc_fopen(const char *name, const char *mode)
+{
+ swrap_load_lib_function(SWRAP_LIBC, fopen);
+
+ return swrap.fns.libc_fopen(name, mode);
+}
+
+static int libc_vopen(const char *pathname, int flags, va_list ap)
+{
+ long int mode = 0;
+ int fd;
+
+ swrap_load_lib_function(SWRAP_LIBC, open);
+
+ mode = va_arg(ap, long int);
+
+ fd = swrap.fns.libc_open(pathname, flags, (mode_t)mode);
+
+ return fd;
+}
+
+static int libc_open(const char *pathname, int flags, ...)
+{
+ va_list ap;
+ int fd;
+
+ va_start(ap, flags);
+ fd = libc_vopen(pathname, flags, ap);
+ va_end(ap);
+
+ return fd;
+}
+
+static int libc_pipe(int pipefd[2])
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, pipe);
+
+ return swrap.fns.libc_pipe(pipefd);
+}
+
+static int libc_read(int fd, void *buf, size_t count)
+{
+ swrap_load_lib_function(SWRAP_LIBC, read);
+
+ return swrap.fns.libc_read(fd, buf, count);
+}
+
+static ssize_t libc_readv(int fd, const struct iovec *iov, int iovcnt)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, readv);
+
+ return swrap.fns.libc_readv(fd, iov, iovcnt);
+}
+
+static int libc_recv(int sockfd, void *buf, size_t len, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, recv);
+
+ return swrap.fns.libc_recv(sockfd, buf, len, flags);
+}
+
+static int libc_recvfrom(int sockfd,
+ void *buf,
+ size_t len,
+ int flags,
+ struct sockaddr *src_addr,
+ socklen_t *addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, recvfrom);
+
+ return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
+}
+
+static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
+
+ return swrap.fns.libc_recvmsg(sockfd, msg, flags);
+}
+
+static int libc_send(int sockfd, const void *buf, size_t len, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, send);
+
+ return swrap.fns.libc_send(sockfd, buf, len, flags);
+}
+
+static int libc_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, sendmsg);
+
+ return swrap.fns.libc_sendmsg(sockfd, msg, flags);
+}
+
+static int libc_sendto(int sockfd,
+ const void *buf,
+ size_t len,
+ int flags,
+ const struct sockaddr *dst_addr,
+ socklen_t addrlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, sendto);
+
+ return swrap.fns.libc_sendto(sockfd, buf, len, flags, dst_addr, addrlen);
+}
+
+static int libc_setsockopt(int sockfd,
+ int level,
+ int optname,
+ const void *optval,
+ socklen_t optlen)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, setsockopt);
+
+ return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen);
+}
+
+#ifdef HAVE_SIGNALFD
+static int libc_signalfd(int fd, const sigset_t *mask, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd);
+
+ return swrap.fns.libc_signalfd(fd, mask, flags);
+}
+#endif
+
+static int libc_socket(int domain, int type, int protocol)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, socket);
+
+ return swrap.fns.libc_socket(domain, type, protocol);
+}
+
+static int libc_socketpair(int domain, int type, int protocol, int sv[2])
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair);
+
+ return swrap.fns.libc_socketpair(domain, type, protocol, sv);
+}
+
+#ifdef HAVE_TIMERFD_CREATE
+static int libc_timerfd_create(int clockid, int flags)
+{
+ swrap_load_lib_function(SWRAP_LIBC, timerfd_create);
+
+ return swrap.fns.libc_timerfd_create(clockid, flags);
+}
+#endif
+
+static ssize_t libc_write(int fd, const void *buf, size_t count)
+{
+ swrap_load_lib_function(SWRAP_LIBC, write);
+
+ return swrap.fns.libc_write(fd, buf, count);
+}
+
+static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ swrap_load_lib_function(SWRAP_LIBSOCKET, writev);
+
+ return swrap.fns.libc_writev(fd, iov, iovcnt);
+}
+
+/*********************************************************
+ * SWRAP HELPER FUNCTIONS
+ *********************************************************/
+
+#ifdef HAVE_IPV6
+/*
+ * FD00::5357:5FXX
+ */
+static const struct in6_addr *swrap_ipv6(void)
+{
+ static struct in6_addr v;
+ static int initialized;
+ int ret;
+
+ if (initialized) {
+ return &v;
+ }
+ initialized = 1;
+
+ ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
+ if (ret <= 0) {
+ abort();
+ }
+
+ return &v;
+}
+static struct in6_addr swrap_make_ipv6(unsigned int a0, unsigned int a1,
+ unsigned int a2, unsigned int a3)
+{
+ struct in6_addr v;
+ int i;
+ for (i = 0 ; i < 4; i++)
+ {
+ v.s6_addr[ 0 + i] = a0;
+ v.s6_addr[ 4 + i] = a1;
+ v.s6_addr[ 8 + i] = a2;
+ v.s6_addr[12 + i] = a3;
+ a0 >>= 8;
+ a1 >>= 8;
+ a2 >>= 8;
+ a3 >>= 8;
+ }
+ return v;
+}
+static void swrap_make_ipv6_ints(const unsigned char s[16], unsigned int *a0, unsigned int *a1,
+ unsigned int *a2, unsigned int *a3)
+{
+ int i;
+
+ *a0 = 0; *a1 = 0; *a2 = 0; *a3 = 0;
+ for (i = 3 ; i > 0; i--)
+ {
+ *a0 += s[ 0 + i];
+ *a1 += s[ 4 + i];
+ *a2 += s[ 8 + i];
+ *a3 += s[12 + i];
+ *a0 <<= 8;
+ *a1 <<= 8;
+ *a2 <<= 8;
+ *a3 <<= 8;
+ }
+ *a0 += s[ 0];
+ *a1 += s[ 4];
+ *a2 += s[ 8];
+ *a3 += s[12];
+}
+
+#endif
+
+static void set_port(int family, int prt, struct swrap_address *addr)
+{
+ switch (family) {
+ case AF_INET:
+ addr->sa.in.sin_port = htons(prt);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ addr->sa.in6.sin6_port = htons(prt);
+ break;
+#endif
+ }
+}
+
+static size_t socket_length(int family)
+{
+ switch (family) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+#endif
+ }
+ return 0;
+}
+
+static const char *socket_wrapper_dir(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DIR");
+ if (s == NULL) {
+ return NULL;
+ }
+ /* TODO use realpath(3) here, when we add support for threads */
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+
+ SWRAP_LOG(SWRAP_LOG_TRACE, "socket_wrapper_dir: %s", s);
+ return s;
+}
+
+static unsigned int socket_wrapper_mtu(void)
+{
+ static unsigned int max_mtu = 0;
+ unsigned int tmp;
+ const char *s;
+ char *endp;
+
+ if (max_mtu != 0) {
+ return max_mtu;
+ }
+
+ max_mtu = SOCKET_WRAPPER_MTU_DEFAULT;
+
+ s = getenv("SOCKET_WRAPPER_MTU");
+ if (s == NULL) {
+ goto done;
+ }
+
+ tmp = strtol(s, &endp, 10);
+ if (s == endp) {
+ goto done;
+ }
+
+ if (tmp < SOCKET_WRAPPER_MTU_MIN || tmp > SOCKET_WRAPPER_MTU_MAX) {
+ goto done;
+ }
+ max_mtu = tmp;
+
+done:
+ return max_mtu;
+}
+
+bool socket_wrapper_enabled(void)
+{
+ const char *s = socket_wrapper_dir();
+
+ return s != NULL ? true : false;
+}
+
+static unsigned int socket_wrapper_default_iface(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
+ if (s) {
+ unsigned int iface;
+ if (sscanf(s, "%u", &iface) == 1) {
+ if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
+ return iface;
+ }
+ }
+ }
+
+ return 1;/* 127.0.0.1 */
+}
+
+static unsigned int socket_wrapper_default_addr(void)
+{
+ const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
+ if (s) {
+ unsigned int iface;
+ if (sscanf(s, "%u", &iface) == 1) {
+ if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
+ return (127<<24) | iface;
+ }
+ }
+ }
+ return (127<<24) | 0x00000001; /* 127.0.0.1 */
+}
+
+static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
+{
+ unsigned int prt;
+ const char *p;
+ char type;
+
+ p = strrchr(un->sun_path, '/');
+ if (p) p++; else p = un->sun_path;
+
+ type = p[0];
+
+
+ switch(type) {
+ case SOCKET_TYPE_CHAR_TCP_LONG:
+ case SOCKET_TYPE_CHAR_UDP_LONG: {
+ unsigned int in4_addr;
+ struct sockaddr_in *in2 = (struct sockaddr_in *)(void *)in;
+
+ if ((*len) < sizeof(*in2)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (sscanf(p, SOCKET_FORMAT_LONG, &type, &in4_addr, &prt) != 3) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (prt > 0xFFFF) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(in2, 0, sizeof(*in2));
+ in2->sin_family = AF_INET;
+ in2->sin_addr.s_addr = htonl(in4_addr);
+ in2->sin_port = htons(prt);
+
+ *len = sizeof(*in2);
+ break;
+ }
+#ifdef HAVE_IPV6
+ case SOCKET_TYPE_CHAR_TCP_V6_LONG:
+ case SOCKET_TYPE_CHAR_UDP_V6_LONG: {
+ unsigned int in6_a0, in6_a1, in6_a2, in6_a3;
+ struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)(void *)in;
+
+ if (sscanf(p, SOCKET_FORMAT_V6_LONG, &type,
+ &in6_a0, &in6_a1, &in6_a2, &in6_a3, &prt) != 6) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((*len) < sizeof(*in2)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(in2, 0, sizeof(*in2));
+ in2->sin6_family = AF_INET6;
+ in2->sin6_addr = swrap_make_ipv6(in6_a0,in6_a1,in6_a2,in6_a3);
+ in2->sin6_port = htons(prt);
+
+ *len = sizeof(*in2);
+ break;
+ }
+#endif
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
+ int *bcast)
+{
+ char type = '\0';
+ unsigned int prt;
+ unsigned int in4_addr, in6_a0, in6_a1, in6_a2, in6_a3;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ switch (inaddr->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in *in =
+ (const struct sockaddr_in *)(const void *)inaddr;
+ unsigned int addr = ntohl(in->sin_addr.s_addr);
+ char u_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP_LONG;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ a_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ b_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ prt = ntohs(in->sin_port);
+ if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ in4_addr = socket_wrapper_default_addr();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ in4_addr = socket_wrapper_default_addr();
+ } else {
+ is_bcast = 0;
+ type = u_type;
+ in4_addr = addr;
+ }
+ if (bcast) *bcast = is_bcast;
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *in =
+ (const struct sockaddr_in6 *)(const void *)inaddr;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6_LONG;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6_LONG;
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ /* XXX no multicast/broadcast */
+
+ prt = ntohs(in->sin6_port);
+
+ /* TODO - More checks */
+
+ swrap_make_ipv6_ints(in->sin6_addr.s6_addr,&in6_a0,&in6_a1,&in6_a2,&in6_a3);
+ break;
+ }
+#endif
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family!\n");
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+ if (prt == 0) {
+ SWRAP_LOG(SWRAP_LOG_WARN, "Port not set\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (is_bcast) {
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
+ socket_wrapper_dir());
+ SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
+ /* the caller need to do more processing */
+ return 0;
+ }
+
+ switch (inaddr->sa_family) {
+ case AF_INET:
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_LONG,
+ socket_wrapper_dir(), type, in4_addr, prt);
+ break;
+ case AF_INET6:
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_V6_LONG,
+ socket_wrapper_dir(), type, in6_a0, in6_a1, in6_a2, in6_a3, prt);
+ break;
+ }
+ SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
+
+ return 0;
+}
+
+static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
+ int *bcast)
+{
+ char type = '\0';
+ unsigned int prt;
+ unsigned int in4_addr, in6_a0, in6_a1, in6_a2, in6_a3;
+ struct stat st;
+ int is_bcast = 0;
+
+ if (bcast) *bcast = 0;
+
+ switch (si->family) {
+ case AF_INET: {
+ const struct sockaddr_in *in =
+ (const struct sockaddr_in *)(const void *)inaddr;
+ unsigned int addr = ntohl(in->sin_addr.s_addr);
+ char u_type = '\0';
+ char d_type = '\0';
+ char b_type = '\0';
+ char a_type = '\0';
+
+ prt = ntohs(in->sin_port);
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ u_type = SOCKET_TYPE_CHAR_TCP_LONG;
+ d_type = SOCKET_TYPE_CHAR_TCP_LONG;
+ break;
+ case SOCK_DGRAM:
+ u_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ d_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ a_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ b_type = SOCKET_TYPE_CHAR_UDP_LONG;
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ if (addr == 0) {
+ /* 0.0.0.0 */
+ is_bcast = 0;
+ type = d_type;
+ in4_addr = socket_wrapper_default_addr();
+ } else if (a_type && addr == 0xFFFFFFFF) {
+ /* 255.255.255.255 only udp */
+ is_bcast = 2;
+ type = a_type;
+ in4_addr = socket_wrapper_default_addr();
+ } else if (b_type && addr == 0x7FFFFFFF) {
+ /* 127.255.255.255 only udp */
+ is_bcast = 1;
+ type = b_type;
+ in4_addr = socket_wrapper_default_addr();
+ } else {
+ /* 127.0.0.X */
+ is_bcast = 0;
+ type = u_type;
+ in4_addr = addr;
+ }
+
+ /* Store the bind address for connect() */
+ if (si->bindname.sa_socklen == 0) {
+ struct sockaddr_in bind_in;
+ socklen_t blen = sizeof(struct sockaddr_in);
+
+ ZERO_STRUCT(bind_in);
+ bind_in.sin_family = in->sin_family;
+ bind_in.sin_port = in->sin_port;
+ bind_in.sin_addr.s_addr = htonl(in4_addr);
+
+ si->bindname.sa_socklen = blen;
+ memcpy(&si->bindname.sa.in, &bind_in, blen);
+ }
+
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *in =
+ (const struct sockaddr_in6 *)(const void *)inaddr;
+ struct sockaddr_in6 in6_addr = *in;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6_LONG;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6_LONG;
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ /* XXX no multicast/broadcast */
+
+ prt = ntohs(in->sin6_port);
+
+ /* TODO - More checks */
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
+ in6_addr.sin6_addr = *swrap_ipv6();
+ in6_addr.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
+ }
+
+ swrap_make_ipv6_ints(in6_addr.sin6_addr.s6_addr,&in6_a0,&in6_a1,&in6_a2,&in6_a3);
+
+ /* Store the bind address for connect() */
+ if (si->bindname.sa_socklen == 0) {
+ struct sockaddr_in6 bind_in;
+ socklen_t blen = sizeof(struct sockaddr_in6);
+
+ ZERO_STRUCT(bind_in);
+ bind_in.sin6_family = in6_addr.sin6_family;
+ bind_in.sin6_port = in6_addr.sin6_port;
+
+ bind_in.sin6_addr = in6_addr.sin6_addr;
+
+ memcpy(&si->bindname.sa.in6, &bind_in, blen);
+ si->bindname.sa_socklen = blen;
+ }
+
+ break;
+ }
+#endif
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
+ errno = EADDRNOTAVAIL;
+ return -1;
+ }
+
+
+ if (bcast) *bcast = is_bcast;
+
+
+ if (prt == 0) {
+ /* handle auto-allocation of ephemeral ports */
+ for (prt = 5001; prt < 10000; prt++) {
+ if (si->family == AF_INET)
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_LONG,
+ socket_wrapper_dir(), type, in4_addr, prt);
+ else
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_V6_LONG,
+ socket_wrapper_dir(), type, in6_a0,in6_a1, in6_a2, in6_a3, prt);
+
+ if (stat(un->sun_path, &st) == 0) continue;
+
+ set_port(si->family, prt, &si->myname);
+ set_port(si->family, prt, &si->bindname);
+
+ break;
+ }
+ if (prt == 10000) {
+ errno = ENFILE;
+ return -1;
+ }
+ }
+
+ if (si->family == AF_INET)
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_LONG,
+ socket_wrapper_dir(), type, in4_addr, prt);
+ else
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT_V6_LONG,
+ socket_wrapper_dir(), type, in6_a0,in6_a1, in6_a2, in6_a3, prt);
+ SWRAP_LOG(SWRAP_LOG_DEBUG, "un path [%s]", un->sun_path);
+ return 0;
+}
+
+static struct socket_info *find_socket_info(int fd)
+{
+ struct socket_info *i;
+
+ for (i = sockets; i; i = i->next) {
+ struct socket_info_fd *f;
+ for (f = i->fds; f; f = f->next) {
+ if (f->fd == fd) {
+ return i;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+#if 0 /* FIXME */
+static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
+{
+ struct socket_info *s;
+
+ /* first catch invalid input */
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (len < sizeof(struct sockaddr_in)) {
+ return false;
+ }
+ break;
+#if HAVE_IPV6
+ case AF_INET6:
+ if (len < sizeof(struct sockaddr_in6)) {
+ return false;
+ }
+ break;
+#endif
+ default:
+ return false;
+ break;
+ }
+
+ for (s = sockets; s != NULL; s = s->next) {
+ if (s->myname == NULL) {
+ continue;
+ }
+ if (s->myname->sa_family != sa->sa_family) {
+ continue;
+ }
+ switch (s->myname->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in *)s->myname;
+ sin2 = (struct sockaddr_in *)sa;
+
+ if (sin1->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ continue;
+ }
+ if (sin1->sin_port != sin2->sin_port) {
+ continue;
+ }
+ if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#if HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin1, *sin2;
+
+ sin1 = (struct sockaddr_in6 *)s->myname;
+ sin2 = (struct sockaddr_in6 *)sa;
+
+ if (sin1->sin6_port != sin2->sin6_port) {
+ continue;
+ }
+ if (!IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr,
+ &sin2->sin6_addr))
+ {
+ continue;
+ }
+
+ /* found */
+ return true;
+ break;
+ }
+#endif
+ default:
+ continue;
+ break;
+
+ }
+ }
+
+ return false;
+}
+#endif
+
+static void swrap_remove_stale(int fd)
+{
+ struct socket_info *si = find_socket_info(fd);
+ struct socket_info_fd *fi;
+
+ if (si != NULL) {
+ for (fi = si->fds; fi; fi = fi->next) {
+ if (fi->fd == fd) {
+ SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
+ SWRAP_DLIST_REMOVE(si->fds, fi);
+ free(fi);
+ break;
+ }
+ }
+
+ if (si->fds == NULL) {
+ SWRAP_DLIST_REMOVE(sockets, si);
+ if (si->un_addr.sun_path[0] != '\0') {
+ unlink(si->un_addr.sun_path);
+ }
+ free(si);
+ }
+ }
+}
+
+static int sockaddr_convert_to_un(struct socket_info *si,
+ const struct sockaddr *in_addr,
+ socklen_t in_len,
+ struct sockaddr_un *out_addr,
+ int alloc_sock,
+ int *bcast)
+{
+ struct sockaddr *out = (struct sockaddr *)(void *)out_addr;
+
+ (void) in_len; /* unused */
+
+ if (out_addr == NULL) {
+ return 0;
+ }
+
+ out->sa_family = AF_UNIX;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ out->sa_len = sizeof(*out_addr);
+#endif
+
+ switch (in_addr->sa_family) {
+ case AF_UNSPEC: {
+ const struct sockaddr_in *sin;
+ if (si->family != AF_INET) {
+ break;
+ }
+ if (in_len < sizeof(struct sockaddr_in)) {
+ break;
+ }
+ sin = (const struct sockaddr_in *)(const void *)in_addr;
+ if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
+ break;
+ }
+
+ /*
+ * Note: in the special case of AF_UNSPEC and INADDR_ANY,
+ * AF_UNSPEC is mapped to AF_INET and must be treated here.
+ */
+
+ /* FALL THROUGH */
+ }
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ if (alloc_sock) {
+ return convert_in_un_alloc(si, in_addr, out_addr, bcast);
+ } else {
+ return convert_in_un_remote(si, in_addr, out_addr, bcast);
+ }
+ default:
+ break;
+ }
+
+ errno = EAFNOSUPPORT;
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
+ return -1;
+}
+
+static int sockaddr_convert_from_un(const struct socket_info *si,
+ const struct sockaddr_un *in_addr,
+ socklen_t un_addrlen,
+ int family,
+ struct sockaddr *out_addr,
+ socklen_t *out_addrlen)
+{
+ int ret;
+
+ if (out_addr == NULL || out_addrlen == NULL)
+ return 0;
+
+ if (un_addrlen == 0) {
+ *out_addrlen = 0;
+ return 0;
+ }
+
+ switch (family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ switch (si->type) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown socket type!\n");
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+ ret = convert_un_in(in_addr, out_addr, out_addrlen);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ out_addr->sa_len = *out_addrlen;
+#endif
+ return ret;
+ default:
+ break;
+ }
+
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Unknown address family\n");
+ errno = EAFNOSUPPORT;
+ return -1;
+}
+
+enum swrap_packet_type {
+ SWRAP_CONNECT_SEND,
+ SWRAP_CONNECT_UNREACH,
+ SWRAP_CONNECT_RECV,
+ SWRAP_CONNECT_ACK,
+ SWRAP_ACCEPT_SEND,
+ SWRAP_ACCEPT_RECV,
+ SWRAP_ACCEPT_ACK,
+ SWRAP_RECVFROM,
+ SWRAP_SENDTO,
+ SWRAP_SENDTO_UNREACH,
+ SWRAP_PENDING_RST,
+ SWRAP_RECV,
+ SWRAP_RECV_RST,
+ SWRAP_SEND,
+ SWRAP_SEND_RST,
+ SWRAP_CLOSE_SEND,
+ SWRAP_CLOSE_RECV,
+ SWRAP_CLOSE_ACK,
+};
+
+struct swrap_file_hdr {
+ uint32_t magic;
+ uint16_t version_major;
+ uint16_t version_minor;
+ int32_t timezone;
+ uint32_t sigfigs;
+ uint32_t frame_max_len;
+#define SWRAP_FRAME_LENGTH_MAX 0xFFFF
+ uint32_t link_type;
+};
+#define SWRAP_FILE_HDR_SIZE 24
+
+struct swrap_packet_frame {
+ uint32_t seconds;
+ uint32_t micro_seconds;
+ uint32_t recorded_length;
+ uint32_t full_length;
+};
+#define SWRAP_PACKET_FRAME_SIZE 16
+
+union swrap_packet_ip {
+ struct {
+ uint8_t ver_hdrlen;
+ uint8_t tos;
+ uint16_t packet_length;
+ uint16_t identification;
+ uint8_t flags;
+ uint8_t fragment;
+ uint8_t ttl;
+ uint8_t protocol;
+ uint16_t hdr_checksum;
+ uint32_t src_addr;
+ uint32_t dest_addr;
+ } v4;
+#define SWRAP_PACKET_IP_V4_SIZE 20
+ struct {
+ uint8_t ver_prio;
+ uint8_t flow_label_high;
+ uint16_t flow_label_low;
+ uint16_t payload_length;
+ uint8_t next_header;
+ uint8_t hop_limit;
+ uint8_t src_addr[16];
+ uint8_t dest_addr[16];
+ } v6;
+#define SWRAP_PACKET_IP_V6_SIZE 40
+};
+#define SWRAP_PACKET_IP_SIZE 40
+
+union swrap_packet_payload {
+ struct {
+ uint16_t source_port;
+ uint16_t dest_port;
+ uint32_t seq_num;
+ uint32_t ack_num;
+ uint8_t hdr_length;
+ uint8_t control;
+ uint16_t window;
+ uint16_t checksum;
+ uint16_t urg;
+ } tcp;
+#define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
+ struct {
+ uint16_t source_port;
+ uint16_t dest_port;
+ uint16_t length;
+ uint16_t checksum;
+ } udp;
+#define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
+ struct {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t unused;
+ } icmp4;
+#define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
+ struct {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t unused;
+ } icmp6;
+#define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
+};
+#define SWRAP_PACKET_PAYLOAD_SIZE 20
+
+#define SWRAP_PACKET_MIN_ALLOC \
+ (SWRAP_PACKET_FRAME_SIZE + \
+ SWRAP_PACKET_IP_SIZE + \
+ SWRAP_PACKET_PAYLOAD_SIZE)
+
+static const char *swrap_pcap_init_file(void)
+{
+ static const char *s = NULL;
+ static const struct swrap_file_hdr h;
+ static const struct swrap_packet_frame f;
+ static const union swrap_packet_ip i;
+ static const union swrap_packet_payload p;
+
+ // if (initialized == 1) {
+ // printf("return: 1\n");
+ // return s;
+ // }
+ // initialized = 1;
+
+ /*
+ * TODO: don't use the structs use plain buffer offsets
+ * and PUSH_U8(), PUSH_U16() and PUSH_U32()
+ *
+ * for now make sure we disable PCAP support
+ * if the struct has alignment!
+ */
+ if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
+ return NULL;
+ }
+ if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
+ return NULL;
+ }
+ if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
+ return NULL;
+ }
+ if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
+ return NULL;
+ }
+ if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
+ return NULL;
+ }
+
+ s = getenv("SOCKET_WRAPPER_PCAP_FILE");
+ if (s == NULL) {
+ return NULL;
+ }
+ if (strncmp(s, "./", 2) == 0) {
+ s += 2;
+ }
+ return s;
+}
+
+static uint8_t *swrap_pcap_packet_init(struct timeval *tval,
+ const struct sockaddr *src,
+ const struct sockaddr *dest,
+ int socket_type,
+ const uint8_t *payload,
+ size_t payload_len,
+ unsigned long tcp_seqno,
+ unsigned long tcp_ack,
+ unsigned char tcp_ctl,
+ int unreachable,
+ size_t *_packet_len)
+{
+ uint8_t *base;
+ uint8_t *buf;
+ struct swrap_packet_frame *frame;
+ union swrap_packet_ip *ip;
+ union swrap_packet_payload *pay;
+ size_t packet_len;
+ size_t alloc_len;
+ size_t nonwire_len = sizeof(*frame);
+ size_t wire_hdr_len = 0;
+ size_t wire_len = 0;
+ size_t ip_hdr_len = 0;
+ size_t icmp_hdr_len = 0;
+ size_t icmp_truncate_len = 0;
+ uint8_t protocol = 0, icmp_protocol = 0;
+ const struct sockaddr_in *src_in = NULL;
+ const struct sockaddr_in *dest_in = NULL;
+#ifdef HAVE_IPV6
+ const struct sockaddr_in6 *src_in6 = NULL;
+ const struct sockaddr_in6 *dest_in6 = NULL;
+#endif
+ uint16_t src_port;
+ uint16_t dest_port;
+
+ switch (src->sa_family) {
+ case AF_INET:
+ src_in = (const struct sockaddr_in *)(const void *)src;
+ dest_in = (const struct sockaddr_in *)(const void *)dest;
+ src_port = src_in->sin_port;
+ dest_port = dest_in->sin_port;
+ ip_hdr_len = sizeof(ip->v4);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ src_in6 = (const struct sockaddr_in6 *)(const void *)src;
+ dest_in6 = (const struct sockaddr_in6 *)(const void *)dest;
+ src_port = src_in6->sin6_port;
+ dest_port = dest_in6->sin6_port;
+ ip_hdr_len = sizeof(ip->v6);
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ protocol = 0x06; /* TCP */
+ wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+
+ case SOCK_DGRAM:
+ protocol = 0x11; /* UDP */
+ wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
+ wire_len = wire_hdr_len + payload_len;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (unreachable) {
+ icmp_protocol = protocol;
+ switch (src->sa_family) {
+ case AF_INET:
+ protocol = 0x01; /* ICMPv4 */
+ icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ protocol = 0x3A; /* ICMPv6 */
+ icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
+ break;
+#endif
+ }
+ if (wire_len > 64 ) {
+ icmp_truncate_len = wire_len - 64;
+ }
+ wire_hdr_len += icmp_hdr_len;
+ wire_len += icmp_hdr_len;
+ }
+
+ packet_len = nonwire_len + wire_len;
+ alloc_len = packet_len;
+ if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
+ alloc_len = SWRAP_PACKET_MIN_ALLOC;
+ }
+
+ base = (uint8_t *)calloc(1, alloc_len);
+ if (base == NULL) {
+ return NULL;
+ }
+
+ buf = base;
+
+ frame = (struct swrap_packet_frame *)(void *)buf;
+ frame->seconds = tval->tv_sec;
+ frame->micro_seconds = tval->tv_usec;
+ frame->recorded_length = wire_len - icmp_truncate_len;
+ frame->full_length = wire_len - icmp_truncate_len;
+ buf += SWRAP_PACKET_FRAME_SIZE;
+
+ ip = (union swrap_packet_ip *)(void *)buf;
+ switch (src->sa_family) {
+ case AF_INET:
+ ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ ip->v4.tos = 0x00;
+ ip->v4.packet_length = htons(wire_len - icmp_truncate_len);
+ ip->v4.identification = htons(0xFFFF);
+ ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
+ ip->v4.fragment = htons(0x0000);
+ ip->v4.ttl = 0xFF;
+ ip->v4.protocol = protocol;
+ ip->v4.hdr_checksum = htons(0x0000);
+ ip->v4.src_addr = src_in->sin_addr.s_addr;
+ ip->v4.dest_addr = dest_in->sin_addr.s_addr;
+ buf += SWRAP_PACKET_IP_V4_SIZE;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
+ ip->v6.flow_label_high = 0x00;
+ ip->v6.flow_label_low = 0x0000;
+ ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
+ ip->v6.next_header = protocol;
+ memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
+ memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
+ buf += SWRAP_PACKET_IP_V6_SIZE;
+ break;
+#endif
+ }
+
+ if (unreachable) {
+ pay = (union swrap_packet_payload *)(void *)buf;
+ switch (src->sa_family) {
+ case AF_INET:
+ pay->icmp4.type = 0x03; /* destination unreachable */
+ pay->icmp4.code = 0x01; /* host unreachable */
+ pay->icmp4.checksum = htons(0x0000);
+ pay->icmp4.unused = htonl(0x00000000);
+ buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
+
+ /* set the ip header in the ICMP payload */
+ ip = (union swrap_packet_ip *)(void *)buf;
+ ip->v4.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
+ ip->v4.tos = 0x00;
+ ip->v4.packet_length = htons(wire_len - icmp_hdr_len);
+ ip->v4.identification = htons(0xFFFF);
+ ip->v4.flags = 0x40; /* BIT 1 set - means don't fragment */
+ ip->v4.fragment = htons(0x0000);
+ ip->v4.ttl = 0xFF;
+ ip->v4.protocol = icmp_protocol;
+ ip->v4.hdr_checksum = htons(0x0000);
+ ip->v4.src_addr = dest_in->sin_addr.s_addr;
+ ip->v4.dest_addr = src_in->sin_addr.s_addr;
+ buf += SWRAP_PACKET_IP_V4_SIZE;
+
+ src_port = dest_in->sin_port;
+ dest_port = src_in->sin_port;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ pay->icmp6.type = 0x01; /* destination unreachable */
+ pay->icmp6.code = 0x03; /* address unreachable */
+ pay->icmp6.checksum = htons(0x0000);
+ pay->icmp6.unused = htonl(0x00000000);
+ buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
+
+ /* set the ip header in the ICMP payload */
+ ip = (union swrap_packet_ip *)(void *)buf;
+ ip->v6.ver_prio = 0x60; /* version 4 and 5 * 32 bit words */
+ ip->v6.flow_label_high = 0x00;
+ ip->v6.flow_label_low = 0x0000;
+ ip->v6.payload_length = htons(wire_len - icmp_truncate_len); /* TODO */
+ ip->v6.next_header = protocol;
+ memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
+ memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
+ buf += SWRAP_PACKET_IP_V6_SIZE;
+
+ src_port = dest_in6->sin6_port;
+ dest_port = src_in6->sin6_port;
+ break;
+#endif
+ }
+ }
+
+ pay = (union swrap_packet_payload *)(void *)buf;
+
+ switch (socket_type) {
+ case SOCK_STREAM:
+ pay->tcp.source_port = src_port;
+ pay->tcp.dest_port = dest_port;
+ pay->tcp.seq_num = htonl(tcp_seqno);
+ pay->tcp.ack_num = htonl(tcp_ack);
+ pay->tcp.hdr_length = 0x50; /* 5 * 32 bit words */
+ pay->tcp.control = tcp_ctl;
+ pay->tcp.window = htons(0x7FFF);
+ pay->tcp.checksum = htons(0x0000);
+ pay->tcp.urg = htons(0x0000);
+ buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
+
+ break;
+
+ case SOCK_DGRAM:
+ pay->udp.source_port = src_port;
+ pay->udp.dest_port = dest_port;
+ pay->udp.length = htons(8 + payload_len);
+ pay->udp.checksum = htons(0x0000);
+ buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
+
+ break;
+ }
+
+ if (payload && payload_len > 0) {
+ memcpy(buf, payload, payload_len);
+ }
+
+ *_packet_len = packet_len - icmp_truncate_len;
+ return base;
+}
+
+static int swrap_pcap_get_fd(const char *fname)
+{
+ int fd = -1;
+
+ // if (fd != -1) return fd;
+
+ fd = libc_open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
+ if (fd != -1) {
+ struct swrap_file_hdr file_hdr;
+ file_hdr.magic = 0xA1B2C3D4;
+ file_hdr.version_major = 0x0002;
+ file_hdr.version_minor = 0x0004;
+ file_hdr.timezone = 0x00000000;
+ file_hdr.sigfigs = 0x00000000;
+ file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
+ file_hdr.link_type = 0x0065; /* 101 RAW IP */
+
+ if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
+ close(fd);
+ fd = -1;
+ }
+ return fd;
+ }
+
+ fd = libc_open(fname, O_WRONLY|O_APPEND, 0644);
+
+ return fd;
+}
+
+static uint8_t *swrap_pcap_marshall_packet(struct socket_info *si,
+ const struct sockaddr *addr,
+ enum swrap_packet_type type,
+ const void *buf, size_t len,
+ size_t *packet_len)
+{
+ const struct sockaddr *src_addr;
+ const struct sockaddr *dest_addr;
+ unsigned long tcp_seqno = 0;
+ unsigned long tcp_ack = 0;
+ unsigned char tcp_ctl = 0;
+ int unreachable = 0;
+
+ struct timeval tv;
+
+ switch (si->family) {
+ case AF_INET:
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ switch (type) {
+ case SWRAP_CONNECT_SEND:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ src_addr = &si->myname.sa.s;
+ dest_addr = addr;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CONNECT_RECV:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x12; /** SYN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CONNECT_UNREACH:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
+ tcp_seqno = si->io.pck_snd - 1;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x02; /* SYN */
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_CONNECT_ACK:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ src_addr = &si->myname.sa.s;
+ dest_addr = addr;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_ACCEPT_SEND:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x02; /* SYN */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_RECV:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ src_addr = &si->myname.sa.s;
+ dest_addr = addr;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x12; /* SYN,ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_ACCEPT_ACK:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+
+ case SWRAP_SEND:
+ src_addr = &si->myname.sa.s;
+ dest_addr = &si->peername.sa.s;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SEND_RST:
+ dest_addr = &si->myname.sa.s;
+ src_addr = &si->peername.sa.s;
+
+ if (si->type == SOCK_DGRAM) {
+ return swrap_pcap_marshall_packet(si,
+ &si->peername.sa.s,
+ SWRAP_SENDTO_UNREACH,
+ buf,
+ len,
+ packet_len);
+ }
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /** RST,ACK */
+
+ break;
+
+ case SWRAP_PENDING_RST:
+ dest_addr = &si->myname.sa.s;
+ src_addr = &si->peername.sa.s;
+
+ if (si->type == SOCK_DGRAM) {
+ return NULL;
+ }
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_RECV:
+ dest_addr = &si->myname.sa.s;
+ src_addr = &si->peername.sa.s;
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x18; /* PSH,ACK */
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_RECV_RST:
+ dest_addr = &si->myname.sa.s;
+ src_addr = &si->peername.sa.s;
+
+ if (si->type == SOCK_DGRAM) {
+ return NULL;
+ }
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x14; /* RST,ACK */
+
+ break;
+
+ case SWRAP_SENDTO:
+ src_addr = &si->myname.sa.s;
+ dest_addr = addr;
+
+ si->io.pck_snd += len;
+
+ break;
+
+ case SWRAP_SENDTO_UNREACH:
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ unreachable = 1;
+
+ break;
+
+ case SWRAP_RECVFROM:
+ dest_addr = &si->myname.sa.s;
+ src_addr = addr;
+
+ si->io.pck_rcv += len;
+
+ break;
+
+ case SWRAP_CLOSE_SEND:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ src_addr = &si->myname.sa.s;
+ dest_addr = &si->peername.sa.s;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x11; /* FIN, ACK */
+
+ si->io.pck_snd += 1;
+
+ break;
+
+ case SWRAP_CLOSE_RECV:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ dest_addr = &si->myname.sa.s;
+ src_addr = &si->peername.sa.s;
+
+ tcp_seqno = si->io.pck_rcv;
+ tcp_ack = si->io.pck_snd;
+ tcp_ctl = 0x11; /* FIN,ACK */
+
+ si->io.pck_rcv += 1;
+
+ break;
+
+ case SWRAP_CLOSE_ACK:
+ if (si->type != SOCK_STREAM) return NULL;
+
+ src_addr = &si->myname.sa.s;
+ dest_addr = &si->peername.sa.s;
+
+ tcp_seqno = si->io.pck_snd;
+ tcp_ack = si->io.pck_rcv;
+ tcp_ctl = 0x10; /* ACK */
+
+ break;
+ default:
+ return NULL;
+ }
+
+ swrapGetTimeOfDay(&tv);
+
+ return swrap_pcap_packet_init(&tv,
+ src_addr,
+ dest_addr,
+ si->type,
+ (const uint8_t *)buf,
+ len,
+ tcp_seqno,
+ tcp_ack,
+ tcp_ctl,
+ unreachable,
+ packet_len);
+}
+
+static void swrap_pcap_dump_packet(struct socket_info *si,
+ const struct sockaddr *addr,
+ enum swrap_packet_type type,
+ const void *buf, size_t len)
+{
+ const char *file_name;
+ uint8_t *packet;
+ size_t packet_len = 0;
+ int fd;
+
+ file_name = swrap_pcap_init_file();
+ if (!file_name) {
+ return;
+ }
+
+ packet = swrap_pcap_marshall_packet(si,
+ addr,
+ type,
+ buf,
+ len,
+ &packet_len);
+ if (packet == NULL) {
+ return;
+ }
+
+ fd = swrap_pcap_get_fd(file_name);
+ if (fd != -1) {
+ if (write(fd, packet, packet_len) != (ssize_t)packet_len) {
+ close(fd);
+ free(packet);
+ return;
+ }
+ }
+ close(fd);
+ free(packet);
+}
+
+/****************************************************************************
+ * SIGNALFD
+ ***************************************************************************/
+
+#ifdef HAVE_SIGNALFD
+static int swrap_signalfd(int fd, const sigset_t *mask, int flags)
+{
+ int rc;
+
+ rc = libc_signalfd(fd, mask, flags);
+ if (rc != -1) {
+ swrap_remove_stale(fd);
+ }
+
+ return rc;
+}
+
+int signalfd(int fd, const sigset_t *mask, int flags)
+{
+ return swrap_signalfd(fd, mask, flags);
+}
+#endif
+
+/****************************************************************************
+ * SOCKET
+ ***************************************************************************/
+
+static int swrap_socket(int family, int type, int protocol)
+{
+ struct socket_info *si;
+ struct socket_info_fd *fi;
+ int fd;
+ int real_type = type;
+
+ /*
+ * Remove possible addition flags passed to socket() so
+ * do not fail checking the type.
+ * See https://lwn.net/Articles/281965/
+ */
+#ifdef SOCK_CLOEXEC
+ real_type &= ~SOCK_CLOEXEC;
+#endif
+#ifdef SOCK_NONBLOCK
+ real_type &= ~SOCK_NONBLOCK;
+#endif
+
+ if (!socket_wrapper_enabled()) {
+ return libc_socket(family, type, protocol);
+ }
+
+ switch (family) {
+ case AF_INET:
+#ifdef HAVE_IPV6
+ case AF_INET6:
+#endif
+ break;
+#ifdef AF_NETLINK
+ case AF_NETLINK:
+#endif /* AF_NETLINK */
+#ifdef AF_PACKET
+ case AF_PACKET:
+#endif /* AF_PACKET */
+ case AF_UNIX:
+ return libc_socket(family, type, protocol);
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ switch (real_type) {
+ case SOCK_STREAM:
+ break;
+ case SOCK_DGRAM:
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ switch (protocol) {
+ case 0:
+ break;
+ case 6:
+ if (real_type == SOCK_STREAM) {
+ break;
+ }
+ /*fall through*/
+ case 17:
+ if (real_type == SOCK_DGRAM) {
+ break;
+ }
+ /*fall through*/
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+
+ /*
+ * We must call libc_socket with type, from the caller, not the version
+ * we removed SOCK_CLOEXEC and SOCK_NONBLOCK from
+ */
+ fd = libc_socket(AF_UNIX, type, 0);
+
+ if (fd == -1) {
+ return -1;
+ }
+
+ /* Check if we have a stale fd and remove it */
+ si = find_socket_info(fd);
+ if (si != NULL) {
+ swrap_remove_stale(fd);
+ }
+
+ si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+ if (si == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ si->family = family;
+
+ /* however, the rest of the socket_wrapper code expects just
+ * the type, not the flags */
+ si->type = real_type;
+ si->protocol = protocol;
+
+ /*
+ * Setup myname so getsockname() can succeed to find out the socket
+ * type.
+ */
+ switch(si->family) {
+ case AF_INET: {
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ };
+
+ si->myname.sa_socklen = sizeof(struct sockaddr_in);
+ memcpy(&si->myname.sa.in, &sin, si->myname.sa_socklen);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ };
+
+ si->myname.sa_socklen = sizeof(struct sockaddr_in6);
+ memcpy(&si->myname.sa.in6, &sin6, si->myname.sa_socklen);
+ break;
+ }
+ default:
+ free(si);
+ errno = EINVAL;
+ return -1;
+ }
+
+ fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
+ if (fi == NULL) {
+ free(si);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ fi->fd = fd;
+
+ SWRAP_DLIST_ADD(si->fds, fi);
+ SWRAP_DLIST_ADD(sockets, si);
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "Created %s socket for protocol %s",
+ si->family == AF_INET ? "IPv4" : "IPv6",
+ si->type == SOCK_DGRAM ? "UDP" : "TCP");
+
+ return fd;
+}
+
+int socket(int family, int type, int protocol)
+{
+ return swrap_socket(family, type, protocol);
+}
+
+/****************************************************************************
+ * SOCKETPAIR
+ ***************************************************************************/
+
+static int swrap_socketpair(int family, int type, int protocol, int sv[2])
+{
+ int rc;
+
+ rc = libc_socketpair(family, type, protocol, sv);
+ if (rc != -1) {
+ swrap_remove_stale(sv[0]);
+ swrap_remove_stale(sv[1]);
+ }
+
+ return rc;
+}
+
+int socketpair(int family, int type, int protocol, int sv[2])
+{
+ return swrap_socketpair(family, type, protocol, sv);
+}
+
+/****************************************************************************
+ * SOCKETPAIR
+ ***************************************************************************/
+
+#ifdef HAVE_TIMERFD_CREATE
+static int swrap_timerfd_create(int clockid, int flags)
+{
+ int fd;
+
+ fd = libc_timerfd_create(clockid, flags);
+ if (fd != -1) {
+ swrap_remove_stale(fd);
+ }
+
+ return fd;
+}
+
+int timerfd_create(int clockid, int flags)
+{
+ return swrap_timerfd_create(clockid, flags);
+}
+#endif
+
+/****************************************************************************
+ * PIPE
+ ***************************************************************************/
+
+static int swrap_pipe(int pipefd[2])
+{
+ int rc;
+
+ rc = libc_pipe(pipefd);
+ if (rc != -1) {
+ swrap_remove_stale(pipefd[0]);
+ swrap_remove_stale(pipefd[1]);
+ }
+
+ return rc;
+}
+
+int pipe(int pipefd[2])
+{
+ return swrap_pipe(pipefd);
+}
+
+/****************************************************************************
+ * ACCEPT
+ ***************************************************************************/
+
+static int swrap_accept(int s,
+ struct sockaddr *addr,
+ socklen_t *addrlen,
+ int flags)
+{
+ struct socket_info *parent_si, *child_si;
+ struct socket_info_fd *child_fi;
+ int fd;
+ struct swrap_address un_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ struct swrap_address un_my_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ struct swrap_address in_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct swrap_address in_my_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int ret;
+
+ parent_si = find_socket_info(s);
+ if (!parent_si) {
+#ifdef HAVE_ACCEPT4
+ return libc_accept4(s, addr, addrlen, flags);
+#else
+ return libc_accept(s, addr, addrlen);
+#endif
+ }
+
+ /*
+ * assume out sockaddr have the same size as the in parent
+ * socket family
+ */
+ in_addr.sa_socklen = socket_length(parent_si->family);
+ if (in_addr.sa_socklen <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+#ifdef HAVE_ACCEPT4
+ ret = libc_accept4(s, &un_addr.sa.s, &un_addr.sa_socklen, flags);
+#else
+ ret = libc_accept(s, &un_addr.sa.s, &un_addr.sa_socklen);
+#endif
+ if (ret == -1) {
+ if (errno == ENOTSOCK) {
+ /* Remove stale fds */
+ swrap_remove_stale(s);
+ }
+ return ret;
+ }
+
+ fd = ret;
+
+ ret = sockaddr_convert_from_un(parent_si,
+ &un_addr.sa.un,
+ un_addr.sa_socklen,
+ parent_si->family,
+ &in_addr.sa.s,
+ &in_addr.sa_socklen);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+
+ child_si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
+ if (child_si == NULL) {
+ close(fd);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
+ if (child_fi == NULL) {
+ free(child_si);
+ close(fd);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ child_fi->fd = fd;
+
+ SWRAP_DLIST_ADD(child_si->fds, child_fi);
+
+ child_si->family = parent_si->family;
+ child_si->type = parent_si->type;
+ child_si->protocol = parent_si->protocol;
+ child_si->bound = 1;
+ child_si->is_server = 1;
+ child_si->connected = 1;
+
+ child_si->peername = (struct swrap_address) {
+ .sa_socklen = in_addr.sa_socklen,
+ };
+ memcpy(&child_si->peername.sa.ss, &in_addr.sa.ss, in_addr.sa_socklen);
+
+ if (addr != NULL && addrlen != NULL) {
+ size_t copy_len = MIN(*addrlen, in_addr.sa_socklen);
+ if (copy_len > 0) {
+ memcpy(addr, &in_addr.sa.ss, copy_len);
+ }
+ *addrlen = in_addr.sa_socklen;
+ }
+
+ ret = libc_getsockname(fd,
+ &un_my_addr.sa.s,
+ &un_my_addr.sa_socklen);
+ if (ret == -1) {
+ free(child_fi);
+ free(child_si);
+ close(fd);
+ return ret;
+ }
+
+ ret = sockaddr_convert_from_un(child_si,
+ &un_my_addr.sa.un,
+ un_my_addr.sa_socklen,
+ child_si->family,
+ &in_my_addr.sa.s,
+ &in_my_addr.sa_socklen);
+ if (ret == -1) {
+ free(child_fi);
+ free(child_si);
+ close(fd);
+ return ret;
+ }
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "accept() path=%s, fd=%d",
+ un_my_addr.sa.un.sun_path, s);
+
+ child_si->myname = (struct swrap_address) {
+ .sa_socklen = in_my_addr.sa_socklen,
+ };
+ memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
+
+ SWRAP_DLIST_ADD(sockets, child_si);
+
+ if (addr != NULL) {
+ swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
+ swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
+ swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
+ }
+
+ return fd;
+}
+
+#ifdef HAVE_ACCEPT4
+int accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags)
+{
+ return swrap_accept(s, addr, (socklen_t *)addrlen, flags);
+}
+#endif
+
+#ifdef HAVE_ACCEPT_PSOCKLEN_T
+int accept(int s, struct sockaddr *addr, Psocklen_t addrlen)
+#else
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+#endif
+{
+ return swrap_accept(s, addr, (socklen_t *)addrlen, 0);
+}
+
+static int autobind_start_init;
+static int autobind_start;
+
+/* using sendto() or connect() on an unbound socket would give the
+ recipient no way to reply, as unlike UDP and TCP, a unix domain
+ socket can't auto-assign ephemeral port numbers, so we need to
+ assign it here.
+ Note: this might change the family from ipv6 to ipv4
+*/
+static int swrap_auto_bind(int fd, struct socket_info *si, int family)
+{
+ struct swrap_address un_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ int i;
+ char type;
+ int ret;
+ int port;
+ unsigned int in4_addr, in6_a0, in6_a1, in6_a2, in6_a3;
+ struct stat st;
+
+ if (autobind_start_init != 1) {
+ autobind_start_init = 1;
+ autobind_start = getpid();
+ autobind_start %= 50000;
+ autobind_start += 10000;
+ }
+
+ un_addr.sa.un.sun_family = AF_UNIX;
+
+ switch (family) {
+ case AF_INET: {
+ struct sockaddr_in in;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_LONG;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_LONG;
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ in4_addr = socket_wrapper_default_addr();
+ in.sin_addr.s_addr = htonl(in4_addr);
+
+ si->myname = (struct swrap_address) {
+ .sa_socklen = sizeof(in),
+ };
+ memcpy(&si->myname.sa.in, &in, si->myname.sa_socklen);
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 in6;
+
+ if (si->family != family) {
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ type = SOCKET_TYPE_CHAR_TCP_V6_LONG;
+ break;
+ case SOCK_DGRAM:
+ type = SOCKET_TYPE_CHAR_UDP_V6_LONG;
+ break;
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ memset(&in6, 0, sizeof(in6));
+ in6.sin6_family = AF_INET6;
+ in6.sin6_addr = *swrap_ipv6();
+ in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
+
+ si->myname = (struct swrap_address) {
+ .sa_socklen = sizeof(in6),
+ };
+ memcpy(&si->myname.sa.in6, &in6, si->myname.sa_socklen);
+ swrap_make_ipv6_ints(in6.sin6_addr.s6_addr,&in6_a0,&in6_a1,&in6_a2,&in6_a3);
+ break;
+ }
+#endif
+ default:
+ errno = ESOCKTNOSUPPORT;
+ return -1;
+ }
+
+ if (autobind_start > 60000) {
+ autobind_start = 10000;
+ }
+
+ for (i = 0; i < SOCKET_MAX_SOCKETS; i++) {
+ port = autobind_start + i;
+
+ if (family == AF_INET)
+ snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
+ "%s/"SOCKET_FORMAT_LONG, socket_wrapper_dir(),
+ type, in4_addr, port);
+ else
+ snprintf(un_addr.sa.un.sun_path, sizeof(un_addr.sa.un.sun_path),
+ "%s/"SOCKET_FORMAT_V6_LONG, socket_wrapper_dir(),
+ type, in6_a0,in6_a1, in6_a2, in6_a3, port);
+
+ if (stat(un_addr.sa.un.sun_path, &st) == 0) continue;
+
+ ret = libc_bind(fd, &un_addr.sa.s, un_addr.sa_socklen);
+ if (ret == -1) return ret;
+
+ si->un_addr = un_addr.sa.un;
+
+ si->bound = 1;
+ autobind_start = port + 1;
+ SWRAP_LOG(SWRAP_LOG_TRACE, "bound to: %s", un_addr.sa.un.sun_path);
+ break;
+ }
+ if (i == SOCKET_MAX_SOCKETS) {
+ SWRAP_LOG(SWRAP_LOG_ERROR, "Too many open unix sockets (%u) for "
+ "interface "SOCKET_FORMAT,
+ SOCKET_MAX_SOCKETS,
+ type,
+ socket_wrapper_default_addr(),
+ 0);
+ errno = ENFILE;
+ return -1;
+ }
+
+ si->family = family;
+ set_port(si->family, port, &si->myname);
+
+ return 0;
+}
+
+/****************************************************************************
+ * CONNECT
+ ***************************************************************************/
+
+static int swrap_connect(int s, const struct sockaddr *serv_addr,
+ socklen_t addrlen)
+{
+ int ret;
+ struct swrap_address un_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ struct socket_info *si = find_socket_info(s);
+ int bcast = 0;
+
+ if (!si) {
+ return libc_connect(s, serv_addr, addrlen);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(s, si, serv_addr->sa_family);
+ if (ret == -1) return -1;
+ }
+
+ if (si->family != serv_addr->sa_family) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ret = sockaddr_convert_to_un(si, serv_addr,
+ addrlen, &un_addr.sa.un, 0, &bcast);
+ if (ret == -1) return -1;
+
+ if (bcast) {
+ errno = ENETUNREACH;
+ return -1;
+ }
+
+ if (si->type == SOCK_DGRAM) {
+ si->defer_connect = 1;
+ ret = 0;
+ } else {
+ swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
+
+ ret = libc_connect(s,
+ &un_addr.sa.s,
+ un_addr.sa_socklen);
+ }
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "connect() path=%s, fd=%d",
+ un_addr.sa.un.sun_path, s);
+
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == 0) {
+ si->peername = (struct swrap_address) {
+ .sa_socklen = addrlen,
+ };
+
+ memcpy(&si->peername.sa.ss, serv_addr, addrlen);
+ si->connected = 1;
+
+ /*
+ * When we connect() on a socket than we have to bind the
+ * outgoing connection on the interface we use for the
+ * transport. We already bound it on the right interface
+ * but here we have to update the name so getsockname()
+ * returns correct information.
+ */
+ if (si->bindname.sa_socklen > 0) {
+ si->myname = (struct swrap_address) {
+ .sa_socklen = si->bindname.sa_socklen,
+ };
+
+ memcpy(&si->myname.sa.ss,
+ &si->bindname.sa.ss,
+ si->bindname.sa_socklen);
+
+ /* Cleanup bindname */
+ si->bindname = (struct swrap_address) {
+ .sa_socklen = 0,
+ };
+ }
+
+ swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
+ swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
+ } else {
+ swrap_pcap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
+ }
+
+ return ret;
+}
+
+int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+ return swrap_connect(s, serv_addr, addrlen);
+}
+
+/****************************************************************************
+ * BIND
+ ***************************************************************************/
+
+static int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
+{
+ int ret;
+ struct swrap_address un_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ struct socket_info *si = find_socket_info(s);
+ int bind_error = 0;
+#if 0 /* FIXME */
+ bool in_use;
+#endif
+
+ if (!si) {
+ return libc_bind(s, myaddr, addrlen);
+ }
+
+ switch (si->family) {
+ case AF_INET: {
+ const struct sockaddr_in *sin;
+ if (addrlen < sizeof(struct sockaddr_in)) {
+ bind_error = EINVAL;
+ break;
+ }
+
+ sin = (const struct sockaddr_in *)(const void *)myaddr;
+
+ if (sin->sin_family != AF_INET) {
+ bind_error = EAFNOSUPPORT;
+ }
+
+ /* special case for AF_UNSPEC */
+ if (sin->sin_family == AF_UNSPEC &&
+ (sin->sin_addr.s_addr == htonl(INADDR_ANY)))
+ {
+ bind_error = 0;
+ }
+
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const struct sockaddr_in6 *sin6;
+ if (addrlen < sizeof(struct sockaddr_in6)) {
+ bind_error = EINVAL;
+ break;
+ }
+
+ sin6 = (const struct sockaddr_in6 *)(const void *)myaddr;
+
+ if (sin6->sin6_family != AF_INET6) {
+ bind_error = EAFNOSUPPORT;
+ }
+
+ break;
+ }
+#endif
+ default:
+ bind_error = EINVAL;
+ break;
+ }
+
+ if (bind_error != 0) {
+ errno = bind_error;
+ return -1;
+ }
+
+#if 0 /* FIXME */
+ in_use = check_addr_port_in_use(myaddr, addrlen);
+ if (in_use) {
+ errno = EADDRINUSE;
+ return -1;
+ }
+#endif
+
+ si->myname.sa_socklen = addrlen;
+ memcpy(&si->myname.sa.ss, myaddr, addrlen);
+
+ ret = sockaddr_convert_to_un(si,
+ myaddr,
+ addrlen,
+ &un_addr.sa.un,
+ 1,
+ &si->bcast);
+ if (ret == -1) return -1;
+
+ unlink(un_addr.sa.un.sun_path);
+
+ ret = libc_bind(s, &un_addr.sa.s, un_addr.sa_socklen);
+
+ SWRAP_LOG(SWRAP_LOG_TRACE,
+ "bind() path=%s, fd=%d",
+ un_addr.sa.un.sun_path, s);
+
+ if (ret == 0) {
+ si->bound = 1;
+ }
+
+ return ret;
+}
+
+int bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
+{
+ return swrap_bind(s, myaddr, addrlen);
+}
+
+/****************************************************************************
+ * BINDRESVPORT
+ ***************************************************************************/
+
+#ifdef HAVE_BINDRESVPORT
+static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen);
+
+static int swrap_bindresvport_sa(int sd, struct sockaddr *sa)
+{
+ struct swrap_address myaddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ socklen_t salen;
+ static uint16_t port;
+ uint16_t i;
+ int rc = -1;
+ int af;
+
+#define SWRAP_STARTPORT 600
+#define SWRAP_ENDPORT (IPPORT_RESERVED - 1)
+#define SWRAP_NPORTS (SWRAP_ENDPORT - SWRAP_STARTPORT + 1)
+
+ if (port == 0) {
+ port = (getpid() % SWRAP_NPORTS) + SWRAP_STARTPORT;
+ }
+
+ if (sa == NULL) {
+ salen = myaddr.sa_socklen;
+ sa = &myaddr.sa.s;
+
+ rc = swrap_getsockname(sd, &myaddr.sa.s, &salen);
+ if (rc < 0) {
+ return -1;
+ }
+
+ af = sa->sa_family;
+ memset(&myaddr.sa.ss, 0, salen);
+ } else {
+ af = sa->sa_family;
+ }
+
+ for (i = 0; i < SWRAP_NPORTS; i++, port++) {
+ switch(af) {
+ case AF_INET: {
+ struct sockaddr_in *sinp = (struct sockaddr_in *)(void *)sa;
+
+ salen = sizeof(struct sockaddr_in);
+ sinp->sin_port = htons(port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *)(void *)sa;
+
+ salen = sizeof(struct sockaddr_in6);
+ sin6p->sin6_port = htons(port);
+ break;
+ }
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ sa->sa_family = af;
+
+ if (port > SWRAP_ENDPORT) {
+ port = SWRAP_STARTPORT;
+ }
+
+ rc = swrap_bind(sd, (struct sockaddr *)sa, salen);
+ if (rc == 0 || errno != EADDRINUSE) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int bindresvport(int sockfd, struct sockaddr_in *sinp)
+{
+ return swrap_bindresvport_sa(sockfd, (struct sockaddr *)sinp);
+}
+#endif
+
+/****************************************************************************
+ * LISTEN
+ ***************************************************************************/
+
+static int swrap_listen(int s, int backlog)
+{
+ int ret;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return libc_listen(s, backlog);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(s, si, si->family);
+ if (ret == -1) {
+ errno = EADDRINUSE;
+ return ret;
+ }
+ }
+
+ ret = libc_listen(s, backlog);
+
+ return ret;
+}
+
+int listen(int s, int backlog)
+{
+ return swrap_listen(s, backlog);
+}
+
+/****************************************************************************
+ * FOPEN
+ ***************************************************************************/
+
+static FILE *swrap_fopen(const char *name, const char *mode)
+{
+ FILE *fp;
+
+ fp = libc_fopen(name, mode);
+ if (fp != NULL) {
+ int fd = fileno(fp);
+
+ swrap_remove_stale(fd);
+ }
+
+ return fp;
+}
+
+FILE *fopen(const char *name, const char *mode)
+{
+ return swrap_fopen(name, mode);
+}
+
+/****************************************************************************
+ * OPEN
+ ***************************************************************************/
+
+static int swrap_vopen(const char *pathname, int flags, va_list ap)
+{
+ int ret;
+
+ ret = libc_vopen(pathname, flags, ap);
+ if (ret != -1) {
+ /*
+ * There are methods for closing descriptors (libc-internal code
+ * paths, direct syscalls) which close descriptors in ways that
+ * we can't intercept, so try to recover when we notice that
+ * that's happened
+ */
+ swrap_remove_stale(ret);
+ }
+ return ret;
+}
+
+int open(const char *pathname, int flags, ...)
+{
+ va_list ap;
+ int fd;
+
+ va_start(ap, flags);
+ fd = swrap_vopen(pathname, flags, ap);
+ va_end(ap);
+
+ return fd;
+}
+
+/****************************************************************************
+ * GETPEERNAME
+ ***************************************************************************/
+
+static int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+ socklen_t len;
+
+ if (!si) {
+ return libc_getpeername(s, name, addrlen);
+ }
+
+ if (si->peername.sa_socklen == 0)
+ {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ len = MIN(*addrlen, si->peername.sa_socklen);
+ if (len == 0) {
+ return 0;
+ }
+
+ memcpy(name, &si->peername.sa.ss, len);
+ *addrlen = si->peername.sa_socklen;
+
+ return 0;
+}
+
+#ifdef HAVE_ACCEPT_PSOCKLEN_T
+int getpeername(int s, struct sockaddr *name, Psocklen_t addrlen)
+#else
+int getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
+#endif
+{
+ return swrap_getpeername(s, name, (socklen_t *)addrlen);
+}
+
+/****************************************************************************
+ * GETSOCKNAME
+ ***************************************************************************/
+
+static int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
+{
+ struct socket_info *si = find_socket_info(s);
+ socklen_t len;
+
+ if (!si) {
+ return libc_getsockname(s, name, addrlen);
+ }
+
+ len = MIN(*addrlen, si->myname.sa_socklen);
+ if (len == 0) {
+ return 0;
+ }
+
+ memcpy(name, &si->myname.sa.ss, len);
+ *addrlen = si->myname.sa_socklen;
+
+ return 0;
+}
+
+#ifdef HAVE_ACCEPT_PSOCKLEN_T
+int getsockname(int s, struct sockaddr *name, Psocklen_t addrlen)
+#else
+int getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
+#endif
+{
+ return swrap_getsockname(s, name, (socklen_t *)addrlen);
+}
+
+/****************************************************************************
+ * GETSOCKOPT
+ ***************************************************************************/
+
+#ifndef SO_PROTOCOL
+# ifdef SO_PROTOTYPE /* The Solaris name */
+# define SO_PROTOCOL SO_PROTOTYPE
+# endif /* SO_PROTOTYPE */
+#endif /* SO_PROTOCOL */
+
+static int swrap_getsockopt(int s, int level, int optname,
+ void *optval, socklen_t *optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return libc_getsockopt(s,
+ level,
+ optname,
+ optval,
+ optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ switch (optname) {
+#ifdef SO_DOMAIN
+ case SO_DOMAIN:
+ if (optval == NULL || optlen == NULL ||
+ *optlen < (socklen_t)sizeof(int)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *optlen = sizeof(int);
+ *(int *)optval = si->family;
+ return 0;
+#endif /* SO_DOMAIN */
+
+#ifdef SO_PROTOCOL
+ case SO_PROTOCOL:
+ if (optval == NULL || optlen == NULL ||
+ *optlen < (socklen_t)sizeof(int)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *optlen = sizeof(int);
+ *(int *)optval = si->protocol;
+ return 0;
+#endif /* SO_PROTOCOL */
+ case SO_TYPE:
+ if (optval == NULL || optlen == NULL ||
+ *optlen < (socklen_t)sizeof(int)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *optlen = sizeof(int);
+ *(int *)optval = si->type;
+ return 0;
+ default:
+ return libc_getsockopt(s,
+ level,
+ optname,
+ optval,
+ optlen);
+ }
+ } else if (level == IPPROTO_TCP) {
+ switch (optname) {
+#ifdef TCP_NODELAY
+ case TCP_NODELAY:
+ /*
+ * This enables sending packets directly out over TCP.
+ * As a unix socket is doing that any way, report it as
+ * enabled.
+ */
+ if (optval == NULL || optlen == NULL ||
+ *optlen < (socklen_t)sizeof(int)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *optlen = sizeof(int);
+ *(int *)optval = si->tcp_nodelay;
+
+ return 0;
+#endif /* TCP_NODELAY */
+ default:
+ break;
+ }
+ }
+
+ errno = ENOPROTOOPT;
+ return -1;
+}
+
+#ifdef HAVE_ACCEPT_PSOCKLEN_T
+int getsockopt(int s, int level, int optname, void *optval, Psocklen_t optlen)
+#else
+int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+#endif
+{
+ return swrap_getsockopt(s, level, optname, optval, (socklen_t *)optlen);
+}
+
+/****************************************************************************
+ * SETSOCKOPT
+ ***************************************************************************/
+
+static int swrap_setsockopt(int s, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return libc_setsockopt(s,
+ level,
+ optname,
+ optval,
+ optlen);
+ }
+
+ if (level == SOL_SOCKET) {
+ return libc_setsockopt(s,
+ level,
+ optname,
+ optval,
+ optlen);
+ } else if (level == IPPROTO_TCP) {
+ switch (optname) {
+#ifdef TCP_NODELAY
+ case TCP_NODELAY: {
+ int i;
+
+ /*
+ * This enables sending packets directly out over TCP.
+ * A unix socket is doing that any way.
+ */
+ if (optval == NULL || optlen == 0 ||
+ optlen < (socklen_t)sizeof(int)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ i = *discard_const_p(int, optval);
+ if (i != 0 && i != 1) {
+ errno = EINVAL;
+ return -1;
+ }
+ si->tcp_nodelay = i;
+
+ return 0;
+ }
+#endif /* TCP_NODELAY */
+ default:
+ break;
+ }
+ }
+
+ switch (si->family) {
+ case AF_INET:
+ if (level == IPPROTO_IP) {
+#ifdef IP_PKTINFO
+ if (optname == IP_PKTINFO) {
+ si->pktinfo = AF_INET;
+ }
+#endif /* IP_PKTINFO */
+ }
+ return 0;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ if (level == IPPROTO_IPV6) {
+#ifdef IPV6_RECVPKTINFO
+ if (optname == IPV6_RECVPKTINFO) {
+ si->pktinfo = AF_INET6;
+ }
+#endif /* IPV6_PKTINFO */
+ }
+ return 0;
+#endif
+ default:
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+}
+
+int setsockopt(int s, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ return swrap_setsockopt(s, level, optname, optval, optlen);
+}
+
+/****************************************************************************
+ * IOCTL
+ ***************************************************************************/
+
+static int swrap_vioctl(int s, unsigned long int r, va_list va)
+{
+ struct socket_info *si = find_socket_info(s);
+ va_list ap;
+ int value;
+ int rc;
+
+ if (!si) {
+ return libc_vioctl(s, r, va);
+ }
+
+ va_copy(ap, va);
+
+ rc = libc_vioctl(s, r, va);
+
+ switch (r) {
+ case FIONREAD:
+ value = *((int *)va_arg(ap, int *));
+
+ if (rc == -1 && errno != EAGAIN && errno != ENOBUFS) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ } else if (value == 0) { /* END OF FILE */
+ swrap_pcap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
+ }
+ break;
+ }
+
+ va_end(ap);
+
+ return rc;
+}
+
+#ifdef HAVE_IOCTL_INT
+int ioctl(int s, int r, ...)
+#else
+int ioctl(int s, unsigned long int r, ...)
+#endif
+{
+ va_list va;
+ int rc;
+
+ va_start(va, r);
+
+ rc = swrap_vioctl(s, (unsigned long int) r, va);
+
+ va_end(va);
+
+ return rc;
+}
+
+/*****************
+ * CMSG
+ *****************/
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+
+#ifndef CMSG_ALIGN
+# ifdef _ALIGN /* BSD */
+#define CMSG_ALIGN _ALIGN
+# else
+#define CMSG_ALIGN(len) (((len) + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1))
+# endif /* _ALIGN */
+#endif /* CMSG_ALIGN */
+
+/**
+ * @brief Add a cmsghdr to a msghdr.
+ *
+ * This is an function to add any type of cmsghdr. It will operate on the
+ * msg->msg_control and msg->msg_controllen you pass in by adapting them to
+ * the buffer position after the added cmsg element. Hence, this function is
+ * intended to be used with an intermediate msghdr and not on the original
+ * one handed in by the client.
+ *
+ * @param[in] msg The msghdr to which to add the cmsg.
+ *
+ * @param[in] level The cmsg level to set.
+ *
+ * @param[in] type The cmsg type to set.
+ *
+ * @param[in] data The cmsg data to set.
+ *
+ * @param[in] len the length of the data to set.
+ */
+static void swrap_msghdr_add_cmsghdr(struct msghdr *msg,
+ int level,
+ int type,
+ const void *data,
+ size_t len)
+{
+ size_t cmlen = CMSG_LEN(len);
+ size_t cmspace = CMSG_SPACE(len);
+ uint8_t cmbuf[cmspace];
+ void *cast_ptr = (void *)cmbuf;
+ struct cmsghdr *cm = (struct cmsghdr *)cast_ptr;
+ uint8_t *p;
+
+ memset(cmbuf, 0, cmspace);
+
+ if (msg->msg_controllen < cmlen) {
+ cmlen = msg->msg_controllen;
+ msg->msg_flags |= MSG_CTRUNC;
+ }
+
+ if (msg->msg_controllen < cmspace) {
+ cmspace = msg->msg_controllen;
+ }
+
+ /*
+ * We copy the full input data into an intermediate cmsghdr first
+ * in order to more easily cope with truncation.
+ */
+ cm->cmsg_len = cmlen;
+ cm->cmsg_level = level;
+ cm->cmsg_type = type;
+ memcpy(CMSG_DATA(cm), data, len);
+
+ /*
+ * We now copy the possibly truncated buffer.
+ * We copy cmlen bytes, but consume cmspace bytes,
+ * leaving the possible padding uninitialiazed.
+ */
+ p = (uint8_t *)msg->msg_control;
+ memcpy(p, cm, cmlen);
+ p += cmspace;
+ msg->msg_control = p;
+ msg->msg_controllen -= cmspace;
+
+ return;
+}
+
+static int swrap_msghdr_add_pktinfo(struct socket_info *si,
+ struct msghdr *msg)
+{
+ /* Add packet info */
+ switch (si->pktinfo) {
+#if defined(IP_PKTINFO) && (defined(HAVE_STRUCT_IN_PKTINFO) || defined(IP_RECVDSTADDR))
+ case AF_INET: {
+ struct sockaddr_in *sin;
+#if defined(HAVE_STRUCT_IN_PKTINFO)
+ struct in_pktinfo pkt;
+#elif defined(IP_RECVDSTADDR)
+ struct in_addr pkt;
+#endif
+
+ if (si->bindname.sa_socklen == sizeof(struct sockaddr_in)) {
+ sin = &si->bindname.sa.in;
+ } else {
+ if (si->myname.sa_socklen != sizeof(struct sockaddr_in)) {
+ return 0;
+ }
+ sin = &si->myname.sa.in;
+ }
+
+ ZERO_STRUCT(pkt);
+
+#if defined(HAVE_STRUCT_IN_PKTINFO)
+ pkt.ipi_ifindex = socket_wrapper_default_iface();
+ pkt.ipi_addr.s_addr = sin->sin_addr.s_addr;
+#elif defined(IP_RECVDSTADDR)
+ pkt = sin->sin_addr;
+#endif
+
+ swrap_msghdr_add_cmsghdr(msg, IPPROTO_IP, IP_PKTINFO,
+ &pkt, sizeof(pkt));
+
+ break;
+ }
+#endif /* IP_PKTINFO */
+#if defined(HAVE_IPV6)
+ case AF_INET6: {
+#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
+ struct sockaddr_in6 *sin6;
+ struct in6_pktinfo pkt6;
+
+ if (si->bindname.sa_socklen == sizeof(struct sockaddr_in6)) {
+ sin6 = &si->bindname.sa.in6;
+ } else {
+ if (si->myname.sa_socklen != sizeof(struct sockaddr_in6)) {
+ return 0;
+ }
+ sin6 = &si->myname.sa.in6;
+ }
+
+ ZERO_STRUCT(pkt6);
+
+ pkt6.ipi6_ifindex = socket_wrapper_default_iface();
+ pkt6.ipi6_addr = sin6->sin6_addr;
+
+ swrap_msghdr_add_cmsghdr(msg, IPPROTO_IPV6, IPV6_PKTINFO,
+ &pkt6, sizeof(pkt6));
+#endif /* HAVE_STRUCT_IN6_PKTINFO */
+
+ break;
+ }
+#endif /* IPV6_PKTINFO */
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int swrap_msghdr_add_socket_info(struct socket_info *si,
+ struct msghdr *omsg)
+{
+ int rc = 0;
+
+ if (si->pktinfo > 0) {
+ rc = swrap_msghdr_add_pktinfo(si, omsg);
+ }
+
+ return rc;
+}
+
+static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space);
+static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space);
+
+static int swrap_sendmsg_filter_cmsghdr(struct msghdr *msg,
+ uint8_t **cm_data,
+ size_t *cm_data_space) {
+ struct cmsghdr *cmsg;
+ int rc = -1;
+
+ /* Nothing to do */
+ if (msg->msg_controllen == 0 || msg->msg_control == NULL) {
+ return 0;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ switch (cmsg->cmsg_level) {
+ case IPPROTO_IP:
+ rc = swrap_sendmsg_filter_cmsg_socket(cmsg,
+ cm_data,
+ cm_data_space);
+ break;
+ default:
+ rc = swrap_sendmsg_copy_cmsg(cmsg,
+ cm_data,
+ cm_data_space);
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int swrap_sendmsg_copy_cmsg(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space)
+{
+ size_t cmspace;
+ uint8_t *p;
+
+ cmspace = *cm_data_space + CMSG_ALIGN(cmsg->cmsg_len);
+
+ p = realloc((*cm_data), cmspace);
+ if (p == NULL) {
+ return -1;
+ }
+ (*cm_data) = p;
+
+ p = (*cm_data) + (*cm_data_space);
+ *cm_data_space = cmspace;
+
+ memcpy(p, cmsg, cmsg->cmsg_len);
+
+ return 0;
+}
+
+static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space);
+
+
+static int swrap_sendmsg_filter_cmsg_socket(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space)
+{
+ int rc = -1;
+
+ switch(cmsg->cmsg_type) {
+#ifdef IP_PKTINFO
+ case IP_PKTINFO:
+ rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
+ cm_data,
+ cm_data_space);
+ break;
+#endif
+#ifdef IPV6_PKTINFO
+ case IPV6_PKTINFO:
+ rc = swrap_sendmsg_filter_cmsg_pktinfo(cmsg,
+ cm_data,
+ cm_data_space);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+static int swrap_sendmsg_filter_cmsg_pktinfo(struct cmsghdr *cmsg,
+ uint8_t **cm_data,
+ size_t *cm_data_space)
+{
+ (void)cmsg; /* unused */
+ (void)cm_data; /* unused */
+ (void)cm_data_space; /* unused */
+
+ /*
+ * Passing a IP pktinfo to a unix socket might be rejected by the
+ * Kernel, at least on FreeBSD. So skip this cmsg.
+ */
+ return 0;
+}
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
+static ssize_t swrap_sendmsg_before(int fd,
+ struct socket_info *si,
+ struct msghdr *msg,
+ struct iovec *tmp_iov,
+ struct sockaddr_un *tmp_un,
+ const struct sockaddr_un **to_un,
+ const struct sockaddr **to,
+ int *bcast)
+{
+ size_t i, len = 0;
+ ssize_t ret;
+
+ if (to_un) {
+ *to_un = NULL;
+ }
+ if (to) {
+ *to = NULL;
+ }
+ if (bcast) {
+ *bcast = 0;
+ }
+
+ switch (si->type) {
+ case SOCK_STREAM: {
+ unsigned long mtu;
+
+ if (!si->connected) {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ if (msg->msg_iovlen == 0) {
+ break;
+ }
+
+ mtu = socket_wrapper_mtu();
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ size_t nlen;
+ nlen = len + msg->msg_iov[i].iov_len;
+ if (nlen > mtu) {
+ break;
+ }
+ }
+ msg->msg_iovlen = i;
+ if (msg->msg_iovlen == 0) {
+ *tmp_iov = msg->msg_iov[0];
+ tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
+ (size_t)mtu);
+ msg->msg_iov = tmp_iov;
+ msg->msg_iovlen = 1;
+ }
+ break;
+ }
+ case SOCK_DGRAM:
+ if (si->connected) {
+ if (msg->msg_name != NULL) {
+ /*
+ * We are dealing with unix sockets and if we
+ * are connected, we should only talk to the
+ * connected unix path. Using the fd to send
+ * to another server would be hard to achieve.
+ */
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ }
+ } else {
+ const struct sockaddr *msg_name;
+ msg_name = (const struct sockaddr *)msg->msg_name;
+
+ if (msg_name == NULL) {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+
+ ret = sockaddr_convert_to_un(si, msg_name, msg->msg_namelen,
+ tmp_un, 0, bcast);
+ if (ret == -1) return -1;
+
+ if (to_un) {
+ *to_un = tmp_un;
+ }
+ if (to) {
+ *to = msg_name;
+ }
+ msg->msg_name = tmp_un;
+ msg->msg_namelen = sizeof(*tmp_un);
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(fd, si, si->family);
+ if (ret == -1) {
+ if (errno == ENOTSOCK) {
+ swrap_remove_stale(fd);
+ return -ENOTSOCK;
+ } else {
+ SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed");
+ return -1;
+ }
+ }
+ }
+
+ if (!si->defer_connect) {
+ break;
+ }
+
+ ret = sockaddr_convert_to_un(si,
+ &si->peername.sa.s,
+ si->peername.sa_socklen,
+ tmp_un,
+ 0,
+ NULL);
+ if (ret == -1) return -1;
+
+ ret = libc_connect(fd,
+ (struct sockaddr *)(void *)tmp_un,
+ sizeof(*tmp_un));
+
+ /* to give better errors */
+ if (ret == -1 && errno == ENOENT) {
+ errno = EHOSTUNREACH;
+ }
+
+ if (ret == -1) {
+ return ret;
+ }
+
+ si->defer_connect = 0;
+ break;
+ default:
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ if (msg->msg_controllen > 0 && msg->msg_control != NULL) {
+ uint8_t *cmbuf = NULL;
+ size_t cmlen = 0;
+
+ ret = swrap_sendmsg_filter_cmsghdr(msg, &cmbuf, &cmlen);
+ if (ret < 0) {
+ free(cmbuf);
+ return -1;
+ }
+
+ if (cmlen == 0) {
+ msg->msg_controllen = 0;
+ msg->msg_control = NULL;
+ } else if (cmlen < msg->msg_controllen && cmbuf != NULL) {
+ memcpy(msg->msg_control, cmbuf, cmlen);
+ msg->msg_controllen = cmlen;
+ }
+ free(cmbuf);
+ }
+#endif
+
+ return 0;
+}
+
+static void swrap_sendmsg_after(int fd,
+ struct socket_info *si,
+ struct msghdr *msg,
+ const struct sockaddr *to,
+ ssize_t ret)
+{
+ int saved_errno = errno;
+ size_t i, len = 0;
+ uint8_t *buf;
+ off_t ofs = 0;
+ size_t avail = 0;
+ size_t remain;
+
+ /* to give better errors */
+ if (ret == -1) {
+ if (saved_errno == ENOENT) {
+ saved_errno = EHOSTUNREACH;
+ } else if (saved_errno == ENOTSOCK) {
+ /* If the fd is not a socket, remove it */
+ swrap_remove_stale(fd);
+ }
+ }
+
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ avail += msg->msg_iov[i].iov_len;
+ }
+
+ if (ret == -1) {
+ remain = MIN(80, avail);
+ } else {
+ remain = ret;
+ }
+
+ /* we capture it as one single packet */
+ buf = (uint8_t *)malloc(remain);
+ if (!buf) {
+ /* we just not capture the packet */
+ errno = saved_errno;
+ return;
+ }
+
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
+ memcpy(buf + ofs,
+ msg->msg_iov[i].iov_base,
+ this_time);
+ ofs += this_time;
+ remain -= this_time;
+ }
+ len = ofs;
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ if (ret == -1) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+ swrap_pcap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
+ } else {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
+ }
+ break;
+
+ case SOCK_DGRAM:
+ if (si->connected) {
+ to = &si->peername.sa.s;
+ }
+ if (ret == -1) {
+ swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+ swrap_pcap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
+ } else {
+ swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+ }
+ break;
+ }
+
+ free(buf);
+ errno = saved_errno;
+}
+
+static int swrap_recvmsg_before(int fd,
+ struct socket_info *si,
+ struct msghdr *msg,
+ struct iovec *tmp_iov)
+{
+ size_t i, len = 0;
+ ssize_t ret;
+
+ (void)fd; /* unused */
+
+ switch (si->type) {
+ case SOCK_STREAM: {
+ unsigned int mtu;
+ if (!si->connected) {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ if (msg->msg_iovlen == 0) {
+ break;
+ }
+
+ mtu = socket_wrapper_mtu();
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ size_t nlen;
+ nlen = len + msg->msg_iov[i].iov_len;
+ if (nlen > mtu) {
+ break;
+ }
+ }
+ msg->msg_iovlen = i;
+ if (msg->msg_iovlen == 0) {
+ *tmp_iov = msg->msg_iov[0];
+ tmp_iov->iov_len = MIN((size_t)tmp_iov->iov_len,
+ (size_t)mtu);
+ msg->msg_iov = tmp_iov;
+ msg->msg_iovlen = 1;
+ }
+ break;
+ }
+ case SOCK_DGRAM:
+ if (msg->msg_name == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (msg->msg_iovlen == 0) {
+ break;
+ }
+
+ if (si->bound == 0) {
+ ret = swrap_auto_bind(fd, si, si->family);
+ if (ret == -1) {
+ /*
+ * When attempting to read or write to a
+ * descriptor, if an underlying autobind fails
+ * because it's not a socket, stop intercepting
+ * uses of that descriptor.
+ */
+ if (errno == ENOTSOCK) {
+ swrap_remove_stale(fd);
+ return -ENOTSOCK;
+ } else {
+ SWRAP_LOG(SWRAP_LOG_ERROR,
+ "swrap_recvmsg_before failed");
+ return -1;
+ }
+ }
+ }
+ break;
+ default:
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int swrap_recvmsg_after(int fd,
+ struct socket_info *si,
+ struct msghdr *msg,
+ const struct sockaddr_un *un_addr,
+ socklen_t un_addrlen,
+ ssize_t ret)
+{
+ int saved_errno = errno;
+ size_t i;
+ uint8_t *buf = NULL;
+ off_t ofs = 0;
+ size_t avail = 0;
+ size_t remain;
+ int rc;
+
+ /* to give better errors */
+ if (ret == -1) {
+ if (saved_errno == ENOENT) {
+ saved_errno = EHOSTUNREACH;
+ } else if (saved_errno == ENOTSOCK) {
+ /* If the fd is not a socket, remove it */
+ swrap_remove_stale(fd);
+ }
+ }
+
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ avail += msg->msg_iov[i].iov_len;
+ }
+
+ /* Convert the socket address before we leave */
+ if (si->type == SOCK_DGRAM && un_addr != NULL) {
+ rc = sockaddr_convert_from_un(si,
+ un_addr,
+ un_addrlen,
+ si->family,
+ msg->msg_name,
+ &msg->msg_namelen);
+ if (rc == -1) {
+ goto done;
+ }
+ }
+
+ if (avail == 0) {
+ rc = 0;
+ goto done;
+ }
+
+ if (ret == -1) {
+ remain = MIN(80, avail);
+ } else {
+ remain = ret;
+ }
+
+ /* we capture it as one single packet */
+ buf = (uint8_t *)malloc(remain);
+ if (buf == NULL) {
+ /* we just not capture the packet */
+ errno = saved_errno;
+ return -1;
+ }
+
+ for (i = 0; i < (size_t)msg->msg_iovlen; i++) {
+ size_t this_time = MIN(remain, (size_t)msg->msg_iov[i].iov_len);
+ memcpy(buf + ofs,
+ msg->msg_iov[i].iov_base,
+ this_time);
+ ofs += this_time;
+ remain -= this_time;
+ }
+
+ switch (si->type) {
+ case SOCK_STREAM:
+ if (ret == -1 && saved_errno != EAGAIN && saved_errno != ENOBUFS) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else if (ret == 0) { /* END OF FILE */
+ swrap_pcap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+ } else if (ret > 0) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+ }
+ break;
+
+ case SOCK_DGRAM:
+ if (ret == -1) {
+ break;
+ }
+
+ if (un_addr != NULL) {
+ swrap_pcap_dump_packet(si,
+ msg->msg_name,
+ SWRAP_RECVFROM,
+ buf,
+ ret);
+ } else {
+ swrap_pcap_dump_packet(si,
+ msg->msg_name,
+ SWRAP_RECV,
+ buf,
+ ret);
+ }
+
+ break;
+ }
+
+ rc = 0;
+done:
+ free(buf);
+ errno = saved_errno;
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ if (rc == 0 &&
+ msg->msg_controllen > 0 &&
+ msg->msg_control != NULL) {
+ rc = swrap_msghdr_add_socket_info(si, msg);
+ if (rc < 0) {
+ return -1;
+ }
+ }
+#endif
+
+ return rc;
+}
+
+/****************************************************************************
+ * RECVFROM
+ ***************************************************************************/
+
+static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen)
+{
+ struct swrap_address from_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ ssize_t ret;
+ struct socket_info *si = find_socket_info(s);
+ struct swrap_address saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr msg;
+ struct iovec tmp;
+ int tret;
+
+ if (!si) {
+ return libc_recvfrom(s,
+ buf,
+ len,
+ flags,
+ from,
+ fromlen);
+ }
+
+ tmp.iov_base = buf;
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ if (from != NULL && fromlen != NULL) {
+ msg.msg_name = from; /* optional address */
+ msg.msg_namelen = *fromlen; /* size of address */
+ } else {
+ msg.msg_name = &saddr.sa.s; /* optional address */
+ msg.msg_namelen = saddr.sa_socklen; /* size of address */
+ }
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+ if (tret < 0) {
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ ret = libc_recvfrom(s,
+ buf,
+ len,
+ flags,
+ &from_addr.sa.s,
+ &from_addr.sa_socklen);
+ if (ret == -1) {
+ return ret;
+ }
+
+ tret = swrap_recvmsg_after(s,
+ si,
+ &msg,
+ &from_addr.sa.un,
+ from_addr.sa_socklen,
+ ret);
+ if (tret != 0) {
+ return tret;
+ }
+
+ if (from != NULL && fromlen != NULL) {
+ *fromlen = msg.msg_namelen;
+ }
+
+ return ret;
+}
+
+#ifdef HAVE_ACCEPT_PSOCKLEN_T
+ssize_t recvfrom(int s, void *buf, size_t len, int flags,
+ struct sockaddr *from, Psocklen_t fromlen)
+#else
+ssize_t recvfrom(int s, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen)
+#endif
+{
+ return swrap_recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen);
+}
+
+/****************************************************************************
+ * SENDTO
+ ***************************************************************************/
+
+static ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ struct msghdr msg;
+ struct iovec tmp;
+ struct swrap_address un_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ const struct sockaddr_un *to_un = NULL;
+ ssize_t ret;
+ int rc;
+ struct socket_info *si = find_socket_info(s);
+ int bcast = 0;
+
+ if (!si) {
+ return libc_sendto(s, buf, len, flags, to, tolen);
+ }
+
+ tmp.iov_base = discard_const_p(char, buf);
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = discard_const_p(struct sockaddr, to); /* optional address */
+ msg.msg_namelen = tolen; /* size of address */
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#if HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ rc = swrap_sendmsg_before(s,
+ si,
+ &msg,
+ &tmp,
+ &un_addr.sa.un,
+ &to_un,
+ &to,
+ &bcast);
+ if (rc < 0) {
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ if (bcast) {
+/* struct stat st;
+ unsigned int iface; */
+ unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
+ unsigned int remote_prt;
+ unsigned int in4_addr;
+ char type;
+ DIR *d;
+ struct dirent *dir;
+
+/*
+ type = SOCKET_TYPE_CHAR_UDP;
+
+ for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
+ snprintf(un_addr.sa.un.sun_path,
+ sizeof(un_addr.sa.un.sun_path),
+ "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un_addr.sa.un.sun_path, &st) != 0) continue;
+
+ / * ignore the any errors in broadcast sends * /
+ libc_sendto(s,
+ buf,
+ len,
+ flags,
+ &un_addr.sa.s,
+ un_addr.sa_socklen);
+ }
+*/
+
+ d = opendir(socket_wrapper_dir());
+ if (d) {
+ while ((dir = readdir(d)) != NULL) {
+ if (dir->d_name[0] == SOCKET_TYPE_CHAR_UDP_LONG)
+ /* TODO - use S_ISSOCK ? */
+ if (sscanf(dir->d_name, SOCKET_FORMAT_LONG, &type, &in4_addr, &remote_prt) == 3)
+ if (prt == remote_prt) {
+ snprintf(un_addr.sa.un.sun_path,
+ sizeof(un_addr.sa.un.sun_path),
+ "%s/%s",
+ socket_wrapper_dir(),dir->d_name);
+ libc_sendto(s,
+ buf,
+ len,
+ flags,
+ &un_addr.sa.s,
+ un_addr.sa_socklen);
+ SWRAP_LOG(SWRAP_LOG_DEBUG,"send bcast packet to %s", dir->d_name);
+ }
+ }
+ closedir(d);
+ }
+
+ swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+
+ return len;
+ }
+
+ /*
+ * If it is a dgram socket and we are connected, don't include the
+ * 'to' address.
+ */
+ if (si->type == SOCK_DGRAM && si->connected) {
+ ret = libc_sendto(s,
+ buf,
+ len,
+ flags,
+ NULL,
+ 0);
+ } else {
+ ret = libc_sendto(s,
+ buf,
+ len,
+ flags,
+ (struct sockaddr *)msg.msg_name,
+ msg.msg_namelen);
+ }
+
+ swrap_sendmsg_after(s, si, &msg, to, ret);
+
+ return ret;
+}
+
+ssize_t sendto(int s, const void *buf, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ return swrap_sendto(s, buf, len, flags, to, tolen);
+}
+
+/****************************************************************************
+ * READV
+ ***************************************************************************/
+
+static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
+{
+ struct socket_info *si;
+ struct msghdr msg;
+ struct swrap_address saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct iovec tmp;
+ ssize_t ret;
+ int tret;
+
+ si = find_socket_info(s);
+ if (si == NULL) {
+ return libc_recv(s, buf, len, flags);
+ }
+
+ tmp.iov_base = buf;
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = &saddr.sa.s; /* optional address */
+ msg.msg_namelen = saddr.sa_socklen; /* size of address */
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+ if (tret < 0) {
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ ret = libc_recv(s, buf, len, flags);
+
+ tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
+ if (tret != 0) {
+ return tret;
+ }
+
+ return ret;
+}
+
+ssize_t recv(int s, void *buf, size_t len, int flags)
+{
+ return swrap_recv(s, buf, len, flags);
+}
+
+/****************************************************************************
+ * READ
+ ***************************************************************************/
+
+static ssize_t swrap_read(int s, void *buf, size_t len)
+{
+ struct socket_info *si;
+ struct msghdr msg;
+ struct iovec tmp;
+ struct swrap_address saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ ssize_t ret;
+ int tret;
+
+ si = find_socket_info(s);
+ if (si == NULL) {
+ return libc_read(s, buf, len);
+ }
+
+ tmp.iov_base = buf;
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = &saddr.sa.ss; /* optional address */
+ msg.msg_namelen = saddr.sa_socklen; /* size of address */
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+ if (tret < 0) {
+ if (tret == -ENOTSOCK) {
+ return libc_read(s, buf, len);
+ }
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ ret = libc_read(s, buf, len);
+
+ tret = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
+ if (tret != 0) {
+ return tret;
+ }
+
+ return ret;
+}
+
+ssize_t read(int s, void *buf, size_t len)
+{
+ return swrap_read(s, buf, len);
+}
+
+/****************************************************************************
+ * WRITE
+ ***************************************************************************/
+
+static ssize_t swrap_write(int s, const void *buf, size_t len)
+{
+ struct msghdr msg;
+ struct iovec tmp;
+ struct sockaddr_un un_addr;
+ ssize_t ret;
+ int rc;
+ struct socket_info *si;
+
+ si = find_socket_info(s);
+ if (si == NULL) {
+ return libc_write(s, buf, len);
+ }
+
+ tmp.iov_base = discard_const_p(char, buf);
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = NULL; /* optional address */
+ msg.msg_namelen = 0; /* size of address */
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#if HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
+ if (rc < 0) {
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ ret = libc_write(s, buf, len);
+
+ swrap_sendmsg_after(s, si, &msg, NULL, ret);
+
+ return ret;
+}
+
+ssize_t write(int s, const void *buf, size_t len)
+{
+ return swrap_write(s, buf, len);
+}
+
+/****************************************************************************
+ * SEND
+ ***************************************************************************/
+
+static ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
+{
+ struct msghdr msg;
+ struct iovec tmp;
+ struct sockaddr_un un_addr;
+ ssize_t ret;
+ int rc;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return libc_send(s, buf, len, flags);
+ }
+
+ tmp.iov_base = discard_const_p(char, buf);
+ tmp.iov_len = len;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = NULL; /* optional address */
+ msg.msg_namelen = 0; /* size of address */
+ msg.msg_iov = &tmp; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+#if HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
+ if (rc < 0) {
+ return -1;
+ }
+
+ buf = msg.msg_iov[0].iov_base;
+ len = msg.msg_iov[0].iov_len;
+
+ ret = libc_send(s, buf, len, flags);
+
+ swrap_sendmsg_after(s, si, &msg, NULL, ret);
+
+ return ret;
+}
+
+ssize_t send(int s, const void *buf, size_t len, int flags)
+{
+ return swrap_send(s, buf, len, flags);
+}
+
+/****************************************************************************
+ * RECVMSG
+ ***************************************************************************/
+
+static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
+{
+ struct swrap_address from_addr = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ struct swrap_address convert_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct socket_info *si;
+ struct msghdr msg;
+ struct iovec tmp;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ size_t msg_ctrllen_filled;
+ size_t msg_ctrllen_left;
+#endif
+
+ ssize_t ret;
+ int rc;
+
+ si = find_socket_info(s);
+ if (si == NULL) {
+ return libc_recvmsg(s, omsg, flags);
+ }
+
+ tmp.iov_base = NULL;
+ tmp.iov_len = 0;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = &from_addr.sa; /* optional address */
+ msg.msg_namelen = from_addr.sa_socklen; /* size of address */
+ msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
+ msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg_ctrllen_filled = 0;
+ msg_ctrllen_left = omsg->msg_controllen;
+
+ msg.msg_control = omsg->msg_control; /* ancillary data, see below */
+ msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
+ msg.msg_flags = omsg->msg_flags; /* flags on received message */
+#endif
+
+ rc = swrap_recvmsg_before(s, si, &msg, &tmp);
+ if (rc < 0) {
+ return -1;
+ }
+
+ ret = libc_recvmsg(s, &msg, flags);
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg_ctrllen_filled += msg.msg_controllen;
+ msg_ctrllen_left -= msg.msg_controllen;
+
+ if (omsg->msg_control != NULL) {
+ uint8_t *p;
+
+ p = omsg->msg_control;
+ p += msg_ctrllen_filled;
+
+ msg.msg_control = p;
+ msg.msg_controllen = msg_ctrllen_left;
+ } else {
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ }
+#endif
+
+ /*
+ * We convert the unix address to a IP address so we need a buffer
+ * which can store the address in case of SOCK_DGRAM, see below.
+ */
+ msg.msg_name = &convert_addr.sa;
+ msg.msg_namelen = convert_addr.sa_socklen;
+
+ rc = swrap_recvmsg_after(s,
+ si,
+ &msg,
+ &from_addr.sa.un,
+ from_addr.sa_socklen,
+ ret);
+ if (rc != 0) {
+ return rc;
+ }
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ if (omsg->msg_control != NULL) {
+ /* msg.msg_controllen = space left */
+ msg_ctrllen_left = msg.msg_controllen;
+ msg_ctrllen_filled = omsg->msg_controllen - msg_ctrllen_left;
+ }
+
+ /* Update the original message length */
+ omsg->msg_controllen = msg_ctrllen_filled;
+ omsg->msg_flags = msg.msg_flags;
+#endif
+ omsg->msg_iovlen = msg.msg_iovlen;
+
+ /*
+ * From the manpage:
+ *
+ * The msg_name field points to a caller-allocated buffer that is
+ * used to return the source address if the socket is unconnected. The
+ * caller should set msg_namelen to the size of this buffer before this
+ * call; upon return from a successful call, msg_name will contain the
+ * length of the returned address. If the application does not need
+ * to know the source address, msg_name can be specified as NULL.
+ */
+ if (si->type == SOCK_STREAM) {
+ omsg->msg_namelen = 0;
+ } else if (omsg->msg_name != NULL &&
+ omsg->msg_namelen != 0 &&
+ omsg->msg_namelen >= msg.msg_namelen) {
+ memcpy(omsg->msg_name, msg.msg_name, msg.msg_namelen);
+ omsg->msg_namelen = msg.msg_namelen;
+ }
+
+ return ret;
+}
+
+ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+ return swrap_recvmsg(sockfd, msg, flags);
+}
+
+/****************************************************************************
+ * SENDMSG
+ ***************************************************************************/
+
+static ssize_t swrap_sendmsg(int s, const struct msghdr *omsg, int flags)
+{
+ struct msghdr msg;
+ struct iovec tmp;
+ struct sockaddr_un un_addr;
+ const struct sockaddr_un *to_un = NULL;
+ const struct sockaddr *to = NULL;
+ ssize_t ret;
+ int rc;
+ struct socket_info *si = find_socket_info(s);
+ int bcast = 0;
+
+ if (!si) {
+ return libc_sendmsg(s, omsg, flags);
+ }
+
+ ZERO_STRUCT(un_addr);
+
+ tmp.iov_base = NULL;
+ tmp.iov_len = 0;
+
+ ZERO_STRUCT(msg);
+
+ if (si->connected == 0) {
+ msg.msg_name = omsg->msg_name; /* optional address */
+ msg.msg_namelen = omsg->msg_namelen; /* size of address */
+ }
+ msg.msg_iov = omsg->msg_iov; /* scatter/gather array */
+ msg.msg_iovlen = omsg->msg_iovlen; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ if (msg.msg_controllen > 0 && msg.msg_control != NULL) {
+ /* omsg is a const so use a local buffer for modifications */
+ uint8_t cmbuf[omsg->msg_controllen];
+
+ memcpy(cmbuf, omsg->msg_control, omsg->msg_controllen);
+
+ msg.msg_control = cmbuf; /* ancillary data, see below */
+ msg.msg_controllen = omsg->msg_controllen; /* ancillary data buffer len */
+ }
+ msg.msg_flags = omsg->msg_flags; /* flags on received message */
+#endif
+
+ rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, &to_un, &to, &bcast);
+ if (rc < 0) {
+ return -1;
+ }
+
+ if (bcast) {
+// struct stat st;
+// unsigned int iface;
+ unsigned int prt = ntohs(((const struct sockaddr_in *)(const void *)to)->sin_port);
+ char type;
+ size_t i, len = 0;
+ uint8_t *buf;
+ off_t ofs = 0;
+ size_t avail = 0;
+ size_t remain;
+
+ unsigned int remote_prt;
+ unsigned int in4_addr;
+ DIR *d;
+ struct dirent *dir;
+
+
+ for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
+ avail += msg.msg_iov[i].iov_len;
+ }
+
+ len = avail;
+ remain = avail;
+
+ /* we capture it as one single packet */
+ buf = (uint8_t *)malloc(remain);
+ if (!buf) {
+ return -1;
+ }
+
+ for (i = 0; i < (size_t)msg.msg_iovlen; i++) {
+ size_t this_time = MIN(remain, (size_t)msg.msg_iov[i].iov_len);
+ memcpy(buf + ofs,
+ msg.msg_iov[i].iov_base,
+ this_time);
+ ofs += this_time;
+ remain -= this_time;
+ }
+
+ /*
+ type = SOCKET_TYPE_CHAR_UDP;
+
+ for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
+ snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
+ socket_wrapper_dir(), type, iface, prt);
+ if (stat(un_addr.sun_path, &st) != 0) continue;
+
+ msg.msg_name = &un_addr; / * optional address * /
+ msg.msg_namelen = sizeof(un_addr); / * size of address * /
+
+ / * ignore the any errors in broadcast sends * /
+ libc_sendmsg(s, &msg, flags);
+ }
+ */
+
+
+ d = opendir(socket_wrapper_dir());
+ if (d) {
+ while ((dir = readdir(d)) != NULL) {
+ if (dir->d_name[0] == SOCKET_TYPE_CHAR_UDP_LONG)
+ /* TODO - use S_ISSOCK ? */
+ if (sscanf(dir->d_name, SOCKET_FORMAT_LONG, &type, &in4_addr, &remote_prt) == 3)
+ if (prt == remote_prt) {
+ snprintf(un_addr.sun_path,
+ sizeof(un_addr.sun_path),
+ "%s/%s",
+ socket_wrapper_dir(),dir->d_name);
+ libc_sendmsg(s, &msg, flags);
+ SWRAP_LOG(SWRAP_LOG_DEBUG,"send bcast packet to %s", dir->d_name);
+ }
+ }
+ closedir(d);
+ }
+
+ swrap_pcap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
+ free(buf);
+
+ return len;
+ }
+
+ ret = libc_sendmsg(s, &msg, flags);
+
+ swrap_sendmsg_after(s, si, &msg, to, ret);
+
+ return ret;
+}
+
+ssize_t sendmsg(int s, const struct msghdr *omsg, int flags)
+{
+ return swrap_sendmsg(s, omsg, flags);
+}
+
+/****************************************************************************
+ * READV
+ ***************************************************************************/
+
+static ssize_t swrap_readv(int s, const struct iovec *vector, int count)
+{
+ struct socket_info *si;
+ struct msghdr msg;
+ struct iovec tmp;
+ struct swrap_address saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage)
+ };
+ ssize_t ret;
+ int rc;
+
+ si = find_socket_info(s);
+ if (si == NULL) {
+ return libc_readv(s, vector, count);
+ }
+
+ tmp.iov_base = NULL;
+ tmp.iov_len = 0;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = &saddr.sa.s; /* optional address */
+ msg.msg_namelen = saddr.sa_socklen; /* size of address */
+ msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
+ msg.msg_iovlen = count; /* # elements in msg_iov */
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ rc = swrap_recvmsg_before(s, si, &msg, &tmp);
+ if (rc < 0) {
+ if (rc == -ENOTSOCK) {
+ return libc_readv(s, vector, count);
+ }
+ return -1;
+ }
+
+ ret = libc_readv(s, msg.msg_iov, msg.msg_iovlen);
+
+ rc = swrap_recvmsg_after(s, si, &msg, NULL, 0, ret);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return ret;
+}
+
+ssize_t readv(int s, const struct iovec *vector, int count)
+{
+ return swrap_readv(s, vector, count);
+}
+
+/****************************************************************************
+ * WRITEV
+ ***************************************************************************/
+
+static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
+{
+ struct msghdr msg;
+ struct iovec tmp;
+ struct sockaddr_un un_addr;
+ ssize_t ret;
+ int rc;
+ struct socket_info *si = find_socket_info(s);
+
+ if (!si) {
+ return libc_writev(s, vector, count);
+ }
+
+ tmp.iov_base = NULL;
+ tmp.iov_len = 0;
+
+ ZERO_STRUCT(msg);
+ msg.msg_name = NULL; /* optional address */
+ msg.msg_namelen = 0; /* size of address */
+ msg.msg_iov = discard_const_p(struct iovec, vector); /* scatter/gather array */
+ msg.msg_iovlen = count; /* # elements in msg_iov */
+#if HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ msg.msg_control = NULL; /* ancillary data, see below */
+ msg.msg_controllen = 0; /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+#endif
+
+ rc = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
+ if (rc < 0) {
+ if (rc == -ENOTSOCK) {
+ return libc_readv(s, vector, count);
+ }
+ return -1;
+ }
+
+ ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
+
+ swrap_sendmsg_after(s, si, &msg, NULL, ret);
+
+ return ret;
+}
+
+ssize_t writev(int s, const struct iovec *vector, int count)
+{
+ return swrap_writev(s, vector, count);
+}
+
+/****************************
+ * CLOSE
+ ***************************/
+
+static int swrap_close(int fd)
+{
+ struct socket_info *si = find_socket_info(fd);
+ struct socket_info_fd *fi;
+ int ret;
+
+ if (!si) {
+ return libc_close(fd);
+ }
+
+ for (fi = si->fds; fi; fi = fi->next) {
+ if (fi->fd == fd) {
+ SWRAP_DLIST_REMOVE(si->fds, fi);
+ free(fi);
+ break;
+ }
+ }
+
+ if (si->fds) {
+ /* there are still references left */
+ return libc_close(fd);
+ }
+
+ SWRAP_DLIST_REMOVE(sockets, si);
+
+ if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
+ }
+
+ ret = libc_close(fd);
+
+ if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
+ swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
+ swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
+ }
+
+ if (si->un_addr.sun_path[0] != '\0') {
+ unlink(si->un_addr.sun_path);
+ }
+ free(si);
+
+ return ret;
+}
+
+int close(int fd)
+{
+ return swrap_close(fd);
+}
+
+/****************************
+ * DUP
+ ***************************/
+
+static int swrap_dup(int fd)
+{
+ struct socket_info *si;
+ struct socket_info_fd *fi;
+
+ si = find_socket_info(fd);
+
+ if (!si) {
+ return libc_dup(fd);
+ }
+
+ fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
+ if (fi == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ fi->fd = libc_dup(fd);
+ if (fi->fd == -1) {
+ int saved_errno = errno;
+ free(fi);
+ errno = saved_errno;
+ return -1;
+ }
+
+ /* Make sure we don't have an entry for the fd */
+ swrap_remove_stale(fi->fd);
+
+ SWRAP_DLIST_ADD(si->fds, fi);
+ return fi->fd;
+}
+
+int dup(int fd)
+{
+ return swrap_dup(fd);
+}
+
+/****************************
+ * DUP2
+ ***************************/
+
+static int swrap_dup2(int fd, int newfd)
+{
+ struct socket_info *si;
+ struct socket_info_fd *fi;
+
+ si = find_socket_info(fd);
+
+ if (!si) {
+ return libc_dup2(fd, newfd);
+ }
+
+ if (find_socket_info(newfd)) {
+ /* dup2() does an implicit close of newfd, which we
+ * need to emulate */
+ swrap_close(newfd);
+ }
+
+ fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
+ if (fi == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ fi->fd = libc_dup2(fd, newfd);
+ if (fi->fd == -1) {
+ int saved_errno = errno;
+ free(fi);
+ errno = saved_errno;
+ return -1;
+ }
+
+ /* Make sure we don't have an entry for the fd */
+ swrap_remove_stale(fi->fd);
+
+ SWRAP_DLIST_ADD(si->fds, fi);
+ return fi->fd;
+}
+
+int dup2(int fd, int newfd)
+{
+ return swrap_dup2(fd, newfd);
+}
+
+/****************************
+ * FCNTL
+ ***************************/
+
+static int swrap_vfcntl(int fd, int cmd, va_list va)
+{
+ struct socket_info_fd *fi;
+ struct socket_info *si;
+ int rc;
+
+ si = find_socket_info(fd);
+ if (si == NULL) {
+ rc = libc_vfcntl(fd, cmd, va);
+
+ return rc;
+ }
+
+ switch (cmd) {
+ case F_DUPFD:
+ fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
+ if (fi == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ fi->fd = libc_vfcntl(fd, cmd, va);
+ if (fi->fd == -1) {
+ int saved_errno = errno;
+ free(fi);
+ errno = saved_errno;
+ return -1;
+ }
+
+ /* Make sure we don't have an entry for the fd */
+ swrap_remove_stale(fi->fd);
+
+ SWRAP_DLIST_ADD(si->fds, fi);
+
+ rc = fi->fd;
+ break;
+ default:
+ rc = libc_vfcntl(fd, cmd, va);
+ break;
+ }
+
+ return rc;
+}
+
+int fcntl(int fd, int cmd, ...)
+{
+ va_list va;
+ int rc;
+
+ va_start(va, cmd);
+
+ rc = swrap_vfcntl(fd, cmd, va);
+
+ va_end(va);
+
+ return rc;
+}
+
+/****************************
+ * EVENTFD
+ ***************************/
+
+#ifdef HAVE_EVENTFD
+static int swrap_eventfd(int count, int flags)
+{
+ int fd;
+
+ fd = libc_eventfd(count, flags);
+ if (fd != -1) {
+ swrap_remove_stale(fd);
+ }
+
+ return fd;
+}
+
+#ifdef HAVE_EVENTFD_UNSIGNED_INT
+int eventfd(unsigned int count, int flags)
+#else
+int eventfd(int count, int flags)
+#endif
+{
+ return swrap_eventfd(count, flags);
+}
+#endif
+
+#ifdef HAVE_PLEDGE
+int pledge(const char *promises, const char *paths[])
+{
+ (void)promises; /* unused */
+ (void)paths; /* unused */
+
+ return 0;
+}
+#endif /* HAVE_PLEDGE */
+
+/****************************
+ * DESTRUCTOR
+ ***************************/
+
+/*
+ * This function is called when the library is unloaded and makes sure that
+ * sockets get closed and the unix file for the socket are unlinked.
+ */
+void swrap_destructor(void)
+{
+ struct socket_info *s = sockets;
+
+ while (s != NULL) {
+ struct socket_info_fd *f = s->fds;
+ if (f != NULL) {
+ swrap_close(f->fd);
+ }
+ s = sockets;
+ }
+
+ if (swrap.libc_handle != NULL) {
+ dlclose(swrap.libc_handle);
+ }
+ if (swrap.libsocket_handle) {
+ dlclose(swrap.libsocket_handle);
+ }
+}
diff --git a/tests/deckard/contrib/libswrap/tests/CMakeLists.txt b/tests/deckard/contrib/libswrap/tests/CMakeLists.txt
new file mode 100644
index 0000000..aecf6b8
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/CMakeLists.txt
@@ -0,0 +1,57 @@
+project(tests C)
+
+include_directories(
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMOCKA_INCLUDE_DIR}
+)
+
+set(TORTURE_LIBRARY torture)
+
+# RFC862 echo server
+add_executable(echo_srv echo_srv.c)
+target_link_libraries(echo_srv ${SWRAP_REQUIRED_LIBRARIES})
+
+add_library(${TORTURE_LIBRARY} STATIC torture.c)
+target_link_libraries(${TORTURE_LIBRARY}
+ ${CMOCKA_LIBRARY}
+ ${SWRAP_REQUIRED_LIBRARIES})
+
+set(SWRAP_TESTS
+ test_ioctl
+ test_tcp_listen
+ test_echo_tcp_socket
+ test_echo_tcp_connect
+ test_echo_tcp_bind
+ test_echo_tcp_socket_options
+ test_echo_tcp_sendmsg_recvmsg
+ test_echo_tcp_write_read
+ test_echo_tcp_writev_readv
+ test_echo_tcp_get_peer_sock_name
+ test_echo_udp_sendto_recvfrom
+ test_echo_udp_send_recv
+ test_echo_udp_sendmsg_recvmsg
+ test_swrap_unit)
+
+if (HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ set(SWRAP_TESTS ${SWRAP_TESTS} test_sendmsg_recvmsg_fd)
+endif (HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+
+foreach(_SWRAP_TEST ${SWRAP_TESTS})
+ add_cmocka_test(${_SWRAP_TEST} ${_SWRAP_TEST}.c ${TORTURE_LIBRARY})
+
+ if (OSX)
+ set_property(
+ TEST
+ ${_SWRAP_TEST}
+ PROPERTY
+ ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${SOCKET_WRAPPER_LOCATION})
+ else ()
+ set_property(
+ TEST
+ ${_SWRAP_TEST}
+ PROPERTY
+ ENVIRONMENT LD_PRELOAD=${SOCKET_WRAPPER_LOCATION})
+ endif()
+endforeach()
diff --git a/tests/deckard/contrib/libswrap/tests/README b/tests/deckard/contrib/libswrap/tests/README
new file mode 100644
index 0000000..26bf1fb
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/README
@@ -0,0 +1,9 @@
+In this directory you can find all socket_wrapper tests. All tests can also be
+executed outside of the 'make test' environment and without socket_wrapper.
+
+This can be done with:
+
+TORTURE_SERVER_ADDRESS_IPV4="127.0.0.1" \
+TORTURE_SERVER_ADDRESS_IPV6="::1" \
+TORTURE_SERVER_PORT=7777 \
+./tests/test_echo_tcp_write_read
diff --git a/tests/deckard/contrib/libswrap/tests/echo_srv.c b/tests/deckard/contrib/libswrap/tests/echo_srv.c
new file mode 100644
index 0000000..5b784de
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/echo_srv.c
@@ -0,0 +1,925 @@
+#include "config.h"
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <resolv.h>
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#ifndef PIDFILE
+#define PIDFILE "echo_srv.pid"
+#endif /* PIDFILE */
+
+#define ECHO_SRV_IPV4 "127.0.0.10"
+/* socket wrapper IPv6 prefix fd00::5357:5fxx */
+#define ECHO_SRV_IPV6 "fd00::5357:5f0a"
+
+#define DFL_PORT 7
+#define BACKLOG 5
+
+#ifndef BUFSIZE
+#define BUFSIZE 0x400000
+#endif /* BUFSIZE */
+
+#ifndef discard_const
+#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
+#endif
+
+#ifndef discard_const_p
+#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
+#endif
+
+#ifndef ZERO_STRUCT
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
+
+struct torture_address {
+ socklen_t sa_socklen;
+ union {
+ struct sockaddr s;
+ struct sockaddr_in in;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr_storage ss;
+ } sa;
+};
+
+struct echo_srv_opts {
+ int port;
+ int socktype;
+ bool daemon;
+ char *bind;
+ const char *pidfile;
+};
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+
+#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO)
+union pktinfo {
+#ifdef HAVE_STRUCT_IN6_PKTINFO
+ struct in6_pktinfo pkt6;
+#endif
+#ifdef HAVE_STRUCT_IN_PKTINFO
+ struct in_pktinfo pkt4;
+#elif defined(IP_RECVDSTADDR)
+ struct in_addr pkt4;
+#endif
+ char c;
+};
+
+#define HAVE_UNION_PKTINFO 1
+#endif /* IP_PKTINFO || IP_RECVDSTADDR || IPV6_PKTINFO */
+
+static const char *echo_server_address(int family)
+{
+ switch (family) {
+ case AF_INET: {
+ const char *ip4 = getenv("TORTURE_SERVER_ADDRESS_IPV4");
+
+ if (ip4 != NULL && ip4[0] != '\0') {
+ return ip4;
+ }
+
+ return ECHO_SRV_IPV4;
+ }
+ case AF_INET6: {
+ const char *ip6 = getenv("TORTURE_SERVER_ADDRESS_IPV6");
+
+ if (ip6 != NULL && ip6[0] != '\0') {
+ return ip6;
+ }
+
+ return ECHO_SRV_IPV6;
+ }
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
+static void _assert_return_code(int rc,
+ int err,
+ const char * const file,
+ const int line)
+{
+ if (rc < 0) {
+ fprintf(stderr, "Fatal error: %s\n", strerror(err));
+ fprintf(stderr, "%s:%d", file, line);
+
+ abort();
+ }
+}
+#define assert_return_code(rc, err) \
+ _assert_return_code(rc, err, __FILE__, __LINE__)
+
+
+static int pidfile(const char *path)
+{
+ int err;
+ int fd;
+ char pid_str[32] = { 0 };
+ ssize_t nwritten;
+ size_t len;
+
+ fd = open(path, O_RDONLY, 0644);
+ err = errno;
+ if (fd != -1) {
+ close(fd);
+ return EEXIST;
+ } else if (err != ENOENT) {
+ return err;
+ }
+
+ fd = open(path, O_CREAT | O_WRONLY | O_EXCL, 0644);
+ err = errno;
+ if (fd == -1) {
+ return err;
+ }
+
+ snprintf(pid_str, sizeof(pid_str) -1, "%u\n", (unsigned int) getpid());
+ len = strlen(pid_str);
+
+ nwritten = write(fd, pid_str, len);
+ close(fd);
+ if (nwritten != (ssize_t)len) {
+ return EIO;
+ }
+
+ return 0;
+}
+
+static int become_daemon(void)
+{
+ int ret;
+ pid_t child_pid;
+ int fd;
+ int i;
+
+ if (getppid() == 1) {
+ return 0;
+ }
+
+ child_pid = fork();
+ if (child_pid == -1) {
+ ret = errno;
+ perror("fork");
+ return ret;
+ } else if (child_pid > 0) {
+ exit(0);
+ }
+
+ /* If a working directory was defined, go there */
+#ifdef WORKING_DIR
+ chdir(WORKING_DIR);
+#endif
+
+ ret = setsid();
+ if (ret == -1) {
+ ret = errno;
+ perror("setsid");
+ return ret;
+ }
+
+ for (fd = getdtablesize(); fd >= 0; --fd) {
+ close(fd);
+ }
+
+ for (i = 0; i < 3; i++) {
+ fd = open("/dev/null", O_RDWR, 0);
+ if (fd < 0) {
+ fd = open("/dev/null", O_WRONLY, 0);
+ }
+ if (fd < 0) {
+ ret = errno;
+ perror("Can't open /dev/null");
+ return ret;
+ }
+ if (fd != i) {
+ perror("Didn't get correct fd");
+ close(fd);
+ return EINVAL;
+ }
+ }
+
+ umask(0177);
+ return 0;
+}
+
+static void set_sock_pktinfo(int sock, int family)
+{
+ int sockopt = 1;
+ int option = 0;
+ int proto = 0;
+ int rc;
+
+ switch(family) {
+ case AF_INET:
+ proto = IPPROTO_IP;
+#ifdef IP_PKTINFO
+ option = IP_PKTINFO;
+#elif IP_RECVDSTADDR
+ option = IP_RECVDSTADDR;
+#else
+ return;
+#endif /* IP_PKTINFO */
+ break;
+#ifdef HAVE_IPV6
+#ifdef IPV6_RECVPKTINFO
+ case AF_INET6:
+ proto = IPPROTO_IPV6;
+ option = IPV6_RECVPKTINFO;
+ break;
+#endif /* IPV6_RECVPKTINFO */
+#endif /* HAVE_IPV6 */
+ default:
+ return;
+ }
+
+ rc = setsockopt(sock, proto, option, &sockopt, sizeof(sockopt));
+ assert_return_code(rc, errno);
+}
+
+/* Returns 0 on success, errno on failure. If successful,
+ * sock is a ready to use socket */
+static int setup_srv(struct echo_srv_opts *opts, int *_sock)
+{
+ struct addrinfo hints;
+ struct addrinfo *res, *ri;
+ char svc[6];
+ int ret;
+ int sock;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = opts->socktype;
+ hints.ai_flags = AI_PASSIVE;
+
+ snprintf(svc, sizeof(svc), "%d", opts->port);
+
+ ret = getaddrinfo(opts->bind, svc, &hints, &res);
+ if (ret != 0) {
+ return errno;
+ }
+
+ for (ri = res; ri != NULL; ri = ri->ai_next) {
+ sock = socket(ri->ai_family, ri->ai_socktype,
+ ri->ai_protocol);
+ if (sock == -1) {
+ ret = errno;
+ freeaddrinfo(res);
+ perror("socket");
+ return ret;
+ }
+
+ if (ri->ai_socktype == SOCK_DGRAM) {
+ set_sock_pktinfo(sock, ri->ai_family);
+ }
+
+ ret = bind(sock, ri->ai_addr, ri->ai_addrlen);
+ if (ret == 0) {
+ break;
+ }
+
+ close(sock);
+ }
+ freeaddrinfo(res);
+
+ if (ri == NULL) {
+ fprintf(stderr, "Could not bind\n");
+ return EFAULT;
+ }
+
+ if (opts->socktype == SOCK_STREAM) {
+ ret = listen(sock, BACKLOG);
+ if (ret == -1) {
+ ret = errno;
+ close(sock);
+ perror("listen");
+ return ret;
+ }
+ }
+
+ *_sock = sock;
+ return 0;
+}
+
+static int socket_dup(int s)
+{
+ struct torture_address cli_addr1 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr1 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ struct torture_address cli_addr2 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr2 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ struct torture_address cli_addr3 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr3 = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ int s2;
+ int rc;
+
+ rc = getsockname(s, &srv_addr1.sa.s, &srv_addr1.sa_socklen);
+ if (rc == -1) {
+ perror("getsockname");
+ return -1;
+ }
+
+ rc = getpeername(s, &cli_addr1.sa.s, &cli_addr1.sa_socklen);
+ if (rc == -1) {
+ perror("getpeername");
+ return -1;
+ }
+
+ if (cli_addr1.sa.ss.ss_family != srv_addr1.sa.ss.ss_family) {
+ perror("client/server family mismatch");
+ return -1;
+ }
+
+ /* Test dup */
+ s2 = dup(s);
+ if (s2 == -1) {
+ perror("dup");
+ return -1;
+ }
+ close(s);
+
+ rc = getsockname(s2, &srv_addr2.sa.s, &srv_addr2.sa_socklen);
+ if (rc == -1) {
+ perror("getsockname");
+ close(s2);
+ return -1;
+ }
+
+ rc = getpeername(s2, &cli_addr2.sa.s, &cli_addr2.sa_socklen);
+ if (rc == -1) {
+ perror("getpeername");
+ close(s2);
+ return -1;
+ }
+
+ if (cli_addr1.sa_socklen != cli_addr2.sa_socklen ||
+ srv_addr1.sa_socklen != srv_addr2.sa_socklen) {
+ perror("length mismatch");
+ close(s2);
+ return -1;
+ }
+
+ switch(cli_addr1.sa.ss.ss_family) {
+ case AF_INET: {
+ rc = memcmp(&cli_addr1.sa.in, &cli_addr2.sa.in, sizeof(struct sockaddr_in));
+ if (rc != 0) {
+ perror("client mismatch");
+ }
+
+ rc = memcmp(&srv_addr1.sa.in, &srv_addr2.sa.in, sizeof(struct sockaddr_in));
+ if (rc != 0) {
+ perror("server mismatch");
+ }
+ break;
+ }
+ case AF_INET6: {
+ rc = memcmp(&cli_addr1.sa.in6, &cli_addr2.sa.in6, sizeof(struct sockaddr_in6));
+ if (rc != 0) {
+ perror("client mismatch");
+ }
+
+ rc = memcmp(&srv_addr1.sa.in6, &srv_addr2.sa.in6, sizeof(struct sockaddr_in6));
+ if (rc != 0) {
+ perror("server mismatch");
+ }
+ break;
+ }
+ default:
+ perror("family mismatch");
+ close(s2);
+ return -1;
+ }
+
+ /* Test dup2 */
+ s = dup2(s2, s);
+ close(s2);
+ if (s == -1) {
+ perror("dup");
+ return -1;
+ }
+
+ rc = getsockname(s, &srv_addr3.sa.s, &srv_addr3.sa_socklen);
+ if (rc == -1) {
+ perror("getsockname");
+ close(s);
+ return -1;
+ }
+
+ rc = getpeername(s, &cli_addr3.sa.s, &cli_addr3.sa_socklen);
+ if (rc == -1) {
+ perror("getpeername");
+ close(s);
+ return -1;
+ }
+
+ if (cli_addr2.sa_socklen != cli_addr3.sa_socklen ||
+ srv_addr2.sa_socklen != srv_addr3.sa_socklen) {
+ perror("length mismatch");
+ close(s);
+ return -1;
+ }
+
+ switch(cli_addr2.sa.ss.ss_family) {
+ case AF_INET: {
+ rc = memcmp(&cli_addr1.sa.in, &cli_addr2.sa.in, sizeof(struct sockaddr_in));
+ if (rc != 0) {
+ perror("client mismatch");
+ }
+
+ rc = memcmp(&srv_addr1.sa.in, &srv_addr2.sa.in, sizeof(struct sockaddr_in));
+ if (rc != 0) {
+ perror("server mismatch");
+ }
+ break;
+ }
+ case AF_INET6: {
+ rc = memcmp(&cli_addr1.sa.in6, &cli_addr2.sa.in6, sizeof(struct sockaddr_in6));
+ if (rc != 0) {
+ perror("client mismatch");
+ }
+
+ rc = memcmp(&srv_addr1.sa.in6, &srv_addr2.sa.in6, sizeof(struct sockaddr_in6));
+ if (rc != 0) {
+ perror("server mismatch");
+ }
+ break;
+ }
+ default:
+ perror("family mismatch");
+ close(s);
+ return -1;
+ }
+
+ return s;
+}
+
+static void echo_tcp(int sock)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ char buf[BUFSIZE];
+ ssize_t bret;
+
+ int client_sock = -1;
+ int s;
+
+ s = accept(sock, &addr.sa.s, &addr.sa_socklen);
+ if (s == -1) {
+ perror("accept");
+ goto done;
+ }
+
+ client_sock = socket_dup(s);
+ if (client_sock == -1) {
+ perror("socket_dup");
+ goto done;
+ }
+
+ /* Start ping pong */
+ while (1) {
+ bret = recv(client_sock, buf, BUFSIZE, 0);
+ if (bret == -1) {
+ perror("recv");
+ goto done;
+ } else if (bret == 0) {
+ break;
+ }
+
+ bret = send(client_sock, buf, bret, 0);
+ if (bret == -1) {
+ perror("send");
+ goto done;
+ }
+ }
+
+done:
+ if (client_sock != -1) {
+ close(client_sock);
+ }
+}
+
+static ssize_t echo_udp_recv_from_to(int sock,
+ void *buf, size_t buflen, int flags,
+ struct sockaddr *from, socklen_t *fromlen,
+ struct sockaddr *to, socklen_t *tolen)
+{
+ struct msghdr rmsg;
+ struct iovec riov;
+ ssize_t ret;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO)
+ size_t cmlen = CMSG_LEN(sizeof(union pktinfo));
+ char cmsg[cmlen];
+#else
+ (void)to; /* unused */
+ (void)tolen; /* unused */
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
+ riov.iov_base = buf;
+ riov.iov_len = buflen;
+
+ ZERO_STRUCT(rmsg);
+
+ rmsg.msg_name = from;
+ rmsg.msg_namelen = *fromlen;
+
+ rmsg.msg_iov = &riov;
+ rmsg.msg_iovlen = 1;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO)
+ memset(cmsg, 0, cmlen);
+
+ rmsg.msg_control = cmsg;
+ rmsg.msg_controllen = cmlen;
+#endif
+
+ ret = recvmsg(sock, &rmsg, flags);
+ if (ret < 0) {
+ return ret;
+ }
+ *fromlen = rmsg.msg_namelen;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO)
+ if (rmsg.msg_controllen > 0) {
+ struct cmsghdr *cmsgptr;
+
+ cmsgptr = CMSG_FIRSTHDR(&rmsg);
+ while (cmsgptr != NULL) {
+ const char *p;
+
+#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO)
+ if (cmsgptr->cmsg_level == IPPROTO_IP &&
+ cmsgptr->cmsg_type == IP_PKTINFO) {
+ char ip[INET_ADDRSTRLEN] = { 0 };
+ struct sockaddr_in *sinp = (struct sockaddr_in *)to;
+ struct in_pktinfo *pkt;
+ void *cmsg_cast_ptr = CMSG_DATA(cmsgptr);
+
+ pkt = (struct in_pktinfo *)cmsg_cast_ptr;
+
+ sinp->sin_family = AF_INET;
+ sinp->sin_addr = pkt->ipi_addr;
+ *tolen = sizeof(struct sockaddr_in);
+
+ p = inet_ntop(AF_INET, &sinp->sin_addr, ip, sizeof(ip));
+ if (p == 0) {
+ fprintf(stderr, "Failed to convert IP address");
+ abort();
+ }
+
+ if (strcmp(ip, echo_server_address(AF_INET)) != 0) {
+ fprintf(stderr, "Wrong IP received");
+ abort();
+ }
+ }
+#endif /* IP_PKTINFO */
+#ifdef IP_RECVDSTADDR
+ if (cmsgptr->cmsg_level == IPPROTO_IP &&
+ cmsgptr->cmsg_type == IP_RECVDSTADDR) {
+ char ip[INET_ADDRSTRLEN] = { 0 };
+ struct sockaddr_in *sinp =
+ (struct sockaddr_in *)(void *)to;
+ struct in_addr *addr;
+ void *cmsg_cast_ptr = CMSG_DATA(cmsgptr);
+
+ addr = (struct in_addr *)cmsg_cast_ptr;
+
+ sinp->sin_family = AF_INET;
+ sinp->sin_addr = *addr;
+ *tolen = sizeof(struct sockaddr_in);
+
+ p = inet_ntop(AF_INET, &sinp->sin_addr, ip, sizeof(ip));
+ if (p == 0) {
+ fprintf(stderr, "Failed to convert IP address");
+ abort();
+ }
+
+ if (strcmp(ip, echo_server_address(AF_INET)) != 0) {
+ fprintf(stderr, "Wrong IP received");
+ abort();
+ }
+ }
+#endif /* IP_RECVDSTADDR */
+#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO)
+ if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
+ cmsgptr->cmsg_type == IPV6_PKTINFO) {
+ char ip[INET6_ADDRSTRLEN] = { 0 };
+ struct in6_pktinfo *pkt6;
+ struct sockaddr_in6 *sin6p =
+ (struct sockaddr_in6 *)(void *)to;
+ void *cmsg_cast_ptr = CMSG_DATA(cmsgptr);
+
+ pkt6 = (struct in6_pktinfo *)cmsg_cast_ptr;
+
+ sin6p->sin6_family = AF_INET6;
+ sin6p->sin6_addr = pkt6->ipi6_addr;
+
+ p = inet_ntop(AF_INET6, &sin6p->sin6_addr, ip, sizeof(ip));
+ if (p == 0) {
+ fprintf(stderr, "Failed to convert IP address");
+ abort();
+ }
+
+ if (strcmp(ip, echo_server_address(AF_INET6)) != 0) {
+ fprintf(stderr, "Wrong IP received");
+ abort();
+ }
+ }
+#endif /* IPV6_PKTINFO */
+ cmsgptr = CMSG_NXTHDR(&rmsg, cmsgptr);
+ }
+ } else {
+ fprintf(stderr, "Failed to receive pktinfo");
+ abort();
+ }
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL && HAVE_UNION_PKTINFO */
+
+ return ret;
+}
+
+static ssize_t echo_udp_send_to_from(int sock,
+ void *buf, size_t buflen, int flags,
+ struct sockaddr *to, socklen_t tolen,
+ struct sockaddr *from, socklen_t fromlen)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ ssize_t ret;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO)
+ size_t clen = CMSG_SPACE(sizeof(union pktinfo));
+ char cbuf[clen];
+ struct cmsghdr *cmsgptr;
+#else
+ (void)from; /* unused */
+ (void)fromlen; /* unused */
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL && HAVE_UNION_PKTINFO */
+
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ ZERO_STRUCT(msg);
+
+ msg.msg_name = to;
+ msg.msg_namelen = tolen;
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && defined(HAVE_UNION_PKTINFO)
+ memset(cbuf, 0, clen);
+
+ msg.msg_control = cbuf;
+ msg.msg_controllen = clen;
+
+ cmsgptr = CMSG_FIRSTHDR(&msg);
+ msg.msg_controllen = 0;
+
+ switch (from->sa_family) {
+#if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
+ case AF_INET: {
+ void *cmsg_cast_ptr = CMSG_DATA(cmsgptr);
+#ifdef IP_PKTINFO
+ struct in_pktinfo *p = (struct in_pktinfo *)cmsg_cast_ptr;
+#elif defined(IP_SENDSRCADDR)
+ struct in_addr *p = (struct in_addr *)cmsg_cast_ptr;
+#endif
+ const struct sockaddr_in *from4 =
+ (const struct sockaddr_in *)(const void *)from;
+
+ if (fromlen != sizeof(struct sockaddr_in)) {
+ break;
+ }
+
+ cmsgptr->cmsg_level = IPPROTO_IP;
+#ifdef IP_PKTINFO
+ cmsgptr->cmsg_type = IP_PKTINFO;
+ p->ipi_spec_dst = from4->sin_addr;
+#elif defined(IP_SENDSRCADDR)
+ cmsgptr->cmsg_type = IP_SENDSRCADDR;
+ *p = from4->sin_addr;
+#endif
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(*p));
+
+ msg.msg_controllen = CMSG_SPACE(sizeof(*p));
+
+ break;
+ }
+#endif /* IP_PKTINFO || IP_SENDSRCADDR */
+#ifdef IPV6_PKTINFO
+ case AF_INET6: {
+ void *cast_ptr = CMSG_DATA(cmsgptr);
+ struct in6_pktinfo *p = (struct in6_pktinfo *)cast_ptr;
+ const struct sockaddr_in6 *from6 =
+ (const struct sockaddr_in6 *)(const void *)from;
+
+ if (fromlen != sizeof(struct sockaddr_in6)) {
+ break;
+ }
+
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_PKTINFO;
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+
+ p->ipi6_addr = from6->sin6_addr;
+
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+
+ break;
+ }
+#endif /* IPV6_PKTINFO */
+ default:
+ break;
+ }
+#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL && HAVE_UNION_PKTINFO */
+
+ ret = sendmsg(sock, &msg, flags);
+
+ return ret;
+}
+
+static void echo_udp(int sock)
+{
+ struct torture_address saddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address daddr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ ssize_t bret;
+ char buf[BUFSIZE];
+
+ while (1) {
+ bret = echo_udp_recv_from_to(sock,
+ buf,
+ BUFSIZE,
+ 0,
+ &saddr.sa.s,
+ &saddr.sa_socklen,
+ &daddr.sa.s,
+ &daddr.sa_socklen);
+ if (bret == -1) {
+ perror("recvfrom");
+ continue;
+ }
+
+ bret = echo_udp_send_to_from(sock,
+ buf,
+ bret,
+ 0,
+ &saddr.sa.s,
+ saddr.sa_socklen,
+ &daddr.sa.s,
+ daddr.sa_socklen);
+ if (bret == -1) {
+ perror("sendto");
+ continue;
+ }
+ }
+}
+
+static void echo(int sock, struct echo_srv_opts *opts)
+{
+ switch (opts->socktype) {
+ case SOCK_STREAM:
+ echo_tcp(sock);
+ return;
+ case SOCK_DGRAM:
+ echo_udp(sock);
+ return;
+ default:
+ fprintf(stderr, "Unsupported protocol\n");
+ return;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ int sock = -1;
+ struct echo_srv_opts opts;
+ int opt;
+ int optindex;
+ static struct option long_options[] = {
+ { discard_const_p(char, "tcp"), no_argument, 0, 't' },
+ { discard_const_p(char, "udp"), no_argument, 0, 'u' },
+ { discard_const_p(char, "bind-addr"), required_argument, 0, 'b' },
+ { discard_const_p(char, "port"), required_argument, 0, 'p' },
+ { discard_const_p(char, "daemon"), no_argument, 0, 'D' },
+ { discard_const_p(char, "pid"), required_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+
+ opts.port = DFL_PORT;
+ opts.socktype = SOCK_STREAM;
+ opts.bind = NULL;
+ opts.pidfile = PIDFILE;
+ opts.daemon = false;
+
+ while ((opt = getopt_long(argc, argv, "Dutp:b:",
+ long_options, &optindex)) != -1) {
+ switch (opt) {
+ case 0:
+ if (optindex == 5) {
+ opts.pidfile = optarg;
+ }
+ break;
+ case 'p':
+ opts.port = atoi(optarg);
+ break;
+ case 'b':
+ opts.bind = optarg;
+ break;
+ case 'u':
+ opts.socktype = SOCK_DGRAM;
+ break;
+ case 't':
+ opts.socktype = SOCK_STREAM;
+ break;
+ case 'D':
+ opts.daemon = true;
+ break;
+ default: /* '?' */
+ fprintf(stderr, "Usage: %s [-p port] [-u] [-t] [-b bind_addr] " \
+ "[-D] [--pid pidfile]\n"
+ "-t makes the server listen on TCP\n"
+ "-u makes the server listen on UDP\n"
+ "-D tells the server to become a deamon and " \
+ "write a PIDfile\n"
+ "The default port is 7, the default PIDfile is " \
+ "echo_srv.pid in the current directory\n",
+ argv[0]);
+ ret = 1;
+ goto done;
+ }
+ }
+
+ if (opts.daemon) {
+ ret = become_daemon();
+ if (ret != 0) {
+ fprintf(stderr, "Cannot become daemon: %s\n", strerror(ret));
+ goto done;
+ }
+ }
+
+ ret = setup_srv(&opts, &sock);
+ if (ret != 0) {
+ fprintf(stderr, "Cannot setup server: %s\n", strerror(ret));
+ goto done;
+ }
+
+ if (opts.daemon && opts.pidfile != NULL) {
+ ret = pidfile(opts.pidfile);
+ if (ret != 0) {
+ fprintf(stderr, "Cannot create pidfile %s: %s\n",
+ opts.pidfile, strerror(ret));
+ goto done;
+ }
+ }
+
+ echo(sock, &opts);
+ close(sock);
+
+ if (opts.daemon) {
+ unlink(opts.pidfile);
+ }
+
+ ret = 0;
+done:
+ return ret;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_bind.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_bind.c
new file mode 100644
index 0000000..cde7e3f
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_bind.c
@@ -0,0 +1,536 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+static int setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv6(state);
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_bind_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address addr_in = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address addr_un = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /*
+ * Test various cases with family AF_UNSPEC
+ */
+
+ /* UNSPEC, len == 1: EINVAL */
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_UNSPEC,
+ };
+ rc = bind(s, &addr.sa.s, 1);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EINVAL);
+
+ /* UNSPEC: EAFNOSUPPORT */
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_UNSPEC,
+ };
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr_in.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ /* FreeBSD uses EADDRNOTAVAIL here ... */
+ assert_true(errno == EAFNOSUPPORT || errno == EADDRNOTAVAIL);
+
+ /* special case: AF_UNSPEC with INADDR_ANY: success mapped to AF_INET */
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_UNSPEC,
+ };
+ assert_int_equal(addr_in.sa.in.sin_addr.s_addr, htonl(INADDR_ANY));
+
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s);
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /*
+ * Test various cases with family AF_UNIX
+ * all fail with EAFNOSUPPORT
+ */
+
+ addr.sa.ss = (struct sockaddr_storage) {
+ .ss_family = AF_UNIX,
+ };
+ rc = bind(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_UNIX,
+ };
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+
+ addr_un.sa.un = (struct sockaddr_un) {
+ .sun_family = AF_UNIX,
+ };
+ rc = bind(s, &addr_un.sa.s, addr_un.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+
+#ifdef HAVE_IPV6
+ /*
+ * Test with family AF_INET6 - fail
+ */
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET6,
+ };
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+#endif
+
+ /*
+ * Finally, success binding a new IPv4 address.
+ */
+ addr_in = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ },
+ };
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr_in.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_return_code(rc, errno);
+
+ addr_in = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(torture_server_port()),
+ },
+ };
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr_in.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s);
+}
+
+#if 0 /* TODO */
+static void test_bind_ipv4_addr_in_use(void **state)
+{
+ struct sockaddr_in sin, sin2;
+ socklen_t slen = sizeof(struct sockaddr_in);
+ int rc;
+ int s, s2;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /*
+ * Try to bind to the same address as already bound by a
+ * different process.
+ */
+
+ /* Without specifying the port - success */
+
+ ZERO_STRUCT(sin);
+ sin.sin_family = AF_INET;
+ rc = inet_pton(AF_INET, torture_server_address(AF_INET), &sin.sin_addr);
+ assert_int_equal(rc, 1);
+ rc = bind(s, (struct sockaddr *)&sin, slen);
+ assert_return_code(rc, errno);
+
+ close(s);
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+#if 0
+ /* specify the same port - fail with EADDRINUSE. */
+
+ /* Not supported by socket_wrapper yet. ==> TODO! */
+
+ ZERO_STRUCT(sin);
+ sin.sin_family = AF_INET,
+ sin.sin_port = htons(torture_server_port());
+ rc = inet_pton(AF_INET, torture_server_address(AF_INET), &sin.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, (struct sockaddr *)&sin, slen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EADDRINUSE);
+#endif
+
+ /*
+ * Try double binding when the firs bind is with port == 0
+ */
+
+ ZERO_STRUCT(sin);
+ sin.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, (struct sockaddr *)&sin, slen);
+ assert_return_code(rc, errno);
+
+ /*
+ * Open a second socket locally and try to bind to the same address.
+ */
+
+ /* Succeeds with port == 0 */
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin2);
+ sin2.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s2, (struct sockaddr *)&sin2, slen);
+ assert_return_code(rc, errno);
+
+ close(s2);
+
+ /* second bind with port != 0 - succeeds */
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin2);
+ sin2.sin_family = AF_INET;
+ sin2.sin_port = htons(12345);
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s2, (struct sockaddr *)&sin2, slen);
+ assert_return_code(rc, errno);
+
+ close(s2);
+ close(s);
+
+ /*
+ * Try double binding when the first bind is with port != 0
+ */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(12345);
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, (struct sockaddr *)&sin, slen);
+ assert_return_code(rc, errno);
+
+ /*
+ * Open a second socket locally and try to bind to the same address.
+ */
+
+ /* Succeeds with port == 0 */
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin2);
+ sin2.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s2, (struct sockaddr *)&sin2, slen);
+ assert_return_code(rc, errno);
+
+ close(s2);
+
+ /* with same port as above - fail with EADDRINUSE */
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin2);
+ sin2.sin_family = AF_INET;
+ sin2.sin_port = htons(12345);
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin2.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s2, (struct sockaddr *)&sin2, slen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EADDRINUSE);
+
+ close(s);
+}
+#endif
+
+#ifdef HAVE_BINDRESVPORT
+static void test_bindresvport_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ addr.sa.in.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bindresvport(s, &addr.sa.in);
+ assert_return_code(rc, errno);
+
+ addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(torture_server_port()),
+ },
+ };
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s);
+}
+
+static void test_bindresvport_ipv4_null(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ rc = bindresvport(s, NULL);
+ assert_return_code(rc, errno);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+ rc = inet_pton(AF_INET, torture_server_address(AF_INET), &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s);
+}
+#endif /* HAVE_BINDRESVPORT */
+
+#ifdef HAVE_IPV6
+static void test_bind_on_ipv6_sock(void **state)
+{
+ struct torture_address addr_in = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address addr_un = {
+ .sa_socklen = sizeof(struct sockaddr_un),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ addr_un.sa.un.sun_family = AF_UNIX;
+ rc = bind(s, &addr_un.sa.s, addr_un.sa_socklen);
+ assert_int_equal(rc, -1);
+ /* FreeBSD uses EINVAL here... */
+ assert_true(errno == EAFNOSUPPORT || errno == EINVAL);
+
+ addr_in.sa.in.sin_family = AF_INET;
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EINVAL);
+
+ addr_in.sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ };
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr_in.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EINVAL);
+
+ addr_in = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ },
+ };
+
+ rc = bind(s, &addr_in.sa.s, addr_in.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+
+ close(s);
+}
+
+#ifdef HAVE_BINDRESVPORT
+static void test_bindresvport_on_ipv6_sock(void **state)
+{
+ struct sockaddr_in sin;
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ ZERO_STRUCT(sin);
+ sin.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &sin.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bindresvport(s, &sin);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EINVAL);
+
+ close(s);
+}
+
+static void test_bindresvport_on_ipv6_sock_null(void **state)
+{
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ rc = bindresvport(s, NULL);
+ assert_return_code(rc, errno);
+
+ close(s);
+}
+#endif /* HAVE_BINDRESVPORT */
+#endif /* HAVE_IPV6 */
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tcp_bind_tests[] = {
+ cmocka_unit_test_setup_teardown(test_bind_ipv4,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#if 0 /* TODO */
+ cmocka_unit_test_setup_teardown(test_bind_ipv4_addr_in_use,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#endif
+#ifdef HAVE_BINDRESVPORT
+ cmocka_unit_test_setup_teardown(test_bindresvport_ipv4,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_bindresvport_ipv4_null,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#endif /* HAVE_BINDRESVPORT */
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_bind_on_ipv6_sock,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+#ifdef HAVE_BINDRESVPORT
+ cmocka_unit_test_setup_teardown(test_bindresvport_on_ipv6_sock,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_bindresvport_on_ipv6_sock_null,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+#endif /* HAVE_BINDRESVPORT */
+#endif /* HAVE_IPV6 */
+ };
+
+ rc = cmocka_run_group_tests(tcp_bind_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_connect.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_connect.c
new file mode 100644
index 0000000..d2020c8
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_connect.c
@@ -0,0 +1,101 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_connect_broadcast_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+ addr.sa.in.sin_addr.s_addr = INADDR_BROADCAST;
+
+ /* We don't allow connect to broadcast addresses */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, -1);
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_connect_downgrade_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect should downgrade to IPv4 and allow the connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ close(s);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tcp_connect_tests[] = {
+ cmocka_unit_test(test_connect_broadcast_ipv4),
+#ifdef HAVE_IPV6
+ cmocka_unit_test(test_connect_downgrade_ipv6),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(tcp_connect_tests,
+ setup_echo_srv_tcp_ipv4,
+ teardown);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_get_peer_sock_name.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_get_peer_sock_name.c
new file mode 100644
index 0000000..ac369dd
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_get_peer_sock_name.c
@@ -0,0 +1,476 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "20", 1);
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void _assert_sockaddr_equal(struct torture_address *addr, const char *a,
+ const char * const file, const int line)
+{
+ char ip[INET6_ADDRSTRLEN] = { 0 };
+ const char *p;
+
+ p = inet_ntop(addr->sa.ss.ss_family,
+ addr->sa.ss.ss_family == AF_INET6 ?
+ (void *)&addr->sa.in6.sin6_addr :
+ (void *)&addr->sa.in.sin_addr,
+ ip,
+ sizeof(ip));
+ _assert_true(cast_ptr_to_largest_integral_type(p),
+ "inet_ntop: Failed to convert IP address", file, line);
+
+ _assert_string_equal(ip, a, file, line);
+}
+
+#define assert_sockaddr_equal(ss, a) \
+ _assert_sockaddr_equal(ss, a, __FILE__, __LINE__)
+
+static void _assert_sockaddr_port_equal(struct torture_address *addr,
+ const char *a,
+ uint16_t port,
+ const char * const file, const int line)
+{
+ uint16_t n_port;
+
+ _assert_sockaddr_equal(addr, a, file, line);
+
+ switch(addr->sa.ss.ss_family) {
+ case AF_INET:
+ n_port = addr->sa.in.sin_port;
+ break;
+ case AF_INET6:
+ n_port = addr->sa.in6.sin6_port;
+ break;
+ default:
+ return;
+ }
+
+ _assert_int_equal(ntohs(n_port), port, file, line);
+}
+
+#define assert_sockaddr_port_equal(ss, a, prt) \
+ _assert_sockaddr_port_equal(ss, a, prt, __FILE__, __LINE__)
+
+static void _assert_sockaddr_port_range_equal(struct torture_address *addr,
+ const char *a,
+ uint16_t min_port, uint16_t max_port,
+ const char * const file, const int line)
+{
+ uint16_t n_port;
+
+ _assert_sockaddr_equal(addr, a, file, line);
+
+ switch(addr->sa.ss.ss_family) {
+ case AF_INET:
+ n_port = addr->sa.in.sin_port;
+ break;
+ case AF_INET6:
+ n_port = addr->sa.in6.sin6_port;
+ break;
+ default:
+ return;
+ }
+
+ _assert_in_range(ntohs(n_port),
+ min_port,
+ max_port,
+ file,
+ line);
+}
+
+#define assert_sockaddr_port_range_equal(ss, a, min_prt, max_prt) \
+ _assert_sockaddr_port_range_equal(ss, a, min_prt, max_prt, __FILE__, __LINE__)
+
+static void test_connect_getsockname_getpeername(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address cli_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /* Bind client address to wildcard address */
+ addr.sa.in.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = bind(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
+
+ rc = getpeername(s, &addr.sa.s, &addr.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, ENOTCONN);
+
+ /* connect */
+ addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(torture_server_port()),
+ },
+ };
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ cli_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
+
+ srv_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
+
+ close(s);
+}
+
+static void test_connect_getsockname_getpeername_port(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address cli_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /* Bind client address to wildcard address */
+ addr.sa.in.sin_family = AF_INET;
+
+ rc = inet_pton(AF_INET, "127.0.0.20", &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+ addr.sa.in.sin_port = htons(12345);
+
+ rc = bind(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, ENOTCONN);
+
+ /* connect */
+ addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ .sa.in = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(torture_server_port()),
+ },
+ };
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ cli_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
+
+ srv_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
+
+ close(s);
+}
+
+static void test_connect_getsockname_getpeername_any(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address cli_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /* Bind client address to wildcard address */
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ rc = bind(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_range_equal(&cli_addr, "0.0.0.0", 1024, 65535);
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, ENOTCONN);
+
+ /* connect */
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ cli_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
+
+ srv_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
+
+ close(s);
+}
+
+static void test_connect_getsockname_getpeername_any_port(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address cli_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /* Bind client address to wildcard address */
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sa.in.sin_port = htons(12345);
+
+ rc = bind(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&cli_addr, "0.0.0.0", 12345);
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, ENOTCONN);
+
+ /* connect */
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ cli_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
+
+ srv_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
+
+ close(s);
+}
+
+static void test_connect_getsockname_getpeername_len(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct torture_address cli_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address srv_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ socklen_t tmp_len;
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s, errno);
+
+ /* connect */
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ /* Connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ /* Check with len=0 */
+ cli_addr.sa_socklen = 0;
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ srv_addr.sa_socklen = 0;
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ /* Check with len=too small */
+ cli_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_in) - 2,
+ };
+
+ tmp_len = cli_addr.sa_socklen;
+ rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(tmp_len + 2, cli_addr.sa_socklen);
+
+ srv_addr = (struct torture_address) {
+ .sa_socklen = sizeof(struct sockaddr_in) - 2,
+ };
+
+ tmp_len = srv_addr.sa_socklen;
+ rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(tmp_len + 2, srv_addr.sa_socklen);
+
+ close(s);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest sock_name_tests[] = {
+ cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_port,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_any,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_any_port,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_len,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ };
+
+ rc = cmocka_run_group_tests(sock_name_tests,
+ NULL,
+ NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_sendmsg_recvmsg.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_sendmsg_recvmsg.c
new file mode 100644
index 0000000..4f7629e
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_sendmsg_recvmsg.c
@@ -0,0 +1,273 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_sendmsg_recvmsg_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+
+ for (i = 0; i < 10; i++) {
+ struct torture_address reply_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = 0,
+ };
+ struct iovec s_iov;
+ struct iovec r_iov;
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ /* This should be ignored */
+ rc = inet_pton(AF_INET,
+ "127.0.0.1",
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ s_msg.msg_name = &addr.sa.s;
+ s_msg.msg_namelen = addr.sa_socklen;
+
+ s_iov.iov_base = send_buf;
+ s_iov.iov_len = sizeof(send_buf);
+
+ s_msg.msg_iov = &s_iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ r_msg.msg_name = &reply_addr.sa.s;
+ r_msg.msg_namelen = reply_addr.sa_socklen;
+
+ r_iov.iov_base = recv_buf;
+ r_iov.iov_len = sizeof(recv_buf);
+
+ r_msg.msg_iov = &r_iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, 0);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_sendmsg_recvmsg_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET6;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+
+ for (i = 0; i < 10; i++) {
+ struct torture_address reply_addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = 0,
+ };
+ struct iovec s_iov;
+ struct iovec r_iov;
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ s_iov.iov_base = send_buf;
+ s_iov.iov_len = sizeof(send_buf);
+
+ s_msg.msg_iov = &s_iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ r_msg.msg_name = &reply_addr.sa.s;
+ r_msg.msg_namelen = reply_addr.sa_socklen;
+
+ r_iov.iov_base = recv_buf;
+ r_iov.iov_len = sizeof(recv_buf);
+
+ r_msg.msg_iov = &r_iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, 0);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+#endif
+
+static void test_sendmsg_recvmsg_ipv4_null(void **state)
+{
+ struct torture_address send_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = 0,
+ };
+ struct iovec iov;
+ char payload[] = "PACKET";
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void)state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ send_addr.sa.in.sin_family = AF_INET;
+ send_addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &send_addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
+
+ /* msg_name = NULL */
+
+ iov.iov_base = (void *)payload;
+ iov.iov_len = sizeof(payload);
+
+ s_msg.msg_iov = &iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ /* msg_name = NULL */
+
+ memset(payload, 0, sizeof(payload));
+
+ r_msg.msg_iov = &iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, 0);
+ assert_null(r_msg.msg_name);
+
+ close(s);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest sendmsg_tests[] = {
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_null,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv6,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(sendmsg_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket.c
new file mode 100644
index 0000000..57b92de
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket.c
@@ -0,0 +1,69 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void test_socket_getsockname(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ rc = getsockname(s, &addr.sa.s, &addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(addr.sa.in.sin_family, AF_INET);
+}
+
+#ifdef HAVE_IPV6
+static void test_socket_getsockname6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ rc = getsockname(s, &addr.sa.s, &addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(addr.sa.in6.sin6_family, AF_INET6);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest getsockname_tests[] = {
+ cmocka_unit_test(test_socket_getsockname),
+#ifdef HAVE_IPV6
+ cmocka_unit_test(test_socket_getsockname6),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(getsockname_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket_options.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket_options.c
new file mode 100644
index 0000000..dfa46fe
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_socket_options.c
@@ -0,0 +1,368 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef ZERO_STRUCT
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv6(state);
+
+ return 0;
+}
+
+static int setup_ipv6(void **state)
+{
+ torture_setup_socket_dir(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_sockopt_sndbuf(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int obufsize = 0;
+ socklen_t olen = sizeof(obufsize);
+ int gbufsize = 0;
+ socklen_t glen = sizeof(gbufsize);
+ int sbufsize = 0;
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &obufsize, &olen);
+ assert_int_equal(rc, 0);
+
+ /* request 4k, on Linux the kernel doubles the value */
+ sbufsize = 4096;
+ rc = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sbufsize, sizeof(sbufsize));
+ assert_int_equal(rc, 0);
+
+ rc = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &gbufsize, &glen);
+ assert_int_equal(rc, 0);
+
+ assert_true(sbufsize == gbufsize || sbufsize == gbufsize/2);
+
+ close(s);
+}
+
+#ifndef SO_PROTOCOL
+# ifdef SO_PROTOTYPE /* The Solaris name */
+# define SO_PROTOCOL SO_PROTOTYPE
+# endif /* SO_PROTOTYPE */
+#endif /* SO_PROTOCOL */
+
+static void test_sockopt_so(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ socklen_t so_len;
+#ifdef SO_DOMAIN
+ int so_domain = -1;
+#endif /* SO_DOMAIN */
+#ifdef SO_PROTOCOL
+ int so_protocol = -1;
+ int so_type = -1;
+#endif /* SO_PROTOCOL */
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+#ifdef SO_DOMAIN
+ so_len = sizeof(so_domain);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_DOMAIN,
+ &so_domain,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_domain, AF_INET);
+ assert_int_equal(so_len, sizeof(int));
+#endif /* SO_DOMAIN */
+
+#ifdef SO_PROTOCOL
+ so_len = sizeof(so_protocol);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_PROTOCOL,
+ &so_protocol,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_protocol, IPPROTO_TCP);
+ assert_int_equal(so_len, sizeof(int));
+
+ so_len = sizeof(so_type);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_TYPE,
+ &so_type,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_type, SOCK_STREAM);
+ assert_int_equal(so_len, sizeof(int));
+#endif /* SO_PROTOCOL */
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_sockopt_so6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+#ifdef SO_DOMAIN
+ int so_domain = -1;
+#endif /* SO_DOMAIN */
+#ifdef SO_PROTOCOL
+ socklen_t so_len;
+ int so_protocol = -1;
+ int so_type = -1;
+#endif /* SO_PROTOCOL */
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in6.sin6_family,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+#ifdef SO_DOMAIN
+ so_len = sizeof(so_domain);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_DOMAIN,
+ &so_domain,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_domain, AF_INET6);
+ assert_int_equal(so_len, sizeof(int));
+#endif /* SO_DOMAIN */
+
+#ifdef SO_PROTOCOL
+ so_len = sizeof(so_protocol);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_PROTOCOL,
+ &so_protocol,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_protocol, IPPROTO_TCP);
+ assert_int_equal(so_len, sizeof(int));
+
+ so_len = sizeof(so_type);
+ rc = getsockopt(s,
+ SOL_SOCKET,
+ SO_TYPE,
+ &so_type,
+ &so_len);
+ assert_return_code(rc, errno);
+ assert_int_equal(so_type, SOCK_STREAM);
+ assert_int_equal(so_len, sizeof(int));
+#endif /* SO_PROTOCOL */
+
+ close(s);
+}
+
+static void test_bind_ipv6_only(void **state)
+{
+ struct addrinfo hints;
+ struct addrinfo *res, *ri;
+ char svc[] = "7777";
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ ZERO_STRUCT(hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ rc = getaddrinfo(torture_server_address(AF_INET6), svc, &hints, &res);
+ assert_int_equal(rc, 0);
+
+ for (ri = res; ri != NULL; ri = ri->ai_next) {
+ int one = 1;
+
+ s = socket(ri->ai_family,
+ ri->ai_socktype,
+ ri->ai_protocol);
+ assert_int_not_equal(rc, -1);
+
+ rc = setsockopt(s,
+ IPPROTO_IPV6,
+ IPV6_V6ONLY,
+ (const void *)&one,
+ sizeof(one));
+ switch(ri->ai_family) {
+ case AF_INET:
+ assert_int_equal(rc, -1);
+
+ break;
+ case AF_INET6:
+ assert_int_equal(rc, 0);
+
+ rc = bind(s, ri->ai_addr, ri->ai_addrlen);
+ assert_int_equal(rc, 0);
+
+ break;
+ default:
+ break;
+ }
+
+ close(s);
+ }
+ freeaddrinfo(res);
+}
+#endif
+
+static void test_sockopt_tcp(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ int opt = -1;
+ socklen_t optlen = sizeof(int);
+ int rc;
+
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ rc = getsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen);
+ assert_return_code(rc, errno);
+ assert_int_equal(opt, 0);
+
+ opt = 1; /* Turn on TCP_NODELAY */
+ optlen = sizeof(int);
+ rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, optlen);
+ assert_return_code(rc, errno);
+
+ opt = -1;
+ optlen = sizeof(int);
+ rc = getsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen);
+ assert_return_code(rc, errno);
+ assert_int_equal(opt, 1);
+
+ close(s);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest sockopt_tests[] = {
+ cmocka_unit_test_setup_teardown(test_sockopt_sndbuf,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_sockopt_so,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_sockopt_so6,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_bind_ipv6_only,
+ setup_ipv6,
+ teardown),
+#endif
+ cmocka_unit_test_setup_teardown(test_sockopt_tcp,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+ };
+
+ rc = cmocka_run_group_tests(sockopt_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_write_read.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_write_read.c
new file mode 100644
index 0000000..9129022
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_write_read.c
@@ -0,0 +1,156 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_write_read_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 0; i < 10; i++) {
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = write(s,
+ send_buf,
+ sizeof(send_buf));
+ assert_int_not_equal(ret, -1);
+
+ ret = read(s,
+ recv_buf,
+ sizeof(recv_buf));
+ assert_int_not_equal(ret, -1);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_write_read_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 0; i < 10; i++) {
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = write(s,
+ send_buf,
+ sizeof(send_buf));
+ assert_int_not_equal(ret, -1);
+
+ ret = read(s,
+ recv_buf,
+ sizeof(recv_buf));
+ assert_int_not_equal(ret, -1);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tcp_write_tests[] = {
+ cmocka_unit_test_setup_teardown(test_write_read_ipv4,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_write_read_ipv6,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(tcp_write_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_tcp_writev_readv.c b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_writev_readv.c
new file mode 100644
index 0000000..e011236
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_tcp_writev_readv.c
@@ -0,0 +1,189 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_tcp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_writev_readv_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(addr.sa.in.sin_family,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 1; i < 10; i++) {
+ char send_buf[10][64];
+ char recv_buf[10][64];
+ struct iovec iov_send[10];
+ struct iovec iov_recv[10];
+ int j;
+
+ for (j = 0; j < i; j++) {
+ memset(send_buf[j], 0, 64);
+ snprintf(send_buf[j], sizeof(send_buf[j]),
+ "packet.%d", j);
+
+ iov_send[j].iov_base = send_buf[j];
+ iov_send[j].iov_len = strlen(send_buf[j]);
+
+ iov_recv[j].iov_base = recv_buf[j];
+ iov_recv[j].iov_len = strlen(send_buf[j]);
+ }
+
+ ret = writev(s, iov_send, j);
+ assert_int_not_equal(ret, -1);
+
+ ret = readv(s, iov_recv, j);
+ assert_int_not_equal(ret, -1);
+
+ for (j = 0; j < i; j++) {
+ assert_int_equal(iov_send[j].iov_len,
+ iov_recv[j].iov_len);
+
+ assert_memory_equal(iov_send[j].iov_base,
+ iov_recv[j].iov_base,
+ iov_send[j].iov_len);
+ }
+ }
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_writev_readv_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 1; i < 10; i++) {
+ char send_buf[10][64];
+ char recv_buf[10][64];
+ struct iovec iov_send[10];
+ struct iovec iov_recv[10];
+ int j;
+
+ for (j = 0; j < i; j++) {
+ memset(send_buf[j], 0, 64);
+ snprintf(send_buf[j], sizeof(send_buf[j]),
+ "packet.%d", j);
+
+ iov_send[j].iov_base = send_buf[j];
+ iov_send[j].iov_len = strlen(send_buf[j]);
+
+ iov_recv[j].iov_base = recv_buf[j];
+ iov_recv[j].iov_len = strlen(send_buf[j]);
+ }
+
+ ret = writev(s, iov_send, j);
+ assert_int_not_equal(ret, -1);
+
+ ret = readv(s, iov_recv, j);
+ assert_int_not_equal(ret, -1);
+
+ for (j = 0; j < i; j++) {
+ assert_int_equal(iov_send[j].iov_len,
+ iov_recv[j].iov_len);
+
+ assert_memory_equal(iov_send[j].iov_base,
+ iov_recv[j].iov_base,
+ iov_send[j].iov_len);
+ }
+ }
+
+ close(s);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tcp_writev_tests[] = {
+ cmocka_unit_test_setup_teardown(test_writev_readv_ipv4,
+ setup_echo_srv_tcp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_writev_readv_ipv6,
+ setup_echo_srv_tcp_ipv6,
+ teardown),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(tcp_writev_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_udp_send_recv.c b/tests/deckard/contrib/libswrap/tests/test_echo_udp_send_recv.c
new file mode 100644
index 0000000..cf4e848
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_udp_send_recv.c
@@ -0,0 +1,160 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_udp_ipv4(void **state)
+{
+ torture_setup_echo_srv_udp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_udp_ipv6(void **state)
+{
+ torture_setup_echo_srv_udp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_send_recv_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 0; i < 10; i++) {
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = send(s,
+ send_buf,
+ sizeof(send_buf),
+ 0);
+ assert_int_not_equal(ret, -1);
+
+ ret = recv(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_send_recv_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_int_equal(rc, 0);
+
+ for (i = 0; i < 10; i++) {
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = send(s,
+ send_buf,
+ sizeof(send_buf),
+ 0);
+ assert_int_not_equal(ret, -1);
+
+ ret = recv(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest send_tests[] = {
+ cmocka_unit_test_setup_teardown(test_send_recv_ipv4,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_send_recv_ipv6,
+ setup_echo_srv_udp_ipv6,
+ teardown),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(send_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendmsg_recvmsg.c b/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendmsg_recvmsg.c
new file mode 100644
index 0000000..93450b7
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendmsg_recvmsg.c
@@ -0,0 +1,407 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_udp_ipv4(void **state)
+{
+ torture_setup_echo_srv_udp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_udp_ipv6(void **state)
+{
+ torture_setup_echo_srv_udp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_sendmsg_recvmsg_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ for (i = 0; i < 10; i++) {
+ char ip[INET_ADDRSTRLEN] = {0};
+ const char *a;
+ struct torture_address srv_in = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ struct msghdr s_msg;
+ struct msghdr r_msg;
+ struct iovec s_iov;
+ struct iovec r_iov;
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ZERO_STRUCT(s_msg);
+
+ s_msg.msg_name = &addr.sa.s;
+ s_msg.msg_namelen = addr.sa_socklen;
+
+ s_iov.iov_base = send_buf;
+ s_iov.iov_len = sizeof(send_buf);
+
+ s_msg.msg_iov = &s_iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ ZERO_STRUCT(r_msg);
+
+ r_msg.msg_name = &srv_in.sa.s;
+ r_msg.msg_namelen = srv_in.sa_socklen;
+
+ r_iov.iov_base = recv_buf;
+ r_iov.iov_len = sizeof(recv_buf);
+
+ r_msg.msg_iov = &r_iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in));
+
+ a = inet_ntop(AF_INET, &srv_in.sa.in.sin_addr, ip, sizeof(ip));
+ assert_non_null(a);
+ assert_string_equal(a, torture_server_address(AF_INET));
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_sendmsg_recvmsg_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ for (i = 0; i < 10; i++) {
+ char ip[INET6_ADDRSTRLEN] = {0};
+ const char *a;
+ struct torture_address srv_in6 = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ struct msghdr s_msg;
+ struct msghdr r_msg;
+ struct iovec s_iov;
+ struct iovec r_iov;
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ZERO_STRUCT(s_msg);
+
+ s_msg.msg_name = &addr.sa.s;
+ s_msg.msg_namelen = addr.sa_socklen;
+
+ s_iov.iov_base = send_buf;
+ s_iov.iov_len = sizeof(send_buf);
+
+ s_msg.msg_iov = &s_iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ ZERO_STRUCT(r_msg);
+ r_msg.msg_name = &srv_in6.sa.s;
+ r_msg.msg_namelen = srv_in6.sa_socklen;
+
+ r_iov.iov_base = recv_buf;
+ r_iov.iov_len = sizeof(recv_buf);
+
+ r_msg.msg_iov = &r_iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in6));
+
+ a = inet_ntop(AF_INET6, &srv_in6.sa.in6.sin6_addr, ip, sizeof(ip));
+ assert_non_null(a);
+ assert_string_equal(a, torture_server_address(AF_INET6));
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ close(s);
+}
+#endif
+
+static void test_sendmsg_recvmsg_ipv4_connected(void **state)
+{
+ struct torture_address send_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct torture_address r_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = 0,
+ };
+ struct iovec iov;
+ char ip[INET_ADDRSTRLEN] = {0};
+ char payload[] = "PACKET";
+ const char *a;
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void)state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ send_addr.sa.in.sin_family = AF_INET;
+ send_addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &send_addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
+
+ iov.iov_base = (void *)payload;
+ iov.iov_len = sizeof(payload);
+
+ /* msg_name is NULL */
+
+ s_msg.msg_iov = &iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ r_msg.msg_name = &r_addr.sa.ss;
+ r_msg.msg_namelen = r_addr.sa_socklen;
+
+ memset(payload, 0, sizeof(payload));
+
+ r_msg.msg_iov = &iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in));
+
+ a = inet_ntop(AF_INET, &r_addr.sa.in.sin_addr, ip, sizeof(ip));
+ assert_non_null(a);
+ assert_string_equal(a, torture_server_address(AF_INET));
+
+ close(s);
+}
+
+static void test_sendmsg_recvmsg_ipv4_connected_null(void **state)
+{
+ struct torture_address send_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = 0,
+ };
+ struct iovec iov;
+ char payload[] = "PACKET";
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void)state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ send_addr.sa.in.sin_family = AF_INET;
+ send_addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &send_addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
+
+ /* msg_name = NULL */
+
+ iov.iov_base = (void *)payload;
+ iov.iov_len = sizeof(payload);
+
+ s_msg.msg_iov = &iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ /* msg_name = NULL */
+
+ memset(payload, 0, sizeof(payload));
+
+ r_msg.msg_iov = &iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ assert_int_equal(r_msg.msg_namelen, 0);
+ assert_null(r_msg.msg_name);
+
+ close(s);
+}
+
+static void test_sendmsg_recvmsg_ipv4_connected_namelen(void **state)
+{
+ struct torture_address send_addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ struct msghdr s_msg = {
+ .msg_namelen = 0,
+ };
+ struct msghdr r_msg = {
+ .msg_namelen = sizeof(struct sockaddr_storage),
+ };
+ struct iovec iov;
+ char payload[] = "PACKET";
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void)state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ send_addr.sa.in.sin_family = AF_INET;
+ send_addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &send_addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
+
+ /* msg_name = NULL */
+
+ iov.iov_base = (void *)payload;
+ iov.iov_len = sizeof(payload);
+
+ s_msg.msg_iov = &iov;
+ s_msg.msg_iovlen = 1;
+
+ ret = sendmsg(s, &s_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ /* msg_name = NULL */
+
+ memset(payload, 0, sizeof(payload));
+
+ r_msg.msg_iov = &iov;
+ r_msg.msg_iovlen = 1;
+
+ ret = recvmsg(s, &r_msg, 0);
+ assert_int_not_equal(ret, -1);
+
+ close(s);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest sendmsg_tests[] = {
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv6,
+ setup_echo_srv_udp_ipv6,
+ teardown),
+#endif
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected_null,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected_namelen,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+ };
+
+ rc = cmocka_run_group_tests(sendmsg_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendto_recvfrom.c b/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendto_recvfrom.c
new file mode 100644
index 0000000..bb22371
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_echo_udp_sendto_recvfrom.c
@@ -0,0 +1,316 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int setup_echo_srv_udp_ipv4(void **state)
+{
+ torture_setup_echo_srv_udp_ipv4(state);
+
+ return 0;
+}
+
+#ifdef HAVE_IPV6
+static int setup_echo_srv_udp_ipv6(void **state)
+{
+ torture_setup_echo_srv_udp_ipv6(state);
+
+ return 0;
+}
+#endif
+
+static int teardown(void **state)
+{
+ torture_teardown_echo_srv(state);
+
+ return 0;
+}
+
+static void test_sendto_recvfrom_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ for (i = 0; i < 10; i++) {
+ char ip[INET_ADDRSTRLEN] = {0};
+ const char *a;
+ struct torture_address srv_in = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ &addr.sa.s,
+ addr.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ &srv_in.sa.s,
+ &srv_in.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ a = inet_ntop(AF_INET, &srv_in.sa.in.sin_addr, ip, sizeof(ip));
+ assert_non_null(a);
+ assert_string_equal(a, torture_server_address(AF_INET));
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ &addr.sa.s,
+ addr.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ NULL,
+ NULL);
+ assert_int_not_equal(ret, -1);
+
+ close(s);
+}
+
+#ifdef HAVE_IPV6
+static void test_sendto_recvfrom_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+ char send_buf[64] = {0};
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int i;
+ int s;
+
+ (void) state; /* unused */
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ addr.sa.in6.sin6_family = AF_INET6;
+ addr.sa.in6.sin6_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET6,
+ torture_server_address(AF_INET6),
+ &addr.sa.in6.sin6_addr);
+ assert_int_equal(rc, 1);
+
+ for (i = 0; i < 10; i++) {
+ char ip[INET6_ADDRSTRLEN] = {0};
+ const char *a;
+ struct torture_address srv_in6 = {
+ .sa_socklen = sizeof(struct sockaddr_in6),
+ };
+
+ snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ &addr.sa.s,
+ addr.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ &srv_in6.sa.s,
+ &srv_in6.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ a = inet_ntop(AF_INET6, &srv_in6.sa.in6.sin6_addr, ip, sizeof(ip));
+ assert_non_null(a);
+ assert_string_equal(a, torture_server_address(AF_INET6));
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+ }
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ &addr.sa.s,
+ addr.sa_socklen);
+ assert_int_not_equal(ret, -1);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ NULL,
+ NULL);
+ assert_int_not_equal(ret, -1);
+
+ close(s);
+}
+#endif
+
+static void test_connect_sendto_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ char send_buf[] = "packet.0";
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ /* Now, connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ &addr.sa.s,
+ addr.sa_socklen);
+ assert_return_code(ret, errno);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ NULL,
+ 0);
+ assert_return_code(ret, errno);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+
+ close(s);
+}
+
+static void test_connect_sendto_null_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_in),
+ };
+ char send_buf[] = "packet.0";
+ char recv_buf[64] = {0};
+ ssize_t ret;
+ int rc;
+ int s;
+
+ (void) state; /* unused */
+
+ addr.sa.in.sin_family = AF_INET;
+ addr.sa.in.sin_port = htons(torture_server_port());
+
+ rc = inet_pton(AF_INET,
+ torture_server_address(AF_INET),
+ &addr.sa.in.sin_addr);
+ assert_int_equal(rc, 1);
+
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert_int_not_equal(s, -1);
+
+ /* Now, connect */
+ rc = connect(s, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ ret = sendto(s,
+ send_buf,
+ sizeof(send_buf),
+ 0,
+ NULL,
+ 0);
+ assert_return_code(ret, errno);
+
+ ret = recvfrom(s,
+ recv_buf,
+ sizeof(recv_buf),
+ 0,
+ NULL,
+ 0);
+ assert_return_code(ret, errno);
+
+ assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
+
+ close(s);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest sendto_tests[] = {
+ cmocka_unit_test_setup_teardown(test_sendto_recvfrom_ipv4,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+#ifdef HAVE_IPV6
+ cmocka_unit_test_setup_teardown(test_sendto_recvfrom_ipv6,
+ setup_echo_srv_udp_ipv6,
+ teardown),
+#endif
+ cmocka_unit_test_setup_teardown(test_connect_sendto_ipv4,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+ cmocka_unit_test_setup_teardown(test_connect_sendto_null_ipv4,
+ setup_echo_srv_udp_ipv4,
+ teardown),
+ };
+
+ rc = cmocka_run_group_tests(sendto_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_ioctl.c b/tests/deckard/contrib/libswrap/tests/test_ioctl.c
new file mode 100644
index 0000000..aebff91
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_ioctl.c
@@ -0,0 +1,110 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+static int setup(void **state)
+{
+ char test_tmpdir[256];
+ const char *p;
+
+ (void) state; /* unused */
+
+ snprintf(test_tmpdir, sizeof(test_tmpdir), "/tmp/test_socket_wrapper_XXXXXX");
+
+ p = mkdtemp(test_tmpdir);
+ assert_non_null(p);
+
+ *state = strdup(p);
+ setenv("SOCKET_WRAPPER_DIR", p, 1);
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "11", 1);
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ char remove_cmd[PATH_MAX] = {0};
+ char *s = (char *)*state;
+ int rc;
+
+ if (s == NULL) {
+ return -1;
+ }
+
+ snprintf(remove_cmd, sizeof(remove_cmd), "rm -rf %s", s);
+ free(s);
+
+ rc = system(remove_cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s failed: %s", remove_cmd, strerror(errno));
+ }
+
+ return rc;
+}
+
+static void test_swrap_socket(void **state)
+{
+ int rc;
+
+ (void) state; /* unused */
+
+ rc = socket(1337, 1337, 0);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EAFNOSUPPORT);
+
+ rc = socket(AF_INET, 1337, 0);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EPROTONOSUPPORT);
+
+ rc = socket(AF_INET, SOCK_DGRAM, 10);
+ assert_int_equal(rc, -1);
+ assert_int_equal(errno, EPROTONOSUPPORT);
+}
+
+static void test_swrap_ioctl_sock(void **state)
+{
+ int fd;
+#ifdef SIOCGPGRP
+ int rc;
+ int grp = -127;
+#endif
+
+ (void) state; /* unused */
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ assert_int_not_equal(fd, -1);
+
+#ifdef SIOCGPGRP
+ rc = ioctl(fd, SIOCGPGRP, &grp);
+ assert_int_equal(rc, 0);
+
+ assert_int_not_equal(grp, -127);
+#endif
+
+ close(fd);
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest ioctl_tests[] = {
+ cmocka_unit_test_setup_teardown(test_swrap_socket, setup, teardown),
+ cmocka_unit_test_setup_teardown(test_swrap_ioctl_sock, setup, teardown),
+ };
+
+ rc = cmocka_run_group_tests(ioctl_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_sendmsg_recvmsg_fd.c b/tests/deckard/contrib/libswrap/tests/test_sendmsg_recvmsg_fd.c
new file mode 100644
index 0000000..30c9861
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_sendmsg_recvmsg_fd.c
@@ -0,0 +1,116 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+static void test_sendmsg_recvmsg_fd(void **state)
+{
+ int sv[2];
+ int child_fd, parent_fd;
+ int rc;
+ pid_t pid;
+
+ (void) state; /* unused */
+
+ rc = socketpair(AF_LOCAL, SOCK_STREAM, 0, sv);
+ assert_int_not_equal(rc, -1);
+
+ parent_fd = sv[0];
+ child_fd = sv[1];
+
+ pid = fork();
+ assert_int_not_equal(pid, -1);
+
+ if (pid == 0) {
+ /* Child */
+ struct msghdr child_msg;
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *cmsg;
+ int rcv_fd;
+ char buf[8];
+ int i;
+
+ memset(&child_msg, 0, sizeof(child_msg));
+ child_msg.msg_control = cmsgbuf;
+ child_msg.msg_controllen = sizeof(cmsgbuf);
+
+ do {
+ errno = 0;
+ rc = recvmsg(child_fd, &child_msg, 0);
+ } while (errno == EAGAIN || errno == EWOULDBLOCK);
+ assert_int_not_equal(rc, -1);
+
+ cmsg = CMSG_FIRSTHDR(&child_msg);
+ assert_non_null(cmsg);
+ assert_int_equal(cmsg->cmsg_type, SCM_RIGHTS);
+
+ memcpy(&rcv_fd, CMSG_DATA(cmsg), sizeof(rcv_fd));
+ assert_int_not_equal(rcv_fd, -1);
+
+ rc = read(rcv_fd, buf, sizeof(buf));
+ assert_int_not_equal(rc, -1);
+ for (i = 0; i < 8; i++) {
+ assert_int_equal(buf[i], 0);
+ }
+ exit(0);
+ } else {
+ /* Parent */
+ int pass_fd;
+ struct msghdr parent_msg;
+ struct cmsghdr *cmsg;
+ char cmsgbuf[CMSG_SPACE(sizeof(pass_fd))];
+ char byte = '!';
+ struct iovec iov;
+ int cs;
+
+ pass_fd = open("/dev/zero", O_RDONLY);
+ assert_int_not_equal(pass_fd, -1);
+
+ iov.iov_base = &byte;
+ iov.iov_len = 1;
+
+ memset(&parent_msg, 0, sizeof(parent_msg));
+ parent_msg.msg_iov = &iov;
+ parent_msg.msg_iovlen = 1;
+ parent_msg.msg_control = cmsgbuf;
+ parent_msg.msg_controllen = sizeof(cmsgbuf);
+
+ cmsg = CMSG_FIRSTHDR(&parent_msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(pass_fd));
+
+ memcpy(CMSG_DATA(cmsg), &pass_fd, sizeof(pass_fd));
+ parent_msg.msg_controllen = cmsg->cmsg_len;
+
+ rc = sendmsg(parent_fd, &parent_msg, 0);
+ assert_int_not_equal(rc, -1);
+
+ alarm(5); /* 5 seconds timeout for the child */
+ rc = waitpid(pid, &cs, 0);
+ assert_int_not_equal(rc, -1);
+ }
+}
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_sendmsg_recvmsg_fd),
+ };
+
+ rc = cmocka_run_group_tests(tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_swrap_unit.c b/tests/deckard/contrib/libswrap/tests/test_swrap_unit.c
new file mode 100644
index 0000000..469aa24
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_swrap_unit.c
@@ -0,0 +1,120 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#include "socket_wrapper.c"
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+
+/**
+ * test wrap_sendmsg_filter_cmsghdr()
+ *
+ * Prepare a message with two cmsg:
+ * - the first cmsg is a char buf with the string "Hello World"
+ * - the second cmsg is a char buf with the string "!\n"
+ *
+ * Both cmsgs will be copied without modification by
+ * wrap_sendmsg_filter_cmsghdr(), so we can check that the msg
+ * controllen, the cmsg sizes and the payload are the same.
+ *
+ * We use an not existing cmsg_type which triggers cmsg copying.
+ */
+static void test_sendmsg_cmsg(void **state)
+{
+ int rc = 0;
+ char byte = '!';
+ struct iovec iov;
+ struct msghdr msg = { 0 };
+ struct cmsghdr *cmsg;
+ char *cmsgbuf;
+ int cmsgbuf_size;
+ const char *s1 = "Hello World";
+ const int s1_len = strlen(s1);
+ const char *s2 = "!\n";
+ const int s2_len = strlen(s2);
+ uint8_t *cmbuf = NULL;
+ size_t cmlen = 0;
+
+ (void)state; /* unused */
+
+ iov.iov_base = &byte;
+ iov.iov_len = 1;
+
+ /*
+ * Prepare cmsgbuf and msg
+ */
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ cmsgbuf_size = CMSG_SPACE(s1_len) + CMSG_SPACE(s2_len);
+ cmsgbuf = calloc(cmsgbuf_size, sizeof(char));
+ assert_non_null(cmsgbuf);
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = cmsgbuf_size;
+
+ /*
+ * Prepare first cmsg with string "Hello World"
+ */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ assert_non_null(cmsg);
+
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = ~0 - 1;
+ cmsg->cmsg_len = CMSG_LEN(s1_len);
+ memcpy(CMSG_DATA(cmsg), s1, s1_len);
+
+ /*
+ * Prepare second cmsg with string "!\n"
+ */
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ assert_non_null(cmsg);
+
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = ~0 - 2;
+ cmsg->cmsg_len = CMSG_LEN(s2_len);
+ memcpy(CMSG_DATA(cmsg), s2, s2_len);
+
+ /*
+ * Now call swrap_sendmsg_filter_cmsghdr() on the msg
+ */
+ rc = swrap_sendmsg_filter_cmsghdr(&msg, &cmbuf, &cmlen);
+ assert_return_code(rc, errno);
+ assert_int_equal(cmlen, msg.msg_controllen);
+
+ /*
+ * Insert filtered cmsgbug into msg and validate cmsgs.
+ */
+ msg.msg_control = cmbuf;
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ assert_non_null(cmsg);
+ assert_int_equal(cmsg->cmsg_len, CMSG_LEN(s1_len));
+ assert_memory_equal(CMSG_DATA(cmsg), s1, s1_len);
+
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ assert_non_null(cmsg);
+ assert_int_equal(cmsg->cmsg_len, CMSG_LEN(s2_len));
+ assert_memory_equal(CMSG_DATA(cmsg), s2, s2_len);
+
+ free(cmbuf);
+ free(cmsgbuf);
+}
+#endif
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest unit_tests[] = {
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ cmocka_unit_test(test_sendmsg_cmsg),
+#endif
+ };
+
+ rc = cmocka_run_group_tests(unit_tests, NULL, NULL);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/test_tcp_listen.c b/tests/deckard/contrib/libswrap/tests/test_tcp_listen.c
new file mode 100644
index 0000000..5641c47
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/test_tcp_listen.c
@@ -0,0 +1,115 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
+
+static int setup(void **state)
+{
+ torture_setup_socket_dir(state);
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ torture_teardown_socket_dir(state);
+
+ return 0;
+}
+
+static void test_listen_unbound_ipv4(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s1;
+ int s2;
+
+ (void) state; /* unused */
+
+ s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s1, errno);
+
+ rc = listen(s1, SOMAXCONN);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s1, &addr.sa.s, &addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(addr.sa_socklen, sizeof(struct sockaddr_in));
+ assert_in_range(ntohs(addr.sa.in.sin_port), 1024, 65535);
+
+ s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s2, errno);
+
+ rc = connect(s2, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s1);
+ close(s2);
+}
+
+#ifdef HAVE_IPV6
+static void test_listen_unbound_ipv6(void **state)
+{
+ struct torture_address addr = {
+ .sa_socklen = sizeof(struct sockaddr_storage),
+ };
+ int rc;
+ int s1;
+ int s2;
+
+ (void) state; /* unused */
+
+ s1 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s1, errno);
+
+ rc = listen(s1, SOMAXCONN);
+ assert_return_code(rc, errno);
+
+ rc = getsockname(s1, &addr.sa.s, &addr.sa_socklen);
+ assert_return_code(rc, errno);
+ assert_int_equal(addr.sa_socklen, sizeof(struct sockaddr_in6));
+ assert_in_range(ntohs(addr.sa.in6.sin6_port), 1024, 65535);
+
+ s2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ assert_return_code(s2, errno);
+
+ rc = connect(s2, &addr.sa.s, addr.sa_socklen);
+ assert_return_code(rc, errno);
+
+ close(s1);
+ close(s2);
+}
+#endif /* HAVE_IPV6 */
+
+int main(void) {
+ int rc;
+
+ const struct CMUnitTest tcp_listen_tests[] = {
+ cmocka_unit_test(test_listen_unbound_ipv4),
+#ifdef HAVE_IPV6
+ cmocka_unit_test(test_listen_unbound_ipv6),
+#endif /* HAVE_IPV6 */
+ };
+
+ rc = cmocka_run_group_tests(tcp_listen_tests, setup, teardown);
+
+ return rc;
+}
diff --git a/tests/deckard/contrib/libswrap/tests/torture.c b/tests/deckard/contrib/libswrap/tests/torture.c
new file mode 100644
index 0000000..d3ad84a
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/torture.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ *
+ * 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 author 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#include "config.h"
+
+#include "torture.h"
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdbool.h>
+
+#define TORTURE_ECHO_SRV_IPV4 "127.0.0.10"
+/* socket wrapper IPv6 prefix fd00::5357:5fxx */
+#define TORTURE_ECHO_SRV_IPV6 "fd00::5357:5f0a"
+#define TORTURE_ECHO_SRV_PORT 7
+
+#define TORTURE_SOCKET_DIR "/tmp/w_XXXXXX"
+#define TORTURE_ECHO_SRV_PIDFILE "echo_srv.pid"
+#define TORTURE_PCAP_FILE "socket_trace.pcap"
+
+const char *torture_server_address(int family)
+{
+ switch (family) {
+ case AF_INET: {
+ const char *ip4 = getenv("TORTURE_SERVER_ADDRESS_IPV4");
+
+ if (ip4 != NULL && ip4[0] != '\0') {
+ return ip4;
+ }
+
+ return TORTURE_ECHO_SRV_IPV4;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ const char *ip6 = getenv("TORTURE_SERVER_ADDRESS_IPV6");
+
+ if (ip6 != NULL && ip6[0] != '\0') {
+ return ip6;
+ }
+
+ return TORTURE_ECHO_SRV_IPV6;
+ }
+#endif
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+int torture_server_port(void)
+{
+ char *env = getenv("TORTURE_SERVER_PORT");
+
+ if (env != NULL && env[0] != '\0' && strlen(env) < 6) {
+ int port = atoi(env);
+
+ if (port > 0 && port < 65536) {
+ return port;
+ }
+ }
+
+ return TORTURE_ECHO_SRV_PORT;
+}
+
+void torture_setup_socket_dir(void **state)
+{
+ struct torture_state *s;
+ const char *p;
+ size_t len;
+
+ s = malloc(sizeof(struct torture_state));
+ assert_non_null(s);
+
+ s->socket_dir = strdup(TORTURE_SOCKET_DIR);
+ assert_non_null(s->socket_dir);
+
+ p = mkdtemp(s->socket_dir);
+ assert_non_null(p);
+
+ /* pcap file */
+ len = strlen(p) + 1 + strlen(TORTURE_PCAP_FILE) + 1;
+
+ s->pcap_file = malloc(len);
+ assert_non_null(s->pcap_file);
+
+ snprintf(s->pcap_file, len, "%s/%s", p, TORTURE_PCAP_FILE);
+
+ /* pid file */
+ len = strlen(p) + 1 + strlen(TORTURE_ECHO_SRV_PIDFILE) + 1;
+
+ s->srv_pidfile = malloc(len);
+ assert_non_null(s->srv_pidfile);
+
+ snprintf(s->srv_pidfile, len, "%s/%s", p, TORTURE_ECHO_SRV_PIDFILE);
+
+ setenv("SOCKET_WRAPPER_DIR", p, 1);
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1);
+ setenv("SOCKET_WRAPPER_PCAP_FILE", s->pcap_file, 1);
+
+ *state = s;
+}
+
+static void torture_setup_echo_srv_ip(void **state,
+ const char *ip,
+ int port,
+ int type)
+{
+ struct torture_state *s;
+ char start_echo_srv[1024] = {0};
+ const char *t;
+ int count = 0;
+ int rc;
+
+ torture_setup_socket_dir(state);
+
+ s = *state;
+
+ switch (type) {
+ case SOCK_STREAM:
+ t = "-t";
+ break;
+ case SOCK_DGRAM:
+ t = "-u";
+ break;
+ default:
+ t = "";
+ break;
+ }
+
+ /* set default iface for the server */
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
+
+ snprintf(start_echo_srv, sizeof(start_echo_srv),
+ "%s/tests/echo_srv -b %s -p %d -D %s --pid %s",
+ BINARYDIR, ip, port, t, s->srv_pidfile);
+
+ rc = system(start_echo_srv);
+ assert_int_equal(rc, 0);
+
+ do {
+ struct stat sb;
+
+ count++;
+ if (count > 100) {
+ break;
+ }
+
+ rc = stat(s->srv_pidfile, &sb);
+ usleep(200);
+ } while (rc != 0);
+ assert_int_equal(rc, 0);
+
+ /* set default iface for the client */
+ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1);
+}
+
+void torture_setup_echo_srv_udp_ipv4(void **state)
+{
+ torture_setup_echo_srv_ip(state,
+ "0.0.0.0",
+ torture_server_port(),
+ SOCK_DGRAM);
+}
+
+void torture_setup_echo_srv_udp_ipv6(void **state)
+{
+ torture_setup_echo_srv_ip(state,
+ "::",
+ torture_server_port(),
+ SOCK_DGRAM);
+}
+
+void torture_setup_echo_srv_tcp_ipv4(void **state)
+{
+ torture_setup_echo_srv_ip(state,
+ "0.0.0.0",
+ torture_server_port(),
+ SOCK_STREAM);
+}
+
+void torture_setup_echo_srv_tcp_ipv6(void **state)
+{
+ torture_setup_echo_srv_ip(state,
+ "::",
+ torture_server_port(),
+ SOCK_STREAM);
+}
+
+void torture_teardown_socket_dir(void **state)
+{
+ struct torture_state *s = *state;
+ char *env = getenv("TORTURE_SKIP_CLEANUP");
+ char remove_cmd[1024] = {0};
+ int rc;
+
+ if (env != NULL && env[0] == '1') {
+ fprintf(stderr, ">>> Skipping cleanup of %s", s->socket_dir);
+ } else {
+ snprintf(remove_cmd, sizeof(remove_cmd), "rm -rf %s", s->socket_dir);
+
+ rc = system(remove_cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s failed: %s", remove_cmd, strerror(errno));
+ }
+ }
+
+ free(s->socket_dir);
+ free(s->pcap_file);
+ free(s->srv_pidfile);
+ free(s);
+}
+
+void torture_teardown_echo_srv(void **state)
+{
+ struct torture_state *s = *state;
+ char buf[8] = {0};
+ long int tmp;
+ ssize_t rc;
+ pid_t pid;
+ int fd;
+ bool is_running = true;
+ int count;
+
+ /* read the pidfile */
+ fd = open(s->srv_pidfile, O_RDONLY);
+ if (fd < 0) {
+ goto done;
+ }
+
+ rc = read(fd, buf, sizeof(buf));
+ close(fd);
+ if (rc <= 0) {
+ goto done;
+ }
+
+ buf[sizeof(buf) - 1] = '\0';
+
+ tmp = strtol(buf, NULL, 10);
+ if (tmp == 0 || tmp > 0xFFFF || errno == ERANGE) {
+ goto done;
+ }
+
+ pid = (pid_t)(tmp & 0xFFFF);
+
+ for (count = 0; count < 10; count++) {
+ /* Make sure the daemon goes away! */
+ kill(pid, SIGTERM);
+
+ usleep(200);
+
+ rc = kill(pid, 0);
+ if (rc != 0) {
+ is_running = false;
+ break;
+ }
+ }
+
+ if (is_running) {
+ fprintf(stderr,
+ "WARNING the echo server is still running!\n");
+ }
+
+done:
+ torture_teardown_socket_dir(state);
+}
+
+void torture_generate_random_buffer(uint8_t *out, int len)
+{
+ int i;
+
+ srand(time(NULL));
+
+ for (i = 0; i < len; i++) {
+ out[i] = (uint8_t)rand();
+ }
+}
diff --git a/tests/deckard/contrib/libswrap/tests/torture.h b/tests/deckard/contrib/libswrap/tests/torture.h
new file mode 100644
index 0000000..921195d
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/torture.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
+ *
+ * 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 author 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef _TORTURE_H
+#define _TORTURE_H
+
+#include "config.h"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <stdint.h>
+#include <string.h>
+
+struct torture_address {
+ socklen_t sa_socklen;
+ union {
+ struct sockaddr s;
+ struct sockaddr_in in;
+#ifdef HAVE_IPV6
+ struct sockaddr_in6 in6;
+#endif
+ struct sockaddr_un un;
+ struct sockaddr_storage ss;
+ } sa;
+};
+
+struct torture_state {
+ char *socket_dir;
+ char *pcap_file;
+ char *srv_pidfile;
+};
+
+#ifndef ZERO_STRUCT
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
+
+const char *torture_server_address(int domain);
+int torture_server_port(void);
+
+void torture_setup_socket_dir(void **state);
+void torture_setup_echo_srv_udp_ipv4(void **state);
+void torture_setup_echo_srv_udp_ipv6(void **state);
+
+void torture_setup_echo_srv_tcp_ipv4(void **state);
+void torture_setup_echo_srv_tcp_ipv6(void **state);
+
+void torture_teardown_socket_dir(void **state);
+void torture_teardown_echo_srv(void **state);
+
+void torture_generate_random_buffer(uint8_t *out, int len);
+#endif /* _TORTURE_H */
diff --git a/tests/deckard/contrib/libswrap/tests/valgrind.supp b/tests/deckard/contrib/libswrap/tests/valgrind.supp
new file mode 100644
index 0000000..9857825
--- /dev/null
+++ b/tests/deckard/contrib/libswrap/tests/valgrind.supp
@@ -0,0 +1,16 @@
+### GLIBC
+{
+ glibc_dlopen_alloc
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlopen@@GLIBC_2.2.5
+}
+
+{
+ glibc_dlclose_alloc
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlclose
+}
diff --git a/tests/deckard/deckard.py b/tests/deckard/deckard.py
new file mode 100755
index 0000000..6b75c70
--- /dev/null
+++ b/tests/deckard/deckard.py
@@ -0,0 +1,432 @@
+#!/usr/bin/env python3
+from datetime import datetime
+import errno
+import ipaddress
+import logging
+import logging.config
+import os
+import shutil
+import socket
+import subprocess
+import tempfile
+import time
+from typing import Set # noqa
+
+import dpkt
+import jinja2
+
+from pydnstest import scenario, testserver
+
+
+# path to Deckard files
+INSTALLDIR = os.path.dirname(os.path.abspath(__file__))
+# relative to working directory
+TRUST_ANCHOR_SUBDIR = 'ta'
+
+
+class DeckardUnderLoadError(Exception):
+ pass
+
+
+class IfaceManager:
+ """
+ Network interface allocation manager
+
+ Keeps mapping between 'name', interface number, and IP address.
+ """
+ def __init__(self, sockfamily):
+ """
+ Parameters:
+ sockfamily Address family used in given test scenatio
+ (a constant from socket module)
+ """
+ if sockfamily not in {socket.AF_INET, socket.AF_INET6}:
+ raise NotImplementedError("address family not supported '%i'" % sockfamily)
+ self.sockfamily = sockfamily
+ self.free = list(range(40, 10, -1)) # range accepted by libswrap
+ self.name2iface = {}
+
+ def allocate(self, name):
+ """
+ Map name to a free interface number.
+ """
+ if name in self.name2iface:
+ raise ValueError('duplicate interface name %s' % name)
+ iface = str(self.free.pop())
+ self.name2iface[name] = iface
+ return iface
+
+ def getiface(self, name):
+ """
+ Map name to allocated interface number.
+
+ Returns:
+ Interface number as string (so it can be assigned to os.environ)
+ """
+ return self.name2iface[name]
+
+ def getipaddr(self, name):
+ """
+ Get default IP address assigned to interface allocated to given name.
+
+ Returns:
+ Address from address family specified during IfaceManager init.
+ """
+ iface = self.getiface(name)
+ if self.sockfamily == socket.AF_INET:
+ addr_local_pattern = "127.0.0.{}"
+ elif self.sockfamily == socket.AF_INET6:
+ addr_local_pattern = "fd00::5357:5f{:02X}"
+ return addr_local_pattern.format(int(iface))
+
+ def getalladdrs(self):
+ """
+ Get mapping from all names to all IP addresses.
+
+ Returns:
+ {name: IP address}
+ """
+ return {name: self.getipaddr(name)
+ for name in self.name2iface}
+
+
+def write_timestamp_file(path, tst):
+ time_file = open(path, 'w')
+ time_file.write(datetime.fromtimestamp(tst).strftime('@%Y-%m-%d %H:%M:%S'))
+ time_file.flush()
+ time_file.close()
+
+
+def setup_common_env(ctx):
+ """
+ Setup environment shared between Deckard and binaries under test.
+
+ Environment for child processes must be based on on.environ as modified
+ by this function.
+
+ Returns:
+ path to working directory
+ """
+ # working directory
+ if "SOCKET_WRAPPER_DIR" in os.environ:
+ tmpdir = os.environ["SOCKET_WRAPPER_DIR"]
+ if os.path.lexists(tmpdir):
+ raise ValueError('SOCKET_WRAPPER_DIR "%s" must not exist' % tmpdir)
+ else:
+ tmpdir = tempfile.mkdtemp(suffix='', prefix='tmpdeckard')
+
+ # Set up libfaketime
+ os.environ["FAKETIME_NO_CACHE"] = "1"
+ os.environ["FAKETIME_TIMESTAMP_FILE"] = '%s/.time' % tmpdir
+ # fake initial time
+ write_timestamp_file(os.environ["FAKETIME_TIMESTAMP_FILE"],
+ ctx.get('_OVERRIDE_TIMESTAMP', time.time()))
+
+ # Set up socket_wrapper
+ os.environ["SOCKET_WRAPPER_DIR"] = tmpdir
+ os.environ["SOCKET_WRAPPER_PCAP_FILE"] = '%s/deckard.pcap' % tmpdir
+
+ return tmpdir
+
+
+def setup_daemon_env(prog_cfg, tmpdir):
+ """ Set up test environment and config """
+ name = prog_cfg['name']
+ log = logging.getLogger('deckard.daemon.%s.setup_env' % name)
+ # Set up child process env() to use socket wrapper interface
+ child_env = os.environ.copy()
+ child_env['SOCKET_WRAPPER_DEFAULT_IFACE'] = prog_cfg['iface']
+ prog_cfg['dir'] = os.path.join(tmpdir, name)
+ log.debug('directory: %s', prog_cfg['dir'])
+ child_env['SOCKET_WRAPPER_PCAP_FILE'] = '%s/pcap' % prog_cfg['dir']
+
+ return child_env
+
+
+def setup_network(sockfamily, prog_cfgs):
+ """Allocate fake interfaces and IP addresses to all entities.
+
+ Returns:
+ - SOCKET_WRAPPER_DEFAULT_IFACE will be set in os.environ
+ - Dict suitable for usage in Jinja2 templates will be returned
+ {
+ ROOT_ADDR: <DeckardIP>,
+ IPADDRS: {name: <IPaddress>}
+ }
+ """
+ net_config = {}
+ # assign interfaces and IP addresses to all involved programs
+ ifacemgr = IfaceManager(sockfamily)
+ # fake interface for Deckard itself
+ deckard_iface = ifacemgr.allocate('deckard')
+ os.environ['SOCKET_WRAPPER_DEFAULT_IFACE'] = deckard_iface
+ net_config['ROOT_ADDR'] = ifacemgr.getipaddr('deckard')
+
+ for prog_cfg in prog_cfgs['programs']:
+ prog_cfg['iface'] = ifacemgr.allocate(prog_cfg['name'])
+ prog_cfg['ipaddr'] = ifacemgr.getipaddr(prog_cfg['name'])
+ net_config['IPADDRS'] = ifacemgr.getalladdrs()
+
+ return net_config
+
+
+def _fixme_prebind_hack(sockfamily, childaddr):
+ """
+ Prebind to sockets to create necessary files
+
+ @TODO: this is probably a workaround for socket_wrapper bug
+ """
+ if 'NOPRELOAD' not in os.environ:
+ for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM):
+ sock = socket.socket(sockfamily, sock_type)
+ sock.setsockopt(sockfamily, socket.SO_REUSEADDR, 1)
+ sock.bind((childaddr, 53))
+ if sock_type & socket.SOCK_STREAM:
+ sock.listen(5)
+
+
+def create_trust_anchor_files(ta_files, work_dir):
+ """
+ Write trust anchor files in specified working directory.
+
+ Params:
+ ta_files Dict {domain name: [TA lines]}
+ Returns:
+ List of absolute filesystem paths to TA files.
+ """
+ full_paths = []
+ for domain, ta_lines in ta_files.items():
+ file_name = u'{}.key'.format(domain)
+ full_path = os.path.realpath(
+ os.path.join(work_dir, TRUST_ANCHOR_SUBDIR, file_name))
+ full_paths.append(full_path)
+ dir_path = os.path.dirname(full_path)
+ try:
+ os.makedirs(dir_path)
+ except OSError as ex:
+ if ex.errno != errno.EEXIST:
+ raise
+ with open(full_path, "w") as ta_file:
+ ta_file.writelines('{0}\n'.format(l) for l in ta_lines)
+ return full_paths
+
+
+def setup_daemon_files(prog_cfg, template_ctx, ta_files):
+ name = prog_cfg['name']
+ # add program-specific variables
+ subst = template_ctx.copy()
+ subst['DAEMON_NAME'] = name
+
+ subst['WORKING_DIR'] = prog_cfg['dir']
+ os.mkdir(prog_cfg['dir'])
+ subst['SELF_ADDR'] = prog_cfg['ipaddr']
+
+ # daemons might write to TA files so every daemon gets its own copy
+ subst['TRUST_ANCHOR_FILES'] = create_trust_anchor_files(
+ ta_files, prog_cfg['dir'])
+
+ # generate configuration files
+ j2template_loader = jinja2.FileSystemLoader(searchpath=os.getcwd())
+ print(os.path.abspath(os.getcwd()))
+ j2template_env = jinja2.Environment(loader=j2template_loader)
+ logging.getLogger('deckard.daemon.%s.template' % name).debug(subst)
+
+ assert len(prog_cfg['templates']) == len(prog_cfg['configs'])
+ for template_name, config_name in zip(prog_cfg['templates'], prog_cfg['configs']):
+ j2template = j2template_env.get_template(template_name)
+ cfg_rendered = j2template.render(subst)
+ with open(os.path.join(prog_cfg['dir'], config_name), 'w') as output:
+ output.write(cfg_rendered)
+
+ _fixme_prebind_hack(template_ctx['_SOCKET_FAMILY'], subst['SELF_ADDR'])
+
+
+def run_daemon(cfg, environ):
+ """Start binary and return its process object"""
+ name = cfg['name']
+ proc = None
+ cfg['log'] = os.path.join(cfg['dir'], 'server.log')
+ daemon_log_file = open(cfg['log'], 'w')
+ cfg['args'] = args = [cfg['binary']] + cfg['additional']
+ logging.getLogger('deckard.daemon.%s.env' % name).debug('%s', environ)
+ logging.getLogger('deckard.daemon.%s.argv' % name).debug('%s', args)
+ try:
+ proc = subprocess.Popen(args, stdout=daemon_log_file, stderr=subprocess.STDOUT,
+ cwd=cfg['dir'], env=environ, start_new_session=True)
+ except subprocess.CalledProcessError:
+ logger = logging.getLogger('deckard.daemon_log.%s' % name)
+ logger.exception("Can't start '%s'", args)
+ raise
+ return proc
+
+
+def conncheck_daemon(process, cfg, sockfamily):
+ """Wait until the server accepts TCP clients"""
+ sock = socket.socket(sockfamily, socket.SOCK_STREAM)
+ tstart = datetime.now()
+ while True:
+ time.sleep(0.1)
+ if (datetime.now() - tstart).total_seconds() > 5:
+ raise RuntimeError("Server took too long to respond")
+ # Check if the process is running
+ if process.poll() is not None:
+ msg = 'process died "%s", logs in "%s"' % (cfg['name'], cfg['dir'])
+ logger = logging.getLogger('deckard.daemon_log.%s' % cfg['name'])
+ logger.critical(msg)
+ logger.error(open(cfg['log']).read())
+ raise subprocess.CalledProcessError(process.returncode, cfg['args'], msg)
+ try:
+ sock.connect((cfg['ipaddr'], 53))
+ except socket.error:
+ continue
+ break
+ sock.close()
+
+
+def process_file(path, qmin, prog_cfgs):
+ """Parse scenario from a file object and create workdir."""
+ # Parse scenario
+ case, cfg_text = scenario.parse_file(os.path.realpath(path))
+ cfg_ctx, ta_files = scenario.parse_config(cfg_text, qmin, INSTALLDIR)
+ template_ctx = setup_network(cfg_ctx['_SOCKET_FAMILY'], prog_cfgs)
+ # merge variables from scenario with generated network variables (scenario has priority)
+ template_ctx.update(cfg_ctx)
+ # Deckard will communicate with first program
+ prog_under_test = prog_cfgs['programs'][0]['name']
+ prog_under_test_ip = template_ctx['IPADDRS'][prog_under_test]
+
+ # get working directory and environment variables
+ tmpdir = setup_common_env(cfg_ctx)
+ shutil.copy2(path, os.path.join(tmpdir))
+ try:
+ daemons = setup_daemons(tmpdir, prog_cfgs, template_ctx, ta_files)
+ run_testcase(daemons,
+ case,
+ template_ctx['ROOT_ADDR'],
+ template_ctx['_SOCKET_FAMILY'],
+ prog_under_test_ip)
+ if prog_cfgs.get('noclean'):
+ logging.getLogger('deckard.hint').info(
+ 'test working directory %s', tmpdir)
+ else:
+ shutil.rmtree(tmpdir)
+ except Exception:
+ logging.getLogger('deckard.hint').error(
+ 'test failed, inspect working directory %s', tmpdir)
+ raise
+
+
+def setup_daemons(tmpdir, prog_cfgs, template_ctx, ta_files):
+ """Configure daemons and run the test"""
+ # Setup daemon environment
+ daemons = []
+ for prog_cfg in prog_cfgs['programs']:
+ daemon_env = setup_daemon_env(prog_cfg, tmpdir)
+ setup_daemon_files(prog_cfg, template_ctx, ta_files)
+ daemon_proc = run_daemon(prog_cfg, daemon_env)
+ daemons.append({'proc': daemon_proc, 'cfg': prog_cfg})
+ try:
+ conncheck_daemon(daemon_proc, prog_cfg, template_ctx['_SOCKET_FAMILY'])
+ except: # noqa -- bare except might be valid here?
+ daemon_proc.terminate()
+ raise
+ return daemons
+
+
+def check_for_icmp():
+ """ Checks Deckards's PCAP for ICMP packets """
+ # Deckard's responses to resolvers might be delayed due to load which
+ # leads the resolver to close the port and to the test failing in the
+ # end. We partially detect these by checking the PCAP for ICMP packets.
+ path = os.environ["SOCKET_WRAPPER_PCAP_FILE"]
+ udp_seen = False
+ with open(path, "rb") as f:
+ pcap = dpkt.pcap.Reader(f)
+ for _, packet in pcap:
+ try:
+ ip = dpkt.ip.IP(packet)
+ except dpkt.dpkt.UnpackError:
+ ip = dpkt.ip6.IP6(packet)
+ if isinstance(ip.data, dpkt.udp.UDP):
+ udp_seen = True
+
+ if udp_seen:
+ if isinstance(ip.data, (dpkt.icmp.ICMP, dpkt.icmp6.ICMP6)):
+ raise DeckardUnderLoadError("Deckard is under load. "
+ "Other errors might be false negatives. "
+ "Consider retrying the job later.")
+ return False
+
+
+def check_for_reply_steps(case: scenario.Scenario) -> bool:
+ return any(s.type == "REPLY" for s in case.steps)
+
+
+def check_for_unknown_servers(case: scenario.Scenario, daemon: dict) -> None:
+ """ Checks Deckards's PCAP for packets going to servers not present in scenario """
+ path = os.path.join(daemon["cfg"]["dir"], "pcap")
+ asked_servers = set()
+ with open(path, "rb") as f:
+ pcap = dpkt.pcap.Reader(f)
+ for _, packet in pcap:
+ try:
+ ip = dpkt.ip.IP(packet)
+ except dpkt.dpkt.UnpackError:
+ ip = dpkt.ip6.IP6(packet)
+ # pylint: disable=no-member
+ dest = ipaddress.ip_address(int.from_bytes(ip.dst, byteorder="big"))
+ # pylint: enable=no-member
+
+ # Socket wrapper asigns (random) link local addresses to the binary under test
+ # and Deckard itself. We have to filter them out of the pcap.
+ if dest.is_global:
+ asked_servers.add(dest)
+
+ scenario_ips = set() # type: Set[str]
+ for r in case.ranges:
+ scenario_ips |= r.addresses
+
+ scenario_servers = {ipaddress.ip_address(ip) for ip in scenario_ips}
+
+ servers_not_in_scenario = asked_servers - scenario_servers
+
+ if servers_not_in_scenario:
+ if not check_for_reply_steps(case):
+ raise RuntimeError("Binary in test asked an IP address not present in scenario %s"
+ % servers_not_in_scenario)
+
+
+def run_testcase(daemons, case, root_addr, addr_family, prog_under_test_ip):
+ """Run actual test and raise exception if the test failed"""
+ server = testserver.TestServer(case, root_addr, addr_family)
+ server.start()
+
+ try:
+ server.play(prog_under_test_ip)
+ except ValueError as e:
+ if not check_for_icmp():
+ raise e
+ finally:
+ server.stop()
+
+ if check_for_reply_steps(case):
+ logging.warning("%s has REPLY steps in it. These are known to fail randomly. "
+ "Errors might be false positives.", case.file)
+
+ for daemon in daemons:
+ daemon['proc'].terminate()
+ daemon['proc'].wait()
+ daemon_logger_log = logging.getLogger('deckard.daemon_log.%s' % daemon['cfg']['name'])
+ with open(daemon['cfg']['log']) as logf:
+ for line in logf:
+ daemon_logger_log.debug(line.strip())
+ ignore_exit = daemon["cfg"].get('ignore_exit_code', False)
+ if daemon['proc'].returncode != 0 and not ignore_exit:
+ raise ValueError('process %s terminated with return code %s'
+ % (daemon['cfg']['name'], daemon['proc'].returncode))
+ check_for_unknown_servers(case, daemon)
+
+ # Do not clear files if the server crashed (for analysis)
+ if server.undefined_answers > 0:
+ if not check_for_icmp():
+ raise ValueError('the scenario does not define all necessary answers (see error log)')
diff --git a/tests/deckard/deckard_pytest.ini b/tests/deckard/deckard_pytest.ini
new file mode 100644
index 0000000..df9378d
--- /dev/null
+++ b/tests/deckard/deckard_pytest.ini
@@ -0,0 +1,7 @@
+[pytest]
+log_print = true
+python_files=deckard_pytest.py
+norecursedirs=*
+log_cli=true
+log_level=WARNING
+
diff --git a/tests/deckard/deckard_pytest.py b/tests/deckard/deckard_pytest.py
new file mode 100755
index 0000000..3c5f4b8
--- /dev/null
+++ b/tests/deckard/deckard_pytest.py
@@ -0,0 +1,67 @@
+import logging
+import os
+import subprocess
+import random
+import sys
+import time
+
+import pytest
+
+import deckard
+
+
+def set_coverage_env(path, qmin):
+ """Sets up enviroment variables so code coverage utility can work."""
+ if os.environ.get("COVERAGE"):
+ exports = subprocess.check_output([os.environ["COVERAGE_ENV_SCRIPT"],
+ os.environ["DAEMONSRCDIR"],
+ os.environ["COVERAGE_STATSDIR"],
+ path + "-qmin-" + str(qmin)]).decode()
+ for export in exports.split():
+ key, value = export.split("=", 1)
+ value = value.strip('"')
+ os.environ[key] = value
+
+
+def check_platform():
+ if sys.platform == 'windows':
+ pytest.exit('Not supported at all on Windows')
+
+
+# Suppress extensive Augeas logging
+logging.getLogger("augeas").setLevel(logging.ERROR)
+
+
+check_platform()
+
+
+def run_test(path, qmin, config, max_retries, retries=0):
+ set_coverage_env(path, qmin)
+ try:
+ del os.environ["SOCKET_WRAPPER_DIR"]
+ except KeyError:
+ pass
+ try:
+ deckard.process_file(path, qmin, config)
+ except deckard.DeckardUnderLoadError as e:
+ if retries < max_retries:
+ logging.error("Deckard under load. Retrying…")
+ # Exponential backoff
+ time.sleep((2 ** retries) + random.random())
+ run_test(path, qmin, config, max_retries, retries + 1)
+ else:
+ raise e
+
+
+def test_passes_qmin_on(scenario, max_retries):
+ if scenario.qmin is True or scenario.qmin is None:
+ run_test(scenario.path, True, scenario.config, max_retries)
+ else:
+ pytest.skip("Query minimization is off in test config")
+
+
+def test_passes_qmin_off(scenario, max_retries):
+ if scenario.qmin is False or scenario.qmin is None:
+ run_test(scenario.path, False, scenario.config, max_retries)
+ else:
+ pytest.skip("Query minimization is on in test config")
diff --git a/tests/deckard/doc/devel_guide.rst b/tests/deckard/doc/devel_guide.rst
new file mode 100644
index 0000000..a93b79d
--- /dev/null
+++ b/tests/deckard/doc/devel_guide.rst
@@ -0,0 +1,25 @@
+Notes for Deckard developers
+============================
+
+socket wrapper library (cwrap)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Detailed instructions on using cwrap you can be found here_
+
+cwrap environment is managed by Deckard. Default values are sufficient, do not touch the environment unless you are trying to debug something. Variables available for direct use are:
+
+- ``SOCKET_WRAPPER_DIR`` is a generic working directory. It defaults
+ to a new temporary directory with randomly generated name,
+ prefixed by ``tmpdeckard``. When a test fails, the work directory can contain useful
+ information for post-mortem analysis. You can explicitly set ``SOCKET_WRAPPER_DIR``
+ to a custom path for more convenient analysis.
+- ``SOCKET_WRAPPER_DEBUGLEVEL`` is not set by default.
+
+Deckard automatically sets ``SOCKET_WRAPPER_PCAP_FILE`` to create separate PCAP files in working directory for Deckard itself and each daemon. Feel free to inspect them.
+
+.. _here: https://git.samba.org/?p=socket_wrapper.git;a=blob;f=doc/socket_wrapper.1.txt;hb=HEAD
+
+
+libfaketime
+^^^^^^^^^^^
+Run-time changes to ``FAKETIME_`` environment variables might not be picked up by running process if ``FAKETIME_NO_CACHE=1`` variable is not set before the process starts.
diff --git a/tests/deckard/doc/scenario_example.rst b/tests/deckard/doc/scenario_example.rst
new file mode 100644
index 0000000..7fb6f3e
--- /dev/null
+++ b/tests/deckard/doc/scenario_example.rst
@@ -0,0 +1,337 @@
+Scenario example
+=================
+iter_ns_badaa.rpl
+::
+
+ ; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ CONFIG_END
+
+ SCENARIO_BEGIN Test iterator with NS falsely declaring referral answer as authoritative.
+
+ ; K.ROOT-SERVERS.NET.
+ RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ . IN NS
+ SECTION ANSWER
+ . IN NS K.ROOT-SERVERS.NET.
+ SECTION ADDITIONAL
+ K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ ; False declaration here
+ REPLY QR AA NOERROR
+ SECTION QUESTION
+ MORECOWBELL. IN A
+ SECTION AUTHORITY
+ MORECOWBELL. IN NS a.gtld-servers.net.
+ SECTION ADDITIONAL
+ a.gtld-servers.net. IN A 192.5.6.30
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR NOERROR
+ SECTION QUESTION
+ a.gtld-servers.net. IN A
+ SECTION ANSWER
+ a.gtld-servers.net. IN A 192.5.6.30
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR NOERROR
+ SECTION QUESTION
+ a.gtld-servers.net. IN AAAA
+ SECTION AUTHORITY
+ . SOA bla bla 1 2 3 4 5
+ ENTRY_END
+
+ RANGE_END
+
+ ; a.gtld-servers.net.
+ RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA NOERROR
+ SECTION QUESTION
+ CATALYST.MORECOWBELL. IN A
+ SECTION ANSWER
+ CATALYST.MORECOWBELL. IN A 10.20.30.40
+ SECTION AUTHORITY
+ CATALYST.MORECOWBELL. IN NS a.gtld-servers.net.
+ ENTRY_END
+
+ RANGE_END
+
+ STEP 1 QUERY
+ ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ catalyst.morecowbell. IN A
+ ENTRY_END
+
+ ; recursion happens here.
+ STEP 10 CHECK_ANSWER
+ ENTRY_BEGIN
+ MATCH all
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+ catalyst.morecowbell. IN A
+ SECTION ANSWER
+ catalyst.morecowbell. IN A 10.20.30.40
+ ENTRY_END
+
+ SCENARIO_END
+
+Execution flow :
+
+First, STEP 1 QUERY will be performed.
+
+Python sends query to Resolver
+::
+
+ id 31296
+ opcode QUERY
+ rcode NOERROR
+ flags RD
+ edns 1
+ eflags
+ payload 1280
+ ;QUESTION
+ catalyst.morecowbell. IN A
+ ;ANSWER
+ ;AUTHORITY
+ ;ADDITIONAL
+
+At this scenario stub-addr is set to 193.0.14.129, thus Resolver have been configured to use address
+193.0.14.129 as a root server. So it sends query to Python fake server which listen at address 193.0.14.129
+
+::
+
+ > [plan] plan 'catalyst.morecowbell.' type 'A'
+ [resl] => using root hints
+ [resl] => querying: '193.0.14.129' score: 10 zone cut: '.' m12n: 'CaTALYSt.MoReCoWBEll.' type: 'A'
+
+
+::
+
+ id 7367
+ opcode QUERY
+ rcode NOERROR
+ flags
+ edns 0
+ payload 1452
+ ;QUESTION
+ CaTALYSt.MoReCoWBEll. IN A
+ ;ANSWER
+ ;AUTHORITY
+ ;ADDITIONAL
+
+Python fake server starts range analyzing to make answer.
+Let's look at first range
+::
+
+ RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+
+STEP ID is equal 1, so it matches the condition n1 <= step id <= n2
+Next, ADDRESS field is equal to 193.0.14.129. Since query was directed
+specifically to 193.0.14.129, this range will be used.
+
+Next, Python walks through list of entries to choose eligible entry.
+First entry at this range requires comparison of "opcode qtype qname" field list.
+Since opcode is QUERY, first comparison is true.
+Next, qtype field at question section is equal NS.
+But qtype field at question section of incoming query is A.
+So this comparison failed and this entry will be rejected.
+
+Next entry requires comparison of opcode and subdomain fields.
+As we seen, opcode matches.
+Let's look at domain names.
+ENTRY datablock:
+::
+
+ SECTION QUESTION
+ MORECOWBELL. IN A
+
+Incoming query :
+::
+
+ ;QUESTION
+ CaTALYSt.MoReCoWBEll. IN A
+
+So, subdomain matches and second entry of first range used as answer pattern.
+Python fake server sends answer to Resolver :
+::
+
+ id 7367
+ opcode QUERY
+ rcode NOERROR
+ flags QR AA
+ edns 0
+ payload 1280
+ ;QUESTION
+ CaTALYSt.MoReCoWBEll. IN A
+ ;ANSWER
+ ;AUTHORITY
+ MORECOWBELL. 3600 IN NS a.gtld-servers.net.
+ ;ADDITIONAL
+ a.gtld-servers.net. 3600 IN A 192.5.6.30
+
+Note that additional section contains IP address. Because new address is found,
+Python fake server immediately starts listening on this address.
+Resolver sends next query to 192.5.6.30:
+
+::
+
+ [iter] <= referral response, follow
+ [ pc ] => answer cached for TTL=900
+ [resl] => querying: '192.5.6.30' score: 10 zone cut: 'morecowbell.' m12n: 'catalyst.mOREcoWBEll.' type: 'A'
+
+
+::
+
+ id 58167
+ opcode QUERY
+ rcode NOERROR
+ flags
+ edns 0
+ payload 1452
+ ;QUESTION
+ catalyst.mOREcoWBEll. IN A
+ ;ANSWER
+ ;AUTHORITY
+ ;ADDITIONAL
+
+Since query is directed to 192.5.6.30,
+this range will be analyzed :
+::
+
+ ; a.gtld-servers.net.
+ RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+It has a single entry, which requires "opcode qtype qname" field list to be compared.
+Opcode and qtype fields are the same as fields in incoming query.
+Let's compare qname.
+ENTRY datablock :
+::
+
+ SECTION QUESTION
+ CATALYST.MORECOWBELL. IN A
+
+Incoming query :
+::
+
+ ;QUESTION
+ catalyst.mOREcoWBEll. IN A
+
+So, qname also the same. All fields matches and Python server sends answer
+derived from this entry :
+::
+
+ id 58167
+ opcode QUERY
+ rcode NOERROR
+ flags QR AA
+ edns 0
+ payload 1280
+ ;QUESTION
+ cAtaLyst.MoRECowBEll. IN A
+ ;ANSWER
+ CATALYST.MORECOWBELL. 3600 IN A 10.20.30.40
+ ;AUTHORITY
+ CATALYST.MORECOWBELL. 3600 IN NS a.gtld-servers.net.
+ ;ADDITIONAL
+
+Here Python found new address 10.20.30.40 and starts listening.
+Next queries and answers :
+
+::
+
+ [iter] <= referral response, follow
+ [plan] plan 'a.gtld-servers.net.' type 'AAAA'
+ [resl] => using root hints
+ [resl] => querying: '193.0.14.129' score: 54 zone cut: '.' m12n: 'A.Gtld-sERverS.nEt.' type: 'AAAA'
+
+
+query; Resolver ---> Python (193.0.14.129)
+::
+
+ id 13810
+ opcode QUERY
+ rcode NOERROR
+ flags
+ edns 0
+ payload 1452
+ ;QUESTION
+ A.Gtld-sERverS.nEt. IN AAAA
+ ;ANSWER
+ ;AUTHORITY
+ ;ADDITIONAL
+
+answer; Python ---> Resolver
+::
+
+ id 13810
+ opcode QUERY
+ rcode NOERROR
+ flags QR
+ edns 0
+ payload 1280
+ ;QUESTION
+ A.gTld-serveRS.NET. IN AAAA
+ ;ANSWER
+ ;AUTHORITY
+ . 3600 IN SOA bla. bla. 1 2 3 4 5
+ ;ADDITIONAL
+
+
+at this point Resolver returns answer to query from STEP 1 QUERY.
+
+::
+
+ [iter] <= rcode: NOERROR
+ [ pc ] => answer cached for TTL=900
+ [ rc ] => satisfied from cache
+ [iter] <= rcode: NOERROR
+ [resl] finished: 4, queries: 2, mempool: 16400 B
+
+
+::
+
+ opcode QUERY
+ rcode NOERROR
+ flags QR RD RA
+ edns 0
+ payload 4096
+ ;QUESTION
+ catalyst.morecowbell. IN A
+ ;ANSWER
+ catalyst.morecowbell. 3600 IN A 10.20.30.40
+ ;AUTHORITY
+ ;ADDITIONAL
+
+Now STEP 10 will be performed. Is has a single entry which contains
+**MATCH all** clause. **MATCH all** means set of dns flags must be equal and
+all sections presented in ENTRY must be equal to ones in answer.
+Incoming answer has next flags were set: **QR RD AA**. ENTRY datablock contains
+**REPLY QR RD RA NOERROR** clause. As we see, flags set is equal. Also, we can
+see equality of question and answer sections of both dns messages.
+
+So, Python got expected answer and test is passed.
+
diff --git a/tests/deckard/doc/scenario_guide.rst b/tests/deckard/doc/scenario_guide.rst
new file mode 100644
index 0000000..e588968
--- /dev/null
+++ b/tests/deckard/doc/scenario_guide.rst
@@ -0,0 +1,431 @@
+Deckard scenario guide
+======================
+.. contents::
+
+On the highest level, Deckard scenario consists of three parts (in this order):
+
+- scenario-specific configuration in the header,
+- declarative description of the simulated network environment,
+- sequence of test steps.
+
+The scenario is stored as ASCII encoded text file with following structure:
+
+.. code-block::
+
+ ; configuration part starts on beginning of the file
+ ; comments start with semicolon
+ CONFIG_END
+
+ SCENARIO_BEGIN ; SCENARIO block combines declarative description and sequence of steps
+
+
+ ; declarative description of network environment starts here
+ RANGE_BEGIN a b
+ ENTRY_BEGIN
+ ; entries inside RANGE block describe DNS messages
+ ; used as answers from simulated network
+ ENTRY_END
+ RANGE_END
+
+
+ ; sequence of test steps begins here
+ STEP x QUERY ; this is step number x
+ ENTRY_BEGIN
+ ; ENTRY inside STEP may describe DNS message sent as query
+ ENTRY_END
+
+ STEP y CHECK_ANSWER ; arbitrary number of steps is allowed
+ ENTRY_BEGIN
+ ; also, ENTRY inside STEP may describe DNS message with expected answer
+ ENTRY_END
+ SCENARIO_END
+
+The scenario is processed as follows:
+
+- Deckard parses configuration block and generates configuration files for binaries under test
+- binaries are executed in an isolated network environment
+- Deckard walks through all ``STEP`` blocks and sends queries to the binary under test, and checks answers it receives
+- when a binary attempts to contact another server, Deckard intercepts the communication and replies with scripted answer as defined in ``RANGE`` blocks
+
+To better understand this structure, we will walk-through from sequential steps through declarative description up to scenario-specific configuration.
+
+Scenario
+--------
+Scenario part starts with ``SCENARIO_BEGIN`` and ends with ``SCENARIO_END`` statements, which are present after ``CONFIG_END`` keyword. ``SCENARIO_BEGIN`` keyword must be followed by scenario description:
+
+.. code-block::
+
+ SCENARIO_BEGIN Test basic query minimization www.example.com.
+ ...
+ SCENARIO_END
+
+
+
+Test steps (``STEP``)
+---------------------
+One ``STEP`` describes one action during scenario execution. It might be action like send next query to binary under test, send reply to binary under test, change faked system time, or check the last answer. Sequence of two steps might look like this:
+
+.. code-block::
+
+ STEP 1 QUERY ; send query specified in the following ENTRY to the binary
+ ENTRY_BEGIN ; ENTRY defines content of DNS message
+ REPLY RD
+ SECTION QUESTION
+ www.example.com. IN A
+ ENTRY_END
+
+ STEP 10 CHECK_ANSWER ; check that answer to the previous query matches following ENTRY
+ ENTRY_BEGIN
+ MATCH all ; MATCH specifies what fields in answer have to match the ENTRY
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. IN CNAME www.next.com.
+ www.next.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+ SECTION ADDITIONAL
+ ENTRY_END
+
+
+Most important parts of a step are:
+
+- id - number specifying order in which steps are executed, e.g. ``1`` or ``10``
+- type - action to execute, e.g. ``QUERY`` or ``CHECK_ANSWER``
+- entry - DNS message content, while meaning of the message depends on the step *type*
+
+One ``STEP`` block starts with ``STEP`` keyword and continues until one of {``STEP``,
+``RANGE``, ``END_SCENARIO``} keywords is found.
+
+Format
+^^^^^^
+
+.. code-block::
+
+ STEP id type [additional data]
+
+- id - step identifier, a positive integer value; all steps must have
+ different id's. This value used within RANGE block, see above.
+- type - step type; can be ``QUERY`` | ``REPLY`` | ``CHECK_ANSWER`` | ``TIME_PASSES ELAPSE`` *seconds*
+
+ - QUERY - send query defined by associated ``ENTRY`` to binary under test
+ - CHECK_ANSWER - check if last received answer matches associated ``ENTRY``
+ - TIME_PASSES ELAPSE - move faked system time for binary under test by number of *seconds* to future
+ - REPLY - *use of this type is discouraged*; it defines one-shot reply to query from binary under test
+
+.. warning::
+ - ``REPLY`` type is useful only if you know exact order of queries sent *by the binary under test*
+ - steps of this type are used only when no matching ``RANGE`` datablock exists
+ - priority of ``REPLY`` type is going to change in future
+
+
+.. _entry:
+
+DNS messages (normal ``ENTRY``)
+-------------------------------
+One ``ENTRY`` describes one DNS message plus additional metadata, depending on intended use of the entry. There are three possible uses of entry which require little bit different entry format. An entry might define:
+
+#. *query message* to be sent in ``STEP QUERY``
+#. *expected message* to be compared with a message received from binary in ``STEP CHECK_ANSWER``
+#. *answer template message* to be used for simulating answers from network in ``RANGE`` block
+
+Particular use of data in an ``ENTRY`` depends on context and is different
+for ``STEP`` types and ``RANGE`` blocks, see details below.
+
+In any case, entry starts with ``ENTRY_BEGIN`` and ends with ``ENTRY_END`` keywords and share ``REPLY`` and ``SECTION`` definitions.
+Some fields in DNS messages have default values which can be overriden by explicit specification.
+
+Format of query messages (for ``STEP QUERY``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+``STEP QUERY`` requires a DNS message which will be sent by Deckard to the binary under test. Structure of the entry is:
+
+.. code-block::
+
+ STEP <n> QUERY
+ ENTRY_BEGIN
+ REPLY <OPCODE flags> ; REPLY is a bad keyword name, OPCODE and flags will be sent out!
+ SECTION QUESTION ; it is possible to replace QUESTION section or omit it
+ <name> <class> <type> ; to simulate weird queries
+ ENTRY_END
+
+The message will be assigned a random message ID, converted into DNS wire format, and sent to the binary under test.
+
+.. warning:: The keyword ``REPLY`` in fact defines value of flags in the outgoing message. The confusing name is here for compatibility with the original ``testbound``.
+
+
+Format of expected messages (for ``STEP CHECK_ANSWER``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+``STEP CHECK_ANSWER`` requires a DNS message which will be compared with a reply received from the binary under test. Structure of the entry describing the expected message is:
+
+.. code-block::
+
+ ENTRY_BEGIN
+ MATCH <match element list> ; MATCH elements define what message fields will be compared
+ REPLY <OPCODE RCODE flags> ; REPLY field here defines expected OPCODE, RCODE as well as flags!
+ SECTION QUESTION
+ <name> <class> <type> ; to simulate weird queries
+ SECTION <type2>
+ <RR sets>
+ ENTRY_END
+
+Deckard will compare messages according to *<match element list>*. Any mismatch between *received* message and the *expected* message (specified by the entry) will result in test failure. (See chapter `entry matching`_.)
+
+
+Format of answer templates (for ``RANGE``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Entries in ``RANGE`` blocks are used to answer queries *from binaries under test*. E.g. if a DNS resolver under test sends query ``. IN NS`` to a simulated server, Deckard will use matching entry associated with the simulated server for reply. Entry used for answer is selected using the same `entry matching`_ logic as with ``STEP CHECK_ANSWER``. The difference is that entry is automatically modified before sending out the answer. These modifications are specified by ``ADJUST`` and ``REPLY`` keywords. It's also possible to not send any reply using the ``ADJUST do_not_answer`` option. See chapters `entry adjusting`_ and `entry flags`_.
+
+.. code-block::
+
+ ENTRY_BEGIN
+ MATCH <match element list> ; all MATCH elements must match before using this answer template
+ ADJUST <adjust element list> ; ADJUST fields will be modified before answering
+ REPLY <OPCODE RCODE flags> ; OPCODE, RCODE, and flags to be set in the outgoing answer
+ SECTION <type1>
+ <RR sets>
+ SECTION <type2>
+ <RR sets>
+ ENTRY_END
+
+
+.. _`entry matching`:
+
+Entry matching
+^^^^^^^^^^^^^^
+Entries present in Deckard scenario define values *expected* in DNS messages. The *expected* values are compared with values in messages *received* from the network. Entry matches only if all specified elements match.
+
+.. code-block::
+
+ MATCH <match element list>
+
+*<match element list>* is a space-separated list of elements in *expected* and *received* messages to be compared. Supported elements are:
+
+============ =========================================================================================
+element DNS message fields and additional rules
+============ =========================================================================================
+opcode ``OPCODE`` as `defined in IANA registry <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5>`_
+
+ - *expected* message ``OPCODE`` is defined by ``REPLY`` keyword
+
+qtype RR type in question section [qmatch]_
+qname name in question section (case insensitive) [qmatch]_
+qcase name in question section (case sensitive) [qmatch]_
+subdomain name in question section of the *received* message is a subdomain of the name in *expected* question section
+ (case insensitive, exact match accepted) [qmatch]_
+flags all `defined flags <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-12>`_
+ in message header: ``QR AA TC RD RA AD CD``
+
+ - it does not match on ``DO`` flag which resides in EDNS header flags
+ - *expected* message flags are defined by ``REPLY`` keyword
+
+rcode extended response code (``RCODE`` value
+ `combined from message header and EDNS header <https://tools.ietf.org/html/rfc6891#section-6.1.3>`_)
+
+ - *expected* message ``RCODE`` is defined by ``REPLY`` keyword
+
+question equivalent to ``qtype qname``
+answer whole ANSWER section [sectmatch]_
+authority whole AUTHORITY section [sectmatch]_
+additional whole ADDITIONAL section [sectmatch]_
+edns EDNS `version <https://tools.ietf.org/html/rfc6891#section-6.1.3>`_ and
+ EDNS `payload <https://tools.ietf.org/html/rfc6891#section-6.1.2>`_ size
+nsid `NSID <https://tools.ietf.org/html/rfc5001>`_ presence and value
+all equivalent to ``opcode qtype qname flags rcode answer authority additional``
+============ =========================================================================================
+
+.. [qmatch] *Expected* values are defined by QUESTION section in the entry. If the *expected* QUESTION section is empty, the conditions is ignored. Only values from the first (qname, qclass, qtype) tuple are checked. Question matching is case insensitive (except for ``qcase``).
+
+.. [sectmatch] Number of records must match. Owner names are case-insensitive and TTL is ignored. RR data are compared according to type-specific rules. Each RR present in the *expected* message must be present in the *received* message and vice versa.
+
+
+.. _`entry adjusting`:
+
+Entry adjusting
+^^^^^^^^^^^^^^^
+.. code-block::
+
+ ADJUST <adjust element list>
+
+An entry used as a template to prepare an answer to an incoming query might be preprocessed.
+Adjust element list defines what fields will be modified:
+
+============= ===========================================================================================
+element modification to the DNS message
+============= ===========================================================================================
+copy_id query id + query domain name will be copied from incoming message [copy_id_bug]_
+copy_query whole question section will be copied from incoming message
+raw_id query id will be copied into the first two bytes of RAW answer
+do_not_answer no response will be sent at all
+============= ===========================================================================================
+
+.. [copy_id_bug] https://gitlab.labs.nic.cz/knot/deckard/issues/9
+
+
+.. _`entry flags`:
+
+Entry flags
+^^^^^^^^^^^
+.. code-block::
+
+ REPLY <RCODE flags>
+
+*<RCODE flags>* is space-separated RCODE and list of flags in the entry. Usage of these flags depend on entry context.
+
+Supported values:
+
+ - NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMP, REFUSED, YXDOMAIN, YXRRSET, NXRRSET, NOTAUTH, NOTZONE, BADVERS - standard rcodes
+ - QR, AA, TC, RD, RA, AD, CD - i.e. standard dns flags
+ - DO - enable 'DNSSEC desired' flag
+
+.. warning:: The keyword ``REPLY`` has different meaning depending on the ``ENTRY`` context.
+
+
+Entry RR sections
+^^^^^^^^^^^^^^^^^
+An entry might specify content of DNS message sections QUESTION, ANSWER, AUTHORITY, and ADDITIONAL. Syntax is of resource records is the same as in zone file. Format:
+
+.. code-block::
+
+ SECTION QUESTION
+ <owner name> [class] <RR type> ; QUESTION is special
+ SECTION <ANSWER/AUTHORITY/ADDITIONAL>
+ <owner name> [TTL] [class] <RR type> <RR data> ; same as in zone file
+ ...
+ <owner name> [TTL] [class] <RR type> <RR data>
+
+Example:
+
+.. code-block::
+
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. IN A 10.20.30.40
+ SECTION AUTHORITY
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 1.2.3.4
+
+
+Default values for DNS messages
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+========== ===========================================================================================
+feature default value
+========== ===========================================================================================
+EDNS version 0 with buffer size 4096 B
+REPLY QUERY, NOERROR
+========== ===========================================================================================
+
+
+Entry with RAW data
+^^^^^^^^^^^^^^^^^^^
+An entry might have special section named ``RAW``. This section is used only for sending raw,
+potentially invalid DNS messages. The section contains a single-line data interpreted as hexadecimal string.
+Data decoded from this string will be sent to binary under test without any changes.
+
+Deckard does not expect any answer to RAW queries, so ``STEP CHECK_ANSWER`` is not needed.
+Main intent of this behavior is to check if binary under test is
+able to process valid queries after getting series badly formed packets.
+
+It is also possible to use ``RAW`` in conjuction with ``SECTION`` for the
+purpose of responding with raw data to a query that matches the ``SECTION``.
+It's possible to modify raw data to use query's ID by using ``ADJUST raw_id``.
+
+One ``ENTRY`` can contain only one ``RAW`` section.
+
+Example
+
+.. code-block::
+
+ ENTRY_BEGIN
+ RAW
+ b5c9ca3d50104320f4120000000000000000
+ ENTRY_END
+
+
+
+Mock answers (``RANGE``)
+------------------------
+When Deckard receives a query *from binary under test*, it searches for mock answers.
+A set of mock answers for particular set of IP addresses and ID range is described using ``RANGE``
+block starting with ``RANGE_BEGIN`` keyword. The ``RANGE`` contains mock DNS messages represented
+as ENTRY_ blocks which specify `entry matching`_ conditions along with `entry adjusting`_ actions and `entry flags`_ specification.
+
+Format:
+
+.. code-block::
+
+ ; comment before the range, e.g. K.ROOT-SERVERS.NET.
+ RANGE_BEGIN 0 100 ; this RANGE is valid for STEP IDs <0, 100>
+ ADDRESS 193.0.14.129 ; IP address simulated by this range
+ ;ADDRESS 192.0.2.222 ; multiple IP addresses are allowed
+
+ ENTRY_BEGIN ; first ENTRY in this range
+ MATCH opcode qtype qname ; use this entry only if all these match the query
+ ADJUST copy_id ; adjust message ID before senting the answer
+ REPLY QR NOERROR ; answer with RCODE NOERROR and QR flag set
+ SECTION QUESTION
+ . IN NS ; MATCH qname qtype are compared with this value
+ SECTION ANSWER ; all this will be copied verbatim to the answer
+ . IN NS K.ROOT-SERVERS.NET.
+ SECTION ADDITIONAL
+ K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ ENTRY_END
+
+ ENTRY_BEGIN ; second ENTRY in this range
+ ...
+ ENTRY_END
+
+ RANGE_END
+
+When Deckard receives a query *from binary under test*, it searches for an eligible range. When an eligible range is found, it searches inside the range to find a mock answer. In detail, it works like this:
+
+#. Deckard searches for an eligible ``RANGE`` block. Following two conditions must be fulfilled:
+
+ - current ``STEP ID`` is inside ID range specified by ``RANGE_BEGIN`` keyword.
+ - target IP address of the query is in set of IP addresses specified using ``ADDRESS`` keywords
+
+#. If an eligible range is found, Deckard examines all entries in the range and evaluate all ``MATCH`` conditions associated with entries.
+#. An entry where all MATCH conditions are fulfilled is used as template for the mock answer. (See `entry matching`_.)
+#. Mock answer is modified according to ``ADJUST`` and ``REPLY`` keywords. (See `entry adjusting`_ actions and `entry flags`_ specification.)
+#. The modified answer message is sent to the binary under test.
+
+Valid scenario must specify answers for all queries generated by the binary under test. The test will fail if no answer is found in the eligible range or if no eligible range is defined.
+
+.. note:: Behavior of the binary under test, including queries it generates, depends on its configuration. For example enabling or disabling query name minimization will change minimal set of queries which a test scenario has to describe using ``RANGE`` blocks.
+
+.. tip:: It is recommended to construct scenarios that support multiple configurations and possibly software implementations. This leads to higher number of entries in ``RANGE`` blocks but provides robustness against changes in particular implementation. E.g. a scenario for DNS resolver testing can be developed using multiple DNS resolver implementations and combine entries for all of them inside single scenario. With this approach a small change in a resolver implementation will likely not require further changes to the scenario.
+
+
+Configuration (``CONFIG_END``)
+------------------------------
+Configuration block affects behavior of the binary under test. Deckard transforms configuration block into configuration for the binary under test.
+
+Format is list of "key: value" pairs, one pair per line. There is no explicit start keyword, configuration block starts immediately at scenario file begin and ends with keyword ``CONFIG_END``.
+
+.. code-block::
+
+ ; config options
+ query-minimization: on
+ stub-addr: 193.0.14.129 ; K.ROOT-SERVERS.NET.
+ trust-anchor: ". 3600 IN DS 10000 13 4 ABCDEF0123456789"
+ val-override-date: "1442323400"
+ CONFIG_END
+
+========================== ======= =====================================================================
+config option default meaning
+========================== ======= =====================================================================
+do-not-query-localhost on on = queries cannot be sent to 127.0.0.1/8 or ::1/128 addresses
+domain-insecure (none) domain name specifying DNS sub-tree with explicitly disabled DNSSEC validation
+force-ipv6 off use a IPv6 address as ``stub-addr``
+harden-glue on additional checks on glue addresses
+query-minimization on RFC 7816 query algorithm enabled; default inherited from QMIN environment variable
+stub-addr (none) IP address for resolver priming queries (RFC 8109)
+trust-anchor (none) owner name with its DS records (this option can be repeated multiple times)
+val-override-date (none) system time reported to binary under the test; format ``YYYYMMDDHHMMSS``, so ``20120420235959`` means ``Fri Apr 20 23:59:59 2012``
+val-override-timestamp (none) system time reported to binary under the test: format POSIX timestamp
+========================== ======= =====================================================================
+
+Examples
+--------
+See `scenatio example <scenario_example.rst>`_. The example there is a bit terse but still valid.
diff --git a/tests/deckard/doc/user_guide.rst b/tests/deckard/doc/user_guide.rst
new file mode 100644
index 0000000..b6e379f
--- /dev/null
+++ b/tests/deckard/doc/user_guide.rst
@@ -0,0 +1,297 @@
+.. sectnum::
+
+How to use Deckard
+==================
+.. contents::
+
+Deckard runs one or more binaries in isolated network which is described by so-called *scenario*.
+There are four components in play:
+
+- Deckard itself (test orchestrator)
+- binary under test (your own)
+- configuration for the binary (generated by Deckard from *template* and *YaML configuration*, i.e. ``.j2`` and ``.yaml`` files)
+- environment description and test data (Deckard *scenario*, i.e. ``.rpl`` file)
+
+It is easy to run tests if everything is already prepared and running tests gets harder
+as number of components you have to prepare yourself raises.
+
+Let's start with the easiest case:
+
+First run
+---------
+Easiest way to run Deckard is using one of the prepared Shell scripts in Deckard repository (``{kresd,unbound,pdns}_run.sh`` for Knot Resolver, Unbound and PowerDNS Recursor respectively).
+
+Please note that Deckard depends on a couple of modified C libraries.
+These will be automatically downloaded and compiled on first run, so do not be surprised when you see
+output from Git and C compiler:
+
+.. code-block::
+
+ $ ./kresd_run.sh
+ Submodule 'contrib/libfaketime' (https://github.com/wolfcw/libfaketime.git) registered for path 'contrib/libfaketime'
+ Submodule 'contrib/libswrap' (https://gitlab.labs.nic.cz/labs/socket_wrapper.git) registered for path 'contrib/libswrap'
+ [...]
+ -- The C compiler identification is GNU 6.3.1
+ [...]
+ [ 50%] Building C object src/CMakeFiles/socket_wrapper.dir/socket_wrapper.c.o
+ [...]
+ [100%] Built target socket_wrapper
+ …
+
+For details see `README <../README.rst>`_.
+
+Deckard uses `pytest` to generate and run the tests as well as collect the results.
+Output is therefore generated by `pytest` as well (``.`` for passed test, ``F`` for failed test and ``s`` for skipped test) and will look something like this:
+
+.. code-block::
+
+ $ ./kresd_run.sh
+ ........s...s...s....................ssss...s.ss.............ssss..s..ss [ 24%]
+ ssss.....sssssssssssssss.sssss.......ssssss.ss...s..s.ss.sss.s.s........ [ 49%]
+ .............ssss....................................................... [ 73%]
+ ........................................................................ [ 98%]
+ .... [100%]
+ 229 passed, 62 skipped in 76.50 seconds
+
+.. note:: There is a lot of tests skipped because we run them with query minimization both on and off and some of the scenarios work only with query minimization on (or off respectively). For details see `Scenario guide#Configuration <scenario_guide.rst#configuration-config-end>`_.
+
+ Time elapsed which is printed by `py.test` is often not acurate (or even negative). `py.test` is confused about our time shifting shenanigans done with ``libfaketime``. We can overcome this by using ``-n`` command line argument. See below.
+
+
+Command line arguments
+----------------------
+As mentioned above we use `py.test` to run the tests so all possible command line arguments for the ``*run.sh`` scripts can be seen by running ``py.test -h`` in the root of Deckard repository.
+
+Here is a list of the most useful ones:
+
+- ``-n number`` – runs the testing in parallel with ``number`` of processes (this requires `pytest-xdist` to be installed)
+- ``-k EXPRESSION`` – only run tests which match the given substring expression (e.g. ``./kresd_run -k "world_"`` will only run the scenarios with `world_` in their file name.
+- ``--collectonly`` – only print the names of selected tests, no tests will be run
+- ``--log-level DEBUG`` – print all debug information for failed tests
+- ``--scenarios path`` – specifies where to look for `.rpl` files (``sets/resolver`` is the default)
+
+YaML configuration
+------------------
+All ``*_run.sh`` scripts internally call the ``run.sh`` script and pass command line arguments to it. For example:
+
+.. code-block::
+
+ # running ./kresd_run.sh -n 4 -k "iter_" will result in running
+ ./run.sh --config configs/kresd.yaml -n 4 -k "iter_"
+
+As you can see, path to YaML configuration file is passed to ``run.sh``. You can edit one of the prepared ones stored in `configs/` or write your own.
+
+Commented contents of ``kresd.yaml`` follows:
+
+.. code-block:: yaml
+
+ programs:
+ - name: kresd # path to binary under test
+ binary: kresd
+ additional: # list additional parameters for binary under test (e.g. path to configuration files)
+ - -f
+ - "1" # CAUTION: All parameters must be strings.
+ templates:
+ - template/kresd.j2 # list of Jinja2_ template files to generate configuration files
+ configs:
+ - config # list of names of configuration files to be generated from Jinja2_ templates
+ noclean: True # optional, do not remove working dir after a successful test
+
+- 'configs' files will be generated from respective files in 'templates' list
+- i.e. the first file in 'configs' list is the result of processing of the first file from 'templates' list and so on
+- generated files are stored in a new working directory created by Deckard for each binary
+
+Most often it is sufficient to use these files for basic configuration changes. Read next section for details about config file templates.
+
+Running multiple binaries
+^^^^^^^^^^^^^^^^^^^^^^^^^
+You can specify multiple programs to run in the YaML configuration. Deckard executes all binaries using parameters from the file. This is handy for testing interoperability of multiple binaries, e.g. when one program is configured as DNS recursor and other program is using it as forwarder.
+
+The YAML file contains **ordered** list of binaries and their parameters. Deckard will send queries to the binary listed first.
+
+.. code-block:: yaml
+
+ programs:
+ - name: forwarding # name of this Knot Resolver instance
+ binary: kresd # kresd is first so it will receive queries from Deckard
+ additional: []
+ templates:
+ - template/kresd_fwd.j2 # this template uses variable IPADDRS['recursor']
+ configs:
+ - config
+ - name: recursor # name of this Unbound instance
+ binary: unbound
+ additional:
+ - -d
+ - -c
+ - unbound.conf
+ templates:
+ - template/unbound.j2
+ - template/hints_zone.j2 # this template uses variable ROOT_ADDR
+ configs:
+ - unbound.conf
+ - hints.zone
+ - ta.keys
+
+In this setup it is necessary to configure one binary to contact the other. IP addresses assigned by Deckard at run-time are accessible using ``IPADDRS`` `template variables`_ and symbolic names assigned to binaries in the YAML file. For example, template ``kresd_fwd.j2`` can use IP address of binary named ``recursor`` like this:
+
+.. code-block:: lua
+
+ policy.add(policy.all(policy.FORWARD("{{IPADDRS['recursor']}}")))
+
+When all preparations are finished, run Deckard using following syntax:
+
+.. code-block:: bash
+
+ $ ./run.sh --config path/to/config.yaml
+
+.. note:: You can run multiple configs in one test instance. Just be aware that ``--scenarios`` must be provided for each config.
+
+.. code-block::
+
+ # This will run scenarios from `scenarios1` folder with configuration from `config1.yaml` and `scenarios2.yaml` with `config2.yaml` respectively.
+ $ ./run.sh --config path/to/config1.yaml --scenarios path/to/scenarios1 --config path/to/config2.yaml --scenarios path/to/scenarios2
+
+
+
+
+Using an existing scenarios with custom configuration template
+--------------------------------------------------------------
+
+It some cases it is necessary to modify or create new template files. Typically this is needed when:
+
+- there are no templates for particular binary (e.g. if you want to test a brand new program)
+- an existing template hardcodes some configuration and you want to change it
+
+Deckard uses the Jinja2_ templating engine (like Ansible or Salt) and supplies several variables that you can use in templates. For simplicity you can imagine that all occurrences of ``{{variable}}`` in template are replaced with value of the *variable*. See Jinja2_ documentation for further details.
+
+Here is an example of template for Unbound:
+
+.. code-block:: jinja
+
+ server:
+ directory: "" # do not leave current working directory
+ chroot: ""
+ pidfile: ""
+ username: ""
+
+ interface: {{SELF_ADDR}} # Deckard will assign an address
+ interface-automatic: no
+ access-control: ::0/0 allow # accept queries from Deckard
+
+ do-daemonize: no # log to stdout & stderr
+ use-syslog: no
+ verbosity: 3 # be verbose, it is handy for debugging
+ val-log-level: 2
+ log-queries: yes
+
+ {% if QMIN == "false" %} # Jinja2 condition
+ qname-minimisation: no # a constant inside condition
+ {% else %}
+ qname-minimisation: yes
+ {% endif %}
+ harden-glue: no # hardcoded constant, use a variable instead!
+
+ root-hints: "hints.zone" # reference to other files in working directory
+ trust-anchor-file: "ta.keys" # use separate template to generate these
+
+This configuration snippet refers to files ``hints.zone`` and ``ta.keys`` which need to be generated as well. Each file uses own template file. An template for ``hints.zone`` might look like this:
+
+.. code-block:: jinja
+
+ # this is hints file which directs resolver to query
+ # fake root server simulated by Deckard
+ . 3600000 NS K.ROOT-SERVERS.NET.
+ # IP address version depends on scenario setting, handle IPv4 & IPv6
+ {% if ':' in ROOT_ADDR %}
+ K.ROOT-SERVERS.NET. 3600000 AAAA {{ROOT_ADDR}}
+ {% else %}
+ K.ROOT-SERVERS.NET. 3600000 A {{ROOT_ADDR}}
+ {% endif %}
+
+Templates can use any of following variables:
+
+.. _`template variables`:
+
+List of variables for templates
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Addresses:
+
+- ``DAEMON_NAME`` - user-specified symbolic name of particular binary under test, e.g. ``recursor``
+- ``IPADDRS`` - dictionary with ``{symbolic name: IP address}`` mapping
+
+ - it is handy for cases where configuration for one binary under test has to refer to another binary under test
+
+- ``ROOT_ADDR`` - fake root server hint (Deckard is listening here; port is not expressed, must be 53)
+
+ - IP version depends on settings in particular scenario
+ - templates must handle IPv4 and IPv6 as well
+
+- ``SELF_ADDR`` - address assigned to the binary under test (port is not expressed, must be 53)
+
+Path variables:
+
+- ``INSTALL_DIR`` - path to directory containing file ``deckard.py``
+- ``WORKING_DIR`` - working directory for binary under test, each binary gets its own directory
+
+DNS specifics:
+
+- ``DO_NOT_QUERY_LOCALHOST`` [bool]_ - allows or disallows querying local addresses
+- ``HARDEN_GLUE`` [bool]_ - enables or disables additional checks on glue addresses
+- ``QMIN`` [bool]_ - enables or disables query minimization respectively
+- ``TRUST_ANCHORS`` - list of trust anchors in form of a DS records, see `scenario guide <doc/scenario_guide.rst>`_
+- ``NEGATIVE_TRUST_ANCHORS`` - list of domain names with explicitly disabled DNSSEC validation
+
+.. [bool] boolean expressed as string ``true``/``false``
+
+It's okay if you don't use all of the variables, but expect some tests to fail. E.g. if you don't set the ``TRUST_ANCHORS``,
+then the DNSSEC tests will not work properly.
+
+
+Debugging scenario execution
+----------------------------
+Output from a failed test looks like this:
+
+.. code-block::
+
+ $ ./kresd_run.sh
+ =========================================== FAILURES ===========================================
+ _____ test_passes_qmin_off[Scenario(path='sets/resolver/val_ta_sentinel.rpl', qmin=False)] _____
+ [...]
+ E ValueError: val_ta_sentinel.rpl step 212 char position 15875, "rcode": expected 'SERVFAIL',
+ E got 'NOERROR' in the response:
+ E id 54873
+ E opcode QUERY
+ E rcode NOERROR
+ E flags QR RD RA AD
+ E edns 0
+ E payload 4096
+ E ;QUESTION
+ E _is-ta-bd19.test. IN A
+ E ;ANSWER
+ E _is-ta-bd19.test. 5 IN A 192.0.2.1
+ E ;AUTHORITY
+ E ;ADDITIONAL
+
+ pydnstest/scenario.py:888: ValueError
+
+In this example, the test step ``212`` in scenario ``sets/resolver/val_ta_sentinel.rpl`` is failing with query-minimisation off. The binary under test did not produce expected answer, so either the test scenario or binary is wrong. If we were debugging this example, we would have to open file ``val_ta_sentinel.rpl`` on character postition ``15875`` and use our brains :-).
+
+Tips:
+
+- details about scenario format are in `the scenario guide <scenario_guide.rst>`_
+- network traffic from each binary is logged in PCAP format to a file in working directory
+- standard output and error from each binary is logged into log file in working directory
+- working directory can be explicitly specified in environment variable ``SOCKET_WRAPPER_DIR``
+- command line argument ``--log-level DEBUG`` forces extra verbose logging, including logs from all binaries and packets handled by Deckard
+
+
+Writting own scenarios
+----------------------
+See `the scenario guide <scenario_guide.rst>`_.
+
+
+
+
+
+.. _`Jinja2`: http://jinja.pocoo.org/
diff --git a/tests/deckard/getdns_run.sh b/tests/deckard/getdns_run.sh
new file mode 100755
index 0000000..2dc7313
--- /dev/null
+++ b/tests/deckard/getdns_run.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+# Below a summary of tests that failed including a reason for the failure.
+# It might be wise to move these out of the way before testing with getdns.
+# Or provide alternatives.
+#
+# Tests known to fail can be moved out of the way:
+#
+# mkdir sets/resolver.out-of-the-way; for t in `grep '^##' getdns_run.sh | sed 's/^## //g'` ; do mv sets/resolver/$t sets/resolver.out-of-the-way; done
+#
+#
+# OPT-OUT is INSECURE
+# ===================
+# These fail because getdns will give answers to proven opt-out NSEC3 spans
+# the INSECURE status, but will include the DNSSEC data still:
+#
+## val_nsec3_b1_nameerror.rpl val_nsec3_b4_wild.rpl val_nsec3_b5_wcnodata.rpl
+## val_nsec3_b5_wcnodata_nowc.rpl val_nsec3_noopt_ref.out
+#
+#
+# Dependent on specific unbound configuration
+# ===========================================
+# These fail because they set specific unbound options in the
+# "; config options" section. We might consider facilitating this in getdns
+# at some point.
+#
+## iter_cycle_noh.rpl iter_ns_spoof.rpl
+#
+#
+# Knot resolver specific behaviour
+# ================================
+# These fail because it tests specific behaviour which is not the only "right"
+# way to do it correct.
+#
+## iter_lame_nosoa.rpl
+#
+#
+# Modules
+# =======
+# These fail because it tests certain modules that getdns does not have (yet).
+#
+## module_dns64.rpl module_policy_pass_deny.rpl
+## module_hint_static.rpl module_policy_rpz.rpl
+## module_policy_deny_all.rpl module_policy_tc.rpl
+## module_policy_deny_suff_comm.rpl module_renumber.rpl
+## module_policy_deny_suff_patt.rpl module_view_addr.rpl
+## module_policy_forward.rpl module_view_tsig.rpl
+#
+#
+# To investigate
+# ==============
+# These tests don't work, but we need to investigate what's wrong.
+#
+## iter_cname_badauth.rpl iter_minim_nonempty.rpl
+## iter_escape_bailiwick.rpl iter_minim_ns.rpl
+## iter_formerr.rpl iter_validate_extradata.rpl
+## iter_lame_root.rpl iter_validate.rpl
+## iter_minim_a_nxdomain.rpl nsec3_wildcard_no_data_response.rpl
+## iter_minim_a.rpl val_nsec3_optout_unsec_cache.rpl
+
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/getdns.yaml "$@"
diff --git a/tests/deckard/knotd_master_run.sh b/tests/deckard/knotd_master_run.sh
new file mode 100755
index 0000000..9a61f3c
--- /dev/null
+++ b/tests/deckard/knotd_master_run.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+echo 'INFO: Tests require Knot compiled with ./configure --enable-recvmmsg=no'
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/knotd_master.yaml "$@"
diff --git a/tests/deckard/knotd_slave_run.sh b/tests/deckard/knotd_slave_run.sh
new file mode 100755
index 0000000..239cef1
--- /dev/null
+++ b/tests/deckard/knotd_slave_run.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+echo 'INFO: Tests require Knot compiled with ./configure --enable-recvmmsg=no'
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/knotd_slave.yaml "$@"
diff --git a/tests/deckard/kresd_run.sh b/tests/deckard/kresd_run.sh
new file mode 100755
index 0000000..5fd93e1
--- /dev/null
+++ b/tests/deckard/kresd_run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/kresd.yaml "$@"
diff --git a/tests/deckard/pdns_run.sh b/tests/deckard/pdns_run.sh
new file mode 100755
index 0000000..bb1900e
--- /dev/null
+++ b/tests/deckard/pdns_run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/pdns.yaml "$@"
diff --git a/tests/deckard/platform.mk b/tests/deckard/platform.mk
new file mode 100644
index 0000000..4a96c71
--- /dev/null
+++ b/tests/deckard/platform.mk
@@ -0,0 +1,27 @@
+# Evaluate library
+define have_lib
+ifeq ($$(strip $$($(1)_LIBS)),)
+ HAS_$(1) := no
+else
+ HAS_$(1) := yes
+endif
+endef
+
+# Find library (pkg-config)
+define find_lib
+ $(call find_alt,$(1),$(1),$(2))
+endef
+
+# Find library alternative (pkg-config)
+define find_alt
+ ifeq ($$(strip $$($(1)_LIBS)),)
+ ifneq ($(strip $(3)),)
+ $(1)_VER := $(shell pkg-config --atleast-version=$(3) $(2) && echo $(3))
+ endif
+ ifeq ($(strip $(3)),$$($(1)_VER))
+ $(1)_CFLAGS := $(shell pkg-config --cflags $(2) --silence-errors)
+ $(1)_LIBS := $(shell pkg-config --libs $(2) --silence-errors)
+ endif
+ endif
+ $(call have_lib,$(1),$(3))
+endef
diff --git a/tests/deckard/pydnstest/__init__.py b/tests/deckard/pydnstest/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/deckard/pydnstest/__init__.py
diff --git a/tests/deckard/pydnstest/augwrap.py b/tests/deckard/pydnstest/augwrap.py
new file mode 100644
index 0000000..20e7857
--- /dev/null
+++ b/tests/deckard/pydnstest/augwrap.py
@@ -0,0 +1,227 @@
+#!/usr/bin/python3
+
+# Copyright (C) 2017
+
+import posixpath
+import logging
+import os
+import collections
+
+from augeas import Augeas
+
+AUGEAS_LOAD_PATH = '/augeas/load/'
+AUGEAS_FILES_PATH = '/files/'
+AUGEAS_ERROR_PATH = '//error'
+
+log = logging.getLogger('augeas')
+
+
+def join(*paths):
+ """
+ join two Augeas tree paths
+
+ FIXME: Beware: // is normalized to /
+ """
+ norm_paths = [posixpath.normpath(path) for path in paths]
+ # first path must be absolute
+ assert norm_paths[0][0] == '/'
+ new_paths = [norm_paths[0]]
+ # relativize all other paths so join works as expected
+ for path in norm_paths[1:]:
+ if path.startswith('/'):
+ path = path[1:]
+ new_paths.append(path)
+ new_path = posixpath.join(*new_paths)
+ log.debug("join: new_path %s", new_path)
+ return posixpath.normpath(new_path)
+
+
+class AugeasWrapper:
+ """python-augeas higher-level wrapper.
+
+ Load single augeas lens and configuration file.
+ Exposes configuration file as AugeasNode object with dict-like interface.
+
+ AugeasWrapper can be used in with statement in the same way as file does.
+ """
+
+ def __init__(self, confpath, lens, root=None, loadpath=None,
+ flags=Augeas.NO_MODL_AUTOLOAD | Augeas.NO_LOAD | Augeas.ENABLE_SPAN):
+ """Parse configuration file using given lens.
+
+ Params:
+ confpath (str): Absolute path to the configuration file
+ lens (str): Name of module containing Augeas lens
+ root: passed down to original Augeas
+ flags: passed down to original Augeas
+ loadpath: passed down to original Augeas
+ flags: passed down to original Augeas
+ """
+ log.debug('loadpath: %s', loadpath)
+ log.debug('confpath: %s', confpath)
+ self._aug = Augeas(root=root, loadpath=loadpath, flags=flags)
+
+ # /augeas/load/{lens}
+ aug_load_path = join(AUGEAS_LOAD_PATH, lens)
+ # /augeas/load/{lens}/lens = {lens}.lns
+ self._aug.set(join(aug_load_path, 'lens'), '%s.lns' % lens)
+ # /augeas/load/{lens}/incl[0] = {confpath}
+ self._aug.set(join(aug_load_path, 'incl[0]'), confpath)
+ self._aug.load()
+
+ errors = self._aug.match(AUGEAS_ERROR_PATH)
+ if errors:
+ err_msg = '\n'.join(
+ ["{}: {}".format(e, self._aug.get(e)) for e in errors]
+ )
+ raise RuntimeError(err_msg)
+
+ path = join(AUGEAS_FILES_PATH, confpath)
+ paths = self._aug.match(path)
+ if len(paths) != 1:
+ raise ValueError('path %s did not match exactly once' % path)
+ self.tree = AugeasNode(self._aug, path)
+ self._loaded = True
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.save()
+ self.close()
+
+ def save(self):
+ """Save Augeas tree to its original file."""
+ assert self._loaded
+ try:
+ self._aug.save()
+ except IOError as exc:
+ log.exception(exc)
+ for err_path in self._aug.match('//error'):
+ log.error('%s: %s', err_path,
+ self._aug.get(os.path.join(err_path, 'message')))
+ raise
+
+ def close(self):
+ """
+ close Augeas library
+
+ After calling close() the object must not be used anymore.
+ """
+ assert self._loaded
+ self._aug.close()
+ del self._aug
+ self._loaded = False
+
+ def match(self, path):
+ """Yield AugeasNodes matching given expression."""
+ assert self._loaded
+ assert path
+ log.debug('tree match %s', path)
+ for matched_path in self._aug.match(path):
+ yield AugeasNode(self._aug, matched_path)
+
+
+class AugeasNode(collections.MutableMapping):
+ """One Augeas tree node with dict-like interface."""
+
+ def __init__(self, aug, path):
+ """
+ Args:
+ aug (AugeasWrapper or Augeas): Augeas library instance
+ path (str): absolute path in Augeas tree matching single node
+
+ BEWARE: There are no sanity checks of given path for performance reasons.
+ """
+ assert aug
+ assert path
+ assert path.startswith('/')
+ self._aug = aug
+ self._path = path
+ self._span = None
+
+ @property
+ def path(self):
+ """canonical path in Augeas tree, read-only"""
+ return self._path
+
+ @property
+ def value(self):
+ """
+ get value of this node in Augeas tree
+ """
+ value = self._aug.get(self._path)
+ log.debug('tree get: %s = %s', self._path, value)
+ return value
+
+ @value.setter
+ def value(self, value):
+ """
+ set value of this node in Augeas tree
+ """
+ log.debug('tree set: %s = %s', self._path, value)
+ self._aug.set(self._path, value)
+
+ @property
+ def span(self):
+ if self._span is None:
+ self._span = "char position %s" % self._aug.span(self._path)[5]
+ return self._span
+
+ @property
+ def char(self):
+ return self._aug.span(self._path)[5]
+
+ def __len__(self):
+ """
+ number of items matching this path
+
+ It is always 1 after __init__() but it may change
+ as Augeas tree changes.
+ """
+ return len(self._aug.match(self._path))
+
+ def __getitem__(self, key):
+ if isinstance(key, int):
+ # int is a shortcut to write [int]
+ target_path = '%s[%s]' % (self._path, key)
+ else:
+ target_path = self._path + key
+ log.debug('tree getitem: target_path %s', target_path)
+ paths = self._aug.match(target_path)
+ if len(paths) != 1:
+ raise KeyError('path %s did not match exactly once' % target_path)
+ return AugeasNode(self._aug, target_path)
+
+ def __delitem__(self, key):
+ log.debug('tree delitem: %s + %s', self._path, key)
+ target_path = self._path + key
+ log.debug('tree delitem: target_path %s', target_path)
+ self._aug.remove(target_path)
+
+ def __setitem__(self, key, value):
+ assert isinstance(value, AugeasNode)
+ target_path = self.path + key
+ self._aug.copy(value.path, target_path)
+
+ def __iter__(self):
+ self_path_len = len(self._path)
+ assert self_path_len > 0
+
+ log.debug('tree iter: %s', self._path)
+ for new_path in self._aug.match(self._path):
+ if len(new_path) == self_path_len:
+ yield ''
+ else:
+ yield new_path[self_path_len - 1:]
+
+ def match(self, subpath):
+ """Yield AugeasNodes matching given sub-expression."""
+ assert subpath.startswith("/")
+ match_path = "%s%s" % (self._path, subpath)
+ log.debug('tree match %s: %s', match_path, self._path)
+ for matched_path in self._aug.match(match_path):
+ yield AugeasNode(self._aug, matched_path)
+
+ def __repr__(self):
+ return 'AugeasNode(%s)' % self._path
diff --git a/tests/deckard/pydnstest/deckard.aug b/tests/deckard/pydnstest/deckard.aug
new file mode 100644
index 0000000..9e2d167
--- /dev/null
+++ b/tests/deckard/pydnstest/deckard.aug
@@ -0,0 +1,94 @@
+module Deckard =
+ autoload xfm
+
+let del_str = Util.del_str
+
+let space = del /[ \t]+/ " "
+let tab = del /[ \t]+/ "\t"
+let ws = del /[\t ]*/ ""
+let word = /[^\t\n\/; ]+/
+
+let comment = del /[;]/ ";" . [label "comment" . store /[^\n]+/]
+
+let eol = del /([ \t]*([;][^\n]*)?\n)+/ "\n" . Util.indent
+let comment_or_eol = ws . comment? . del_str "\n" . del /([ \t]*([;][^\n]*)?\n)*/ "" . Util.indent
+
+
+(*let comment_or_eol = [ label "#comment" . counter "comment" . (ws . [del /[;#]/ ";" . label "" . store /[^\n]*/ ]? . del_str "\n")]+ . Util.indent
+*)
+
+
+let domain_re = (/[^.\t\n\/; ]+(\.[^.\t\n\/; ]+)*\.?/ | ".") - "SECTION" (*quick n dirty, sorry to whoever will ever own SECTION TLD*)
+let class_re = /CLASS[0-9]+/ | "IN" | "CH" | "HS" | "NONE" | "ANY"
+let domain = [ label "domain" . store domain_re ]
+let ttl = [label "ttl" . store /[0-9]+/]
+let class = [label "class" . store class_re ]
+let type = [label "type" . store ((/[^0-9;\n \t][^\t\n\/; ]*/) - class_re) ]
+(* RFC 3597 section 5 rdata syntax is "\# 1 ab"*)
+let data_re = /((\\#[ \t])?[^ \t\n;][^\n;]*[^ \t\n;])|[^ \t\n;]/ (*Can not start nor end with whitespace but can have whitespace in the middle. Disjunction is there so we match strings of length one.*)
+let data = [label "data" . store data_re ]
+
+let ip_re = /[0-9a-f.:]+/
+let hex_re = /[0-9a-fA-F]+/
+
+
+let match_option = "opcode" | "qtype" | "qcase" | "qname" | "subdomain" | "flags" | "rcode" | "question" | "answer" | "authority" | "additional" | "all" | "edns"
+let adjust_option = "copy_id" | "copy_query" | "raw_id" | "do_not_answer"
+let reply_option = "QR" | "TC" | "AA" | "AD" | "RD" | "RA" | "CD" | "DO" | "NOERROR" | "FORMERR" | "SERVFAIL" | "NXDOMAIN" | "NOTIMP" | "REFUSED" | "YXDOMAIN" | "YXRRSET" | "NXRRSET" | "NOTAUTH" | "NOTZONE" | "BADVERS" | "BADSIG" | "BADKEY" | "BADTIME" | "BADMODE" | "BADNAME" | "BADALG" | "BADTRUNC" | "BADCOOKIE"
+let step_option = "REPLY" | "QUERY" | "CHECK_ANSWER" | "CHECK_OUT_QUERY" | /TIME_PASSES[ \t]+ELAPSE/
+
+let mandatory = [del_str "MANDATORY" . label "mandatory" . value "true" . comment_or_eol]
+let tsig = [del_str "TSIG" . label "tsig" . space . [label "keyname" . store word] . space . [label "secret" . store word] . comment_or_eol]
+
+let match = (mandatory | tsig)* . [ label "match_present" . value "true" . del_str "MATCH" ] . [space . label "match" . store match_option ]+ . comment_or_eol
+let adjust = (mandatory | tsig)* . del_str "ADJUST" . [space . label "adjust" . store adjust_option ]+ . comment_or_eol
+let reply = (mandatory | tsig)* . del ("REPLY" | "FLAGS") "REPLY" . [space . label "reply" . store reply_option ]+ . comment_or_eol
+
+
+let question = [label "record" . domain . tab . (class . tab)? . type . comment_or_eol ]
+let record = [label "record" . domain . tab . (ttl . tab)? . (class . tab)? . type . tab . data . comment_or_eol]
+
+let section_question = [ label "question" . del_str "SECTION QUESTION" .
+ comment_or_eol . question? ]
+let section_answer = [ label "answer" . del_str "SECTION ANSWER" .
+ comment_or_eol . record* ]
+let section_authority = [ label "authority" . del_str "SECTION AUTHORITY" .
+ comment_or_eol . record* ]
+let section_additional = [ label "additional" . del_str "SECTION ADDITIONAL" .
+ comment_or_eol . record* ]
+let sections = [label "section" . section_question? . section_answer? . section_authority? . section_additional?]
+let raw = [del_str "RAW" . comment_or_eol . label "raw" . store hex_re ] . comment_or_eol
+
+(* This is quite dirty hack to match every combination of options given to entry since 'let dnsmsg = ((match | adjust | reply | mandatory | tsig)* . sections)' just is not possible *)
+
+let dnsmsg = (match . (adjust . reply? | reply . adjust?)? | adjust . (match . reply? | reply . match?)? | reply . (match . adjust? | adjust . match?)?)? . (mandatory | tsig)* . sections
+
+let entry = [label "entry" . del_str "ENTRY_BEGIN" . comment_or_eol . dnsmsg . raw? . del_str "ENTRY_END" . eol]
+
+let single_address = [ label "address" . space . store ip_re ]
+
+let addresses = [label "address" . counter "address" . [seq "address" . del_str "ADDRESS" . space . store ip_re . comment_or_eol]+]
+
+let range = [label "range" . del_str "RANGE_BEGIN" . space . [ label "from" . store /[0-9]+/] . space .
+ [ label "to" . store /[0-9]+/] . single_address? . comment_or_eol . addresses? . entry* . del_str "RANGE_END" . eol]
+
+let step = [label "step" . del_str "STEP" . space . store /[0-9]+/ . space . [label "type" . store step_option] . [space . label "timestamp" . store /[0-9]+/]? . comment_or_eol .
+ entry? ]
+
+let config_record = /[^\n]*/ - ("CONFIG_END" | /STEP.*/ | /SCENARIO.*/ | /RANGE.*/ | /ENTRY.*/)
+
+let config = [ label "config" . counter "config" . [seq "config" . store config_record . del_str "\n"]* . del_str "CONFIG_END" . comment_or_eol ]
+
+let guts = (step | range )*
+
+let scenario = [label "scenario" . del_str "SCENARIO_BEGIN" . space . store data_re . comment_or_eol . guts . del_str "SCENARIO_END" . eol]
+
+let lns = config? . scenario
+
+(* TODO: REPLAY step *)
+(* TODO: store all comments into the tree instead of ignoring them *)
+
+(*let filter = incl "/home/test/*.rpl"*)
+let filter = incl "/home/sbalazik/nic/deckard/git/sets/resolver/*.rpl"
+
+let xfm = transform lns filter
diff --git a/tests/deckard/pydnstest/empty.rpl b/tests/deckard/pydnstest/empty.rpl
new file mode 100644
index 0000000..295d5a5
--- /dev/null
+++ b/tests/deckard/pydnstest/empty.rpl
@@ -0,0 +1,20 @@
+stub-addr: 127.0.0.10
+CONFIG_END
+
+SCENARIO_BEGIN empty replies
+
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.10
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+SECTION QUESTION
+. IN A
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/pydnstest/matchpart.py b/tests/deckard/pydnstest/matchpart.py
new file mode 100644
index 0000000..294e64c
--- /dev/null
+++ b/tests/deckard/pydnstest/matchpart.py
@@ -0,0 +1,238 @@
+"""matchpart is used to compare two DNS messages using a single criterion"""
+
+from typing import ( # noqa
+ Any, Hashable, Sequence, Tuple, Union)
+
+import dns.edns
+import dns.rcode
+import dns.set
+
+MismatchValue = Union[str, Sequence[Any]]
+
+
+class DataMismatch(Exception):
+ def __init__(self, exp_val, got_val):
+ super().__init__()
+ self.exp_val = exp_val
+ self.got_val = got_val
+
+ @staticmethod
+ def format_value(value: MismatchValue) -> str:
+ if isinstance(value, list):
+ return ' '.join([str(val) for val in value])
+ else:
+ return str(value)
+
+ def __str__(self) -> str:
+ return 'expected "{}" got "{}"'.format(
+ self.format_value(self.exp_val),
+ self.format_value(self.got_val))
+
+ def __eq__(self, other):
+ return (isinstance(other, DataMismatch)
+ and self.exp_val == other.exp_val
+ and self.got_val == other.got_val)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ @property
+ def key(self) -> Tuple[Hashable, Hashable]:
+ def make_hashable(value):
+ if isinstance(value, (list, dns.set.Set)):
+ value = (make_hashable(item) for item in value)
+ value = tuple(value)
+ return value
+
+ return (make_hashable(self.exp_val), make_hashable(self.got_val))
+
+ def __hash__(self) -> int:
+ return hash(self.key)
+
+
+def compare_val(exp, got):
+ """Compare arbitraty objects, throw exception if different. """
+ if exp != got:
+ raise DataMismatch(exp, got)
+ return True
+
+
+def compare_rrs(expected, got):
+ """ Compare lists of RR sets, throw exception if different. """
+ for rr in expected:
+ if rr not in got:
+ raise DataMismatch(expected, got)
+ for rr in got:
+ if rr not in expected:
+ raise DataMismatch(expected, got)
+ if len(expected) != len(got):
+ raise DataMismatch(expected, got)
+ return True
+
+
+def compare_rrs_types(exp_val, got_val, skip_rrsigs):
+ """sets of RR types in both sections must match"""
+ def rr_ordering_key(rrset):
+ if rrset.covers:
+ return rrset.covers, 1 # RRSIGs go to the end of RRtype list
+ else:
+ return rrset.rdtype, 0
+
+ def key_to_text(rrtype, rrsig):
+ if not rrsig:
+ return dns.rdatatype.to_text(rrtype)
+ else:
+ return 'RRSIG(%s)' % dns.rdatatype.to_text(rrtype)
+
+ if skip_rrsigs:
+ exp_val = (rrset for rrset in exp_val
+ if rrset.rdtype != dns.rdatatype.RRSIG)
+ got_val = (rrset for rrset in got_val
+ if rrset.rdtype != dns.rdatatype.RRSIG)
+
+ exp_types = frozenset(rr_ordering_key(rrset) for rrset in exp_val)
+ got_types = frozenset(rr_ordering_key(rrset) for rrset in got_val)
+ if exp_types != got_types:
+ exp_types = tuple(key_to_text(*i) for i in sorted(exp_types))
+ got_types = tuple(key_to_text(*i) for i in sorted(got_types))
+ raise DataMismatch(exp_types, got_types)
+
+
+def check_question(question):
+ if len(question) > 2:
+ raise NotImplementedError("More than one record in QUESTION SECTION.")
+
+
+def match_opcode(exp, got):
+ return compare_val(exp.opcode(),
+ got.opcode())
+
+
+def match_qtype(exp, got):
+ check_question(exp.question)
+ check_question(got.question)
+ if not exp.question and not got.question:
+ return True
+ if not exp.question:
+ raise DataMismatch("<empty question>", got.question[0].rdtype)
+ if not got.question:
+ raise DataMismatch(exp.question[0].rdtype, "<empty question>")
+ return compare_val(exp.question[0].rdtype,
+ got.question[0].rdtype)
+
+
+def match_qname(exp, got):
+ check_question(exp.question)
+ check_question(got.question)
+ if not exp.question and not got.question:
+ return True
+ if not exp.question:
+ raise DataMismatch("<empty question>", got.question[0].name)
+ if not got.question:
+ raise DataMismatch(exp.question[0].name, "<empty question>")
+ return compare_val(exp.question[0].name,
+ got.question[0].name)
+
+
+def match_qcase(exp, got):
+ check_question(exp.question)
+ check_question(got.question)
+ if not exp.question and not got.question:
+ return True
+ if not exp.question:
+ raise DataMismatch("<empty question>", got.question[0].name.labels)
+ if not got.question:
+ raise DataMismatch(exp.question[0].name.labels, "<empty question>")
+ return compare_val(exp.question[0].name.labels,
+ got.question[0].name.labels)
+
+
+def match_subdomain(exp, got):
+ if not exp.question:
+ return True
+ if got.question:
+ qname = got.question[0].name
+ else:
+ qname = dns.name.root
+ if exp.question[0].name.is_superdomain(qname):
+ return True
+ raise DataMismatch(exp, got)
+
+
+def match_flags(exp, got):
+ return compare_val(dns.flags.to_text(exp.flags),
+ dns.flags.to_text(got.flags))
+
+
+def match_rcode(exp, got):
+ return compare_val(dns.rcode.to_text(exp.rcode()),
+ dns.rcode.to_text(got.rcode()))
+
+
+def match_answer(exp, got):
+ return compare_rrs(exp.answer,
+ got.answer)
+
+
+def match_answertypes(exp, got):
+ return compare_rrs_types(exp.answer,
+ got.answer, skip_rrsigs=True)
+
+
+def match_answerrrsigs(exp, got):
+ return compare_rrs_types(exp.answer,
+ got.answer, skip_rrsigs=False)
+
+
+def match_authority(exp, got):
+ return compare_rrs(exp.authority,
+ got.authority)
+
+
+def match_additional(exp, got):
+ return compare_rrs(exp.additional,
+ got.additional)
+
+
+def match_edns(exp, got):
+ if got.edns != exp.edns:
+ raise DataMismatch(exp.edns,
+ got.edns)
+ if got.payload != exp.payload:
+ raise DataMismatch(exp.payload,
+ got.payload)
+
+
+def match_nsid(exp, got):
+ nsid_opt = None
+ for opt in exp.options:
+ if opt.otype == dns.edns.NSID:
+ nsid_opt = opt
+ break
+ # Find matching NSID
+ for opt in got.options:
+ if opt.otype == dns.edns.NSID:
+ if not nsid_opt:
+ raise DataMismatch(None, opt.data)
+ if opt == nsid_opt:
+ return True
+ else:
+ raise DataMismatch(nsid_opt.data, opt.data)
+ if nsid_opt:
+ raise DataMismatch(nsid_opt.data, None)
+ return True
+
+
+MATCH = {"opcode": match_opcode, "qtype": match_qtype, "qname": match_qname, "qcase": match_qcase,
+ "subdomain": match_subdomain, "flags": match_flags, "rcode": match_rcode,
+ "answer": match_answer, "answertypes": match_answertypes,
+ "answerrrsigs": match_answerrrsigs, "authority": match_authority,
+ "additional": match_additional, "edns": match_edns,
+ "nsid": match_nsid}
+
+
+def match_part(exp, got, code):
+ try:
+ return MATCH[code](exp, got)
+ except KeyError:
+ raise NotImplementedError('unknown match request "%s"' % code)
diff --git a/tests/deckard/pydnstest/scenario.py b/tests/deckard/pydnstest/scenario.py
new file mode 100644
index 0000000..5e0661b
--- /dev/null
+++ b/tests/deckard/pydnstest/scenario.py
@@ -0,0 +1,1058 @@
+# FIXME pylint: disable=too-many-lines
+from abc import ABC
+import binascii
+import calendar
+from datetime import datetime
+import errno
+import logging
+import os
+import posixpath
+import random
+import socket
+import string
+import struct
+import time
+from typing import Optional
+
+import dns.dnssec
+import dns.message
+import dns.name
+import dns.rcode
+import dns.rrset
+import dns.tsigkeyring
+
+import pydnstest.augwrap
+import pydnstest.matchpart
+
+
+def str2bool(v):
+ """ Return conversion of JSON-ish string value to boolean. """
+ return v.lower() in ('yes', 'true', 'on', '1')
+
+
+# Global statistics
+g_rtt = 0.0
+g_nqueries = 0
+
+
+def recvfrom_msg(stream, raw=False):
+ """
+ Receive DNS message from TCP/UDP socket.
+
+ Returns:
+ if raw == False: (DNS message object, peer address)
+ if raw == True: (blob, peer address)
+ """
+ if stream.type & socket.SOCK_DGRAM:
+ data, addr = stream.recvfrom(4096)
+ elif stream.type & socket.SOCK_STREAM:
+ data = stream.recv(2)
+ if not data:
+ return None, None
+ msg_len = struct.unpack_from("!H", data)[0]
+ data = b""
+ received = 0
+ while received < msg_len:
+ next_chunk = stream.recv(4096)
+ if not next_chunk:
+ return None, None
+ data += next_chunk
+ received += len(next_chunk)
+ addr = stream.getpeername()[0]
+ else:
+ raise NotImplementedError("[recvfrom_msg]: unknown socket type '%i'" % stream.type)
+ if raw:
+ return data, addr
+ else:
+ msg = dns.message.from_wire(data, one_rr_per_rrset=True)
+ return msg, addr
+
+
+def sendto_msg(stream, message, addr=None):
+ """ Send DNS/UDP/TCP message. """
+ try:
+ if stream.type & socket.SOCK_DGRAM:
+ if addr is None:
+ stream.send(message)
+ else:
+ stream.sendto(message, addr)
+ elif stream.type & socket.SOCK_STREAM:
+ data = struct.pack("!H", len(message)) + message
+ stream.send(data)
+ else:
+ raise NotImplementedError("[sendto_msg]: unknown socket type '%i'" % stream.type)
+ except socket.error as ex:
+ if ex.errno != errno.ECONNREFUSED: # TODO Investigate how this can happen
+ raise
+
+
+def replay_rrs(rrs, nqueries, destination, args=None):
+ """ Replay list of queries and report statistics. """
+ if args is None:
+ args = []
+ navail, queries = len(rrs), []
+ chunksize = 16
+ for i in range(nqueries if 'RAND' in args else navail):
+ rr = rrs[i % navail]
+ name = rr.name
+ if 'RAND' in args:
+ prefix = ''.join([random.choice(string.ascii_letters + string.digits)
+ for _ in range(8)])
+ name = prefix + '.' + rr.name.to_text()
+ msg = dns.message.make_query(name, rr.rdtype, rr.rdclass)
+ if 'DO' in args:
+ msg.want_dnssec(True)
+ queries.append(msg.to_wire())
+ # Make a UDP connected socket to the destination
+ family = socket.AF_INET6 if ':' in destination[0] else socket.AF_INET
+ sock = socket.socket(family, socket.SOCK_DGRAM)
+ sock.connect(destination)
+ sock.setblocking(False)
+ # Play the query set
+ # @NOTE: this is only good for relative low-speed replay
+ rcvbuf = bytearray('\x00' * 512)
+ nsent, nrcvd, nwait, navail = 0, 0, 0, len(queries)
+ fdset = [sock]
+ import select
+ while nsent - nwait < nqueries:
+ to_read, to_write, _ = select.select(fdset, fdset if nwait < chunksize else [], [], 0.5)
+ if to_write:
+ try:
+ while nsent < nqueries and nwait < chunksize:
+ sock.send(queries[nsent % navail])
+ nwait += 1
+ nsent += 1
+ except socket.error:
+ pass # EINVAL
+ if to_read:
+ try:
+ while nwait > 0:
+ sock.recv_into(rcvbuf)
+ nwait -= 1
+ nrcvd += 1
+ except socket.error:
+ pass
+ if not to_write and not to_read:
+ nwait = 0 # Timeout, started dropping packets
+ break
+ return nsent, nrcvd
+
+
+class DNSBlob(ABC):
+ def to_wire(self) -> bytes:
+ raise NotImplementedError
+
+ def __str__(self) -> str:
+ return '<DNSBlob>'
+
+
+class DNSMessage(DNSBlob):
+ def __init__(self, message: dns.message.Message) -> None:
+ assert message is not None
+ self.message = message
+
+ def to_wire(self) -> bytes:
+ return self.message.to_wire(max_size=65535)
+
+ def __str__(self) -> str:
+ return str(self.message)
+
+
+class DNSReply(DNSMessage):
+ def __init__(
+ self,
+ message: dns.message.Message,
+ query: Optional[dns.message.Message] = None,
+ copy_id: bool = False,
+ copy_query: bool = False
+ ) -> None:
+ super().__init__(message)
+ if copy_id or copy_query:
+ if query is None:
+ raise ValueError("query must be provided to adjust copy_id/copy_query")
+ self.adjust_reply(query, copy_id, copy_query)
+
+ def adjust_reply(
+ self,
+ query: dns.message.Message,
+ copy_id: bool = True,
+ copy_query: bool = True
+ ) -> None:
+ answer = dns.message.from_wire(self.message.to_wire(),
+ xfr=self.message.xfr,
+ one_rr_per_rrset=True)
+ answer.use_edns(query.edns, query.ednsflags, options=self.message.options)
+ if copy_id:
+ answer.id = query.id
+ # Copy letter-case if the template has QD
+ if answer.question:
+ answer.question[0].name = query.question[0].name
+ if copy_query:
+ answer.question = query.question
+ # Re-set, as the EDNS might have reset the ext-rcode
+ answer.set_rcode(self.message.rcode())
+
+ # sanity check: adjusted answer should be almost the same
+ assert len(answer.answer) == len(self.message.answer)
+ assert len(answer.authority) == len(self.message.authority)
+ assert len(answer.additional) == len(self.message.additional)
+ self.message = answer
+
+
+class DNSReplyRaw(DNSBlob):
+ def __init__(
+ self,
+ wire: bytes,
+ query: Optional[dns.message.Message] = None,
+ copy_id: bool = False
+ ) -> None:
+ assert wire is not None
+ self.wire = wire
+ if copy_id:
+ self.adjust_reply(query, copy_id)
+
+ def adjust_reply(
+ self,
+ query: dns.message.Message,
+ copy_id: bool = True
+ ) -> None:
+ if copy_id:
+ if len(self.wire) < 2:
+ raise ValueError(
+ 'wire data must contain at least 2 bytes to adjust query id')
+ raw_answer = bytearray(self.wire)
+ struct.pack_into('!H', raw_answer, 0, query.id)
+ self.wire = bytes(raw_answer)
+
+ def to_wire(self) -> bytes:
+ return self.wire
+
+ def __str__(self) -> str:
+ return '<DNSReplyRaw>'
+
+
+class DNSReplyServfail(DNSMessage):
+ def __init__(self, query: dns.message.Message) -> None:
+ message = dns.message.make_response(query)
+ message.set_rcode(dns.rcode.SERVFAIL)
+ super().__init__(message)
+
+
+class Entry:
+ """
+ Data entry represents scripted message and extra metadata,
+ notably match criteria and reply adjustments.
+ """
+
+ # Globals
+ default_ttl = 3600
+ default_cls = 'IN'
+ default_rc = 'NOERROR'
+
+ def __init__(self, node):
+ """ Initialize data entry. """
+ self.node = node
+ self.origin = '.'
+ self.message = dns.message.Message()
+ self.message.use_edns(edns=0, payload=4096)
+ self.fired = 0
+
+ # RAW
+ self.raw_data = None # type: Optional[bytes]
+ self.is_raw_data_entry = self.process_raw()
+
+ # MATCH
+ self.match_fields = self.process_match()
+
+ # FLAGS
+ self.process_reply_line()
+
+ # ADJUST
+ self.adjust_fields = {m.value for m in node.match("/adjust")}
+
+ # MANDATORY
+ try:
+ self.mandatory = list(node.match("/mandatory"))[0]
+ except (KeyError, IndexError):
+ self.mandatory = None
+
+ # TSIG
+ self.process_tsig()
+
+ # SECTIONS & RECORDS
+ self.sections = self.process_sections()
+
+ def process_raw(self):
+ try:
+ self.raw_data = binascii.unhexlify(self.node["/raw"].value)
+ return True
+ except KeyError:
+ return False
+
+ def process_match(self):
+ try:
+ self.node["/match_present"]
+ except KeyError:
+ return None
+
+ fields = set(m.value for m in self.node.match("/match"))
+
+ if 'all' in fields:
+ fields.remove("all")
+ fields |= set(["opcode", "qtype", "qname", "flags",
+ "rcode", "answer", "authority", "additional"])
+
+ if 'question' in fields:
+ fields.remove("question")
+ fields |= set(["qtype", "qname"])
+
+ return fields
+
+ def process_reply_line(self):
+ """Extracts flags, rcode and opcode from given node and adjust dns message accordingly"""
+ self.fields = [f.value for f in self.node.match("/reply")]
+ if 'DO' in self.fields:
+ self.message.want_dnssec(True)
+ opcode = self.get_opcode(fields=self.fields)
+ rcode = self.get_rcode(fields=self.fields)
+ self.message.flags = self.get_flags(fields=self.fields)
+ if rcode is not None:
+ self.message.set_rcode(rcode)
+ if opcode is not None:
+ self.message.set_opcode(opcode)
+
+ def process_tsig(self):
+ try:
+ tsig = list(self.node.match("/tsig"))[0]
+ tsig_keyname = tsig["/keyname"].value
+ tsig_secret = tsig["/secret"].value
+ keyring = dns.tsigkeyring.from_text({tsig_keyname: tsig_secret})
+ self.message.use_tsig(keyring=keyring, keyname=tsig_keyname)
+ except (KeyError, IndexError):
+ pass
+
+ def process_sections(self):
+ sections = set()
+ for section in self.node.match("/section/*"):
+ section_name = posixpath.basename(section.path)
+ sections.add(section_name)
+ for record in section.match("/record"):
+ owner = record['/domain'].value
+ if not owner.endswith("."):
+ owner += self.origin
+ try:
+ ttl = dns.ttl.from_text(record['/ttl'].value)
+ except KeyError:
+ ttl = self.default_ttl
+ try:
+ rdclass = dns.rdataclass.from_text(record['/class'].value)
+ except KeyError:
+ rdclass = dns.rdataclass.from_text(self.default_cls)
+ rdtype = dns.rdatatype.from_text(record['/type'].value)
+ rr = dns.rrset.from_text(owner, ttl, rdclass, rdtype)
+ if section_name != "question":
+ rd = record['/data'].value.split()
+ if rd:
+ if rdtype == dns.rdatatype.DS:
+ rd[1] = str(dns.dnssec.algorithm_from_text(rd[1]))
+ rd = dns.rdata.from_text(rr.rdclass, rr.rdtype, ' '.join(
+ rd), origin=dns.name.from_text(self.origin), relativize=False)
+ rr.add(rd)
+ if section_name == 'question':
+ if rr.rdtype == dns.rdatatype.AXFR:
+ self.message.xfr = True
+ self.message.question.append(rr)
+ elif section_name == 'answer':
+ self.message.answer.append(rr)
+ elif section_name == 'authority':
+ self.message.authority.append(rr)
+ elif section_name == 'additional':
+ self.message.additional.append(rr)
+ return sections
+
+ def __str__(self):
+ txt = 'ENTRY_BEGIN\n'
+ if not self.is_raw_data_entry:
+ txt += 'MATCH {0}\n'.format(' '.join(self.match_fields))
+ txt += 'ADJUST {0}\n'.format(' '.join(self.adjust_fields))
+ txt += 'REPLY {rcode} {flags}\n'.format(
+ rcode=dns.rcode.to_text(self.message.rcode()),
+ flags=' '.join([dns.flags.to_text(self.message.flags),
+ dns.flags.edns_to_text(self.message.ednsflags)])
+ )
+ for sect_name in ['question', 'answer', 'authority', 'additional']:
+ sect = getattr(self.message, sect_name)
+ if not sect:
+ continue
+ txt += 'SECTION {n}\n'.format(n=sect_name.upper())
+ for rr in sect:
+ txt += str(rr)
+ txt += '\n'
+ if self.is_raw_data_entry:
+ txt += 'RAW\n'
+ if self.raw_data:
+ txt += binascii.hexlify(self.raw_data)
+ else:
+ txt += 'NULL'
+ txt += '\n'
+ txt += 'ENTRY_END\n'
+ return txt
+
+ @classmethod
+ def get_flags(cls, fields):
+ """From `fields` extracts and returns flags"""
+ flags = []
+ for code in fields:
+ try:
+ dns.flags.from_text(code) # throws KeyError on failure
+ flags.append(code)
+ except KeyError:
+ pass
+ return dns.flags.from_text(' '.join(flags))
+
+ @classmethod
+ def get_rcode(cls, fields):
+ """
+ From `fields` extracts and returns rcode.
+ Throws `ValueError` if there are more then one rcodes
+ """
+ rcodes = []
+ for code in fields:
+ try:
+ rcodes.append(dns.rcode.from_text(code))
+ except dns.rcode.UnknownRcode:
+ pass
+ if len(rcodes) > 1:
+ raise ValueError("Parse failed, too many rcode values.", rcodes)
+ if not rcodes:
+ return None
+ return rcodes[0]
+
+ @classmethod
+ def get_opcode(cls, fields):
+ """
+ From `fields` extracts and returns opcode.
+ Throws `ValueError` if there are more then one opcodes
+ """
+ opcodes = []
+ for code in fields:
+ try:
+ opcodes.append(dns.opcode.from_text(code))
+ except dns.opcode.UnknownOpcode:
+ pass
+ if len(opcodes) > 1:
+ raise ValueError("Parse failed, too many opcode values.")
+ if not opcodes:
+ return None
+ return opcodes[0]
+
+ def match(self, msg):
+ """ Compare scripted reply to given message based on match criteria. """
+ for code in self.match_fields:
+ try:
+ pydnstest.matchpart.match_part(self.message, msg, code)
+ except pydnstest.matchpart.DataMismatch as ex:
+ errstr = '%s in the response:\n%s' % (str(ex), msg.to_text())
+ # TODO: cisla radku
+ raise ValueError("%s, \"%s\": %s" % (self.node.span, code, errstr))
+
+ def cmp_raw(self, raw_value):
+ assert self.is_raw_data_entry
+ expected = None
+ if self.raw_data is not None:
+ expected = binascii.hexlify(self.raw_data)
+ got = None
+ if raw_value is not None:
+ got = binascii.hexlify(raw_value)
+ if expected != got:
+ raise ValueError("raw message comparsion failed: expected %s got %s" % (expected, got))
+
+ def reply(self, query) -> Optional[DNSBlob]:
+ if 'do_not_answer' in self.adjust_fields:
+ return None
+ if self.is_raw_data_entry:
+ copy_id = 'raw_data' in self.adjust_fields
+ assert self.raw_data is not None
+ return DNSReplyRaw(self.raw_data, query, copy_id)
+ copy_id = 'copy_id' in self.adjust_fields
+ copy_query = 'copy_query' in self.adjust_fields
+ return DNSReply(self.message, query, copy_id, copy_query)
+
+ def set_edns(self, fields):
+ """ Set EDNS version and bufsize. """
+ version = 0
+ bufsize = 4096
+ if fields and fields[0].isdigit():
+ version = int(fields.pop(0))
+ if fields and fields[0].isdigit():
+ bufsize = int(fields.pop(0))
+ if bufsize == 0:
+ self.message.use_edns(False)
+ return
+ opts = []
+ for v in fields:
+ k, v = tuple(v.split('=')) if '=' in v else (v, True)
+ if k.lower() == 'nsid':
+ opts.append(dns.edns.GenericOption(dns.edns.NSID, '' if v is True else v))
+ if k.lower() == 'subnet':
+ net = v.split('/')
+ subnet_addr = net[0]
+ family = socket.AF_INET6 if ':' in subnet_addr else socket.AF_INET
+ addr = socket.inet_pton(family, subnet_addr)
+ prefix = len(addr) * 8
+ if len(net) > 1:
+ prefix = int(net[1])
+ addr = addr[0: (prefix + 7) / 8]
+ if prefix % 8 != 0: # Mask the last byte
+ addr = addr[:-1] + chr(ord(addr[-1]) & 0xFF << (8 - prefix % 8))
+ opts.append(dns.edns.GenericOption(8, struct.pack(
+ "!HBB", 1 if family == socket.AF_INET else 2, prefix, 0) + addr))
+ self.message.use_edns(edns=version, payload=bufsize, options=opts)
+
+
+class Range:
+ """
+ Range represents a set of scripted queries valid for given step range.
+ """
+ log = logging.getLogger('pydnstest.scenario.Range')
+
+ def __init__(self, node):
+ """ Initialize reply range. """
+ self.node = node
+ self.a = int(node['/from'].value)
+ self.b = int(node['/to'].value)
+ assert self.a <= self.b
+
+ address = node["/address"].value
+ self.addresses = {address} if address is not None else set()
+ self.addresses |= {a.value for a in node.match("/address/*")}
+ self.stored = [Entry(n) for n in node.match("/entry")]
+ self.args = {}
+ self.received = 0
+ self.sent = 0
+
+ def __del__(self):
+ self.log.info('[ RANGE %d-%d ] %s received: %d sent: %d',
+ self.a, self.b, self.addresses, self.received, self.sent)
+
+ def __str__(self):
+ txt = '\nRANGE_BEGIN {a} {b}\n'.format(a=self.a, b=self.b)
+ for addr in self.addresses:
+ txt += ' ADDRESS {0}\n'.format(addr)
+
+ for entry in self.stored:
+ txt += '\n'
+ txt += str(entry)
+ txt += 'RANGE_END\n\n'
+ return txt
+
+ def eligible(self, ident, address):
+ """ Return true if this range is eligible for fetching reply. """
+ if self.a <= ident <= self.b:
+ return (None is address
+ or set() == self.addresses
+ or address in self.addresses)
+ return False
+
+ def reply(self, query: dns.message.Message) -> Optional[DNSBlob]:
+ """Get answer for given query (adjusted if needed)."""
+ self.received += 1
+ for candidate in self.stored:
+ try:
+ candidate.match(query)
+ resp = candidate.reply(query)
+ # Probabilistic loss
+ if 'LOSS' in self.args:
+ if random.random() < float(self.args['LOSS']):
+ return DNSReplyServfail(query)
+ self.sent += 1
+ candidate.fired += 1
+ return resp
+ except ValueError:
+ pass
+ return DNSReplyServfail(query)
+
+
+class StepLogger(logging.LoggerAdapter): # pylint: disable=too-few-public-methods
+ """
+ Prepent Step identification before each log message.
+ """
+ def process(self, msg, kwargs):
+ return '[STEP %s %s] %s' % (self.extra['id'], self.extra['type'], msg), kwargs
+
+
+class Step:
+ """
+ Step represents one scripted action in a given moment,
+ each step has an order identifier, type and optionally data entry.
+ """
+ require_data = ['QUERY', 'CHECK_ANSWER', 'REPLY']
+
+ def __init__(self, node):
+ """ Initialize single scenario step. """
+ self.node = node
+ self.id = int(node.value)
+ self.type = node["/type"].value
+ self.log = StepLogger(logging.getLogger('pydnstest.scenario.Step'),
+ {'id': self.id, 'type': self.type})
+ try:
+ self.delay = int(node["/timestamp"].value)
+ except KeyError:
+ pass
+ self.data = [Entry(n) for n in node.match("/entry")]
+ self.queries = []
+ self.has_data = self.type in Step.require_data
+ self.answer = None
+ self.raw_answer = None
+ self.repeat_if_fail = 0
+ self.pause_if_fail = 0
+ self.next_if_fail = -1
+
+ # TODO Parser currently can't parse CHECK_ANSWER args, player doesn't understand them anyway
+ # if type == 'CHECK_ANSWER':
+ # for arg in extra_args:
+ # param = arg.split('=')
+ # try:
+ # if param[0] == 'REPEAT':
+ # self.repeat_if_fail = int(param[1])
+ # elif param[0] == 'PAUSE':
+ # self.pause_if_fail = float(param[1])
+ # elif param[0] == 'NEXT':
+ # self.next_if_fail = int(param[1])
+ # except Exception as e:
+ # raise Exception('step %d - wrong %s arg: %s' % (self.id, param[0], str(e)))
+
+ def __str__(self):
+ txt = '\nSTEP {i} {t}'.format(i=self.id, t=self.type)
+ if self.repeat_if_fail:
+ txt += ' REPEAT {v}'.format(v=self.repeat_if_fail)
+ elif self.pause_if_fail:
+ txt += ' PAUSE {v}'.format(v=self.pause_if_fail)
+ elif self.next_if_fail != -1:
+ txt += ' NEXT {v}'.format(v=self.next_if_fail)
+ # if self.args:
+ # txt += ' '
+ # txt += ' '.join(self.args)
+ txt += '\n'
+
+ for data in self.data:
+ # from IPython.core.debugger import Tracer
+ # Tracer()()
+ txt += str(data)
+ return txt
+
+ def play(self, ctx):
+ """ Play one step from a scenario. """
+ if self.type == 'QUERY':
+ self.log.info('')
+ self.log.debug(self.data[0].message.to_text())
+ # Parse QUERY-specific parameters
+ choice, tcp, source = None, False, None
+ return self.__query(ctx, tcp=tcp, choice=choice, source=source)
+ elif self.type == 'CHECK_OUT_QUERY': # ignore
+ self.log.info('')
+ return None
+ elif self.type == 'CHECK_ANSWER' or self.type == 'ANSWER':
+ self.log.info('')
+ return self.__check_answer(ctx)
+ elif self.type == 'TIME_PASSES ELAPSE':
+ self.log.info('')
+ return self.__time_passes()
+ elif self.type == 'REPLY' or self.type == 'MOCK':
+ self.log.info('')
+ return None
+ # Parser currently doesn't support step types LOG, REPLAY and ASSERT.
+ # No test uses them.
+ # elif self.type == 'LOG':
+ # if not ctx.log:
+ # raise Exception('scenario has no log interface')
+ # return ctx.log.match(self.args)
+ # elif self.type == 'REPLAY':
+ # self.__replay(ctx)
+ # elif self.type == 'ASSERT':
+ # self.__assert(ctx)
+ else:
+ raise NotImplementedError('step %03d type %s unsupported' % (self.id, self.type))
+
+ def __check_answer(self, ctx):
+ """ Compare answer from previously resolved query. """
+ if not self.data:
+ raise ValueError("response definition required")
+ expected = self.data[0]
+ if expected.is_raw_data_entry is True:
+ self.log.debug("raw answer: %s", ctx.last_raw_answer.to_text())
+ expected.cmp_raw(ctx.last_raw_answer)
+ else:
+ if ctx.last_answer is None:
+ raise ValueError("no answer from preceding query")
+ self.log.debug("answer: %s", ctx.last_answer.to_text())
+ expected.match(ctx.last_answer)
+
+ # def __replay(self, ctx, chunksize=8):
+ # nqueries = len(self.queries)
+ # if len(self.args) > 0 and self.args[0].isdigit():
+ # nqueries = int(self.args.pop(0))
+ # destination = ctx.client[ctx.client.keys()[0]]
+ # self.log.info('replaying %d queries to %s@%d (%s)',
+ # nqueries, destination[0], destination[1], ' '.join(self.args))
+ # if 'INTENSIFY' in os.environ:
+ # nqueries *= int(os.environ['INTENSIFY'])
+ # tstart = datetime.now()
+ # nsent, nrcvd = replay_rrs(self.queries, nqueries, destination, self.args)
+ # # Keep/print the statistics
+ # rtt = (datetime.now() - tstart).total_seconds() * 1000
+ # pps = 1000 * nrcvd / rtt
+ # self.log.debug('sent: %d, received: %d (%d ms, %d p/s)', nsent, nrcvd, rtt, pps)
+ # tag = None
+ # for arg in self.args:
+ # if arg.upper().startswith('PRINT'):
+ # _, tag = tuple(arg.split('=')) if '=' in arg else (None, 'replay')
+ # if tag:
+ # self.log.info('[ REPLAY ] test: %s pps: %5d time: %4d sent: %5d received: %5d',
+ # tag.ljust(11), pps, rtt, nsent, nrcvd)
+
+ def __query(self, ctx, tcp=False, choice=None, source=None):
+ """
+ Send query and wait for an answer (if the query is not RAW).
+
+ The received answer is stored in self.answer and ctx.last_answer.
+ """
+ if not self.data:
+ raise ValueError("query definition required")
+ if self.data[0].is_raw_data_entry is True:
+ data_to_wire = self.data[0].raw_data
+ else:
+ # Don't use a message copy as the EDNS data portion is not copied.
+ data_to_wire = self.data[0].message.to_wire()
+ if choice is None or not choice:
+ choice = list(ctx.client.keys())[0]
+ if choice not in ctx.client:
+ raise ValueError('step %03d invalid QUERY target: %s' % (self.id, choice))
+ # Create socket to test subject
+ sock = None
+ destination = ctx.client[choice]
+ family = socket.AF_INET6 if ':' in destination[0] else socket.AF_INET
+ sock = socket.socket(family, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ if tcp:
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
+ sock.settimeout(3)
+ if source:
+ sock.bind((source, 0))
+ sock.connect(destination)
+ # Send query to client and wait for response
+ tstart = datetime.now()
+ while True:
+ try:
+ sendto_msg(sock, data_to_wire)
+ break
+ except OSError as ex:
+ # ENOBUFS, throttle sending
+ if ex.errno == errno.ENOBUFS:
+ time.sleep(0.1)
+ # Wait for a response for a reasonable time
+ answer = None
+ if not self.data[0].is_raw_data_entry:
+ while True:
+ if (datetime.now() - tstart).total_seconds() > 5:
+ raise RuntimeError("Server took too long to respond")
+ try:
+ answer, _ = recvfrom_msg(sock, True)
+ break
+ except OSError as ex:
+ if ex.errno == errno.ENOBUFS:
+ time.sleep(0.1)
+ # Track RTT
+ rtt = (datetime.now() - tstart).total_seconds() * 1000
+ global g_rtt, g_nqueries
+ g_nqueries += 1
+ g_rtt += rtt
+ # Remember last answer for checking later
+ self.raw_answer = answer
+ ctx.last_raw_answer = answer
+ if self.raw_answer is not None:
+ self.answer = dns.message.from_wire(self.raw_answer, one_rr_per_rrset=True)
+ else:
+ self.answer = None
+ ctx.last_answer = self.answer
+
+ def __time_passes(self):
+ """ Modify system time. """
+ file_old = os.environ["FAKETIME_TIMESTAMP_FILE"]
+ file_next = os.environ["FAKETIME_TIMESTAMP_FILE"] + ".next"
+ with open(file_old, 'r') as time_file:
+ line = time_file.readline().strip()
+ t = time.mktime(datetime.strptime(line, '@%Y-%m-%d %H:%M:%S').timetuple())
+ t += self.delay
+ with open(file_next, 'w') as time_file:
+ time_file.write(datetime.fromtimestamp(t).strftime('@%Y-%m-%d %H:%M:%S') + "\n")
+ time_file.flush()
+ os.replace(file_next, file_old)
+
+ # def __assert(self, ctx):
+ # """ Assert that a passed expression evaluates to True. """
+ # result = eval(' '.join(self.args), {'SCENARIO': ctx, 'RANGE': ctx.ranges})
+ # # Evaluate subexpressions for clarity
+ # subexpr = []
+ # for expr in self.args:
+ # try:
+ # ee = eval(expr, {'SCENARIO': ctx, 'RANGE': ctx.ranges})
+ # subexpr.append(str(ee))
+ # except:
+ # subexpr.append(expr)
+ # assert result is True, '"%s" assertion fails (%s)' % (
+ # ' '.join(self.args), ' '.join(subexpr))
+
+
+class Scenario:
+ log = logging.getLogger('pydnstest.scenatio.Scenario')
+
+ def __init__(self, node, filename):
+ """ Initialize scenario with description. """
+ self.node = node
+ self.info = node.value
+ self.file = filename
+ self.ranges = [Range(n) for n in node.match("/range")]
+ self.current_range = None
+ self.steps = [Step(n) for n in node.match("/step")]
+ self.current_step = None
+ self.client = {}
+
+ def __str__(self):
+ txt = 'SCENARIO_BEGIN'
+ if self.info:
+ txt += ' {0}'.format(self.info)
+ txt += '\n'
+ for range_ in self.ranges:
+ txt += str(range_)
+ for step in self.steps:
+ txt += str(step)
+ txt += "\nSCENARIO_END"
+ return txt
+
+ def reply(self, query: dns.message.Message, address=None) -> Optional[DNSBlob]:
+ """Generate answer packet for given query."""
+ current_step_id = self.current_step.id
+ # Unknown address, select any match
+ # TODO: workaround until the server supports stub zones
+ all_addresses = set() # type: ignore
+ for rng in self.ranges:
+ all_addresses.update(rng.addresses)
+ if address not in all_addresses:
+ address = None
+ # Find current valid query response range
+ for rng in self.ranges:
+ if rng.eligible(current_step_id, address):
+ self.current_range = rng
+ return rng.reply(query)
+ # Find any prescripted one-shot replies
+ for step in self.steps:
+ if step.id < current_step_id or step.type != 'REPLY':
+ continue
+ try:
+ candidate = step.data[0]
+ candidate.match(query)
+ step.data.remove(candidate)
+ return candidate.reply(query)
+ except (IndexError, ValueError):
+ pass
+ return DNSReplyServfail(query)
+
+ def play(self, paddr):
+ """ Play given scenario. """
+ # Store test subject => address mapping
+ self.client = paddr
+
+ step = None
+ i = 0
+ while i < len(self.steps):
+ step = self.steps[i]
+ self.current_step = step
+ try:
+ step.play(self)
+ except ValueError as ex:
+ if step.repeat_if_fail > 0:
+ self.log.info("[play] step %d: exception - '%s', retrying step %d (%d left)",
+ step.id, ex, step.next_if_fail, step.repeat_if_fail)
+ step.repeat_if_fail -= 1
+ if step.pause_if_fail > 0:
+ time.sleep(step.pause_if_fail)
+ if step.next_if_fail != -1:
+ next_steps = [j for j in range(len(self.steps)) if self.steps[
+ j].id == step.next_if_fail]
+ if not next_steps:
+ raise ValueError('step %d: wrong NEXT value "%d"' %
+ (step.id, step.next_if_fail))
+ next_step = next_steps[0]
+ if next_step < len(self.steps):
+ i = next_step
+ else:
+ raise ValueError('step %d: Can''t branch to NEXT value "%d"' %
+ (step.id, step.next_if_fail))
+ continue
+ else:
+ raise ValueError('%s step %d %s' % (self.file, step.id, str(ex)))
+ i += 1
+
+ for r in self.ranges:
+ for e in r.stored:
+ if e.mandatory and e.fired == 0:
+ # TODO: cisla radku
+ raise ValueError('Mandatory section at %s not fired' % e.mandatory.span)
+
+
+def get_next(file_in, skip_empty=True):
+ """ Return next token from the input stream. """
+ while True:
+ line = file_in.readline()
+ if not line:
+ return False
+ quoted, escaped = False, False
+ for i, char in enumerate(line):
+ if char == '\\':
+ escaped = not escaped
+ if not escaped and char == '"':
+ quoted = not quoted
+ if char == ';' and not quoted:
+ line = line[0:i]
+ break
+ if char != '\\':
+ escaped = False
+ tokens = ' '.join(line.strip().split()).split()
+ if not tokens:
+ if skip_empty:
+ continue
+ else:
+ return '', []
+ op = tokens.pop(0)
+ return op, tokens
+
+
+def parse_config(scn_cfg, qmin, installdir): # FIXME: pylint: disable=too-many-statements
+ """
+ Transform scene config (key, value) pairs into dict filled with defaults.
+ Returns tuple:
+ context dict: {Jinja2 variable: value}
+ trust anchor dict: {domain: [TA lines for particular domain]}
+ """
+ # defaults
+ do_not_query_localhost = True
+ harden_glue = True
+ sockfamily = 0 # auto-select value for socket.getaddrinfo
+ trust_anchor_list = []
+ trust_anchor_files = {}
+ negative_ta_list = []
+ stub_addr = None
+ override_timestamp = None
+
+ features = {}
+ feature_list_delimiter = ';'
+ feature_pair_delimiter = '='
+
+ for k, v in scn_cfg:
+ # Enable selectively for some tests
+ if k == 'do-not-query-localhost':
+ do_not_query_localhost = str2bool(v)
+ elif k == 'domain-insecure':
+ negative_ta_list.append(v)
+ elif k == 'harden-glue':
+ harden_glue = str2bool(v)
+ elif k == 'query-minimization':
+ qmin = str2bool(v)
+ elif k == 'trust-anchor':
+ trust_anchor = v.strip('"\'')
+ trust_anchor_list.append(trust_anchor)
+ domain = dns.name.from_text(trust_anchor.split()[0]).canonicalize()
+ if domain not in trust_anchor_files:
+ trust_anchor_files[domain] = []
+ trust_anchor_files[domain].append(trust_anchor)
+ elif k == 'val-override-timestamp':
+ override_timestamp_str = v.strip('"\'')
+ override_timestamp = int(override_timestamp_str)
+ elif k == 'val-override-date':
+ override_date_str = v.strip('"\'')
+ ovr_yr = override_date_str[0:4]
+ ovr_mnt = override_date_str[4:6]
+ ovr_day = override_date_str[6:8]
+ ovr_hr = override_date_str[8:10]
+ ovr_min = override_date_str[10:12]
+ ovr_sec = override_date_str[12:]
+ override_date_str_arg = '{0} {1} {2} {3} {4} {5}'.format(
+ ovr_yr, ovr_mnt, ovr_day, ovr_hr, ovr_min, ovr_sec)
+ override_date = time.strptime(override_date_str_arg, "%Y %m %d %H %M %S")
+ override_timestamp = calendar.timegm(override_date)
+ elif k == 'stub-addr':
+ stub_addr = v.strip('"\'')
+ elif k == 'features':
+ feature_list = v.split(feature_list_delimiter)
+ try:
+ for f_item in feature_list:
+ if f_item.find(feature_pair_delimiter) != -1:
+ f_key, f_value = [x.strip()
+ for x
+ in f_item.split(feature_pair_delimiter, 1)]
+ else:
+ f_key = f_item.strip()
+ f_value = ""
+ features[f_key] = f_value
+ except KeyError as ex:
+ raise KeyError("can't parse features (%s) in config section (%s)" % (v, str(ex)))
+ elif k == 'feature-list':
+ try:
+ f_key, f_value = [x.strip() for x in v.split(feature_pair_delimiter, 1)]
+ if f_key not in features:
+ features[f_key] = []
+ f_value = f_value.replace("{{INSTALL_DIR}}", installdir)
+ features[f_key].append(f_value)
+ except KeyError as ex:
+ raise KeyError("can't parse feature-list (%s) in config section (%s)"
+ % (v, str(ex)))
+ elif k == 'force-ipv6' and v.upper() == 'TRUE':
+ sockfamily = socket.AF_INET6
+ else:
+ raise NotImplementedError('unsupported CONFIG key "%s"' % k)
+
+ ctx = {
+ "DO_NOT_QUERY_LOCALHOST": str(do_not_query_localhost).lower(),
+ "NEGATIVE_TRUST_ANCHORS": negative_ta_list,
+ "FEATURES": features,
+ "HARDEN_GLUE": str(harden_glue).lower(),
+ "INSTALL_DIR": installdir,
+ "QMIN": str(qmin).lower(),
+ "TRUST_ANCHORS": trust_anchor_list,
+ "TRUST_ANCHOR_FILES": trust_anchor_files.keys()
+ }
+ if stub_addr:
+ ctx['ROOT_ADDR'] = stub_addr
+ # determine and verify socket family for specified root address
+ gai = socket.getaddrinfo(stub_addr, 53, sockfamily, 0,
+ socket.IPPROTO_UDP, socket.AI_NUMERICHOST)
+ assert len(gai) == 1
+ sockfamily = gai[0][0]
+ if not sockfamily:
+ sockfamily = socket.AF_INET # default to IPv4
+ ctx['_SOCKET_FAMILY'] = sockfamily
+ if override_timestamp:
+ ctx['_OVERRIDE_TIMESTAMP'] = override_timestamp
+ return (ctx, trust_anchor_files)
+
+
+def parse_file(path):
+ """ Parse scenario from a file. """
+
+ aug = pydnstest.augwrap.AugeasWrapper(
+ confpath=path, lens='Deckard', loadpath=os.path.dirname(__file__))
+ node = aug.tree
+ config = []
+ for line in [c.value for c in node.match("/config/*")]:
+ if line:
+ if not line.startswith(';'):
+ if '#' in line:
+ line = line[0:line.index('#')]
+ # Break to key-value pairs
+ # e.g.: ['minimization', 'on']
+ kv = [x.strip() for x in line.split(':', 1)]
+ if len(kv) >= 2:
+ config.append(kv)
+ scenario = Scenario(node["/scenario"], posixpath.basename(node.path))
+ return scenario, config
diff --git a/tests/deckard/pydnstest/tests/__init__.py b/tests/deckard/pydnstest/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/deckard/pydnstest/tests/__init__.py
diff --git a/tests/deckard/pydnstest/tests/test_parse_config.py b/tests/deckard/pydnstest/tests/test_parse_config.py
new file mode 100644
index 0000000..0668760
--- /dev/null
+++ b/tests/deckard/pydnstest/tests/test_parse_config.py
@@ -0,0 +1,17 @@
+""" This is unittest file for parse methods in scenario.py """
+import os
+
+from pydnstest.scenario import parse_config
+
+
+def test_parse_config__trust_anchor():
+ """Checks if trust-anchors are separated into files according to domain."""
+ anchor1 = u'domain1.com.\t3600\tIN\tDS\t11901 7 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ anchor2 = u'domain2.net.\t3600\tIN\tDS\t59835 7 1 cccccccccccccccccccccccccccccccccccccccc'
+ anchor3 = u'domain1.com.\t3600\tIN\tDS\t11902 7 1 1111111111111111111111111111111111111111'
+ anchors = [[u'trust-anchor', u'"{}"'.format(anchor1)],
+ [u'trust-anchor', u'"{}"'.format(anchor2)],
+ [u'trust-anchor', u'"{}"'.format(anchor3)]]
+ args = (anchors, True, os.getcwd())
+ _, ta_files = parse_config(*args)
+ assert sorted(ta_files.values()) == sorted([[anchor1, anchor3], [anchor2]])
diff --git a/tests/deckard/pydnstest/tests/test_scenario.py b/tests/deckard/pydnstest/tests/test_scenario.py
new file mode 100644
index 0000000..454cb5c
--- /dev/null
+++ b/tests/deckard/pydnstest/tests/test_scenario.py
@@ -0,0 +1,55 @@
+""" This is unittest file for scenario.py """
+
+import pytest
+
+from pydnstest.scenario import Entry
+
+RCODE_FLAGS = ['NOERROR', 'FORMERR', 'SERVFAIL', 'NXDOMAIN', 'NOTIMP', 'REFUSED', 'YXDOMAIN',
+ 'YXRRSET', 'NXRRSET', 'NOTAUTH', 'NOTZONE', 'BADVERS']
+OPCODE_FLAGS = ['QUERY', 'IQUERY', 'STATUS', 'NOTIFY', 'UPDATE']
+FLAGS = ['QR', 'TC', 'AA', 'AD', 'RD', 'RA', 'CD']
+
+
+def test_entry__get_flags():
+ """Checks if all rcodes and opcodes are filtered out"""
+ expected_flags = Entry.get_flags(FLAGS)
+ for flag in RCODE_FLAGS + OPCODE_FLAGS:
+ rcode_flags = Entry.get_flags(FLAGS + [flag])
+ assert rcode_flags == expected_flags, \
+ 'Entry._get_flags does not filter out "{flag}"'.format(flag=flag)
+
+
+def test_entry__get_rcode():
+ """
+ Checks if the error is raised for multiple rcodes
+ checks if None is returned for no rcode
+ checks if flags and opcode are filtered out
+ """
+ with pytest.raises(ValueError):
+ Entry.get_rcode(RCODE_FLAGS[:2])
+
+ assert Entry.get_rcode(FLAGS) is None
+ assert Entry.get_rcode([]) is None
+
+ for rcode in RCODE_FLAGS:
+ given_rcode = Entry.get_rcode(FLAGS + OPCODE_FLAGS + [rcode])
+ assert given_rcode is not None, 'Entry.get_rcode does not recognize {rcode}'.format(
+ rcode=rcode)
+
+
+def test_entry__get_opcode():
+ """
+ Checks if the error is raised for multiple opcodes
+ checks if None is returned for no opcode
+ checks if flags and opcode are filtered out
+ """
+ with pytest.raises(ValueError):
+ Entry.get_opcode(OPCODE_FLAGS[:2])
+
+ assert Entry.get_opcode(FLAGS) is None
+ assert Entry.get_opcode([]) is None
+
+ for opcode in OPCODE_FLAGS:
+ given_rcode = Entry.get_opcode(FLAGS + RCODE_FLAGS + [opcode])
+ assert given_rcode is not None, 'Entry.get_opcode does not recognize {opcode}'.format(
+ opcode=opcode)
diff --git a/tests/deckard/pydnstest/testserver.py b/tests/deckard/pydnstest/testserver.py
new file mode 100644
index 0000000..8767644
--- /dev/null
+++ b/tests/deckard/pydnstest/testserver.py
@@ -0,0 +1,278 @@
+import argparse
+import itertools
+import logging
+import os
+import signal
+import selectors
+import socket
+import sys
+import threading
+import time
+
+import dns.message
+import dns.rdatatype
+
+from pydnstest import scenario
+
+
+class TestServer:
+ """ This simulates UDP DNS server returning scripted or mirror DNS responses. """
+
+ def __init__(self, test_scenario, root_addr, addr_family):
+ """ Initialize server instance. """
+ self.thread = None
+ self.srv_socks = []
+ self.client_socks = []
+ self.connections = []
+ self.active = False
+ self.active_lock = threading.Lock()
+ self.condition = threading.Condition()
+ self.scenario = test_scenario
+ self.addr_map = []
+ self.start_iface = 2
+ self.cur_iface = self.start_iface
+ self.kroot_local = root_addr
+ self.addr_family = addr_family
+ self.undefined_answers = 0
+
+ def __del__(self):
+ """ Cleanup after deletion. """
+ with self.active_lock:
+ active = self.active
+ if active:
+ self.stop()
+
+ def start(self, port=53):
+ """ Synchronous start """
+ with self.active_lock:
+ if self.active:
+ raise Exception('TestServer already started')
+ with self.active_lock:
+ self.active = True
+ addr, _ = self.start_srv((self.kroot_local, port), self.addr_family)
+ self.start_srv(addr, self.addr_family, socket.IPPROTO_TCP)
+ self._bind_sockets()
+
+ def stop(self):
+ """ Stop socket server operation. """
+ with self.active_lock:
+ self.active = False
+ if self.thread:
+ self.thread.join()
+ for conn in self.connections:
+ conn.close()
+ for srv_sock in self.srv_socks:
+ srv_sock.close()
+ for client_sock in self.client_socks:
+ client_sock.close()
+ self.client_socks = []
+ self.srv_socks = []
+ self.connections = []
+ self.scenario = None
+
+ def address(self):
+ """ Returns opened sockets list """
+ addrlist = []
+ for s in self.srv_socks:
+ addrlist.append(s.getsockname())
+ return addrlist
+
+ def handle_query(self, client):
+ """
+ Receive query from client socket and send an answer.
+
+ Returns:
+ True if client socket should be closed by caller
+ False if client socket should be kept open
+ """
+ log = logging.getLogger('pydnstest.testserver.handle_query')
+ server_addr = client.getsockname()[0]
+ query, client_addr = scenario.recvfrom_msg(client)
+ if query is None:
+ return False
+ log.debug('server %s received query from %s: %s', server_addr, client_addr, query)
+
+ message = self.scenario.reply(query, server_addr)
+ if not message:
+ log.debug('ignoring')
+ return True
+ elif isinstance(message, scenario.DNSReplyServfail):
+ self.undefined_answers += 1
+ self.scenario.current_step.log.error(
+ 'server %s has no response for question %s, answering with SERVFAIL',
+ server_addr,
+ '; '.join([str(rr) for rr in query.question]))
+ else:
+ log.debug('response: %s', message)
+
+ scenario.sendto_msg(client, message.to_wire(), client_addr)
+ return True
+
+ def query_io(self):
+ """ Main server process """
+ self.undefined_answers = 0
+ with self.active_lock:
+ if not self.active:
+ raise Exception("[query_io] Test server not active")
+ while True:
+ with self.condition:
+ self.condition.notify()
+ with self.active_lock:
+ if not self.active:
+ break
+ objects = self.srv_socks + self.connections
+ sel = selectors.DefaultSelector()
+ for obj in objects:
+ sel.register(obj, selectors.EVENT_READ)
+ items = sel.select(0.1)
+ for key, event in items:
+ sock = key.fileobj
+ if event & selectors.EVENT_READ:
+ if sock in self.srv_socks:
+ if sock.proto == socket.IPPROTO_TCP:
+ conn, _ = sock.accept()
+ self.connections.append(conn)
+ else:
+ self.handle_query(sock)
+ elif sock in self.connections:
+ if not self.handle_query(sock):
+ sock.close()
+ self.connections.remove(sock)
+ else:
+ raise Exception(
+ "[query_io] Socket IO internal error {}, exit"
+ .format(sock.getsockname()))
+ else:
+ raise Exception("[query_io] Socket IO error {}, exit"
+ .format(sock.getsockname()))
+
+ def start_srv(self, address, family, proto=socket.IPPROTO_UDP):
+ """ Starts listening thread if necessary """
+ assert address
+ assert address[0] # host
+ assert address[1] # port
+ assert family
+ assert proto
+ if family == socket.AF_INET6:
+ if not socket.has_ipv6:
+ raise NotImplementedError("[start_srv] IPv6 is not supported by socket {0}"
+ .format(socket))
+ elif family != socket.AF_INET:
+ raise NotImplementedError("[start_srv] unsupported protocol family {0}".format(family))
+
+ if proto == socket.IPPROTO_TCP:
+ socktype = socket.SOCK_STREAM
+ elif proto == socket.IPPROTO_UDP:
+ socktype = socket.SOCK_DGRAM
+ else:
+ raise NotImplementedError("[start_srv] unsupported protocol {0}".format(proto))
+
+ if self.thread is None:
+ self.thread = threading.Thread(target=self.query_io)
+ self.thread.start()
+ with self.condition:
+ self.condition.wait()
+
+ for srv_sock in self.srv_socks:
+ if (srv_sock.family == family
+ and srv_sock.getsockname() == address
+ and srv_sock.proto == proto):
+ return srv_sock.getsockname()
+
+ sock = socket.socket(family, socktype, proto)
+ sock.bind(address)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ if proto == socket.IPPROTO_TCP:
+ sock.listen(5)
+ self.srv_socks.append(sock)
+ sockname = sock.getsockname()
+ return sockname, proto
+
+ def _bind_sockets(self):
+ """
+ Bind test server to port 53 on all addresses referenced by test scenario.
+ """
+ # Bind to test servers
+ for r in self.scenario.ranges:
+ for addr in r.addresses:
+ family = socket.AF_INET6 if ':' in addr else socket.AF_INET
+ self.start_srv((addr, 53), family)
+
+ # Bind addresses in ad-hoc REPLYs
+ for s in self.scenario.steps:
+ if s.type == 'REPLY':
+ reply = s.data[0].message
+ for rr in itertools.chain(reply.answer,
+ reply.additional,
+ reply.question,
+ reply.authority):
+ for rd in rr:
+ if rd.rdtype == dns.rdatatype.A:
+ self.start_srv((rd.address, 53), socket.AF_INET)
+ elif rd.rdtype == dns.rdatatype.AAAA:
+ self.start_srv((rd.address, 53), socket.AF_INET6)
+
+ def play(self, subject_addr):
+ self.scenario.play({'': (subject_addr, 53)})
+
+
+def empty_test_case():
+ """
+ Return (scenario, config) pair which answers to any query on 127.0.0.10.
+ """
+ # Mirror server
+ empty_test_path = os.path.dirname(os.path.realpath(__file__)) + "/empty.rpl"
+ test_config = {'ROOT_ADDR': '127.0.0.10',
+ '_SOCKET_FAMILY': socket.AF_INET}
+ return scenario.parse_file(empty_test_path)[0], test_config
+
+
+def standalone_self_test():
+ """
+ Self-test code
+
+ Usage:
+ LD_PRELOAD=libsocket_wrapper.so SOCKET_WRAPPER_DIR=/tmp $PYTHON -m pydnstest.testserver --help
+ """
+ logging.basicConfig(level=logging.DEBUG)
+ argparser = argparse.ArgumentParser()
+ argparser.add_argument('--scenario', help='absolute path to test scenario',
+ required=False)
+ argparser.add_argument('--step', help='step # in the scenario (default: first)',
+ required=False, type=int)
+ args = argparser.parse_args()
+ if args.scenario:
+ test_scenario, test_config_text = scenario.parse_file(args.scenario)
+ test_config, _ = scenario.parse_config(test_config_text, True, os.getcwd())
+ else:
+ test_scenario, test_config = empty_test_case()
+
+ if args.step:
+ for step in test_scenario.steps:
+ if step.id == args.step:
+ test_scenario.current_step = step
+ if not test_scenario.current_step:
+ raise ValueError('step ID %s not found in scenario' % args.step)
+ else:
+ test_scenario.current_step = test_scenario.steps[0]
+
+ server = TestServer(test_scenario, test_config['ROOT_ADDR'], test_config['_SOCKET_FAMILY'])
+ server.start()
+
+ logging.info("[==========] Mirror server running at %s", server.address())
+
+ def kill(signum, frame): # pylint: disable=unused-argument
+ logging.info("[==========] Shutdown.")
+ server.stop()
+ sys.exit(128 + signum)
+
+ signal.signal(signal.SIGINT, kill)
+ signal.signal(signal.SIGTERM, kill)
+
+ while True:
+ time.sleep(0.5)
+
+
+if __name__ == '__main__':
+ # this is done to avoid creating global variables
+ standalone_self_test()
diff --git a/tests/deckard/pylintrc b/tests/deckard/pylintrc
new file mode 100644
index 0000000..62f7f28
--- /dev/null
+++ b/tests/deckard/pylintrc
@@ -0,0 +1,26 @@
+[MESSAGES CONTROL]
+
+disable=
+ missing-docstring,
+ too-few-public-methods,
+ too-many-arguments,
+ too-many-locals,
+ too-many-branches,
+ too-many-instance-attributes,
+ fixme,
+ unused-import, # checked by flake8
+ line-too-long, # checked by flake8
+ invalid-name,
+ global-statement,
+ no-else-return,
+ bad-continuation,
+
+
+[SIMILARITIES]
+min-similarity-lines=6
+ignore-comments=yes
+ignore-docstrings=yes
+ignore-imports=no
+
+[DESIGN]
+max-parents=10
diff --git a/tests/deckard/requirements.txt b/tests/deckard/requirements.txt
new file mode 100644
index 0000000..59ec275
--- /dev/null
+++ b/tests/deckard/requirements.txt
@@ -0,0 +1,7 @@
+dnspython>=1.15
+dpkt
+Jinja2>=2.8
+PyYAML
+python-augeas
+pytest>=3.4
+pytest-xdist
diff --git a/tests/deckard/rplint.py b/tests/deckard/rplint.py
new file mode 100755
index 0000000..c0aa6e9
--- /dev/null
+++ b/tests/deckard/rplint.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python3
+
+import itertools
+import os
+import sys
+from typing import Any, Callable, Iterable, Iterator, Optional, List, Union, Set # noqa
+
+import pydnstest.augwrap
+import pydnstest.matchpart
+import pydnstest.scenario
+
+Element = Union["Entry", "Step", pydnstest.scenario.Range]
+
+RCODES = {"NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED", "YXDOMAIN", "YXRRSET",
+ "NXRRSET", "NOTAUTH", "NOTZONE", "BADVERS", "BADSIG", "BADKEY", "BADTIME", "BADMODE",
+ "BADNAME", "BADALG", "BADTRUNC", "BADCOOKIE"}
+FLAGS = {"QR", "AA", "TC", "RD", "RA", "AD", "CD"}
+SECTIONS = {"question", "answer", "authority", "additional"}
+
+
+class RplintError(ValueError):
+ def __init__(self, fails):
+ msg = ""
+ for fail in fails:
+ msg += str(fail) + "\n"
+ super().__init__(msg)
+
+
+def get_line_number(file: str, char_number: int) -> int:
+ pos = 0
+ for number, line in enumerate(open(file)):
+ pos += len(line)
+ if pos >= char_number:
+ return number + 2
+ return 0
+
+
+def is_empty(iterable: Iterator[Any]) -> bool:
+ try:
+ next(iterable)
+ except StopIteration:
+ return True
+ return False
+
+
+class Entry:
+ def __init__(self, node: pydnstest.augwrap.AugeasNode) -> None:
+ self.match = {m.value for m in node.match("/match")}
+ self.adjust = {a.value for a in node.match("/adjust")}
+ self.authority = list(node.match("/section/authority/record"))
+ self.reply = {r.value for r in node.match("/reply")}
+ self.records = list(node.match("/section/*/record"))
+ self.node = node
+
+
+class Step:
+ def __init__(self, node: pydnstest.augwrap.AugeasNode) -> None:
+ self.node = node
+ self.type = node["/type"].value
+ try:
+ self.entry = Entry(node["/entry"]) # type: Optional[Entry]
+ except KeyError:
+ self.entry = None
+
+
+class RplintFail:
+ def __init__(self, test: "RplintTest",
+ element: Optional[Element] = None,
+ etc: str = "") -> None:
+ self.path = test.path
+ self.element = element # type: Optional[Element]
+ self.line = get_line_number(self.path, element.node.char if element is not None else 0)
+ self.etc = etc
+ self.check = None # type: Optional[Callable[[RplintTest], List[RplintFail]]]
+
+ def __str__(self):
+ if self.etc:
+ return "{}:{} {}: {} ({})".format(os.path.basename(self.path), self.line,
+ self.check.__name__, self.check.__doc__, self.etc)
+ return "{}:{} {}: {}".format(os.path.basename(self.path), self.line, self.check.__name__,
+ self.check.__doc__)
+
+
+class RplintTest:
+ def __init__(self, path: str) -> None:
+ aug = pydnstest.augwrap.AugeasWrapper(confpath=os.path.realpath(path),
+ lens='Deckard',
+ loadpath=os.path.join(os.path.dirname(__file__),
+ 'pydnstest'))
+ self.node = aug.tree
+ self.name = os.path.basename(path)
+ self.path = path
+
+ _, self.config = pydnstest.scenario.parse_file(os.path.realpath(path))
+ self.range_entries = [Entry(node) for node in self.node.match("/scenario/range/entry")]
+ self.steps = [Step(node) for node in self.node.match("/scenario/step")]
+ self.step_entries = [step.entry for step in self.steps if step.entry is not None]
+ self.entries = self.range_entries + self.step_entries
+
+ self.ranges = [pydnstest.scenario.Range(n) for n in self.node.match("/scenario/range")]
+
+ self.fails = None # type: Optional[List[RplintFail]]
+ self.checks = [
+ entry_more_than_one_rcode,
+ entry_no_qname_qtype_copy_query,
+ # Commented out for now until we implement selective turning off of checks
+ # entry_ns_in_authority,
+ range_overlapping_ips,
+ range_shadowing_match_rules,
+ step_check_answer_no_match,
+ step_query_match,
+ step_section_unchecked,
+ step_unchecked_match,
+ step_unchecked_rcode,
+ scenario_ad_or_rrsig_no_ta,
+ scenario_timestamp,
+ config_trust_anchor_trailing_period_missing,
+ step_duplicate_id,
+ ]
+
+ def run_checks(self) -> bool:
+ """returns True iff all tests passed"""
+ self.fails = []
+ for check in self.checks:
+ fails = check(self)
+ for fail in fails:
+ fail.check = check
+ self.fails += fails
+
+ if self.fails == []:
+ return True
+ return False
+
+ def print_fails(self) -> None:
+ if self.fails is None:
+ raise RuntimeError("Maybe you should run some test first…")
+ for fail in self.fails:
+ print(fail)
+
+
+def config_trust_anchor_trailing_period_missing(test: RplintTest) -> List[RplintFail]:
+ """Trust-anchor option in configuration contains domain without trailing period"""
+ for conf in test.config:
+ if conf[0] == "trust-anchor":
+ if conf[1].split()[0][-1] != ".":
+ return [RplintFail(test, etc=conf[1])]
+ return []
+
+
+def scenario_timestamp(test: RplintTest) -> List[RplintFail]:
+ """RRSSIG record present in test but no val-override-date or val-override-timestamp in config"""
+ rrsigs = []
+ for entry in test.entries:
+ for record in entry.records:
+ if record["/type"].value == "RRSIG":
+ rrsigs.append(RplintFail(test, entry))
+ if rrsigs:
+ for k in test.config:
+ if k[0] == "val-override-date" or k[0] == "val-override-timestamp":
+ return []
+ return rrsigs
+
+
+def entry_no_qname_qtype_copy_query(test: RplintTest) -> List[RplintFail]:
+ """ENTRY without qname and qtype in MATCH and without copy_query in ADJUST"""
+ fails = []
+ for entry in test.range_entries:
+ if "question" not in entry.match and ("qname" not in entry.match or
+ "qtype" not in entry.match):
+ if "copy_query" not in entry.adjust:
+ fails.append(RplintFail(test, entry))
+ return fails
+
+
+def entry_ns_in_authority(test: RplintTest) -> List[RplintFail]:
+ """ENTRY has authority section with NS records, consider using MATCH subdomain"""
+ fails = []
+ for entry in test.range_entries:
+ if entry.authority and "subdomain" not in entry.match:
+ for record in entry.authority:
+ if record["/type"].value == "NS":
+ fails.append(RplintFail(test, entry))
+ return fails
+
+
+def entry_more_than_one_rcode(test: RplintTest) -> List[RplintFail]:
+ """ENTRY has more than one rcode in MATCH"""
+ fails = []
+ for entry in test.entries:
+ if len(RCODES & entry.reply) > 1:
+ fails.append(RplintFail(test, entry))
+ return fails
+
+
+def scenario_ad_or_rrsig_no_ta(test: RplintTest) -> List[RplintFail]:
+ """AD or RRSIG present in test but no trust-anchor present in config"""
+ dnssec = []
+ for entry in test.entries:
+ if "AD" in entry.reply or "AD" in entry.match:
+ dnssec.append(RplintFail(test, entry))
+ else:
+ for record in entry.records:
+ if record["/type"].value == "RRSIG":
+ dnssec.append(RplintFail(test, entry))
+
+ if dnssec:
+ for k in test.config:
+ if k[0] == "trust-anchor":
+ return []
+ return dnssec
+
+
+def step_query_match(test: RplintTest) -> List[RplintFail]:
+ """STEP QUERY has a MATCH rule"""
+ return [RplintFail(test, step) for step in test.steps if step.type == "QUERY" and
+ step.entry and step.entry.match]
+
+
+def step_check_answer_no_match(test: RplintTest) -> List[RplintFail]:
+ """ENTRY in STEP CHECK_ANSWER has no MATCH rule"""
+ return [RplintFail(test, step) for step in test.steps if step.type == "CHECK_ANSWER" and
+ step.entry and not step.entry.match]
+
+
+def step_unchecked_rcode(test: RplintTest) -> List[RplintFail]:
+ """ENTRY specifies rcode but STEP MATCH does not check for it."""
+ fails = []
+ for step in test.steps:
+ if step.type == "CHECK_ANSWER" and step.entry and "all" not in step.entry.match:
+ if step.entry.reply & RCODES and "rcode" not in step.entry.match:
+ fails.append(RplintFail(test, step.entry))
+ return fails
+
+
+def step_unchecked_match(test: RplintTest) -> List[RplintFail]:
+ """ENTRY specifies flags but MATCH does not check for them"""
+ fails = []
+ for step in test.steps:
+ if step.type == "CHECK_ANSWER":
+ entry = step.entry
+ if entry and "all" not in entry.match and entry.reply - RCODES and \
+ "flags" not in entry.match:
+ fails.append(RplintFail(test, entry, str(entry.reply - RCODES)))
+ return fails
+
+
+def step_section_unchecked(test: RplintTest) -> List[RplintFail]:
+ """ENTRY has non-empty sections but MATCH does not check for all of them"""
+ fails = []
+ for step in test.steps:
+ if step.type == "CHECK_ANSWER" and step.entry and "all" not in step.entry.match:
+ for section in SECTIONS:
+ if not is_empty(step.node.match("/entry/section/" + section + "/*")):
+ if section not in step.entry.match:
+ fails.append(RplintFail(test, step.entry, section))
+ return fails
+
+
+def range_overlapping_ips(test: RplintTest) -> List[RplintFail]:
+ """RANGE has common IPs with some previous overlapping RANGE"""
+ fails = []
+ for r1, r2 in itertools.combinations(test.ranges, 2):
+ # If the ranges overlap
+ if min(r1.b, r2.b) >= max(r1.a, r2.a):
+ if r1.addresses & r2.addresses:
+ info = "previous range on line %d" % get_line_number(test.path, r1.node.char)
+ fails.append(RplintFail(test, r2, info))
+ return fails
+
+
+def range_shadowing_match_rules(test: RplintTest) -> List[RplintFail]:
+ """ENTRY has no effect since one of previous entries has the same or broader match rules"""
+ fails = []
+ for r in test.ranges:
+ for e1, e2 in itertools.combinations(r.stored, 2):
+ try:
+ e1.match(e2.message)
+ except ValueError:
+ pass
+ else:
+ info = "previous entry on line %d" % get_line_number(test.path, e1.node.char)
+ if e1.match_fields > e2.match_fields:
+ continue
+ if "subdomain" not in e1.match_fields and "subdomain" in e2.match_fields:
+ continue
+ fails.append(RplintFail(test, e2, info))
+ return fails
+
+
+def step_duplicate_id(test: RplintTest) -> List[RplintFail]:
+ """STEP has the same ID as one of previous ones"""
+ fails = []
+ step_numbers = set() # type: Set[int]
+ for step in test.steps:
+ if step.node.value in step_numbers:
+ fails.append(RplintFail(test, step))
+ else:
+ step_numbers.add(step.node.value)
+ return fails
+
+
+# TODO: This will make sense after we fix how we handle defaults in deckard.aug and scenario.py
+# We might just not use defaults altogether as testbound does
+# if "copy_id" not in adjust:
+# entry_error(test, entry, "copy_id should be in ADJUST")
+
+def test_run_rplint(rpl_path: str) -> None:
+ t = RplintTest(rpl_path)
+ passed = t.run_checks()
+ if not passed:
+ raise RplintError(t.fails)
+
+
+def main():
+ try:
+ test_path = sys.argv[1]
+ except IndexError:
+ print("usage: %s <path to rpl file>" % sys.argv[0])
+ sys.exit(2)
+ if not os.path.isfile(test_path):
+ print("rplint.py works on single file only.")
+ print("Use rplint.sh with --scenarios=<directory with rpls> to run on rpls.")
+ sys.exit(2)
+ print("Linting %s" % test_path)
+ t = RplintTest(test_path)
+ passed = t.run_checks()
+ t.print_fails()
+
+ if passed:
+ sys.exit(0)
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/deckard/rplint.sh b/tests/deckard/rplint.sh
new file mode 100755
index 0000000..ccdc435
--- /dev/null
+++ b/tests/deckard/rplint.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -x
+set -o errexit -o nounset
+MAKEDIR="$(dirname "$0")"
+python3 -m pytest -c "${MAKEDIR}/rplint_pytest.ini" ${TESTS:+"--scenarios=${TESTS}"} "$@"
diff --git a/tests/deckard/rplint_pytest.ini b/tests/deckard/rplint_pytest.ini
new file mode 100644
index 0000000..400f4ad
--- /dev/null
+++ b/tests/deckard/rplint_pytest.ini
@@ -0,0 +1,4 @@
+[pytest]
+log_print = False
+python_files=rplint.py
+norecursedirs=*
diff --git a/tests/deckard/run.sh b/tests/deckard/run.sh
new file mode 100755
index 0000000..2d1a33c
--- /dev/null
+++ b/tests/deckard/run.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+MAKEDIR="$(dirname "$0")"
+# build env.sh only if needed
+# it is handy if someone is executing run.sh in parallel
+test ! -f "${MAKEDIR}/env.sh" && make depend -C "${MAKEDIR}"
+source "${MAKEDIR}/env.sh"
+
+# compatibility with old TESTS= env variable
+# add --scenarios= only if the variable TESTS is non-empty
+python3 -m pytest -c "${MAKEDIR}/deckard_pytest.ini" --tb=short -q ${VERBOSE:+"--log-level=DEBUG"} "${MAKEDIR}" ${DECKARDFLAGS:-} ${TESTS:+"--scenarios=${TESTS}"} "$@"
diff --git a/tests/deckard/sets/knotd/master/example.com.zone b/tests/deckard/sets/knotd/master/example.com.zone
new file mode 100644
index 0000000..ee51895
--- /dev/null
+++ b/tests/deckard/sets/knotd/master/example.com.zone
@@ -0,0 +1,22 @@
+$ORIGIN example.com.
+$TTL 3600
+
+@ SOA dns1.example.com. hostmaster.example.com. (
+ 2010111213 ; serial
+ 6h ; refresh
+ 1h ; retry
+ 1w ; expire
+ 1d ) ; minimum
+
+ NS dns1
+ NS dns2
+ MX 10 mail
+
+dns1 A 192.0.2.1
+ AAAA 2001:DB8::1
+
+dns2 A 192.0.2.2
+ AAAA 2001:DB8::2
+
+mail A 192.0.2.3
+ AAAA 2001:DB8::3
diff --git a/tests/deckard/sets/knotd/master/iter_ns.rpl b/tests/deckard/sets/knotd/master/iter_ns.rpl
new file mode 100644
index 0000000..089dec1
--- /dev/null
+++ b/tests/deckard/sets/knotd/master/iter_ns.rpl
@@ -0,0 +1,28 @@
+ stub-addr: 192.0.2.10
+CONFIG_END
+
+SCENARIO_BEGIN Simple knotd query.
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com IN NS
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS dns1.example.com.
+example.com. 3600 IN NS dns2.example.com.
+SECTION ADDITIONAL
+dns1.example.com. 3600 IN A 192.0.2.1
+dns1.example.com. 3600 IN AAAA 2001:DB8::1
+dns2.example.com. 3600 IN A 192.0.2.2
+dns2.example.com. 3600 IN AAAA 2001:DB8::2
+ENTRY_END
+
diff --git a/tests/deckard/sets/knotd/slave/iter_ns.rpl b/tests/deckard/sets/knotd/slave/iter_ns.rpl
new file mode 100644
index 0000000..3015d08
--- /dev/null
+++ b/tests/deckard/sets/knotd/slave/iter_ns.rpl
@@ -0,0 +1,78 @@
+ stub-addr: 192.0.2.10
+CONFIG_END
+
+SCENARIO_BEGIN Simple knotd query.
+
+RANGE_BEGIN 0 100
+ADDRESS 192.0.2.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. 3600 IN SOA dns1.example.com. hostmaster.example.com. 2010111213 21600 3600 604800 86400
+example.com. 3600 IN NS dns1.example.com.
+example.com. 3600 IN NS dns2.example.com.
+example.com. 3600 IN MX 10 mail.example.com.
+dns1.example.com. 3600 IN A 192.0.2.1
+dns1.example.com. 3600 IN AAAA 2001:DB8::1
+dns2.example.com. 3600 IN A 192.0.2.2
+dns2.example.com. 3600 IN AAAA 2001:DB8::2
+mail.example.com. 3600 IN A 192.0.2.3
+mail.example.com. 3600 IN AAAA 2001:DB8::3
+example.com. 3600 IN SOA dns1.example.com. hostmaster.example.com. 2010111213 21600 3600 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+example.com. 3600 IN SOA dns1.example.com. hostmaster.example.com. 2010111213 21600 3600 604800 86400
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com IN SOA
+ENTRY_END
+
+STEP 20 CHECK_ANSWER REPEAT=3 PAUSE=1 NEXT=10
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+example.com IN SOA
+SECTION ANSWER
+example.com. 3600 IN SOA dns1.example.com. hostmaster.example.com. 2010111213 21600 3600 604800 86400
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com IN NS
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS dns1.example.com.
+example.com. 3600 IN NS dns2.example.com.
+SECTION ADDITIONAL
+dns1.example.com. 3600 IN A 192.0.2.1
+dns1.example.com. 3600 IN AAAA 2001:DB8::1
+dns2.example.com. 3600 IN A 192.0.2.2
+dns2.example.com. 3600 IN AAAA 2001:DB8::2
+ENTRY_END
+
diff --git a/tests/deckard/sets/resolver/LICENSE b/tests/deckard/sets/resolver/LICENSE
new file mode 100644
index 0000000..1859c09
--- /dev/null
+++ b/tests/deckard/sets/resolver/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2007, NLnet Labs. All rights reserved.
+
+This software is open source.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+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.
+
+Neither the name of the NLNET LABS 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+HOLDER 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.
diff --git a/tests/deckard/sets/resolver/black_data.rpl b/tests/deckard/sets/resolver/black_data.rpl
new file mode 100644
index 0000000..80da4e1
--- /dev/null
+++ b/tests/deckard/sets/resolver/black_data.rpl
@@ -0,0 +1,300 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 34385 7 1 32E1CF5B4E0089080FF6DDC4A48CEE63E88101D6 "
+val-override-date: "20181130121750"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with blacklist for data response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN A
+SECTION ANSWER
+ns.blabla.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+; no ns.blabla.com, try that later
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101749 20181130101749 34385 example.com. hMeEUjDsEFCHHAzHnCKeBg1j9lMvQROaOx8I0mLqMvuLWaxcjpkxNL5W J4GOZbQuAZRQSCPUpZoR6PXazY/2Iiqaa6VsHBKYlUKOMkqOJBkEs19L PCFUlTFZ8Ayv4eN6OR2BzDdHv0o38Cu6OBQul/hyEmpIX2g03aO1cpGT 3s0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101749 20181130101749 34385 example.com. F5OQnNGBxu5PjpUClx48y03pqOFnKIVYDzCdVWquRlXj3kaIDgHipesg oTs2e7cd9/P6MtSRWumr9FQNs1+L0gcfs/YIzuHBeoBH3LG5zZ4qpbs9 Z1Ay7yrxLIritwayyQnZMd9hlUFYLzNLxpL1cjMl/865r0lA3aVajmcv SYc= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcNjFHsWLbEHq/G2EjKS2pq/bGsWy6NtwBW7IcP4stnCF+a3cBpJ MZpR78GnL+YxpQYj0IyasgziAGTI/tgiTyY2qatR+6OaqebJkVbJDFx5 g0Ts1VrUk/4Z/G5tm0RMZxXxWMjjIy3wnET3Bt3dvUSI/tcTs5CUegnM MNrcMbG3 ;{id = 2854 (zsk), size = 1688b}
+; make priming query succeed
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101749 20181130101749 34385 example.com. cbYR1BnWMDItEpJqSz9L+D7XC/Zl6wnkhOA3+Z8ikZivBMfAu3OSFLWA Wu1SyiBFU+ooZ8v4/vVWN/IAkqt2CGvXeiWweiifegZEENjeAQCh8Jzw qTBf43yXwPeIpN2DpAoS+UxKbSOYhhSwBahoRefgZl7iEo3lg6TdoaOl y+U= ;{id = 2854}
+;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854}
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.blabla.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854}
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. aFxyCGziQusXsW6tz5yQdklAv+PvoEHP1cC8IkJqo9YnMcSdoFHbZALs XFlbNRl2uwPnthKOIPZf89/pXNX3o19aq4LzfPOEiOkylboTiKmgLVyi WhqYKkJtK1B9SVn/dZN4VnmSNtrcmHi5EERl/aTEM7nfIT3jG4a/ORz6 IHY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101749 20181130101749 34385 example.com. hMeEUjDsEFCHHAzHnCKeBg1j9lMvQROaOx8I0mLqMvuLWaxcjpkxNL5W J4GOZbQuAZRQSCPUpZoR6PXazY/2Iiqaa6VsHBKYlUKOMkqOJBkEs19L PCFUlTFZ8Ayv4eN6OR2BzDdHv0o38Cu6OBQul/hyEmpIX2g03aO1cpGT 3s0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.blabla.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101749 20181130101749 34385 example.com. hMeEUjDsEFCHHAzHnCKeBg1j9lMvQROaOx8I0mLqMvuLWaxcjpkxNL5W J4GOZbQuAZRQSCPUpZoR6PXazY/2Iiqaa6VsHBKYlUKOMkqOJBkEs19L PCFUlTFZ8Ayv4eN6OR2BzDdHv0o38Cu6OBQul/hyEmpIX2g03aO1cpGT 3s0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101749 20181130101749 34385 example.com. F5OQnNGBxu5PjpUClx48y03pqOFnKIVYDzCdVWquRlXj3kaIDgHipesg oTs2e7cd9/P6MtSRWumr9FQNs1+L0gcfs/YIzuHBeoBH3LG5zZ4qpbs9 Z1Ay7yrxLIritwayyQnZMd9hlUFYLzNLxpL1cjMl/865r0lA3aVajmcv SYc= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcNjFHsWLbEHq/G2EjKS2pq/bGsWy6NtwBW7IcP4stnCF+a3cBpJ MZpR78GnL+YxpQYj0IyasgziAGTI/tgiTyY2qatR+6OaqebJkVbJDFx5 g0Ts1VrUk/4Z/G5tm0RMZxXxWMjjIy3wnET3Bt3dvUSI/tcTs5CUegnM MNrcMbG3 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101749 20181130101749 34385 example.com. cbYR1BnWMDItEpJqSz9L+D7XC/Zl6wnkhOA3+Z8ikZivBMfAu3OSFLWA Wu1SyiBFU+ooZ8v4/vVWN/IAkqt2CGvXeiWweiifegZEENjeAQCh8Jzw qTBf43yXwPeIpN2DpAoS+UxKbSOYhhSwBahoRefgZl7iEo3lg6TdoaOl y+U= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101749 20181130101749 34385 example.com. hMeEUjDsEFCHHAzHnCKeBg1j9lMvQROaOx8I0mLqMvuLWaxcjpkxNL5W J4GOZbQuAZRQSCPUpZoR6PXazY/2Iiqaa6VsHBKYlUKOMkqOJBkEs19L PCFUlTFZ8Ayv4eN6OR2BzDdHv0o38Cu6OBQul/hyEmpIX2g03aO1cpGT 3s0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. GoDRZGoKPMI48wT/JYtif460cxOjvcdpRm+mjHsKQ9GrMPf3lCuWfY9H 1cB5eeo0yxUW7euIOiKgMD9zsKaafoca1VxXgRp4DaBGgEu59AQI8ot1 FRqYwKUme8v723ZcTpaW4g2e3x2MdVs5F8HtNAII+u+MbPAhNBCzy7rk GbM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101749 20181130101749 34385 example.com. hMeEUjDsEFCHHAzHnCKeBg1j9lMvQROaOx8I0mLqMvuLWaxcjpkxNL5W J4GOZbQuAZRQSCPUpZoR6PXazY/2Iiqaa6VsHBKYlUKOMkqOJBkEs19L PCFUlTFZ8Ayv4eN6OR2BzDdHv0o38Cu6OBQul/hyEmpIX2g03aO1cpGT 3s0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. aFxyCGziQusXsW6tz5yQdklAv+PvoEHP1cC8IkJqo9YnMcSdoFHbZALs XFlbNRl2uwPnthKOIPZf89/pXNX3o19aq4LzfPOEiOkylboTiKmgLVyi WhqYKkJtK1B9SVn/dZN4VnmSNtrcmHi5EERl/aTEM7nfIT3jG4a/ORz6 IHY= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101749 20181130101749 34385 example.com. aFxyCGziQusXsW6tz5yQdklAv+PvoEHP1cC8IkJqo9YnMcSdoFHbZALs XFlbNRl2uwPnthKOIPZf89/pXNX3o19aq4LzfPOEiOkylboTiKmgLVyi WhqYKkJtK1B9SVn/dZN4VnmSNtrcmHi5EERl/aTEM7nfIT3jG4a/ORz6 IHY= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; remove pending ns.blabla.com AAAA msg
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA DO NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/black_dnskey.rpl b/tests/deckard/sets/resolver/black_dnskey.rpl
new file mode 100644
index 0000000..ae91109
--- /dev/null
+++ b/tests/deckard/sets/resolver/black_dnskey.rpl
@@ -0,0 +1,508 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 62867 7 1 FD75C8B653BF8FECB755D16AC0DF400B33043881 "
+val-override-date: "20181130121751"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with blacklist for DNSKEY response
+; DNSKEY not for prime but further down the chain of trust
+; data response also needs a blacklist action.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN A
+SECTION ANSWER
+ns.blabla.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.foo.com. IN A
+SECTION ANSWER
+ns.foo.com. IN A 1.2.4.7
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.foo.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+; no ns.blabla.com, try that later
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101751 20181130101751 62867 example.com. l15h4pHl98ot8mRBklpnoFYwYmqmoz/iWC/tS8q0bkurxZivPdmvt63C DjHpH8vv36fnO0s89btfC3eIBnDX5miuaiLbxqINmxpxDYgy3/TN+DWT VfjiWAPfaFkfwedx8oHHWwO0O7DEjrnbaqTI+5BJW7LOVYSMLNx7nFjg 490= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101751 20181130101751 62867 example.com. RHlNZwaJDQlK7ptDtIq0/V+QBXNIv0F5NTYnJoxDRmUdE3dMqsTxS6jC RIV6U2T609yLL+6elv4WtkLyfSVLlN/DO1TAPzPeWstx5VHvPS3beBn7 0FmcTWvj7vEJlmVfQEn8KeEDsOrThvBCgGjHJ/ottlz0VCL4KHJQfqXx ewA= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdMz5YCS6AnlK5Id93IA0wp8aFVHsecJNWYjPNOIdN1G0FufP8z7 yVfdWef/Lmj7VzrpHq9a+HlJ1396SCr6FYbm4Wg0nx4KxF4/dXKpIRYw HWdQiwxAu/bqixy1Yklz1HaljKenSQxEsy0dbRv+GQM65whuNui0Uk/D P1bgZsW9 ;{id = 2854 (zsk), size = 1688b}
+; make priming query succeed
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101751 20181130101751 62867 example.com. wSoXZPx8cm7DDDLM8cN7Guzh3kSSCkVgmhBSNzs9kPT/fOfz8nUyeBaf saOeU19aPuSKWFxLKiUCxy1Nwtcyax6HIeYgDVBsZ0iNxV5SD6znoJlY f/vLg/43c3e/CLSSCuWM/4DA9fZNyBrthX7BgcZdnHY5D9TVsTAskp4b 97w= ;{id = 2854}
+;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854}
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.blabla.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854}
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. byNMYNt2pVPZe/Or/iLKGuxmkYlSzh2T+zq2SUMbgDKBgAXQGeZaYHIm ypvZzbmxGtXJfFK0vT1VexagQasf8WSGbZD5O3B8oSDuQ+0Dos9JYRBp q16dhOU+rGgBaBDPfF1WNP2V9kmMRkYOP+3MhxRyynywzIrlu+uMb5sw EOI= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101751 20181130101751 62867 example.com. l15h4pHl98ot8mRBklpnoFYwYmqmoz/iWC/tS8q0bkurxZivPdmvt63C DjHpH8vv36fnO0s89btfC3eIBnDX5miuaiLbxqINmxpxDYgy3/TN+DWT VfjiWAPfaFkfwedx8oHHWwO0O7DEjrnbaqTI+5BJW7LOVYSMLNx7nFjg 490= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 12981 5 1 626AD6C14D2BE93B5EDF1C8A2FFCBC5447666CF3
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101751 20181130101751 62867 example.com. bwKyS7x0t/By9YxMmwnJSIkMZEYQu7MPW4MmIZqB6/2amawL0r16mBKe fhuamuH2CdYvzoSdYqjk4+8xZ9YyhzLI4Fmd4nE2XznoCDc+/GG4QH4R eH3e+GEXtyRnmZgANk845pYYJ2n4TcE3F3OwG7AIP6ol8I8k17g9RfGT w2I= ;{id = 2854}
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN DS 12981 5 1 626AD6C14D2BE93B5EDF1C8A2FFCBC5447666CF3
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101751 20181130101751 62867 example.com. bwKyS7x0t/By9YxMmwnJSIkMZEYQu7MPW4MmIZqB6/2amawL0r16mBKe fhuamuH2CdYvzoSdYqjk4+8xZ9YyhzLI4Fmd4nE2XznoCDc+/GG4QH4R eH3e+GEXtyRnmZgANk845pYYJ2n4TcE3F3OwG7AIP6ol8I8k17g9RfGT w2I= ;{id = 2854}
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.blabla.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101751 20181130101751 62867 example.com. l15h4pHl98ot8mRBklpnoFYwYmqmoz/iWC/tS8q0bkurxZivPdmvt63C DjHpH8vv36fnO0s89btfC3eIBnDX5miuaiLbxqINmxpxDYgy3/TN+DWT VfjiWAPfaFkfwedx8oHHWwO0O7DEjrnbaqTI+5BJW7LOVYSMLNx7nFjg 490= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101751 20181130101751 62867 example.com. RHlNZwaJDQlK7ptDtIq0/V+QBXNIv0F5NTYnJoxDRmUdE3dMqsTxS6jC RIV6U2T609yLL+6elv4WtkLyfSVLlN/DO1TAPzPeWstx5VHvPS3beBn7 0FmcTWvj7vEJlmVfQEn8KeEDsOrThvBCgGjHJ/ottlz0VCL4KHJQfqXx ewA= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdMz5YCS6AnlK5Id93IA0wp8aFVHsecJNWYjPNOIdN1G0FufP8z7 yVfdWef/Lmj7VzrpHq9a+HlJ1396SCr6FYbm4Wg0nx4KxF4/dXKpIRYw HWdQiwxAu/bqixy1Yklz1HaljKenSQxEsy0dbRv+GQM65whuNui0Uk/D P1bgZsW9 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101751 20181130101751 62867 example.com. wSoXZPx8cm7DDDLM8cN7Guzh3kSSCkVgmhBSNzs9kPT/fOfz8nUyeBaf saOeU19aPuSKWFxLKiUCxy1Nwtcyax6HIeYgDVBsZ0iNxV5SD6znoJlY f/vLg/43c3e/CLSSCuWM/4DA9fZNyBrthX7BgcZdnHY5D9TVsTAskp4b 97w= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101751 20181130101751 62867 example.com. l15h4pHl98ot8mRBklpnoFYwYmqmoz/iWC/tS8q0bkurxZivPdmvt63C DjHpH8vv36fnO0s89btfC3eIBnDX5miuaiLbxqINmxpxDYgy3/TN+DWT VfjiWAPfaFkfwedx8oHHWwO0O7DEjrnbaqTI+5BJW7LOVYSMLNx7nFjg 490= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. nJSkzyA17he6wGm7+lLbzVsblvW+zsWx5LctUfEeHOkaJ6YqvrZ2yuKl ePHbVN5yO5czQEHa8arTAhh6lSZNFAz1QijkCX/HW8VHzQgUnCjncAvE nf6ab3vVx25Ggr5E3TqJnyH62AP0qZbTZfc3dBYT1F9tQC5LUebW8Xes EBU= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101751 20181130101751 62867 example.com. l15h4pHl98ot8mRBklpnoFYwYmqmoz/iWC/tS8q0bkurxZivPdmvt63C DjHpH8vv36fnO0s89btfC3eIBnDX5miuaiLbxqINmxpxDYgy3/TN+DWT VfjiWAPfaFkfwedx8oHHWwO0O7DEjrnbaqTI+5BJW7LOVYSMLNx7nFjg 490= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101751 20181130101751 62867 example.com. byNMYNt2pVPZe/Or/iLKGuxmkYlSzh2T+zq2SUMbgDKBgAXQGeZaYHIm ypvZzbmxGtXJfFK0vT1VexagQasf8WSGbZD5O3B8oSDuQ+0Dos9JYRBp q16dhOU+rGgBaBDPfF1WNP2V9kmMRkYOP+3MhxRyynywzIrlu+uMb5sw EOI= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 12981 5 1 626AD6C14D2BE93B5EDF1C8A2FFCBC5447666CF3
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101751 20181130101751 62867 example.com. bwKyS7x0t/By9YxMmwnJSIkMZEYQu7MPW4MmIZqB6/2amawL0r16mBKe fhuamuH2CdYvzoSdYqjk4+8xZ9YyhzLI4Fmd4nE2XznoCDc+/GG4QH4R eH3e+GEXtyRnmZgANk845pYYJ2n4TcE3F3OwG7AIP6ol8I8k17g9RfGT w2I= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN DS 12981 5 1 626AD6C14D2BE93B5EDF1C8A2FFCBC5447666CF3
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101751 20181130101751 62867 example.com. bwKyS7x0t/By9YxMmwnJSIkMZEYQu7MPW4MmIZqB6/2amawL0r16mBKe fhuamuH2CdYvzoSdYqjk4+8xZ9YyhzLI4Fmd4nE2XznoCDc+/GG4QH4R eH3e+GEXtyRnmZgANk845pYYJ2n4TcE3F3OwG7AIP6ol8I8k17g9RfGT w2I= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.4.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAbrzxhWzLVhOSmsCj1rysaYFaF6NLfPmXdhjppCOzDb2LxQUZ5tE yiTKViI/ZUSMDKKLk1IdDGpIniYzx3vrUQ7KzA+p8p/XR3qvD8T496Us mdAB/8Dflk5mK36kRCBp5GEKI+yz1R5Z5VolpZFnIuRLB/hXJlt7EzDz zcFMIgzT ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. piLZqA+rmQur/BRNwZ5dVdqehHNP4Egt16bO/qdYL7UE/GRfwWWImAKQ Z924Lmk7qrZfF8+a16+R6YgVQJoUX+qqVNSdjTyC4NT0IKx82qdamZSZ dTVktU5cCeE5A1WhXQHq4zcwO+EQaCyOEUf+X+wMtYkGQBjpcWP5rui8 KPM= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. YVs4zyrUqmkkbSsCNDKsisAfl4+R/0Ozg8kLqlWjwkd7QTcfu4WsOZUk johg9ESaatO13/isxiqa3W2dD6W+68LnxSflkppanaMBZYRfMmiFf3Fr u3tf4cNFk7KoGt7WL4svoeW8qnkxyKZk16ro6whu6RGO7tpv+mXrIvLZ /1A= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. nhOqrjoDipjtxEH1NcbqQ9whB09kjjWlrYPNoRx9M1Es7x67D5JLvLdP MaCo//BnF9COEXFwlAq/Gg+MJ2I7ge7b+kJMYFxoSUSg+6zD8pP5RuOv 6wxdc+OtTuB/zY3qNpwQZPGhJC5ruBRFQuPsX8JXJXwHAadZcQ3KX+Vq xQc= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN A
+SECTION ANSWER
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. nhOqrjoDipjtxEH1NcbqQ9whB09kjjWlrYPNoRx9M1Es7x67D5JLvLdP MaCo//BnF9COEXFwlAq/Gg+MJ2I7ge7b+kJMYFxoSUSg+6zD8pP5RuOv 6wxdc+OtTuB/zY3qNpwQZPGhJC5ruBRFQuPsX8JXJXwHAadZcQ3KX+Vq xQc= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION AUTHORITY
+ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A
+ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 5 20181230101751 20181130101751 12981 sub.example.com. ESWHtKvRk0CTvXrjV0AGQ0GM3ygY020B+A4GrVPsZa6DwqnTCff13R1M SQ8u+yl71YPh+5HFMbIOFdYoPMSPvU3FyOCwPK/4Mo0z86QT5nkjx6X3 T4YLX+LRfLJ+sqJtRIyA7Mjg7xIratVCa+RYrxbYbXHwSkBScQDKdew9 g5E= ;{id = 30899}
+sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5
+sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. HGuneHQjhKCum7m/PdpryrXY4ASNLfnZS38i+CnJXopIY8CWfaRDeU/k fpj9cBRzGafJAbef4ePxLqTNgWsmzQPZaIFsVIu/vjTMj5JVYmHYcvk/ SyAcQzGV4iqes/8T9z7iQTpDbWH3bD8vZdccdTRAfWi1Tl6t4+phCYVj lAI= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.20.30.40
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. YYrHYSUaXA+cM1tLnfVLmVuZPugapKRSUYG/DrYzm0UQ08nuvptESpcz 6ZAP5DP9oPuoHiwPd+rvdwOtX3dWj1BfPDQ0RfAlkHMPXR2Sez3p5kI7 XNuo/FDMs337F52eij9iWSDTzgzeeBusqJPfJMRwao1THKAmDbFsvTne qpQ= ;{id = 30899}
+ENTRY_END
+
+RANGE_END
+
+; ns.foo.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.4.7
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAbrzxhWzLVhOSmsCj1rysaYFaF6NLfPmXdhjppCOzDb2LxQUZ5tE yiTKViI/ZUSMDKKLk1IdDGpIniYzx3vrUQ7KzA+p8p/XR3qvD8T496Us mdAB/8Dflk5mK36kRCBp5GEKI+yz1R5Z5VolpZFnIuRLB/hXJlt7EzDz zcFMIgzT ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. piLZqA+rmQur/BRNwZ5dVdqehHNP4Egt16bO/qdYL7UE/GRfwWWImAKQ Z924Lmk7qrZfF8+a16+R6YgVQJoUX+qqVNSdjTyC4NT0IKx82qdamZSZ dTVktU5cCeE5A1WhXQHq4zcwO+EQaCyOEUf+X+wMtYkGQBjpcWP5rui8 KPM= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. YVs4zyrUqmkkbSsCNDKsisAfl4+R/0Ozg8kLqlWjwkd7QTcfu4WsOZUk johg9ESaatO13/isxiqa3W2dD6W+68LnxSflkppanaMBZYRfMmiFf3Fr u3tf4cNFk7KoGt7WL4svoeW8qnkxyKZk16ro6whu6RGO7tpv+mXrIvLZ /1A= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. nhOqrjoDipjtxEH1NcbqQ9whB09kjjWlrYPNoRx9M1Es7x67D5JLvLdP MaCo//BnF9COEXFwlAq/Gg+MJ2I7ge7b+kJMYFxoSUSg+6zD8pP5RuOv 6wxdc+OtTuB/zY3qNpwQZPGhJC5ruBRFQuPsX8JXJXwHAadZcQ3KX+Vq xQc= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN A
+SECTION ANSWER
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. nhOqrjoDipjtxEH1NcbqQ9whB09kjjWlrYPNoRx9M1Es7x67D5JLvLdP MaCo//BnF9COEXFwlAq/Gg+MJ2I7ge7b+kJMYFxoSUSg+6zD8pP5RuOv 6wxdc+OtTuB/zY3qNpwQZPGhJC5ruBRFQuPsX8JXJXwHAadZcQ3KX+Vq xQc= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION AUTHORITY
+ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A
+ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 5 20181230101751 20181130101751 12981 sub.example.com. ESWHtKvRk0CTvXrjV0AGQ0GM3ygY020B+A4GrVPsZa6DwqnTCff13R1M SQ8u+yl71YPh+5HFMbIOFdYoPMSPvU3FyOCwPK/4Mo0z86QT5nkjx6X3 T4YLX+LRfLJ+sqJtRIyA7Mjg7xIratVCa+RYrxbYbXHwSkBScQDKdew9 g5E= ;{id = 30899}
+sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5
+sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20181230101751 20181130101751 12981 sub.example.com. HGuneHQjhKCum7m/PdpryrXY4ASNLfnZS38i+CnJXopIY8CWfaRDeU/k fpj9cBRzGafJAbef4ePxLqTNgWsmzQPZaIFsVIu/vjTMj5JVYmHYcvk/ SyAcQzGV4iqes/8T9z7iQTpDbWH3bD8vZdccdTRAfWi1Tl6t4+phCYVj lAI= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.20.30.40
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. YYrHYSUaXA+cM1tLnfVLmVuZPugapKRSUYG/DrYzm0UQ08nuvptESpcz 6ZAP5DP9oPuoHiwPd+rvdwOtX3dWj1BfPDQ0RfAlkHMPXR2Sez3p5kI7 XNuo/FDMs337F52eij9iWSDTzgzeeBusqJPfJMRwao1THKAmDbFsvTne qpQ= ;{id = 30899}
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.20.30.40
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101751 20181130101751 12981 sub.example.com. YYrHYSUaXA+cM1tLnfVLmVuZPugapKRSUYG/DrYzm0UQ08nuvptESpcz 6ZAP5DP9oPuoHiwPd+rvdwOtX3dWj1BfPDQ0RfAlkHMPXR2Sez3p5kI7 XNuo/FDMs337F52eij9iWSDTzgzeeBusqJPfJMRwao1THKAmDbFsvTne qpQ= ;{id = 30899}
+ENTRY_END
+
+; remove pending ns.blabla.com AAAA msg
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA DO NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/black_ds.rpl b/tests/deckard/sets/resolver/black_ds.rpl
new file mode 100644
index 0000000..978cb23
--- /dev/null
+++ b/tests/deckard/sets/resolver/black_ds.rpl
@@ -0,0 +1,418 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 14258 7 1 302A703D2FFDA8133175342B41DCA895E435127E "
+val-override-date: "20181130121755"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with blacklist for DS response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN A
+SECTION ANSWER
+ns.blabla.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+; no ns.blabla.com, try that later
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101755 20181130101755 14258 example.com. TNep4HmQC9pyzvYZmfK3dtYLZ1wsDoVp9IuIe+Wsg94hQLWoVOnWCka1 u5KkOHalzUtwKA8bhO9PxViMkuxJzzUFNmuKVA+bZHi1wCvD5jgkC1Lq YN+ZKno6BS3LIQb9DoEHsgwuTz96K18+dXw8An9SAL2ovo+1UCb8p576 jY4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101755 20181130101755 14258 example.com. MdF5+Lt55oT5mRBOVu3pgdzPpDcXGj/B1OmH/ZKM+M/PavxyoI74HUXX 2MJUaa4D0T2t5EuvFnie54ts6+yQbOqqVAw7/0wEDjnG0x7AyGMocsI9 sncRGe5cF4DAidhLaXUjEh7isWTaMK4x7CZUMSSgQCM1iBnhzh78XIBy aEo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAat4hP1sUv+0zcKCDkb0Bj2Lg4irrLl884ks+sFXcdS9lwFIsWoD C4i91QW1AQk6/ajuxJ5fqUT0GRiQAlmsqmFFnPpUtpf2YAQh3Scfe1dg xhluZjUQfrjKpob0vwqcZK9gbMfPjygdZSkgdhOga7Ru0vQKCTj+lfTg jIwNsQgX ;{id = 2854 (zsk), size = 1688b}
+; make priming query succeed
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101755 20181130101755 14258 example.com. ZeB6Y/3u/MPCxdJmrn5A5/JN0/z5ueHGXJsi9/EBe43o9TN+/CotY4Lu 9/4t45Sb3qmpJyW8Y5Jch267TUTuFe++hfaYXO3ytBRmHgaFinoDg0ca MXPdYUa1RqL2NGHCZmBnQbSuL/9wWAk1KEpKpugNlhPM4iGfbulzR0FK CMg= ;{id = 2854}
+;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854}
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.blabla.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854}
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. OIh7nTI2GlTjlgoOmmH3XWO69HN9yK61kg9JS3oFNJcWhTUolF/YwFTV 4NL3xYixn2XVRh7YppvYqviK8C5fxP8kYnNn2gijdWC19bTqbjON/d7f n79Fj6yHjQWftVVIclF+d2o7yDhjwPwtsako8FMbeYFcQ+QdSMTvLw8D czE= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101755 20181130101755 14258 example.com. TNep4HmQC9pyzvYZmfK3dtYLZ1wsDoVp9IuIe+Wsg94hQLWoVOnWCka1 u5KkOHalzUtwKA8bhO9PxViMkuxJzzUFNmuKVA+bZHi1wCvD5jgkC1Lq YN+ZKno6BS3LIQb9DoEHsgwuTz96K18+dXw8An9SAL2ovo+1UCb8p576 jY4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 34461 5 1 40F060ED2F80CC6C1D7DC32A7A8926D15E2F96C7
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101755 20181130101755 14258 example.com. Mf7vpHZblSANjCrSIUHXdZ4a8gKy8OXu7TQH9r/CSJ5y01ha9IMgHwEt i5bmQRTPAZjp0DsmFQZAyqW6zu9HXI4o/dtvg1kqNJnQQoGmlKv87OG6 +yVuydaRudH17v9ETVxlaGg+qdYdN+RtlpDcfb5VQvUMXX4xT01gVLtc wLY= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN DS 34461 5 1 40F060ED2F80CC6C1D7DC32A7A8926D15E2F96C7
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101755 20181130101755 14258 example.com. Mf7vpHZblSANjCrSIUHXdZ4a8gKy8OXu7TQH9r/CSJ5y01ha9IMgHwEt i5bmQRTPAZjp0DsmFQZAyqW6zu9HXI4o/dtvg1kqNJnQQoGmlKv87OG6 +yVuydaRudH17v9ETVxlaGg+qdYdN+RtlpDcfb5VQvUMXX4xT01gVLtc wLY= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.blabla.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101755 20181130101755 14258 example.com. TNep4HmQC9pyzvYZmfK3dtYLZ1wsDoVp9IuIe+Wsg94hQLWoVOnWCka1 u5KkOHalzUtwKA8bhO9PxViMkuxJzzUFNmuKVA+bZHi1wCvD5jgkC1Lq YN+ZKno6BS3LIQb9DoEHsgwuTz96K18+dXw8An9SAL2ovo+1UCb8p576 jY4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101755 20181130101755 14258 example.com. MdF5+Lt55oT5mRBOVu3pgdzPpDcXGj/B1OmH/ZKM+M/PavxyoI74HUXX 2MJUaa4D0T2t5EuvFnie54ts6+yQbOqqVAw7/0wEDjnG0x7AyGMocsI9 sncRGe5cF4DAidhLaXUjEh7isWTaMK4x7CZUMSSgQCM1iBnhzh78XIBy aEo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAat4hP1sUv+0zcKCDkb0Bj2Lg4irrLl884ks+sFXcdS9lwFIsWoD C4i91QW1AQk6/ajuxJ5fqUT0GRiQAlmsqmFFnPpUtpf2YAQh3Scfe1dg xhluZjUQfrjKpob0vwqcZK9gbMfPjygdZSkgdhOga7Ru0vQKCTj+lfTg jIwNsQgX ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101755 20181130101755 14258 example.com. ZeB6Y/3u/MPCxdJmrn5A5/JN0/z5ueHGXJsi9/EBe43o9TN+/CotY4Lu 9/4t45Sb3qmpJyW8Y5Jch267TUTuFe++hfaYXO3ytBRmHgaFinoDg0ca MXPdYUa1RqL2NGHCZmBnQbSuL/9wWAk1KEpKpugNlhPM4iGfbulzR0FK CMg= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101755 20181130101755 14258 example.com. TNep4HmQC9pyzvYZmfK3dtYLZ1wsDoVp9IuIe+Wsg94hQLWoVOnWCka1 u5KkOHalzUtwKA8bhO9PxViMkuxJzzUFNmuKVA+bZHi1wCvD5jgkC1Lq YN+ZKno6BS3LIQb9DoEHsgwuTz96K18+dXw8An9SAL2ovo+1UCb8p576 jY4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. IwIqfkUTC6i4BvdOLg51xRwq6PBThrC54g5XrEAizTg9H7w55qbEes/9 +ojie/elleI3WydgCNbSFC4Ax/4wsmOF4RwN0qbG0s38FHZVtuI5PANs QB40JZJftnaW2KVSyr5WiwyaRJFsootBULdUF3XjGG89oo+EF7gnm2Tz GhI= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101755 20181130101755 14258 example.com. TNep4HmQC9pyzvYZmfK3dtYLZ1wsDoVp9IuIe+Wsg94hQLWoVOnWCka1 u5KkOHalzUtwKA8bhO9PxViMkuxJzzUFNmuKVA+bZHi1wCvD5jgkC1Lq YN+ZKno6BS3LIQb9DoEHsgwuTz96K18+dXw8An9SAL2ovo+1UCb8p576 jY4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101755 20181130101755 14258 example.com. OIh7nTI2GlTjlgoOmmH3XWO69HN9yK61kg9JS3oFNJcWhTUolF/YwFTV 4NL3xYixn2XVRh7YppvYqviK8C5fxP8kYnNn2gijdWC19bTqbjON/d7f n79Fj6yHjQWftVVIclF+d2o7yDhjwPwtsako8FMbeYFcQ+QdSMTvLw8D czE= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 34461 5 1 40F060ED2F80CC6C1D7DC32A7A8926D15E2F96C7
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101755 20181130101755 14258 example.com. Mf7vpHZblSANjCrSIUHXdZ4a8gKy8OXu7TQH9r/CSJ5y01ha9IMgHwEt i5bmQRTPAZjp0DsmFQZAyqW6zu9HXI4o/dtvg1kqNJnQQoGmlKv87OG6 +yVuydaRudH17v9ETVxlaGg+qdYdN+RtlpDcfb5VQvUMXX4xT01gVLtc wLY= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN DS 34461 5 1 40F060ED2F80CC6C1D7DC32A7A8926D15E2F96C7
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101755 20181130101755 14258 example.com. Mf7vpHZblSANjCrSIUHXdZ4a8gKy8OXu7TQH9r/CSJ5y01ha9IMgHwEt i5bmQRTPAZjp0DsmFQZAyqW6zu9HXI4o/dtvg1kqNJnQQoGmlKv87OG6 +yVuydaRudH17v9ETVxlaGg+qdYdN+RtlpDcfb5VQvUMXX4xT01gVLtc wLY= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.4.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAcJc2r+SCY+fkRzchGj7gEfuutF+Gwt7H0/4EnOKxIwlf0LthG7p 9xyHAuEGFN9aSkVyg0S/edWEODCGL583yRXnaJ6Ryc90H1SfSX1Wytdd XrBENgFI/B2vf4IZxm4tutwJwvMh8CXhMIGGhRzROIwijNB+eABCKu6z duD8nxL1 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101754 20181130101754 34461 sub.example.com. CbEKDlQCkG0clRptCLxKpUt6yiydTYdLmjwocdAcJOZ2MMI0joFuyPvV 89+l5xzSsvhA9CLLD5COcIhymMUtNLqF87GmnvtN/NSBTSQoOA+Ujr7t 3zp0FOWNasL/xIuORU7HBZvXq9saCjwnuRckXCouTop01Fr25ht+jYfj A6o= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.foo.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101754 20181130101754 34461 sub.example.com. hZbI8UiV3LAHw6Rchr6vYqHkuURNG7fAzlQAvxxdqyHQKNd1EUZwPulE knjiklD+Ke5kk4PEWQaWlmBlfmhOkYA3bdLeDKIMi9jsVTPLAwUmPZOV uAMbvnrEvnqdxTHNRgtwoDD/20mMJqaNEmGLayc1Yf5zmOMQQ+m68DGx Ths= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101754 20181130101754 34461 sub.example.com. J48RT+8rS2wShNJabUbeeKSsXi7v808iOwI0UQbAGg4QXzKIgDZR32dy ClKPkSAId20AfrGotJWz1kJyUAH7EDD9BVpX7PlF5BKfTJD0VRmBu+FF BSarqtziyTaNRsQwzgf74Gj2xRQmEfiGwLSyX1SXNC1sl4Wv+tGnH8M1 VOU= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN A
+SECTION ANSWER
+ns.sub.example.com. IN A 1.2.4.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101754 20181130101754 34461 sub.example.com. J48RT+8rS2wShNJabUbeeKSsXi7v808iOwI0UQbAGg4QXzKIgDZR32dy ClKPkSAId20AfrGotJWz1kJyUAH7EDD9BVpX7PlF5BKfTJD0VRmBu+FF BSarqtziyTaNRsQwzgf74Gj2xRQmEfiGwLSyX1SXNC1sl4Wv+tGnH8M1 VOU= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION AUTHORITY
+ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A
+ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 5 20181230101754 20181130101754 34461 sub.example.com. Jsa5cpk3YApRVWatd1d3E7g6Rh1iqyxw8IzY9hBX5HkxBm0gaRZ0B7F3 np27mEtQi7Ca7dYzjhMAPJtki5AwFhG9TQq3nEm9mhFQy4M5JdqnKcPX uIy7QZAhlBgg3EiFlMER/VHWWTGie1aOdS11EW9uAoLP3jGxRuVod9YK Vno= ;{id = 30899}
+sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5
+sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20181230101754 20181130101754 34461 sub.example.com. gRW+r5SnhDYodC44XwY0qc4M5AV7f2UsX0BMdxnBc6BOoo/TwmWfY1YU TCf50YQMfE/aoRrFpnzy/IMFHzgzWiWMBYgQ07jZFaYaT21JV90orXnA PEmAQ7BTwnvEA7kM6uNAYVYJeE5sh0/ILZ+HpCVh+oHC3GX2BCcEUK4p F0o= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.20.30.40
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101754 20181130101754 34461 sub.example.com. vKBtMjGLMImbm4KKVDbVeiShF7NWxnoSKKVEefhpH7x/sG8xKK2v3LYV Fc0KX+kPTYrXJCEQiwMPNqH4YdldjH3OEVP5C1oOIx3EoB+nRwFIHBxu JjoS/7XV/tdDqJ17FIOCDsARmWbLz6tJteFwRZyLvaozVNDl0z8VHAQB 7cE= ;{id = 30899}
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.20.30.40
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101754 20181130101754 34461 sub.example.com. vKBtMjGLMImbm4KKVDbVeiShF7NWxnoSKKVEefhpH7x/sG8xKK2v3LYV Fc0KX+kPTYrXJCEQiwMPNqH4YdldjH3OEVP5C1oOIx3EoB+nRwFIHBxu JjoS/7XV/tdDqJ17FIOCDsARmWbLz6tJteFwRZyLvaozVNDl0z8VHAQB 7cE= ;{id = 30899}
+ENTRY_END
+
+; remove pending ns.blabla.com AAAA msg
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA DO NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/black_ent.rpl b/tests/deckard/sets/resolver/black_ent.rpl
new file mode 100644
index 0000000..05d9d58
--- /dev/null
+++ b/tests/deckard/sets/resolver/black_ent.rpl
@@ -0,0 +1,451 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 5459 7 1 40E1D493C25150C341D3AB775BCF908C857DDF7D "
+val-override-date: "20181130121757"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with blacklist for ENT response
+; 'ENT' Empty Non Terminal
+; which needs a valid NSEC(3) proof.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN A
+SECTION ANSWER
+ns.blabla.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+; no ns.blabla.com, try that later
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101756 20181130101756 5459 example.com. MGpbBGEQk6CQ0GBHNByUfF9s7kXOl2Qflh74erA5oFkrlK0/fJFRAkMb Edgmrs4FjvrlJJ1Gi5BWqv0avoyPUWVhwYz15VhjJjXP6jLuVn1j/EnT J5t55UU6hGf2R9NHvLRdeebJDOMryVW+1r9UWQYuabdCkxtnT+xcw9Or nDs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101756 20181130101756 5459 example.com. WM9C+vSGlYtmk/wVLfWyqGwo4vbo8fGaD7DoGnJGFpICmoM8v7mcs4Pd UyZv9CPBMy9gYNM1wWcNVofQu2IC5gUgEpkuhluJji5BeocqOGzIuHW+ AVIHJjN4m9z12swsCrAq71vO+UEfWqPO4JOu40vVkSsDiaINYd8FRWkr yfg= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAaQAmPhsPdOjFE6SGc95hYvPxUHoNkUetYpu81j7j9WXUsvn8Y6M DrHOnLrVd9uV7+1Aj2nkLY+6BvLxsPcp3yBO7UPB6Mv1ZfYCP0D7qCcs Jg6NjLWD5+2owvglTk7XveTztZLFIgDGo2sxZ4/wKE2fhsmh6/Hn7GiW ySEwHURb ;{id = 2854 (zsk), size = 1688b}
+; make priming query succeed
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101756 20181130101756 5459 example.com. Pfl3n2c2oppL26sSLAFSTTkOken2ZlU+bJwpH3ipCz6BTCIm8zHjk/u7 IPyX6RiKEgVwUKEoNIXSYxkZg4Q2OHOINwRhARgQR5XOZaVN9s4acmYK yPcZHteq2YChTbLreIj4xGgoIIzW9G3e98FAvgzMyMw7b8s6678hLA7S EW8= ;{id = 2854}
+;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854}
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.blabla.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854}
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. UJ98Ev1G8XsVXX6xqSkSeqhDauNtAK1fnTgt1qdGf1+TFJuqPjHmEBr3 I8u381FKJaGPF2ZKH+A5oSPy6jPLQLe4TipFgnTZptq4IZ53holOKlx9 RSjz5kovs5wYafSeBBM+cjX6LJogyP8vrnPuSJ/Z8Uk2+Ojhd1j7sR2C PwY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101756 20181130101756 5459 example.com. MGpbBGEQk6CQ0GBHNByUfF9s7kXOl2Qflh74erA5oFkrlK0/fJFRAkMb Edgmrs4FjvrlJJ1Gi5BWqv0avoyPUWVhwYz15VhjJjXP6jLuVn1j/EnT J5t55UU6hGf2R9NHvLRdeebJDOMryVW+1r9UWQYuabdCkxtnT+xcw9Or nDs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+ENTRY_END
+
+; ENT request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+rub.example.com. IN NSEC sub.sub.example.com. RRSIG NSEC A
+rub.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101756 20181130101756 5459 example.com. LxXDGCPOA5KoYz7wy2512fZqTzWTdfRdL2VQU6+v+k39hMpVvBbRbW3R 8X1YFrbl+gKMbzhtH3kKkjibwlKethd71p8xZKwIw4df1u3kdJygijuH +BvwG6jCIzF8wBLh8Uuv14KJOybmqJXzUdVKAU9MyQNvnfJk+Ekdj/sY MEw= ;{id = 2854}
+; extraneous DS
+sub.sub.example.com. IN NSEC tub.example.com. RRSIG NSEC DS
+sub.sub.example.com. 3600 IN RRSIG NSEC 7 4 3600 20181230101756 20181130101756 5459 example.com. RoMochVq8vIslggd50/mnc5rV+OKchIZPUdrVjVpGZjsieh50UoM1+bV ChGrxwDNUYvs7vzztSaZ+oyBErPiGzkK6/nUQ5P8fhxMyPMaFrCNtHCC +tZsImjSbiwVm3bLpdcoNEDRHjiVb0Y7ztScMQji2QyN6iFLPrXXXNaW HXU= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN DS
+SECTION ANSWER
+sub.sub.example.com. 3600 IN DS 14511 5 1 9C23483B120C7BCAB7E9BD00BCA7F30B38F92E1A
+sub.sub.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101756 20181130101756 5459 example.com. jkShmezNgvdoBxXKSiTVnmofgublfIQPCqrHwEDMCzs1WbIJWWEmzmxX 7dzupiSnVPlVQfKLXzEbSqM/QGxmU/bBn2lUAYNLpM2kFm85TVEXCLf8 u12NeWbBupsr1UctfzF2WtaUGxVfDZ+J86ka3qqQnmYYYAbz4MlnKvyQ p5c= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN NS
+SECTION AUTHORITY
+sub.sub.example.com. IN NS ns.sub.sub.example.com.
+sub.sub.example.com. IN NS ns.foo.com.
+sub.sub.example.com. 3600 IN DS 14511 5 1 9C23483B120C7BCAB7E9BD00BCA7F30B38F92E1A
+sub.sub.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101756 20181130101756 5459 example.com. jkShmezNgvdoBxXKSiTVnmofgublfIQPCqrHwEDMCzs1WbIJWWEmzmxX 7dzupiSnVPlVQfKLXzEbSqM/QGxmU/bBn2lUAYNLpM2kFm85TVEXCLf8 u12NeWbBupsr1UctfzF2WtaUGxVfDZ+J86ka3qqQnmYYYAbz4MlnKvyQ p5c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.blabla.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101756 20181130101756 5459 example.com. MGpbBGEQk6CQ0GBHNByUfF9s7kXOl2Qflh74erA5oFkrlK0/fJFRAkMb Edgmrs4FjvrlJJ1Gi5BWqv0avoyPUWVhwYz15VhjJjXP6jLuVn1j/EnT J5t55UU6hGf2R9NHvLRdeebJDOMryVW+1r9UWQYuabdCkxtnT+xcw9Or nDs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101756 20181130101756 5459 example.com. WM9C+vSGlYtmk/wVLfWyqGwo4vbo8fGaD7DoGnJGFpICmoM8v7mcs4Pd UyZv9CPBMy9gYNM1wWcNVofQu2IC5gUgEpkuhluJji5BeocqOGzIuHW+ AVIHJjN4m9z12swsCrAq71vO+UEfWqPO4JOu40vVkSsDiaINYd8FRWkr yfg= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAaQAmPhsPdOjFE6SGc95hYvPxUHoNkUetYpu81j7j9WXUsvn8Y6M DrHOnLrVd9uV7+1Aj2nkLY+6BvLxsPcp3yBO7UPB6Mv1ZfYCP0D7qCcs Jg6NjLWD5+2owvglTk7XveTztZLFIgDGo2sxZ4/wKE2fhsmh6/Hn7GiW ySEwHURb ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101756 20181130101756 5459 example.com. Pfl3n2c2oppL26sSLAFSTTkOken2ZlU+bJwpH3ipCz6BTCIm8zHjk/u7 IPyX6RiKEgVwUKEoNIXSYxkZg4Q2OHOINwRhARgQR5XOZaVN9s4acmYK yPcZHteq2YChTbLreIj4xGgoIIzW9G3e98FAvgzMyMw7b8s6678hLA7S EW8= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101756 20181130101756 5459 example.com. MGpbBGEQk6CQ0GBHNByUfF9s7kXOl2Qflh74erA5oFkrlK0/fJFRAkMb Edgmrs4FjvrlJJ1Gi5BWqv0avoyPUWVhwYz15VhjJjXP6jLuVn1j/EnT J5t55UU6hGf2R9NHvLRdeebJDOMryVW+1r9UWQYuabdCkxtnT+xcw9Or nDs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. aAhY236a0BQlJUnglecaUzphiHPw9ozBTu5v4Lx2ppQLqUZf4AXPgetm 5WjHUVJIqU9e0AwyHiqq3vKK6kDrUcdtI3Ygyn9O5WgCeGUd1UNXrx9h 2SLESwVt5MWFfFP3M0vKwgWrvWS4eZKD6Uc1VUm5tzIo5VRb6Q839qGw yKU= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101756 20181130101756 5459 example.com. MGpbBGEQk6CQ0GBHNByUfF9s7kXOl2Qflh74erA5oFkrlK0/fJFRAkMb Edgmrs4FjvrlJJ1Gi5BWqv0avoyPUWVhwYz15VhjJjXP6jLuVn1j/EnT J5t55UU6hGf2R9NHvLRdeebJDOMryVW+1r9UWQYuabdCkxtnT+xcw9Or nDs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101756 20181130101756 5459 example.com. UJ98Ev1G8XsVXX6xqSkSeqhDauNtAK1fnTgt1qdGf1+TFJuqPjHmEBr3 I8u381FKJaGPF2ZKH+A5oSPy6jPLQLe4TipFgnTZptq4IZ53holOKlx9 RSjz5kovs5wYafSeBBM+cjX6LJogyP8vrnPuSJ/Z8Uk2+Ojhd1j7sR2C PwY= ;{id = 2854}
+ENTRY_END
+
+; ENT request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+rub.example.com. IN NSEC sub.sub.example.com. RRSIG NSEC A
+rub.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101756 20181130101756 5459 example.com. LxXDGCPOA5KoYz7wy2512fZqTzWTdfRdL2VQU6+v+k39hMpVvBbRbW3R 8X1YFrbl+gKMbzhtH3kKkjibwlKethd71p8xZKwIw4df1u3kdJygijuH +BvwG6jCIzF8wBLh8Uuv14KJOybmqJXzUdVKAU9MyQNvnfJk+Ekdj/sY MEw= ;{id = 2854}
+; extraneous DS
+sub.sub.example.com. IN NSEC tub.example.com. RRSIG NSEC DS
+sub.sub.example.com. 3600 IN RRSIG NSEC 7 4 3600 20181230101756 20181130101756 5459 example.com. RoMochVq8vIslggd50/mnc5rV+OKchIZPUdrVjVpGZjsieh50UoM1+bV ChGrxwDNUYvs7vzztSaZ+oyBErPiGzkK6/nUQ5P8fhxMyPMaFrCNtHCC +tZsImjSbiwVm3bLpdcoNEDRHjiVb0Y7ztScMQji2QyN6iFLPrXXXNaW HXU= ;{id = 2854}
+ENTRY_END
+
+; DS request
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN DS
+SECTION ANSWER
+sub.sub.example.com. 3600 IN DS 14511 5 1 9C23483B120C7BCAB7E9BD00BCA7F30B38F92E1A
+sub.sub.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101756 20181130101756 5459 example.com. jkShmezNgvdoBxXKSiTVnmofgublfIQPCqrHwEDMCzs1WbIJWWEmzmxX 7dzupiSnVPlVQfKLXzEbSqM/QGxmU/bBn2lUAYNLpM2kFm85TVEXCLf8 u12NeWbBupsr1UctfzF2WtaUGxVfDZ+J86ka3qqQnmYYYAbz4MlnKvyQ p5c= ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN NS
+SECTION AUTHORITY
+sub.sub.example.com. IN NS ns.sub.sub.example.com.
+sub.sub.example.com. IN NS ns.foo.com.
+sub.sub.example.com. 3600 IN DS 14511 5 1 9C23483B120C7BCAB7E9BD00BCA7F30B38F92E1A
+sub.sub.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101756 20181130101756 5459 example.com. jkShmezNgvdoBxXKSiTVnmofgublfIQPCqrHwEDMCzs1WbIJWWEmzmxX 7dzupiSnVPlVQfKLXzEbSqM/QGxmU/bBn2lUAYNLpM2kFm85TVEXCLf8 u12NeWbBupsr1UctfzF2WtaUGxVfDZ+J86ka3qqQnmYYYAbz4MlnKvyQ p5c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.sub.example.com. IN A 1.2.4.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.4.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAabTZ4z4UwwLP6+/SGL9K8q35Xrmey7BMhj0ljyMLM3SGf+2syaV eLubZDwaFf6mO7/hc4HOVrXsdl9mWm8kvuKj8zcj/hi26dcUUfd4OAyR Fy1qrnyutzHJkB/9Ahau0/ORuQXAAstUaQERk1u2RQI2u/iWmuEN5o1H Tf4CUruX ;{id = 30899 (zsk), size = 512b}
+sub.sub.example.com. 3600 IN RRSIG DNSKEY 5 4 3600 20181230101756 20181130101756 14511 sub.sub.example.com. jTL8Io/JECEwS06P0rTJquZjpFzONP/UKmSPscICI+yI6aOLc+Fa1ig9 OC+XLfBmbnpN/W+KAtpJGwkDzFiXMWLB+Q3BnAVnqQvsDHv0CKIDyN4k Vo7rVqMuDM5bFYsoPhojltZ+2ZP/m6c/ylxwj5Yr0tuRpJSiyj4rEKRv Ohs= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.sub.example.com. IN NS
+SECTION ANSWER
+sub.sub.example.com. IN NS ns.sub.sub.example.com.
+sub.sub.example.com. IN NS ns.foo.com.
+sub.sub.example.com. 3600 IN RRSIG NS 5 4 3600 20181230101756 20181130101756 14511 sub.sub.example.com. I4VuZ180mFDV4B2YK7gWXaFYYxJE+Mt4X12/azYSudLBesx/NR99GYNc dQbrE03JEGvDRmTataRE1za7RdpR7HkJfUfY+2Wa/CtmdIvLkxnDkK0G AexLq0ws8ozntfMdrI1Ahz9mMj8/tifrlvNSMA0ifjtmjENZX0HyBuYX OwI= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.sub.example.com. IN A 1.2.4.6
+ns.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20181230101756 20181130101756 14511 sub.sub.example.com. eWvgi1EsYq54z+3NIjhwoeq+qGmJ/5GUnXAE024QLD8J/a1fN1QB4WR4 awo3UuhPeYd3LHntFQ1LuJDcxqLwT2C4c7mN/EQu39zrnlKwJS2kOyAo eolcUtsEkmf37VY3ZpUXviQZlOtJfEXaAajWeksXMeVAmzuO9l0SOD1O QzQ= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.sub.example.com. IN A
+SECTION ANSWER
+ns.sub.sub.example.com. IN A 1.2.4.6
+ns.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20181230101756 20181130101756 14511 sub.sub.example.com. eWvgi1EsYq54z+3NIjhwoeq+qGmJ/5GUnXAE024QLD8J/a1fN1QB4WR4 awo3UuhPeYd3LHntFQ1LuJDcxqLwT2C4c7mN/EQu39zrnlKwJS2kOyAo eolcUtsEkmf37VY3ZpUXviQZlOtJfEXaAajWeksXMeVAmzuO9l0SOD1O QzQ= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.sub.example.com. IN AAAA
+SECTION AUTHORITY
+ns.sub.sub.example.com. IN NSEC nt.sub.sub.example.com. NSEC RRSIG A
+ns.sub.sub.example.com. 3600 IN RRSIG NSEC 5 5 5 20181230101756 20181130101756 14511 sub.sub.example.com. HcRO6gIx6vkwVAXfGG/OmN7eBBbzjEy1Em3iOwsZT0SuCzcPWJOMS/n2 HnocrKbR/k4seuodrppyUF3nfDcGWJ85gC7HprofbJNgmjVJSErb6Y2Q eGzDf7SJULRKLX5lHmqYY7UUWHmAQKjnnrN7SSnCb8RigPi1DcGUlS5N GzU= ;{id = 30899}
+sub.sub.example.com. IN SOA sub.sub.example.com. hostmaster.sub.sub.example.com. 1 2 3 4 5
+sub.sub.example.com. 3600 IN RRSIG SOA 5 4 3600 20181230101756 20181130101756 14511 sub.sub.example.com. etcKdUzigtePis7MO2hVK0runIUOnpCD59J+2ne554YZk7OYi68IIoZB wvmeJoz6nqEu2V0ciZflj8gX9DAHDqV+mTWSr8ZXqp800hJkbxJ66C7q Q7M+bfMq8QN3+JwjosvjGBYmR6s6AMA/AmgYNA/mN1pCjkY4LpDMDmYU Mks= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.sub.example.com. IN A
+SECTION ANSWER
+www.sub.sub.example.com. IN A 10.20.30.40
+www.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20181230101756 20181130101756 14511 sub.sub.example.com. iOC5Z07Y0wVz7U9rRUqUNZeBopg2GVInGSR7qfn6bhSrvygmhKdayL1Y SZ3urbmXRrv3syTb61Iqy4N6Di2Swj4sLmdUaSobyIzWAQ6XZwKHXBRc 5yDjigDXSR7TTMSSSzQpYtR1P3tIFT5Ppdp4xAiX0CgjQlDs29fPUaQ9 Vx4= ;{id = 30899}
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.sub.example.com. IN A
+SECTION ANSWER
+www.sub.sub.example.com. IN A 10.20.30.40
+www.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20181230101756 20181130101756 14511 sub.sub.example.com. iOC5Z07Y0wVz7U9rRUqUNZeBopg2GVInGSR7qfn6bhSrvygmhKdayL1Y SZ3urbmXRrv3syTb61Iqy4N6Di2Swj4sLmdUaSobyIzWAQ6XZwKHXBRc 5yDjigDXSR7TTMSSSzQpYtR1P3tIFT5Ppdp4xAiX0CgjQlDs29fPUaQ9 Vx4= ;{id = 30899}
+ENTRY_END
+
+; remove pending ns.blabla.com AAAA msg
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA DO NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/black_prime.rpl b/tests/deckard/sets/resolver/black_prime.rpl
new file mode 100644
index 0000000..0cc2d28
--- /dev/null
+++ b/tests/deckard/sets/resolver/black_prime.rpl
@@ -0,0 +1,300 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 62942 7 1 04D720E4CAB3C4AC2049BE5EE7599BF920269624 "
+val-override-date: "20181130121801"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with blacklist for prime response
+; the data response needs a blacklist action as well, since it also
+; comes from an 'expired signatures' name server.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN A
+SECTION ANSWER
+ns.blabla.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+; no ns.blabla.com, try that later
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101800 20181130101800 62942 example.com. j4fGEdXawCQcg5K+EPIlU4ekUeIqvDSxV7ZaPsC2P4IxJaLpCUMQJk54 aF+XCCpedBTbAoe8WBws/mxySdY2CYt0WfUjUhl6hWt+sINX8XXoH87O NKidHTC7z+/lzzEYoqMEJxCc7KdNxM3Y+6QaHshZzg4NYFiw5P62oOev NaE= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdBMHE0Pz/DMrzxL+gmpcUrQJr7lLVUreB+a1rQrMicGVF/5/88V Hu+kDKaPvRHq4x22Ja8ZMmiNrfozQWoszAzhMlupQX1vXF44aSZbElqZ DNYhLyIaC8xBUPJ3qrcBPZOILu/2ylTx3xXfSPDVoX2L8fqODOOIjCim lumwbb5H ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101800 20181130101800 62942 example.com. KECGylKgZL/1kcEKkulqQF7XlT8kCswdtvH3coWkCBGGprMYZ5sJKGP9 mk8lcEXG9vXujUz++YtJ2l1U23MMAr8stnoJ0xRlTMO2VwoLlTnW68ng F12n5eeQs7GNq1hDz6xnLAF0flpI8qfTIABqnw8M7LmYoqEbwNHPtVDt nfE= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. cN4kzlqQDlhENCeWp7RaqU6N0CaVPCgOJLpdkVh7+Q6swyKe/Ponmgia SZ44kBtXXt91EIsaJgDU/Rhwq7zCmHT1XOHGNdNjPfHdOAOjtL42rVKU lnhS0rjcFn4SN9zgE1kiQIiu3zgIlkimNaL6JqgtUpbaIrTE6Ol9PMWU 6v8= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.blabla.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101800 20181130101800 62942 example.com. j4fGEdXawCQcg5K+EPIlU4ekUeIqvDSxV7ZaPsC2P4IxJaLpCUMQJk54 aF+XCCpedBTbAoe8WBws/mxySdY2CYt0WfUjUhl6hWt+sINX8XXoH87O NKidHTC7z+/lzzEYoqMEJxCc7KdNxM3Y+6QaHshZzg4NYFiw5P62oOev NaE= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdBMHE0Pz/DMrzxL+gmpcUrQJr7lLVUreB+a1rQrMicGVF/5/88V Hu+kDKaPvRHq4x22Ja8ZMmiNrfozQWoszAzhMlupQX1vXF44aSZbElqZ DNYhLyIaC8xBUPJ3qrcBPZOILu/2ylTx3xXfSPDVoX2L8fqODOOIjCim lumwbb5H ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101800 20181130101800 62942 example.com. KECGylKgZL/1kcEKkulqQF7XlT8kCswdtvH3coWkCBGGprMYZ5sJKGP9 mk8lcEXG9vXujUz++YtJ2l1U23MMAr8stnoJ0xRlTMO2VwoLlTnW68ng F12n5eeQs7GNq1hDz6xnLAF0flpI8qfTIABqnw8M7LmYoqEbwNHPtVDt nfE= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. KDQYC0xU8LVsNTK2uldzRU89po6ti/vnp94h9lo7TYI7Z+lGtBIXK23H nFL4/DBbcAChUB0xTeXRm6LHt3lI2M/cpGCQ7fcByBzv7cFDeIuJ3BZ9 ufbJBkmTmw9292zjMoDqP+9tGgSIDV3amJdP39C0VC1qhOjG+crIlEKB XIg= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.blabla.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101800 20181130101800 62942 example.com. qmB12jqvKtMSxWX+8K3dKRRvFHxAcxe0bHtpZjiFn9dpUpsvo/CZ2nSV rrZ53C6WRIKA0i7Z2Q7CzeKjnOpXqVXfZ2rZyFaWQs23AbXLAIhpoG+7 g+9xCRkXED5kgkCjsyg5CmzFx5G68bZj9IOZNna/ZNfij8vaiJPO3IW9 mmM= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. cN4kzlqQDlhENCeWp7RaqU6N0CaVPCgOJLpdkVh7+Q6swyKe/Ponmgia SZ44kBtXXt91EIsaJgDU/Rhwq7zCmHT1XOHGNdNjPfHdOAOjtL42rVKU lnhS0rjcFn4SN9zgE1kiQIiu3zgIlkimNaL6JqgtUpbaIrTE6Ol9PMWU 6v8= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101800 20181130101800 62942 example.com. cN4kzlqQDlhENCeWp7RaqU6N0CaVPCgOJLpdkVh7+Q6swyKe/Ponmgia SZ44kBtXXt91EIsaJgDU/Rhwq7zCmHT1XOHGNdNjPfHdOAOjtL42rVKU lnhS0rjcFn4SN9zgE1kiQIiu3zgIlkimNaL6JqgtUpbaIrTE6Ol9PMWU 6v8= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; remove pending ns.blabla.com AAAA msg
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA DO NOERROR
+SECTION QUESTION
+ns.blabla.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+com. IN SOA com. com. 2009100100 28800 7200 604800 3600
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_badglue.rpl b/tests/deckard/sets/resolver/iter_badglue.rpl
new file mode 100644
index 0000000..131a8a9
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_badglue.rpl
@@ -0,0 +1,272 @@
+stub-addr: 1.1.1.1
+CONFIG_END
+
+SCENARIO_BEGIN Test not using cached glue records
+
+;root server
+RANGE_BEGIN 0 100
+ ADDRESS 1.1.1.1
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS ns.com.
+SECTION ADDITIONAL
+ns.com. IN A 2.2.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS ns.net.
+SECTION ADDITIONAL
+ns.net IN A 3.3.3.3
+ENTRY_END
+RANGE_END
+
+;ns.com.
+RANGE_BEGIN 0 100
+ ADDRESS 2.2.2.2
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS ns.com.
+SECTION ADDITIONAL
+ns.com. IN A 2.2.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns.com. IN A
+SECTION ANSWER
+ns.com. IN A 2.2.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns.com. IN AAAA
+SECTION AUTHORITY
+com. IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+a.com. IN NS
+SECTION AUTHORITY
+a.com. IN NS ns-a.net. ; out-of-bailwick nameservers
+a.com. IN NS ns-obsolete.net.
+SECTION ADDITIONAL
+ns-a.net. IN A 4.4.4.4
+ns-obsolete.net. IN A 6.6.6.6 ; dead address in glue records
+ENTRY_END
+RANGE_END
+
+;ns.net.
+RANGE_BEGIN 0 100
+ ADDRESS 3.3.3.3
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS ns.net.
+SECTION ADDITIONAL
+ns.net. IN A 3.3.3.3
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns.net. IN A
+SECTION ANSWER
+ns.net. IN A 3.3.3.3
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+net. 900 IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+ns-a.net. IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+net. 900 IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns-a.net. IN A
+SECTION ANSWER
+ns-a.net. IN A 4.4.4.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns-obsolete.net. IN A
+SECTION ANSWER
+ns-obsolete.net. IN A 9.9.9.9 ; working address
+ENTRY_END
+
+; no IPv6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns-a.net. IN AAAA
+SECTION AUTHORITY
+net. 900 IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+ns-obsolete.net. IN AAAA
+SECTION AUTHORITY
+net. 900 IN SOA . . 1487352364 1800 900 604800 86400
+ENTRY_END
+RANGE_END
+
+;ns-a.net
+RANGE_BEGIN 0 100
+ ADDRESS 4.4.4.4
+ ADDRESS 9.9.9.9
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+a.com. IN NS
+SECTION ANSWER
+a.com. IN NS ns-a.net. ; out-of-bailwick nameservers
+a.com. IN NS ns-obsolete.net.
+SECTION ADDITIONAL
+ns-a.net. IN A 4.4.4.4
+ns-obsolete.net. IN A 9.9.9.9 ; the new (functional) address
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+; phony target used to pollute resolver's cache
+www.a.com. IN A
+SECTION ANSWER
+www.a.com. IN A 5.5.5.5
+ENTRY_END
+RANGE_END
+
+; ask for phony target to pollute resolver's cache
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.a.com. IN A
+ENTRY_END
+
+; we don't actually care about this answer
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.a.com. IN A
+SECTION ANSWER
+www.a.com. IN A 5.5.5.5
+ENTRY_END
+
+; check if obsolete data from glue records is returned to the client
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns-obsolete.net. IN A
+ENTRY_END
+
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns-obsolete.net. IN A
+SECTION ANSWER
+ns-obsolete.net. IN A 9.9.9.9 ; 6.6.6.6 should not be here
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_badraw.rpl b/tests/deckard/sets/resolver/iter_badraw.rpl
new file mode 100644
index 0000000..0653b76
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_badraw.rpl
@@ -0,0 +1,18699 @@
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN raw queries from inbound.
+
+STEP 10 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004aa200000204059801010402
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+RAW
+b5c9ca3d50104320f4120000000000000000
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+RAW
+b5c9ca3d5018432054550000009010c0000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe52403c4fd20003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 40 QUERY
+ENTRY_BEGIN
+RAW
+b5c9ca4b50114312f37f0000000000000000
+ENTRY_END
+
+STEP 50 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400026fc00000204059801010402
+ENTRY_END
+
+STEP 60 QUERY
+ENTRY_BEGIN
+RAW
+b5c9ca4c50104312f37e0000000000000000
+ENTRY_END
+
+STEP 70 QUERY
+ENTRY_BEGIN
+RAW
+b5ca72d85010432027d10000000000000000
+ENTRY_END
+
+STEP 80 QUERY
+ENTRY_BEGIN
+RAW
+b5ca72d8501843209a9300000090ff40000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe52403c4fd20003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 90 QUERY
+ENTRY_BEGIN
+RAW
+b5ca72e650114312273e0000000000000000
+ENTRY_END
+
+STEP 100 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006b1b00000204059801010402
+ENTRY_END
+
+STEP 110 QUERY
+ENTRY_BEGIN
+RAW
+b5ca72e750104312273d0000000000000000
+ENTRY_END
+
+STEP 120 QUERY
+ENTRY_BEGIN
+RAW
+b5cb35d550104320a8f20000000000000000
+ENTRY_END
+
+STEP 130 QUERY
+ENTRY_BEGIN
+RAW
+b5cb35d550184320a275000000907880000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe52403c4fd20003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 140 QUERY
+ENTRY_BEGIN
+RAW
+b5cb35e350114312a85f0000000000000000
+ENTRY_END
+
+STEP 150 QUERY
+ENTRY_BEGIN
+RAW
+b5cb35e450104312a85e0000000000000000
+ENTRY_END
+
+STEP 160 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0362600000204057801010402
+ENTRY_END
+
+STEP 170 QUERY
+ENTRY_BEGIN
+RAW
+b5cf40235010fb906c0b0000000000000000
+ENTRY_END
+
+STEP 180 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000671b0000020405b401010402
+ENTRY_END
+
+STEP 190 QUERY
+ENTRY_BEGIN
+RAW
+b5cf40235018fb90fce000000090c500000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afcd1403c4e510003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000057524b53544e3036484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 200 QUERY
+ENTRY_BEGIN
+RAW
+b5d0233950104470b6550000000000000000
+ENTRY_END
+
+STEP 210 QUERY
+ENTRY_BEGIN
+RAW
+b5d023395018447066590000008e2a0f000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcd0403c4e5000030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 220 QUERY
+ENTRY_BEGIN
+RAW
+b5cf40315011fb826b780000000000000000
+ENTRY_END
+
+STEP 230 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08db400000204057801010402
+ENTRY_END
+
+STEP 240 QUERY
+ENTRY_BEGIN
+RAW
+b5d0234750114462b5c40000000000000000
+ENTRY_END
+
+STEP 250 QUERY
+ENTRY_BEGIN
+RAW
+b5cf40325010fb826b770000000000000000
+ENTRY_END
+
+STEP 260 QUERY
+ENTRY_BEGIN
+RAW
+b5d0234850104462b5c30000000000000000
+ENTRY_END
+
+STEP 270 QUERY
+ENTRY_BEGIN
+RAW
+b5d0e1385010fb9022830000000000000000
+ENTRY_END
+
+STEP 280 QUERY
+ENTRY_BEGIN
+RAW
+b5d0e1385018fb908a5800000090f000000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afcd1403c4e510003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000057524b53544e3036484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 290 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000dff20000020405b401010402
+ENTRY_END
+
+STEP 300 QUERY
+ENTRY_BEGIN
+RAW
+b5d0e1465011fb8221f00000000000000000
+ENTRY_END
+
+STEP 310 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0310300000204057801010402
+ENTRY_END
+
+STEP 320 QUERY
+ENTRY_BEGIN
+RAW
+b5d188c150104470c9a30000000000000000
+ENTRY_END
+
+STEP 330 QUERY
+ENTRY_BEGIN
+RAW
+b5d0e1475010fb8221ef0000000000000000
+ENTRY_END
+
+STEP 340 QUERY
+ENTRY_BEGIN
+RAW
+b5d188c1501844701fee0000008e84c9000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcd0403c4e5000030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 350 QUERY
+ENTRY_BEGIN
+RAW
+b5d2225d5010fb9084ab0000000000000000
+ENTRY_END
+
+STEP 360 QUERY
+ENTRY_BEGIN
+RAW
+b4745fb5501144625f360000000000000000
+ENTRY_END
+
+STEP 370 QUERY
+ENTRY_BEGIN
+RAW
+b5d2225d5018fb909e01000000903e80000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afcd1403c4e510003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000057524b53544e3036484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 380 QUERY
+ENTRY_BEGIN
+RAW
+b5d188cf50114462c9120000000000000000
+ENTRY_END
+
+STEP 390 QUERY
+ENTRY_BEGIN
+RAW
+b5d188d050104462c9110000000000000000
+ENTRY_END
+
+STEP 400 QUERY
+ENTRY_BEGIN
+RAW
+b5d2226b5011fb8284180000000000000000
+ENTRY_END
+
+STEP 410 QUERY
+ENTRY_BEGIN
+RAW
+b5d2226c5010fb8284170000000000000000
+ENTRY_END
+
+STEP 420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ad730000020405b401010402
+ENTRY_END
+
+STEP 430 QUERY
+ENTRY_BEGIN
+RAW
+b5d3163f5010447009a50000000000000000
+ENTRY_END
+
+STEP 440 QUERY
+ENTRY_BEGIN
+RAW
+b4745fb6501044625f350000000000000000
+ENTRY_END
+
+STEP 450 QUERY
+ENTRY_BEGIN
+RAW
+b5d3163f5018447005350000008edf83000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcd0403c4e5000030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 460 QUERY
+ENTRY_BEGIN
+RAW
+b5d3164d5011446209140000000000000000
+ENTRY_END
+
+STEP 470 QUERY
+ENTRY_BEGIN
+RAW
+b5d3164e5010446209130000000000000000
+ENTRY_END
+
+;STEP 480 QUERY
+;ENTRY_BEGIN
+;RAW
+;13f6000000010000000000001664696572656e61727473656e6f697374657277696a6b026e6c00000f0001c0
+;ENTRY_END
+
+STEP 490 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c81100000204055001010402
+ENTRY_END
+
+STEP 500 QUERY
+ENTRY_BEGIN
+RAW
+b5d6cf7c5010451069fe0000000000000000
+ENTRY_END
+
+STEP 510 QUERY
+ENTRY_BEGIN
+RAW
+b5d6cf7c501845104c27000000931280000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 520 QUERY
+ENTRY_BEGIN
+RAW
+b5d6cf8a5011450269680000000000000000
+ENTRY_END
+
+STEP 530 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400002c300000204055001010402
+ENTRY_END
+
+STEP 540 QUERY
+ENTRY_BEGIN
+RAW
+b5d6cf8b5010450269670000000000000000
+ENTRY_END
+
+STEP 550 QUERY
+ENTRY_BEGIN
+RAW
+b5d7afb650104510c4740000000000000000
+ENTRY_END
+
+STEP 560 QUERY
+ENTRY_BEGIN
+RAW
+b5d7afb650184510e85d00000093d1c0000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 570 QUERY
+ENTRY_BEGIN
+RAW
+b5d7afc450114502c3de0000000000000000
+ENTRY_END
+
+STEP 580 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000463d00000204055001010402
+ENTRY_END
+
+STEP 590 QUERY
+ENTRY_BEGIN
+RAW
+b5d7afc550104502c3dd0000000000000000
+ENTRY_END
+
+STEP 600 QUERY
+ENTRY_BEGIN
+RAW
+b5d8998b501045101e190000000000000000
+ENTRY_END
+
+STEP 610 QUERY
+ENTRY_BEGIN
+RAW
+b5d8998b5018451082c2000000939100000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 620 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf04e890000020405b401010402
+ENTRY_END
+
+STEP 630 QUERY
+ENTRY_BEGIN
+RAW
+b5d89999501145021d830000000000000000
+ENTRY_END
+
+STEP 640 QUERY
+ENTRY_BEGIN
+RAW
+b5d8999a501045021d820000000000000000
+ENTRY_END
+
+STEP 650 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400060f900000204055001010402
+ENTRY_END
+
+STEP 660 QUERY
+ENTRY_BEGIN
+RAW
+b5d95492501045107dcd0000000000000000
+ENTRY_END
+
+STEP 670 QUERY
+ENTRY_BEGIN
+RAW
+b5d954925018451062f6000000930f80000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 680 QUERY
+ENTRY_BEGIN
+RAW
+b5d954a0501145027d370000000000000000
+ENTRY_END
+
+STEP 690 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000784600000204055001010402
+ENTRY_END
+
+STEP 700 QUERY
+ENTRY_BEGIN
+RAW
+b5d954a1501045027d360000000000000000
+ENTRY_END
+
+STEP 710 QUERY
+ENTRY_BEGIN
+RAW
+b5da034150104510e66a0000000000000000
+ENTRY_END
+
+STEP 720 QUERY
+ENTRY_BEGIN
+RAW
+b5da03415018451059540000009382c0000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 730 QUERY
+ENTRY_BEGIN
+RAW
+b5da034f50114502e5d40000000000000000
+ENTRY_END
+
+STEP 740 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e0de00000204055001010402
+ENTRY_END
+
+;STEP 750 QUERY
+;ENTRY_BEGIN
+;RAW
+;1f64000000010000000000000e6875676f63617273797374656d73026e6c00000f000100
+;ENTRY_END
+
+STEP 760 QUERY
+ENTRY_BEGIN
+RAW
+b5da035050104502e5d30000000000000000
+ENTRY_END
+
+STEP 770 QUERY
+ENTRY_BEGIN
+RAW
+b5dadc785010451075cb0000000000000000
+ENTRY_END
+
+STEP 780 QUERY
+ENTRY_BEGIN
+RAW
+b5dadc78501845102975000000934200000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afed1403c50510003000000344e544c4d535350000100000097b200e0090009002b0000000b000b002000000046494c4553455256455231444d4e4d554c4445520000
+ENTRY_END
+
+STEP 790 QUERY
+ENTRY_BEGIN
+RAW
+b5dadc865011450275350000000000000000
+ENTRY_END
+
+STEP 800 QUERY
+ENTRY_BEGIN
+RAW
+b5dadc875010450275340000000000000000
+ENTRY_END
+
+STEP 810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf04ab80000020405b401010402
+ENTRY_END
+
+STEP 820 QUERY
+ENTRY_BEGIN
+RAW
+b5dd4b595010faf076350000000000000000
+ENTRY_END
+
+STEP 830 QUERY
+ENTRY_BEGIN
+RAW
+b5dd4b595018faf05667000000931680000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403afce2403c4e620003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000422d5345525645523031425552474552544a45530000
+ENTRY_END
+
+STEP 840 QUERY
+ENTRY_BEGIN
+RAW
+b5dd4b675011fae2759f0000000000000000
+ENTRY_END
+
+STEP 850 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf017e30000020405b401010402
+ENTRY_END
+
+STEP 860 QUERY
+ENTRY_BEGIN
+RAW
+b5dd4b685010fae2759e0000000000000000
+ENTRY_END
+
+STEP 870 QUERY
+ENTRY_BEGIN
+RAW
+b5de11195010faf07d9f0000000000000000
+ENTRY_END
+
+STEP 880 QUERY
+ENTRY_BEGIN
+RAW
+b5de11195018faf04852000000932d00000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afce2403c4e620003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000422d5345525645523031425552474552544a45530000
+ENTRY_END
+
+STEP 890 QUERY
+ENTRY_BEGIN
+RAW
+b5de11275011fae27d090000000000000000
+ENTRY_END
+
+STEP 900 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0325f0000020405b401010402
+ENTRY_END
+
+STEP 910 QUERY
+ENTRY_BEGIN
+RAW
+b5de11285010fae27d080000000000000000
+ENTRY_END
+
+STEP 920 QUERY
+ENTRY_BEGIN
+RAW
+b5decd685010faf0dbcb0000000000000000
+ENTRY_END
+
+STEP 930 QUERY
+ENTRY_BEGIN
+RAW
+b5decd685018faf08b7e000000934800000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afce2403c4e620003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000422d5345525645523031425552474552544a45530000
+ENTRY_END
+
+STEP 940 QUERY
+ENTRY_BEGIN
+RAW
+b5decd765011fae2db350000000000000000
+ENTRY_END
+
+STEP 950 QUERY
+ENTRY_BEGIN
+RAW
+b5decd775010fae2db340000000000000000
+ENTRY_END
+
+STEP 960 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ae090000020405ac01010402
+ENTRY_END
+
+STEP 970 QUERY
+ENTRY_BEGIN
+RAW
+b5e1b72b5010441069980000000000000000
+ENTRY_END
+
+STEP 980 QUERY
+ENTRY_BEGIN
+RAW
+b5e1b72b501844100ec700000094cb29000000010001000000000f313031333631323238313837342d330000f900010f313031333631323238313837342d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403af729403c48a90003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 990 QUERY
+ENTRY_BEGIN
+RAW
+b5e1b7395011440269010000000000000000
+ENTRY_END
+
+STEP 1000 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000be8d0000020405ac01010402
+ENTRY_END
+
+STEP 1010 QUERY
+ENTRY_BEGIN
+RAW
+b5e1b73a5010440269000000000000000000
+ENTRY_END
+
+STEP 1020 QUERY
+ENTRY_BEGIN
+RAW
+b5e2af585010441081ee0000000000000000
+ENTRY_END
+
+STEP 1030 QUERY
+ENTRY_BEGIN
+RAW
+b5e2af58501844109df6000000945551000000010001000000000f313031333631323238313837342d320000f900010f313031333631323238313837342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af729403c48a90003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 1040 QUERY
+ENTRY_BEGIN
+RAW
+b5e2af665011440281570000000000000000
+ENTRY_END
+
+STEP 1050 QUERY
+ENTRY_BEGIN
+RAW
+b5e2af675010440281560000000000000000
+ENTRY_END
+
+STEP 1060 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000cc0a0000020405b401010402
+ENTRY_END
+
+STEP 1070 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf089fb0000020405b401010402
+ENTRY_END
+
+STEP 1080 QUERY
+ENTRY_BEGIN
+RAW
+b5e6ab0d50104470935a0000000000000000
+ENTRY_END
+
+STEP 1090 QUERY
+ENTRY_BEGIN
+RAW
+b5e6ab0d5018447076b20000008998c8000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7de0403ccf6000030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 1100 QUERY
+ENTRY_BEGIN
+RAW
+b5e73d7d5010faf0c34a0000000000000000
+ENTRY_END
+
+STEP 1110 QUERY
+ENTRY_BEGIN
+RAW
+b5e73d7d5018faf01ee00000009431b8000000010001000000000f313039393531313632373739342d330000f900010f313039393531313632373739342d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afb18403c4c980003000000354e544c4d535350000100000097b208e00e000e00270000000700070020000000544553542d41444b4148554e412d544553544c41420000
+ENTRY_END
+
+STEP 1120 QUERY
+ENTRY_BEGIN
+RAW
+b5e73d8b5011fae2c2b30000000000000000
+ENTRY_END
+
+STEP 1130 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf09e490000020405b401010402
+ENTRY_END
+
+STEP 1140 QUERY
+ENTRY_BEGIN
+RAW
+b5e6ab1b5011446292ce0000000000000000
+ENTRY_END
+
+STEP 1150 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d7b30000020405b401010402
+ENTRY_END
+
+STEP 1160 QUERY
+ENTRY_BEGIN
+RAW
+b5e73d8c5010fae2c2b20000000000000000
+ENTRY_END
+
+STEP 1170 QUERY
+ENTRY_BEGIN
+RAW
+b5e829da5010faf0eb3a0000000000000000
+ENTRY_END
+
+STEP 1180 QUERY
+ENTRY_BEGIN
+RAW
+b5e829da5018faf0c24a00000094b73e000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afb18403c4c980003000000354e544c4d535350000100000097b208e00e000e00270000000700070020000000544553542d41444b4148554e412d544553544c41420000
+ENTRY_END
+
+STEP 1190 QUERY
+ENTRY_BEGIN
+RAW
+b5e6ab1c5010446292cd0000000000000000
+ENTRY_END
+
+STEP 1200 QUERY
+ENTRY_BEGIN
+RAW
+b5e8ed83501044705c8b0000000000000000
+ENTRY_END
+
+STEP 1210 QUERY
+ENTRY_BEGIN
+RAW
+b5e829e85011fae2eaa30000000000000000
+ENTRY_END
+
+STEP 1220 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf067190000020405b401010402
+ENTRY_END
+
+STEP 1230 QUERY
+ENTRY_BEGIN
+RAW
+b5e8ed8350184470d094000000890918000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7de0403ccf6000030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 1240 QUERY
+ENTRY_BEGIN
+RAW
+b5e829e95010fae2eaa20000000000000000
+ENTRY_END
+
+STEP 1250 QUERY
+ENTRY_BEGIN
+RAW
+b5e978885010faf0655b0000000000000000
+ENTRY_END
+
+STEP 1260 QUERY
+ENTRY_BEGIN
+RAW
+b5e978885018faf0052b00000094ee7e000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afb18403c4c980003000000354e544c4d535350000100000097b208e00e000e00270000000700070020000000544553542d41444b4148554e412d544553544c41420000
+ENTRY_END
+
+STEP 1270 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e51f00000204059801010402
+ENTRY_END
+
+STEP 1280 QUERY
+ENTRY_BEGIN
+RAW
+b5e8ed91501144625bff0000000000000000
+ENTRY_END
+
+STEP 1290 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400000aa0000020405b401010402
+ENTRY_END
+
+STEP 1300 QUERY
+ENTRY_BEGIN
+RAW
+b5e978965011fae264c40000000000000000
+ENTRY_END
+
+STEP 1310 QUERY
+ENTRY_BEGIN
+RAW
+b5ea6c7550104320ec370000000000000000
+ENTRY_END
+
+STEP 1320 QUERY
+ENTRY_BEGIN
+RAW
+b5e978975010fae264c30000000000000000
+ENTRY_END
+
+STEP 1330 QUERY
+ENTRY_BEGIN
+RAW
+b5e8ed92501044625bfe0000000000000000
+ENTRY_END
+
+STEP 1340 QUERY
+ENTRY_BEGIN
+RAW
+b5ea6c755018432081b900000090d180000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe57403c4fd70003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 1350 QUERY
+ENTRY_BEGIN
+RAW
+b5eb227d5010447050850000000000000000
+ENTRY_END
+
+STEP 1360 QUERY
+ENTRY_BEGIN
+RAW
+b5eb227d50184470f82900000089d57c000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7de0403ccf6000030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 1370 QUERY
+ENTRY_BEGIN
+RAW
+b5ea6c8350114312eba40000000000000000
+ENTRY_END
+
+STEP 1380 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ad7200000204059801010402
+ENTRY_END
+
+STEP 1390 QUERY
+ENTRY_BEGIN
+RAW
+b5eb228b501144624ff90000000000000000
+ENTRY_END
+
+STEP 1400 QUERY
+ENTRY_BEGIN
+RAW
+b5ea6c8450104312eba30000000000000000
+ENTRY_END
+
+STEP 1410 QUERY
+ENTRY_BEGIN
+RAW
+b5ebebc85010432035360000000000000000
+ENTRY_END
+
+STEP 1420 QUERY
+ENTRY_BEGIN
+RAW
+b5ebebc850184320dd3800000090c000000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe57403c4fd70003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 1430 QUERY
+ENTRY_BEGIN
+RAW
+b5eb228c501044624ff80000000000000000
+ENTRY_END
+
+STEP 1440 QUERY
+ENTRY_BEGIN
+RAW
+b5ebebd65011431234a30000000000000000
+ENTRY_END
+
+STEP 1450 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ce3800000204059801010402
+ENTRY_END
+
+STEP 1460 QUERY
+ENTRY_BEGIN
+RAW
+b5ebebd75010431234a20000000000000000
+ENTRY_END
+
+STEP 1470 QUERY
+ENTRY_BEGIN
+RAW
+b5ec666650104320db5d0000000000000000
+ENTRY_END
+
+STEP 1480 QUERY
+ENTRY_BEGIN
+RAW
+b5ec6666501843202b61000000901800000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afe57403c4fd70003000000314e544c4d535350000100000097b208e0060006002b0000000b000b00200000004441525941534552564552544157414e410000
+ENTRY_END
+
+STEP 1490 QUERY
+ENTRY_BEGIN
+RAW
+b5ec667450114312daca0000000000000000
+ENTRY_END
+
+STEP 1500 QUERY
+ENTRY_BEGIN
+RAW
+b5ec667550104312dac90000000000000000
+ENTRY_END
+
+STEP 1510 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000595000000204055001010402
+ENTRY_END
+
+STEP 1520 QUERY
+ENTRY_BEGIN
+RAW
+b5ee16d850104510b3c90000000000000000
+ENTRY_END
+
+STEP 1530 QUERY
+ENTRY_BEGIN
+RAW
+b5ee16d85018451089d00000008a63db000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc58403c4dd800030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004d414e55454c414150484c414e0000
+ENTRY_END
+
+STEP 1540 QUERY
+ENTRY_BEGIN
+RAW
+b5ee16e650114502b33c0000000000000000
+ENTRY_END
+
+STEP 1550 QUERY
+ENTRY_BEGIN
+RAW
+b5ee16e750104502b33b0000000000000000
+ENTRY_END
+
+STEP 1560 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b1fd00000204055001010402
+ENTRY_END
+
+STEP 1570 QUERY
+ENTRY_BEGIN
+RAW
+b5eecbbd5010451057910000000000000000
+ENTRY_END
+
+STEP 1580 QUERY
+ENTRY_BEGIN
+RAW
+b5eecbbd50184510b3ed0000008adf85000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc58403c4dd800030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004d414e55454c414150484c414e0000
+ENTRY_END
+
+STEP 1590 QUERY
+ENTRY_BEGIN
+RAW
+b5eecbcb5011450257040000000000000000
+ENTRY_END
+
+STEP 1600 QUERY
+ENTRY_BEGIN
+RAW
+b5eecbcc5010450257030000000000000000
+ENTRY_END
+
+STEP 1610 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000be5c00000204055001010402
+ENTRY_END
+
+STEP 1620 QUERY
+ENTRY_BEGIN
+RAW
+b5ef8d0d50104510a29f0000000000000000
+ENTRY_END
+
+STEP 1630 QUERY
+ENTRY_BEGIN
+RAW
+b5ef8d0d501845100bfa0000008ad287000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc58403c4dd800030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004d414e55454c414150484c414e0000
+ENTRY_END
+
+STEP 1640 QUERY
+ENTRY_BEGIN
+RAW
+b5ef8d1b50114502a2120000000000000000
+ENTRY_END
+
+STEP 1650 QUERY
+ENTRY_BEGIN
+RAW
+b5ef8d1c50104502a2110000000000000000
+ENTRY_END
+
+STEP 1660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c0510000020405b401010402
+ENTRY_END
+
+STEP 1670 QUERY
+ENTRY_BEGIN
+RAW
+b5f18dd25010faf0a9410000000000000000
+ENTRY_END
+
+STEP 1680 QUERY
+ENTRY_BEGIN
+RAW
+b5f18dd25018faf0e1bb0000008eeec4000000010001000000000f313237313331303331393633342d330000f900010f313237313331303331393633342d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04ae403c562e00030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 1690 QUERY
+ENTRY_BEGIN
+RAW
+b5f18de05011fae2a8b00000000000000000
+ENTRY_END
+
+STEP 1700 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08ee30000020405b401010402
+ENTRY_END
+
+STEP 1710 QUERY
+ENTRY_BEGIN
+RAW
+b5f18de15010fae2a8af0000000000000000
+ENTRY_END
+
+STEP 1720 QUERY
+ENTRY_BEGIN
+RAW
+b5f277b05010faf08df40000000000000000
+ENTRY_END
+
+STEP 1730 QUERY
+ENTRY_BEGIN
+RAW
+b5f277b05018faf064b80000008e517c000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04ae403c562e00030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 1740 QUERY
+ENTRY_BEGIN
+RAW
+b5f277be5011fae28d630000000000000000
+ENTRY_END
+
+STEP 1750 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06fb10000020405b401010402
+ENTRY_END
+
+STEP 1760 QUERY
+ENTRY_BEGIN
+RAW
+b5f277bf5010fae28d620000000000000000
+ENTRY_END
+
+STEP 1770 QUERY
+ENTRY_BEGIN
+RAW
+b5f2f44d5010faf0f2240000000000000000
+ENTRY_END
+
+STEP 1780 QUERY
+ENTRY_BEGIN
+RAW
+b5f2f44d5018faf05e280000008ebc3c000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04ae403c562e00030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 1790 QUERY
+ENTRY_BEGIN
+RAW
+b5f2f45b5011fae2f1930000000000000000
+ENTRY_END
+
+STEP 1800 QUERY
+ENTRY_BEGIN
+RAW
+b5f2f45c5010fae2f1920000000000000000
+ENTRY_END
+
+;STEP 1810 QUERY
+;ENTRY_BEGIN
+;RAW
+;076a000000010000000000000e6875676f63617273797374656d73026e6c00000f000100
+;ENTRY_END
+
+STEP 1820 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0764800000204056401010402
+ENTRY_END
+
+STEP 1830 QUERY
+ENTRY_BEGIN
+RAW
+b5f550df5010fd5c996b0000000000000000
+ENTRY_END
+
+STEP 1840 QUERY
+ENTRY_BEGIN
+RAW
+b5f550df5018fd5c34450000008ed972000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd93403c4f1300030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 1850 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000df860000020405b401010402
+ENTRY_END
+
+STEP 1860 QUERY
+ENTRY_BEGIN
+RAW
+b5f550ed5011fd4e98da0000000000000000
+ENTRY_END
+
+STEP 1870 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf05a7600000204056401010402
+ENTRY_END
+
+STEP 1880 QUERY
+ENTRY_BEGIN
+RAW
+b5f5d4c8501044707d0c0000000000000000
+ENTRY_END
+
+STEP 1890 QUERY
+ENTRY_BEGIN
+RAW
+b5f5d4c850184470f2d3000000992a30000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda1403c1f2100030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 1900 QUERY
+ENTRY_BEGIN
+RAW
+b5f550ee5010fd4e98d90000000000000000
+ENTRY_END
+
+STEP 1910 QUERY
+ENTRY_BEGIN
+RAW
+b5f6a7075010fd5c27700000000000000000
+ENTRY_END
+
+STEP 1920 QUERY
+ENTRY_BEGIN
+RAW
+b5f6a7075018fd5c47b70000008e5506000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd93403c4f1300030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 1930 QUERY
+ENTRY_BEGIN
+RAW
+b5f5d4d6501144627c700000000000000000
+ENTRY_END
+
+STEP 1940 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033c60000020405b401010402
+ENTRY_END
+
+STEP 1950 QUERY
+ENTRY_BEGIN
+RAW
+b5f6a7155011fd4e26df0000000000000000
+ENTRY_END
+
+STEP 1960 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08f9300000204056401010402
+ENTRY_END
+
+STEP 1970 QUERY
+ENTRY_BEGIN
+RAW
+b5f5d4d7501044627c6f0000000000000000
+ENTRY_END
+
+STEP 1980 QUERY
+ENTRY_BEGIN
+RAW
+b5f74ebe5010447057540000000000000000
+ENTRY_END
+
+STEP 1990 QUERY
+ENTRY_BEGIN
+RAW
+b5f6a7165010fd4e26de0000000000000000
+ENTRY_END
+
+STEP 2000 QUERY
+ENTRY_BEGIN
+RAW
+b5f74ebe5018447031ec00000099c660000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda1403c1f2100030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 2010 QUERY
+ENTRY_BEGIN
+RAW
+b5f822bd5010fd5ce0d50000000000000000
+ENTRY_END
+
+STEP 2020 QUERY
+ENTRY_BEGIN
+RAW
+b5f822bd5018fd5cb3f20000008ea230000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd93403c4f1300030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 2030 QUERY
+ENTRY_BEGIN
+RAW
+b5f74ecc5011446256b80000000000000000
+ENTRY_END
+
+STEP 2040 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ebf80000020405b401010402
+ENTRY_END
+
+STEP 2050 QUERY
+ENTRY_BEGIN
+RAW
+b5f822cb5011fd4ee0440000000000000000
+ENTRY_END
+
+STEP 2060 QUERY
+ENTRY_BEGIN
+RAW
+b5f74ecd5010446256b70000000000000000
+ENTRY_END
+
+STEP 2070 QUERY
+ENTRY_BEGIN
+RAW
+b5f8bd2750104470a11c0000000000000000
+ENTRY_END
+
+STEP 2080 QUERY
+ENTRY_BEGIN
+RAW
+b5f8bd27501844703755000000990ac0000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda1403c1f2100030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 2090 QUERY
+ENTRY_BEGIN
+RAW
+b5f822cc5010fd4ee0430000000000000000
+ENTRY_END
+
+STEP 2100 QUERY
+ENTRY_BEGIN
+RAW
+b5f8bd3550114462a0800000000000000000
+ENTRY_END
+
+STEP 2110 QUERY
+ENTRY_BEGIN
+RAW
+b5f8bd3650104462a07f0000000000000000
+ENTRY_END
+
+STEP 2120 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e4bf0000020405b401010402
+ENTRY_END
+
+STEP 2130 QUERY
+ENTRY_BEGIN
+RAW
+b5f94cd4501044700a360000000000000000
+ENTRY_END
+
+STEP 2140 QUERY
+ENTRY_BEGIN
+RAW
+b5f94cd450184470a70a0000008ebfc0000000010001000000000f313033303739323135313035382d330000f900010f313033303739323135313035382d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403af9aa403c4b2a00030000002f4e544c4d535350000100000097b200e0080008002700000007000700200000004445454e4b41414445454e4b4141300000
+ENTRY_END
+
+STEP 2150 QUERY
+ENTRY_BEGIN
+RAW
+b5f94ce25011446209a50000000000000000
+ENTRY_END
+
+STEP 2160 QUERY
+ENTRY_BEGIN
+RAW
+b5f94ce35010446209a40000000000000000
+ENTRY_END
+
+STEP 2170 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400012600000020405b401010402
+ENTRY_END
+
+STEP 2180 QUERY
+ENTRY_BEGIN
+RAW
+b5f9f08b50104470941e0000000000000000
+ENTRY_END
+
+STEP 2190 QUERY
+ENTRY_BEGIN
+RAW
+b5f9f08b50184470b7f40000008e39c0000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af9aa403c4b2a00030000002f4e544c4d535350000100000097b200e0080008002700000007000700200000004445454e4b41414445454e4b4141300000
+ENTRY_END
+
+STEP 2200 QUERY
+ENTRY_BEGIN
+RAW
+b5f9f09950114462938d0000000000000000
+ENTRY_END
+
+STEP 2210 QUERY
+ENTRY_BEGIN
+RAW
+b5f9f09a50104462938c0000000000000000
+ENTRY_END
+
+STEP 2220 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400009cf0000020405b401010402
+ENTRY_END
+
+STEP 2230 QUERY
+ENTRY_BEGIN
+RAW
+b5fc831750104470f8fe0000000000000000
+ENTRY_END
+
+STEP 2240 QUERY
+ENTRY_BEGIN
+RAW
+b5fc83175018447044550000008e1240000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af9aa403c4b2a00030000002f4e544c4d535350000100000097b200e0080008002700000007000700200000004445454e4b41414445454e4b4141300000
+ENTRY_END
+
+STEP 2250 QUERY
+ENTRY_BEGIN
+RAW
+b5fc832550114462f86d0000000000000000
+ENTRY_END
+
+STEP 2260 QUERY
+ENTRY_BEGIN
+RAW
+b5fc832650104462f86c0000000000000000
+ENTRY_END
+
+STEP 2270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400018250000020405ac01010402
+ENTRY_END
+
+STEP 2280 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf09f980000020405b401010402
+ENTRY_END
+
+STEP 2290 QUERY
+ENTRY_BEGIN
+RAW
+b5fde23c5010fbec33160000000000000000
+ENTRY_END
+
+STEP 2300 QUERY
+ENTRY_BEGIN
+RAW
+b5fd4fd4501044103aef0000000000000000
+ENTRY_END
+
+STEP 2310 QUERY
+ENTRY_BEGIN
+RAW
+b5fde23c5018fbece71a0000008d8180000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff2f403c50af00030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 2320 QUERY
+ENTRY_BEGIN
+RAW
+b5fd4fd45018441087bb00000094248d000000010001000000000f313031333631323238313837342d320000f900010f313031333631323238313837342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af729403c48a90003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 2330 QUERY
+ENTRY_BEGIN
+RAW
+b5fde24a5011fbde32860000000000000000
+ENTRY_END
+
+STEP 2340 QUERY
+ENTRY_BEGIN
+RAW
+b5fd4fe2501144023a580000000000000000
+ENTRY_END
+
+STEP 2350 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0eeb60000020405b401010402
+ENTRY_END
+
+STEP 2360 QUERY
+ENTRY_BEGIN
+RAW
+b5fde24b5010fbde32850000000000000000
+ENTRY_END
+
+STEP 2370 QUERY
+ENTRY_BEGIN
+RAW
+b5fd4fe3501044023a570000000000000000
+ENTRY_END
+
+STEP 2380 QUERY
+ENTRY_BEGIN
+RAW
+b5feceaf5010fbec95c00000000000000000
+ENTRY_END
+
+STEP 2390 QUERY
+ENTRY_BEGIN
+RAW
+b5feceaf5018fbecfa450000008dd200000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff2f403c50af00030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 2400 QUERY
+ENTRY_BEGIN
+RAW
+b5fecebd5011fbde95300000000000000000
+ENTRY_END
+
+STEP 2410 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f3a80000020405b401010402
+ENTRY_END
+
+STEP 2420 QUERY
+ENTRY_BEGIN
+RAW
+b5fecebe5010fbde952f0000000000000000
+ENTRY_END
+
+STEP 2430 QUERY
+ENTRY_BEGIN
+RAW
+b5ff56835010fbec12de0000000000000000
+ENTRY_END
+
+STEP 2440 QUERY
+ENTRY_BEGIN
+RAW
+b5ff56835018fbec30e40000008d1880000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff2f403c50af00030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 2450 QUERY
+ENTRY_BEGIN
+RAW
+b5ff56915011fbde124e0000000000000000
+ENTRY_END
+
+STEP 2460 QUERY
+ENTRY_BEGIN
+RAW
+b5ff56925010fbde124d0000000000000000
+ENTRY_END
+
+STEP 2470 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0467900000204056401010402
+ENTRY_END
+
+STEP 2480 QUERY
+ENTRY_BEGIN
+RAW
+b6062f415010fd5c8b290000000000000000
+ENTRY_END
+
+STEP 2490 QUERY
+ENTRY_BEGIN
+RAW
+b6062f415018fd5c71600000008f9dd8000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcc8403c4e480003000000304e544c4d535350000100000097b208e0050005002b0000000b000b00200000005a5745524d5345525645525a5745524d0000
+ENTRY_END
+
+STEP 2500 QUERY
+ENTRY_BEGIN
+RAW
+b6062f4f5011fd4e8a970000000000000000
+ENTRY_END
+
+STEP 2510 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b12900000204056401010402
+ENTRY_END
+
+STEP 2520 QUERY
+ENTRY_BEGIN
+RAW
+b6062f505010fd4e8a960000000000000000
+ENTRY_END
+
+STEP 2530 QUERY
+ENTRY_BEGIN
+RAW
+b6071d2d5010fd5c07ed0000000000000000
+ENTRY_END
+
+STEP 2540 QUERY
+ENTRY_BEGIN
+RAW
+b6071d2d5018fd5c32830000008f5a7a000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcc8403c4e480003000000304e544c4d535350000100000097b208e0050005002b0000000b000b00200000005a5745524d5345525645525a5745524d0000
+ENTRY_END
+
+STEP 2550 QUERY
+ENTRY_BEGIN
+RAW
+b6071d3b5011fd4e075b0000000000000000
+ENTRY_END
+
+STEP 2560 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08f9300000204056401010402
+ENTRY_END
+
+STEP 2570 QUERY
+ENTRY_BEGIN
+RAW
+b6071d3c5010fd4e075a0000000000000000
+ENTRY_END
+
+STEP 2580 QUERY
+ENTRY_BEGIN
+RAW
+b607bf705010fd5c44130000000000000000
+ENTRY_END
+
+STEP 2590 QUERY
+ENTRY_BEGIN
+RAW
+b607bf705018fd5c5fe70000008f693c000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcc8403c4e480003000000304e544c4d535350000100000097b208e0050005002b0000000b000b00200000005a5745524d5345525645525a5745524d0000
+ENTRY_END
+
+STEP 2600 QUERY
+ENTRY_BEGIN
+RAW
+b607bf7e5011fd4e43810000000000000000
+ENTRY_END
+
+STEP 2610 QUERY
+ENTRY_BEGIN
+RAW
+b607bf7f5010fd4e43800000000000000000
+ENTRY_END
+
+;STEP 2620 QUERY
+;ENTRY_BEGIN
+;RAW
+;0774000000010000000000000b7374617274706167696e61026e6c00000f000100
+;ENTRY_END
+
+STEP 2630 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000aa5b0000020405b401010402
+ENTRY_END
+
+STEP 2640 QUERY
+ENTRY_BEGIN
+RAW
+b6099d2a501044707f6b0000000000000000
+ENTRY_END
+
+STEP 2650 QUERY
+ENTRY_BEGIN
+RAW
+b6099d2a50184470d042000000994920000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda4403c1f2400030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 2660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf04e890000020405b401010402
+ENTRY_END
+
+STEP 2670 QUERY
+ENTRY_BEGIN
+RAW
+b6099d38501144627ecf0000000000000000
+ENTRY_END
+
+STEP 2680 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c30f0000020405b401010402
+ENTRY_END
+
+STEP 2690 QUERY
+ENTRY_BEGIN
+RAW
+b6099d39501044627ece0000000000000000
+ENTRY_END
+
+STEP 2700 QUERY
+ENTRY_BEGIN
+RAW
+b60a3e1850104470f7300000000000000000
+ENTRY_END
+
+STEP 2710 QUERY
+ENTRY_BEGIN
+RAW
+b60a3e1850184470acd800000099e550000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda4403c1f2400030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 2720 QUERY
+ENTRY_BEGIN
+RAW
+b60a3e2650114462f6940000000000000000
+ENTRY_END
+
+STEP 2730 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c42f0000020405b401010402
+ENTRY_END
+
+STEP 2740 QUERY
+ENTRY_BEGIN
+RAW
+b60a3e2750104462f6930000000000000000
+ENTRY_END
+
+STEP 2750 QUERY
+ENTRY_BEGIN
+RAW
+b60b1d975010447018d10000000000000000
+ENTRY_END
+
+STEP 2760 QUERY
+ENTRY_BEGIN
+RAW
+b60b1d97501844708c99000000992530000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403acda5403c1f2500030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000005343414e4449542d5345525645525343414e44495453525630310000
+ENTRY_END
+
+STEP 2770 QUERY
+ENTRY_BEGIN
+RAW
+b60b1da55011446218350000000000000000
+ENTRY_END
+
+STEP 2780 QUERY
+ENTRY_BEGIN
+RAW
+b60b1da65010446218340000000000000000
+ENTRY_END
+
+;STEP 2790 QUERY
+;ENTRY_BEGIN
+;RAW
+;2bfa01000001000000000000056b6f726e6f026e6c00000f000100
+;ENTRY_END
+
+STEP 2800 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400088c600000204057a01010402
+ENTRY_END
+
+STEP 2810 QUERY
+ENTRY_BEGIN
+RAW
+b610654e501041b898290000000000000000
+ENTRY_END
+
+STEP 2820 QUERY
+ENTRY_BEGIN
+RAW
+b610654e501841b8139400000090d480000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff54403c50d40003000000314e544c4d535350000100000097b208e00a000a002700000007000700200000005345525645523453504f525443495459340000
+ENTRY_END
+
+STEP 2830 QUERY
+ENTRY_BEGIN
+RAW
+b610655c501141aa97960000000000000000
+ENTRY_END
+
+STEP 2840 QUERY
+ENTRY_BEGIN
+RAW
+b610655d501041aa97950000000000000000
+ENTRY_END
+
+STEP 2850 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008aa700000204057a01010402
+ENTRY_END
+
+STEP 2860 QUERY
+ENTRY_BEGIN
+RAW
+b6125547501041b8aa0f0000000000000000
+ENTRY_END
+
+STEP 2870 QUERY
+ENTRY_BEGIN
+RAW
+b6125547501841b804fb00000090f600000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff54403c50d40003000000314e544c4d535350000100000097b208e00a000a002700000007000700200000005345525645523453504f525443495459340000
+ENTRY_END
+
+STEP 2880 QUERY
+ENTRY_BEGIN
+RAW
+b6125555501141aaa97c0000000000000000
+ENTRY_END
+
+STEP 2890 QUERY
+ENTRY_BEGIN
+RAW
+b6125556501041aaa97b0000000000000000
+ENTRY_END
+
+STEP 2900 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e70d00000204057a01010402
+ENTRY_END
+
+STEP 2910 QUERY
+ENTRY_BEGIN
+RAW
+b6132124501041b83a980000000000000000
+ENTRY_END
+
+STEP 2920 QUERY
+ENTRY_BEGIN
+RAW
+b6132124501841b871c40000009019c0000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff54403c50d40003000000314e544c4d535350000100000097b208e00a000a002700000007000700200000005345525645523453504f525443495459340000
+ENTRY_END
+
+STEP 2930 QUERY
+ENTRY_BEGIN
+RAW
+b6132132501141aa3a050000000000000000
+ENTRY_END
+
+STEP 2940 QUERY
+ENTRY_BEGIN
+RAW
+b6132133501041aa3a040000000000000000
+ENTRY_END
+
+STEP 2950 QUERY
+ENTRY_BEGIN
+RAW
+5b2f083d50040000c2170000000000000000
+ENTRY_END
+
+STEP 2960 QUERY
+ENTRY_BEGIN
+RAW
+0000000060025e38cd070000020405b40000
+ENTRY_END
+
+STEP 2970 QUERY
+ENTRY_BEGIN
+RAW
+b6185ae050102da004540000000000000000
+ENTRY_END
+
+STEP 2980 QUERY
+ENTRY_BEGIN
+RAW
+b6185ae050102da081160000008c4dd3000000010001000000000e3932373731323933353935342d330000f900010e3932373731323933353935342d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd65403c4ee500030000002f4e544c4d535350000100000097b200e0050005002a0000000a000a0020000000434f4d505554455231384e504942560000
+ENTRY_END
+
+STEP 2990 QUERY
+ENTRY_BEGIN
+RAW
+b6185aee501027ec096c0000000000000000
+ENTRY_END
+
+STEP 3000 QUERY
+ENTRY_BEGIN
+RAW
+b6185aee50112da003b70000000000000000
+ENTRY_END
+
+STEP 3010 QUERY
+ENTRY_BEGIN
+RAW
+b6185aee50102da003b70000000000000000
+ENTRY_END
+
+STEP 3020 QUERY
+ENTRY_BEGIN
+RAW
+0000000060025e3872b90000020405b40000
+ENTRY_END
+
+STEP 3030 QUERY
+ENTRY_BEGIN
+RAW
+b61b831350102da081cf0000000000000000
+ENTRY_END
+
+STEP 3040 QUERY
+ENTRY_BEGIN
+RAW
+b61b831350102da0dc970000008c6fcd000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd66403c4ee600030000002f4e544c4d535350000100000097b200e0050005002a0000000a000a0020000000434f4d505554455231384e504942560000
+ENTRY_END
+
+STEP 3050 QUERY
+ENTRY_BEGIN
+RAW
+b61b8321501027ec86e70000000000000000
+ENTRY_END
+
+STEP 3060 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf093c900000204059801010402
+ENTRY_END
+
+STEP 3070 QUERY
+ENTRY_BEGIN
+RAW
+b61d400b5010fbb8c9700000000000000000
+ENTRY_END
+
+STEP 3080 QUERY
+ENTRY_BEGIN
+RAW
+b61d400b5018fbb85398000000946438000000010001000000000f313237313331303331393633342d330000f900010f313237313331303331393633342d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403af8e4403c4a640003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 3090 QUERY
+ENTRY_BEGIN
+RAW
+b61d40195011fbaac8d90000000000000000
+ENTRY_END
+
+STEP 3100 QUERY
+ENTRY_BEGIN
+RAW
+b61d401a5010fbaac8d80000000000000000
+ENTRY_END
+
+STEP 3110 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0abe200000204059801010402
+ENTRY_END
+
+STEP 3120 QUERY
+ENTRY_BEGIN
+RAW
+b6185aef50102da003b60000000000000000
+ENTRY_END
+
+STEP 3130 QUERY
+ENTRY_BEGIN
+RAW
+b61f52c65010fbb8cecc0000000000000000
+ENTRY_END
+
+STEP 3140 QUERY
+ENTRY_BEGIN
+RAW
+b61f52c65018fbb8714c000000944ae1000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af8e5403c4a650003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 3150 QUERY
+ENTRY_BEGIN
+RAW
+b61f52d45011fbaace350000000000000000
+ENTRY_END
+
+STEP 3160 QUERY
+ENTRY_BEGIN
+RAW
+b61f52d55010fbaace340000000000000000
+ENTRY_END
+
+STEP 3170 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06bd800000204059801010402
+ENTRY_END
+
+STEP 3180 QUERY
+ENTRY_BEGIN
+RAW
+b62004255010fbb8dd620000000000000000
+ENTRY_END
+
+STEP 3190 QUERY
+ENTRY_BEGIN
+RAW
+b62004255018fbb8ea1f00000094e0a3000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af8e5403c4a650003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 3200 QUERY
+ENTRY_BEGIN
+RAW
+b62004335011fbaadccb0000000000000000
+ENTRY_END
+
+STEP 3210 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf02c3a0000020405b401010402
+ENTRY_END
+
+STEP 3220 QUERY
+ENTRY_BEGIN
+RAW
+b62004345010fbaadcca0000000000000000
+ENTRY_END
+
+STEP 3230 QUERY
+ENTRY_BEGIN
+RAW
+b620f85c5010faf0aa700000000000000000
+ENTRY_END
+
+STEP 3240 QUERY
+ENTRY_BEGIN
+RAW
+b620f85c5018faf073ec00000095ab9c000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc88403c4e080003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+;STEP 3250 QUERY
+;ENTRY_BEGIN
+;RAW
+;00780000000100000000000007736d756c776562026e6c00000f0001c0
+;ENTRY_END
+
+STEP 3260 QUERY
+ENTRY_BEGIN
+RAW
+b620f86a5011fae2a9d80000000000000000
+ENTRY_END
+
+STEP 3270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d0ad0000020405b401010402
+ENTRY_END
+
+STEP 3280 QUERY
+ENTRY_BEGIN
+RAW
+b620f86b5010fae2a9d70000000000000000
+ENTRY_END
+
+STEP 3290 QUERY
+ENTRY_BEGIN
+RAW
+b621d5c55010faf0717a0000000000000000
+ENTRY_END
+
+STEP 3300 QUERY
+ENTRY_BEGIN
+RAW
+b621d5c55018faf0905b000000955738000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc88403c4e080003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+STEP 3310 QUERY
+ENTRY_BEGIN
+RAW
+b61b832150112da081320000000000000000
+ENTRY_END
+
+STEP 3320 QUERY
+ENTRY_BEGIN
+RAW
+b621d5d35011fae270e20000000000000000
+ENTRY_END
+
+STEP 3330 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf04b080000020405b401010402
+ENTRY_END
+
+STEP 3340 QUERY
+ENTRY_BEGIN
+RAW
+b621d5d45010fae270e10000000000000000
+ENTRY_END
+
+STEP 3350 QUERY
+ENTRY_BEGIN
+RAW
+0000000060025e38547f0000020405b40000
+ENTRY_END
+
+STEP 3360 QUERY
+ENTRY_BEGIN
+RAW
+b62289055010faf038940000000000000000
+ENTRY_END
+
+STEP 3370 QUERY
+ENTRY_BEGIN
+RAW
+b6234c9c50102da09a040000000000000000
+ENTRY_END
+
+STEP 3380 QUERY
+ENTRY_BEGIN
+RAW
+b62289055018faf0abd90000009502d4000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc88403c4e080003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+STEP 3390 QUERY
+ENTRY_BEGIN
+RAW
+b62289135011fae237fc0000000000000000
+ENTRY_END
+
+STEP 3400 QUERY
+ENTRY_BEGIN
+RAW
+b62289145010fae237fb0000000000000000
+ENTRY_END
+
+STEP 3410 QUERY
+ENTRY_BEGIN
+RAW
+b6234c9c50102da027580000008c3b42000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd67403c4ee700030000002f4e544c4d535350000100000097b200e0050005002a0000000a000a0020000000434f4d505554455231384e504942560000
+ENTRY_END
+
+STEP 3420 QUERY
+ENTRY_BEGIN
+RAW
+b6234caa501027ec9f1c0000000000000000
+ENTRY_END
+
+STEP 3430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f8cf0000020405b401010402
+ENTRY_END
+
+STEP 3440 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000deb700000204059801010402
+ENTRY_END
+
+STEP 3450 QUERY
+ENTRY_BEGIN
+RAW
+b62553b65010faf01ba80000000000000000
+ENTRY_END
+
+STEP 3460 QUERY
+ENTRY_BEGIN
+RAW
+b625d01e5010432081eb0000000000000000
+ENTRY_END
+
+STEP 3470 QUERY
+ENTRY_BEGIN
+RAW
+b625d01e50184320ce84000000850690000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8be403c4a3e0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 3480 QUERY
+ENTRY_BEGIN
+RAW
+b62553b65018faf087e70000009508d9000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc88403c4e080003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+STEP 3490 QUERY
+ENTRY_BEGIN
+RAW
+b625d02c5011431281630000000000000000
+ENTRY_END
+
+STEP 3500 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000cc4600000204059801010402
+ENTRY_END
+
+STEP 3510 QUERY
+ENTRY_BEGIN
+RAW
+b625d02d5010431281620000000000000000
+ENTRY_END
+
+STEP 3520 QUERY
+ENTRY_BEGIN
+RAW
+b62553c45011fae21b100000000000000000
+ENTRY_END
+
+STEP 3530 QUERY
+ENTRY_BEGIN
+RAW
+b6267f7450104320c0230000000000000000
+ENTRY_END
+
+STEP 3540 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0ccf40000020405b401010402
+ENTRY_END
+
+STEP 3550 QUERY
+ENTRY_BEGIN
+RAW
+b6267f74501843201fcd00000085f480000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8be403c4a3e0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 3560 QUERY
+ENTRY_BEGIN
+RAW
+b6267f8250114312bf9b0000000000000000
+ENTRY_END
+
+STEP 3570 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033b600000204059801010402
+ENTRY_END
+
+STEP 3580 QUERY
+ENTRY_BEGIN
+RAW
+b62553c55010fae21b0f0000000000000000
+ENTRY_END
+
+STEP 3590 QUERY
+ENTRY_BEGIN
+RAW
+b6267f8350104312bf9a0000000000000000
+ENTRY_END
+
+STEP 3600 QUERY
+ENTRY_BEGIN
+RAW
+b629a6275010432000dd0000000000000000
+ENTRY_END
+
+STEP 3610 QUERY
+ENTRY_BEGIN
+RAW
+b629a62750184320d786000000857d80000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8be403c4a3e0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 3620 QUERY
+ENTRY_BEGIN
+RAW
+b629a6355011431200550000000000000000
+ENTRY_END
+
+STEP 3630 QUERY
+ENTRY_BEGIN
+RAW
+b61b832250102da081310000000000000000
+ENTRY_END
+
+STEP 3640 QUERY
+ENTRY_BEGIN
+RAW
+b627516b5010faf0f2150000000000000000
+ENTRY_END
+
+STEP 3650 QUERY
+ENTRY_BEGIN
+RAW
+b629a6365010431200540000000000000000
+ENTRY_END
+
+STEP 3660 QUERY
+ENTRY_BEGIN
+RAW
+b627516b5018faf0847000000095e1be000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc89403c4e090003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+STEP 3670 QUERY
+ENTRY_BEGIN
+RAW
+b62751795011fae2f17d0000000000000000
+ENTRY_END
+
+STEP 3680 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf094de0000020405b401010402
+ENTRY_END
+
+STEP 3690 QUERY
+ENTRY_BEGIN
+RAW
+b627517a5010fae2f17c0000000000000000
+ENTRY_END
+
+STEP 3700 QUERY
+ENTRY_BEGIN
+RAW
+b62a382a5010faf0d33d0000000000000000
+ENTRY_END
+
+STEP 3710 QUERY
+ENTRY_BEGIN
+RAW
+b62a382a5018faf0b9fc000000958d5a000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afc89403c4e090003000000364e544c4d535350000100000097b208e0080008002e0000000e000e002000000050484149522d52544d2d4d41494e504841495252544d0000
+ENTRY_END
+
+STEP 3720 QUERY
+ENTRY_BEGIN
+RAW
+b62a38385011fae2d2a50000000000000000
+ENTRY_END
+
+STEP 3730 QUERY
+ENTRY_BEGIN
+RAW
+b62a38395010fae2d2a40000000000000000
+ENTRY_END
+
+STEP 3740 QUERY
+ENTRY_BEGIN
+RAW
+b6234caa50112da099670000000000000000
+ENTRY_END
+
+;STEP 3750 QUERY
+;ENTRY_BEGIN
+;RAW
+;17a00000000100000000000009726f7a656e62757267026e6c00000f000100
+;ENTRY_END
+
+STEP 3760 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000eb890000020405b401010402
+ENTRY_END
+
+STEP 3770 QUERY
+ENTRY_BEGIN
+RAW
+b62c80b350104470dced0000000000000000
+ENTRY_END
+
+STEP 3780 QUERY
+ENTRY_BEGIN
+RAW
+b62c80b3501844706614000000979708000000010001000000000f313432353932393134323239302d330000f900010f313432353932393134323239302d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 3790 QUERY
+ENTRY_BEGIN
+RAW
+b62c80c150114462dc530000000000000000
+ENTRY_END
+
+STEP 3800 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000beea0000020405b401010402
+ENTRY_END
+
+STEP 3810 QUERY
+ENTRY_BEGIN
+RAW
+b6234cab50102da099660000000000000000
+ENTRY_END
+
+STEP 3820 QUERY
+ENTRY_BEGIN
+RAW
+b62c80c250104462dc520000000000000000
+ENTRY_END
+
+STEP 3830 QUERY
+ENTRY_BEGIN
+RAW
+b62f3e5b50104470f2a30000000000000000
+ENTRY_END
+
+STEP 3840 QUERY
+ENTRY_BEGIN
+RAW
+b62f3e5b50184470267d00000097ed56000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 3850 QUERY
+ENTRY_BEGIN
+RAW
+b62f3e6950114462f2090000000000000000
+ENTRY_END
+
+STEP 3860 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d4da0000020405b401010402
+ENTRY_END
+
+STEP 3870 QUERY
+ENTRY_BEGIN
+RAW
+b62f3e6a50104462f2080000000000000000
+ENTRY_END
+
+STEP 3880 QUERY
+ENTRY_BEGIN
+RAW
+b62fc881501044707e6d0000000000000000
+ENTRY_END
+
+STEP 3890 QUERY
+ENTRY_BEGIN
+RAW
+b62fc88150184470880000000097179d000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 3900 QUERY
+ENTRY_BEGIN
+RAW
+b62fc88f501144627dd30000000000000000
+ENTRY_END
+
+STEP 3910 QUERY
+ENTRY_BEGIN
+RAW
+b62fc890501044627dd20000000000000000
+ENTRY_END
+
+STEP 3920 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ace50000020405b401010402
+ENTRY_END
+
+STEP 3930 QUERY
+ENTRY_BEGIN
+RAW
+b630894a5010447095ae0000000000000000
+ENTRY_END
+
+STEP 3940 QUERY
+ENTRY_BEGIN
+RAW
+b630894a50184470b7ad00000097fe2f000000010001000000000f313432353932393134323239302d330000f900010f313432353932393134323239302d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 3950 QUERY
+ENTRY_BEGIN
+RAW
+b63089585011446295140000000000000000
+ENTRY_END
+
+STEP 3960 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000dc510000020405b401010402
+ENTRY_END
+
+STEP 3970 QUERY
+ENTRY_BEGIN
+RAW
+b63089595010446295130000000000000000
+ENTRY_END
+
+STEP 3980 QUERY
+ENTRY_BEGIN
+RAW
+b63142c6501044700b9e0000000000000000
+ENTRY_END
+
+STEP 3990 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e78400000204056401010402
+ENTRY_END
+
+STEP 4000 QUERY
+ENTRY_BEGIN
+RAW
+b63142c650184470ef4d000000973d80000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 4010 QUERY
+ENTRY_BEGIN
+RAW
+b631e3bb501040b0794b0000000000000000
+ENTRY_END
+
+STEP 4020 QUERY
+ENTRY_BEGIN
+RAW
+b631e3bb501840b0823000000084dc00000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000004a03677373096d6963726f736f667403636f6d00403afd0c403c4e8c0003000000274e544c4d535350000100000097b200c003000300240000000400040020000000534441374445500000
+ENTRY_END
+
+STEP 4030 QUERY
+ENTRY_BEGIN
+RAW
+b631e3c9501140a278c40000000000000000
+ENTRY_END
+
+STEP 4040 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000012100000204056401010402
+ENTRY_END
+
+STEP 4050 QUERY
+ENTRY_BEGIN
+RAW
+b63142d4501144620b040000000000000000
+ENTRY_END
+
+STEP 4060 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000cfba0000020405b401010402
+ENTRY_END
+
+STEP 4070 QUERY
+ENTRY_BEGIN
+RAW
+b631e3ca501040a278c30000000000000000
+ENTRY_END
+
+STEP 4080 QUERY
+ENTRY_BEGIN
+RAW
+b632940b501040b0e2960000000000000000
+ENTRY_END
+
+STEP 4090 QUERY
+ENTRY_BEGIN
+RAW
+b632940b501840b0167c00000084b300000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000004a03677373096d6963726f736f667403636f6d00403afd0c403c4e8c0003000000274e544c4d535350000100000097b200c003000300240000000400040020000000534441374445500000
+ENTRY_END
+
+STEP 4100 QUERY
+ENTRY_BEGIN
+RAW
+b6329419501140a2e20f0000000000000000
+ENTRY_END
+
+STEP 4110 QUERY
+ENTRY_BEGIN
+RAW
+b63142d5501044620b030000000000000000
+ENTRY_END
+
+STEP 4120 QUERY
+ENTRY_BEGIN
+RAW
+b632941a501040a2e20e0000000000000000
+ENTRY_END
+
+STEP 4130 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004da000000204056401010402
+ENTRY_END
+
+STEP 4140 QUERY
+ENTRY_BEGIN
+RAW
+b63367f650104470d9d40000000000000000
+ENTRY_END
+
+STEP 4150 QUERY
+ENTRY_BEGIN
+RAW
+b6345892501040b06a8d0000000000000000
+ENTRY_END
+
+STEP 4160 QUERY
+ENTRY_BEGIN
+RAW
+b6345892501840b0dbf2000000847580000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000004a03677373096d6963726f736f667403636f6d00403afd0c403c4e8c0003000000274e544c4d535350000100000097b200c003000300240000000400040020000000534441374445500000
+ENTRY_END
+
+STEP 4170 QUERY
+ENTRY_BEGIN
+RAW
+b63367f650184470f6430000009704c1000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe2403c4d620003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 4180 QUERY
+ENTRY_BEGIN
+RAW
+b63458a0501140a26a060000000000000000
+ENTRY_END
+
+STEP 4190 QUERY
+ENTRY_BEGIN
+RAW
+b63458a1501040a26a050000000000000000
+ENTRY_END
+
+STEP 4200 QUERY
+ENTRY_BEGIN
+RAW
+b633680450114462d93a0000000000000000
+ENTRY_END
+
+STEP 4210 QUERY
+ENTRY_BEGIN
+RAW
+b633680550104462d9390000000000000000
+ENTRY_END
+
+STEP 4220 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff0045bd00000204055001010402
+ENTRY_END
+
+STEP 4230 QUERY
+ENTRY_BEGIN
+RAW
+b6392e195010ff008dba0000000000000000
+ENTRY_END
+
+STEP 4240 QUERY
+ENTRY_BEGIN
+RAW
+b6392e195018ff0004e90000008fedfc000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdf0403c4f700003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+;STEP 4250 QUERY
+;ENTRY_BEGIN
+;RAW
+;044f00000001000000000000076275726d656573026e6c00000f000100
+;ENTRY_END
+
+STEP 4260 QUERY
+ENTRY_BEGIN
+RAW
+b6392e275011fef28d280000000000000000
+ENTRY_END
+
+STEP 4270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff0080c700000204055001010402
+ENTRY_END
+
+STEP 4280 QUERY
+ENTRY_BEGIN
+RAW
+b6392e285010fef28d270000000000000000
+ENTRY_END
+
+STEP 4290 QUERY
+ENTRY_BEGIN
+RAW
+b63a092c5010ff00edb00000000000000000
+ENTRY_END
+
+STEP 4300 QUERY
+ENTRY_BEGIN
+RAW
+b63a092c5018ff0081700000008fd26c000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdf0403c4f700003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+STEP 4310 QUERY
+ENTRY_BEGIN
+RAW
+b63a093a5011fef2ed1e0000000000000000
+ENTRY_END
+
+STEP 4320 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff008e7500000204055001010402
+ENTRY_END
+
+STEP 4330 QUERY
+ENTRY_BEGIN
+RAW
+b63a093b5010fef2ed1d0000000000000000
+ENTRY_END
+
+STEP 4340 QUERY
+ENTRY_BEGIN
+RAW
+b63adcf25010ff0027980000000000000000
+ENTRY_END
+
+STEP 4350 QUERY
+ENTRY_BEGIN
+RAW
+b63adcf25018ff0091310000008ffc92000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdf0403c4f700003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+STEP 4360 QUERY
+ENTRY_BEGIN
+RAW
+b63add005011fef227060000000000000000
+ENTRY_END
+
+STEP 4370 QUERY
+ENTRY_BEGIN
+RAW
+b63add015010fef227050000000000000000
+ENTRY_END
+
+STEP 4380 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000aeff0000020405b401010402
+ENTRY_END
+
+STEP 4390 QUERY
+ENTRY_BEGIN
+RAW
+b63fd61a5010080087590000000000000000
+ENTRY_END
+
+STEP 4400 QUERY
+ENTRY_BEGIN
+RAW
+b63fd61a501044704ae90000000000000000
+ENTRY_END
+
+STEP 4410 QUERY
+ENTRY_BEGIN
+RAW
+b63fd61a50184470a0020000008f603e000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afc48403c4dc80003000000324e544c4d535350000100000097b208e0050005002d0000000d000d0020000000434f4d5345525645523230303041442d4d420000
+ENTRY_END
+
+STEP 4420 QUERY
+ENTRY_BEGIN
+RAW
+b63fd628501144624a570000000000000000
+ENTRY_END
+
+STEP 4430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400083b30000020405b401010402
+ENTRY_END
+
+STEP 4440 QUERY
+ENTRY_BEGIN
+RAW
+b63fd629501044624a560000000000000000
+ENTRY_END
+
+STEP 4450 QUERY
+ENTRY_BEGIN
+RAW
+b6409f8850100800929e0000000000000000
+ENTRY_END
+
+STEP 4460 QUERY
+ENTRY_BEGIN
+RAW
+b6409f8850104470562e0000000000000000
+ENTRY_END
+
+STEP 4470 QUERY
+ENTRY_BEGIN
+RAW
+b6409f885018447052af0000008fbad6000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afc48403c4dc80003000000324e544c4d535350000100000097b208e0050005002d0000000d000d0020000000434f4d5345525645523230303041442d4d420000
+ENTRY_END
+
+STEP 4480 QUERY
+ENTRY_BEGIN
+RAW
+b6409f9650114462559c0000000000000000
+ENTRY_END
+
+STEP 4490 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400034540000020405b401010402
+ENTRY_END
+
+STEP 4500 QUERY
+ENTRY_BEGIN
+RAW
+b6409f9750104462559b0000000000000000
+ENTRY_END
+
+STEP 4510 QUERY
+ENTRY_BEGIN
+RAW
+b64185ae501008005d180000000000000000
+ENTRY_END
+
+STEP 4520 QUERY
+ENTRY_BEGIN
+RAW
+b64185ae5010447020a80000000000000000
+ENTRY_END
+
+STEP 4530 QUERY
+ENTRY_BEGIN
+RAW
+b64185ae5018447000890000008fd776000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afc48403c4dc80003000000324e544c4d535350000100000097b208e0050005002d0000000d000d0020000000434f4d5345525645523230303041442d4d420000
+ENTRY_END
+
+STEP 4540 QUERY
+ENTRY_BEGIN
+RAW
+b64185bc5011446220160000000000000000
+ENTRY_END
+
+STEP 4550 QUERY
+ENTRY_BEGIN
+RAW
+b64185bd5010446220150000000000000000
+ENTRY_END
+
+STEP 4560 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f7cc00000204056401010402
+ENTRY_END
+
+STEP 4570 QUERY
+ENTRY_BEGIN
+RAW
+b643986d5010fd5cd3130000000000000000
+ENTRY_END
+
+STEP 4580 QUERY
+ENTRY_BEGIN
+RAW
+b643986d5018fd5cc6f90000008e6466000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afda1403c4f2100030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 4590 QUERY
+ENTRY_BEGIN
+RAW
+b643987b5011fd4ed2820000000000000000
+ENTRY_END
+
+STEP 4600 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf01fca00000204056401010402
+ENTRY_END
+
+STEP 4610 QUERY
+ENTRY_BEGIN
+RAW
+b643987c5010fd4ed2810000000000000000
+ENTRY_END
+
+STEP 4620 QUERY
+ENTRY_BEGIN
+RAW
+b6441ee65010fd5c74970000000000000000
+ENTRY_END
+
+STEP 4630 QUERY
+ENTRY_BEGIN
+RAW
+b6441ee65018fd5ccbe40000008e0000000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afda2403c4f2200030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 4640 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b61d0000020405b401010402
+ENTRY_END
+
+STEP 4650 QUERY
+ENTRY_BEGIN
+RAW
+b6441ef45011fd4e74060000000000000000
+ENTRY_END
+
+STEP 4660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08df200000204056401010402
+ENTRY_END
+
+STEP 4670 QUERY
+ENTRY_BEGIN
+RAW
+b645129150104470158b0000000000000000
+ENTRY_END
+
+STEP 4680 QUERY
+ENTRY_BEGIN
+RAW
+b645129150184470ce2a000000975080000000010001000000000f313337343338393533343733382d330000f900010f313337343338393533343733382d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe6403c4d660003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 4690 QUERY
+ENTRY_BEGIN
+RAW
+b6441ef55010fd4e74050000000000000000
+ENTRY_END
+
+STEP 4700 QUERY
+ENTRY_BEGIN
+RAW
+b645dd1c5010fd5c24880000000000000000
+ENTRY_END
+
+STEP 4710 QUERY
+ENTRY_BEGIN
+RAW
+b645dd1c5018fd5c00410000008e7b94000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afda2403c4f2200030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 4720 QUERY
+ENTRY_BEGIN
+RAW
+b645129f5011446214f10000000000000000
+ENTRY_END
+
+STEP 4730 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a3460000020405b401010402
+ENTRY_END
+
+STEP 4740 QUERY
+ENTRY_BEGIN
+RAW
+b645dd2a5011fd4e23f70000000000000000
+ENTRY_END
+
+STEP 4750 QUERY
+ENTRY_BEGIN
+RAW
+b645dd2b5010fd4e23f60000000000000000
+ENTRY_END
+
+STEP 4760 QUERY
+ENTRY_BEGIN
+RAW
+b64512a05010446214f00000000000000000
+ENTRY_END
+
+STEP 4770 QUERY
+ENTRY_BEGIN
+RAW
+b646af605010447065e30000000000000000
+ENTRY_END
+
+STEP 4780 QUERY
+ENTRY_BEGIN
+RAW
+b646af60501844707b4300000097f4c0000000010001000000000f313337343338393533343733382d320000f900010f313337343338393533343733382d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe6403c4d660003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 4790 QUERY
+ENTRY_BEGIN
+RAW
+b646af6e5011446265490000000000000000
+ENTRY_END
+
+STEP 4800 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400061b00000020405b401010402
+ENTRY_END
+
+STEP 4810 QUERY
+ENTRY_BEGIN
+RAW
+b646af6f5010446265480000000000000000
+ENTRY_END
+
+STEP 4820 QUERY
+ENTRY_BEGIN
+RAW
+b6473a8f50104470991d0000000000000000
+ENTRY_END
+
+STEP 4830 QUERY
+ENTRY_BEGIN
+RAW
+b6473a8f50184470b9bd00000097e980000000010001000000000f313337343338393533343733382d320000f900010f313337343338393533343733382d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afbe6403c4d660003000000384e544c4d535350000100000097b208e00a000a002e0000000e000e0020000000454c5354414c4144414d2d535256454c5354414c4144414d0000
+ENTRY_END
+
+STEP 4840 QUERY
+ENTRY_BEGIN
+RAW
+b6473a9d5011446298830000000000000000
+ENTRY_END
+
+STEP 4850 QUERY
+ENTRY_BEGIN
+RAW
+b6473a9e5010446298820000000000000000
+ENTRY_END
+
+STEP 4860 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e0620000020405b401010402
+ENTRY_END
+
+STEP 4870 QUERY
+ENTRY_BEGIN
+RAW
+b6498c2050104470c63c0000000000000000
+ENTRY_END
+
+STEP 4880 QUERY
+ENTRY_BEGIN
+RAW
+b6498c2050184470e776000000893428000000010001000000000f313230323539303834323839382d330000f900010f313230323539303834323839382d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefc403c507c00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 4890 QUERY
+ENTRY_BEGIN
+RAW
+b6498c2e50114462c5b00000000000000000
+ENTRY_END
+
+STEP 4900 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ad0d0000020405b401010402
+ENTRY_END
+
+STEP 4910 QUERY
+ENTRY_BEGIN
+RAW
+b6498c2f50104462c5af0000000000000000
+ENTRY_END
+
+STEP 4920 QUERY
+ENTRY_BEGIN
+RAW
+b64a5b3a50104470c3cc0000000000000000
+ENTRY_END
+
+STEP 4930 QUERY
+ENTRY_BEGIN
+RAW
+b64a5b3a50184470cb9f000000894e90000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefc403c507c00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 4940 QUERY
+ENTRY_BEGIN
+RAW
+b64a5b4850114462c3400000000000000000
+ENTRY_END
+
+STEP 4950 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400026120000020405b401010402
+ENTRY_END
+
+STEP 4960 QUERY
+ENTRY_BEGIN
+RAW
+b64a5b4950104462c33f0000000000000000
+ENTRY_END
+
+STEP 4970 QUERY
+ENTRY_BEGIN
+RAW
+b64b06c050104470914a0000000000000000
+ENTRY_END
+
+STEP 4980 QUERY
+ENTRY_BEGIN
+RAW
+b64b06c050184470367d00000089b130000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefc403c507c00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 4990 QUERY
+ENTRY_BEGIN
+RAW
+b64b06ce5011446290be0000000000000000
+ENTRY_END
+
+STEP 5000 QUERY
+ENTRY_BEGIN
+RAW
+b64b06cf5010446290bd0000000000000000
+ENTRY_END
+
+STEP 5010 QUERY
+ENTRY_BEGIN
+RAW
+186e0000000100000000000006736d7470303603777873026e6c00000f000100
+ENTRY_END
+
+STEP 5020 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400028290000020405b401010402
+ENTRY_END
+
+STEP 5030 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d1f10000020405b401010402
+ENTRY_END
+
+STEP 5040 QUERY
+ENTRY_BEGIN
+RAW
+b64dd61350104470c40b0000000000000000
+ENTRY_END
+
+STEP 5050 QUERY
+ENTRY_BEGIN
+RAW
+b64ea29c50104470a14a0000000000000000
+ENTRY_END
+
+STEP 5060 QUERY
+ENTRY_BEGIN
+RAW
+b64ea29c501844707cb60000009574fc000000010001000000000f313235343133303435303435302d330000f900010f313235343133303435303435302d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5070 QUERY
+ENTRY_BEGIN
+RAW
+b64dd61350184470dab1000000893cbc000000010001000000000f313230323539303834323839382d330000f900010f313230323539303834323839382d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefd403c507d00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 5080 QUERY
+ENTRY_BEGIN
+RAW
+b64ea2aa50114462a0b20000000000000000
+ENTRY_END
+
+STEP 5090 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008bd00000020405b401010402
+ENTRY_END
+
+STEP 5100 QUERY
+ENTRY_BEGIN
+RAW
+b64dd62150114462c37f0000000000000000
+ENTRY_END
+
+STEP 5110 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000031c0000020405b401010402
+ENTRY_END
+
+STEP 5120 QUERY
+ENTRY_BEGIN
+RAW
+b64ea2ab50104462a0b10000000000000000
+ENTRY_END
+
+STEP 5130 QUERY
+ENTRY_BEGIN
+RAW
+b64f4bce50104470b1f60000000000000000
+ENTRY_END
+
+STEP 5140 QUERY
+ENTRY_BEGIN
+RAW
+b64f4bce50184470dc7f0000009526e0000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5150 QUERY
+ENTRY_BEGIN
+RAW
+b64dd62250104462c37e0000000000000000
+ENTRY_END
+
+STEP 5160 QUERY
+ENTRY_BEGIN
+RAW
+040b00000001000000000000116672616e6b656e656e76616e7765657274026e6c00000f000100
+ENTRY_END
+
+STEP 5170 QUERY
+ENTRY_BEGIN
+RAW
+b64fffa85010447075670000000000000000
+ENTRY_END
+
+STEP 5180 QUERY
+ENTRY_BEGIN
+RAW
+b64f4bdc50114462b15e0000000000000000
+ENTRY_END
+
+STEP 5190 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400091e30000020405b401010402
+ENTRY_END
+
+STEP 5200 QUERY
+ENTRY_BEGIN
+RAW
+b64fffa8501844702a6e000000899f5c000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefd403c507d00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 5210 QUERY
+ENTRY_BEGIN
+RAW
+b64f4bdd50104462b15d0000000000000000
+ENTRY_END
+
+STEP 5220 QUERY
+ENTRY_BEGIN
+RAW
+b6509596501044706e400000000000000000
+ENTRY_END
+
+STEP 5230 QUERY
+ENTRY_BEGIN
+RAW
+b65095965018447032c5000000958ce4000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5240 QUERY
+ENTRY_BEGIN
+RAW
+b64fffb65011446274db0000000000000000
+ENTRY_END
+
+STEP 5250 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c1350000020405b401010402
+ENTRY_END
+
+STEP 5260 QUERY
+ENTRY_BEGIN
+RAW
+b65095a4501144626da80000000000000000
+ENTRY_END
+
+STEP 5270 QUERY
+ENTRY_BEGIN
+RAW
+b65095a5501044626da70000000000000000
+ENTRY_END
+
+STEP 5280 QUERY
+ENTRY_BEGIN
+RAW
+b64fffb75010446274da0000000000000000
+ENTRY_END
+
+STEP 5290 QUERY
+ENTRY_BEGIN
+RAW
+b651696f50104470c9b80000000000000000
+ENTRY_END
+
+STEP 5300 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006ba70000020405b401010402
+ENTRY_END
+
+STEP 5310 QUERY
+ENTRY_BEGIN
+RAW
+b651696f501844701c200000008901fc000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afefd403c507d00030000002a4e544c4d535350000100000097b208e0060006002400000004000400200000004e5453313233435a30300000
+ENTRY_END
+
+STEP 5320 QUERY
+ENTRY_BEGIN
+RAW
+b652266c50104470b72c0000000000000000
+ENTRY_END
+
+STEP 5330 QUERY
+ENTRY_BEGIN
+RAW
+b652266c50184470065900000095013c000000010001000000000f313235343133303435303435302d330000f900010f313235343133303435303435302d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5340 QUERY
+ENTRY_BEGIN
+RAW
+b651697d50114462c92c0000000000000000
+ENTRY_END
+
+STEP 5350 QUERY
+ENTRY_BEGIN
+RAW
+b652267a50114462b6940000000000000000
+ENTRY_END
+
+STEP 5360 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400080fc0000020405b401010402
+ENTRY_END
+
+STEP 5370 QUERY
+ENTRY_BEGIN
+RAW
+b652267b50104462b6930000000000000000
+ENTRY_END
+
+STEP 5380 QUERY
+ENTRY_BEGIN
+RAW
+b652bfd55010447033180000000000000000
+ENTRY_END
+
+STEP 5390 QUERY
+ENTRY_BEGIN
+RAW
+b651697e50104462c92b0000000000000000
+ENTRY_END
+
+STEP 5400 QUERY
+ENTRY_BEGIN
+RAW
+b652bfd550184470abf600000095d88a000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5410 QUERY
+ENTRY_BEGIN
+RAW
+b652bfe35011446232800000000000000000
+ENTRY_END
+
+STEP 5420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000729e0000020405b401010402
+ENTRY_END
+
+STEP 5430 QUERY
+ENTRY_BEGIN
+RAW
+b652bfe450104462327f0000000000000000
+ENTRY_END
+
+STEP 5440 QUERY
+ENTRY_BEGIN
+RAW
+b65534ff50104470af8d0000000000000000
+ENTRY_END
+
+STEP 5450 QUERY
+ENTRY_BEGIN
+RAW
+b65534ff50184470511e00000095afd8000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd90403c4f100003000000364e544c4d535350000100000097b208e00d000d00290000000900090020000000524942454d412d4e4c5343484f434b5f524942454d410000
+ENTRY_END
+
+STEP 5460 QUERY
+ENTRY_BEGIN
+RAW
+b655350d50114462aef50000000000000000
+ENTRY_END
+
+STEP 5470 QUERY
+ENTRY_BEGIN
+RAW
+b655350e50104462aef40000000000000000
+ENTRY_END
+
+STEP 5480 QUERY
+ENTRY_BEGIN
+RAW
+000000005004faf0e84a0000000000000000
+ENTRY_END
+
+STEP 5490 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000385c0000020405b401010402
+ENTRY_END
+
+STEP 5500 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000905f00000204057a01010402
+ENTRY_END
+
+STEP 5510 QUERY
+ENTRY_BEGIN
+RAW
+b658c73e50104470e3080000000000000000
+ENTRY_END
+
+STEP 5520 QUERY
+ENTRY_BEGIN
+RAW
+b6596076501041b8a4510000000000000000
+ENTRY_END
+
+STEP 5530 QUERY
+ENTRY_BEGIN
+RAW
+b6596076501841b838880000009068f4000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403af9b5403c4b350003000000314e544c4d535350000100000097b208e0080008002900000009000900200000004242425345525645524242422d4144414d0000
+ENTRY_END
+
+STEP 5540 QUERY
+ENTRY_BEGIN
+RAW
+b658c73e501844701fbb000000879ffc000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000434553473031434553470000
+ENTRY_END
+
+STEP 5550 QUERY
+ENTRY_BEGIN
+RAW
+b6596084501141aaa3be0000000000000000
+ENTRY_END
+
+STEP 5560 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009c2d00000204057a01010402
+ENTRY_END
+
+STEP 5570 QUERY
+ENTRY_BEGIN
+RAW
+b6596085501041aaa3bd0000000000000000
+ENTRY_END
+
+STEP 5580 QUERY
+ENTRY_BEGIN
+RAW
+b659f314501041b81d810000000000000000
+ENTRY_END
+
+STEP 5590 QUERY
+ENTRY_BEGIN
+RAW
+b659f314501841b8513400000090ca78000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403af9b5403c4b350003000000314e544c4d535350000100000097b208e0080008002900000009000900200000004242425345525645524242422d4144414d0000
+ENTRY_END
+
+STEP 5600 QUERY
+ENTRY_BEGIN
+RAW
+b658c74c50114462e27e0000000000000000
+ENTRY_END
+
+STEP 5610 QUERY
+ENTRY_BEGIN
+RAW
+b659f322501141aa1cee0000000000000000
+ENTRY_END
+
+STEP 5620 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ec0c0000020405b401010402
+ENTRY_END
+
+STEP 5630 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004d1c00000204057a01010402
+ENTRY_END
+
+STEP 5640 QUERY
+ENTRY_BEGIN
+RAW
+b659f323501041aa1ced0000000000000000
+ENTRY_END
+
+STEP 5650 QUERY
+ENTRY_BEGIN
+RAW
+b65ba67a501041b81b080000000000000000
+ENTRY_END
+
+STEP 5660 QUERY
+ENTRY_BEGIN
+RAW
+b65ba67a501841b8ed37000000902bfc000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403af9b5403c4b350003000000314e544c4d535350000100000097b208e0080008002900000009000900200000004242425345525645524242422d4144414d0000
+ENTRY_END
+
+STEP 5670 QUERY
+ENTRY_BEGIN
+RAW
+b658c74d50104462e27d0000000000000000
+ENTRY_END
+
+STEP 5680 QUERY
+ENTRY_BEGIN
+RAW
+b65ba688501141aa1a750000000000000000
+ENTRY_END
+
+STEP 5690 QUERY
+ENTRY_BEGIN
+RAW
+b65ad9b55010447084400000000000000000
+ENTRY_END
+
+STEP 5700 QUERY
+ENTRY_BEGIN
+RAW
+b65ba689501041aa1a740000000000000000
+ENTRY_END
+
+STEP 5710 QUERY
+ENTRY_BEGIN
+RAW
+b65ad9b550184470c70a000000879be4000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000434553473031434553470000
+ENTRY_END
+
+STEP 5720 QUERY
+ENTRY_BEGIN
+RAW
+b65ad9c35011446283b60000000000000000
+ENTRY_END
+
+STEP 5730 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ebab0000020405b401010402
+ENTRY_END
+
+STEP 5740 QUERY
+ENTRY_BEGIN
+RAW
+b65ad9c45010446283b50000000000000000
+ENTRY_END
+
+STEP 5750 QUERY
+ENTRY_BEGIN
+RAW
+b65c2b0a5010447032890000000000000000
+ENTRY_END
+
+STEP 5760 QUERY
+ENTRY_BEGIN
+RAW
+b65c2b0a50184470796b0000008797cc000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000434553473031434553470000
+ENTRY_END
+
+STEP 5770 QUERY
+ENTRY_BEGIN
+RAW
+b65c2b185011446231ff0000000000000000
+ENTRY_END
+
+STEP 5780 QUERY
+ENTRY_BEGIN
+RAW
+b65c2b195010446231fe0000000000000000
+ENTRY_END
+
+STEP 5790 QUERY
+ENTRY_BEGIN
+RAW
+28ed00000001000000000000066d6978666978026e6c00000f000100
+ENTRY_END
+
+STEP 5800 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400069e100000204056401010402
+ENTRY_END
+
+STEP 5810 QUERY
+ENTRY_BEGIN
+RAW
+b6630195501040b0dd9c0000000000000000
+ENTRY_END
+
+STEP 5820 QUERY
+ENTRY_BEGIN
+RAW
+b6630195501840b030e7000000900ca7000000010001000000000f313136383233313130343533302d330000f900010f313136383233313130343533302d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403afdf8403c4f780003000000314e544c4d535350000100000097b200e00a000a0027000000070007002000000044564d544b475344564d454449414b47530000
+ENTRY_END
+
+STEP 5830 QUERY
+ENTRY_BEGIN
+RAW
+b66301a3501140a2dd090000000000000000
+ENTRY_END
+
+STEP 5840 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ecb600000204056401010402
+ENTRY_END
+
+STEP 5850 QUERY
+ENTRY_BEGIN
+RAW
+b66301a4501040a2dd080000000000000000
+ENTRY_END
+
+STEP 5860 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc00a4280000020405b401010402
+ENTRY_END
+
+STEP 5870 QUERY
+ENTRY_BEGIN
+RAW
+b663a87e501040b0b9880000000000000000
+ENTRY_END
+
+STEP 5880 QUERY
+ENTRY_BEGIN
+RAW
+b66453ed5010fc00c68a0000000000000000
+ENTRY_END
+
+STEP 5890 QUERY
+ENTRY_BEGIN
+RAW
+b66453ed5018fc0070e60000008abe78000000010001000000000e3939363433323431323639302d330000f900010e3939363433323431323639302d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403af9c5403c4b4500030000002d4e544c4d535350000100000097b200e00600060027000000070007002000000057494e324b50434b50544553540000
+ENTRY_END
+
+STEP 5900 QUERY
+ENTRY_BEGIN
+RAW
+b66453fb5011fbf2c5fd0000000000000000
+ENTRY_END
+
+STEP 5910 QUERY
+ENTRY_BEGIN
+RAW
+b663a87e501840b0d705000000904375000000010001000000000f313136383233313130343533302d320000f900010f313136383233313130343533302d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afdf8403c4f780003000000314e544c4d535350000100000097b200e00a000a0027000000070007002000000044564d544b475344564d454449414b47530000
+ENTRY_END
+
+STEP 5920 QUERY
+ENTRY_BEGIN
+RAW
+b66453fc5010fbf2c5fc0000000000000000
+ENTRY_END
+
+STEP 5930 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc00de6d0000020405b401010402
+ENTRY_END
+
+STEP 5940 QUERY
+ENTRY_BEGIN
+RAW
+b6654c635010fc0008590000000000000000
+ENTRY_END
+
+STEP 5950 QUERY
+ENTRY_BEGIN
+RAW
+b663a88c501140a2b8f50000000000000000
+ENTRY_END
+
+STEP 5960 QUERY
+ENTRY_BEGIN
+RAW
+b6654c635018fc00072d0000008a6c00000000010001000000000e3939363433323431323639302d320000f900010e3939363433323431323639302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403af9c5403c4b4500030000002d4e544c4d535350000100000097b200e00600060027000000070007002000000057494e324b50434b50544553540000
+ENTRY_END
+
+STEP 5970 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002f9000000204056401010402
+ENTRY_END
+
+STEP 5980 QUERY
+ENTRY_BEGIN
+RAW
+b6654c715011fbf207cc0000000000000000
+ENTRY_END
+
+STEP 5990 QUERY
+ENTRY_BEGIN
+RAW
+b6654c725010fbf207cb0000000000000000
+ENTRY_END
+
+STEP 6000 QUERY
+ENTRY_BEGIN
+RAW
+b663a88d501040a2b8f40000000000000000
+ENTRY_END
+
+STEP 6010 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc0083840000020405b401010402
+ENTRY_END
+
+STEP 6020 QUERY
+ENTRY_BEGIN
+RAW
+b6663c2f501040b068ae0000000000000000
+ENTRY_END
+
+STEP 6030 QUERY
+ENTRY_BEGIN
+RAW
+b666fe1c5010fc00fbb40000000000000000
+ENTRY_END
+
+STEP 6040 QUERY
+ENTRY_BEGIN
+RAW
+b666fe1c5018fc007cc80000008ae9c0000000010001000000000e3939363433323431323639302d320000f900010e3939363433323431323639302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403af9c5403c4b4500030000002d4e544c4d535350000100000097b200e00600060027000000070007002000000057494e324b50434b50544553540000
+ENTRY_END
+
+STEP 6050 QUERY
+ENTRY_BEGIN
+RAW
+b666fe2a5011fbf2fb270000000000000000
+ENTRY_END
+
+STEP 6060 QUERY
+ENTRY_BEGIN
+RAW
+b666fe2b5010fbf2fb260000000000000000
+ENTRY_END
+
+STEP 6070 QUERY
+ENTRY_BEGIN
+RAW
+b6663c2f501840b04f5d000000907a43000000010001000000000f313136383233313130343533302d320000f900010f313136383233313130343533302d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403afdf8403c4f780003000000314e544c4d535350000100000097b200e00a000a0027000000070007002000000044564d544b475344564d454449414b47530000
+ENTRY_END
+
+STEP 6080 QUERY
+ENTRY_BEGIN
+RAW
+b6663c3d501140a2681b0000000000000000
+ENTRY_END
+
+STEP 6090 QUERY
+ENTRY_BEGIN
+RAW
+b6663c3e501040a2681a0000000000000000
+ENTRY_END
+
+STEP 6100 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf02ae300000204057a01010402
+ENTRY_END
+
+STEP 6110 QUERY
+ENTRY_BEGIN
+RAW
+b66a29aa5010fbec764c0000000000000000
+ENTRY_END
+
+STEP 6120 QUERY
+ENTRY_BEGIN
+RAW
+b66a29aa5018fbeca98c0000008f5105000000010001000000000f313033303739323135313035382d330000f900010f313033303739323135313035382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403b06fa403c587a0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 6130 QUERY
+ENTRY_BEGIN
+RAW
+b66a29b85011fbde75ba0000000000000000
+ENTRY_END
+
+STEP 6140 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a2200000020405b401010402
+ENTRY_END
+
+STEP 6150 QUERY
+ENTRY_BEGIN
+RAW
+b66a29b95010fbde75b90000000000000000
+ENTRY_END
+
+STEP 6160 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f29900000204057a01010402
+ENTRY_END
+
+STEP 6170 QUERY
+ENTRY_BEGIN
+RAW
+b66acd7f50104470467a0000000000000000
+ENTRY_END
+
+STEP 6180 QUERY
+ENTRY_BEGIN
+RAW
+b66acd7f50184470c7f40000008d352e000000010001000000000f313031333631323238313837342d330000f900010f313031333631323238313837342d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afce9403c4e6900030000002e4e544c4d535350000100000097b208e0050005002900000009000900200000005345525645522d4343435952454b0000
+ENTRY_END
+
+STEP 6190 QUERY
+ENTRY_BEGIN
+RAW
+b66acd8d5011446245ea0000000000000000
+ENTRY_END
+
+STEP 6200 QUERY
+ENTRY_BEGIN
+RAW
+b66bbecf5010fbeca8dc0000000000000000
+ENTRY_END
+
+STEP 6210 QUERY
+ENTRY_BEGIN
+RAW
+b66bbecf5018fbecf6930000008f378f000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403b06fa403c587a0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 6220 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400067760000020405b401010402
+ENTRY_END
+
+STEP 6230 QUERY
+ENTRY_BEGIN
+RAW
+b66acd8e5010446245e90000000000000000
+ENTRY_END
+
+STEP 6240 QUERY
+ENTRY_BEGIN
+RAW
+b66bbedd5011fbdea84a0000000000000000
+ENTRY_END
+
+STEP 6250 QUERY
+ENTRY_BEGIN
+RAW
+b66c83605010447055ed0000000000000000
+ENTRY_END
+
+STEP 6260 QUERY
+ENTRY_BEGIN
+RAW
+b66c83605018447026c40000008de6d2000000010001000000000f313031333631323238313837342d320000f900010f313031333631323238313837342d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afce9403c4e6900030000002e4e544c4d535350000100000097b208e0050005002900000009000900200000005345525645522d4343435952454b0000
+ENTRY_END
+
+STEP 6270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d34200000204057a01010402
+ENTRY_END
+
+STEP 6280 QUERY
+ENTRY_BEGIN
+RAW
+b66c836e50114462555d0000000000000000
+ENTRY_END
+
+STEP 6290 QUERY
+ENTRY_BEGIN
+RAW
+b66bbede5010fbdea8490000000000000000
+ENTRY_END
+
+STEP 6300 QUERY
+ENTRY_BEGIN
+RAW
+b66d191c5010fbec2f370000000000000000
+ENTRY_END
+
+STEP 6310 QUERY
+ENTRY_BEGIN
+RAW
+b66d191c5018fbecc6460000008fee36000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403b06fa403c587a0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 6320 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000810b0000020405b401010402
+ENTRY_END
+
+STEP 6330 QUERY
+ENTRY_BEGIN
+RAW
+b66c836f50104462555c0000000000000000
+ENTRY_END
+
+STEP 6340 QUERY
+ENTRY_BEGIN
+RAW
+b66da42b501044704eb60000000000000000
+ENTRY_END
+
+STEP 6350 QUERY
+ENTRY_BEGIN
+RAW
+b66da42b501844706de90000008d9876000000010001000000000f313031333631323238313837342d320000f900010f313031333631323238313837342d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afce9403c4e6900030000002e4e544c4d535350000100000097b208e0050005002900000009000900200000005345525645522d4343435952454b0000
+ENTRY_END
+
+STEP 6360 QUERY
+ENTRY_BEGIN
+RAW
+b66d192a5011fbde2ea50000000000000000
+ENTRY_END
+
+STEP 6370 QUERY
+ENTRY_BEGIN
+RAW
+b66da439501144624e260000000000000000
+ENTRY_END
+
+STEP 6380 QUERY
+ENTRY_BEGIN
+RAW
+b66d192b5010fbde2ea40000000000000000
+ENTRY_END
+
+STEP 6390 QUERY
+ENTRY_BEGIN
+RAW
+b66da43a501044624e250000000000000000
+ENTRY_END
+
+STEP 6400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e71c0000020405b401010402
+ENTRY_END
+
+STEP 6410 QUERY
+ENTRY_BEGIN
+RAW
+b66e311b5010faf02c470000000000000000
+ENTRY_END
+
+STEP 6420 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc00ee0b00000204057801010402
+ENTRY_END
+
+STEP 6430 QUERY
+ENTRY_BEGIN
+RAW
+b6719dda5010fc00c6370000000000000000
+ENTRY_END
+
+STEP 6440 QUERY
+ENTRY_BEGIN
+RAW
+b6719dda5018fc006c5e00000091d5b0000000010001000000000e3932373731323933353935342d330000f900010e3932373731323933353935342d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403afc98403c4e180003000000344e544c4d535350000100000097b208e0080008002c0000000c000c0020000000504c414e4e494e472d494e544e4b4f45524945520000
+ENTRY_END
+
+STEP 6450 QUERY
+ENTRY_BEGIN
+RAW
+b6719de85011fbf2c5a30000000000000000
+ENTRY_END
+
+STEP 6460 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc00095d00000204057801010402
+ENTRY_END
+
+STEP 6470 QUERY
+ENTRY_BEGIN
+RAW
+b6719de95010fbf2c5a20000000000000000
+ENTRY_END
+
+STEP 6480 QUERY
+ENTRY_BEGIN
+RAW
+b6722e745010fc0050ee0000000000000000
+ENTRY_END
+
+STEP 6490 QUERY
+ENTRY_BEGIN
+RAW
+b6722e745018fc00071f00000091c7a6000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afc98403c4e180003000000344e544c4d535350000100000097b208e0080008002c0000000c000c0020000000504c414e4e494e472d494e544e4b4f45524945520000
+ENTRY_END
+
+STEP 6500 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b5a300000204057a01010402
+ENTRY_END
+
+STEP 6510 QUERY
+ENTRY_BEGIN
+RAW
+b673057f501041b824730000000000000000
+ENTRY_END
+
+STEP 6520 QUERY
+ENTRY_BEGIN
+RAW
+b673057f501841b86c7200000095bcc0000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6530 QUERY
+ENTRY_BEGIN
+RAW
+b673058d501141aa23db0000000000000000
+ENTRY_END
+
+STEP 6540 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400032f400000204057a01010402
+ENTRY_END
+
+STEP 6550 QUERY
+ENTRY_BEGIN
+RAW
+b6722e825011fbf2505a0000000000000000
+ENTRY_END
+
+STEP 6560 QUERY
+ENTRY_BEGIN
+RAW
+b673058e501041aa23da0000000000000000
+ENTRY_END
+
+STEP 6570 QUERY
+ENTRY_BEGIN
+RAW
+b673a2cf501041b804730000000000000000
+ENTRY_END
+
+STEP 6580 QUERY
+ENTRY_BEGIN
+RAW
+b673a2cf501841b8d533000000953500000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6590 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc00bb6f00000204057801010402
+ENTRY_END
+
+STEP 6600 QUERY
+ENTRY_BEGIN
+RAW
+b673a2dd501141aa03db0000000000000000
+ENTRY_END
+
+STEP 6610 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004e5b00000204057a01010402
+ENTRY_END
+
+STEP 6620 QUERY
+ENTRY_BEGIN
+RAW
+b6722e835010fbf250590000000000000000
+ENTRY_END
+
+STEP 6630 QUERY
+ENTRY_BEGIN
+RAW
+b673a2de501041aa03da0000000000000000
+ENTRY_END
+
+STEP 6640 QUERY
+ENTRY_BEGIN
+RAW
+b674f779501041b8cb2e0000000000000000
+ENTRY_END
+
+STEP 6650 QUERY
+ENTRY_BEGIN
+RAW
+b674f779501841b823af00000095ad40000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6660 QUERY
+ENTRY_BEGIN
+RAW
+b674f787501141aaca960000000000000000
+ENTRY_END
+
+STEP 6670 QUERY
+ENTRY_BEGIN
+RAW
+b674219e5010fc000fd50000000000000000
+ENTRY_END
+
+STEP 6680 QUERY
+ENTRY_BEGIN
+RAW
+b674f788501041aaca950000000000000000
+ENTRY_END
+
+STEP 6690 QUERY
+ENTRY_BEGIN
+RAW
+b674219e5018fc0075b20000009117fa000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afc98403c4e180003000000344e544c4d535350000100000097b208e0080008002c0000000c000c0020000000504c414e4e494e472d494e544e4b4f45524945520000
+ENTRY_END
+
+STEP 6700 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005e6e00000204057a01010402
+ENTRY_END
+
+STEP 6710 QUERY
+ENTRY_BEGIN
+RAW
+b6758667501041b84c530000000000000000
+ENTRY_END
+
+STEP 6720 QUERY
+ENTRY_BEGIN
+RAW
+b6758667501841b83393000000951d80000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6730 QUERY
+ENTRY_BEGIN
+RAW
+b67421ac5011fbf20f410000000000000000
+ENTRY_END
+
+STEP 6740 QUERY
+ENTRY_BEGIN
+RAW
+b6758675501141aa4bbb0000000000000000
+ENTRY_END
+
+STEP 6750 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000834f00000204057a01010402
+ENTRY_END
+
+STEP 6760 QUERY
+ENTRY_BEGIN
+RAW
+b6758676501041aa4bba0000000000000000
+ENTRY_END
+
+STEP 6770 QUERY
+ENTRY_BEGIN
+RAW
+b6764c30501041b8ab6a0000000000000000
+ENTRY_END
+
+STEP 6780 QUERY
+ENTRY_BEGIN
+RAW
+b6764c30501841b81b6b0000009595c0000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6790 QUERY
+ENTRY_BEGIN
+RAW
+b67421ad5010fbf20f400000000000000000
+ENTRY_END
+
+STEP 6800 QUERY
+ENTRY_BEGIN
+RAW
+b6764c3e501141aaaad20000000000000000
+ENTRY_END
+
+STEP 6810 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b5d500000204057a01010402
+ENTRY_END
+
+STEP 6820 QUERY
+ENTRY_BEGIN
+RAW
+b6764c3f501041aaaad10000000000000000
+ENTRY_END
+
+STEP 6830 QUERY
+ENTRY_BEGIN
+RAW
+b676e889501041b841970000000000000000
+ENTRY_END
+
+STEP 6840 QUERY
+ENTRY_BEGIN
+RAW
+b676e889501841b83958000000950e00000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afcec403c4e6c0003000000364e544c4d535350000100000097b200e0070007002f0000000f000f00200000004453412d323030302d534552564552445341323030300000
+ENTRY_END
+
+STEP 6850 QUERY
+ENTRY_BEGIN
+RAW
+b676e897501141aa40ff0000000000000000
+ENTRY_END
+
+STEP 6860 QUERY
+ENTRY_BEGIN
+RAW
+b676e898501041aa40fe0000000000000000
+ENTRY_END
+
+STEP 6870 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400095d800000204056401010402
+ENTRY_END
+
+STEP 6880 QUERY
+ENTRY_BEGIN
+RAW
+b67b1e67501040b0eca90000000000000000
+ENTRY_END
+
+STEP 6890 QUERY
+ENTRY_BEGIN
+RAW
+b67b1e67501840b0d66800000089f180000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd03403c4e8300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004641585352564241494c45590000
+ENTRY_END
+
+STEP 6900 QUERY
+ENTRY_BEGIN
+RAW
+b67b1e75501140a2ec1d0000000000000000
+ENTRY_END
+
+STEP 6910 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000693a00000204056401010402
+ENTRY_END
+
+STEP 6920 QUERY
+ENTRY_BEGIN
+RAW
+b67b1e76501040a2ec1c0000000000000000
+ENTRY_END
+
+STEP 6930 QUERY
+ENTRY_BEGIN
+RAW
+b67bf069501040b0ee080000000000000000
+ENTRY_END
+
+STEP 6940 QUERY
+ENTRY_BEGIN
+RAW
+b67bf069501840b024c800000089a680000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd03403c4e8300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004641585352564241494c45590000
+ENTRY_END
+
+STEP 6950 QUERY
+ENTRY_BEGIN
+RAW
+b67bf077501140a2ed7c0000000000000000
+ENTRY_END
+
+STEP 6960 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000124a00000204056401010402
+ENTRY_END
+
+STEP 6970 QUERY
+ENTRY_BEGIN
+RAW
+b67bf078501040a2ed7b0000000000000000
+ENTRY_END
+
+STEP 6980 QUERY
+ENTRY_BEGIN
+RAW
+b67d7555501040b0122b0000000000000000
+ENTRY_END
+
+STEP 6990 QUERY
+ENTRY_BEGIN
+RAW
+b67d7555501840b0906a000000895d00000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd04403c4e8400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004641585352564241494c45590000
+ENTRY_END
+
+STEP 7000 QUERY
+ENTRY_BEGIN
+RAW
+b67d7563501140a2119f0000000000000000
+ENTRY_END
+
+STEP 7010 QUERY
+ENTRY_BEGIN
+RAW
+b67d7564501040a2119e0000000000000000
+ENTRY_END
+
+STEP 7020 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d9cd00000204051e01010402
+ENTRY_END
+
+STEP 7030 QUERY
+ENTRY_BEGIN
+RAW
+b67e3beb5010ffdc0e960000000000000000
+ENTRY_END
+
+STEP 7040 QUERY
+ENTRY_BEGIN
+RAW
+b67e3beb5018ffdc1df400000099934e000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005d03677373096d6963726f736f667403636f6d00403afd1b403c4e9b00030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000004e504552535045435449454630314e50455253504543544945460000
+ENTRY_END
+
+STEP 7050 QUERY
+ENTRY_BEGIN
+RAW
+b67e3bf95011ffce0dfa0000000000000000
+ENTRY_END
+
+STEP 7060 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0182100000204051e01010402
+ENTRY_END
+
+STEP 7070 QUERY
+ENTRY_BEGIN
+RAW
+b67e3bfa5010ffce0df90000000000000000
+ENTRY_END
+
+STEP 7080 QUERY
+ENTRY_BEGIN
+RAW
+b67edec85010ffdcaa0b0000000000000000
+ENTRY_END
+
+STEP 7090 QUERY
+ENTRY_BEGIN
+RAW
+b67edec85018ffdc9cbb00000099b0fd000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403afd1b403c4e9b00030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000004e504552535045435449454630314e50455253504543544945460000
+ENTRY_END
+
+STEP 7100 QUERY
+ENTRY_BEGIN
+RAW
+b67eded65011ffcea96f0000000000000000
+ENTRY_END
+
+STEP 7110 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf066bc00000204051e01010402
+ENTRY_END
+
+STEP 7120 QUERY
+ENTRY_BEGIN
+RAW
+b67eded75010ffcea96e0000000000000000
+ENTRY_END
+
+STEP 7130 QUERY
+ENTRY_BEGIN
+RAW
+b67fb3b25010ffdc23bc0000000000000000
+ENTRY_END
+
+STEP 7140 QUERY
+ENTRY_BEGIN
+RAW
+b67fb3b25018ffdca0cd00000099269c000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005d03677373096d6963726f736f667403636f6d00403afd1b403c4e9b00030000003a4e544c4d535350000100000097b208e00c000c002e0000000e000e00200000004e504552535045435449454630314e50455253504543544945460000
+ENTRY_END
+
+STEP 7150 QUERY
+ENTRY_BEGIN
+RAW
+b67fb3c05011ffce23200000000000000000
+ENTRY_END
+
+STEP 7160 QUERY
+ENTRY_BEGIN
+RAW
+b67fb3c15010ffce231f0000000000000000
+ENTRY_END
+
+STEP 7170 QUERY
+ENTRY_BEGIN
+RAW
+b66e311b5018faf02f370000008d25c0000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd13403c4e9300030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 7180 QUERY
+ENTRY_BEGIN
+RAW
+b66e311b5018faf02f370000008d25c0000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd13403c4e9300030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 7190 QUERY
+ENTRY_BEGIN
+RAW
+b66e31295011fae22bb70000000000000000
+ENTRY_END
+
+STEP 7200 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0a80c0000020405b401010402
+ENTRY_END
+
+STEP 7210 QUERY
+ENTRY_BEGIN
+RAW
+b66e312a5010fae22bb60000000000000000
+ENTRY_END
+
+STEP 7220 QUERY
+ENTRY_BEGIN
+RAW
+b68303575010faf01ae60000000000000000
+ENTRY_END
+
+STEP 7230 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf091b40000020405b401010402
+ENTRY_END
+
+STEP 7240 QUERY
+ENTRY_BEGIN
+RAW
+b683c2c05010faf045240000000000000000
+ENTRY_END
+
+STEP 7250 QUERY
+ENTRY_BEGIN
+RAW
+b683c2c05018faf0f2860000008e4bdc000000010001000000000f313237313331303331393633342d330000f900010f313237313331303331393633342d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04c5403c564500030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 7260 QUERY
+ENTRY_BEGIN
+RAW
+b683c2ce5011fae244930000000000000000
+ENTRY_END
+
+STEP 7270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf044dc0000020405b401010402
+ENTRY_END
+
+STEP 7280 QUERY
+ENTRY_BEGIN
+RAW
+b683c2cf5010fae244920000000000000000
+ENTRY_END
+
+STEP 7290 QUERY
+ENTRY_BEGIN
+RAW
+b6844daf5010faf06d5c0000000000000000
+ENTRY_END
+
+STEP 7300 QUERY
+ENTRY_BEGIN
+RAW
+b6844daf5018faf0669c0000008e0100000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04c5403c564500030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 7310 QUERY
+ENTRY_BEGIN
+RAW
+b6844dbd5011fae26ccb0000000000000000
+ENTRY_END
+
+STEP 7320 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf058a60000020405b401010402
+ENTRY_END
+
+STEP 7330 QUERY
+ENTRY_BEGIN
+RAW
+b6844dbe5010fae26cca0000000000000000
+ENTRY_END
+
+STEP 7340 QUERY
+ENTRY_BEGIN
+RAW
+b686ac6c5010faf022670000000000000000
+ENTRY_END
+
+STEP 7350 QUERY
+ENTRY_BEGIN
+RAW
+b686ac6c5018faf065460000008eb560000000010001000000000f313237313331303331393633342d320000f900010f313237313331303331393633342d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403b04c6403c564600030000002f4e544c4d535350000100000097b208e0070007002800000008000800200000005345525645522d31545247524f55500000
+ENTRY_END
+
+STEP 7360 QUERY
+ENTRY_BEGIN
+RAW
+b686ac7a5011fae221d60000000000000000
+ENTRY_END
+
+STEP 7370 QUERY
+ENTRY_BEGIN
+RAW
+b686ac7b5010fae221d50000000000000000
+ENTRY_END
+
+STEP 7380 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bdaf0000020405b401010402
+ENTRY_END
+
+STEP 7390 QUERY
+ENTRY_BEGIN
+RAW
+b68abd075010447072610000000000000000
+ENTRY_END
+
+STEP 7400 QUERY
+ENTRY_BEGIN
+RAW
+b68abd0750184470b7c30000008d553b000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcf1403c4e7100030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 7410 QUERY
+ENTRY_BEGIN
+RAW
+b68abd155011446271d10000000000000000
+ENTRY_END
+
+STEP 7420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c6270000020405b401010402
+ENTRY_END
+
+STEP 7430 QUERY
+ENTRY_BEGIN
+RAW
+b68abd165010446271d00000000000000000
+ENTRY_END
+
+STEP 7440 QUERY
+ENTRY_BEGIN
+RAW
+b68bafe25010447087fd0000000000000000
+ENTRY_END
+
+STEP 7450 QUERY
+ENTRY_BEGIN
+RAW
+b68bafe25018447063a10000008dbffa000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcf1403c4e7100030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 7460 QUERY
+ENTRY_BEGIN
+RAW
+b68baff050114462876d0000000000000000
+ENTRY_END
+
+STEP 7470 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000803f0000020405b401010402
+ENTRY_END
+
+STEP 7480 QUERY
+ENTRY_BEGIN
+RAW
+b68baff150104462876c0000000000000000
+ENTRY_END
+
+STEP 7490 QUERY
+ENTRY_BEGIN
+RAW
+b68c3a0a50104470b7ec0000000000000000
+ENTRY_END
+
+STEP 7500 QUERY
+ENTRY_BEGIN
+RAW
+b68c3a0a501844701e530000008d3538000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcf1403c4e7100030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 7510 QUERY
+ENTRY_BEGIN
+RAW
+b68c3a1850114462b75c0000000000000000
+ENTRY_END
+
+STEP 7520 QUERY
+ENTRY_BEGIN
+RAW
+b68c3a1950104462b75b0000000000000000
+ENTRY_END
+
+STEP 7530 QUERY
+ENTRY_BEGIN
+RAW
+000000006002223800990000020405b40000
+ENTRY_END
+
+STEP 7540 QUERY
+ENTRY_BEGIN
+RAW
+b68efdc55010223863f10000000000000000
+ENTRY_END
+
+STEP 7550 QUERY
+ENTRY_BEGIN
+RAW
+b68efdc550182238a3690000001d92300000000100000000000008736c61676572696a026e6c0000060001
+ENTRY_END
+
+STEP 7560 QUERY
+ENTRY_BEGIN
+RAW
+b68efe335010223863640000000000000000
+ENTRY_END
+
+STEP 7570 QUERY
+ENTRY_BEGIN
+RAW
+b68efe335011223863630000000000000000
+ENTRY_END
+
+STEP 7580 QUERY
+ENTRY_BEGIN
+RAW
+b68efe345010223863620000000000000000
+ENTRY_END
+
+STEP 7590 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bd7e0000020405b401010402
+ENTRY_END
+
+STEP 7600 QUERY
+ENTRY_BEGIN
+RAW
+b68f86c850104470a86a0000000000000000
+ENTRY_END
+
+STEP 7610 QUERY
+ENTRY_BEGIN
+RAW
+b68f86c8501844702e0000000092d500000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd41403c4ec10003000000334e544c4d535350000100000097b208e00e000e002500000005000500200000004e414f4d494e45544c494a4e4e45545745524b0000
+ENTRY_END
+
+STEP 7620 QUERY
+ENTRY_BEGIN
+RAW
+b68f86d650114462a7d50000000000000000
+ENTRY_END
+
+STEP 7630 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000ff90000020405b401010402
+ENTRY_END
+
+STEP 7640 QUERY
+ENTRY_BEGIN
+RAW
+b68f86d750104462a7d40000000000000000
+ENTRY_END
+
+STEP 7650 QUERY
+ENTRY_BEGIN
+RAW
+b6902691501044705b1b0000000000000000
+ENTRY_END
+
+STEP 7660 QUERY
+ENTRY_BEGIN
+RAW
+b690269150184470c6b100000092f000000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd41403c4ec10003000000334e544c4d535350000100000097b208e00e000e002500000005000500200000004e414f4d494e45544c494a4e4e45545745524b0000
+ENTRY_END
+
+STEP 7670 QUERY
+ENTRY_BEGIN
+RAW
+b690269f501144625a860000000000000000
+ENTRY_END
+
+STEP 7680 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400057280000020405b401010402
+ENTRY_END
+
+STEP 7690 QUERY
+ENTRY_BEGIN
+RAW
+b69026a0501044625a850000000000000000
+ENTRY_END
+
+STEP 7700 QUERY
+ENTRY_BEGIN
+RAW
+b69105e050104470c2fa0000000000000000
+ENTRY_END
+
+STEP 7710 QUERY
+ENTRY_BEGIN
+RAW
+b69105e050184470c511000000925980000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd41403c4ec10003000000334e544c4d535350000100000097b208e00e000e002500000005000500200000004e414f4d494e45544c494a4e4e45545745524b0000
+ENTRY_END
+
+STEP 7720 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238210a0000020405b40000
+ENTRY_END
+
+STEP 7730 QUERY
+ENTRY_BEGIN
+RAW
+b69105ee50114462c2650000000000000000
+ENTRY_END
+
+;STEP 7740 QUERY
+;ENTRY_BEGIN
+;RAW
+;2c0901000001000000000000056b6f726e6f026e6c00000f000100
+;ENTRY_END
+
+STEP 7750 QUERY
+ENTRY_BEGIN
+RAW
+b691d4ec50102238ad380000000000000000
+ENTRY_END
+
+STEP 7760 QUERY
+ENTRY_BEGIN
+RAW
+b691d4ec501822387976000000264f0c00000001000000000000116f6e7477696b6b656c696e6773696e7374026e6c0000060001
+ENTRY_END
+
+STEP 7770 QUERY
+ENTRY_BEGIN
+RAW
+b69105ef50104462c2640000000000000000
+ENTRY_END
+
+STEP 7780 QUERY
+ENTRY_BEGIN
+RAW
+b691d55650102238aca60000000000000000
+ENTRY_END
+
+STEP 7790 QUERY
+ENTRY_BEGIN
+RAW
+b691d55650112238aca50000000000000000
+ENTRY_END
+
+STEP 7800 QUERY
+ENTRY_BEGIN
+RAW
+b691d55750102238aca40000000000000000
+ENTRY_END
+
+STEP 7810 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238543a0000020405b401010402
+ENTRY_END
+
+STEP 7820 QUERY
+ENTRY_BEGIN
+RAW
+00000000600222387a780000020405b40000
+ENTRY_END
+
+STEP 7830 QUERY
+ENTRY_BEGIN
+RAW
+b69320c750102238baca0000000000000000
+ENTRY_END
+
+STEP 7840 QUERY
+ENTRY_BEGIN
+RAW
+b69320c75018223807270000001c1125000000010000000000000774617861746965026e6c0000060001
+ENTRY_END
+
+STEP 7850 QUERY
+ENTRY_BEGIN
+RAW
+b693211d50102238ba560000000000000000
+ENTRY_END
+
+STEP 7860 QUERY
+ENTRY_BEGIN
+RAW
+b693211d50112238ba550000000000000000
+ENTRY_END
+
+STEP 7870 QUERY
+ENTRY_BEGIN
+RAW
+b693211e50102238ba540000000000000000
+ENTRY_END
+
+STEP 7880 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf036a60000020405b401010402
+ENTRY_END
+
+STEP 7890 QUERY
+ENTRY_BEGIN
+RAW
+b69592cf5010faf019f50000000000000000
+ENTRY_END
+
+STEP 7900 QUERY
+ENTRY_BEGIN
+RAW
+b69592cf5018faf0921a0000008e6b08000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcc7403c4e4700030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 7910 QUERY
+ENTRY_BEGIN
+RAW
+b69592dd5011fae219640000000000000000
+ENTRY_END
+
+STEP 7920 QUERY
+ENTRY_BEGIN
+RAW
+b69592de5010fae219630000000000000000
+ENTRY_END
+
+STEP 7930 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f88d0000020405b401010402
+ENTRY_END
+
+STEP 7940 QUERY
+ENTRY_BEGIN
+RAW
+b696589b5010faf016100000000000000000
+ENTRY_END
+
+STEP 7950 QUERY
+ENTRY_BEGIN
+RAW
+b696589b5018faf0eca60000008e0d98000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcc7403c4e4700030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 7960 QUERY
+ENTRY_BEGIN
+RAW
+b69658a95011fae2157f0000000000000000
+ENTRY_END
+
+STEP 7970 QUERY
+ENTRY_BEGIN
+RAW
+b69658aa5010fae2157e0000000000000000
+ENTRY_END
+
+STEP 7980 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d1d60000020405b401010402
+ENTRY_END
+
+STEP 7990 QUERY
+ENTRY_BEGIN
+RAW
+b6925a485010223870130000000000000000
+ENTRY_END
+
+STEP 8000 QUERY
+ENTRY_BEGIN
+RAW
+b6973bb55010faf00c3e0000000000000000
+ENTRY_END
+
+STEP 8010 QUERY
+ENTRY_BEGIN
+RAW
+b6973bb55018faf0ee6c0000008e0000000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcc8403c4e4800030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 8020 QUERY
+ENTRY_BEGIN
+RAW
+b6925a48501822385efc00000096a91f000000010001000000000f313033303739323135313035382d330000f900010f313033303739323135313035382d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afcf6403c4e760003000000374e544c4d535350000100000097b200e0080008002f0000000f000f00200000004b4d57452d4345335648394a4450504b4d57452d5553500000
+ENTRY_END
+
+STEP 8030 QUERY
+ENTRY_BEGIN
+RAW
+b6973bc35011fae20bad0000000000000000
+ENTRY_END
+
+STEP 8040 QUERY
+ENTRY_BEGIN
+RAW
+b6973bc45010fae20bac0000000000000000
+ENTRY_END
+
+STEP 8050 QUERY
+ENTRY_BEGIN
+RAW
+b6925a565011222a6f7a0000000000000000
+ENTRY_END
+
+STEP 8060 QUERY
+ENTRY_BEGIN
+RAW
+000000007002223860470000020405b401010402
+ENTRY_END
+
+STEP 8070 QUERY
+ENTRY_BEGIN
+RAW
+b6925a575010222a6f790000000000000000
+ENTRY_END
+
+STEP 8080 QUERY
+ENTRY_BEGIN
+RAW
+b698080850102238ce5a0000000000000000
+ENTRY_END
+
+STEP 8090 QUERY
+ENTRY_BEGIN
+RAW
+b69808085018223875ef00000096f174000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afcf6403c4e760003000000374e544c4d535350000100000097b200e0080008002f0000000f000f00200000004b4d57452d4345335648394a4450504b4d57452d5553500000
+ENTRY_END
+
+STEP 8100 QUERY
+ENTRY_BEGIN
+RAW
+000000006002223824c20000020405b40000
+ENTRY_END
+
+STEP 8110 QUERY
+ENTRY_BEGIN
+RAW
+b698ca5350102238bb820000000000000000
+ENTRY_END
+
+STEP 8120 QUERY
+ENTRY_BEGIN
+RAW
+b698ca535018223813cf000000236e56000000010000000000000e6761642d676f6f692d7665636874026e6c0000060001
+ENTRY_END
+
+STEP 8130 QUERY
+ENTRY_BEGIN
+RAW
+b698caba50102238baf60000000000000000
+ENTRY_END
+
+STEP 8140 QUERY
+ENTRY_BEGIN
+RAW
+b698caba50112238baf50000000000000000
+ENTRY_END
+
+STEP 8150 QUERY
+ENTRY_BEGIN
+RAW
+b698cabb50102238baf40000000000000000
+ENTRY_END
+
+STEP 8160 QUERY
+ENTRY_BEGIN
+RAW
+b69808165011222acdc10000000000000000
+ENTRY_END
+
+STEP 8170 QUERY
+ENTRY_BEGIN
+RAW
+00000000700222386f010000020405b401010402
+ENTRY_END
+
+STEP 8180 QUERY
+ENTRY_BEGIN
+RAW
+00000000600222389deb0000020405b40000
+ENTRY_END
+
+STEP 8190 QUERY
+ENTRY_BEGIN
+RAW
+b69becab5010223812510000000000000000
+ENTRY_END
+
+STEP 8200 QUERY
+ENTRY_BEGIN
+RAW
+b69becab50182238cab200000024e7b1000000010000000000000f68656d6572742d676f72696368656d026e6c0000060001
+ENTRY_END
+
+STEP 8210 QUERY
+ENTRY_BEGIN
+RAW
+b69bed135010223811c30000000000000000
+ENTRY_END
+
+STEP 8220 QUERY
+ENTRY_BEGIN
+RAW
+b69bed135011223811c20000000000000000
+ENTRY_END
+
+STEP 8230 QUERY
+ENTRY_BEGIN
+RAW
+b69bed145010223811c10000000000000000
+ENTRY_END
+
+STEP 8240 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238b4740000020405b40000
+ENTRY_END
+
+STEP 8250 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238b67e0000020405b40000
+ENTRY_END
+
+STEP 8260 QUERY
+ENTRY_BEGIN
+RAW
+b69cc8d1501022384cb30000000000000000
+ENTRY_END
+
+STEP 8270 QUERY
+ENTRY_BEGIN
+RAW
+b69cc8d1501822382c12000000209f3f000000010000000000000b76657a656c68656e6e6570026e6c0000060001
+ENTRY_END
+
+STEP 8280 QUERY
+ENTRY_BEGIN
+RAW
+b69d9e7350102238791a0000000000000000
+ENTRY_END
+
+STEP 8290 QUERY
+ENTRY_BEGIN
+RAW
+b69d9e7350182238ea300000001eaf1000000001000000000000096f6f672d726164696f026e6c0000060001
+ENTRY_END
+
+STEP 8300 QUERY
+ENTRY_BEGIN
+RAW
+b69cc935501022384c2d0000000000000000
+ENTRY_END
+
+STEP 8310 QUERY
+ENTRY_BEGIN
+RAW
+b69cc935501122384c2c0000000000000000
+ENTRY_END
+
+STEP 8320 QUERY
+ENTRY_BEGIN
+RAW
+b69d9ed55010223878980000000000000000
+ENTRY_END
+
+STEP 8330 QUERY
+ENTRY_BEGIN
+RAW
+b69d9ed55011223878970000000000000000
+ENTRY_END
+
+STEP 8340 QUERY
+ENTRY_BEGIN
+RAW
+b69808175010222acdc00000000000000000
+ENTRY_END
+
+STEP 8350 QUERY
+ENTRY_BEGIN
+RAW
+b69b68b4501022387c650000000000000000
+ENTRY_END
+
+STEP 8360 QUERY
+ENTRY_BEGIN
+RAW
+b69b68b450182238179600000096fbd8000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afcf7403c4e770003000000374e544c4d535350000100000097b200e0080008002f0000000f000f00200000004b4d57452d4345335648394a4450504b4d57452d5553500000
+ENTRY_END
+
+STEP 8370 QUERY
+ENTRY_BEGIN
+RAW
+b69d9ed65010223878960000000000000000
+ENTRY_END
+
+STEP 8380 QUERY
+ENTRY_BEGIN
+RAW
+b69b68c25011222a7bcc0000000000000000
+ENTRY_END
+
+STEP 8390 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238f8440000020405b40000
+ENTRY_END
+
+STEP 8400 QUERY
+ENTRY_BEGIN
+RAW
+b69e234c5010223836070000000000000000
+ENTRY_END
+
+STEP 8410 QUERY
+ENTRY_BEGIN
+RAW
+b69e234c50182238a76e0000001cec240000000100000000000007646574616e6574026e6c0000060001
+ENTRY_END
+
+STEP 8420 QUERY
+ENTRY_BEGIN
+RAW
+b69e23a25010223835930000000000000000
+ENTRY_END
+
+STEP 8430 QUERY
+ENTRY_BEGIN
+RAW
+b69e23a25011223835920000000000000000
+ENTRY_END
+
+STEP 8440 QUERY
+ENTRY_BEGIN
+RAW
+b69e23a35010223835910000000000000000
+ENTRY_END
+
+STEP 8450 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238dcbc0000020405b40000
+ENTRY_END
+
+STEP 8460 QUERY
+ENTRY_BEGIN
+RAW
+b69ef086501022384d440000000000000000
+ENTRY_END
+
+STEP 8470 QUERY
+ENTRY_BEGIN
+RAW
+b69ef08650182238ae2500000022a14e000000010000000000000d726567627772667279736c616e026e6c0000060001
+ENTRY_END
+
+STEP 8480 QUERY
+ENTRY_BEGIN
+RAW
+b69ef0ec501022384cba0000000000000000
+ENTRY_END
+
+STEP 8490 QUERY
+ENTRY_BEGIN
+RAW
+b69ef0ec501122384cb90000000000000000
+ENTRY_END
+
+STEP 8500 QUERY
+ENTRY_BEGIN
+RAW
+b69ef0ed501022384cb80000000000000000
+ENTRY_END
+
+STEP 8510 QUERY
+ENTRY_BEGIN
+RAW
+b69b68c35010222a7bcb0000000000000000
+ENTRY_END
+
+STEP 8520 QUERY
+ENTRY_BEGIN
+RAW
+b68303575018faf04b560000008df340000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd16403c4e9600030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 8530 QUERY
+ENTRY_BEGIN
+RAW
+b68303575018faf04b560000008df340000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd16403c4e9600030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 8540 QUERY
+ENTRY_BEGIN
+RAW
+b68303655011fae21a560000000000000000
+ENTRY_END
+
+STEP 8550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf041b60000020405b401010402
+ENTRY_END
+
+STEP 8560 QUERY
+ENTRY_BEGIN
+RAW
+b68303665010fae21a550000000000000000
+ENTRY_END
+
+STEP 8570 QUERY
+ENTRY_BEGIN
+RAW
+b69faca65010faf00b240000000000000000
+ENTRY_END
+
+STEP 8580 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b3a50000020405b401010402
+ENTRY_END
+
+STEP 8590 QUERY
+ENTRY_BEGIN
+RAW
+b6a1a840501044707d070000000000000000
+ENTRY_END
+
+STEP 8600 QUERY
+ENTRY_BEGIN
+RAW
+b6a1a84050184470f4c200000089cc64000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7dfc403ccf7c00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 8610 QUERY
+ENTRY_BEGIN
+RAW
+b6a1a84e501144627c7b0000000000000000
+ENTRY_END
+
+STEP 8620 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ecb50000020405b401010402
+ENTRY_END
+
+STEP 8630 QUERY
+ENTRY_BEGIN
+RAW
+b6a1a84f501044627c7a0000000000000000
+ENTRY_END
+
+STEP 8640 QUERY
+ENTRY_BEGIN
+RAW
+b6a27e2c50104470e02a0000000000000000
+ENTRY_END
+
+STEP 8650 QUERY
+ENTRY_BEGIN
+RAW
+b6a27e2c501844708c830000008998c8000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7dfc403ccf7c00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 8660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400050a700000204055001010402
+ENTRY_END
+
+STEP 8670 QUERY
+ENTRY_BEGIN
+RAW
+b6a27e3a50114462df9e0000000000000000
+ENTRY_END
+
+STEP 8680 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b8ba0000020405b401010402
+ENTRY_END
+
+STEP 8690 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238473c0000020405b40000
+ENTRY_END
+
+STEP 8700 QUERY
+ENTRY_BEGIN
+RAW
+b6a2fbb450104510c58f0000000000000000
+ENTRY_END
+
+STEP 8710 QUERY
+ENTRY_BEGIN
+RAW
+b6a27e3b50104462df9d0000000000000000
+ENTRY_END
+
+STEP 8720 QUERY
+ENTRY_BEGIN
+RAW
+b6a2fbb4501845108d3c0000008b6710000000010001000000000f313238383439303138383831382d330000f900010f313238383439303138383831382d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afc3b403c4dbb00030000002c4e544c4d535350000100000097b208e0060006002600000006000600200000005345525645524b4f525055540000
+ENTRY_END
+
+STEP 8730 QUERY
+ENTRY_BEGIN
+RAW
+b6a4048e50102238a3b60000000000000000
+ENTRY_END
+
+STEP 8740 QUERY
+ENTRY_BEGIN
+RAW
+b6a4048e5018223847ff000000213084000000010000000000000c636f7379636f6d7061676e79026e6c0000060001
+ENTRY_END
+
+STEP 8750 QUERY
+ENTRY_BEGIN
+RAW
+b6a3836950104470a6f10000000000000000
+ENTRY_END
+
+STEP 8760 QUERY
+ENTRY_BEGIN
+RAW
+b6a2fbc250114502c5010000000000000000
+ENTRY_END
+
+STEP 8770 QUERY
+ENTRY_BEGIN
+RAW
+b6a38369501844702ad200000089c140000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7dfc403ccf7c00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 8780 QUERY
+ENTRY_BEGIN
+RAW
+b6a404f350102238a32e0000000000000000
+ENTRY_END
+
+STEP 8790 QUERY
+ENTRY_BEGIN
+RAW
+b6a404f350112238a32d0000000000000000
+ENTRY_END
+
+STEP 8800 QUERY
+ENTRY_BEGIN
+RAW
+b6a2fbc350104502c5000000000000000000
+ENTRY_END
+
+STEP 8810 QUERY
+ENTRY_BEGIN
+RAW
+b6a404f450102238a32c0000000000000000
+ENTRY_END
+
+STEP 8820 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400097e000000204055001010402
+ENTRY_END
+
+STEP 8830 QUERY
+ENTRY_BEGIN
+RAW
+b6a3837750114462a6650000000000000000
+ENTRY_END
+
+STEP 8840 QUERY
+ENTRY_BEGIN
+RAW
+b6a4a43f50104510643c0000000000000000
+ENTRY_END
+
+STEP 8850 QUERY
+ENTRY_BEGIN
+RAW
+b6a4a43f50184510f6e30000008b9d16000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afc3b403c4dbb00030000002c4e544c4d535350000100000097b208e0060006002600000006000600200000005345525645524b4f525055540000
+ENTRY_END
+
+STEP 8860 QUERY
+ENTRY_BEGIN
+RAW
+b6a3837850104462a6640000000000000000
+ENTRY_END
+
+STEP 8870 QUERY
+ENTRY_BEGIN
+RAW
+b6a4a44d5011450263ae0000000000000000
+ENTRY_END
+
+STEP 8880 QUERY
+ENTRY_BEGIN
+RAW
+b6a4a44e5010450263ad0000000000000000
+ENTRY_END
+
+STEP 8890 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b33700000204055001010402
+ENTRY_END
+
+STEP 8900 QUERY
+ENTRY_BEGIN
+RAW
+b6a5493c50104510da950000000000000000
+ENTRY_END
+
+STEP 8910 QUERY
+ENTRY_BEGIN
+RAW
+b6a5493c5018451037370000008bd31c000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afc3b403c4dbb00030000002c4e544c4d535350000100000097b208e0060006002600000006000600200000005345525645524b4f525055540000
+ENTRY_END
+
+STEP 8920 QUERY
+ENTRY_BEGIN
+RAW
+b6a5494a50114502da070000000000000000
+ENTRY_END
+
+STEP 8930 QUERY
+ENTRY_BEGIN
+RAW
+b6a5494b50104502da060000000000000000
+ENTRY_END
+
+STEP 8940 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004ad60000020405b401010402
+ENTRY_END
+
+STEP 8950 QUERY
+ENTRY_BEGIN
+RAW
+b6a82dab501044708ec60000000000000000
+ENTRY_END
+
+STEP 8960 QUERY
+ENTRY_BEGIN
+RAW
+b6a82dab50184470944f0000008b9351000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afa97403c4c1700030000002e4e544c4d535350000100000097b200c0060006002800000008000800200000004c4150544f5037415a50444550330000
+ENTRY_END
+
+STEP 8970 QUERY
+ENTRY_BEGIN
+RAW
+b6a82db9501144628e380000000000000000
+ENTRY_END
+
+STEP 8980 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000adc20000020405b401010402
+ENTRY_END
+
+STEP 8990 QUERY
+ENTRY_BEGIN
+RAW
+b6a82dba501044628e370000000000000000
+ENTRY_END
+
+STEP 9000 QUERY
+ENTRY_BEGIN
+RAW
+b6a8c206501044705d570000000000000000
+ENTRY_END
+
+STEP 9010 QUERY
+ENTRY_BEGIN
+RAW
+b6a8c206501844702ecc0000008bc965000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afa97403c4c1700030000002e4e544c4d535350000100000097b200c0060006002800000008000800200000004c4150544f5037415a50444550330000
+ENTRY_END
+
+STEP 9020 QUERY
+ENTRY_BEGIN
+RAW
+b6a8c214501144625cc90000000000000000
+ENTRY_END
+
+STEP 9030 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c87d0000020405b401010402
+ENTRY_END
+
+STEP 9040 QUERY
+ENTRY_BEGIN
+RAW
+b6a8c215501044625cc80000000000000000
+ENTRY_END
+
+STEP 9050 QUERY
+ENTRY_BEGIN
+RAW
+b6a93e2050104470fbf70000000000000000
+ENTRY_END
+
+STEP 9060 QUERY
+ENTRY_BEGIN
+RAW
+b6a93e205018447049070000008b4bcb000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afa98403c4c1800030000002e4e544c4d535350000100000097b200c0060006002800000008000800200000004c4150544f5037415a50444550330000
+ENTRY_END
+
+STEP 9070 QUERY
+ENTRY_BEGIN
+RAW
+b6a93e2e50114462fb690000000000000000
+ENTRY_END
+
+STEP 9080 QUERY
+ENTRY_BEGIN
+RAW
+b6a93e2f50104462fb680000000000000000
+ENTRY_END
+
+STEP 9090 QUERY
+ENTRY_BEGIN
+RAW
+b69cc936501022384c2b0000000000000000
+ENTRY_END
+
+STEP 9100 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0235a0000020405b401010402
+ENTRY_END
+
+STEP 9110 QUERY
+ENTRY_BEGIN
+RAW
+b6ab2c4f5010faf06d130000000000000000
+ENTRY_END
+
+STEP 9120 QUERY
+ENTRY_BEGIN
+RAW
+b6ab2c4f5018faf057b60000008ece11000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403af4fb403c467b00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 9130 QUERY
+ENTRY_BEGIN
+RAW
+b6ab2c5d5011fae26c820000000000000000
+ENTRY_END
+
+STEP 9140 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d00e0000020405b401010402
+ENTRY_END
+
+STEP 9150 QUERY
+ENTRY_BEGIN
+RAW
+b6ab2c5e5010fae26c810000000000000000
+ENTRY_END
+
+STEP 9160 QUERY
+ENTRY_BEGIN
+RAW
+b6aba8ae5010faf09d680000000000000000
+ENTRY_END
+
+STEP 9170 QUERY
+ENTRY_BEGIN
+RAW
+b6aba8ae5018faf09fa00000008eb77d000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af4fb403c467b00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 9180 QUERY
+ENTRY_BEGIN
+RAW
+b6aba8bc5011fae29cd70000000000000000
+ENTRY_END
+
+STEP 9190 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0ca480000020405b401010402
+ENTRY_END
+
+STEP 9200 QUERY
+ENTRY_BEGIN
+RAW
+b6aba8bd5010fae29cd60000000000000000
+ENTRY_END
+
+STEP 9210 QUERY
+ENTRY_BEGIN
+RAW
+b6ac8a535010faf0b5fc0000000000000000
+ENTRY_END
+
+STEP 9220 QUERY
+ENTRY_BEGIN
+RAW
+b6ac8a535018faf07d360000008ef27b000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af4fb403c467b00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 9230 QUERY
+ENTRY_BEGIN
+RAW
+b6ac8a615011fae2b56b0000000000000000
+ENTRY_END
+
+STEP 9240 QUERY
+ENTRY_BEGIN
+RAW
+b6ac8a625010fae2b56a0000000000000000
+ENTRY_END
+
+STEP 9250 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d5990000020405b401010402
+ENTRY_END
+
+STEP 9260 QUERY
+ENTRY_BEGIN
+RAW
+b6ad439b5010faf008050000000000000000
+ENTRY_END
+
+STEP 9270 QUERY
+ENTRY_BEGIN
+RAW
+b6ad439b5018faf01c6c0000009404ed000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd46403c4ec60003000000354e544c4d535350000100000097b208e00c000c0029000000090009002000000057454253455256455244455749542d424f454b454c0000
+ENTRY_END
+
+STEP 9280 QUERY
+ENTRY_BEGIN
+RAW
+b6ad43a95011fae2076e0000000000000000
+ENTRY_END
+
+STEP 9290 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c84e0000020405b401010402
+ENTRY_END
+
+STEP 9300 QUERY
+ENTRY_BEGIN
+RAW
+b6ad43aa5010fae2076d0000000000000000
+ENTRY_END
+
+STEP 9310 QUERY
+ENTRY_BEGIN
+RAW
+b6af01195010faf03d3a0000000000000000
+ENTRY_END
+
+STEP 9320 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf015f200000204057a01010402
+ENTRY_END
+
+STEP 9330 QUERY
+ENTRY_BEGIN
+RAW
+b6afec4b5010fbec9e740000000000000000
+ENTRY_END
+
+STEP 9340 QUERY
+ENTRY_BEGIN
+RAW
+b6afec4b5018fbec1c5700000091d900000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afed7403c50570003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 9350 QUERY
+ENTRY_BEGIN
+RAW
+b6afec595011fbde9de00000000000000000
+ENTRY_END
+
+STEP 9360 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf040ad00000204057a01010402
+ENTRY_END
+
+STEP 9370 QUERY
+ENTRY_BEGIN
+RAW
+b6afec5a5010fbde9ddf0000000000000000
+ENTRY_END
+
+STEP 9380 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001ed00000020405b401010402
+ENTRY_END
+
+STEP 9390 QUERY
+ENTRY_BEGIN
+RAW
+b6b09cca5010fbec18b00000000000000000
+ENTRY_END
+
+STEP 9400 QUERY
+ENTRY_BEGIN
+RAW
+b6b09cca5018fbece393000000918d00000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afed7403c50570003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 9410 QUERY
+ENTRY_BEGIN
+RAW
+b6b17c0a5010447014580000000000000000
+ENTRY_END
+
+STEP 9420 QUERY
+ENTRY_BEGIN
+RAW
+b6b17c0a501844707e9d0000008bacbd000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd5b403c4edb00030000002e4e544c4d535350000100000097b200c00900090025000000050005002000000050432d3035574f524b47524f55500000
+ENTRY_END
+
+STEP 9430 QUERY
+ENTRY_BEGIN
+RAW
+b6b09cd85011fbde181c0000000000000000
+ENTRY_END
+
+STEP 9440 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf085cb00000204057a01010402
+ENTRY_END
+
+STEP 9450 QUERY
+ENTRY_BEGIN
+RAW
+b6b09cd95010fbde181b0000000000000000
+ENTRY_END
+
+STEP 9460 QUERY
+ENTRY_BEGIN
+RAW
+b6b17c185011446213ca0000000000000000
+ENTRY_END
+
+STEP 9470 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f4030000020405b401010402
+ENTRY_END
+
+STEP 9480 QUERY
+ENTRY_BEGIN
+RAW
+b6b2661c5010fbec947a0000000000000000
+ENTRY_END
+
+STEP 9490 QUERY
+ENTRY_BEGIN
+RAW
+b6b2661c5018fbecab5e000000914100000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afed7403c50570003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 9500 QUERY
+ENTRY_BEGIN
+RAW
+b6b17c195010446213c90000000000000000
+ENTRY_END
+
+STEP 9510 QUERY
+ENTRY_BEGIN
+RAW
+b6b3418b5010447024090000000000000000
+ENTRY_END
+
+STEP 9520 QUERY
+ENTRY_BEGIN
+RAW
+b6b3418b5018447033d70000008b0935000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd5b403c4edb00030000002e4e544c4d535350000100000097b200c00900090025000000050005002000000050432d3035574f524b47524f55500000
+ENTRY_END
+
+STEP 9530 QUERY
+ENTRY_BEGIN
+RAW
+b6b2662a5011fbde93e60000000000000000
+ENTRY_END
+
+STEP 9540 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000c4d0000020405b401010402
+ENTRY_END
+
+STEP 9550 QUERY
+ENTRY_BEGIN
+RAW
+b6b3419950114462237b0000000000000000
+ENTRY_END
+
+STEP 9560 QUERY
+ENTRY_BEGIN
+RAW
+b6b2662b5010fbde93e50000000000000000
+ENTRY_END
+
+STEP 9570 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400045b80000020405b401010402
+ENTRY_END
+
+STEP 9580 QUERY
+ENTRY_BEGIN
+RAW
+b6b3419a50104462237a0000000000000000
+ENTRY_END
+
+STEP 9590 QUERY
+ENTRY_BEGIN
+RAW
+b6b4f31650104470c4300000000000000000
+ENTRY_END
+
+STEP 9600 QUERY
+ENTRY_BEGIN
+RAW
+b6b42daf50104470502d0000000000000000
+ENTRY_END
+
+STEP 9610 QUERY
+ENTRY_BEGIN
+RAW
+b6b4f3165018447077860000008b65ad000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd5b403c4edb00030000002e4e544c4d535350000100000097b200c00900090025000000050005002000000050432d3035574f524b47524f55500000
+ENTRY_END
+
+STEP 9620 QUERY
+ENTRY_BEGIN
+RAW
+b6b42daf5018447031a50000008fb8e6000000010001000000000f313238383439303138383831382d330000f900010f313238383439303138383831382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afccd403c4e4d0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 9630 QUERY
+ENTRY_BEGIN
+RAW
+b6b4f32450114462c3a20000000000000000
+ENTRY_END
+
+STEP 9640 QUERY
+ENTRY_BEGIN
+RAW
+b6b42dbd501144624f9b0000000000000000
+ENTRY_END
+
+STEP 9650 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400016260000020405b401010402
+ENTRY_END
+
+STEP 9660 QUERY
+ENTRY_BEGIN
+RAW
+b6b4f32550104462c3a10000000000000000
+ENTRY_END
+
+STEP 9670 QUERY
+ENTRY_BEGIN
+RAW
+b6b42dbe501044624f9a0000000000000000
+ENTRY_END
+
+STEP 9680 QUERY
+ENTRY_BEGIN
+RAW
+b6b57d3e501044700a760000000000000000
+ENTRY_END
+
+STEP 9690 QUERY
+ENTRY_BEGIN
+RAW
+b6b57d3e501844703aa10000008f6b34000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afccd403c4e4d0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 9700 QUERY
+ENTRY_BEGIN
+RAW
+b6b57d4c5011446209e40000000000000000
+ENTRY_END
+
+STEP 9710 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002b9e0000020405b401010402
+ENTRY_END
+
+STEP 9720 QUERY
+ENTRY_BEGIN
+RAW
+b6b57d4d5010446209e30000000000000000
+ENTRY_END
+
+STEP 9730 QUERY
+ENTRY_BEGIN
+RAW
+b6b667875010447035a40000000000000000
+ENTRY_END
+
+STEP 9740 QUERY
+ENTRY_BEGIN
+RAW
+b6b66787501844704d880000008f837b000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afccd403c4e4d0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 9750 QUERY
+ENTRY_BEGIN
+RAW
+b6b667955011446235120000000000000000
+ENTRY_END
+
+STEP 9760 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf07fea0000020405b401010402
+ENTRY_END
+
+STEP 9770 QUERY
+ENTRY_BEGIN
+RAW
+b6b8e7615010faf00e840000000000000000
+ENTRY_END
+
+STEP 9780 QUERY
+ENTRY_BEGIN
+RAW
+b6b8e7615018faf014680000009b3a67000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af52c403c46ac00030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 9790 QUERY
+ENTRY_BEGIN
+RAW
+b6b8e76f5011fae20de60000000000000000
+ENTRY_END
+
+STEP 9800 QUERY
+ENTRY_BEGIN
+RAW
+b6b8e7705010fae20de50000000000000000
+ENTRY_END
+
+STEP 9810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f2b90000020405b401010402
+ENTRY_END
+
+STEP 9820 QUERY
+ENTRY_BEGIN
+RAW
+b6b964ca5010faf003ea0000000000000000
+ENTRY_END
+
+STEP 9830 QUERY
+ENTRY_BEGIN
+RAW
+b6b964ca5018faf076f60000009bce3f000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af52c403c46ac00030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 9840 QUERY
+ENTRY_BEGIN
+RAW
+b6b964d85011fae2034c0000000000000000
+ENTRY_END
+
+STEP 9850 QUERY
+ENTRY_BEGIN
+RAW
+b6b964d95010fae2034b0000000000000000
+ENTRY_END
+
+STEP 9860 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0cbb80000020405b401010402
+ENTRY_END
+
+STEP 9870 QUERY
+ENTRY_BEGIN
+RAW
+b6ba546e5010faf0ed430000000000000000
+ENTRY_END
+
+STEP 9880 QUERY
+ENTRY_BEGIN
+RAW
+b6ba546e5018faf0e7820000009b470d000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af52c403c46ac00030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 9890 QUERY
+ENTRY_BEGIN
+RAW
+b6ba547c5011fae2eca50000000000000000
+ENTRY_END
+
+STEP 9900 QUERY
+ENTRY_BEGIN
+RAW
+b6b667965010446235110000000000000000
+ENTRY_END
+
+STEP 9910 QUERY
+ENTRY_BEGIN
+RAW
+b6ba547d5010fae2eca40000000000000000
+ENTRY_END
+
+STEP 9920 QUERY
+ENTRY_BEGIN
+RAW
+301400000001000000000000056162632d64026e6c00000f000100
+ENTRY_END
+
+STEP 9930 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033180000020405b401010402
+ENTRY_END
+
+STEP 9940 QUERY
+ENTRY_BEGIN
+RAW
+b6bc703d5010447034620000000000000000
+ENTRY_END
+
+STEP 9950 QUERY
+ENTRY_BEGIN
+RAW
+b6bc703d50184470bc270000008b5640000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403aff88403c510800030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004f4b465330314f4b42414e4b0000
+ENTRY_END
+
+STEP 9960 QUERY
+ENTRY_BEGIN
+RAW
+b6bc704b5011446233d40000000000000000
+ENTRY_END
+
+STEP 9970 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000f670000020405b401010402
+ENTRY_END
+
+STEP 9980 QUERY
+ENTRY_BEGIN
+RAW
+b6bc704c5010446233d30000000000000000
+ENTRY_END
+
+STEP 9990 QUERY
+ENTRY_BEGIN
+RAW
+b6bd08a65010447078470000000000000000
+ENTRY_END
+
+STEP 10000 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a9bc0000020405b401010402
+ENTRY_END
+
+STEP 10010 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000db0500000204059801010402
+ENTRY_END
+
+STEP 10020 QUERY
+ENTRY_BEGIN
+RAW
+b6bd08a650184470054e0000008b5200000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403aff88403c510800030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004f4b465330314f4b42414e4b0000
+ENTRY_END
+
+STEP 10030 QUERY
+ENTRY_BEGIN
+RAW
+b6bd08b45011446277b90000000000000000
+ENTRY_END
+
+STEP 10040 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400064bd0000020405b401010402
+ENTRY_END
+
+STEP 10050 QUERY
+ENTRY_BEGIN
+RAW
+b6be7cc050104320d0fe0000000000000000
+ENTRY_END
+
+STEP 10060 QUERY
+ENTRY_BEGIN
+RAW
+b6be7cc050184320edb00000008b052a000000010001000000000f313235343133303435303435302d330000f900010f313235343133303435303435302d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afcf2403c4e7200030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 10070 QUERY
+ENTRY_BEGIN
+RAW
+b6bdaa435010447070ff0000000000000000
+ENTRY_END
+
+STEP 10080 QUERY
+ENTRY_BEGIN
+RAW
+b6bd08b55010446277b80000000000000000
+ENTRY_END
+
+STEP 10090 QUERY
+ENTRY_BEGIN
+RAW
+b6bf1e6b50104470b7d60000000000000000
+ENTRY_END
+
+STEP 10100 QUERY
+ENTRY_BEGIN
+RAW
+b6bdaa43501844701b0c0000008fee51000000010001000000000f313238383439303138383831382d330000f900010f313238383439303138383831382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcce403c4e4e0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 10110 QUERY
+ENTRY_BEGIN
+RAW
+b6bf1e6b5018447094dd0000008b0000000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403aff89403c510900030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004f4b465330314f4b42414e4b0000
+ENTRY_END
+
+STEP 10120 QUERY
+ENTRY_BEGIN
+RAW
+b6be7cce50114312d0700000000000000000
+ENTRY_END
+
+STEP 10130 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f0e400000204059801010402
+ENTRY_END
+
+STEP 10140 QUERY
+ENTRY_BEGIN
+RAW
+b6bf1e7950114462b7480000000000000000
+ENTRY_END
+
+STEP 10150 QUERY
+ENTRY_BEGIN
+RAW
+b6be7ccf50104312d06f0000000000000000
+ENTRY_END
+
+STEP 10160 QUERY
+ENTRY_BEGIN
+RAW
+b6c012365010432051660000000000000000
+ENTRY_END
+
+STEP 10170 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000502d0000020405b401010402
+ENTRY_END
+
+STEP 10180 QUERY
+ENTRY_BEGIN
+RAW
+b6bdaa5150114462706d0000000000000000
+ENTRY_END
+
+STEP 10190 QUERY
+ENTRY_BEGIN
+RAW
+b6c01236501843209f6a0000008bd4d8000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afcf2403c4e7200030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 10200 QUERY
+ENTRY_BEGIN
+RAW
+b6bf1e7a50104462b7470000000000000000
+ENTRY_END
+
+STEP 10210 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400049720000020405b401010402
+ENTRY_END
+
+STEP 10220 QUERY
+ENTRY_BEGIN
+RAW
+b6c0be4f5010447003610000000000000000
+ENTRY_END
+
+STEP 10230 QUERY
+ENTRY_BEGIN
+RAW
+b6c012445011431250d80000000000000000
+ENTRY_END
+
+STEP 10240 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400006b200000204059801010402
+ENTRY_END
+
+STEP 10250 QUERY
+ENTRY_BEGIN
+RAW
+b6c0be4f501844704c7700000098a800000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005c03677373096d6963726f736f667403636f6d00403b3488403c86080003000000394e544c4d535350000100000097b200e00b000b002e0000000e000e00200000005352564e53485549534b414d45524445485549534b414d45520000
+ENTRY_END
+
+STEP 10260 QUERY
+ENTRY_BEGIN
+RAW
+b6bdaa5250104462706c0000000000000000
+ENTRY_END
+
+STEP 10270 QUERY
+ENTRY_BEGIN
+RAW
+b6c15b51501044705fa30000000000000000
+ENTRY_END
+
+STEP 10280 QUERY
+ENTRY_BEGIN
+RAW
+b6c0be5d5011446202c60000000000000000
+ENTRY_END
+
+STEP 10290 QUERY
+ENTRY_BEGIN
+RAW
+b6c012455010431250d70000000000000000
+ENTRY_END
+
+STEP 10300 QUERY
+ENTRY_BEGIN
+RAW
+b6c242d15010432036960000000000000000
+ENTRY_END
+
+STEP 10310 QUERY
+ENTRY_BEGIN
+RAW
+b6c15b515018447058630000008fa09f000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcce403c4e4e0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 10320 QUERY
+ENTRY_BEGIN
+RAW
+b6c242d1501843208bcc0000008bcda6000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afcf2403c4e7200030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 10330 QUERY
+ENTRY_BEGIN
+RAW
+b6c0be5e5010446202c50000000000000000
+ENTRY_END
+
+STEP 10340 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400051f60000020405b401010402
+ENTRY_END
+
+STEP 10350 QUERY
+ENTRY_BEGIN
+RAW
+b6c242df5011431236080000000000000000
+ENTRY_END
+
+STEP 10360 QUERY
+ENTRY_BEGIN
+RAW
+b6c2c4ef50104470fe870000000000000000
+ENTRY_END
+
+STEP 10370 QUERY
+ENTRY_BEGIN
+RAW
+b6c15b5f501144625f110000000000000000
+ENTRY_END
+
+STEP 10380 QUERY
+ENTRY_BEGIN
+RAW
+b6c2c4ef501844709c1f000000985480000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005c03677373096d6963726f736f667403636f6d00403b3488403c86080003000000394e544c4d535350000100000097b200e00b000b002e0000000e000e00200000005352564e53485549534b414d45524445485549534b414d45520000
+ENTRY_END
+
+STEP 10390 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400028970000020405b401010402
+ENTRY_END
+
+STEP 10400 QUERY
+ENTRY_BEGIN
+RAW
+b6c242e05010431236070000000000000000
+ENTRY_END
+
+STEP 10410 QUERY
+ENTRY_BEGIN
+RAW
+b6c2c4fd50114462fdec0000000000000000
+ENTRY_END
+
+STEP 10420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c2030000020405b401010402
+ENTRY_END
+
+STEP 10430 QUERY
+ENTRY_BEGIN
+RAW
+b6c15b60501044625f100000000000000000
+ENTRY_END
+
+STEP 10440 QUERY
+ENTRY_BEGIN
+RAW
+b6c34b44501044704ed30000000000000000
+ENTRY_END
+
+STEP 10450 QUERY
+ENTRY_BEGIN
+RAW
+b6c3f5a6501044703ddd0000000000000000
+ENTRY_END
+
+STEP 10460 QUERY
+ENTRY_BEGIN
+RAW
+b6c34b44501844702f4c0000008fb8e6000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afcce403c4e4e0003000000304e544c4d535350000100000097b208e0040004002c0000000c000c002000000044432d505245434953494f4e465331410000
+ENTRY_END
+
+STEP 10470 QUERY
+ENTRY_BEGIN
+RAW
+b6c3f5a650184470517400000098de80000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005c03677373096d6963726f736f667403636f6d00403b3488403c86080003000000394e544c4d535350000100000097b200e00b000b002e0000000e000e00200000005352564e53485549534b414d45524445485549534b414d45520000
+ENTRY_END
+
+STEP 10480 QUERY
+ENTRY_BEGIN
+RAW
+b6c2c4fe50104462fdeb0000000000000000
+ENTRY_END
+
+STEP 10490 QUERY
+ENTRY_BEGIN
+RAW
+b6c3f5b4501144623d420000000000000000
+ENTRY_END
+
+STEP 10500 QUERY
+ENTRY_BEGIN
+RAW
+b6c34b52501144624e410000000000000000
+ENTRY_END
+
+STEP 10510 QUERY
+ENTRY_BEGIN
+RAW
+b6c3f5b5501044623d410000000000000000
+ENTRY_END
+
+STEP 10520 QUERY
+ENTRY_BEGIN
+RAW
+b6c34b53501044624e400000000000000000
+ENTRY_END
+
+STEP 10530 QUERY
+ENTRY_BEGIN
+RAW
+b69faca65018faf061d40000008dc500000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd1a403c4e9a00030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 10540 QUERY
+ENTRY_BEGIN
+RAW
+b69faca65018faf061d40000008dc500000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd1a403c4e9a00030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 10550 QUERY
+ENTRY_BEGIN
+RAW
+b69facb45011fae20a940000000000000000
+ENTRY_END
+
+STEP 10560 QUERY
+ENTRY_BEGIN
+RAW
+b69facb55010fae20a930000000000000000
+ENTRY_END
+
+STEP 10570 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b64800000204057a01010402
+ENTRY_END
+
+STEP 10580 QUERY
+ENTRY_BEGIN
+RAW
+b6c93a3c5010fbecf0c00000000000000000
+ENTRY_END
+
+STEP 10590 QUERY
+ENTRY_BEGIN
+RAW
+b6c93a3c5018fbecb7d2000000934464000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9e3403c4b630003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 10600 QUERY
+ENTRY_BEGIN
+RAW
+b6c93a4a5011fbdef02a0000000000000000
+ENTRY_END
+
+STEP 10610 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c71200000204057a01010402
+ENTRY_END
+
+STEP 10620 QUERY
+ENTRY_BEGIN
+RAW
+b6c93a4b5010fbdef0290000000000000000
+ENTRY_END
+
+STEP 10630 QUERY
+ENTRY_BEGIN
+RAW
+b6c9f1515010fbec4a750000000000000000
+ENTRY_END
+
+STEP 10640 QUERY
+ENTRY_BEGIN
+RAW
+b6c9f1515018fbec5e5f00000093f88c000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9e3403c4b630003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 10650 QUERY
+ENTRY_BEGIN
+RAW
+b6c9f15f5011fbde49df0000000000000000
+ENTRY_END
+
+STEP 10660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e90c00000204057a01010402
+ENTRY_END
+
+STEP 10670 QUERY
+ENTRY_BEGIN
+RAW
+b6c9f1605010fbde49de0000000000000000
+ENTRY_END
+
+STEP 10680 QUERY
+ENTRY_BEGIN
+RAW
+b6cab1035010fbecacbc0000000000000000
+ENTRY_END
+
+STEP 10690 QUERY
+ENTRY_BEGIN
+RAW
+b6cab1035018fbec0c7f00000093acb4000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9e3403c4b630003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 10700 QUERY
+ENTRY_BEGIN
+RAW
+b6cab1115011fbdeac260000000000000000
+ENTRY_END
+
+STEP 10710 QUERY
+ENTRY_BEGIN
+RAW
+b6cab1125010fbdeac250000000000000000
+ENTRY_END
+
+STEP 10720 QUERY
+ENTRY_BEGIN
+RAW
+b6af01195018faf0d037000000948757000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd46403c4ec60003000000354e544c4d535350000100000097b208e00c000c0029000000090009002000000057454253455256455244455749542d424f454b454c0000
+ENTRY_END
+
+STEP 10730 QUERY
+ENTRY_BEGIN
+RAW
+b6af01275011fae23ca30000000000000000
+ENTRY_END
+
+STEP 10740 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b1b20000020405b401010402
+ENTRY_END
+
+STEP 10750 QUERY
+ENTRY_BEGIN
+RAW
+b6af01285010fae23ca20000000000000000
+ENTRY_END
+
+STEP 10760 QUERY
+ENTRY_BEGIN
+RAW
+b6cd10ad5010faf016ec0000000000000000
+ENTRY_END
+
+STEP 10770 QUERY
+ENTRY_BEGIN
+RAW
+b6cd10ad5018faf0499600000094e1aa000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd49403c4ec90003000000354e544c4d535350000100000097b208e00c000c0029000000090009002000000057454253455256455244455749542d424f454b454c0000
+ENTRY_END
+
+STEP 10780 QUERY
+ENTRY_BEGIN
+RAW
+b6cd10bb5011fae216550000000000000000
+ENTRY_END
+
+STEP 10790 QUERY
+ENTRY_BEGIN
+RAW
+b6cd10bc5010fae216540000000000000000
+ENTRY_END
+
+STEP 10800 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400090d30000020405b401010402
+ENTRY_END
+
+STEP 10810 QUERY
+ENTRY_BEGIN
+RAW
+b6cda384501008009b350000000000000000
+ENTRY_END
+
+STEP 10820 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0a8680000020405b401010402
+ENTRY_END
+
+STEP 10830 QUERY
+ENTRY_BEGIN
+RAW
+b6cda384501044705ec50000000000000000
+ENTRY_END
+
+STEP 10840 QUERY
+ENTRY_BEGIN
+RAW
+b6ce7def5010faf0a05e0000000000000000
+ENTRY_END
+
+STEP 10850 QUERY
+ENTRY_BEGIN
+RAW
+b6ce7def5018faf0e2720000008b24c2000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afab8403c4c3800030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005a374a3847374555524f4c494e450000
+ENTRY_END
+
+STEP 10860 QUERY
+ENTRY_BEGIN
+RAW
+b6cda384501844708c0d0000009b7900000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005f03677373096d6963726f736f667403636f6d00403afcf3403c4e7300030000003c4e544c4d535350000100000097b200c00d000d002f0000000f000f00200000004148414e4f4f52442d5052494d55534148414e4f4f5244474f5557450000
+ENTRY_END
+
+STEP 10870 QUERY
+ENTRY_BEGIN
+RAW
+b6ce7dfd5011fae29fd00000000000000000
+ENTRY_END
+
+STEP 10880 QUERY
+ENTRY_BEGIN
+RAW
+b6ce7dfe5010fae29fcf0000000000000000
+ENTRY_END
+
+STEP 10890 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0fa060000020405b401010402
+ENTRY_END
+
+STEP 10900 QUERY
+ENTRY_BEGIN
+RAW
+b6cda392501144625e270000000000000000
+ENTRY_END
+
+STEP 10910 QUERY
+ENTRY_BEGIN
+RAW
+b6cf35215010faf03aca0000000000000000
+ENTRY_END
+
+STEP 10920 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400097f50000020405b401010402
+ENTRY_END
+
+STEP 10930 QUERY
+ENTRY_BEGIN
+RAW
+b6cf35215018faf0e0430000008bc35c000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afab8403c4c3800030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005a374a3847374555524f4c494e450000
+ENTRY_END
+
+STEP 10940 QUERY
+ENTRY_BEGIN
+RAW
+b6cf352f5011fae23a3c0000000000000000
+ENTRY_END
+
+STEP 10950 QUERY
+ENTRY_BEGIN
+RAW
+b6cda393501044625e260000000000000000
+ENTRY_END
+
+STEP 10960 QUERY
+ENTRY_BEGIN
+RAW
+b6cfdbce501008006a0b0000000000000000
+ENTRY_END
+
+STEP 10970 QUERY
+ENTRY_BEGIN
+RAW
+b6cfdbce501044702d9b0000000000000000
+ENTRY_END
+
+STEP 10980 QUERY
+ENTRY_BEGIN
+RAW
+b6cf35305010fae23a3b0000000000000000
+ENTRY_END
+
+STEP 10990 QUERY
+ENTRY_BEGIN
+RAW
+b6cfdbce5018447011640000009bc180000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403afcf4403c4e7400030000003c4e544c4d535350000100000097b200c00d000d002f0000000f000f00200000004148414e4f4f52442d5052494d55534148414e4f4f5244474f5557450000
+ENTRY_END
+
+STEP 11000 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf04c930000020405b401010402
+ENTRY_END
+
+STEP 11010 QUERY
+ENTRY_BEGIN
+RAW
+b6d071415010faf051350000000000000000
+ENTRY_END
+
+STEP 11020 QUERY
+ENTRY_BEGIN
+RAW
+b6d071415018faf08e770000008b2b94000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afab8403c4c3800030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005a374a3847374555524f4c494e450000
+ENTRY_END
+
+STEP 11030 QUERY
+ENTRY_BEGIN
+RAW
+b6d0714f5011fae250a70000000000000000
+ENTRY_END
+
+STEP 11040 QUERY
+ENTRY_BEGIN
+RAW
+b6cfdbdc501144622cfd0000000000000000
+ENTRY_END
+
+STEP 11050 QUERY
+ENTRY_BEGIN
+RAW
+b6d071505010fae250a60000000000000000
+ENTRY_END
+
+STEP 11060 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab920000020405b401010402
+ENTRY_END
+
+STEP 11070 QUERY
+ENTRY_BEGIN
+RAW
+b6cfdbdd501044622cfc0000000000000000
+ENTRY_END
+
+STEP 11080 QUERY
+ENTRY_BEGIN
+RAW
+b6d1320d5010080027680000000000000000
+ENTRY_END
+
+STEP 11090 QUERY
+ENTRY_BEGIN
+RAW
+b6d1320d50104470eaf70000000000000000
+ENTRY_END
+
+STEP 11100 QUERY
+ENTRY_BEGIN
+RAW
+b6d1320d50184470d5800000009bbac0000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403afcf4403c4e7400030000003c4e544c4d535350000100000097b200c00d000d002f0000000f000f00200000004148414e4f4f52442d5052494d55534148414e4f4f5244474f5557450000
+ENTRY_END
+
+STEP 11110 QUERY
+ENTRY_BEGIN
+RAW
+b6d1321b50114462ea590000000000000000
+ENTRY_END
+
+STEP 11120 QUERY
+ENTRY_BEGIN
+RAW
+b6d1321c50104462ea580000000000000000
+ENTRY_END
+
+STEP 11130 QUERY
+ENTRY_BEGIN
+RAW
+301500000001000000000000056162632d64026e6c00000f000100
+ENTRY_END
+
+STEP 11140 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400082ad0000020405b401010402
+ENTRY_END
+
+STEP 11150 QUERY
+ENTRY_BEGIN
+RAW
+b6d481b85010447072640000000000000000
+ENTRY_END
+
+STEP 11160 QUERY
+ENTRY_BEGIN
+RAW
+b6d481b85010447072640000000000000000
+ENTRY_END
+
+STEP 11170 QUERY
+ENTRY_BEGIN
+RAW
+b6d481b8501844700b7c000000909cca000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff7d403c50fd0003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 11180 QUERY
+ENTRY_BEGIN
+RAW
+b6d481c65011446271d10000000000000000
+ENTRY_END
+
+STEP 11190 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008dc10000020405b401010402
+ENTRY_END
+
+STEP 11200 QUERY
+ENTRY_BEGIN
+RAW
+b6d481c75010446271d00000000000000000
+ENTRY_END
+
+STEP 11210 QUERY
+ENTRY_BEGIN
+RAW
+b6d481c75010446271d00000000000000000
+ENTRY_END
+
+STEP 11220 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f37501044709ff60000000000000000
+ENTRY_END
+
+STEP 11230 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f37501044709ff60000000000000000
+ENTRY_END
+
+STEP 11240 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f37501844703a11000000909cc8000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff7d403c50fd0003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 11250 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f45501144629f630000000000000000
+ENTRY_END
+
+STEP 11260 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bf550000020405b401010402
+ENTRY_END
+
+STEP 11270 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f46501044629f620000000000000000
+ENTRY_END
+
+STEP 11280 QUERY
+ENTRY_BEGIN
+RAW
+b6d75f46501044629f620000000000000000
+ENTRY_END
+
+STEP 11290 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c5e50104470e4620000000000000000
+ENTRY_END
+
+STEP 11300 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c5e50104470e4620000000000000000
+ENTRY_END
+
+STEP 11310 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c5e501844707e7f000000909cc6000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff7d403c50fd0003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 11320 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c6c50114462e3cf0000000000000000
+ENTRY_END
+
+STEP 11330 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c6d50104462e3ce0000000000000000
+ENTRY_END
+
+STEP 11340 QUERY
+ENTRY_BEGIN
+RAW
+b6d84c6d50104462e3ce0000000000000000
+ENTRY_END
+
+STEP 11350 QUERY
+ENTRY_BEGIN
+RAW
+19400000000100000000000007616e74656e6e61026e6c00000f0001c0
+ENTRY_END
+
+STEP 11360 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002fa400000204057a01010402
+ENTRY_END
+
+STEP 11370 QUERY
+ENTRY_BEGIN
+RAW
+b6d9d267501041b8d1240000000000000000
+ENTRY_END
+
+STEP 11380 QUERY
+ENTRY_BEGIN
+RAW
+b6d9d267501841b8b41f000000945b40000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe2d403c4fad0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 11390 QUERY
+ENTRY_BEGIN
+RAW
+b6d9d275501141aad08d0000000000000000
+ENTRY_END
+
+STEP 11400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400024ae00000204057a01010402
+ENTRY_END
+
+STEP 11410 QUERY
+ENTRY_BEGIN
+RAW
+b6d9d276501041aad08c0000000000000000
+ENTRY_END
+
+STEP 11420 QUERY
+ENTRY_BEGIN
+RAW
+b6da64c0501041b833d50000000000000000
+ENTRY_END
+
+STEP 11430 QUERY
+ENTRY_BEGIN
+RAW
+b6da64c0501841b84611000000942d00000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe2d403c4fad0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 11440 QUERY
+ENTRY_BEGIN
+RAW
+b6da64ce501141aa333e0000000000000000
+ENTRY_END
+
+STEP 11450 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000572500000204057a01010402
+ENTRY_END
+
+STEP 11460 QUERY
+ENTRY_BEGIN
+RAW
+b6da64cf501041aa333d0000000000000000
+ENTRY_END
+
+STEP 11470 QUERY
+ENTRY_BEGIN
+RAW
+b6db160b501041b8b5000000000000000000
+ENTRY_END
+
+STEP 11480 QUERY
+ENTRY_BEGIN
+RAW
+b6db160b501841b8ff3b00000094f500000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe2d403c4fad0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 11490 QUERY
+ENTRY_BEGIN
+RAW
+b6db1619501141aab4690000000000000000
+ENTRY_END
+
+STEP 11500 QUERY
+ENTRY_BEGIN
+RAW
+b6db161a501041aab4680000000000000000
+ENTRY_END
+
+STEP 11510 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009bd60000020405b401010402
+ENTRY_END
+
+STEP 11520 QUERY
+ENTRY_BEGIN
+RAW
+b6dcb7745010447055c90000000000000000
+ENTRY_END
+
+STEP 11530 QUERY
+ENTRY_BEGIN
+RAW
+b6dcb77450184470b7940000008af31e000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11540 QUERY
+ENTRY_BEGIN
+RAW
+b6dcb78250114462553c0000000000000000
+ENTRY_END
+
+STEP 11550 QUERY
+ENTRY_BEGIN
+RAW
+b6dcb78350104462553b0000000000000000
+ENTRY_END
+
+STEP 11560 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000de930000020405b401010402
+ENTRY_END
+
+STEP 11570 QUERY
+ENTRY_BEGIN
+RAW
+b6dd42c2501044700d380000000000000000
+ENTRY_END
+
+STEP 11580 QUERY
+ENTRY_BEGIN
+RAW
+b6dd42c2501844709dac0000008ac576000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11590 QUERY
+ENTRY_BEGIN
+RAW
+b6dd42d0501144620cab0000000000000000
+ENTRY_END
+
+STEP 11600 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002fe800000204056401010402
+ENTRY_END
+
+STEP 11610 QUERY
+ENTRY_BEGIN
+RAW
+b6dd42d1501044620caa0000000000000000
+ENTRY_END
+
+STEP 11620 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d64a0000020405b401010402
+ENTRY_END
+
+STEP 11630 QUERY
+ENTRY_BEGIN
+RAW
+b6de7c0150104470cbae0000000000000000
+ENTRY_END
+
+STEP 11640 QUERY
+ENTRY_BEGIN
+RAW
+b6dde32a501040b0c1930000000000000000
+ENTRY_END
+
+STEP 11650 QUERY
+ENTRY_BEGIN
+RAW
+b6de7c015018447089cb0000008a97ce000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11660 QUERY
+ENTRY_BEGIN
+RAW
+b6dde32a501840b028ec000000953809000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0270403c53f00003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 11670 QUERY
+ENTRY_BEGIN
+RAW
+b6de7c0f50114462cb210000000000000000
+ENTRY_END
+
+STEP 11680 QUERY
+ENTRY_BEGIN
+RAW
+b6dde338501140a2c0fb0000000000000000
+ENTRY_END
+
+STEP 11690 QUERY
+ENTRY_BEGIN
+RAW
+b6de7c1050104462cb200000000000000000
+ENTRY_END
+
+STEP 11700 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000beb100000204056401010402
+ENTRY_END
+
+STEP 11710 QUERY
+ENTRY_BEGIN
+RAW
+b6dde339501040a2c0fa0000000000000000
+ENTRY_END
+
+STEP 11720 QUERY
+ENTRY_BEGIN
+RAW
+b6df39ac501040b0f9d90000000000000000
+ENTRY_END
+
+STEP 11730 QUERY
+ENTRY_BEGIN
+RAW
+b6df39ac501840b0a77000000095f2cb000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0270403c53f00003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 11740 QUERY
+ENTRY_BEGIN
+RAW
+b6df39ba501140a2f9410000000000000000
+ENTRY_END
+
+STEP 11750 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008b4100000204056401010402
+ENTRY_END
+
+STEP 11760 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e8b40000020405b401010402
+ENTRY_END
+
+STEP 11770 QUERY
+ENTRY_BEGIN
+RAW
+b6df39bb501040a2f9400000000000000000
+ENTRY_END
+
+STEP 11780 QUERY
+ENTRY_BEGIN
+RAW
+b6e211a950104470486d0000000000000000
+ENTRY_END
+
+STEP 11790 QUERY
+ENTRY_BEGIN
+RAW
+b6e12eb0501040b0d1630000000000000000
+ENTRY_END
+
+STEP 11800 QUERY
+ENTRY_BEGIN
+RAW
+b6e12eb0501840b0219a00000095502c000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0270403c53f00003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 11810 QUERY
+ENTRY_BEGIN
+RAW
+b6e211a95018447060d90000008a3c7e000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11820 QUERY
+ENTRY_BEGIN
+RAW
+b6e211b75011446247e00000000000000000
+ENTRY_END
+
+STEP 11830 QUERY
+ENTRY_BEGIN
+RAW
+b6e12ebe501140a2d0cb0000000000000000
+ENTRY_END
+
+STEP 11840 QUERY
+ENTRY_BEGIN
+RAW
+b6e211b85010446247df0000000000000000
+ENTRY_END
+
+STEP 11850 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f6aa0000020405b401010402
+ENTRY_END
+
+STEP 11860 QUERY
+ENTRY_BEGIN
+RAW
+b6e2fd18501044706af30000000000000000
+ENTRY_END
+
+STEP 11870 QUERY
+ENTRY_BEGIN
+RAW
+b6e12ebf501040a2d0ca0000000000000000
+ENTRY_END
+
+STEP 11880 QUERY
+ENTRY_BEGIN
+RAW
+b6e2fd1850184470bff90000008a00e5000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11890 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf077cb00000204057a01010402
+ENTRY_END
+
+STEP 11900 QUERY
+ENTRY_BEGIN
+RAW
+b6e2fd26501144626a660000000000000000
+ENTRY_END
+
+STEP 11910 QUERY
+ENTRY_BEGIN
+RAW
+b6e3b1255010fbec3b400000000000000000
+ENTRY_END
+
+STEP 11920 QUERY
+ENTRY_BEGIN
+RAW
+b6e3b1255018fbec7f23000000910700000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afedd403c505d0003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 11930 QUERY
+ENTRY_BEGIN
+RAW
+b6e2fd27501044626a650000000000000000
+ENTRY_END
+
+STEP 11940 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240003b130000020405b401010402
+ENTRY_END
+
+STEP 11950 QUERY
+ENTRY_BEGIN
+RAW
+b6e476715010447036010000000000000000
+ENTRY_END
+
+STEP 11960 QUERY
+ENTRY_BEGIN
+RAW
+b6e3b1335011fbde3aac0000000000000000
+ENTRY_END
+
+STEP 11970 QUERY
+ENTRY_BEGIN
+RAW
+b6e4767150184470b8ae0000008ad33d000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004e03677373096d6963726f736f667403636f6d00403afd52403c4ed200030000002b4e544c4d535350000100000097b208e00400040027000000070007002000000050535257465331505352570000
+ENTRY_END
+
+STEP 11980 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf053c700000204057a01010402
+ENTRY_END
+
+STEP 11990 QUERY
+ENTRY_BEGIN
+RAW
+b6e3b1345010fbde3aab0000000000000000
+ENTRY_END
+
+STEP 12000 QUERY
+ENTRY_BEGIN
+RAW
+b6e4767f5011446235740000000000000000
+ENTRY_END
+
+STEP 12010 QUERY
+ENTRY_BEGIN
+RAW
+b6e4f3175010fbecd5480000000000000000
+ENTRY_END
+
+STEP 12020 QUERY
+ENTRY_BEGIN
+RAW
+b6e476805010446235730000000000000000
+ENTRY_END
+
+STEP 12030 QUERY
+ENTRY_BEGIN
+RAW
+b6e4f3175018fbec01ad000000911f80000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afedd403c505d0003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 12040 QUERY
+ENTRY_BEGIN
+RAW
+b6e4f3255011fbded4b40000000000000000
+ENTRY_END
+
+STEP 12050 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06dd600000204057a01010402
+ENTRY_END
+
+STEP 12060 QUERY
+ENTRY_BEGIN
+RAW
+b6e4f3265010fbded4b30000000000000000
+ENTRY_END
+
+STEP 12070 QUERY
+ENTRY_BEGIN
+RAW
+b6e56de55010fbec74890000000000000000
+ENTRY_END
+
+STEP 12080 QUERY
+ENTRY_BEGIN
+RAW
+b6e56de55018fbececec00000091d380000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afedd403c505d0003000000324e544c4d535350000100000097b208e00900090029000000090009002000000045422d5345525645524555524f42595445320000
+ENTRY_END
+
+STEP 12090 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238f39c0000020405b40000
+ENTRY_END
+
+STEP 12100 QUERY
+ENTRY_BEGIN
+RAW
+b6e63c915010223817d20000000000000000
+ENTRY_END
+
+STEP 12110 QUERY
+ENTRY_BEGIN
+RAW
+b6e63c9150182238da820000001c90e30000000100000000000007636f6d616e6574026e6c0000060001
+ENTRY_END
+
+STEP 12120 QUERY
+ENTRY_BEGIN
+RAW
+b6e63cf15010223817540000000000000000
+ENTRY_END
+
+STEP 12130 QUERY
+ENTRY_BEGIN
+RAW
+b6e63cf15011223817530000000000000000
+ENTRY_END
+
+STEP 12140 QUERY
+ENTRY_BEGIN
+RAW
+b6e63cf25010223817520000000000000000
+ENTRY_END
+
+STEP 12150 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf03c730000020405b401010402
+ENTRY_END
+
+STEP 12160 QUERY
+ENTRY_BEGIN
+RAW
+b6e7f9de5010faf0b8600000000000000000
+ENTRY_END
+
+STEP 12170 QUERY
+ENTRY_BEGIN
+RAW
+b6e7f9de5018faf0c19a0000008b27c9000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd58403c4ed800030000002c4e544c4d535350000100000097b208e00900090023000000030003002000000042494b42494b4d554c4445520000
+ENTRY_END
+
+STEP 12180 QUERY
+ENTRY_BEGIN
+RAW
+b6e7f9ec5011fae2b7d20000000000000000
+ENTRY_END
+
+STEP 12190 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf034940000020405b401010402
+ENTRY_END
+
+STEP 12200 QUERY
+ENTRY_BEGIN
+RAW
+b6e7f9ed5010fae2b7d10000000000000000
+ENTRY_END
+
+STEP 12210 QUERY
+ENTRY_BEGIN
+RAW
+b6e8bf205010faf0eb3e0000000000000000
+ENTRY_END
+
+STEP 12220 QUERY
+ENTRY_BEGIN
+RAW
+b6e8bf205018faf0b5f60000008b674c000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd58403c4ed800030000002c4e544c4d535350000100000097b208e00900090023000000030003002000000042494b42494b4d554c4445520000
+ENTRY_END
+
+STEP 12230 QUERY
+ENTRY_BEGIN
+RAW
+b6e8bf2e5011fae2eab00000000000000000
+ENTRY_END
+
+STEP 12240 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0aa3b0000020405b401010402
+ENTRY_END
+
+STEP 12250 QUERY
+ENTRY_BEGIN
+RAW
+b6e8bf2f5010fae2eaaf0000000000000000
+ENTRY_END
+
+STEP 12260 QUERY
+ENTRY_BEGIN
+RAW
+b6e9a47b5010faf07b8a0000000000000000
+ENTRY_END
+
+STEP 12270 QUERY
+ENTRY_BEGIN
+RAW
+b6e9a47b5018faf0b67b0000008bf712000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd58403c4ed800030000002c4e544c4d535350000100000097b208e00900090023000000030003002000000042494b42494b4d554c4445520000
+ENTRY_END
+
+STEP 12280 QUERY
+ENTRY_BEGIN
+RAW
+b6e9a4895011fae27afc0000000000000000
+ENTRY_END
+
+STEP 12290 QUERY
+ENTRY_BEGIN
+RAW
+b6e9a48a5010fae27afb0000000000000000
+ENTRY_END
+
+STEP 12300 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc0080570000020405b401010402
+ENTRY_END
+
+STEP 12310 QUERY
+ENTRY_BEGIN
+RAW
+b6ebe7a65010fc000e790000000000000000
+ENTRY_END
+
+STEP 12320 QUERY
+ENTRY_BEGIN
+RAW
+b6ebe7a65004fc000e850000000000000000
+ENTRY_END
+
+STEP 12330 QUERY
+ENTRY_BEGIN
+RAW
+b6e56df35011fbde73f50000000000000000
+ENTRY_END
+
+STEP 12340 QUERY
+ENTRY_BEGIN
+RAW
+b6e56df45010fbde73f40000000000000000
+ENTRY_END
+
+STEP 12350 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001ad30000020405b401010402
+ENTRY_END
+
+STEP 12360 QUERY
+ENTRY_BEGIN
+RAW
+b6eddfed50104470ac3b0000000000000000
+ENTRY_END
+
+STEP 12370 QUERY
+ENTRY_BEGIN
+RAW
+b6eddfed50104470ac3b0000000000000000
+ENTRY_END
+
+STEP 12380 QUERY
+ENTRY_BEGIN
+RAW
+b6eddfed5018447026ab00000090b572000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff80403c51000003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 12390 QUERY
+ENTRY_BEGIN
+RAW
+b6eddffb50114462aba80000000000000000
+ENTRY_END
+
+STEP 12400 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d8ab0000020405b401010402
+ENTRY_END
+
+STEP 12410 QUERY
+ENTRY_BEGIN
+RAW
+b6eddffc50104462aba70000000000000000
+ENTRY_END
+
+STEP 12420 QUERY
+ENTRY_BEGIN
+RAW
+b6eddffc50104462aba70000000000000000
+ENTRY_END
+
+STEP 12430 QUERY
+ENTRY_BEGIN
+RAW
+b6eed8705010447071900000000000000000
+ENTRY_END
+
+STEP 12440 QUERY
+ENTRY_BEGIN
+RAW
+b6eed8705010447071900000000000000000
+ENTRY_END
+
+STEP 12450 QUERY
+ENTRY_BEGIN
+RAW
+b6eed87050184470e4c000000090bdb2000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff80403c51000003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 12460 QUERY
+ENTRY_BEGIN
+RAW
+b6eed87e5011446270fd0000000000000000
+ENTRY_END
+
+STEP 12470 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000edab0000020405b401010402
+ENTRY_END
+
+STEP 12480 QUERY
+ENTRY_BEGIN
+RAW
+b6eed87f5010446270fc0000000000000000
+ENTRY_END
+
+STEP 12490 QUERY
+ENTRY_BEGIN
+RAW
+b6eed87f5010446270fc0000000000000000
+ENTRY_END
+
+STEP 12500 QUERY
+ENTRY_BEGIN
+RAW
+b6f167c150104470f73c0000000000000000
+ENTRY_END
+
+STEP 12510 QUERY
+ENTRY_BEGIN
+RAW
+b6f167c150104470f73c0000000000000000
+ENTRY_END
+
+STEP 12520 QUERY
+ENTRY_BEGIN
+RAW
+b6f167c150184470686f00000090bdb0000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403aff81403c51010003000000314e544c4d535350000100000097b200e0080008002900000009000900200000004e542d53455256455248554c53424f55570000
+ENTRY_END
+
+STEP 12530 QUERY
+ENTRY_BEGIN
+RAW
+b6f167cf50114462f6a90000000000000000
+ENTRY_END
+
+STEP 12540 QUERY
+ENTRY_BEGIN
+RAW
+b6f167d050104462f6a80000000000000000
+ENTRY_END
+
+STEP 12550 QUERY
+ENTRY_BEGIN
+RAW
+b6f167d050104462f6a80000000000000000
+ENTRY_END
+
+STEP 12560 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bf770000020405b401010402
+ENTRY_END
+
+STEP 12570 QUERY
+ENTRY_BEGIN
+RAW
+b6f24c8350104470e4450000000000000000
+ENTRY_END
+
+STEP 12580 QUERY
+ENTRY_BEGIN
+RAW
+b6f24c8350184470a15400000096b1a8000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0084403c52040003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 12590 QUERY
+ENTRY_BEGIN
+RAW
+b6f24c9150114462e3ac0000000000000000
+ENTRY_END
+
+STEP 12600 QUERY
+ENTRY_BEGIN
+RAW
+b6f24c9250104462e3ab0000000000000000
+ENTRY_END
+
+STEP 12610 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f0f20000020405b401010402
+ENTRY_END
+
+STEP 12620 QUERY
+ENTRY_BEGIN
+RAW
+b6f339b750104470288c0000000000000000
+ENTRY_END
+
+STEP 12630 QUERY
+ENTRY_BEGIN
+RAW
+b6f339b750184470906c0000009607d8000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0084403c52040003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 12640 QUERY
+ENTRY_BEGIN
+RAW
+b6f339c55011446227f30000000000000000
+ENTRY_END
+
+STEP 12650 QUERY
+ENTRY_BEGIN
+RAW
+b6f339c65010446227f20000000000000000
+ENTRY_END
+
+STEP 12660 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004f5f0000020405b401010402
+ENTRY_END
+
+STEP 12670 QUERY
+ENTRY_BEGIN
+RAW
+b6f41c4a50104470a4640000000000000000
+ENTRY_END
+
+STEP 12680 QUERY
+ENTRY_BEGIN
+RAW
+b6f41c4a50184470d9f4000000963a28000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0084403c52040003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 12690 QUERY
+ENTRY_BEGIN
+RAW
+b6f41c5850114462a3cb0000000000000000
+ENTRY_END
+
+STEP 12700 QUERY
+ENTRY_BEGIN
+RAW
+b6f41c5950104462a3ca0000000000000000
+ENTRY_END
+
+STEP 12710 QUERY
+ENTRY_BEGIN
+RAW
+00000000700222389b1f00000204057801010402
+ENTRY_END
+
+STEP 12720 QUERY
+ENTRY_BEGIN
+RAW
+b6f6588a50102648b4060000000000000000
+ENTRY_END
+
+STEP 12730 QUERY
+ENTRY_BEGIN
+RAW
+b6f6588a50182648a8900000008d3800000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afca8403c4e2800030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 12740 QUERY
+ENTRY_BEGIN
+RAW
+b6f658985011263ab3760000000000000000
+ENTRY_END
+
+STEP 12750 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238a91f00000204057801010402
+ENTRY_END
+
+STEP 12760 QUERY
+ENTRY_BEGIN
+RAW
+b6f658995010263ab3750000000000000000
+ENTRY_END
+
+STEP 12770 QUERY
+ENTRY_BEGIN
+RAW
+b6f74bfb50102648ce940000000000000000
+ENTRY_END
+
+STEP 12780 QUERY
+ENTRY_BEGIN
+RAW
+b6f74bfb50182648241f0000008dd800000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afca8403c4e2800030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 12790 QUERY
+ENTRY_BEGIN
+RAW
+b6f74c095011263ace040000000000000000
+ENTRY_END
+
+STEP 12800 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238c24f00000204057801010402
+ENTRY_END
+
+STEP 12810 QUERY
+ENTRY_BEGIN
+RAW
+b6f74c0a5010263ace030000000000000000
+ENTRY_END
+
+STEP 12820 QUERY
+ENTRY_BEGIN
+RAW
+b6f99ca65010264897170000000000000000
+ENTRY_END
+
+STEP 12830 QUERY
+ENTRY_BEGIN
+RAW
+b6f99ca6501826484ca20000008d7800000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afca8403c4e2800030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 12840 QUERY
+ENTRY_BEGIN
+RAW
+b6f99cb45011263a96870000000000000000
+ENTRY_END
+
+STEP 12850 QUERY
+ENTRY_BEGIN
+RAW
+b6f99cb55010263a96860000000000000000
+ENTRY_END
+
+STEP 12860 QUERY
+ENTRY_BEGIN
+RAW
+000000005014000081b30000636b6f000000
+ENTRY_END
+
+STEP 12870 QUERY
+ENTRY_BEGIN
+RAW
+0000000050140000f51e0000636b6f000000
+ENTRY_END
+
+STEP 12880 QUERY
+ENTRY_BEGIN
+RAW
+0000000050140000c43b0000636b6f000000
+ENTRY_END
+
+STEP 12890 QUERY
+ENTRY_BEGIN
+RAW
+00000000600222386cca0000020405b40000
+ENTRY_END
+
+STEP 12900 QUERY
+ENTRY_BEGIN
+RAW
+b6fbb85a5010223815210000000000000000
+ENTRY_END
+
+STEP 12910 QUERY
+ENTRY_BEGIN
+RAW
+b6fbb85a50182238a12f0000001e88140000000100000000000009766f6f67642d6b6f6b026e6c0000060001
+ENTRY_END
+
+STEP 12920 QUERY
+ENTRY_BEGIN
+RAW
+b6fbb8bc50102238149f0000000000000000
+ENTRY_END
+
+STEP 12930 QUERY
+ENTRY_BEGIN
+RAW
+b6fbb8bc50112238149e0000000000000000
+ENTRY_END
+
+STEP 12940 QUERY
+ENTRY_BEGIN
+RAW
+b6fbb8bd50102238149d0000000000000000
+ENTRY_END
+
+STEP 12950 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238dfe20000020405b40000
+ENTRY_END
+
+STEP 12960 QUERY
+ENTRY_BEGIN
+RAW
+b6fc71d950102238ceb90000000000000000
+ENTRY_END
+
+STEP 12970 QUERY
+ENTRY_BEGIN
+RAW
+b6fc71d950182238f94a0000002502290000000100000000000010766974616c6974656974736b756e6465026e6c0000060001
+ENTRY_END
+
+STEP 12980 QUERY
+ENTRY_BEGIN
+RAW
+b6fc724d50102238ce1e0000000000000000
+ENTRY_END
+
+STEP 12990 QUERY
+ENTRY_BEGIN
+RAW
+b6fc724d50112238ce1d0000000000000000
+ENTRY_END
+
+STEP 13000 QUERY
+ENTRY_BEGIN
+RAW
+b6fc724e50102238ce1c0000000000000000
+ENTRY_END
+
+STEP 13010 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b9a300000204059801010402
+ENTRY_END
+
+STEP 13020 QUERY
+ENTRY_BEGIN
+RAW
+b6fe92d65010432099460000000000000000
+ENTRY_END
+
+STEP 13030 QUERY
+ENTRY_BEGIN
+RAW
+b6fe92d6501843209c2f000000851640000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8db403c4a5b0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 13040 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc0094110000020405b401010402
+ENTRY_END
+
+STEP 13050 QUERY
+ENTRY_BEGIN
+RAW
+b6fe92e45011431298be0000000000000000
+ENTRY_END
+
+STEP 13060 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400067be00000204059801010402
+ENTRY_END
+
+STEP 13070 QUERY
+ENTRY_BEGIN
+RAW
+000000006002223858200000020405b40000
+ENTRY_END
+
+STEP 13080 QUERY
+ENTRY_BEGIN
+RAW
+b6fe92e55010431298bd0000000000000000
+ENTRY_END
+
+STEP 13090 QUERY
+ENTRY_BEGIN
+RAW
+b70041ea50104320984b0000000000000000
+ENTRY_END
+
+STEP 13100 QUERY
+ENTRY_BEGIN
+RAW
+b701101d50102238a8ae0000000000000000
+ENTRY_END
+
+STEP 13110 QUERY
+ENTRY_BEGIN
+RAW
+b701101d50182238b793000000291b200000000100000000000014636f6d707574657272657061697263656e746572026e6c0000060001
+ENTRY_END
+
+STEP 13120 QUERY
+ENTRY_BEGIN
+RAW
+b70041ea50184320f17400000085c100000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8db403c4a5b0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 13130 QUERY
+ENTRY_BEGIN
+RAW
+b6ff4e015010fc00bbc40000000000000000
+ENTRY_END
+
+STEP 13140 QUERY
+ENTRY_BEGIN
+RAW
+b6ff4e015004fc00bbd00000000000000000
+ENTRY_END
+
+STEP 13150 QUERY
+ENTRY_BEGIN
+RAW
+b701108a50102238a8160000000000000000
+ENTRY_END
+
+STEP 13160 QUERY
+ENTRY_BEGIN
+RAW
+b701108a50112238a8150000000000000000
+ENTRY_END
+
+STEP 13170 QUERY
+ENTRY_BEGIN
+RAW
+b701108b50102238a8140000000000000000
+ENTRY_END
+
+STEP 13180 QUERY
+ENTRY_BEGIN
+RAW
+b70041f85011431297c30000000000000000
+ENTRY_END
+
+STEP 13190 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009fb600000204059801010402
+ENTRY_END
+
+STEP 13200 QUERY
+ENTRY_BEGIN
+RAW
+b70041f95010431297c20000000000000000
+ENTRY_END
+
+STEP 13210 QUERY
+ENTRY_BEGIN
+RAW
+b7018bc85010432086640000000000000000
+ENTRY_END
+
+STEP 13220 QUERY
+ENTRY_BEGIN
+RAW
+b7018bc8501843202e0e000000857280000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004903677373096d6963726f736f667403636f6d00403af8db403c4a5b0003000000264e544c4d535350000100000097b200e0030003002300000003000300200000004653345441300000
+ENTRY_END
+
+STEP 13230 QUERY
+ENTRY_BEGIN
+RAW
+b7018bd65011431285dc0000000000000000
+ENTRY_END
+
+STEP 13240 QUERY
+ENTRY_BEGIN
+RAW
+000000006002223866280000020405b40000
+ENTRY_END
+
+STEP 13250 QUERY
+ENTRY_BEGIN
+RAW
+b7018bd75010431285db0000000000000000
+ENTRY_END
+
+STEP 13260 QUERY
+ENTRY_BEGIN
+RAW
+b7020e2c50102238b8a60000000000000000
+ENTRY_END
+
+STEP 13270 QUERY
+ENTRY_BEGIN
+RAW
+b7020e2c50182238cf5c000000253225000000010000000000001065766f6c7574696f6e2d64657369676e026e6c0000060001
+ENTRY_END
+
+STEP 13280 QUERY
+ENTRY_BEGIN
+RAW
+b7020e9550102238b8160000000000000000
+ENTRY_END
+
+STEP 13290 QUERY
+ENTRY_BEGIN
+RAW
+b7020e9550112238b8150000000000000000
+ENTRY_END
+
+STEP 13300 QUERY
+ENTRY_BEGIN
+RAW
+b7020e9650102238b8140000000000000000
+ENTRY_END
+
+STEP 13310 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400090c60000020405b401010402
+ENTRY_END
+
+STEP 13320 QUERY
+ENTRY_BEGIN
+RAW
+b70494e8501044706d1d0000000000000000
+ENTRY_END
+
+STEP 13330 QUERY
+ENTRY_BEGIN
+RAW
+b70494e8501844709bfe0000008b7900000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0322403c54a200030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 13340 QUERY
+ENTRY_BEGIN
+RAW
+b70494f6501144626c8f0000000000000000
+ENTRY_END
+
+STEP 13350 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400004750000020405b401010402
+ENTRY_END
+
+STEP 13360 QUERY
+ENTRY_BEGIN
+RAW
+b70494f7501044626c8e0000000000000000
+ENTRY_END
+
+STEP 13370 QUERY
+ENTRY_BEGIN
+RAW
+b705694f501044700c640000000000000000
+ENTRY_END
+
+STEP 13380 QUERY
+ENTRY_BEGIN
+RAW
+b705694f5018447094460000008b2100000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0322403c54a200030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 13390 QUERY
+ENTRY_BEGIN
+RAW
+b705695d501144620bd60000000000000000
+ENTRY_END
+
+STEP 13400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400017e90000020405b401010402
+ENTRY_END
+
+STEP 13410 QUERY
+ENTRY_BEGIN
+RAW
+b705695e501044620bd50000000000000000
+ENTRY_END
+
+STEP 13420 QUERY
+ENTRY_BEGIN
+RAW
+b7061c44501044706ce20000000000000000
+ENTRY_END
+
+STEP 13430 QUERY
+ENTRY_BEGIN
+RAW
+b7061c4450184470b6c40000008b5f00000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0322403c54a200030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 13440 QUERY
+ENTRY_BEGIN
+RAW
+b7061c52501144626c540000000000000000
+ENTRY_END
+
+STEP 13450 QUERY
+ENTRY_BEGIN
+RAW
+b7061c53501044626c530000000000000000
+ENTRY_END
+
+STEP 13460 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0117200000204057a01010402
+ENTRY_END
+
+STEP 13470 QUERY
+ENTRY_BEGIN
+RAW
+b706a5135010fbece0d50000000000000000
+ENTRY_END
+
+STEP 13480 QUERY
+ENTRY_BEGIN
+RAW
+b706a5135018fbec03ff00000093d84c000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9eb403c4b6b0003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 13490 QUERY
+ENTRY_BEGIN
+RAW
+b706a5215011fbdee03f0000000000000000
+ENTRY_END
+
+STEP 13500 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0127e00000204057a01010402
+ENTRY_END
+
+STEP 13510 QUERY
+ENTRY_BEGIN
+RAW
+b706a5225010fbdee03e0000000000000000
+ENTRY_END
+
+STEP 13520 QUERY
+ENTRY_BEGIN
+RAW
+b70783b25010fbec03420000000000000000
+ENTRY_END
+
+STEP 13530 QUERY
+ENTRY_BEGIN
+RAW
+b70783b25018fbec7344000000938c74000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9eb403c4b6b0003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 13540 QUERY
+ENTRY_BEGIN
+RAW
+b70783c05011fbde02ac0000000000000000
+ENTRY_END
+
+STEP 13550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0facb00000204057a01010402
+ENTRY_END
+
+STEP 13560 QUERY
+ENTRY_BEGIN
+RAW
+b70783c15010fbde02ab0000000000000000
+ENTRY_END
+
+STEP 13570 QUERY
+ENTRY_BEGIN
+RAW
+b70825495010fbec49f80000000000000000
+ENTRY_END
+
+STEP 13580 QUERY
+ENTRY_BEGIN
+RAW
+b70825495018fbec05d300000093409c000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403af9eb403c4b6b0003000000344e544c4d535350000100000097b208e00a000a002a0000000a000a0020000000504f4d504f454d2d4d4d504f4d504f454e2d4d4d0000
+ENTRY_END
+
+STEP 13590 QUERY
+ENTRY_BEGIN
+RAW
+b70825575011fbde49620000000000000000
+ENTRY_END
+
+STEP 13600 QUERY
+ENTRY_BEGIN
+RAW
+22fc000000010000000000000b6361726565726665766572026e6c00000f000100
+ENTRY_END
+
+STEP 13610 QUERY
+ENTRY_BEGIN
+RAW
+b70825585010fbde49610000000000000000
+ENTRY_END
+
+STEP 13620 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e78d0000020405b401010402
+ENTRY_END
+
+STEP 13630 QUERY
+ENTRY_BEGIN
+RAW
+b70d802c5010faf0dd070000000000000000
+ENTRY_END
+
+STEP 13640 QUERY
+ENTRY_BEGIN
+RAW
+b70d802c5018faf0dbdc000000962509000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd92403c4f120003000000374e544c4d535350000100000097b208e00e000e0029000000090009002000000053422d5345525645525a4f4e4e4556454c442d474f45530000
+ENTRY_END
+
+STEP 13650 QUERY
+ENTRY_BEGIN
+RAW
+b70d803a5011fae2dc6e0000000000000000
+ENTRY_END
+
+STEP 13660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf053ff0000020405b401010402
+ENTRY_END
+
+STEP 13670 QUERY
+ENTRY_BEGIN
+RAW
+b70d803b5010fae2dc6d0000000000000000
+ENTRY_END
+
+STEP 13680 QUERY
+ENTRY_BEGIN
+RAW
+b70e3fda5010faf089ca0000000000000000
+ENTRY_END
+
+STEP 13690 QUERY
+ENTRY_BEGIN
+RAW
+b70e3fda5018faf0e04d00000096ce5b000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd92403c4f120003000000374e544c4d535350000100000097b208e00e000e0029000000090009002000000053422d5345525645525a4f4e4e4556454c442d474f45530000
+ENTRY_END
+
+STEP 13700 QUERY
+ENTRY_BEGIN
+RAW
+b70e3fe85011fae289310000000000000000
+ENTRY_END
+
+STEP 13710 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf067a30000020405b401010402
+ENTRY_END
+
+STEP 13720 QUERY
+ENTRY_BEGIN
+RAW
+b70e3fe95010fae289300000000000000000
+ENTRY_END
+
+STEP 13730 QUERY
+ENTRY_BEGIN
+RAW
+b70f07c45010faf0d5830000000000000000
+ENTRY_END
+
+STEP 13740 QUERY
+ENTRY_BEGIN
+RAW
+b70f07c45018faf0907e0000009669e4000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd92403c4f120003000000374e544c4d535350000100000097b208e00e000e0029000000090009002000000053422d5345525645525a4f4e4e4556454c442d474f45530000
+ENTRY_END
+
+STEP 13750 QUERY
+ENTRY_BEGIN
+RAW
+b70f07d25011fae2d4ea0000000000000000
+ENTRY_END
+
+STEP 13760 QUERY
+ENTRY_BEGIN
+RAW
+b70f07d35010fae2d4e90000000000000000
+ENTRY_END
+
+STEP 13770 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d69200000204055001010402
+ENTRY_END
+
+STEP 13780 QUERY
+ENTRY_BEGIN
+RAW
+b711831550104510c3ab0000000000000000
+ENTRY_END
+
+STEP 13790 QUERY
+ENTRY_BEGIN
+RAW
+b711831550184510e4a100000096a500000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd50403c4ed00003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 13800 QUERY
+ENTRY_BEGIN
+RAW
+b711832350114502c3120000000000000000
+ENTRY_END
+
+STEP 13810 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000542500000204055001010402
+ENTRY_END
+
+STEP 13820 QUERY
+ENTRY_BEGIN
+RAW
+b711832450104502c3110000000000000000
+ENTRY_END
+
+STEP 13830 QUERY
+ENTRY_BEGIN
+RAW
+b7125b4b5010451069070000000000000000
+ENTRY_END
+
+STEP 13840 QUERY
+ENTRY_BEGIN
+RAW
+b7125b4b5018451033fe00000096fc00000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd50403c4ed00003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 13850 QUERY
+ENTRY_BEGIN
+RAW
+b7125b5950114502686e0000000000000000
+ENTRY_END
+
+STEP 13860 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000682c00000204055001010402
+ENTRY_END
+
+STEP 13870 QUERY
+ENTRY_BEGIN
+RAW
+b7125b5a50104502686d0000000000000000
+ENTRY_END
+
+STEP 13880 QUERY
+ENTRY_BEGIN
+RAW
+b71325bc50104510b29c0000000000000000
+ENTRY_END
+
+STEP 13890 QUERY
+ENTRY_BEGIN
+RAW
+b71325bc501845105d94000000961c00000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd50403c4ed00003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 13900 QUERY
+ENTRY_BEGIN
+RAW
+b71325ca50114502b2030000000000000000
+ENTRY_END
+
+STEP 13910 QUERY
+ENTRY_BEGIN
+RAW
+b71325cb50104502b2020000000000000000
+ENTRY_END
+
+STEP 13920 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000baa0000020405b401010402
+ENTRY_END
+
+STEP 13930 QUERY
+ENTRY_BEGIN
+RAW
+b71514c55010447068130000000000000000
+ENTRY_END
+
+STEP 13940 QUERY
+ENTRY_BEGIN
+RAW
+b71514c550184470206000000096ac6a000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0089403c52090003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 13950 QUERY
+ENTRY_BEGIN
+RAW
+b71514d350114462677a0000000000000000
+ENTRY_END
+
+STEP 13960 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400028780000020405b401010402
+ENTRY_END
+
+STEP 13970 QUERY
+ENTRY_BEGIN
+RAW
+b71514d45010446267790000000000000000
+ENTRY_END
+
+STEP 13980 QUERY
+ENTRY_BEGIN
+RAW
+b715995c50104470004a0000000000000000
+ENTRY_END
+
+STEP 13990 QUERY
+ENTRY_BEGIN
+RAW
+b715995c50184470d805000000968dfc000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0089403c52090003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 14000 QUERY
+ENTRY_BEGIN
+RAW
+b715996a50114462ffb00000000000000000
+ENTRY_END
+
+STEP 14010 QUERY
+ENTRY_BEGIN
+RAW
+b715996b50104462ffaf0000000000000000
+ENTRY_END
+
+STEP 14020 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000382b0000020405b401010402
+ENTRY_END
+
+STEP 14030 QUERY
+ENTRY_BEGIN
+RAW
+b71666215010447043370000000000000000
+ENTRY_END
+
+STEP 14040 QUERY
+ENTRY_BEGIN
+RAW
+b716662150184470b65200000096f29c000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403b0089403c52090003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c00200000005748495a5a444f4d504443305748495a5a444f4d5044430000
+ENTRY_END
+
+STEP 14050 QUERY
+ENTRY_BEGIN
+RAW
+b716662f50114462429e0000000000000000
+ENTRY_END
+
+STEP 14060 QUERY
+ENTRY_BEGIN
+RAW
+b716663050104462429d0000000000000000
+ENTRY_END
+
+STEP 14070 QUERY
+ENTRY_BEGIN
+RAW
+360d00000001000000000000076f62646e772d6e026e6c00000f000100
+ENTRY_END
+
+STEP 14080 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fc009d690000020405b401010402
+ENTRY_END
+
+STEP 14090 QUERY
+ENTRY_BEGIN
+RAW
+b716edb85010fc00254e0000000000000000
+ENTRY_END
+
+STEP 14100 QUERY
+ENTRY_BEGIN
+RAW
+b716edb85004fc00255a0000000000000000
+ENTRY_END
+
+STEP 14110 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b2e800000204059801010402
+ENTRY_END
+
+STEP 14120 QUERY
+ENTRY_BEGIN
+RAW
+b717c4505010432060f80000000000000000
+ENTRY_END
+
+STEP 14130 QUERY
+ENTRY_BEGIN
+RAW
+b717c450501843209c70000000905f78000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14140 QUERY
+ENTRY_BEGIN
+RAW
+b717c45e5011431260650000000000000000
+ENTRY_END
+
+STEP 14150 QUERY
+ENTRY_BEGIN
+RAW
+b717c45f5010431260640000000000000000
+ENTRY_END
+
+STEP 14160 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000514e00000204059801010402
+ENTRY_END
+
+STEP 14170 QUERY
+ENTRY_BEGIN
+RAW
+b71a45bc501043207def0000000000000000
+ENTRY_END
+
+STEP 14180 QUERY
+ENTRY_BEGIN
+RAW
+b71a45bc501843207c38000000909da8000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14190 QUERY
+ENTRY_BEGIN
+RAW
+b71a45ca501143127d5c0000000000000000
+ENTRY_END
+
+STEP 14200 QUERY
+ENTRY_BEGIN
+RAW
+b71a45cb501043127d5b0000000000000000
+ENTRY_END
+
+STEP 14210 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400019b400000204059801010402
+ENTRY_END
+
+STEP 14220 QUERY
+ENTRY_BEGIN
+RAW
+b71b20f9501043206b170000000000000000
+ENTRY_END
+
+STEP 14230 QUERY
+ENTRY_BEGIN
+RAW
+b71b20f9501843202b3000000090dbd8000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14240 QUERY
+ENTRY_BEGIN
+RAW
+b71b2107501143126a840000000000000000
+ENTRY_END
+
+STEP 14250 QUERY
+ENTRY_BEGIN
+RAW
+b71b2108501043126a830000000000000000
+ENTRY_END
+
+STEP 14260 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c1f20000020405b401010402
+ENTRY_END
+
+STEP 14270 QUERY
+ENTRY_BEGIN
+RAW
+b71bae6b5010447084af0000000000000000
+ENTRY_END
+
+STEP 14280 QUERY
+ENTRY_BEGIN
+RAW
+b71bae6b50184470db5a0000008f3280000000010001000000000f313230323539303834323839382d330000f900010f313230323539303834323839382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdc9403c4f490003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 14290 QUERY
+ENTRY_BEGIN
+RAW
+b71bae7950114462841d0000000000000000
+ENTRY_END
+
+STEP 14300 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400076f80000020405b401010402
+ENTRY_END
+
+STEP 14310 QUERY
+ENTRY_BEGIN
+RAW
+b71bae7a50104462841c0000000000000000
+ENTRY_END
+
+STEP 14320 QUERY
+ENTRY_BEGIN
+RAW
+b71c76fc5010447071230000000000000000
+ENTRY_END
+
+STEP 14330 QUERY
+ENTRY_BEGIN
+RAW
+b71c76fc5018447011cf0000008fe780000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdca403c4f4a0003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 14340 QUERY
+ENTRY_BEGIN
+RAW
+b71c770a5011446270910000000000000000
+ENTRY_END
+
+STEP 14350 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400026c80000020405b401010402
+ENTRY_END
+
+STEP 14360 QUERY
+ENTRY_BEGIN
+RAW
+b71c770b5010446270900000000000000000
+ENTRY_END
+
+STEP 14370 QUERY
+ENTRY_BEGIN
+RAW
+3b00000000010000000000000b6361726565726665766572026e6c00000f000100
+ENTRY_END
+
+STEP 14380 QUERY
+ENTRY_BEGIN
+RAW
+b71e36195010447061d40000000000000000
+ENTRY_END
+
+STEP 14390 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab3200000204059801010402
+ENTRY_END
+
+STEP 14400 QUERY
+ENTRY_BEGIN
+RAW
+0524000000010000000000000c7065616e75747367616d6573026e6c00000f000100
+ENTRY_END
+
+STEP 14410 QUERY
+ENTRY_BEGIN
+RAW
+b71ee7585010432036330000000000000000
+ENTRY_END
+
+STEP 14420 QUERY
+ENTRY_BEGIN
+RAW
+b71ee758501843200b2b00000090c5f8000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14430 QUERY
+ENTRY_BEGIN
+RAW
+b71e361950184470a9800000008f4080000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdca403c4f4a0003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 14440 QUERY
+ENTRY_BEGIN
+RAW
+b71ee7665011431235a00000000000000000
+ENTRY_END
+
+STEP 14450 QUERY
+ENTRY_BEGIN
+RAW
+b71e36275011446261420000000000000000
+ENTRY_END
+
+STEP 14460 QUERY
+ENTRY_BEGIN
+RAW
+b71ee76750104312359f0000000000000000
+ENTRY_END
+
+STEP 14470 QUERY
+ENTRY_BEGIN
+RAW
+b71e36285010446261410000000000000000
+ENTRY_END
+
+STEP 14480 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400054a900000204059801010402
+ENTRY_END
+
+STEP 14490 QUERY
+ENTRY_BEGIN
+RAW
+b71f842f5010432042d20000000000000000
+ENTRY_END
+
+STEP 14500 QUERY
+ENTRY_BEGIN
+RAW
+b71f842f50184320da9b000000900428000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14510 QUERY
+ENTRY_BEGIN
+RAW
+b71f843d50114312423f0000000000000000
+ENTRY_END
+
+STEP 14520 QUERY
+ENTRY_BEGIN
+RAW
+b71f843e50104312423e0000000000000000
+ENTRY_END
+
+STEP 14530 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005bc700000204059801010402
+ENTRY_END
+
+STEP 14540 QUERY
+ENTRY_BEGIN
+RAW
+b71fffa150104320ce7d0000000000000000
+ENTRY_END
+
+STEP 14550 QUERY
+ENTRY_BEGIN
+RAW
+0000000060022238ed610000020405b40000
+ENTRY_END
+
+STEP 14560 QUERY
+ENTRY_BEGIN
+RAW
+b71fffa150184320b59e00000090b4d0000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403affca403c514a0003000000314e544c4d535350000100000097b208e00e000e002300000003000300200000004653314245524b454e424f5343484e45540000
+ENTRY_END
+
+STEP 14570 QUERY
+ENTRY_BEGIN
+RAW
+b720f253501022385b9a0000000000000000
+ENTRY_END
+
+STEP 14580 QUERY
+ENTRY_BEGIN
+RAW
+b720f25350182238373e000000253f7f000000010000000000001074726f66656f2d616c6661726f6d656f026e6c0000060001
+ENTRY_END
+
+STEP 14590 QUERY
+ENTRY_BEGIN
+RAW
+b71fffaf50114312cdea0000000000000000
+ENTRY_END
+
+STEP 14600 QUERY
+ENTRY_BEGIN
+RAW
+b720f2bc501022385b0a0000000000000000
+ENTRY_END
+
+STEP 14610 QUERY
+ENTRY_BEGIN
+RAW
+b720f2bc501122385b090000000000000000
+ENTRY_END
+
+STEP 14620 QUERY
+ENTRY_BEGIN
+RAW
+b71fffb050104312cde90000000000000000
+ENTRY_END
+
+STEP 14630 QUERY
+ENTRY_BEGIN
+RAW
+b720f2bd501022385b080000000000000000
+ENTRY_END
+
+STEP 14640 QUERY
+ENTRY_BEGIN
+RAW
+16b8000000010000000000000b6379636c696e6732303030026e6c00000f000100
+ENTRY_END
+
+STEP 14650 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400044d80000020405b401010402
+ENTRY_END
+
+STEP 14660 QUERY
+ENTRY_BEGIN
+RAW
+b72633b05010447082450000000000000000
+ENTRY_END
+
+STEP 14670 QUERY
+ENTRY_BEGIN
+RAW
+b72633b050184470f04800000089b41c000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7e0d403ccf8d00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 14680 QUERY
+ENTRY_BEGIN
+RAW
+b72633be5011446281b90000000000000000
+ENTRY_END
+
+STEP 14690 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033630000020405b401010402
+ENTRY_END
+
+STEP 14700 QUERY
+ENTRY_BEGIN
+RAW
+b72633bf5010446281b80000000000000000
+ENTRY_END
+
+STEP 14710 QUERY
+ENTRY_BEGIN
+RAW
+b726ed2d50104470b7520000000000000000
+ENTRY_END
+
+STEP 14720 QUERY
+ENTRY_BEGIN
+RAW
+b726ed2d5018447083f1000000895682000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7e0d403ccf8d00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 14730 QUERY
+ENTRY_BEGIN
+RAW
+b726ed3b50114462b6c60000000000000000
+ENTRY_END
+
+STEP 14740 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400037b50000020405b401010402
+ENTRY_END
+
+STEP 14750 QUERY
+ENTRY_BEGIN
+RAW
+b726ed3c50104462b6c50000000000000000
+ENTRY_END
+
+STEP 14760 QUERY
+ENTRY_BEGIN
+RAW
+b727b1b350104470f71d0000000000000000
+ENTRY_END
+
+STEP 14770 QUERY
+ENTRY_BEGIN
+RAW
+b727b1b350184470f7580000008922e6000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403b7e0d403ccf8d00030000002a4e544c4d535350000100000097b200c004000400260000000600060020000000534552564552574151460000
+ENTRY_END
+
+STEP 14780 QUERY
+ENTRY_BEGIN
+RAW
+b727b1c150114462f6910000000000000000
+ENTRY_END
+
+STEP 14790 QUERY
+ENTRY_BEGIN
+RAW
+b727b1c250104462f6900000000000000000
+ENTRY_END
+
+STEP 14800 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008d750000020405b401010402
+ENTRY_END
+
+STEP 14810 QUERY
+ENTRY_BEGIN
+RAW
+b729774550104470874a0000000000000000
+ENTRY_END
+
+STEP 14820 QUERY
+ENTRY_BEGIN
+RAW
+b729774550184470362b0000008bed00000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0328403c54a800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 14830 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf067e800000204056401010402
+ENTRY_END
+
+STEP 14840 QUERY
+ENTRY_BEGIN
+RAW
+b72977535011446286bc0000000000000000
+ENTRY_END
+
+STEP 14850 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a8b50000020405b401010402
+ENTRY_END
+
+STEP 14860 QUERY
+ENTRY_BEGIN
+RAW
+b72a677e5010fd5c73370000000000000000
+ENTRY_END
+
+STEP 14870 QUERY
+ENTRY_BEGIN
+RAW
+b72977545010446286bb0000000000000000
+ENTRY_END
+
+STEP 14880 QUERY
+ENTRY_BEGIN
+RAW
+b72b311750104470e8b60000000000000000
+ENTRY_END
+
+STEP 14890 QUERY
+ENTRY_BEGIN
+RAW
+b72b311750184470f0980000008b9500000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0328403c54a800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 14900 QUERY
+ENTRY_BEGIN
+RAW
+b72b312550114462e8280000000000000000
+ENTRY_END
+
+STEP 14910 QUERY
+ENTRY_BEGIN
+RAW
+b72a677e5018fd5c94760000008f430e000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403af354403c44d40003000000324e544c4d535350000100000097b208e00a000a0028000000080008002000000050434f4f535431364f4f535445494e4445520000
+ENTRY_END
+
+STEP 14920 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c1d20000020405b401010402
+ENTRY_END
+
+STEP 14930 QUERY
+ENTRY_BEGIN
+RAW
+b72b312650104462e8270000000000000000
+ENTRY_END
+
+STEP 14940 QUERY
+ENTRY_BEGIN
+RAW
+b72c139b501044701f4f0000000000000000
+ENTRY_END
+
+STEP 14950 QUERY
+ENTRY_BEGIN
+RAW
+b72c139b50184470e9300000008bd300000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403b0328403c54a800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552444f4d41494e0000
+ENTRY_END
+
+STEP 14960 QUERY
+ENTRY_BEGIN
+RAW
+b72a678c5011fd4e72a50000000000000000
+ENTRY_END
+
+STEP 14970 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006be700000204059801010402
+ENTRY_END
+
+STEP 14980 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0a28e00000204056401010402
+ENTRY_END
+
+STEP 14990 QUERY
+ENTRY_BEGIN
+RAW
+b72c13a9501144621ec10000000000000000
+ENTRY_END
+
+STEP 15000 QUERY
+ENTRY_BEGIN
+RAW
+b72a678d5010fd4e72a40000000000000000
+ENTRY_END
+
+STEP 15010 QUERY
+ENTRY_BEGIN
+RAW
+b72cd229501043200c090000000000000000
+ENTRY_END
+
+STEP 15020 QUERY
+ENTRY_BEGIN
+RAW
+b72c13aa501044621ec00000000000000000
+ENTRY_END
+
+STEP 15030 QUERY
+ENTRY_BEGIN
+RAW
+b72cd2295018432050a20000008bbf42000000010001000000000f313235343133303435303435302d330000f900010f313235343133303435303435302d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd01403c4e8100030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 15040 QUERY
+ENTRY_BEGIN
+RAW
+b72da6d95010fd5c6e7f0000000000000000
+ENTRY_END
+
+STEP 15050 QUERY
+ENTRY_BEGIN
+RAW
+b72cd237501143120b7b0000000000000000
+ENTRY_END
+
+STEP 15060 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000577700000204059801010402
+ENTRY_END
+
+STEP 15070 QUERY
+ENTRY_BEGIN
+RAW
+b72da6d95018fd5cf1950000008fe336000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403af354403c44d40003000000324e544c4d535350000100000097b208e00a000a0028000000080008002000000050434f4f535431364f4f535445494e4445520000
+ENTRY_END
+
+STEP 15080 QUERY
+ENTRY_BEGIN
+RAW
+b72cd238501043120b7a0000000000000000
+ENTRY_END
+
+STEP 15090 QUERY
+ENTRY_BEGIN
+RAW
+b72e32b150104320970f0000000000000000
+ENTRY_END
+
+STEP 15100 QUERY
+ENTRY_BEGIN
+RAW
+b72e32b150184320e3db0000008bb810000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd01403c4e8100030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 15110 QUERY
+ENTRY_BEGIN
+RAW
+b72da6e75011fd4e6ded0000000000000000
+ENTRY_END
+
+STEP 15120 QUERY
+ENTRY_BEGIN
+RAW
+b72e32bf5011431296810000000000000000
+ENTRY_END
+
+STEP 15130 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007aec00000204059801010402
+ENTRY_END
+
+STEP 15140 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf03bc200000204056401010402
+ENTRY_END
+
+STEP 15150 QUERY
+ENTRY_BEGIN
+RAW
+b72e32c05010431296800000000000000000
+ENTRY_END
+
+STEP 15160 QUERY
+ENTRY_BEGIN
+RAW
+b72ec244501043202af10000000000000000
+ENTRY_END
+
+STEP 15170 QUERY
+ENTRY_BEGIN
+RAW
+b72ec24450184320a80f0000008b87be000000010001000000000f313235343133303435303435302d320000f900010f313235343133303435303435302d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd01403c4e8100030000002c4e544c4d535350000100000097b208e006000600260000000600060020000000564247495341564247444f4d0000
+ENTRY_END
+
+STEP 15180 QUERY
+ENTRY_BEGIN
+RAW
+b72da6e85010fd4e6dec0000000000000000
+ENTRY_END
+
+STEP 15190 QUERY
+ENTRY_BEGIN
+RAW
+b72f4ee65010fd5c5fa40000000000000000
+ENTRY_END
+
+STEP 15200 QUERY
+ENTRY_BEGIN
+RAW
+b72ec252501143122a630000000000000000
+ENTRY_END
+
+STEP 15210 QUERY
+ENTRY_BEGIN
+RAW
+b72ec253501043122a620000000000000000
+ENTRY_END
+
+STEP 15220 QUERY
+ENTRY_BEGIN
+RAW
+b72f4ee65018fd5c51cb0000008f7426000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403af354403c44d40003000000324e544c4d535350000100000097b208e00a000a0028000000080008002000000050434f4f535431364f4f535445494e4445520000
+ENTRY_END
+
+STEP 15230 QUERY
+ENTRY_BEGIN
+RAW
+b72f4ef45011fd4e5f120000000000000000
+ENTRY_END
+
+STEP 15240 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000192e00000204057a01010402
+ENTRY_END
+
+STEP 15250 QUERY
+ENTRY_BEGIN
+RAW
+b72f4ef55010fd4e5f110000000000000000
+ENTRY_END
+
+STEP 15260 QUERY
+ENTRY_BEGIN
+RAW
+b7315009501041b83cb50000000000000000
+ENTRY_END
+
+STEP 15270 QUERY
+ENTRY_BEGIN
+RAW
+b7315009501841b8edef000000947700000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe38403c4fb80003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 15280 QUERY
+ENTRY_BEGIN
+RAW
+b7315017501141aa3c1e0000000000000000
+ENTRY_END
+
+STEP 15290 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f64500000204057a01010402
+ENTRY_END
+
+STEP 15300 QUERY
+ENTRY_BEGIN
+RAW
+b7315018501041aa3c1d0000000000000000
+ENTRY_END
+
+STEP 15310 QUERY
+ENTRY_BEGIN
+RAW
+b731dfc4501041b88a110000000000000000
+ENTRY_END
+
+STEP 15320 QUERY
+ENTRY_BEGIN
+RAW
+b731dfc4501841b8ce8c00000094e4c0000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe38403c4fb80003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 15330 QUERY
+ENTRY_BEGIN
+RAW
+b731dfd2501141aa897a0000000000000000
+ENTRY_END
+
+STEP 15340 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000d5b00000204057a01010402
+ENTRY_END
+
+STEP 15350 QUERY
+ENTRY_BEGIN
+RAW
+b731dfd3501041aa89790000000000000000
+ENTRY_END
+
+STEP 15360 QUERY
+ENTRY_BEGIN
+RAW
+b732a88d501041b8d85c0000000000000000
+ENTRY_END
+
+STEP 15370 QUERY
+ENTRY_BEGIN
+RAW
+b732a88d501841b854d800000094acc0000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afe38403c4fb80003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000535445524e2d534552564552534552564552424f4c0000
+ENTRY_END
+
+STEP 15380 QUERY
+ENTRY_BEGIN
+RAW
+b732a89b501141aad7c50000000000000000
+ENTRY_END
+
+STEP 15390 QUERY
+ENTRY_BEGIN
+RAW
+b732a89c501041aad7c40000000000000000
+ENTRY_END
+
+STEP 15400 QUERY
+ENTRY_BEGIN
+RAW
+316f000000010000000000000a6970336538336237333105737065656406706c616e6574026e6c00000f000100
+ENTRY_END
+
+STEP 15410 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400089e200000204055001010402
+ENTRY_END
+
+STEP 15420 QUERY
+ENTRY_BEGIN
+RAW
+b7367d1a501045107cd10000000000000000
+ENTRY_END
+
+STEP 15430 QUERY
+ENTRY_BEGIN
+RAW
+b7367d1a5018451088c700000096ae00000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd56403c4ed60003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 15440 QUERY
+ENTRY_BEGIN
+RAW
+b7367d28501145027c380000000000000000
+ENTRY_END
+
+STEP 15450 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c2d500000204055001010402
+ENTRY_END
+
+STEP 15460 QUERY
+ENTRY_BEGIN
+RAW
+b7367d29501045027c370000000000000000
+ENTRY_END
+
+STEP 15470 QUERY
+ENTRY_BEGIN
+RAW
+b738f642501045103c9a0000000000000000
+ENTRY_END
+
+STEP 15480 QUERY
+ENTRY_BEGIN
+RAW
+b738f64250184510f291000000960500000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd56403c4ed60003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 15490 QUERY
+ENTRY_BEGIN
+RAW
+b738f650501145023c010000000000000000
+ENTRY_END
+
+STEP 15500 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b71600000204055001010402
+ENTRY_END
+
+STEP 15510 QUERY
+ENTRY_BEGIN
+RAW
+b738f651501045023c000000000000000000
+ENTRY_END
+
+STEP 15520 QUERY
+ENTRY_BEGIN
+RAW
+b7398bf1501045109b2b0000000000000000
+ENTRY_END
+
+STEP 15530 QUERY
+ENTRY_BEGIN
+RAW
+b7398bf1501845103123000000962500000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd56403c4ed60003000000374e544c4d535350000100000097b200e00b000b002c0000000c000c002000000045584143542d534552564552515549434b4f46464943450000
+ENTRY_END
+
+STEP 15540 QUERY
+ENTRY_BEGIN
+RAW
+b7398bff501145029a920000000000000000
+ENTRY_END
+
+STEP 15550 QUERY
+ENTRY_BEGIN
+RAW
+b7398c00501045029a910000000000000000
+ENTRY_END
+
+STEP 15560 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c30100000204056401010402
+ENTRY_END
+
+STEP 15570 QUERY
+ENTRY_BEGIN
+RAW
+b73c34e1501040b002980000000000000000
+ENTRY_END
+
+STEP 15580 QUERY
+ENTRY_BEGIN
+RAW
+b73c34e1501840b0dbc60000008c2e7d000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afae7403c4c6700030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 15590 QUERY
+ENTRY_BEGIN
+RAW
+b73c34ef501140a202090000000000000000
+ENTRY_END
+
+STEP 15600 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e88100000204056401010402
+ENTRY_END
+
+STEP 15610 QUERY
+ENTRY_BEGIN
+RAW
+b73c34f0501040a202080000000000000000
+ENTRY_END
+
+STEP 15620 QUERY
+ENTRY_BEGIN
+RAW
+b73d0406501040b058f20000000000000000
+ENTRY_END
+
+STEP 15630 QUERY
+ENTRY_BEGIN
+RAW
+b73d0406501840b0ded30000008c82cb000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afae7403c4c6700030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 15640 QUERY
+ENTRY_BEGIN
+RAW
+b73d0414501140a258630000000000000000
+ENTRY_END
+
+STEP 15650 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab0400000204056401010402
+ENTRY_END
+
+STEP 15660 QUERY
+ENTRY_BEGIN
+RAW
+b73d0415501040a258620000000000000000
+ENTRY_END
+
+STEP 15670 QUERY
+ENTRY_BEGIN
+RAW
+b73dab04501040b074760000000000000000
+ENTRY_END
+
+STEP 15680 QUERY
+ENTRY_BEGIN
+RAW
+b73dab04501840b0a6090000008cd719000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afae7403c4c6700030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 15690 QUERY
+ENTRY_BEGIN
+RAW
+b73dab12501140a273e70000000000000000
+ENTRY_END
+
+STEP 15700 QUERY
+ENTRY_BEGIN
+RAW
+b73dab13501040a273e60000000000000000
+ENTRY_END
+
+STEP 15710 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000badf0000020405b401010402
+ENTRY_END
+
+STEP 15720 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008d210000020405b401010402
+ENTRY_END
+
+STEP 15730 QUERY
+ENTRY_BEGIN
+RAW
+b744e8ca5010447015560000000000000000
+ENTRY_END
+
+STEP 15740 QUERY
+ENTRY_BEGIN
+RAW
+b744e8ca50184470b35000000091ec00000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2a403c4eaa0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 15750 QUERY
+ENTRY_BEGIN
+RAW
+b744e8d85011446214c20000000000000000
+ENTRY_END
+
+STEP 15760 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d1eb0000020405b401010402
+ENTRY_END
+
+STEP 15770 QUERY
+ENTRY_BEGIN
+RAW
+b74563a75010faf0e3b20000000000000000
+ENTRY_END
+
+STEP 15780 QUERY
+ENTRY_BEGIN
+RAW
+b74563a75018faf096e00000008e0000000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcdf403c4e5f00030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 15790 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400008010000020405b401010402
+ENTRY_END
+
+STEP 15800 QUERY
+ENTRY_BEGIN
+RAW
+b74563b55011fae2e3210000000000000000
+ENTRY_END
+
+STEP 15810 QUERY
+ENTRY_BEGIN
+RAW
+b74563b65010fae2e3200000000000000000
+ENTRY_END
+
+STEP 15820 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf002cf0000020405b401010402
+ENTRY_END
+
+STEP 15830 QUERY
+ENTRY_BEGIN
+RAW
+b744e8d95010446214c10000000000000000
+ENTRY_END
+
+STEP 15840 QUERY
+ENTRY_BEGIN
+RAW
+b74725ec5010faf0524f0000000000000000
+ENTRY_END
+
+STEP 15850 QUERY
+ENTRY_BEGIN
+RAW
+b74725ec5018faf08e160000008e7867000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcdf403c4e5f00030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 15860 QUERY
+ENTRY_BEGIN
+RAW
+b746472d5010447031d10000000000000000
+ENTRY_END
+
+STEP 15870 QUERY
+ENTRY_BEGIN
+RAW
+b74725fa5011fae251be0000000000000000
+ENTRY_END
+
+STEP 15880 QUERY
+ENTRY_BEGIN
+RAW
+b746472d50184470ec4c00000091ce80000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2b403c4eab0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 15890 QUERY
+ENTRY_BEGIN
+RAW
+b74725fb5010fae251bd0000000000000000
+ENTRY_END
+
+STEP 15900 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e9570000020405b401010402
+ENTRY_END
+
+STEP 15910 QUERY
+ENTRY_BEGIN
+RAW
+b748136e5010faf04b550000000000000000
+ENTRY_END
+
+STEP 15920 QUERY
+ENTRY_BEGIN
+RAW
+b748136e5018faf0e48c0000008e1af7000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afcdf403c4e5f00030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005345525645524f534f5345525645520000
+ENTRY_END
+
+STEP 15930 QUERY
+ENTRY_BEGIN
+RAW
+b748137c5011fae24ac40000000000000000
+ENTRY_END
+
+STEP 15940 QUERY
+ENTRY_BEGIN
+RAW
+b746473b50114462313d0000000000000000
+ENTRY_END
+
+STEP 15950 QUERY
+ENTRY_BEGIN
+RAW
+b748137d5010fae24ac30000000000000000
+ENTRY_END
+
+STEP 15960 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f14c0000020405b401010402
+ENTRY_END
+
+STEP 15970 QUERY
+ENTRY_BEGIN
+RAW
+b746473c50104462313c0000000000000000
+ENTRY_END
+
+STEP 15980 QUERY
+ENTRY_BEGIN
+RAW
+b748a93150104470b9160000000000000000
+ENTRY_END
+
+STEP 15990 QUERY
+ENTRY_BEGIN
+RAW
+b748a93150184470dd12000000916500000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2b403c4eab0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 16000 QUERY
+ENTRY_BEGIN
+RAW
+b748a93f50114462b8820000000000000000
+ENTRY_END
+
+STEP 16010 QUERY
+ENTRY_BEGIN
+RAW
+b742be80501044706d600000000000000000
+ENTRY_END
+
+STEP 16020 QUERY
+ENTRY_BEGIN
+RAW
+b742be80501844708594000000962eb5000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe17403c4f970003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 16030 QUERY
+ENTRY_BEGIN
+RAW
+b748a94050104462b8810000000000000000
+ENTRY_END
+
+STEP 16040 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008d4000000204058c01010402
+ENTRY_END
+
+STEP 16050 QUERY
+ENTRY_BEGIN
+RAW
+b749679e5010429098540000000000000000
+ENTRY_END
+
+STEP 16060 QUERY
+ENTRY_BEGIN
+RAW
+b749679e50184290705700000091e4db000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005703677373096d6963726f736f667403636f6d00403afd9c403c4f1c0003000000344e544c4d535350000100000097b200c00d000d002700000007000700200000005641524b4a4553444953545249564552533033410000
+ENTRY_END
+
+STEP 16070 QUERY
+ENTRY_BEGIN
+RAW
+b74967ac5011428297c00000000000000000
+ENTRY_END
+
+STEP 16080 QUERY
+ENTRY_BEGIN
+RAW
+b74967ad5010428297bf0000000000000000
+ENTRY_END
+
+STEP 16090 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f46000000204058c01010402
+ENTRY_END
+
+STEP 16100 QUERY
+ENTRY_BEGIN
+RAW
+b74a49ae501042901d640000000000000000
+ENTRY_END
+
+STEP 16110 QUERY
+ENTRY_BEGIN
+RAW
+b74a49ae5018429054610000009187e1000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afd9c403c4f1c0003000000344e544c4d535350000100000097b200c00d000d002700000007000700200000005641524b4a4553444953545249564552533033410000
+ENTRY_END
+
+STEP 16120 QUERY
+ENTRY_BEGIN
+RAW
+b74a49bc501142821cd00000000000000000
+ENTRY_END
+
+STEP 16130 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fa2700000204058c01010402
+ENTRY_END
+
+STEP 16140 QUERY
+ENTRY_BEGIN
+RAW
+b74a49bd501042821ccf0000000000000000
+ENTRY_END
+
+STEP 16150 QUERY
+ENTRY_BEGIN
+RAW
+b74ac63f50104290a6990000000000000000
+ENTRY_END
+
+STEP 16160 QUERY
+ENTRY_BEGIN
+RAW
+b74ac63f50184290a35700000091c220000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005703677373096d6963726f736f667403636f6d00403afd9c403c4f1c0003000000344e544c4d535350000100000097b200c00d000d002700000007000700200000005641524b4a4553444953545249564552533033410000
+ENTRY_END
+
+STEP 16170 QUERY
+ENTRY_BEGIN
+RAW
+b74ac64d50114282a6050000000000000000
+ENTRY_END
+
+STEP 16180 QUERY
+ENTRY_BEGIN
+RAW
+b74ac64e50104282a6040000000000000000
+ENTRY_END
+
+STEP 16190 QUERY
+ENTRY_BEGIN
+RAW
+b742be8e501144626cc70000000000000000
+ENTRY_END
+
+STEP 16200 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400079c20000020405b401010402
+ENTRY_END
+
+STEP 16210 QUERY
+ENTRY_BEGIN
+RAW
+b742be8f501044626cc60000000000000000
+ENTRY_END
+
+STEP 16220 QUERY
+ENTRY_BEGIN
+RAW
+b74cd39f50104470171a0000000000000000
+ENTRY_END
+
+STEP 16230 QUERY
+ENTRY_BEGIN
+RAW
+b74cd39f501844705a7f000000960285000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe18403c4f980003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 16240 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009a450000020405b401010402
+ENTRY_END
+
+STEP 16250 QUERY
+ENTRY_BEGIN
+RAW
+b74eb5d65010447055640000000000000000
+ENTRY_END
+
+STEP 16260 QUERY
+ENTRY_BEGIN
+RAW
+b74eb5d650184470e49e000000958e00000000010001000000000f343236303630373535373635302d330000f900010f343236303630373535373635302d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd07403c4e870003000000364e544c4d535350000100000097b200e00e000e002800000008000800200000004e54534552564552574547484f5253542d4f4c494b4f0000
+ENTRY_END
+
+STEP 16270 QUERY
+ENTRY_BEGIN
+RAW
+b74eb5e45011446254cc0000000000000000
+ENTRY_END
+
+STEP 16280 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400048fc0000020405b401010402
+ENTRY_END
+
+STEP 16290 QUERY
+ENTRY_BEGIN
+RAW
+b74eb5e55010446254cb0000000000000000
+ENTRY_END
+
+STEP 16300 QUERY
+ENTRY_BEGIN
+RAW
+b7513e29501044707bc50000000000000000
+ENTRY_END
+
+STEP 16310 QUERY
+ENTRY_BEGIN
+RAW
+b7513e29501844706001000000953a00000000010001000000000f343236303630373535373635302d320000f900010f343236303630373535373635302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd07403c4e870003000000364e544c4d535350000100000097b200e00e000e002800000008000800200000004e54534552564552574547484f5253542d4f4c494b4f0000
+ENTRY_END
+
+STEP 16320 QUERY
+ENTRY_BEGIN
+RAW
+b74cd3ad5011446216810000000000000000
+ENTRY_END
+
+STEP 16330 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002efe0000020405b401010402
+ENTRY_END
+
+STEP 16340 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000278d0000020405b401010402
+ENTRY_END
+
+STEP 16350 QUERY
+ENTRY_BEGIN
+RAW
+b7513e37501144627b2d0000000000000000
+ENTRY_END
+
+STEP 16360 QUERY
+ENTRY_BEGIN
+RAW
+b75201fb501044709df40000000000000000
+ENTRY_END
+
+STEP 16370 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b08d0000020405b401010402
+ENTRY_END
+
+STEP 16380 QUERY
+ENTRY_BEGIN
+RAW
+b75201fb50184470261b000000966bb0000000010001000000000f313233363935303538313236362d330000f900010f313233363935303538313236362d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd07403c4e870003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 16390 QUERY
+ENTRY_BEGIN
+RAW
+b7513e38501044627b2c0000000000000000
+ENTRY_END
+
+STEP 16400 QUERY
+ENTRY_BEGIN
+RAW
+b75342ad50104470ded00000000000000000
+ENTRY_END
+
+STEP 16410 QUERY
+ENTRY_BEGIN
+RAW
+b7520209501144629d5b0000000000000000
+ENTRY_END
+
+STEP 16420 QUERY
+ENTRY_BEGIN
+RAW
+b75342ad501844700d0c00000095f000000000010001000000000f343236303630373535373635302d320000f900010f343236303630373535373635302d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd07403c4e870003000000364e544c4d535350000100000097b200e00e000e002800000008000800200000004e54534552564552574547484f5253542d4f4c494b4f0000
+ENTRY_END
+
+STEP 16430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400087df0000020405b401010402
+ENTRY_END
+
+STEP 16440 QUERY
+ENTRY_BEGIN
+RAW
+b752020a501044629d5a0000000000000000
+ENTRY_END
+
+STEP 16450 QUERY
+ENTRY_BEGIN
+RAW
+b75342bb50114462de380000000000000000
+ENTRY_END
+
+STEP 16460 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d3c000000204056401010402
+ENTRY_END
+
+STEP 16470 QUERY
+ENTRY_BEGIN
+RAW
+b754104050104470e88e0000000000000000
+ENTRY_END
+
+STEP 16480 QUERY
+ENTRY_BEGIN
+RAW
+b754104050184470e8b900000096f4ac000000010001000000000f313233363935303538313236362d320000f900010f313233363935303538313236362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd07403c4e870003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 16490 QUERY
+ENTRY_BEGIN
+RAW
+b75342bc50104462de370000000000000000
+ENTRY_END
+
+STEP 16500 QUERY
+ENTRY_BEGIN
+RAW
+b7549d5b501040b0aac40000000000000000
+ENTRY_END
+
+STEP 16510 QUERY
+ENTRY_BEGIN
+RAW
+b754104e50114462e7f50000000000000000
+ENTRY_END
+
+STEP 16520 QUERY
+ENTRY_BEGIN
+RAW
+b7549d5b501840b095820000008c16ee000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afaea403c4c6a00030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 16530 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005e4c0000020405b401010402
+ENTRY_END
+
+STEP 16540 QUERY
+ENTRY_BEGIN
+RAW
+b7549d69501140a2aa350000000000000000
+ENTRY_END
+
+STEP 16550 QUERY
+ENTRY_BEGIN
+RAW
+b754104f50104462e7f40000000000000000
+ENTRY_END
+
+STEP 16560 QUERY
+ENTRY_BEGIN
+RAW
+b755265350104470a8e70000000000000000
+ENTRY_END
+
+STEP 16570 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400038b600000204056401010402
+ENTRY_END
+
+STEP 16580 QUERY
+ENTRY_BEGIN
+RAW
+b7552653501844702017000000967da8000000010001000000000f313233363935303538313236362d320000f900010f313233363935303538313236362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd07403c4e870003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 16590 QUERY
+ENTRY_BEGIN
+RAW
+b7549d6a501040a2aa340000000000000000
+ENTRY_END
+
+STEP 16600 QUERY
+ENTRY_BEGIN
+RAW
+b75604ad501040b0a8660000000000000000
+ENTRY_END
+
+STEP 16610 QUERY
+ENTRY_BEGIN
+RAW
+b75604ad501840b03fd70000008c6b3c000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afaea403c4c6a00030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 16620 QUERY
+ENTRY_BEGIN
+RAW
+b755266150114462a84e0000000000000000
+ENTRY_END
+
+STEP 16630 QUERY
+ENTRY_BEGIN
+RAW
+b755266250104462a84d0000000000000000
+ENTRY_END
+
+STEP 16640 QUERY
+ENTRY_BEGIN
+RAW
+b75604bb501140a2a7d70000000000000000
+ENTRY_END
+
+STEP 16650 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240003d8b00000204056401010402
+ENTRY_END
+
+STEP 16660 QUERY
+ENTRY_BEGIN
+RAW
+b75604bc501040a2a7d60000000000000000
+ENTRY_END
+
+STEP 16670 QUERY
+ENTRY_BEGIN
+RAW
+b756ec01501040b0c5e60000000000000000
+ENTRY_END
+
+STEP 16680 QUERY
+ENTRY_BEGIN
+RAW
+b756ec01501840b069190000008c5f7a000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afaea403c4c6a00030000002d4e544c4d535350000100000097b200c007000700260000000600060020000000534552564552525542594445430000
+ENTRY_END
+
+STEP 16690 QUERY
+ENTRY_BEGIN
+RAW
+b756ec0f501140a2c5570000000000000000
+ENTRY_END
+
+STEP 16700 QUERY
+ENTRY_BEGIN
+RAW
+b756ec10501040a2c5560000000000000000
+ENTRY_END
+
+STEP 16710 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005c4d00000204059801010402
+ENTRY_END
+
+STEP 16720 QUERY
+ENTRY_BEGIN
+RAW
+b757c385501043200ae80000000000000000
+ENTRY_END
+
+STEP 16730 QUERY
+ENTRY_BEGIN
+RAW
+b757c3855018432080320000008b0bc0000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb43403c4cc300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 16740 QUERY
+ENTRY_BEGIN
+RAW
+b757c393501143120a5a0000000000000000
+ENTRY_END
+
+STEP 16750 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000908b00000204059801010402
+ENTRY_END
+
+STEP 16760 QUERY
+ENTRY_BEGIN
+RAW
+b757c394501043120a590000000000000000
+ENTRY_END
+
+STEP 16770 QUERY
+ENTRY_BEGIN
+RAW
+b75a5de550104320a4c30000000000000000
+ENTRY_END
+
+STEP 16780 QUERY
+ENTRY_BEGIN
+RAW
+b75a5de550184320cace0000008b5c00000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb43403c4cc300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 16790 QUERY
+ENTRY_BEGIN
+RAW
+b74cd3ae5010446216800000000000000000
+ENTRY_END
+
+STEP 16800 QUERY
+ENTRY_BEGIN
+RAW
+b7529bd750104470fca60000000000000000
+ENTRY_END
+
+STEP 16810 QUERY
+ENTRY_BEGIN
+RAW
+b7529bd750184470c07c000000968014000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe19403c4f990003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 16820 QUERY
+ENTRY_BEGIN
+RAW
+b75a5df350114312a4350000000000000000
+ENTRY_END
+
+STEP 16830 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000539000000204059801010402
+ENTRY_END
+
+STEP 16840 QUERY
+ENTRY_BEGIN
+RAW
+b75a5df450104312a4340000000000000000
+ENTRY_END
+
+STEP 16850 QUERY
+ENTRY_BEGIN
+RAW
+b75b2958501043209c540000000000000000
+ENTRY_END
+
+STEP 16860 QUERY
+ENTRY_BEGIN
+RAW
+b75b29585018432011e00000008b0c80000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb43403c4cc300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 16870 QUERY
+ENTRY_BEGIN
+RAW
+b75b2966501143129bc60000000000000000
+ENTRY_END
+
+STEP 16880 QUERY
+ENTRY_BEGIN
+RAW
+b75b2967501043129bc50000000000000000
+ENTRY_END
+
+STEP 16890 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fcd600000204059801010402
+ENTRY_END
+
+STEP 16900 QUERY
+ENTRY_BEGIN
+RAW
+b75bfc9650104320725c0000000000000000
+ENTRY_END
+
+STEP 16910 QUERY
+ENTRY_BEGIN
+RAW
+b75bfc965018432095e60000008b5d80000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb43403c4cc300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 16920 QUERY
+ENTRY_BEGIN
+RAW
+b75bfca45011431271ce0000000000000000
+ENTRY_END
+
+STEP 16930 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005ff400000204059801010402
+ENTRY_END
+
+STEP 16940 QUERY
+ENTRY_BEGIN
+RAW
+b75bfca55010431271cd0000000000000000
+ENTRY_END
+
+STEP 16950 QUERY
+ENTRY_BEGIN
+RAW
+b75c9580501043203c8f0000000000000000
+ENTRY_END
+
+STEP 16960 QUERY
+ENTRY_BEGIN
+RAW
+b75c958050184320b09a0000008b0e00000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb43403c4cc300030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 16970 QUERY
+ENTRY_BEGIN
+RAW
+b75c958e501143123c010000000000000000
+ENTRY_END
+
+STEP 16980 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007c5400000204059801010402
+ENTRY_END
+
+STEP 16990 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c5670000020405b401010402
+ENTRY_END
+
+STEP 17000 QUERY
+ENTRY_BEGIN
+RAW
+b75e3db250104470f89a0000000000000000
+ENTRY_END
+
+STEP 17010 QUERY
+ENTRY_BEGIN
+RAW
+b75e3db2501844700e7f0000008c90b3000000010001000000000f313039393531313632373739342d330000f900010f313039393531313632373739342d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc24403c4da400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 17020 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400070f40000020405b401010402
+ENTRY_END
+
+STEP 17030 QUERY
+ENTRY_BEGIN
+RAW
+b75c958f501043123c000000000000000000
+ENTRY_END
+
+STEP 17040 QUERY
+ENTRY_BEGIN
+RAW
+b75d4d2450104320a14a0000000000000000
+ENTRY_END
+
+STEP 17050 QUERY
+ENTRY_BEGIN
+RAW
+b75e3dc050114462f80b0000000000000000
+ENTRY_END
+
+STEP 17060 QUERY
+ENTRY_BEGIN
+RAW
+b75d4d2450184320c9150000008b5840000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17070 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e0850000020405b401010402
+ENTRY_END
+
+STEP 17080 QUERY
+ENTRY_BEGIN
+RAW
+b75e3dc150104462f80a0000000000000000
+ENTRY_END
+
+STEP 17090 QUERY
+ENTRY_BEGIN
+RAW
+b75f940b50104470bd5e0000000000000000
+ENTRY_END
+
+STEP 17100 QUERY
+ENTRY_BEGIN
+RAW
+b75ecb745010447016650000000000000000
+ENTRY_END
+
+STEP 17110 QUERY
+ENTRY_BEGIN
+RAW
+b75f940b501844701be40000008c4913000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc24403c4da400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 17120 QUERY
+ENTRY_BEGIN
+RAW
+b75d4d3250114312a0bc0000000000000000
+ENTRY_END
+
+STEP 17130 QUERY
+ENTRY_BEGIN
+RAW
+b75f941950114462bccf0000000000000000
+ENTRY_END
+
+STEP 17140 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400051fa0000020405b401010402
+ENTRY_END
+
+STEP 17150 QUERY
+ENTRY_BEGIN
+RAW
+b75f941a50104462bcce0000000000000000
+ENTRY_END
+
+STEP 17160 QUERY
+ENTRY_BEGIN
+RAW
+b7604675501044707c680000000000000000
+ENTRY_END
+
+STEP 17170 QUERY
+ENTRY_BEGIN
+RAW
+b75ecb7450184470e98f0000008fa200000000010001000000000f313230323539303834323839382d330000f900010f313230323539303834323839382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdd3403c4f530003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 17180 QUERY
+ENTRY_BEGIN
+RAW
+b760467550184470bc800000008c6780000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc24403c4da400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 17190 QUERY
+ENTRY_BEGIN
+RAW
+b75d4d3350104312a0bb0000000000000000
+ENTRY_END
+
+STEP 17200 QUERY
+ENTRY_BEGIN
+RAW
+b7604683501144627bd90000000000000000
+ENTRY_END
+
+STEP 17210 QUERY
+ENTRY_BEGIN
+RAW
+b7604684501044627bd80000000000000000
+ENTRY_END
+
+STEP 17220 QUERY
+ENTRY_BEGIN
+RAW
+b75ecb825011446215d30000000000000000
+ENTRY_END
+
+STEP 17230 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005d5e0000020405b401010402
+ENTRY_END
+
+STEP 17240 QUERY
+ENTRY_BEGIN
+RAW
+b75ecb835010446215d20000000000000000
+ENTRY_END
+
+STEP 17250 QUERY
+ENTRY_BEGIN
+RAW
+b7630c6050104470c1de0000000000000000
+ENTRY_END
+
+STEP 17260 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000829700000204059801010402
+ENTRY_END
+
+STEP 17270 QUERY
+ENTRY_BEGIN
+RAW
+b7529be550114462fc0d0000000000000000
+ENTRY_END
+
+STEP 17280 QUERY
+ENTRY_BEGIN
+RAW
+b763eae35010432009c80000000000000000
+ENTRY_END
+
+STEP 17290 QUERY
+ENTRY_BEGIN
+RAW
+b7630c60501844703d0a0000008ffb00000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdd3403c4f530003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 17300 QUERY
+ENTRY_BEGIN
+RAW
+b763eae3501843202fd20000008b5900000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17310 QUERY
+ENTRY_BEGIN
+RAW
+b7630c6e50114462c14c0000000000000000
+ENTRY_END
+
+STEP 17320 QUERY
+ENTRY_BEGIN
+RAW
+b763eaf150114312093a0000000000000000
+ENTRY_END
+
+STEP 17330 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400073a600000204059801010402
+ENTRY_END
+
+STEP 17340 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400026de0000020405b401010402
+ENTRY_END
+
+STEP 17350 QUERY
+ENTRY_BEGIN
+RAW
+b7630c6f50104462c14b0000000000000000
+ENTRY_END
+
+STEP 17360 QUERY
+ENTRY_BEGIN
+RAW
+b763eaf25010431209390000000000000000
+ENTRY_END
+
+STEP 17370 QUERY
+ENTRY_BEGIN
+RAW
+b765999a50104470fe210000000000000000
+ENTRY_END
+
+STEP 17380 QUERY
+ENTRY_BEGIN
+RAW
+b764c59f50104320201a0000000000000000
+ENTRY_END
+
+STEP 17390 QUERY
+ENTRY_BEGIN
+RAW
+b764c59f501843209aa50000008b0580000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17400 QUERY
+ENTRY_BEGIN
+RAW
+b765999a50184470204e0000008f5400000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdd3403c4f530003000000304e544c4d535350000100000097b200c0060006002a0000000a000a00200000004459534f53455256455244594e534f4c0000
+ENTRY_END
+
+STEP 17410 QUERY
+ENTRY_BEGIN
+RAW
+b764c5ad501143121f8c0000000000000000
+ENTRY_END
+
+STEP 17420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000865700000204059801010402
+ENTRY_END
+
+STEP 17430 QUERY
+ENTRY_BEGIN
+RAW
+b76599a850114462fd8f0000000000000000
+ENTRY_END
+
+STEP 17440 QUERY
+ENTRY_BEGIN
+RAW
+b764c5ae501043121f8b0000000000000000
+ENTRY_END
+
+STEP 17450 QUERY
+ENTRY_BEGIN
+RAW
+b7668f535010432069150000000000000000
+ENTRY_END
+
+STEP 17460 QUERY
+ENTRY_BEGIN
+RAW
+b7668f535018432033200000008bb600000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17470 QUERY
+ENTRY_BEGIN
+RAW
+b76599a950104462fd8e0000000000000000
+ENTRY_END
+
+STEP 17480 QUERY
+ENTRY_BEGIN
+RAW
+2030000000010000000000000d726f616461697274726176656c026e6c00000f000100
+ENTRY_END
+
+STEP 17490 QUERY
+ENTRY_BEGIN
+RAW
+b7668f615011431268870000000000000000
+ENTRY_END
+
+STEP 17500 QUERY
+ENTRY_BEGIN
+RAW
+b7668f625010431268860000000000000000
+ENTRY_END
+
+STEP 17510 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000677200000204059801010402
+ENTRY_END
+
+STEP 17520 QUERY
+ENTRY_BEGIN
+RAW
+b76739db501043209fa70000000000000000
+ENTRY_END
+
+STEP 17530 QUERY
+ENTRY_BEGIN
+RAW
+b76739db501843206bf10000008bb2c0000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17540 QUERY
+ENTRY_BEGIN
+RAW
+b76739e9501143129f190000000000000000
+ENTRY_END
+
+STEP 17550 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000556e00000204059801010402
+ENTRY_END
+
+STEP 17560 QUERY
+ENTRY_BEGIN
+RAW
+b76739ea501043129f180000000000000000
+ENTRY_END
+
+STEP 17570 QUERY
+ENTRY_BEGIN
+RAW
+b76820ed50104320a6900000000000000000
+ENTRY_END
+
+STEP 17580 QUERY
+ENTRY_BEGIN
+RAW
+b76820ed50184320239c0000008b0300000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17590 QUERY
+ENTRY_BEGIN
+RAW
+b76820fb50114312a6020000000000000000
+ENTRY_END
+
+STEP 17600 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400072f800000204059801010402
+ENTRY_END
+
+STEP 17610 QUERY
+ENTRY_BEGIN
+RAW
+b76820fc50104312a6010000000000000000
+ENTRY_END
+
+STEP 17620 QUERY
+ENTRY_BEGIN
+RAW
+b768f16a50104320f39c0000000000000000
+ENTRY_END
+
+STEP 17630 QUERY
+ENTRY_BEGIN
+RAW
+b768f16a50184320c0270000008bb380000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afb44403c4cc400030000002c4e544c4d535350000100000097b200e0060006002600000006000600200000004d415243454c4845444546410000
+ENTRY_END
+
+STEP 17640 QUERY
+ENTRY_BEGIN
+RAW
+b768f17850114312f30e0000000000000000
+ENTRY_END
+
+STEP 17650 QUERY
+ENTRY_BEGIN
+RAW
+b768f17950104312f30d0000000000000000
+ENTRY_END
+
+STEP 17660 QUERY
+ENTRY_BEGIN
+RAW
+b7529be650104462fc0c0000000000000000
+ENTRY_END
+
+STEP 17670 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fae400000204056401010402
+ENTRY_END
+
+STEP 17680 QUERY
+ENTRY_BEGIN
+RAW
+b76b4fdb501040b01f520000000000000000
+ENTRY_END
+
+STEP 17690 QUERY
+ENTRY_BEGIN
+RAW
+b76b4fdb501840b0d54e00000095c564000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0282403c54020003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 17700 QUERY
+ENTRY_BEGIN
+RAW
+b76b4fe9501140a21eba0000000000000000
+ENTRY_END
+
+STEP 17710 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400048dc00000204056401010402
+ENTRY_END
+
+STEP 17720 QUERY
+ENTRY_BEGIN
+RAW
+b76b4fea501040a21eb90000000000000000
+ENTRY_END
+
+STEP 17730 QUERY
+ENTRY_BEGIN
+RAW
+b76bccee501040b0f0350000000000000000
+ENTRY_END
+
+STEP 17740 QUERY
+ENTRY_BEGIN
+RAW
+b76bccee501840b021e3000000954ab5000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0282403c54020003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 17750 QUERY
+ENTRY_BEGIN
+RAW
+b76bccfc501140a2ef9d0000000000000000
+ENTRY_END
+
+STEP 17760 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002ee600000204056401010402
+ENTRY_END
+
+STEP 17770 QUERY
+ENTRY_BEGIN
+RAW
+b76bccfd501040a2ef9c0000000000000000
+ENTRY_END
+
+STEP 17780 QUERY
+ENTRY_BEGIN
+RAW
+b76cc0f1501040b0e23b0000000000000000
+ENTRY_END
+
+STEP 17790 QUERY
+ENTRY_BEGIN
+RAW
+b76cc0f1501840b0b68700000095a816000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403b0282403c54020003000000364e544c4d535350000100000097b200e00c000c002a0000000a000a00200000004f4d44454e4f4f522d314f4d44454e4f4f52442d48530000
+ENTRY_END
+
+STEP 17800 QUERY
+ENTRY_BEGIN
+RAW
+b76cc0ff501140a2e1a30000000000000000
+ENTRY_END
+
+STEP 17810 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e53c0000020405b401010402
+ENTRY_END
+
+STEP 17820 QUERY
+ENTRY_BEGIN
+RAW
+b76cc100501040a2e1a20000000000000000
+ENTRY_END
+
+STEP 17830 QUERY
+ENTRY_BEGIN
+RAW
+b76d3ff750104470161c0000000000000000
+ENTRY_END
+
+STEP 17840 QUERY
+ENTRY_BEGIN
+RAW
+b76d3ff7501844706a97000000912d80000000010001000000000f313135313035313233353334362d330000f900010f313135313035313233353334362d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2e403c4eae0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 17850 QUERY
+ENTRY_BEGIN
+RAW
+b76d40055011446215880000000000000000
+ENTRY_END
+
+STEP 17860 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000eddd0000020405b401010402
+ENTRY_END
+
+STEP 17870 QUERY
+ENTRY_BEGIN
+RAW
+b76d40065010446215870000000000000000
+ENTRY_END
+
+STEP 17880 QUERY
+ENTRY_BEGIN
+RAW
+b76dbaf750104470a3bc0000000000000000
+ENTRY_END
+
+STEP 17890 QUERY
+ENTRY_BEGIN
+RAW
+b76dbaf750184470fab8000000912c00000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2e403c4eae0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 17900 QUERY
+ENTRY_BEGIN
+RAW
+b76dbb0550114462a3280000000000000000
+ENTRY_END
+
+STEP 17910 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a6000000020405b401010402
+ENTRY_END
+
+STEP 17920 QUERY
+ENTRY_BEGIN
+RAW
+b76dbb0650104462a3270000000000000000
+ENTRY_END
+
+STEP 17930 QUERY
+ENTRY_BEGIN
+RAW
+b76e739b50104470a33a0000000000000000
+ENTRY_END
+
+STEP 17940 QUERY
+ENTRY_BEGIN
+RAW
+b76e739b50184470fbb6000000912a80000000010001000000000f313135313035313233353334362d320000f900010f313135313035313233353334362d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd2e403c4eae0003000000324e544c4d535350000100000097b208e00c000c0026000000060006002000000045434f4e454c4b554e5354454e5a414b454e0000
+ENTRY_END
+
+STEP 17950 QUERY
+ENTRY_BEGIN
+RAW
+b76e73a950114462a2a60000000000000000
+ENTRY_END
+
+STEP 17960 QUERY
+ENTRY_BEGIN
+RAW
+b76e73aa50104462a2a50000000000000000
+ENTRY_END
+
+STEP 17970 QUERY
+ENTRY_BEGIN
+RAW
+01c9000000010000000000000a636974726f656e616972026e6c00000f0001c0
+ENTRY_END
+
+STEP 17980 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ee6c0000020405b401010402
+ENTRY_END
+
+STEP 17990 QUERY
+ENTRY_BEGIN
+RAW
+b77479f150104470e54a0000000000000000
+ENTRY_END
+
+STEP 18000 QUERY
+ENTRY_BEGIN
+RAW
+b77479f150184470b9b70000008d453c000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403b01d7403c535700030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053425332303030484f4c50524f430000
+ENTRY_END
+
+STEP 18010 QUERY
+ENTRY_BEGIN
+RAW
+b77479ff50114462e4ba0000000000000000
+ENTRY_END
+
+STEP 18020 QUERY
+ENTRY_BEGIN
+RAW
+b7747a0050104462e4b90000000000000000
+ENTRY_END
+
+STEP 18030 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000727d00000204059801010402
+ENTRY_END
+
+STEP 18040 QUERY
+ENTRY_BEGIN
+RAW
+b778d534501043200f480000000000000000
+ENTRY_END
+
+STEP 18050 QUERY
+ENTRY_BEGIN
+RAW
+b778d53450184320a10d00000096811c000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c0020000000504f574552454447452d53424f5352444f4d45494e2d310000
+ENTRY_END
+
+STEP 18060 QUERY
+ENTRY_BEGIN
+RAW
+b778d542501143120eaf0000000000000000
+ENTRY_END
+
+STEP 18070 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c9ec00000204059801010402
+ENTRY_END
+
+STEP 18080 QUERY
+ENTRY_BEGIN
+RAW
+b778d543501043120eae0000000000000000
+ENTRY_END
+
+STEP 18090 QUERY
+ENTRY_BEGIN
+RAW
+b7799c6a501043209f800000000000000000
+ENTRY_END
+
+STEP 18100 QUERY
+ENTRY_BEGIN
+RAW
+b7799c6a50184320239b000000968fc8000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c0020000000504f574552454447452d53424f5352444f4d45494e2d310000
+ENTRY_END
+
+STEP 18110 QUERY
+ENTRY_BEGIN
+RAW
+b7799c78501143129ee70000000000000000
+ENTRY_END
+
+STEP 18120 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008c0d00000204059801010402
+ENTRY_END
+
+STEP 18130 QUERY
+ENTRY_BEGIN
+RAW
+b7799c79501043129ee60000000000000000
+ENTRY_END
+
+STEP 18140 QUERY
+ENTRY_BEGIN
+RAW
+b77a3c4a50104320c1c00000000000000000
+ENTRY_END
+
+STEP 18150 QUERY
+ENTRY_BEGIN
+RAW
+b77a3c4a50184320372f000000969e74000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000374e544c4d535350000100000097b208e00b000b002c0000000c000c0020000000504f574552454447452d53424f5352444f4d45494e2d310000
+ENTRY_END
+
+STEP 18160 QUERY
+ENTRY_BEGIN
+RAW
+b77a3c5850114312c1270000000000000000
+ENTRY_END
+
+STEP 18170 QUERY
+ENTRY_BEGIN
+RAW
+b77a3c5950104312c1260000000000000000
+ENTRY_END
+
+STEP 18180 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000baf20000020405b401010402
+ENTRY_END
+
+STEP 18190 QUERY
+ENTRY_BEGIN
+RAW
+b77c30cc50104470faed0000000000000000
+ENTRY_END
+
+STEP 18200 QUERY
+ENTRY_BEGIN
+RAW
+b77c30cc50184470e39a0000008e4390000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd2f403c4eaf00030000002f4e544c4d535350000100000097b208e00900090026000000060006002000000056444c4d475256444c4d455441414c0000
+ENTRY_END
+
+STEP 18210 QUERY
+ENTRY_BEGIN
+RAW
+b77c30da50114462fa5c0000000000000000
+ENTRY_END
+
+STEP 18220 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d8d00000020405b401010402
+ENTRY_END
+
+STEP 18230 QUERY
+ENTRY_BEGIN
+RAW
+b77c30db50104462fa5b0000000000000000
+ENTRY_END
+
+STEP 18240 QUERY
+ENTRY_BEGIN
+RAW
+b77d061b50104470437c0000000000000000
+ENTRY_END
+
+STEP 18250 QUERY
+ENTRY_BEGIN
+RAW
+b77d061b501844701c460000008e5474000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd2f403c4eaf00030000002f4e544c4d535350000100000097b208e00900090026000000060006002000000056444c4d475256444c4d455441414c0000
+ENTRY_END
+
+STEP 18260 QUERY
+ENTRY_BEGIN
+RAW
+b77d06295011446242eb0000000000000000
+ENTRY_END
+
+STEP 18270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400050950000020405b401010402
+ENTRY_END
+
+STEP 18280 QUERY
+ENTRY_BEGIN
+RAW
+b77d062a5010446242ea0000000000000000
+ENTRY_END
+
+STEP 18290 QUERY
+ENTRY_BEGIN
+RAW
+b77dd9ff50104470e75b0000000000000000
+ENTRY_END
+
+STEP 18300 QUERY
+ENTRY_BEGIN
+RAW
+b77dd9ff501844701b610000008ef938000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd2f403c4eaf00030000002f4e544c4d535350000100000097b208e00900090026000000060006002000000056444c4d475256444c4d455441414c0000
+ENTRY_END
+
+STEP 18310 QUERY
+ENTRY_BEGIN
+RAW
+b77dda0d50114462e6ca0000000000000000
+ENTRY_END
+
+STEP 18320 QUERY
+ENTRY_BEGIN
+RAW
+b77dda0e50104462e6c90000000000000000
+ENTRY_END
+
+STEP 18330 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b66a00000204053401010402
+ENTRY_END
+
+STEP 18340 QUERY
+ENTRY_BEGIN
+RAW
+b77f5e2550104470c8890000000000000000
+ENTRY_END
+
+STEP 18350 QUERY
+ENTRY_BEGIN
+RAW
+b77f5e2550184470c1d00000009411de000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03d4403c55540003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 18360 QUERY
+ENTRY_BEGIN
+RAW
+b77f5e3350114462c7f20000000000000000
+ENTRY_END
+
+STEP 18370 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000625d00000204053401010402
+ENTRY_END
+
+STEP 18380 QUERY
+ENTRY_BEGIN
+RAW
+b77f5e3450104462c7f10000000000000000
+ENTRY_END
+
+STEP 18390 QUERY
+ENTRY_BEGIN
+RAW
+b7821b2150104470b77d0000000000000000
+ENTRY_END
+
+STEP 18400 QUERY
+ENTRY_BEGIN
+RAW
+b7821b2150184470cf8800000094f41a000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03d4403c55540003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 18410 QUERY
+ENTRY_BEGIN
+RAW
+b7821b2f50114462b6e60000000000000000
+ENTRY_END
+
+STEP 18420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000723e00000204053401010402
+ENTRY_END
+
+STEP 18430 QUERY
+ENTRY_BEGIN
+RAW
+b7821b3050104462b6e50000000000000000
+ENTRY_END
+
+STEP 18440 QUERY
+ENTRY_BEGIN
+RAW
+b782ac965010447035e90000000000000000
+ENTRY_END
+
+STEP 18450 QUERY
+ENTRY_BEGIN
+RAW
+b782ac9650184470f0ae000000945160000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03d4403c55540003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 18460 QUERY
+ENTRY_BEGIN
+RAW
+b782aca45011446235520000000000000000
+ENTRY_END
+
+STEP 18470 QUERY
+ENTRY_BEGIN
+RAW
+b782aca55010446235510000000000000000
+ENTRY_END
+
+STEP 18480 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400090520000020405b401010402
+ENTRY_END
+
+STEP 18490 QUERY
+ENTRY_BEGIN
+RAW
+b786466a50104470baa50000000000000000
+ENTRY_END
+
+STEP 18500 QUERY
+ENTRY_BEGIN
+RAW
+b786466a501844706f640000008d65eb000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403b01d7403c535700030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053425332303030484f4c50524f430000
+ENTRY_END
+
+STEP 18510 QUERY
+ENTRY_BEGIN
+RAW
+b786467850114462ba150000000000000000
+ENTRY_END
+
+STEP 18520 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000908a0000020405b401010402
+ENTRY_END
+
+STEP 18530 QUERY
+ENTRY_BEGIN
+RAW
+b786467950104462ba140000000000000000
+ENTRY_END
+
+STEP 18540 QUERY
+ENTRY_BEGIN
+RAW
+b787260850104470db3e0000000000000000
+ENTRY_END
+
+STEP 18550 QUERY
+ENTRY_BEGIN
+RAW
+b787260850184470b2ad0000008d3b3b000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403b01db403c535b00030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053425332303030484f4c50524f430000
+ENTRY_END
+
+STEP 18560 QUERY
+ENTRY_BEGIN
+RAW
+b787261650114462daae0000000000000000
+ENTRY_END
+
+STEP 18570 QUERY
+ENTRY_BEGIN
+RAW
+b787261750104462daad0000000000000000
+ENTRY_END
+
+STEP 18580 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c82d0000020405b401010402
+ENTRY_END
+
+STEP 18590 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a61c0000020405b401010402
+ENTRY_END
+
+STEP 18600 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f9bf00000204057801010402
+ENTRY_END
+
+STEP 18610 QUERY
+ENTRY_BEGIN
+RAW
+b78b571050104470bfc40000000000000000
+ENTRY_END
+
+STEP 18620 QUERY
+ENTRY_BEGIN
+RAW
+b78b5710501844704cc600000097e600000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 18630 QUERY
+ENTRY_BEGIN
+RAW
+b78c39d15010fb90343a0000000000000000
+ENTRY_END
+
+STEP 18640 QUERY
+ENTRY_BEGIN
+RAW
+b78c39d15018fb909ce6000000909f24000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000056494e4743415244484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 18650 QUERY
+ENTRY_BEGIN
+RAW
+b78b571e50114462bf2a0000000000000000
+ENTRY_END
+
+STEP 18660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400008150000020405b401010402
+ENTRY_END
+
+STEP 18670 QUERY
+ENTRY_BEGIN
+RAW
+b78c39df5011fb8233a70000000000000000
+ENTRY_END
+
+STEP 18680 QUERY
+ENTRY_BEGIN
+RAW
+b78b571f50104462bf290000000000000000
+ENTRY_END
+
+STEP 18690 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c9e400000204057801010402
+ENTRY_END
+
+STEP 18700 QUERY
+ENTRY_BEGIN
+RAW
+b78cbc5650104470bc750000000000000000
+ENTRY_END
+
+STEP 18710 QUERY
+ENTRY_BEGIN
+RAW
+b78cbc5650184470607800000097d000000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 18720 QUERY
+ENTRY_BEGIN
+RAW
+b78c39e05010fb8233a60000000000000000
+ENTRY_END
+
+STEP 18730 QUERY
+ENTRY_BEGIN
+RAW
+b78da4565010fb9099d80000000000000000
+ENTRY_END
+
+STEP 18740 QUERY
+ENTRY_BEGIN
+RAW
+b78cbc6450114462bbdb0000000000000000
+ENTRY_END
+
+STEP 18750 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000228f0000020405b401010402
+ENTRY_END
+
+STEP 18760 QUERY
+ENTRY_BEGIN
+RAW
+b78da4565018fb901ec30000009084e6000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000056494e4743415244484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 18770 QUERY
+ENTRY_BEGIN
+RAW
+b78cbc6550104462bbda0000000000000000
+ENTRY_END
+
+STEP 18780 QUERY
+ENTRY_BEGIN
+RAW
+b78e75ee501044701d560000000000000000
+ENTRY_END
+
+STEP 18790 QUERY
+ENTRY_BEGIN
+RAW
+b78da4645011fb8299450000000000000000
+ENTRY_END
+
+STEP 18800 QUERY
+ENTRY_BEGIN
+RAW
+b78e75ee50184470d75800000097ba00000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 18810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0089000000204057801010402
+ENTRY_END
+
+STEP 18820 QUERY
+ENTRY_BEGIN
+RAW
+b78da4655010fb8299440000000000000000
+ENTRY_END
+
+STEP 18830 QUERY
+ENTRY_BEGIN
+RAW
+b78e75fc501144621cbc0000000000000000
+ENTRY_END
+
+STEP 18840 QUERY
+ENTRY_BEGIN
+RAW
+b78f54175010fb9028c10000000000000000
+ENTRY_END
+
+STEP 18850 QUERY
+ENTRY_BEGIN
+RAW
+b78f54175018fb9063c900000090cec8000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e00b000b0028000000080008002000000056494e4743415244484f54454c414c4d454c4f0000
+ENTRY_END
+
+STEP 18860 QUERY
+ENTRY_BEGIN
+RAW
+b78e75fd501044621cbb0000000000000000
+ENTRY_END
+
+STEP 18870 QUERY
+ENTRY_BEGIN
+RAW
+b78f54255011fb82282e0000000000000000
+ENTRY_END
+
+STEP 18880 QUERY
+ENTRY_BEGIN
+RAW
+b78f54265010fb82282d0000000000000000
+ENTRY_END
+
+STEP 18890 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000300a0000020405b401010402
+ENTRY_END
+
+STEP 18900 QUERY
+ENTRY_BEGIN
+RAW
+b79029f35010447076ca0000000000000000
+ENTRY_END
+
+STEP 18910 QUERY
+ENTRY_BEGIN
+RAW
+b79029f3501844703bcc00000097ae00000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 18920 QUERY
+ENTRY_BEGIN
+RAW
+b7902a015011446276300000000000000000
+ENTRY_END
+
+STEP 18930 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000652c0000020405b401010402
+ENTRY_END
+
+STEP 18940 QUERY
+ENTRY_BEGIN
+RAW
+b7902a0250104462762f0000000000000000
+ENTRY_END
+
+STEP 18950 QUERY
+ENTRY_BEGIN
+RAW
+b790f1e050104470e3fe0000000000000000
+ENTRY_END
+
+STEP 18960 QUERY
+ENTRY_BEGIN
+RAW
+b790f1e050184470c001000000979800000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 18970 QUERY
+ENTRY_BEGIN
+RAW
+b790f1ee50114462e3640000000000000000
+ENTRY_END
+
+STEP 18980 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400068eb0000020405b401010402
+ENTRY_END
+
+STEP 18990 QUERY
+ENTRY_BEGIN
+RAW
+b790f1ef50104462e3630000000000000000
+ENTRY_END
+
+STEP 19000 QUERY
+ENTRY_BEGIN
+RAW
+b79170fc5010447068a10000000000000000
+ENTRY_END
+
+STEP 19010 QUERY
+ENTRY_BEGIN
+RAW
+b79170fc50184470faa300000097e200000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19020 QUERY
+ENTRY_BEGIN
+RAW
+b791710a5011446268070000000000000000
+ENTRY_END
+
+STEP 19030 QUERY
+ENTRY_BEGIN
+RAW
+b791710b5010446268060000000000000000
+ENTRY_END
+
+STEP 19040 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400020bf0000020405b401010402
+ENTRY_END
+
+STEP 19050 QUERY
+ENTRY_BEGIN
+RAW
+b793c2aa50104470cec40000000000000000
+ENTRY_END
+
+STEP 19060 QUERY
+ENTRY_BEGIN
+RAW
+b793c2aa50184470cbc6000000977600000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19070 QUERY
+ENTRY_BEGIN
+RAW
+b793c2b850114462ce2a0000000000000000
+ENTRY_END
+
+STEP 19080 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000dbf20000020405b401010402
+ENTRY_END
+
+STEP 19090 QUERY
+ENTRY_BEGIN
+RAW
+b793c2b950104462ce290000000000000000
+ENTRY_END
+
+STEP 19100 QUERY
+ENTRY_BEGIN
+RAW
+b794500950104470fc980000000000000000
+ENTRY_END
+
+STEP 19110 QUERY
+ENTRY_BEGIN
+RAW
+b794500950184470109c000000976000000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19120 QUERY
+ENTRY_BEGIN
+RAW
+b78ab6a950104470823d0000000000000000
+ENTRY_END
+
+STEP 19130 QUERY
+ENTRY_BEGIN
+RAW
+b78ab6a95018447098b1000000961c75000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe21403c4fa10003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 19140 QUERY
+ENTRY_BEGIN
+RAW
+b794501750114462fbfe0000000000000000
+ENTRY_END
+
+STEP 19150 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005a800000020405b401010402
+ENTRY_END
+
+STEP 19160 QUERY
+ENTRY_BEGIN
+RAW
+b794501850104462fbfd0000000000000000
+ENTRY_END
+
+STEP 19170 QUERY
+ENTRY_BEGIN
+RAW
+b7952a9c50104470a0920000000000000000
+ENTRY_END
+
+STEP 19180 QUERY
+ENTRY_BEGIN
+RAW
+b7952a9c501844706a9500000097aa00000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19190 QUERY
+ENTRY_BEGIN
+RAW
+b7952aaa501144629ff80000000000000000
+ENTRY_END
+
+STEP 19200 QUERY
+ENTRY_BEGIN
+RAW
+b7952aab501044629ff70000000000000000
+ENTRY_END
+
+STEP 19210 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005b800000020405b401010402
+ENTRY_END
+
+STEP 19220 QUERY
+ENTRY_BEGIN
+RAW
+b795b7cb5010447014630000000000000000
+ENTRY_END
+
+STEP 19230 QUERY
+ENTRY_BEGIN
+RAW
+b795b7cb501844701f65000000976800000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19240 QUERY
+ENTRY_BEGIN
+RAW
+b795b7d95011446213c90000000000000000
+ENTRY_END
+
+STEP 19250 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400082b20000020405b401010402
+ENTRY_END
+
+STEP 19260 QUERY
+ENTRY_BEGIN
+RAW
+b795b7da5010446213c80000000000000000
+ENTRY_END
+
+STEP 19270 QUERY
+ENTRY_BEGIN
+RAW
+b7963fba50104470b3a50000000000000000
+ENTRY_END
+
+STEP 19280 QUERY
+ENTRY_BEGIN
+RAW
+b7963fba5018447075a800000097b200000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19290 QUERY
+ENTRY_BEGIN
+RAW
+b7963fc850114462b30b0000000000000000
+ENTRY_END
+
+STEP 19300 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b50f0000020405b401010402
+ENTRY_END
+
+STEP 19310 QUERY
+ENTRY_BEGIN
+RAW
+b7963fc950104462b30a0000000000000000
+ENTRY_END
+
+STEP 19320 QUERY
+ENTRY_BEGIN
+RAW
+b797006150104470255b0000000000000000
+ENTRY_END
+
+STEP 19330 QUERY
+ENTRY_BEGIN
+RAW
+b797006150184470275e000000977200000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005b03677373096d6963726f736f667403636f6d00403afc56403c4dd60003000000384e544c4d535350000100000097b200e00f000f0029000000090009002000000046532d535445494a4c535445494a4c45522d444f4d45494e0000
+ENTRY_END
+
+STEP 19340 QUERY
+ENTRY_BEGIN
+RAW
+b797006f5011446224c10000000000000000
+ENTRY_END
+
+STEP 19350 QUERY
+ENTRY_BEGIN
+RAW
+b79700705010446224c00000000000000000
+ENTRY_END
+
+STEP 19360 QUERY
+ENTRY_BEGIN
+RAW
+b78ab6b75011446281a40000000000000000
+ENTRY_END
+
+STEP 19370 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a5620000020405b401010402
+ENTRY_END
+
+STEP 19380 QUERY
+ENTRY_BEGIN
+RAW
+b78ab6b85010446281a30000000000000000
+ENTRY_END
+
+STEP 19390 QUERY
+ENTRY_BEGIN
+RAW
+b799061e501044700fef0000000000000000
+ENTRY_END
+
+STEP 19400 QUERY
+ENTRY_BEGIN
+RAW
+b799061e50184470a7d4000000969a04000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe22403c4fa20003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 19410 QUERY
+ENTRY_BEGIN
+RAW
+b799062c501144620f560000000000000000
+ENTRY_END
+
+STEP 19420 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400003530000020405b401010402
+ENTRY_END
+
+STEP 19430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400097ba00000204050201010402
+ENTRY_END
+
+STEP 19440 QUERY
+ENTRY_BEGIN
+RAW
+b79cddf25010411a2d130000000000000000
+ENTRY_END
+
+STEP 19450 QUERY
+ENTRY_BEGIN
+RAW
+b79cddf25018411a5cde0000008c9fd3000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403b010f403c528f00030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 19460 QUERY
+ENTRY_BEGIN
+RAW
+b79cde005011410c2c840000000000000000
+ENTRY_END
+
+STEP 19470 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a37900000204050201010402
+ENTRY_END
+
+STEP 19480 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0aab600000204055001010402
+ENTRY_END
+
+STEP 19490 QUERY
+ENTRY_BEGIN
+RAW
+b79cde015010410c2c830000000000000000
+ENTRY_END
+
+STEP 19500 QUERY
+ENTRY_BEGIN
+RAW
+b79d77645010411a9f5f0000000000000000
+ENTRY_END
+
+STEP 19510 QUERY
+ENTRY_BEGIN
+RAW
+b79e06435010ff0015150000000000000000
+ENTRY_END
+
+STEP 19520 QUERY
+ENTRY_BEGIN
+RAW
+b79d77645018411a70710000008cff8d000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b010f403c528f00030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 19530 QUERY
+ENTRY_BEGIN
+RAW
+b79e06435018ff005db30000009294e1000000010001000000000f313531313832383438383231302d330000f900010f313531313832383438383231302d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403b000c403c518c0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 19540 QUERY
+ENTRY_BEGIN
+RAW
+b79e06515011fef214800000000000000000
+ENTRY_END
+
+STEP 19550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf050e100000204055001010402
+ENTRY_END
+
+STEP 19560 QUERY
+ENTRY_BEGIN
+RAW
+b79d77725011410c9ed00000000000000000
+ENTRY_END
+
+STEP 19570 QUERY
+ENTRY_BEGIN
+RAW
+b79e06525010fef2147f0000000000000000
+ENTRY_END
+
+STEP 19580 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009ac800000204050201010402
+ENTRY_END
+
+STEP 19590 QUERY
+ENTRY_BEGIN
+RAW
+b79ebf905010ff0001f20000000000000000
+ENTRY_END
+
+STEP 19600 QUERY
+ENTRY_BEGIN
+RAW
+b79ebf905018ff008473000000925bff000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b000c403c518c0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 19610 QUERY
+ENTRY_BEGIN
+RAW
+b79ebf9e5011fef2015d0000000000000000
+ENTRY_END
+
+STEP 19620 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b1da00000204055001010402
+ENTRY_END
+
+STEP 19630 QUERY
+ENTRY_BEGIN
+RAW
+b79d77735010410c9ecf0000000000000000
+ENTRY_END
+
+STEP 19640 QUERY
+ENTRY_BEGIN
+RAW
+b79fb44e5010411a59c20000000000000000
+ENTRY_END
+
+STEP 19650 QUERY
+ENTRY_BEGIN
+RAW
+b79ebf9f5010fef2015c0000000000000000
+ENTRY_END
+
+STEP 19660 QUERY
+ENTRY_BEGIN
+RAW
+b7a08dfc5010ff00947d0000000000000000
+ENTRY_END
+
+STEP 19670 QUERY
+ENTRY_BEGIN
+RAW
+b79fb44e5018411a6a970000008cbfca000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b010f403c528f00030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 19680 QUERY
+ENTRY_BEGIN
+RAW
+b7a08dfc5018ff004fe100000092231d000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b000c403c518c0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 19690 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bed00000020405b401010402
+ENTRY_END
+
+STEP 19700 QUERY
+ENTRY_BEGIN
+RAW
+b7a08e0a5011fef293e80000000000000000
+ENTRY_END
+
+STEP 19710 QUERY
+ENTRY_BEGIN
+RAW
+b79fb45c5011410c59330000000000000000
+ENTRY_END
+
+STEP 19720 QUERY
+ENTRY_BEGIN
+RAW
+b7a14a0750104470e56b0000000000000000
+ENTRY_END
+
+STEP 19730 QUERY
+ENTRY_BEGIN
+RAW
+b7a08e0b5010fef293e70000000000000000
+ENTRY_END
+
+STEP 19740 QUERY
+ENTRY_BEGIN
+RAW
+b7a14a0750184470b1d600000090026f000000010001000000000f313230323539303834323839382d330000f900010f313230323539303834323839382d330000f900ff00000000005403677373096d6963726f736f667403636f6d00403b0439403c55b90003000000314e544c4d535350000100000097b200c009000900280000000800080020000000534c4f5453504543534c4f5453504543300000
+ENTRY_END
+
+STEP 19750 QUERY
+ENTRY_BEGIN
+RAW
+b7a14a1550114462e4d80000000000000000
+ENTRY_END
+
+STEP 19760 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002ebf0000020405b401010402
+ENTRY_END
+
+STEP 19770 QUERY
+ENTRY_BEGIN
+RAW
+b79fb45d5010410c59320000000000000000
+ENTRY_END
+
+STEP 19780 QUERY
+ENTRY_BEGIN
+RAW
+b7a14a1650104462e4d70000000000000000
+ENTRY_END
+
+STEP 19790 QUERY
+ENTRY_BEGIN
+RAW
+b7a1da0550104470c55b0000000000000000
+ENTRY_END
+
+STEP 19800 QUERY
+ENTRY_BEGIN
+RAW
+b7a1da0550184470ef6c00000090a5c9000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403b0439403c55b90003000000314e544c4d535350000100000097b200c009000900280000000800080020000000534c4f5453504543534c4f5453504543300000
+ENTRY_END
+
+STEP 19810 QUERY
+ENTRY_BEGIN
+RAW
+b7a1da1350114462c4c80000000000000000
+ENTRY_END
+
+STEP 19820 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009c3d0000020405b401010402
+ENTRY_END
+
+STEP 19830 QUERY
+ENTRY_BEGIN
+RAW
+b7a1da1450104462c4c70000000000000000
+ENTRY_END
+
+STEP 19840 QUERY
+ENTRY_BEGIN
+RAW
+b7a2547350104470b86b0000000000000000
+ENTRY_END
+
+STEP 19850 QUERY
+ENTRY_BEGIN
+RAW
+b7a25473501844705e05000000902a41000000010001000000000f313230323539303834323839382d320000f900010f313230323539303834323839382d320000f900ff00000000005403677373096d6963726f736f667403636f6d00403b0439403c55b90003000000314e544c4d535350000100000097b200c009000900280000000800080020000000534c4f5453504543534c4f5453504543300000
+ENTRY_END
+
+STEP 19860 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006c7000000204050201010402
+ENTRY_END
+
+STEP 19870 QUERY
+ENTRY_BEGIN
+RAW
+b7a2548150114462b7d80000000000000000
+ENTRY_END
+
+STEP 19880 QUERY
+ENTRY_BEGIN
+RAW
+b7a2548250104462b7d70000000000000000
+ENTRY_END
+
+STEP 19890 QUERY
+ENTRY_BEGIN
+RAW
+b7a310eb5010411acec90000000000000000
+ENTRY_END
+
+STEP 19900 QUERY
+ENTRY_BEGIN
+RAW
+b7a310eb5018411a16fa0000008c876e000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403b010f403c528f00030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 19910 QUERY
+ENTRY_BEGIN
+RAW
+b7a310f95011410cce3a0000000000000000
+ENTRY_END
+
+STEP 19920 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033b900000204050201010402
+ENTRY_END
+
+STEP 19930 QUERY
+ENTRY_BEGIN
+RAW
+b7a310fa5010410cce390000000000000000
+ENTRY_END
+
+STEP 19940 QUERY
+ENTRY_BEGIN
+RAW
+b7a40ad35010411a9c290000000000000000
+ENTRY_END
+
+STEP 19950 QUERY
+ENTRY_BEGIN
+RAW
+b7a40ad35018411a2d4e0000008c3f7b000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b010f403c528f00030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 19960 QUERY
+ENTRY_BEGIN
+RAW
+b7a40ae15011410c9b9a0000000000000000
+ENTRY_END
+
+STEP 19970 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000654c00000204050201010402
+ENTRY_END
+
+STEP 19980 QUERY
+ENTRY_BEGIN
+RAW
+b7a40ae25010410c9b990000000000000000
+ENTRY_END
+
+STEP 19990 QUERY
+ENTRY_BEGIN
+RAW
+b7a4fbf25010411adc9c0000000000000000
+ENTRY_END
+
+STEP 20000 QUERY
+ENTRY_BEGIN
+RAW
+b7a4fbf25018411aab3c0000008c0000000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b0110403c529000030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004441422d4856534441424856530000
+ENTRY_END
+
+STEP 20010 QUERY
+ENTRY_BEGIN
+RAW
+b7a4fc005011410cdc0d0000000000000000
+ENTRY_END
+
+STEP 20020 QUERY
+ENTRY_BEGIN
+RAW
+b7a4fc015010410cdc0c0000000000000000
+ENTRY_END
+
+STEP 20030 QUERY
+ENTRY_BEGIN
+RAW
+b799062d501044620f550000000000000000
+ENTRY_END
+
+STEP 20040 QUERY
+ENTRY_BEGIN
+RAW
+b79c1b875010447058730000000000000000
+ENTRY_END
+
+STEP 20050 QUERY
+ENTRY_BEGIN
+RAW
+b79c1b87501844701a89000000966dd4000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afe23403c4fa30003000000374e544c4d535350000100000097b208e00e000e002900000009000900200000004f4e5a45564144455252495050455244415041524b32390000
+ENTRY_END
+
+STEP 20060 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400042ef0000020405b401010402
+ENTRY_END
+
+STEP 20070 QUERY
+ENTRY_BEGIN
+RAW
+b7a68eff50104470248d0000000000000000
+ENTRY_END
+
+STEP 20080 QUERY
+ENTRY_BEGIN
+RAW
+b7a68eff501844701c1f0000008614fc000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000004a03677373096d6963726f736f667403636f6d00403b094d403c5acd0003000000274e544c4d535350000100000097b200e0040004002300000003000300200000004b55424b5542320000
+ENTRY_END
+
+STEP 20090 QUERY
+ENTRY_BEGIN
+RAW
+b7a68f0d5011446224040000000000000000
+ENTRY_END
+
+STEP 20100 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b00b0000020405b401010402
+ENTRY_END
+
+STEP 20110 QUERY
+ENTRY_BEGIN
+RAW
+b7a772d750104470add00000000000000000
+ENTRY_END
+
+STEP 20120 QUERY
+ENTRY_BEGIN
+RAW
+b7a772d7501844709517000000862648000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000004a03677373096d6963726f736f667403636f6d00403b094d403c5acd0003000000274e544c4d535350000100000097b200e0040004002300000003000300200000004b55424b5542320000
+ENTRY_END
+
+STEP 20130 QUERY
+ENTRY_BEGIN
+RAW
+b7a68f0e5010446224030000000000000000
+ENTRY_END
+
+STEP 20140 QUERY
+ENTRY_BEGIN
+RAW
+b79c1b955011446257da0000000000000000
+ENTRY_END
+
+STEP 20150 QUERY
+ENTRY_BEGIN
+RAW
+b7a772e550114462ad470000000000000000
+ENTRY_END
+
+STEP 20160 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008c7e0000020405b401010402
+ENTRY_END
+
+STEP 20170 QUERY
+ENTRY_BEGIN
+RAW
+b7a772e650104462ad460000000000000000
+ENTRY_END
+
+STEP 20180 QUERY
+ENTRY_BEGIN
+RAW
+b7a956ee50104470a62a0000000000000000
+ENTRY_END
+
+STEP 20190 QUERY
+ENTRY_BEGIN
+RAW
+b7a956ee50184470f94200000086ba76000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000004a03677373096d6963726f736f667403636f6d00403b094d403c5acd0003000000274e544c4d535350000100000097b200e0040004002300000003000300200000004b55424b5542320000
+ENTRY_END
+
+STEP 20200 QUERY
+ENTRY_BEGIN
+RAW
+b7a956fc50114462a5a10000000000000000
+ENTRY_END
+
+STEP 20210 QUERY
+ENTRY_BEGIN
+RAW
+b7a956fd50104462a5a00000000000000000
+ENTRY_END
+
+STEP 20220 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e5980000020405b401010402
+ENTRY_END
+
+STEP 20230 QUERY
+ENTRY_BEGIN
+RAW
+b7aa19b2501044703c800000000000000000
+ENTRY_END
+
+STEP 20240 QUERY
+ENTRY_BEGIN
+RAW
+b7aa19b250184470b1f40000008ddd28000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd15403c4e9500030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 20250 QUERY
+ENTRY_BEGIN
+RAW
+b7aa19c0501144623bf00000000000000000
+ENTRY_END
+
+STEP 20260 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400058f40000020405b401010402
+ENTRY_END
+
+STEP 20270 QUERY
+ENTRY_BEGIN
+RAW
+b7aa19c1501044623bef0000000000000000
+ENTRY_END
+
+STEP 20280 QUERY
+ENTRY_BEGIN
+RAW
+b7ab053050104470c45c0000000000000000
+ENTRY_END
+
+STEP 20290 QUERY
+ENTRY_BEGIN
+RAW
+b7ab053050184470d0130000008d47e7000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd15403c4e9500030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 20300 QUERY
+ENTRY_BEGIN
+RAW
+b7ab053e50114462c3cc0000000000000000
+ENTRY_END
+
+STEP 20310 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400017040000020405b401010402
+ENTRY_END
+
+STEP 20320 QUERY
+ENTRY_BEGIN
+RAW
+b7ab053f50104462c3cb0000000000000000
+ENTRY_END
+
+STEP 20330 QUERY
+ENTRY_BEGIN
+RAW
+b7ab93d850104470f3c30000000000000000
+ENTRY_END
+
+STEP 20340 QUERY
+ENTRY_BEGIN
+RAW
+b79c1b965010446257d90000000000000000
+ENTRY_END
+
+STEP 20350 QUERY
+ENTRY_BEGIN
+RAW
+b7ab93d8501844708a3c0000008dbd25000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd15403c4e9500030000002e4e544c4d535350000100000097b200e00700070027000000070007002000000053455256455231534954544152440000
+ENTRY_END
+
+STEP 20360 QUERY
+ENTRY_BEGIN
+RAW
+b7ab93e650114462f3330000000000000000
+ENTRY_END
+
+STEP 20370 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001bf80000020405b401010402
+ENTRY_END
+
+STEP 20380 QUERY
+ENTRY_BEGIN
+RAW
+b7ab93e750104462f3320000000000000000
+ENTRY_END
+
+STEP 20390 QUERY
+ENTRY_BEGIN
+RAW
+b7ac6f7a501044701d150000000000000000
+ENTRY_END
+
+STEP 20400 QUERY
+ENTRY_BEGIN
+RAW
+b7ac6f7a501844708c1a00000091ecce000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd3e403c4ebe0003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 20410 QUERY
+ENTRY_BEGIN
+RAW
+b7ac6f88501144621c810000000000000000
+ENTRY_END
+
+STEP 20420 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000de780000020405b401010402
+ENTRY_END
+
+STEP 20430 QUERY
+ENTRY_BEGIN
+RAW
+b7ac6f89501044621c800000000000000000
+ENTRY_END
+
+STEP 20440 QUERY
+ENTRY_BEGIN
+RAW
+b7aef16c501044705da10000000000000000
+ENTRY_END
+
+STEP 20450 QUERY
+ENTRY_BEGIN
+RAW
+b7aef16c501844706076000000915800000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd3f403c4ebf0003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 20460 QUERY
+ENTRY_BEGIN
+RAW
+b7aef17a501144625d0d0000000000000000
+ENTRY_END
+
+STEP 20470 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ce160000020405b401010402
+ENTRY_END
+
+STEP 20480 QUERY
+ENTRY_BEGIN
+RAW
+b7aef17b501044625d0c0000000000000000
+ENTRY_END
+
+STEP 20490 QUERY
+ENTRY_BEGIN
+RAW
+b7af8e0150104470b0a90000000000000000
+ENTRY_END
+
+STEP 20500 QUERY
+ENTRY_BEGIN
+RAW
+b7af8e0150184470ff7e000000910c00000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd3f403c4ebf0003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 20510 QUERY
+ENTRY_BEGIN
+RAW
+b7af8e0f50114462b0150000000000000000
+ENTRY_END
+
+STEP 20520 QUERY
+ENTRY_BEGIN
+RAW
+b7af8e1050104462b0140000000000000000
+ENTRY_END
+
+STEP 20530 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08ad60000020405b401010402
+ENTRY_END
+
+STEP 20540 QUERY
+ENTRY_BEGIN
+RAW
+b7b2120c5010faf0edcb0000000000000000
+ENTRY_END
+
+STEP 20550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400026770000020405ac01010402
+ENTRY_END
+
+STEP 20560 QUERY
+ENTRY_BEGIN
+RAW
+b7b516e85010441080750000000000000000
+ENTRY_END
+
+STEP 20570 QUERY
+ENTRY_BEGIN
+RAW
+b7b516e8501844102fb1000000943310000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76a403c48ea0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 20580 QUERY
+ENTRY_BEGIN
+RAW
+b7b516f6501144027fde0000000000000000
+ENTRY_END
+
+STEP 20590 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000603d0000020405ac01010402
+ENTRY_END
+
+STEP 20600 QUERY
+ENTRY_BEGIN
+RAW
+b7b516f7501044027fdd0000000000000000
+ENTRY_END
+
+STEP 20610 QUERY
+ENTRY_BEGIN
+RAW
+b7b59189501044103f9a0000000000000000
+ENTRY_END
+
+STEP 20620 QUERY
+ENTRY_BEGIN
+RAW
+b7b59189501844103ef200000094e3f4000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76a403c48ea0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 20630 QUERY
+ENTRY_BEGIN
+RAW
+b7b59197501144023f030000000000000000
+ENTRY_END
+
+STEP 20640 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400004800000020405ac01010402
+ENTRY_END
+
+STEP 20650 QUERY
+ENTRY_BEGIN
+RAW
+b7b59198501044023f020000000000000000
+ENTRY_END
+
+STEP 20660 QUERY
+ENTRY_BEGIN
+RAW
+b7b677b150104410fdb30000000000000000
+ENTRY_END
+
+STEP 20670 QUERY
+ENTRY_BEGIN
+RAW
+b7b677b150184410f59300000094eb6c000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76a403c48ea0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 20680 QUERY
+ENTRY_BEGIN
+RAW
+b7b677bf50114402fd1c0000000000000000
+ENTRY_END
+
+STEP 20690 QUERY
+ENTRY_BEGIN
+RAW
+b7b677c050104402fd1b0000000000000000
+ENTRY_END
+
+STEP 20700 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f20a0000020405b401010402
+ENTRY_END
+
+STEP 20710 QUERY
+ENTRY_BEGIN
+RAW
+b7b8ebb55010447076e00000000000000000
+ENTRY_END
+
+STEP 20720 QUERY
+ENTRY_BEGIN
+RAW
+b7b8ebb550184470510a00000096c39e000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005a03677373096d6963726f736f667403636f6d003707bbc937090d490003000000374e544c4d535350000100000097b200c00a000a002d0000000d000d002000000057494e32303030534552564552323030305345525645520000
+ENTRY_END
+
+STEP 20730 QUERY
+ENTRY_BEGIN
+RAW
+b7b8ebc35011446276470000000000000000
+ENTRY_END
+
+STEP 20740 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400081a30000020405b401010402
+ENTRY_END
+
+STEP 20750 QUERY
+ENTRY_BEGIN
+RAW
+00000000700222386dc500000204057801010402
+ENTRY_END
+
+STEP 20760 QUERY
+ENTRY_BEGIN
+RAW
+b7bc37fc50102648a6740000000000000000
+ENTRY_END
+
+STEP 20770 QUERY
+ENTRY_BEGIN
+RAW
+b7bc37fc50182648d4fd0000008dc800000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcc3403c4e4300030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 20780 QUERY
+ENTRY_BEGIN
+RAW
+b7bc380a5011263aa5e40000000000000000
+ENTRY_END
+
+STEP 20790 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238873c00000204057801010402
+ENTRY_END
+
+STEP 20800 QUERY
+ENTRY_BEGIN
+RAW
+b7b8ebc45010446276460000000000000000
+ENTRY_END
+
+STEP 20810 QUERY
+ENTRY_BEGIN
+RAW
+b7bb91ca5010447060610000000000000000
+ENTRY_END
+
+STEP 20820 QUERY
+ENTRY_BEGIN
+RAW
+b7bb91ca501844700c3000000096f2fa000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d003707bbc937090d490003000000374e544c4d535350000100000097b200c00a000a002d0000000d000d002000000057494e32303030534552564552323030305345525645520000
+ENTRY_END
+
+STEP 20830 QUERY
+ENTRY_BEGIN
+RAW
+b7bc380b5010263aa5e30000000000000000
+ENTRY_END
+
+STEP 20840 QUERY
+ENTRY_BEGIN
+RAW
+b7bcf5915010264802560000000000000000
+ENTRY_END
+
+STEP 20850 QUERY
+ENTRY_BEGIN
+RAW
+b7bcf5915018264891e00000008d6800000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcc3403c4e4300030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 20860 QUERY
+ENTRY_BEGIN
+RAW
+b7bcf59f5011263a01c60000000000000000
+ENTRY_END
+
+STEP 20870 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238650600000204057801010402
+ENTRY_END
+
+STEP 20880 QUERY
+ENTRY_BEGIN
+RAW
+b7bcf5a05010263a01c50000000000000000
+ENTRY_END
+
+STEP 20890 QUERY
+ENTRY_BEGIN
+RAW
+b7bd858150102648502f0000000000000000
+ENTRY_END
+
+STEP 20900 QUERY
+ENTRY_BEGIN
+RAW
+b7bd8581501826483fba0000008d0800000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcc3403c4e4300030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 20910 QUERY
+ENTRY_BEGIN
+RAW
+b7bd858f5011263a4f9f0000000000000000
+ENTRY_END
+
+STEP 20920 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001a7a00000204056401010402
+ENTRY_END
+
+STEP 20930 QUERY
+ENTRY_BEGIN
+RAW
+b7bd85905010263a4f9e0000000000000000
+ENTRY_END
+
+STEP 20940 QUERY
+ENTRY_BEGIN
+RAW
+b7bb91d8501144625fc80000000000000000
+ENTRY_END
+
+STEP 20950 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007ebd0000020405b401010402
+ENTRY_END
+
+STEP 20960 QUERY
+ENTRY_BEGIN
+RAW
+b7be6078501040b02df70000000000000000
+ENTRY_END
+
+STEP 20970 QUERY
+ENTRY_BEGIN
+RAW
+b7be6078501840b0aa3800000092fb2e000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afbc4403c4d440003000000334e544c4d535350000100000097b200e0080008002b0000000b000b00200000005342534d4f4e53494e41494d4f4e53494e41490000
+ENTRY_END
+
+STEP 20980 QUERY
+ENTRY_BEGIN
+RAW
+b7be6086501140a22d620000000000000000
+ENTRY_END
+
+STEP 20990 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ced900000204056401010402
+ENTRY_END
+
+STEP 21000 QUERY
+ENTRY_BEGIN
+RAW
+b7be6087501040a22d610000000000000000
+ENTRY_END
+
+STEP 21010 QUERY
+ENTRY_BEGIN
+RAW
+b7bf9d98501040b0a5350000000000000000
+ENTRY_END
+
+STEP 21020 QUERY
+ENTRY_BEGIN
+RAW
+b7bf9d98501840b0870a00000092969c000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afbc4403c4d440003000000334e544c4d535350000100000097b200e0080008002b0000000b000b00200000005342534d4f4e53494e41494d4f4e53494e41490000
+ENTRY_END
+
+STEP 21030 QUERY
+ENTRY_BEGIN
+RAW
+b7bf9da6501140a2a4a00000000000000000
+ENTRY_END
+
+STEP 21040 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000319000000204056401010402
+ENTRY_END
+
+STEP 21050 QUERY
+ENTRY_BEGIN
+RAW
+b7bf9da7501040a2a49f0000000000000000
+ENTRY_END
+
+STEP 21060 QUERY
+ENTRY_BEGIN
+RAW
+b7bb91d9501044625fc70000000000000000
+ENTRY_END
+
+STEP 21070 QUERY
+ENTRY_BEGIN
+RAW
+b7bf057450104470e9cd0000000000000000
+ENTRY_END
+
+STEP 21080 QUERY
+ENTRY_BEGIN
+RAW
+b7bf057450184470c0c800000096c7ce000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005a03677373096d6963726f736f667403636f6d003707bbc937090d490003000000374e544c4d535350000100000097b200c00a000a002d0000000d000d002000000057494e32303030534552564552323030305345525645520000
+ENTRY_END
+
+STEP 21090 QUERY
+ENTRY_BEGIN
+RAW
+b7c1a905501040b0fc7c0000000000000000
+ENTRY_END
+
+STEP 21100 QUERY
+ENTRY_BEGIN
+RAW
+b7c1a905501840b0a16400000092d389000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afbc4403c4d440003000000334e544c4d535350000100000097b200e0080008002b0000000b000b00200000005342534d4f4e53494e41494d4f4e53494e41490000
+ENTRY_END
+
+STEP 21110 QUERY
+ENTRY_BEGIN
+RAW
+b7c1a913501140a2fbe70000000000000000
+ENTRY_END
+
+STEP 21120 QUERY
+ENTRY_BEGIN
+RAW
+b7c1a914501040a2fbe60000000000000000
+ENTRY_END
+
+STEP 21130 QUERY
+ENTRY_BEGIN
+RAW
+b7bf058250114462e9340000000000000000
+ENTRY_END
+
+STEP 21140 QUERY
+ENTRY_BEGIN
+RAW
+b7bf058350104462e9330000000000000000
+ENTRY_END
+
+;STEP 21150 QUERY
+;ENTRY_BEGIN
+;RAW
+;2c2a01000001000000000000056b6f726e6f026e6c00000f000100
+;ENTRY_END
+
+STEP 21160 QUERY
+ENTRY_BEGIN
+RAW
+b7b2120c5018faf03b6f0000008d7b00000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd3d403c4ebd00030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 21170 QUERY
+ENTRY_BEGIN
+RAW
+b7b2120c5018faf03b6f0000008d7b00000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd3d403c4ebd00030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 21180 QUERY
+ENTRY_BEGIN
+RAW
+b7b2121a5011fae2ed3b0000000000000000
+ENTRY_END
+
+STEP 21190 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf072e80000020405b401010402
+ENTRY_END
+
+STEP 21200 QUERY
+ENTRY_BEGIN
+RAW
+b7b2121b5010fae2ed3a0000000000000000
+ENTRY_END
+
+STEP 21210 QUERY
+ENTRY_BEGIN
+RAW
+b7c35b315010faf08ca70000000000000000
+ENTRY_END
+
+STEP 21220 QUERY
+ENTRY_BEGIN
+RAW
+b7c35b315018faf0d04b0000008d8000000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd40403c4ec000030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 21230 QUERY
+ENTRY_BEGIN
+RAW
+b7c35b3f5011fae28c170000000000000000
+ENTRY_END
+
+STEP 21240 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf033120000020405b401010402
+ENTRY_END
+
+STEP 21250 QUERY
+ENTRY_BEGIN
+RAW
+b7c35b405010fae28c160000000000000000
+ENTRY_END
+
+STEP 21260 QUERY
+ENTRY_BEGIN
+RAW
+b7c5cd275010faf0dad80000000000000000
+ENTRY_END
+
+STEP 21270 QUERY
+ENTRY_BEGIN
+RAW
+b7c5cd275018faf0a87c0000008df600000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afd40403c4ec000030000002e4e544c4d535350000100000097b208e0070007002700000007000700200000005245545f4653315245544152434f0000
+ENTRY_END
+
+STEP 21280 QUERY
+ENTRY_BEGIN
+RAW
+b7c5cd355011fae2da480000000000000000
+ENTRY_END
+
+STEP 21290 QUERY
+ENTRY_BEGIN
+RAW
+b7c5cd365010fae2da470000000000000000
+ENTRY_END
+
+STEP 21300 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000de6f0000020405ac01010402
+ENTRY_END
+
+STEP 21310 QUERY
+ENTRY_BEGIN
+RAW
+b7c6575050104410f7f40000000000000000
+ENTRY_END
+
+STEP 21320 QUERY
+ENTRY_BEGIN
+RAW
+b7c6575050184410ed5700000094e8e8000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76c403c48ec0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 21330 QUERY
+ENTRY_BEGIN
+RAW
+b7c6575e50114402f75d0000000000000000
+ENTRY_END
+
+STEP 21340 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f46f0000020405ac01010402
+ENTRY_END
+
+STEP 21350 QUERY
+ENTRY_BEGIN
+RAW
+b7c6575f50104402f75c0000000000000000
+ENTRY_END
+
+STEP 21360 QUERY
+ENTRY_BEGIN
+RAW
+b7c7018a5010441063ba0000000000000000
+ENTRY_END
+
+STEP 21370 QUERY
+ENTRY_BEGIN
+RAW
+b7c7018a5018441052a600000094f060000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76c403c48ec0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 21380 QUERY
+ENTRY_BEGIN
+RAW
+b7c701985011440263230000000000000000
+ENTRY_END
+
+STEP 21390 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400010880000020405ac01010402
+ENTRY_END
+
+STEP 21400 QUERY
+ENTRY_BEGIN
+RAW
+b7c701995010440263220000000000000000
+ENTRY_END
+
+STEP 21410 QUERY
+ENTRY_BEGIN
+RAW
+b7c7ca4a50104410b7110000000000000000
+ENTRY_END
+
+STEP 21420 QUERY
+ENTRY_BEGIN
+RAW
+b7c7ca4a50184410f51900000094a144000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af76c403c48ec0003000000354e544c4d535350000100000097b200c00f000f002600000006000600200000004e49454c53314b52454e53434f4e53554c54414e430000
+ENTRY_END
+
+STEP 21430 QUERY
+ENTRY_BEGIN
+RAW
+b7c7ca5850114402b67a0000000000000000
+ENTRY_END
+
+STEP 21440 QUERY
+ENTRY_BEGIN
+RAW
+b7c7ca5950104402b6790000000000000000
+ENTRY_END
+
+STEP 21450 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ced600000204053401010402
+ENTRY_END
+
+STEP 21460 QUERY
+ENTRY_BEGIN
+RAW
+b7c8652e50104470d9a30000000000000000
+ENTRY_END
+
+STEP 21470 QUERY
+ENTRY_BEGIN
+RAW
+b7c8652e50184470a322000000942da6000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03de403c555e0003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 21480 QUERY
+ENTRY_BEGIN
+RAW
+b7c8653c50114462d90c0000000000000000
+ENTRY_END
+
+STEP 21490 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d21800000204053401010402
+ENTRY_END
+
+STEP 21500 QUERY
+ENTRY_BEGIN
+RAW
+b7c8653d50104462d90b0000000000000000
+ENTRY_END
+
+STEP 21510 QUERY
+ENTRY_BEGIN
+RAW
+b7cad8d15010447069400000000000000000
+ENTRY_END
+
+STEP 21520 QUERY
+ENTRY_BEGIN
+RAW
+b7cad8d150184470d679000000948aec000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03de403c555e0003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 21530 QUERY
+ENTRY_BEGIN
+RAW
+b7cad8df5011446268a90000000000000000
+ENTRY_END
+
+STEP 21540 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c1d700000204053401010402
+ENTRY_END
+
+STEP 21550 QUERY
+ENTRY_BEGIN
+RAW
+b7cad8e05010446268a80000000000000000
+ENTRY_END
+
+STEP 21560 QUERY
+ENTRY_BEGIN
+RAW
+b7cbb4fa501044707cd50000000000000000
+ENTRY_END
+
+STEP 21570 QUERY
+ENTRY_BEGIN
+RAW
+b7cbb4fa50184470aa8c00000094ca6e000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403b03de403c555e0003000000354e544c4d535350000100000097b208e00f000f0026000000060006002000000053455256455256414e44494a4b43534144564f43410000
+ENTRY_END
+
+STEP 21580 QUERY
+ENTRY_BEGIN
+RAW
+b7cbb508501144627c3e0000000000000000
+ENTRY_END
+
+STEP 21590 QUERY
+ENTRY_BEGIN
+RAW
+b7cbb509501044627c3d0000000000000000
+ENTRY_END
+
+STEP 21600 QUERY
+ENTRY_BEGIN
+RAW
+163800000001000000000000076f62646e772d6e026e6c00000f000100
+ENTRY_END
+
+STEP 21610 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ff160000020405b401010402
+ENTRY_END
+
+STEP 21620 QUERY
+ENTRY_BEGIN
+RAW
+b7cebe2650104470b1650000000000000000
+ENTRY_END
+
+STEP 21630 QUERY
+ENTRY_BEGIN
+RAW
+b7cebe2650184470d07c0000008c6780000000010001000000000f313039393531313632373739342d330000f900010f313039393531313632373739342d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc34403c4db400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 21640 QUERY
+ENTRY_BEGIN
+RAW
+b7cebe3450114462b0d60000000000000000
+ENTRY_END
+
+STEP 21650 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000734a0000020405b401010402
+ENTRY_END
+
+STEP 21660 QUERY
+ENTRY_BEGIN
+RAW
+b7cebe3550104462b0d50000000000000000
+ENTRY_END
+
+STEP 21670 QUERY
+ENTRY_BEGIN
+RAW
+b7cf52485010447091760000000000000000
+ENTRY_END
+
+STEP 21680 QUERY
+ENTRY_BEGIN
+RAW
+b7cf524850184470b6f10000008c621d000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc34403c4db400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 21690 QUERY
+ENTRY_BEGIN
+RAW
+3614000000010000000000000663617374656c026e6c00000f0001c00c000f0001
+ENTRY_END
+
+STEP 21700 QUERY
+ENTRY_BEGIN
+RAW
+2618000000010000000000000663617374656c026e6c00000f0001c00c000f0001
+ENTRY_END
+
+STEP 21710 QUERY
+ENTRY_BEGIN
+RAW
+3e24000000010000000000000663617374656c026e6c00000f0001c00c000f0001
+ENTRY_END
+
+STEP 21720 QUERY
+ENTRY_BEGIN
+RAW
+b7cf52565011446290e70000000000000000
+ENTRY_END
+
+STEP 21730 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400058000000020405b401010402
+ENTRY_END
+
+STEP 21740 QUERY
+ENTRY_BEGIN
+RAW
+262a000000010000000000000663617374656c026e6c00000f0001c00c000f0001
+ENTRY_END
+
+STEP 21750 QUERY
+ENTRY_BEGIN
+RAW
+3e36000000010000000000000663617374656c026e6c00000f0001c00c000f0001
+ENTRY_END
+
+STEP 21760 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400047b900000204056401010402
+ENTRY_END
+
+STEP 21770 QUERY
+ENTRY_BEGIN
+RAW
+b7cf52575010446290e60000000000000000
+ENTRY_END
+
+STEP 21780 QUERY
+ENTRY_BEGIN
+RAW
+b7d1f65650104470d21b0000000000000000
+ENTRY_END
+
+STEP 21790 QUERY
+ENTRY_BEGIN
+RAW
+3654000000010000000000000663617374656c026e6c0000010001c00c00010001
+ENTRY_END
+
+STEP 21800 QUERY
+ENTRY_BEGIN
+RAW
+b7d1f656501844703f370000008c1a7d000000010001000000000f313039393531313632373739342d320000f900010f313039393531313632373739342d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afc34403c4db400030000002d4e544c4d535350000100000097b200c0070007002600000006000600200000005345525645524d4b424144414d0000
+ENTRY_END
+
+STEP 21810 QUERY
+ENTRY_BEGIN
+RAW
+b7d27a61501040b041390000000000000000
+ENTRY_END
+
+STEP 21820 QUERY
+ENTRY_BEGIN
+RAW
+b7d1f66450114462d18c0000000000000000
+ENTRY_END
+
+STEP 21830 QUERY
+ENTRY_BEGIN
+RAW
+b7d27a61501840b0204f00000087126e000000010001000000000e3939363433323431323639302d330000f900010e3939363433323431323639302d330000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afba9403c4d2900030000002a4e544c4d535350000100000097b200e003000300270000000700070020000000545249455354454243430000
+ENTRY_END
+
+STEP 21840 QUERY
+ENTRY_BEGIN
+RAW
+b7d27a6f501140a240af0000000000000000
+ENTRY_END
+
+STEP 21850 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ddcf00000204056401010402
+ENTRY_END
+
+STEP 21860 QUERY
+ENTRY_BEGIN
+RAW
+b7d1f66550104462d18b0000000000000000
+ENTRY_END
+
+STEP 21870 QUERY
+ENTRY_BEGIN
+RAW
+b7d37167501040b0e0480000000000000000
+ENTRY_END
+
+STEP 21880 QUERY
+ENTRY_BEGIN
+RAW
+b7d27a70501040a240ae0000000000000000
+ENTRY_END
+
+STEP 21890 QUERY
+ENTRY_BEGIN
+RAW
+b7d37167501840b09f7f00000087344d000000010001000000000e3939363433323431323639302d320000f900010e3939363433323431323639302d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afba9403c4d2900030000002a4e544c4d535350000100000097b200e003000300270000000700070020000000545249455354454243430000
+ENTRY_END
+
+STEP 21900 QUERY
+ENTRY_BEGIN
+RAW
+b7d37175501140a2dfbe0000000000000000
+ENTRY_END
+
+STEP 21910 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d32800000204056401010402
+ENTRY_END
+
+STEP 21920 QUERY
+ENTRY_BEGIN
+RAW
+b7d37176501040a2dfbd0000000000000000
+ENTRY_END
+
+STEP 21930 QUERY
+ENTRY_BEGIN
+RAW
+b7d40c73501040b03a950000000000000000
+ENTRY_END
+
+STEP 21940 QUERY
+ENTRY_BEGIN
+RAW
+b7d40c73501840b0d7ec00000087562c000000010001000000000e3939363433323431323639302d320000f900010e3939363433323431323639302d320000f900ff00000000004d03677373096d6963726f736f667403636f6d00403afba9403c4d2900030000002a4e544c4d535350000100000097b200e003000300270000000700070020000000545249455354454243430000
+ENTRY_END
+
+STEP 21950 QUERY
+ENTRY_BEGIN
+RAW
+b7d40c81501140a23a0b0000000000000000
+ENTRY_END
+
+STEP 21960 QUERY
+ENTRY_BEGIN
+RAW
+b7d40c82501040a23a0a0000000000000000
+ENTRY_END
+
+STEP 21970 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e2920000020405b401010402
+ENTRY_END
+
+STEP 21980 QUERY
+ENTRY_BEGIN
+RAW
+b7d4ac7950104470a6880000000000000000
+ENTRY_END
+
+STEP 21990 QUERY
+ENTRY_BEGIN
+RAW
+b7d4ac79501844709f9c0000008a49f8000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afac0403c4c4000030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004c4150544f50315a50444550330000
+ENTRY_END
+
+STEP 22000 QUERY
+ENTRY_BEGIN
+RAW
+b7d4ac8750114462a5fb0000000000000000
+ENTRY_END
+
+STEP 22010 QUERY
+ENTRY_BEGIN
+RAW
+b7d4ac8850104462a5fa0000000000000000
+ENTRY_END
+
+STEP 22020 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e45c0000020405b401010402
+ENTRY_END
+
+STEP 22030 QUERY
+ENTRY_BEGIN
+RAW
+b7d5987150104470bc590000000000000000
+ENTRY_END
+
+STEP 22040 QUERY
+ENTRY_BEGIN
+RAW
+b7d598715018447072e10000008a8e84000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afac0403c4c4000030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004c4150544f50315a50444550330000
+ENTRY_END
+
+STEP 22050 QUERY
+ENTRY_BEGIN
+RAW
+b7d5987f50114462bbcc0000000000000000
+ENTRY_END
+
+STEP 22060 QUERY
+ENTRY_BEGIN
+RAW
+b7d5988050104462bbcb0000000000000000
+ENTRY_END
+
+STEP 22070 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000630d0000020405b401010402
+ENTRY_END
+
+STEP 22080 QUERY
+ENTRY_BEGIN
+RAW
+b7d7d13f50104470023a0000000000000000
+ENTRY_END
+
+STEP 22090 QUERY
+ENTRY_BEGIN
+RAW
+b7d7d13f50184470f3c90000008a537c000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afac0403c4c4000030000002d4e544c4d535350000100000097b200e0060006002700000007000700200000004c4150544f50315a50444550330000
+ENTRY_END
+
+STEP 22100 QUERY
+ENTRY_BEGIN
+RAW
+b7d7d14d5011446201ad0000000000000000
+ENTRY_END
+
+STEP 22110 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400068980000020405b401010402
+ENTRY_END
+
+STEP 22120 QUERY
+ENTRY_BEGIN
+RAW
+b7d9fb5b50104470dda60000000000000000
+ENTRY_END
+
+STEP 22130 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf005e600000204057a01010402
+ENTRY_END
+
+STEP 22140 QUERY
+ENTRY_BEGIN
+RAW
+b7d9fb5b501844704b8a0000008f928b000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afead403c502d0003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22150 QUERY
+ENTRY_BEGIN
+RAW
+b7dae9b25010fbec8fd60000000000000000
+ENTRY_END
+
+STEP 22160 QUERY
+ENTRY_BEGIN
+RAW
+b7d9fb6950114462dd140000000000000000
+ENTRY_END
+
+STEP 22170 QUERY
+ENTRY_BEGIN
+RAW
+b7dae9b25018fbec4c120000008f6809000000010001000000000f313033303739323135313035382d330000f900010f313033303739323135313035382d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403b072a403c58aa0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 22180 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006cef0000020405b401010402
+ENTRY_END
+
+STEP 22190 QUERY
+ENTRY_BEGIN
+RAW
+b7d9fb6a50104462dd130000000000000000
+ENTRY_END
+
+STEP 22200 QUERY
+ENTRY_BEGIN
+RAW
+b7dae9c05011fbde8f440000000000000000
+ENTRY_END
+
+STEP 22210 QUERY
+ENTRY_BEGIN
+RAW
+b7db85ea50104470576d0000000000000000
+ENTRY_END
+
+STEP 22220 QUERY
+ENTRY_BEGIN
+RAW
+b7db85ea501844707ce10000008fd3fb000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afeb1403c50310003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22230 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b33800000204057a01010402
+ENTRY_END
+
+STEP 22240 QUERY
+ENTRY_BEGIN
+RAW
+b7dae9c15010fbde8f430000000000000000
+ENTRY_END
+
+STEP 22250 QUERY
+ENTRY_BEGIN
+RAW
+b7dc2ffb5010fbecf6de0000000000000000
+ENTRY_END
+
+STEP 22260 QUERY
+ENTRY_BEGIN
+RAW
+b7db85f85011446256db0000000000000000
+ENTRY_END
+
+STEP 22270 QUERY
+ENTRY_BEGIN
+RAW
+b7dc2ffb5018fbeccd910000008f4e93000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403b072a403c58aa0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 22280 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400060bf0000020405b401010402
+ENTRY_END
+
+STEP 22290 QUERY
+ENTRY_BEGIN
+RAW
+b7dc30095011fbdef64c0000000000000000
+ENTRY_END
+
+STEP 22300 QUERY
+ENTRY_BEGIN
+RAW
+b7db85f95010446256da0000000000000000
+ENTRY_END
+
+STEP 22310 QUERY
+ENTRY_BEGIN
+RAW
+b7dcf17a50104470dfab0000000000000000
+ENTRY_END
+
+STEP 22320 QUERY
+ENTRY_BEGIN
+RAW
+b7dcf17a501844707aa10000008f5e7a000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afeb1403c50310003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22330 QUERY
+ENTRY_BEGIN
+RAW
+b7dcf18850114462df190000000000000000
+ENTRY_END
+
+STEP 22340 QUERY
+ENTRY_BEGIN
+RAW
+b7dcf18950104462df180000000000000000
+ENTRY_END
+
+STEP 22350 QUERY
+ENTRY_BEGIN
+RAW
+b7dc300a5010fbdef64b0000000000000000
+ENTRY_END
+
+STEP 22360 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f7bc00000204057a01010402
+ENTRY_END
+
+STEP 22370 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d1bd00000204058201010402
+ENTRY_END
+
+STEP 22380 QUERY
+ENTRY_BEGIN
+RAW
+b7ddead25010fbec808a0000000000000000
+ENTRY_END
+
+STEP 22390 QUERY
+ENTRY_BEGIN
+RAW
+b7ddead25018fbec70b30000008f351d000000010001000000000f313033303739323135313035382d320000f900010f313033303739323135313035382d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403b072a403c58aa0003000000304e544c4d535350000100000097b208e00900090027000000070007002000000057494e3230303047494f504e54444f4d0000
+ENTRY_END
+
+STEP 22400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400063600000020405b401010402
+ENTRY_END
+
+STEP 22410 QUERY
+ENTRY_BEGIN
+RAW
+b7de811e50104218c32a0000000000000000
+ENTRY_END
+
+STEP 22420 QUERY
+ENTRY_BEGIN
+RAW
+b7de811e50184218042a0000008bafdf000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf7403c4f7700030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22430 QUERY
+ENTRY_BEGIN
+RAW
+b7ddeae05011fbde7ff80000000000000000
+ENTRY_END
+
+STEP 22440 QUERY
+ENTRY_BEGIN
+RAW
+b7de812c5011420ac29c0000000000000000
+ENTRY_END
+
+STEP 22450 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001a6800000204058201010402
+ENTRY_END
+
+STEP 22460 QUERY
+ENTRY_BEGIN
+RAW
+b7df5ab25010447079120000000000000000
+ENTRY_END
+
+STEP 22470 QUERY
+ENTRY_BEGIN
+RAW
+b7df5ab2501844709b1b0000008fd665000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afeb1403c50310003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22480 QUERY
+ENTRY_BEGIN
+RAW
+b7de812d5010420ac29b0000000000000000
+ENTRY_END
+
+STEP 22490 QUERY
+ENTRY_BEGIN
+RAW
+b7e193f550104218f8fa0000000000000000
+ENTRY_END
+
+STEP 22500 QUERY
+ENTRY_BEGIN
+RAW
+b7e193f55018421846bf0000008ba41b000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf7403c4f7700030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22510 QUERY
+ENTRY_BEGIN
+RAW
+b7ddeae15010fbde7ff70000000000000000
+ENTRY_END
+
+STEP 22520 QUERY
+ENTRY_BEGIN
+RAW
+b7e194035011420af86c0000000000000000
+ENTRY_END
+
+STEP 22530 QUERY
+ENTRY_BEGIN
+RAW
+b7df5ac05011446278800000000000000000
+ENTRY_END
+
+STEP 22540 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000f3900000204058201010402
+ENTRY_END
+
+STEP 22550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400079d00000020405b401010402
+ENTRY_END
+
+STEP 22560 QUERY
+ENTRY_BEGIN
+RAW
+b7e194045010420af86b0000000000000000
+ENTRY_END
+
+STEP 22570 QUERY
+ENTRY_BEGIN
+RAW
+b7e2188c5010421869340000000000000000
+ENTRY_END
+
+STEP 22580 QUERY
+ENTRY_BEGIN
+RAW
+b7df5ac150104462787f0000000000000000
+ENTRY_END
+
+STEP 22590 QUERY
+ENTRY_BEGIN
+RAW
+b7e2188c501842183cdb0000008b1e39000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf7403c4f7700030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22600 QUERY
+ENTRY_BEGIN
+RAW
+b7e304b250104470e57e0000000000000000
+ENTRY_END
+
+STEP 22610 QUERY
+ENTRY_BEGIN
+RAW
+b7e304b25018447021fa0000008fbcf4000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afeb1403c50310003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22620 QUERY
+ENTRY_BEGIN
+RAW
+b7e2189a5011420a68a60000000000000000
+ENTRY_END
+
+STEP 22630 QUERY
+ENTRY_BEGIN
+RAW
+b7e304c050114462e4ec0000000000000000
+ENTRY_END
+
+STEP 22640 QUERY
+ENTRY_BEGIN
+RAW
+b7e2189b5010420a68a50000000000000000
+ENTRY_END
+
+STEP 22650 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400091100000020405b401010402
+ENTRY_END
+
+STEP 22660 QUERY
+ENTRY_BEGIN
+RAW
+b7e304c150104462e4eb0000000000000000
+ENTRY_END
+
+STEP 22670 QUERY
+ENTRY_BEGIN
+RAW
+b7e3c233501044703f3d0000000000000000
+ENTRY_END
+
+STEP 22680 QUERY
+ENTRY_BEGIN
+RAW
+b7e3c23350184470d6fa0000008f61b2000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afeb1403c50310003000000304e544c4d535350000100000097b208e009000900270000000700070020000000425241564f31314a4a432d425241564f0000
+ENTRY_END
+
+STEP 22690 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bdff00000204058201010402
+ENTRY_END
+
+STEP 22700 QUERY
+ENTRY_BEGIN
+RAW
+b7e3c241501144623eab0000000000000000
+ENTRY_END
+
+STEP 22710 QUERY
+ENTRY_BEGIN
+RAW
+b7e443e550104218ec9f0000000000000000
+ENTRY_END
+
+STEP 22720 QUERY
+ENTRY_BEGIN
+RAW
+b7e443e550184218d6cd0000008b06b1000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf7403c4f7700030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22730 QUERY
+ENTRY_BEGIN
+RAW
+b7e443f35011420aec110000000000000000
+ENTRY_END
+
+STEP 22740 QUERY
+ENTRY_BEGIN
+RAW
+b7e3c242501044623eaa0000000000000000
+ENTRY_END
+
+STEP 22750 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d9ff00000204058201010402
+ENTRY_END
+
+STEP 22760 QUERY
+ENTRY_BEGIN
+RAW
+b7e443f45010420aec100000000000000000
+ENTRY_END
+
+STEP 22770 QUERY
+ENTRY_BEGIN
+RAW
+b7e5104a501042183c3a0000000000000000
+ENTRY_END
+
+STEP 22780 QUERY
+ENTRY_BEGIN
+RAW
+b7e5104a501842182f400000008bfed9000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf7403c4f7700030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22790 QUERY
+ENTRY_BEGIN
+RAW
+b7e510585011420a3bac0000000000000000
+ENTRY_END
+
+STEP 22800 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000818300000204058201010402
+ENTRY_END
+
+STEP 22810 QUERY
+ENTRY_BEGIN
+RAW
+b7e510595010420a3bab0000000000000000
+ENTRY_END
+
+STEP 22820 QUERY
+ENTRY_BEGIN
+RAW
+b7e5f01a5010421803ed0000000000000000
+ENTRY_END
+
+STEP 22830 QUERY
+ENTRY_BEGIN
+RAW
+b7e5f01a5018421838b30000008bbb19000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf8403c4f7800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22840 QUERY
+ENTRY_BEGIN
+RAW
+b7e5f0285011420a035f0000000000000000
+ENTRY_END
+
+STEP 22850 QUERY
+ENTRY_BEGIN
+RAW
+b7e5f0295010420a035e0000000000000000
+ENTRY_END
+
+STEP 22860 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400094360000020405b401010402
+ENTRY_END
+
+STEP 22870 QUERY
+ENTRY_BEGIN
+RAW
+b7e6be1850104470467b0000000000000000
+ENTRY_END
+
+STEP 22880 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007ffe00000204058201010402
+ENTRY_END
+
+STEP 22890 QUERY
+ENTRY_BEGIN
+RAW
+b7e7a1a25010421850de0000000000000000
+ENTRY_END
+
+STEP 22900 QUERY
+ENTRY_BEGIN
+RAW
+b7e7a1a2501842181a360000008b2587000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf8403c4f7800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22910 QUERY
+ENTRY_BEGIN
+RAW
+b7e6be185018447063d90000008c6106000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd19403c4e9900030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 22920 QUERY
+ENTRY_BEGIN
+RAW
+b7e7a1b05011420a50500000000000000000
+ENTRY_END
+
+STEP 22930 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d0c800000204058201010402
+ENTRY_END
+
+STEP 22940 QUERY
+ENTRY_BEGIN
+RAW
+b7e6be265011446245ec0000000000000000
+ENTRY_END
+
+STEP 22950 QUERY
+ENTRY_BEGIN
+RAW
+b7e7a1b15010420a504f0000000000000000
+ENTRY_END
+
+STEP 22960 QUERY
+ENTRY_BEGIN
+RAW
+b7e8222b50104218211f0000000000000000
+ENTRY_END
+
+STEP 22970 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a6450000020405b401010402
+ENTRY_END
+
+STEP 22980 QUERY
+ENTRY_BEGIN
+RAW
+b7e8222b50184218f34f0000008b1daf000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf8403c4f7800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 22990 QUERY
+ENTRY_BEGIN
+RAW
+b7e822395011420a20910000000000000000
+ENTRY_END
+
+STEP 23000 QUERY
+ENTRY_BEGIN
+RAW
+b7e6be275010446245eb0000000000000000
+ENTRY_END
+
+STEP 23010 QUERY
+ENTRY_BEGIN
+RAW
+b7e8b9fe501044705ca20000000000000000
+ENTRY_END
+
+STEP 23020 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008ecb00000204058201010402
+ENTRY_END
+
+STEP 23030 QUERY
+ENTRY_BEGIN
+RAW
+b7e8223a5010420a20900000000000000000
+ENTRY_END
+
+STEP 23040 QUERY
+ENTRY_BEGIN
+RAW
+b7e96bb55010421895960000000000000000
+ENTRY_END
+
+STEP 23050 QUERY
+ENTRY_BEGIN
+RAW
+b7e8b9fe50184470c0470000008c1bc0000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd19403c4e9900030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 23060 QUERY
+ENTRY_BEGIN
+RAW
+b7e96bb5501842187c9e0000008b08d8000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afdf8403c4f7800030000002c4e544c4d535350000100000097b200c006000600260000000600060020000000534552564552524f4d4d454c0000
+ENTRY_END
+
+STEP 23070 QUERY
+ENTRY_BEGIN
+RAW
+b7e96bc35011420a95080000000000000000
+ENTRY_END
+
+STEP 23080 QUERY
+ENTRY_BEGIN
+RAW
+b7e96bc45010420a95070000000000000000
+ENTRY_END
+
+STEP 23090 QUERY
+ENTRY_BEGIN
+RAW
+b7e8ba0c501144625c130000000000000000
+ENTRY_END
+
+STEP 23100 QUERY
+ENTRY_BEGIN
+RAW
+63097b1c50040000f11a0000000000000000
+ENTRY_END
+
+STEP 23110 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ec7e0000020405b401010402
+ENTRY_END
+
+STEP 23120 QUERY
+ENTRY_BEGIN
+RAW
+b7e8ba0d501044625c120000000000000000
+ENTRY_END
+
+STEP 23130 QUERY
+ENTRY_BEGIN
+RAW
+b7ec28565010447034800000000000000000
+ENTRY_END
+
+STEP 23140 QUERY
+ENTRY_BEGIN
+RAW
+b7ec285650184470d6a40000008cdd40000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd19403c4e9900030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 23150 QUERY
+ENTRY_BEGIN
+RAW
+b7ec28645011446233f10000000000000000
+ENTRY_END
+
+STEP 23160 QUERY
+ENTRY_BEGIN
+RAW
+b7ec28655010446233f00000000000000000
+ENTRY_END
+
+STEP 23170 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0032000000204056401010402
+ENTRY_END
+
+STEP 23180 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf043bb0000020405b401010402
+ENTRY_END
+
+STEP 23190 QUERY
+ENTRY_BEGIN
+RAW
+b7eca26f5010fd5cd2bb0000000000000000
+ENTRY_END
+
+STEP 23200 QUERY
+ENTRY_BEGIN
+RAW
+b7eca26f5018fd5c445900000092c3e6000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5d403c4fdd0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23210 QUERY
+ENTRY_BEGIN
+RAW
+b7eca27d5011fd4ed2260000000000000000
+ENTRY_END
+
+STEP 23220 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf00b5800000204056401010402
+ENTRY_END
+
+STEP 23230 QUERY
+ENTRY_BEGIN
+RAW
+b7eca27e5010fd4ed2250000000000000000
+ENTRY_END
+
+STEP 23240 QUERY
+ENTRY_BEGIN
+RAW
+b7ee6dad5010fd5c0fb40000000000000000
+ENTRY_END
+
+STEP 23250 QUERY
+ENTRY_BEGIN
+RAW
+b7ee6dad5018fd5c0976000000923cc3000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5d403c4fdd0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23260 QUERY
+ENTRY_BEGIN
+RAW
+b7ee6dbb5011fd4e0f1f0000000000000000
+ENTRY_END
+
+STEP 23270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0682600000204056401010402
+ENTRY_END
+
+STEP 23280 QUERY
+ENTRY_BEGIN
+RAW
+b7ee6dbc5010fd4e0f1e0000000000000000
+ENTRY_END
+
+STEP 23290 QUERY
+ENTRY_BEGIN
+RAW
+b7ef54e85010fd5c85460000000000000000
+ENTRY_END
+
+STEP 23300 QUERY
+ENTRY_BEGIN
+RAW
+b7ef54e85018fd5c2cde000000928ced000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5e403c4fde0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23310 QUERY
+ENTRY_BEGIN
+RAW
+b7ef54f65011fd4e84b10000000000000000
+ENTRY_END
+
+STEP 23320 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000bd400000020405b401010402
+ENTRY_END
+
+STEP 23330 QUERY
+ENTRY_BEGIN
+RAW
+b7ef54f75010fd4e84b00000000000000000
+ENTRY_END
+
+STEP 23340 QUERY
+ENTRY_BEGIN
+RAW
+b7f00ee7501044701ead0000000000000000
+ENTRY_END
+
+STEP 23350 QUERY
+ENTRY_BEGIN
+RAW
+b7f00ee7501844705c81000000910c00000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 23360 QUERY
+ENTRY_BEGIN
+RAW
+2e4000000001000000000000076f62646e772d6e026e6c00000f000100
+ENTRY_END
+
+STEP 23370 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf020de00000204056401010402
+ENTRY_END
+
+STEP 23380 QUERY
+ENTRY_BEGIN
+RAW
+b7f00ef5501144621e190000000000000000
+ENTRY_END
+
+STEP 23390 QUERY
+ENTRY_BEGIN
+RAW
+b7f0ad405010fd5ce5a40000000000000000
+ENTRY_END
+
+STEP 23400 QUERY
+ENTRY_BEGIN
+RAW
+b7f0ad405018fd5ca524000000927404000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5e403c4fde0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23410 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400096fb0000020405b401010402
+ENTRY_END
+
+STEP 23420 QUERY
+ENTRY_BEGIN
+RAW
+b7f00ef6501044621e180000000000000000
+ENTRY_END
+
+STEP 23430 QUERY
+ENTRY_BEGIN
+RAW
+b7f0ad4e5011fd4ee50f0000000000000000
+ENTRY_END
+
+STEP 23440 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f72200000204056401010402
+ENTRY_END
+
+STEP 23450 QUERY
+ENTRY_BEGIN
+RAW
+b7f1a62250104470612b0000000000000000
+ENTRY_END
+
+STEP 23460 QUERY
+ENTRY_BEGIN
+RAW
+b7f0ad4f5010fd4ee50e0000000000000000
+ENTRY_END
+
+STEP 23470 QUERY
+ENTRY_BEGIN
+RAW
+b7f1a622501844703700000000917500000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 23480 QUERY
+ENTRY_BEGIN
+RAW
+b7f350355010fd5c18f20000000000000000
+ENTRY_END
+
+STEP 23490 QUERY
+ENTRY_BEGIN
+RAW
+b7f350355018fd5cbfda000000928d9c000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5e403c4fde0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23500 QUERY
+ENTRY_BEGIN
+RAW
+b7f1a6305011446260970000000000000000
+ENTRY_END
+
+STEP 23510 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c07900000204057801010402
+ENTRY_END
+
+STEP 23520 QUERY
+ENTRY_BEGIN
+RAW
+b7f350435011fd4e185d0000000000000000
+ENTRY_END
+
+STEP 23530 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f5eb00000204056401010402
+ENTRY_END
+
+STEP 23540 QUERY
+ENTRY_BEGIN
+RAW
+b7f3f803501041a03b5a0000000000000000
+ENTRY_END
+
+STEP 23550 QUERY
+ENTRY_BEGIN
+RAW
+b7f3f803501841a0e3ed0000008c7123000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403b00f1403c527100030000002d4e544c4d535350000100000097b208e00700070026000000060006002000000049434441544149432d5445414d0000
+ENTRY_END
+
+STEP 23560 QUERY
+ENTRY_BEGIN
+RAW
+b7f350445010fd4e185c0000000000000000
+ENTRY_END
+
+STEP 23570 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400071960000020405b401010402
+ENTRY_END
+
+STEP 23580 QUERY
+ENTRY_BEGIN
+RAW
+b7f3f811501141923acb0000000000000000
+ENTRY_END
+
+STEP 23590 QUERY
+ENTRY_BEGIN
+RAW
+b7f4c0fc5010fd5ca6f20000000000000000
+ENTRY_END
+
+STEP 23600 QUERY
+ENTRY_BEGIN
+RAW
+b7f4c0fc5018fd5ca5cf0000009235a8000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afe5e403c4fde0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a00200000005044435347524156454e4f425347524156454e0000
+ENTRY_END
+
+STEP 23610 QUERY
+ENTRY_BEGIN
+RAW
+b7f1a6315010446260960000000000000000
+ENTRY_END
+
+STEP 23620 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400048b30000020405b401010402
+ENTRY_END
+
+STEP 23630 QUERY
+ENTRY_BEGIN
+RAW
+b7f580c05010447061240000000000000000
+ENTRY_END
+
+STEP 23640 QUERY
+ENTRY_BEGIN
+RAW
+b7f3f812501041923aca0000000000000000
+ENTRY_END
+
+STEP 23650 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000833b00000204057801010402
+ENTRY_END
+
+STEP 23660 QUERY
+ENTRY_BEGIN
+RAW
+b7f580c050184470c704000000916300000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 23670 QUERY
+ENTRY_BEGIN
+RAW
+b7f73e35501041a0b7e60000000000000000
+ENTRY_END
+
+STEP 23680 QUERY
+ENTRY_BEGIN
+RAW
+b7f73e35501841a0aecc0000008c23d2000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b00f1403c527100030000002d4e544c4d535350000100000097b208e00700070026000000060006002000000049434441544149432d5445414d0000
+ENTRY_END
+
+STEP 23690 QUERY
+ENTRY_BEGIN
+RAW
+b7f4c10a5011fd4ea65d0000000000000000
+ENTRY_END
+
+STEP 23700 QUERY
+ENTRY_BEGIN
+RAW
+b7f580ce5011446260900000000000000000
+ENTRY_END
+
+STEP 23710 QUERY
+ENTRY_BEGIN
+RAW
+b7f67a07501044703ef90000000000000000
+ENTRY_END
+
+STEP 23720 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c9110000020405b401010402
+ENTRY_END
+
+STEP 23730 QUERY
+ENTRY_BEGIN
+RAW
+b7f73e4350114192b7570000000000000000
+ENTRY_END
+
+STEP 23740 QUERY
+ENTRY_BEGIN
+RAW
+b7f67a0750184470abcd00000091de00000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 23750 QUERY
+ENTRY_BEGIN
+RAW
+b7f580cf50104462608f0000000000000000
+ENTRY_END
+
+STEP 23760 QUERY
+ENTRY_BEGIN
+RAW
+b7f7f95250104470400b0000000000000000
+ENTRY_END
+
+STEP 23770 QUERY
+ENTRY_BEGIN
+RAW
+b7f73e4450104192b7560000000000000000
+ENTRY_END
+
+STEP 23780 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fcc200000204057801010402
+ENTRY_END
+
+STEP 23790 QUERY
+ENTRY_BEGIN
+RAW
+b7f7f9525018447060ec00000091a900000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 23800 QUERY
+ENTRY_BEGIN
+RAW
+b7f4c10b5010fd4ea65c0000000000000000
+ENTRY_END
+
+STEP 23810 QUERY
+ENTRY_BEGIN
+RAW
+b7f886a3501041a0e8fe0000000000000000
+ENTRY_END
+
+STEP 23820 QUERY
+ENTRY_BEGIN
+RAW
+b7f67a15501144623e650000000000000000
+ENTRY_END
+
+STEP 23830 QUERY
+ENTRY_BEGIN
+RAW
+b7f886a3501841a085450000008c7e71000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403b00f1403c527100030000002d4e544c4d535350000100000097b208e00700070026000000060006002000000049434441544149432d5445414d0000
+ENTRY_END
+
+STEP 23840 QUERY
+ENTRY_BEGIN
+RAW
+b7f7f960501144623f770000000000000000
+ENTRY_END
+
+STEP 23850 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e70c0000020405b401010402
+ENTRY_END
+
+STEP 23860 QUERY
+ENTRY_BEGIN
+RAW
+b7f886b150114192e86f0000000000000000
+ENTRY_END
+
+STEP 23870 QUERY
+ENTRY_BEGIN
+RAW
+b7f7f961501044623f760000000000000000
+ENTRY_END
+
+STEP 23880 QUERY
+ENTRY_BEGIN
+RAW
+b7f886b250104192e86e0000000000000000
+ENTRY_END
+
+STEP 23890 QUERY
+ENTRY_BEGIN
+RAW
+b7f92d3c501044702a1b0000000000000000
+ENTRY_END
+
+STEP 23900 QUERY
+ENTRY_BEGIN
+RAW
+b7f92d3c5018447004fc00000091ef00000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 23910 QUERY
+ENTRY_BEGIN
+RAW
+b7f67a16501044623e640000000000000000
+ENTRY_END
+
+STEP 23920 QUERY
+ENTRY_BEGIN
+RAW
+b7f92d4a5011446229870000000000000000
+ENTRY_END
+
+STEP 23930 QUERY
+ENTRY_BEGIN
+RAW
+b7f92d4b5010446229860000000000000000
+ENTRY_END
+
+STEP 23940 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240001be000000204056401010402
+ENTRY_END
+
+STEP 23950 QUERY
+ENTRY_BEGIN
+RAW
+b7fa1fad501040b06fec0000000000000000
+ENTRY_END
+
+STEP 23960 QUERY
+ENTRY_BEGIN
+RAW
+b7fa1fad501840b0d4e20000008c8580000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403aff69403c50e900030000002d4e544c4d535350000100000097b200e007000700260000000600060020000000534552564552444556414552540000
+ENTRY_END
+
+STEP 23970 QUERY
+ENTRY_BEGIN
+RAW
+b7fa1fbb501140a26f5d0000000000000000
+ENTRY_END
+
+STEP 23980 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400033e800000204056401010402
+ENTRY_END
+
+STEP 23990 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008d7c0000020405b401010402
+ENTRY_END
+
+STEP 24000 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007e4f0000020405b401010402
+ENTRY_END
+
+STEP 24010 QUERY
+ENTRY_BEGIN
+RAW
+b7fbf06c501044700d580000000000000000
+ENTRY_END
+
+STEP 24020 QUERY
+ENTRY_BEGIN
+RAW
+b7fbf06c501844706038000000917600000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 24030 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000deaa0000020405b401010402
+ENTRY_END
+
+STEP 24040 QUERY
+ENTRY_BEGIN
+RAW
+b7fa1fbc501040a26f5c0000000000000000
+ENTRY_END
+
+STEP 24050 QUERY
+ENTRY_BEGIN
+RAW
+b7faff1c501040b0a8840000000000000000
+ENTRY_END
+
+STEP 24060 QUERY
+ENTRY_BEGIN
+RAW
+b7faff1c501840b0bffb0000008cd400000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403aff69403c50e900030000002d4e544c4d535350000100000097b200e007000700260000000600060020000000534552564552444556414552540000
+ENTRY_END
+
+STEP 24070 QUERY
+ENTRY_BEGIN
+RAW
+b7fbf07a501144620cc40000000000000000
+ENTRY_END
+
+STEP 24080 QUERY
+ENTRY_BEGIN
+RAW
+b7fcabad5010447042e90000000000000000
+ENTRY_END
+
+STEP 24090 QUERY
+ENTRY_BEGIN
+RAW
+b7fd5e2d50104470f0c30000000000000000
+ENTRY_END
+
+STEP 24100 QUERY
+ENTRY_BEGIN
+RAW
+b7fcabad50184470e1cf000000940d40000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd77403c4ef70003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24110 QUERY
+ENTRY_BEGIN
+RAW
+b7fd5e2d50184470679700000091d300000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 24120 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400001a90000020405b401010402
+ENTRY_END
+
+STEP 24130 QUERY
+ENTRY_BEGIN
+RAW
+b7faff2a501140a2a7f50000000000000000
+ENTRY_END
+
+STEP 24140 QUERY
+ENTRY_BEGIN
+RAW
+b7fbf07b501044620cc30000000000000000
+ENTRY_END
+
+STEP 24150 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d5fd00000204056401010402
+ENTRY_END
+
+STEP 24160 QUERY
+ENTRY_BEGIN
+RAW
+b7fddb875010447096670000000000000000
+ENTRY_END
+
+STEP 24170 QUERY
+ENTRY_BEGIN
+RAW
+b7fddb8750184470a44800000091bc00000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 24180 QUERY
+ENTRY_BEGIN
+RAW
+b7fcabbb5011446242520000000000000000
+ENTRY_END
+
+STEP 24190 QUERY
+ENTRY_BEGIN
+RAW
+b7faff2b501040a2a7f40000000000000000
+ENTRY_END
+
+STEP 24200 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005a9d0000020405b401010402
+ENTRY_END
+
+STEP 24210 QUERY
+ENTRY_BEGIN
+RAW
+b7fe9a2d501040b0af850000000000000000
+ENTRY_END
+
+STEP 24220 QUERY
+ENTRY_BEGIN
+RAW
+b7fddb955011446295d30000000000000000
+ENTRY_END
+
+STEP 24230 QUERY
+ENTRY_BEGIN
+RAW
+b7fe9a2d501840b0787d0000008c2280000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403aff69403c50e900030000002d4e544c4d535350000100000097b200e007000700260000000600060020000000534552564552444556414552540000
+ENTRY_END
+
+STEP 24240 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c2190000020405b401010402
+ENTRY_END
+
+STEP 24250 QUERY
+ENTRY_BEGIN
+RAW
+b7fcabbc5010446242510000000000000000
+ENTRY_END
+
+STEP 24260 QUERY
+ENTRY_BEGIN
+RAW
+b7ff23a450104470a73d0000000000000000
+ENTRY_END
+
+STEP 24270 QUERY
+ENTRY_BEGIN
+RAW
+b7fddb965010446295d20000000000000000
+ENTRY_END
+
+STEP 24280 QUERY
+ENTRY_BEGIN
+RAW
+b7fe9a3b501140a2aef60000000000000000
+ENTRY_END
+
+STEP 24290 QUERY
+ENTRY_BEGIN
+RAW
+b7ff23a45018447075a400000094dcc0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd78403c4ef80003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24300 QUERY
+ENTRY_BEGIN
+RAW
+b7fd5e3b50114462f02f0000000000000000
+ENTRY_END
+
+STEP 24310 QUERY
+ENTRY_BEGIN
+RAW
+b7fff478501044703de50000000000000000
+ENTRY_END
+
+STEP 24320 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab080000020405b401010402
+ENTRY_END
+
+STEP 24330 QUERY
+ENTRY_BEGIN
+RAW
+b7fff4785018447043c600000091c400000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afafd403c4c7d0003000000324e544c4d535350000100000097b200e00c000c0026000000060006002000000053455256455253544546465953574f524c440000
+ENTRY_END
+
+STEP 24340 QUERY
+ENTRY_BEGIN
+RAW
+b7fe9a3c501040a2aef50000000000000000
+ENTRY_END
+
+STEP 24350 QUERY
+ENTRY_BEGIN
+RAW
+b7ff23b250114462a6a60000000000000000
+ENTRY_END
+
+STEP 24360 QUERY
+ENTRY_BEGIN
+RAW
+b7fff486501144623d510000000000000000
+ENTRY_END
+
+STEP 24370 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400093ce0000020405b401010402
+ENTRY_END
+
+STEP 24380 QUERY
+ENTRY_BEGIN
+RAW
+b7fd5e3c50104462f02e0000000000000000
+ENTRY_END
+
+STEP 24390 QUERY
+ENTRY_BEGIN
+RAW
+b8008be0501044708f6b0000000000000000
+ENTRY_END
+
+STEP 24400 QUERY
+ENTRY_BEGIN
+RAW
+b7fff487501044623d500000000000000000
+ENTRY_END
+
+STEP 24410 QUERY
+ENTRY_BEGIN
+RAW
+b8008be050184470c140000000911900000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 24420 QUERY
+ENTRY_BEGIN
+RAW
+b7ff23b350104462a6a50000000000000000
+ENTRY_END
+
+STEP 24430 QUERY
+ENTRY_BEGIN
+RAW
+b8013f7f50104470c4910000000000000000
+ENTRY_END
+
+STEP 24440 QUERY
+ENTRY_BEGIN
+RAW
+b8008bee501144628ed70000000000000000
+ENTRY_END
+
+STEP 24450 QUERY
+ENTRY_BEGIN
+RAW
+b8013f7f501844705a39000000941580000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd78403c4ef80003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24460 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400087580000020405b401010402
+ENTRY_END
+
+STEP 24470 QUERY
+ENTRY_BEGIN
+RAW
+b8013f8d50114462c3fa0000000000000000
+ENTRY_END
+
+STEP 24480 QUERY
+ENTRY_BEGIN
+RAW
+b8013f8e50104462c3f90000000000000000
+ENTRY_END
+
+STEP 24490 QUERY
+ENTRY_BEGIN
+RAW
+b8008bef501044628ed60000000000000000
+ENTRY_END
+
+STEP 24500 QUERY
+ENTRY_BEGIN
+RAW
+b80237e650104470bfb30000000000000000
+ENTRY_END
+
+STEP 24510 QUERY
+ENTRY_BEGIN
+RAW
+b80237e650184470d108000000913980000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403afd47403c4ec70003000000324e544c4d535350000100000097b208e00b000b00270000000700070020000000495345525645524b5356494e5445524e45540000
+ENTRY_END
+
+STEP 24520 QUERY
+ENTRY_BEGIN
+RAW
+b80237f450114462bf1f0000000000000000
+ENTRY_END
+
+STEP 24530 QUERY
+ENTRY_BEGIN
+RAW
+b80237f550104462bf1e0000000000000000
+ENTRY_END
+
+STEP 24540 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006a560000020405b401010402
+ENTRY_END
+
+STEP 24550 QUERY
+ENTRY_BEGIN
+RAW
+b80679815010447061120000000000000000
+ENTRY_END
+
+STEP 24560 QUERY
+ENTRY_BEGIN
+RAW
+b806798150184470b338000000945600000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24570 QUERY
+ENTRY_BEGIN
+RAW
+b806798f50114462607b0000000000000000
+ENTRY_END
+
+STEP 24580 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009e400000020405b401010402
+ENTRY_END
+
+STEP 24590 QUERY
+ENTRY_BEGIN
+RAW
+b806799050104462607a0000000000000000
+ENTRY_END
+
+STEP 24600 QUERY
+ENTRY_BEGIN
+RAW
+b8070e5a5010447000230000000000000000
+ENTRY_END
+
+STEP 24610 QUERY
+ENTRY_BEGIN
+RAW
+b8070e5a501844701a8a000000948ec0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24620 QUERY
+ENTRY_BEGIN
+RAW
+b8070e6850114462ff8b0000000000000000
+ENTRY_END
+
+STEP 24630 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240009a4a0000020405b401010402
+ENTRY_END
+
+STEP 24640 QUERY
+ENTRY_BEGIN
+RAW
+b8070e6950104462ff8a0000000000000000
+ENTRY_END
+
+STEP 24650 QUERY
+ENTRY_BEGIN
+RAW
+b807ad57501044705d2f0000000000000000
+ENTRY_END
+
+STEP 24660 QUERY
+ENTRY_BEGIN
+RAW
+b807ad5750184470d616000000943040000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24670 QUERY
+ENTRY_BEGIN
+RAW
+b807ad65501144625c980000000000000000
+ENTRY_END
+
+STEP 24680 QUERY
+ENTRY_BEGIN
+RAW
+b807ad66501044625c970000000000000000
+ENTRY_END
+
+STEP 24690 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000b5a30000020405b401010402
+ENTRY_END
+
+STEP 24700 QUERY
+ENTRY_BEGIN
+RAW
+b8083fa650104470e6380000000000000000
+ENTRY_END
+
+STEP 24710 QUERY
+ENTRY_BEGIN
+RAW
+b8083fa650184470331f000000945b40000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24720 QUERY
+ENTRY_BEGIN
+RAW
+b8083fb450114462e5a10000000000000000
+ENTRY_END
+
+STEP 24730 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab0a0000020405b401010402
+ENTRY_END
+
+STEP 24740 QUERY
+ENTRY_BEGIN
+RAW
+b8083fb550104462e5a00000000000000000
+ENTRY_END
+
+STEP 24750 QUERY
+ENTRY_BEGIN
+RAW
+b80933a250104470e7a20000000000000000
+ENTRY_END
+
+STEP 24760 QUERY
+ENTRY_BEGIN
+RAW
+b80933a250184470fcc9000000949400000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24770 QUERY
+ENTRY_BEGIN
+RAW
+b80933b050114462e70b0000000000000000
+ENTRY_END
+
+STEP 24780 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fdbe0000020405b401010402
+ENTRY_END
+
+STEP 24790 QUERY
+ENTRY_BEGIN
+RAW
+b80b2b8e5010447042690000000000000000
+ENTRY_END
+
+STEP 24800 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a29f0000020405b401010402
+ENTRY_END
+
+STEP 24810 QUERY
+ENTRY_BEGIN
+RAW
+b80b2b8e5018447092d00000009458c0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afd79403c4ef90003000000354e544c4d535350000100000097b200c00f000f00260000000600060020000000534552564552444f5649414e55534b414e544f4f520000
+ENTRY_END
+
+STEP 24820 QUERY
+ENTRY_BEGIN
+RAW
+b80933b150104462e70a0000000000000000
+ENTRY_END
+
+STEP 24830 QUERY
+ENTRY_BEGIN
+RAW
+b80b2b9c5011446241d20000000000000000
+ENTRY_END
+
+STEP 24840 QUERY
+ENTRY_BEGIN
+RAW
+b80c085d501044700a7a0000000000000000
+ENTRY_END
+
+STEP 24850 QUERY
+ENTRY_BEGIN
+RAW
+b80b2b9d5010446241d10000000000000000
+ENTRY_END
+
+STEP 24860 QUERY
+ENTRY_BEGIN
+RAW
+b80c085d5018447053cd0000008b07ac000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd53403c4ed300030000002c4e544c4d535350000100000097b200c0060006002600000006000600200000004c4150544f504a41434f42530000
+ENTRY_END
+
+STEP 24870 QUERY
+ENTRY_BEGIN
+RAW
+b80c086b5011446209ec0000000000000000
+ENTRY_END
+
+STEP 24880 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ab970000020405b401010402
+ENTRY_END
+
+STEP 24890 QUERY
+ENTRY_BEGIN
+RAW
+b80c086c5010446209eb0000000000000000
+ENTRY_END
+
+STEP 24900 QUERY
+ENTRY_BEGIN
+RAW
+b80c8b7b5010447090530000000000000000
+ENTRY_END
+
+STEP 24910 QUERY
+ENTRY_BEGIN
+RAW
+b80c8b7b501844702c170000008bb43c000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd54403c4ed400030000002c4e544c4d535350000100000097b200c0060006002600000006000600200000004c4150544f504a41434f42530000
+ENTRY_END
+
+STEP 24920 QUERY
+ENTRY_BEGIN
+RAW
+b80c8b89501144628fc50000000000000000
+ENTRY_END
+
+STEP 24930 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400063ad0000020405b401010402
+ENTRY_END
+
+STEP 24940 QUERY
+ENTRY_BEGIN
+RAW
+b80c8b8a501044628fc40000000000000000
+ENTRY_END
+
+STEP 24950 QUERY
+ENTRY_BEGIN
+RAW
+b80d337550104470a06e0000000000000000
+ENTRY_END
+
+STEP 24960 QUERY
+ENTRY_BEGIN
+RAW
+b80d337550184470f99b0000008bf6d2000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd54403c4ed400030000002c4e544c4d535350000100000097b200c0060006002600000006000600200000004c4150544f504a41434f42530000
+ENTRY_END
+
+STEP 24970 QUERY
+ENTRY_BEGIN
+RAW
+b80d3383501144629fe00000000000000000
+ENTRY_END
+
+STEP 24980 QUERY
+ENTRY_BEGIN
+RAW
+b80d3384501044629fdf0000000000000000
+ENTRY_END
+
+STEP 24990 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400007cf0000020405b401010402
+ENTRY_END
+
+STEP 25000 QUERY
+ENTRY_BEGIN
+RAW
+b80f1979501044705e8a0000000000000000
+ENTRY_END
+
+STEP 25010 QUERY
+ENTRY_BEGIN
+RAW
+b80f19795018447087170000008ba547000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afbd2403c4d5200030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005343484f4c534848454e545a454e0000
+ENTRY_END
+
+STEP 25020 QUERY
+ENTRY_BEGIN
+RAW
+b80f1987501144625dfc0000000000000000
+ENTRY_END
+
+STEP 25030 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400013fa0000020405b401010402
+ENTRY_END
+
+STEP 25040 QUERY
+ENTRY_BEGIN
+RAW
+b80f1988501044625dfb0000000000000000
+ENTRY_END
+
+STEP 25050 QUERY
+ENTRY_BEGIN
+RAW
+b8100fa250104470748b0000000000000000
+ENTRY_END
+
+STEP 25060 QUERY
+ENTRY_BEGIN
+RAW
+b8100fa250184470efe20000008b547d000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afbd2403c4d5200030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005343484f4c534848454e545a454e0000
+ENTRY_END
+
+STEP 25070 QUERY
+ENTRY_BEGIN
+RAW
+b8100fb05011446273fd0000000000000000
+ENTRY_END
+
+STEP 25080 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400030df0000020405b401010402
+ENTRY_END
+
+STEP 25090 QUERY
+ENTRY_BEGIN
+RAW
+b8100fb15010446273fc0000000000000000
+ENTRY_END
+
+STEP 25100 QUERY
+ENTRY_BEGIN
+RAW
+b81096d8501044700a3a0000000000000000
+ENTRY_END
+
+STEP 25110 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf043bb0000020405b401010402
+ENTRY_END
+
+STEP 25120 QUERY
+ENTRY_BEGIN
+RAW
+b81096d8501844706e000000008b6c0e000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afbd2403c4d5200030000002e4e544c4d535350000100000097b208e0080008002600000006000600200000005343484f4c534848454e545a454e0000
+ENTRY_END
+
+STEP 25130 QUERY
+ENTRY_BEGIN
+RAW
+b81096e65011446209ac0000000000000000
+ENTRY_END
+
+STEP 25140 QUERY
+ENTRY_BEGIN
+RAW
+b81096e75010446209ab0000000000000000
+ENTRY_END
+
+STEP 25150 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400074a10000020405b401010402
+ENTRY_END
+
+STEP 25160 QUERY
+ENTRY_BEGIN
+RAW
+b812ca7a501044701a580000000000000000
+ENTRY_END
+
+STEP 25170 QUERY
+ENTRY_BEGIN
+RAW
+b812ca7a50184470b4fb00000090ef06000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005403677373096d6963726f736f667403636f6d004039b1fb403b037b0003000000314e544c4d535350000100000097b200c00a000a0027000000070007002000000042414e4b4a414e4753492d444f4d41494e0000
+ENTRY_END
+
+STEP 25180 QUERY
+ENTRY_BEGIN
+RAW
+b812ca885011446219c50000000000000000
+ENTRY_END
+
+STEP 25190 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d8060000020405b401010402
+ENTRY_END
+
+STEP 25200 QUERY
+ENTRY_BEGIN
+RAW
+b812ca895010446219c40000000000000000
+ENTRY_END
+
+STEP 25210 QUERY
+ENTRY_BEGIN
+RAW
+b81344c45010447003730000000000000000
+ENTRY_END
+
+STEP 25220 QUERY
+ENTRY_BEGIN
+RAW
+b81344c450184470d4fb00000090b722000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005403677373096d6963726f736f667403636f6d004039b1fc403b037c0003000000314e544c4d535350000100000097b200c00a000a0027000000070007002000000042414e4b4a414e4753492d444f4d41494e0000
+ENTRY_END
+
+STEP 25230 QUERY
+ENTRY_BEGIN
+RAW
+b81344d25011446202e00000000000000000
+ENTRY_END
+
+STEP 25240 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000aad60000020405b401010402
+ENTRY_END
+
+STEP 25250 QUERY
+ENTRY_BEGIN
+RAW
+b81344d35010446202df0000000000000000
+ENTRY_END
+
+STEP 25260 QUERY
+ENTRY_BEGIN
+RAW
+b813e03f501044703ac70000000000000000
+ENTRY_END
+
+STEP 25270 QUERY
+ENTRY_BEGIN
+RAW
+b813e03f50184470df7500000090e3fc000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005403677373096d6963726f736f667403636f6d004039b1fc403b037c0003000000314e544c4d535350000100000097b200c00a000a0027000000070007002000000042414e4b4a414e4753492d444f4d41494e0000
+ENTRY_END
+
+STEP 25280 QUERY
+ENTRY_BEGIN
+RAW
+b813e04d501144623a340000000000000000
+ENTRY_END
+
+STEP 25290 QUERY
+ENTRY_BEGIN
+RAW
+b813e04e501044623a330000000000000000
+ENTRY_END
+
+STEP 25300 QUERY
+ENTRY_BEGIN
+RAW
+1a4e00000001000000000000087461786932303030026e6c00000f000100
+ENTRY_END
+
+STEP 25310 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000322000000204057a01010402
+ENTRY_END
+
+STEP 25320 QUERY
+ENTRY_BEGIN
+RAW
+b81609ca501041b89b010000000000000000
+ENTRY_END
+
+STEP 25330 QUERY
+ENTRY_BEGIN
+RAW
+b81609ca501841b82920000000944f25000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa6a403c4bea0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 25340 QUERY
+ENTRY_BEGIN
+RAW
+b81609d8501141aa9a6a0000000000000000
+ENTRY_END
+
+STEP 25350 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000436000000204057a01010402
+ENTRY_END
+
+STEP 25360 QUERY
+ENTRY_BEGIN
+RAW
+b81609d9501041aa9a690000000000000000
+ENTRY_END
+
+STEP 25370 QUERY
+ENTRY_BEGIN
+RAW
+b81695d2501041b820390000000000000000
+ENTRY_END
+
+STEP 25380 QUERY
+ENTRY_BEGIN
+RAW
+b81695d2501841b87aad0000009483d0000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa6a403c4bea0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 25390 QUERY
+ENTRY_BEGIN
+RAW
+b81695e0501141aa1fa20000000000000000
+ENTRY_END
+
+STEP 25400 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000b3700000204057a01010402
+ENTRY_END
+
+STEP 25410 QUERY
+ENTRY_BEGIN
+RAW
+b81695e1501041aa1fa10000000000000000
+ENTRY_END
+
+STEP 25420 QUERY
+ENTRY_BEGIN
+RAW
+b8171898501041b865490000000000000000
+ENTRY_END
+
+STEP 25430 QUERY
+ENTRY_BEGIN
+RAW
+b8171898501841b8206e000000942320000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa6a403c4bea0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 25440 QUERY
+ENTRY_BEGIN
+RAW
+b81718a6501141aa64b20000000000000000
+ENTRY_END
+
+STEP 25450 QUERY
+ENTRY_BEGIN
+RAW
+b81718a7501041aa64b10000000000000000
+ENTRY_END
+
+STEP 25460 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf052f200000204057a01010402
+ENTRY_END
+
+STEP 25470 QUERY
+ENTRY_BEGIN
+RAW
+b817bc735010fbec09e50000000000000000
+ENTRY_END
+
+STEP 25480 QUERY
+ENTRY_BEGIN
+RAW
+b817bc735018fbecebda00000091c518000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403af82a403c49aa0003000000324e544c4d535350000100000097b208e0080008002a0000000a000a00200000004a4844454c49455230314a4844454c4945520000
+ENTRY_END
+
+STEP 25490 QUERY
+ENTRY_BEGIN
+RAW
+b817bc815011fbde09510000000000000000
+ENTRY_END
+
+STEP 25500 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d21400000204057a01010402
+ENTRY_END
+
+STEP 25510 QUERY
+ENTRY_BEGIN
+RAW
+b817bc825010fbde09500000000000000000
+ENTRY_END
+
+STEP 25520 QUERY
+ENTRY_BEGIN
+RAW
+b818a4a45010fbeca0d50000000000000000
+ENTRY_END
+
+STEP 25530 QUERY
+ENTRY_BEGIN
+RAW
+b818a4a45018fbec05b5000000914330000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403af82a403c49aa0003000000324e544c4d535350000100000097b208e0080008002a0000000a000a00200000004a4844454c49455230314a4844454c4945520000
+ENTRY_END
+
+STEP 25540 QUERY
+ENTRY_BEGIN
+RAW
+b818a4b25011fbdea0410000000000000000
+ENTRY_END
+
+STEP 25550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf01cad00000204057a01010402
+ENTRY_END
+
+STEP 25560 QUERY
+ENTRY_BEGIN
+RAW
+b818a4b35010fbdea0400000000000000000
+ENTRY_END
+
+STEP 25570 QUERY
+ENTRY_BEGIN
+RAW
+b8198d495010fbec02c80000000000000000
+ENTRY_END
+
+STEP 25580 QUERY
+ENTRY_BEGIN
+RAW
+b8198d495018fbeccd2600000091ddb0000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403af82a403c49aa0003000000324e544c4d535350000100000097b208e0080008002a0000000a000a00200000004a4844454c49455230314a4844454c4945520000
+ENTRY_END
+
+STEP 25590 QUERY
+ENTRY_BEGIN
+RAW
+b8198d575011fbde02340000000000000000
+ENTRY_END
+
+STEP 25600 QUERY
+ENTRY_BEGIN
+RAW
+b8198d585010fbde02330000000000000000
+ENTRY_END
+
+STEP 25610 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0686900000204055001010402
+ENTRY_END
+
+STEP 25620 QUERY
+ENTRY_BEGIN
+RAW
+b81b91965010ff0046f70000000000000000
+ENTRY_END
+
+STEP 25630 QUERY
+ENTRY_BEGIN
+RAW
+b81b91965018ff00d263000000923613000000010001000000000f313531313832383438383231302d330000f900010f313531313832383438383231302d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403b001a403c519a0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 25640 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240008b6f0000020405b401010402
+ENTRY_END
+
+STEP 25650 QUERY
+ENTRY_BEGIN
+RAW
+b81b91a45011fef246620000000000000000
+ENTRY_END
+
+STEP 25660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c61600000204055001010402
+ENTRY_END
+
+STEP 25670 QUERY
+ENTRY_BEGIN
+RAW
+b81b91a55010fef246610000000000000000
+ENTRY_END
+
+STEP 25680 QUERY
+ENTRY_BEGIN
+RAW
+b81cbbfa5010ff007a3f0000000000000000
+ENTRY_END
+
+STEP 25690 QUERY
+ENTRY_BEGIN
+RAW
+b81c194650104470e2500000000000000000
+ENTRY_END
+
+STEP 25700 QUERY
+ENTRY_BEGIN
+RAW
+b81cbbfa5018ff003f8e00000092fd31000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b001a403c519a0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 25710 QUERY
+ENTRY_BEGIN
+RAW
+b81cbc085011fef279aa0000000000000000
+ENTRY_END
+
+STEP 25720 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0092500000204055001010402
+ENTRY_END
+
+STEP 25730 QUERY
+ENTRY_BEGIN
+RAW
+b81c1946501844707e040000008cd8b0000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd1e403c4e9e00030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 25740 QUERY
+ENTRY_BEGIN
+RAW
+b81da63a5010ff00d30c0000000000000000
+ENTRY_END
+
+STEP 25750 QUERY
+ENTRY_BEGIN
+RAW
+b81da63a5018ff00d13d00000092c44f000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b001a403c519a0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 25760 QUERY
+ENTRY_BEGIN
+RAW
+b81da6485011fef2d2770000000000000000
+ENTRY_END
+
+STEP 25770 QUERY
+ENTRY_BEGIN
+RAW
+b81c195450114462e1c10000000000000000
+ENTRY_END
+
+STEP 25780 QUERY
+ENTRY_BEGIN
+RAW
+b81da6495010fef2d2760000000000000000
+ENTRY_END
+
+STEP 25790 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000572f0000020405b401010402
+ENTRY_END
+
+STEP 25800 QUERY
+ENTRY_BEGIN
+RAW
+b81c195550104462e1c00000000000000000
+ENTRY_END
+
+STEP 25810 QUERY
+ENTRY_BEGIN
+RAW
+b81e3ea55010447088af0000000000000000
+ENTRY_END
+
+STEP 25820 QUERY
+ENTRY_BEGIN
+RAW
+b81e3ea550184470b8510000008c45c3000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd1e403c4e9e00030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 25830 QUERY
+ENTRY_BEGIN
+RAW
+b81e3eb35011446288200000000000000000
+ENTRY_END
+
+STEP 25840 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400007d90000020405b401010402
+ENTRY_END
+
+STEP 25850 QUERY
+ENTRY_BEGIN
+RAW
+b81e3eb450104462881f0000000000000000
+ENTRY_END
+
+STEP 25860 QUERY
+ENTRY_BEGIN
+RAW
+b81eec12501044708beb0000000000000000
+ENTRY_END
+
+STEP 25870 QUERY
+ENTRY_BEGIN
+RAW
+b81eec125018447092a40000008c6eac000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd1e403c4e9e00030000002d4e544c4d535350000100000097b208e007000700260000000600060020000000574e54504d4d574e545f504d4d0000
+ENTRY_END
+
+STEP 25880 QUERY
+ENTRY_BEGIN
+RAW
+b81eec20501144628b5c0000000000000000
+ENTRY_END
+
+STEP 25890 QUERY
+ENTRY_BEGIN
+RAW
+b81eec21501044628b5b0000000000000000
+ENTRY_END
+
+STEP 25900 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400010370000020405b401010402
+ENTRY_END
+
+STEP 25910 QUERY
+ENTRY_BEGIN
+RAW
+b820ebd95010447094800000000000000000
+ENTRY_END
+
+STEP 25920 QUERY
+ENTRY_BEGIN
+RAW
+b820ebd950184470da910000008ef600000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd1f403c4e9f00030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 25930 QUERY
+ENTRY_BEGIN
+RAW
+b820ebe75011446293ef0000000000000000
+ENTRY_END
+
+STEP 25940 QUERY
+ENTRY_BEGIN
+RAW
+b820ebe85010446293ee0000000000000000
+ENTRY_END
+
+STEP 25950 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000cbcf0000020405b401010402
+ENTRY_END
+
+STEP 25960 QUERY
+ENTRY_BEGIN
+RAW
+b821db135010447060de0000000000000000
+ENTRY_END
+
+STEP 25970 QUERY
+ENTRY_BEGIN
+RAW
+b821db13501844703ff10000008e5e00000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd1f403c4e9f00030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 25980 QUERY
+ENTRY_BEGIN
+RAW
+b821db2150114462604d0000000000000000
+ENTRY_END
+
+STEP 25990 QUERY
+ENTRY_BEGIN
+RAW
+b821db2250104462604c0000000000000000
+ENTRY_END
+
+STEP 26000 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400024f30000020405b401010402
+ENTRY_END
+
+STEP 26010 QUERY
+ENTRY_BEGIN
+RAW
+b8229fc850104470f54b0000000000000000
+ENTRY_END
+
+STEP 26020 QUERY
+ENTRY_BEGIN
+RAW
+b8229fc850184470795e0000008eb900000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd1f403c4e9f00030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 26030 QUERY
+ENTRY_BEGIN
+RAW
+b8229fd650114462f4ba0000000000000000
+ENTRY_END
+
+STEP 26040 QUERY
+ENTRY_BEGIN
+RAW
+b8229fd750104462f4b90000000000000000
+ENTRY_END
+
+STEP 26050 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007f1e00000204057801010402
+ENTRY_END
+
+STEP 26060 QUERY
+ENTRY_BEGIN
+RAW
+b82500fd501041a0f0d30000000000000000
+ENTRY_END
+
+STEP 26070 QUERY
+ENTRY_BEGIN
+RAW
+b82500fd501841a0fa410000008d6f40000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403aef20403c40a000030000002e4e544c4d535350000100000097b200c008000800260000000600060020000000534552564552434f42424c4552310000
+ENTRY_END
+
+STEP 26080 QUERY
+ENTRY_BEGIN
+RAW
+b825010b50114192f0430000000000000000
+ENTRY_END
+
+STEP 26090 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400048c400000204057801010402
+ENTRY_END
+
+STEP 26100 QUERY
+ENTRY_BEGIN
+RAW
+b825010c50104192f0420000000000000000
+ENTRY_END
+
+STEP 26110 QUERY
+ENTRY_BEGIN
+RAW
+b825ba8a501041a000ec0000000000000000
+ENTRY_END
+
+STEP 26120 QUERY
+ENTRY_BEGIN
+RAW
+b825ba8a501841a08ada0000008defc0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aef20403c40a000030000002e4e544c4d535350000100000097b200c008000800260000000600060020000000534552564552434f42424c4552310000
+ENTRY_END
+
+STEP 26130 QUERY
+ENTRY_BEGIN
+RAW
+b825ba9850114192005c0000000000000000
+ENTRY_END
+
+STEP 26140 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240004f1300000204057801010402
+ENTRY_END
+
+STEP 26150 QUERY
+ENTRY_BEGIN
+RAW
+b825ba9950104192005b0000000000000000
+ENTRY_END
+
+STEP 26160 QUERY
+ENTRY_BEGIN
+RAW
+b8269830501041a029940000000000000000
+ENTRY_END
+
+STEP 26170 QUERY
+ENTRY_BEGIN
+RAW
+b8269830501841a08f030000008d1440000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aef20403c40a000030000002e4e544c4d535350000100000097b200c008000800260000000600060020000000534552564552434f42424c4552310000
+ENTRY_END
+
+STEP 26180 QUERY
+ENTRY_BEGIN
+RAW
+b826983e5011419229040000000000000000
+ENTRY_END
+
+STEP 26190 QUERY
+ENTRY_BEGIN
+RAW
+b826983f5010419229030000000000000000
+ENTRY_END
+
+STEP 26200 QUERY
+ENTRY_BEGIN
+RAW
+b81cbc0950100000789c0000000000000000
+ENTRY_END
+
+STEP 26210 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000945300000204057a01010402
+ENTRY_END
+
+STEP 26220 QUERY
+ENTRY_BEGIN
+RAW
+b8289ecf501041b8681d0000000000000000
+ENTRY_END
+
+STEP 26230 QUERY
+ENTRY_BEGIN
+RAW
+b8289ecf501841b8c24a0000008eaff4000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d3f403beebf00030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 26240 QUERY
+ENTRY_BEGIN
+RAW
+b8289edd501141aa678c0000000000000000
+ENTRY_END
+
+STEP 26250 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000c58e00000204057a01010402
+ENTRY_END
+
+STEP 26260 QUERY
+ENTRY_BEGIN
+RAW
+b8289ede501041aa678b0000000000000000
+ENTRY_END
+
+STEP 26270 QUERY
+ENTRY_BEGIN
+RAW
+b829975b501041b8a0cb0000000000000000
+ENTRY_END
+
+STEP 26280 QUERY
+ENTRY_BEGIN
+RAW
+b829975b501841b87ebc0000008e2d32000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d3f403beebf00030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 26290 QUERY
+ENTRY_BEGIN
+RAW
+b8299769501141aaa03a0000000000000000
+ENTRY_END
+
+STEP 26300 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400035ff00000204057a01010402
+ENTRY_END
+
+STEP 26310 QUERY
+ENTRY_BEGIN
+RAW
+b829976a501041aaa0390000000000000000
+ENTRY_END
+
+STEP 26320 QUERY
+ENTRY_BEGIN
+RAW
+b82a2f49501041b8794d0000000000000000
+ENTRY_END
+
+STEP 26330 QUERY
+ENTRY_BEGIN
+RAW
+b82a2f49501841b8d9ff0000008eaa70000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d3f403beebf00030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 26340 QUERY
+ENTRY_BEGIN
+RAW
+b82a2f57501141aa78bc0000000000000000
+ENTRY_END
+
+STEP 26350 QUERY
+ENTRY_BEGIN
+RAW
+b82a2f58501041aa78bb0000000000000000
+ENTRY_END
+
+STEP 26360 QUERY
+ENTRY_BEGIN
+RAW
+00000000b002832c24a30000010303010101080a11235f89000000000101040202040564
+ENTRY_END
+
+STEP 26370 QUERY
+ENTRY_BEGIN
+RAW
+b82b27518010859879ee00000101080a11235f8a0128080f
+ENTRY_END
+
+;STEP 26380 QUERY
+;ENTRY_BEGIN
+;RAW
+;2c3901000001000000000000056b6f726e6f026e6c00000f000100
+;ENTRY_END
+
+STEP 26390 QUERY
+ENTRY_BEGIN
+RAW
+b82b275180188598d42e00000101080a11235f9a0128080f008e55dc000000010001000000000f313330353637303035383030322d330000f900010f313330353637303035383030322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afc71403c4df100030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000004c4150544f505745524b47524f45500000
+ENTRY_END
+
+STEP 26400 QUERY
+ENTRY_BEGIN
+RAW
+b82b275f80108598793f00000101080a11235f9b0128080f
+ENTRY_END
+
+STEP 26410 QUERY
+ENTRY_BEGIN
+RAW
+b82b275f8011859878e700000101080a11235ff20128080f
+ENTRY_END
+
+STEP 26420 QUERY
+ENTRY_BEGIN
+RAW
+b82b27608010859878e300000101080a11235ff301280811
+ENTRY_END
+
+STEP 26430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fca499ac00000204057e01010402
+ENTRY_END
+
+STEP 26440 QUERY
+ENTRY_BEGIN
+RAW
+b82fe4a45010fca429560000000000000000
+ENTRY_END
+
+STEP 26450 QUERY
+ENTRY_BEGIN
+RAW
+b82fe4a45018fca4909e000000927690000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd22403c4ea20003000000334e544c4d535350000100000097b208e00a000a0029000000090009002000000043454445522d444331434544455244524545460000
+ENTRY_END
+
+STEP 26460 QUERY
+ENTRY_BEGIN
+RAW
+b82fe4b25011fc9628c10000000000000000
+ENTRY_END
+
+STEP 26470 QUERY
+ENTRY_BEGIN
+RAW
+b82fe4b35010fc9628c00000000000000000
+ENTRY_END
+
+STEP 26480 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fca4a2d800000204057e01010402
+ENTRY_END
+
+STEP 26490 QUERY
+ENTRY_BEGIN
+RAW
+b830dc6f5010fca43ab60000000000000000
+ENTRY_END
+
+STEP 26500 QUERY
+ENTRY_BEGIN
+RAW
+b830dc6f5018fca4199f00000092fff0000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd22403c4ea20003000000334e544c4d535350000100000097b208e00a000a0029000000090009002000000043454445522d444331434544455244524545460000
+ENTRY_END
+
+STEP 26510 QUERY
+ENTRY_BEGIN
+RAW
+b830dc7d5011fc963a210000000000000000
+ENTRY_END
+
+STEP 26520 QUERY
+ENTRY_BEGIN
+RAW
+b830dc7e5010fc963a200000000000000000
+ENTRY_END
+
+STEP 26530 QUERY
+ENTRY_BEGIN
+RAW
+000000007002fca4bdb400000204057e01010402
+ENTRY_END
+
+STEP 26540 QUERY
+ENTRY_BEGIN
+RAW
+b831aa875010fca487790000000000000000
+ENTRY_END
+
+STEP 26550 QUERY
+ENTRY_BEGIN
+RAW
+b831aa875018fca4dd02000000928950000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd22403c4ea20003000000334e544c4d535350000100000097b208e00a000a0029000000090009002000000043454445522d444331434544455244524545460000
+ENTRY_END
+
+STEP 26560 QUERY
+ENTRY_BEGIN
+RAW
+b831aa955011fc9686e40000000000000000
+ENTRY_END
+
+STEP 26570 QUERY
+ENTRY_BEGIN
+RAW
+00000000b002832c74fc0000010303010101080a11236035000000000101040202040564
+ENTRY_END
+
+STEP 26580 QUERY
+ENTRY_BEGIN
+RAW
+b8324e3480108598a35a00000101080a1123603601280812
+ENTRY_END
+
+STEP 26590 QUERY
+ENTRY_BEGIN
+RAW
+b831aa965010fc9686e30000000000000000
+ENTRY_END
+
+STEP 26600 QUERY
+ENTRY_BEGIN
+RAW
+b8324e34801885988e7200000101080a1123604b01280812008ec200000000010001000000000f313330353637303035383030322d320000f900010f313330353637303035383030322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afc73403c4df300030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000004c4150544f505745524b47524f45500000
+ENTRY_END
+
+STEP 26610 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0747000000204056401010402
+ENTRY_END
+
+STEP 26620 QUERY
+ENTRY_BEGIN
+RAW
+b8324e4280108598a2a600000101080a1123604b01280813
+ENTRY_END
+
+STEP 26630 QUERY
+ENTRY_BEGIN
+RAW
+b8344c685010fd5c99cb0000000000000000
+ENTRY_END
+
+STEP 26640 QUERY
+ENTRY_BEGIN
+RAW
+b8344c685018fd5c25800000008e4c97000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afde1403c4f6100030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 26650 QUERY
+ENTRY_BEGIN
+RAW
+b8344c765011fd4e993a0000000000000000
+ENTRY_END
+
+STEP 26660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf063ec00000204056401010402
+ENTRY_END
+
+STEP 26670 QUERY
+ENTRY_BEGIN
+RAW
+b8344c775010fd4e99390000000000000000
+ENTRY_END
+
+STEP 26680 QUERY
+ENTRY_BEGIN
+RAW
+b83533955010fd5ca2190000000000000000
+ENTRY_END
+
+STEP 26690 QUERY
+ENTRY_BEGIN
+RAW
+b83533955018fd5c53880000008e27de000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afde1403c4f6100030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 26700 QUERY
+ENTRY_BEGIN
+RAW
+b83533a35011fd4ea1880000000000000000
+ENTRY_END
+
+STEP 26710 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0873e00000204056401010402
+ENTRY_END
+
+STEP 26720 QUERY
+ENTRY_BEGIN
+RAW
+b83533a45010fd4ea1870000000000000000
+ENTRY_END
+
+STEP 26730 QUERY
+ENTRY_BEGIN
+RAW
+b835f3265010fd5c05da0000000000000000
+ENTRY_END
+
+STEP 26740 QUERY
+ENTRY_BEGIN
+RAW
+b835f3265018fd5c0b910000008ed395000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afde1403c4f6100030000002f4e544c4d535350000100000097b208e007000700280000000800080020000000444330314856534c4f424856534c530000
+ENTRY_END
+
+STEP 26750 QUERY
+ENTRY_BEGIN
+RAW
+b835f3345011fd4e05490000000000000000
+ENTRY_END
+
+STEP 26760 QUERY
+ENTRY_BEGIN
+RAW
+b835f3355010fd4e05480000000000000000
+ENTRY_END
+
+STEP 26770 QUERY
+ENTRY_BEGIN
+RAW
+b8324e4280118598a25e00000101080a1123609201280813
+ENTRY_END
+
+STEP 26780 QUERY
+ENTRY_BEGIN
+RAW
+b8324e4380108598a25b00000101080a1123609301280814
+ENTRY_END
+
+STEP 26790 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06f4c0000020405b401010402
+ENTRY_END
+
+STEP 26800 QUERY
+ENTRY_BEGIN
+RAW
+b83838215010faf0aba60000000000000000
+ENTRY_END
+
+STEP 26810 QUERY
+ENTRY_BEGIN
+RAW
+b83838215018faf04ae500000088c200000000010001000000000f313432353932393134323239302d330000f900010f313432353932393134323239302d330000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe84403c50040003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 26820 QUERY
+ENTRY_BEGIN
+RAW
+b838382f5011fae2ab1b0000000000000000
+ENTRY_END
+
+STEP 26830 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf09b570000020405b401010402
+ENTRY_END
+
+STEP 26840 QUERY
+ENTRY_BEGIN
+RAW
+b83838305010fae2ab1a0000000000000000
+ENTRY_END
+
+STEP 26850 QUERY
+ENTRY_BEGIN
+RAW
+b83916d95010faf0f8f80000000000000000
+ENTRY_END
+
+STEP 26860 QUERY
+ENTRY_BEGIN
+RAW
+b83916d95018faf0b1dc00000088a95c000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe84403c50040003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 26870 QUERY
+ENTRY_BEGIN
+RAW
+b83916e75011fae2f86d0000000000000000
+ENTRY_END
+
+STEP 26880 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b4fb0000020405b401010402
+ENTRY_END
+
+STEP 26890 QUERY
+ENTRY_BEGIN
+RAW
+b83916e85010fae2f86c0000000000000000
+ENTRY_END
+
+STEP 26900 QUERY
+ENTRY_BEGIN
+RAW
+b83af3e45010faf035900000000000000000
+ENTRY_END
+
+STEP 26910 QUERY
+ENTRY_BEGIN
+RAW
+b83af3e45018faf02fd0000000886800000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe84403c50040003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 26920 QUERY
+ENTRY_BEGIN
+RAW
+b83af3f25011fae235050000000000000000
+ENTRY_END
+
+STEP 26930 QUERY
+ENTRY_BEGIN
+RAW
+b83af3f35010fae235040000000000000000
+ENTRY_END
+
+STEP 26940 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000796d00000204057a01010402
+ENTRY_END
+
+STEP 26950 QUERY
+ENTRY_BEGIN
+RAW
+b83be921501041b802d20000000000000000
+ENTRY_END
+
+STEP 26960 QUERY
+ENTRY_BEGIN
+RAW
+b83be921501841b8a70b0000008e5fe8000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d42403beec200030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 26970 QUERY
+ENTRY_BEGIN
+RAW
+b83be92f501141aa02410000000000000000
+ENTRY_END
+
+STEP 26980 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000882000000204057a01010402
+ENTRY_END
+
+STEP 26990 QUERY
+ENTRY_BEGIN
+RAW
+b83be930501041aa02400000000000000000
+ENTRY_END
+
+STEP 27000 QUERY
+ENTRY_BEGIN
+RAW
+b83cde58501041b81c4d0000000000000000
+ENTRY_END
+
+STEP 27010 QUERY
+ENTRY_BEGIN
+RAW
+b83cde58501841b844490000008edd26000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d42403beec200030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 27020 QUERY
+ENTRY_BEGIN
+RAW
+b83cde66501141aa1bbc0000000000000000
+ENTRY_END
+
+STEP 27030 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f57d00000204057a01010402
+ENTRY_END
+
+STEP 27040 QUERY
+ENTRY_BEGIN
+RAW
+b83cde67501041aa1bbb0000000000000000
+ENTRY_END
+
+STEP 27050 QUERY
+ENTRY_BEGIN
+RAW
+b83db28d501041b8b5740000000000000000
+ENTRY_END
+
+STEP 27060 QUERY
+ENTRY_BEGIN
+RAW
+b83db28d501841b830130000008e8a84000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403a9d42403beec200030000002f4e544c4d535350000100000097b200e0090009002600000006000600200000004144455749544152494544455749540000
+ENTRY_END
+
+STEP 27070 QUERY
+ENTRY_BEGIN
+RAW
+b83db29b501141aab4e30000000000000000
+ENTRY_END
+
+STEP 27080 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000dd470000020405b401010402
+ENTRY_END
+
+STEP 27090 QUERY
+ENTRY_BEGIN
+RAW
+b83db29c501041aab4e20000000000000000
+ENTRY_END
+
+STEP 27100 QUERY
+ENTRY_BEGIN
+RAW
+b83e9b2e50104470b21e0000000000000000
+ENTRY_END
+
+STEP 27110 QUERY
+ENTRY_BEGIN
+RAW
+b83e9b2e50184470d9ec0000008e0c44000000010001000000000f313131363639313439363937382d330000f900010f313131363639313439363937382d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd23403c4ea300030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 27120 QUERY
+ENTRY_BEGIN
+RAW
+b83e9b3c50114462b18d0000000000000000
+ENTRY_END
+
+STEP 27130 QUERY
+ENTRY_BEGIN
+RAW
+b83e9b3d50104462b18c0000000000000000
+ENTRY_END
+
+STEP 27140 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e2d50000020405b401010402
+ENTRY_END
+
+STEP 27150 QUERY
+ENTRY_BEGIN
+RAW
+b83f3c0b5010447016cf0000000000000000
+ENTRY_END
+
+STEP 27160 QUERY
+ENTRY_BEGIN
+RAW
+b83f3c0b50184470e4e30000008e66fe000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd23403c4ea300030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 27170 QUERY
+ENTRY_BEGIN
+RAW
+b83f3c1950114462163e0000000000000000
+ENTRY_END
+
+STEP 27180 QUERY
+ENTRY_BEGIN
+RAW
+b83f3c1a50104462163d0000000000000000
+ENTRY_END
+
+STEP 27190 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a9590000020405b401010402
+ENTRY_END
+
+STEP 27200 QUERY
+ENTRY_BEGIN
+RAW
+b841d41050104470454b0000000000000000
+ENTRY_END
+
+STEP 27210 QUERY
+ENTRY_BEGIN
+RAW
+b841d41050184470b8a50000008ec1b8000000010001000000000f313131363639313439363937382d320000f900010f313131363639313439363937382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afd23403c4ea300030000002f4e544c4d535350000100000097b200c009000900260000000600060020000000544f544f524f434f524e574f524c440000
+ENTRY_END
+
+STEP 27220 QUERY
+ENTRY_BEGIN
+RAW
+b841d41e5011446244ba0000000000000000
+ENTRY_END
+
+STEP 27230 QUERY
+ENTRY_BEGIN
+RAW
+b841d41f5010446244b90000000000000000
+ENTRY_END
+
+STEP 27240 QUERY
+ENTRY_BEGIN
+RAW
+00000000b002832c6d8b0000010303010101080a11236100000000000101040202040564
+ENTRY_END
+
+STEP 27250 QUERY
+ENTRY_BEGIN
+RAW
+b843dd9f801085980c6800000101080a1123610101280817
+ENTRY_END
+
+STEP 27260 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf043bb0000020405b401010402
+ENTRY_END
+
+STEP 27270 QUERY
+ENTRY_BEGIN
+RAW
+b843dd9f801885981a0800000101080a1123610e01280817008e9b80000000010001000000000f313330353637303035383030322d320000f900010f313330353637303035383030322d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afc75403c4df500030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000004c4150544f505745524b47524f45500000
+ENTRY_END
+
+STEP 27280 QUERY
+ENTRY_BEGIN
+RAW
+b843ddad801085980bbd00000101080a1123610e01280817
+ENTRY_END
+
+STEP 27290 QUERY
+ENTRY_BEGIN
+RAW
+b843ddad801185980b7b00000101080a1123614f01280817
+ENTRY_END
+
+STEP 27300 QUERY
+ENTRY_BEGIN
+RAW
+b843ddae801085980b7900000101080a1123614f01280818
+ENTRY_END
+
+STEP 27310 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240006bdd0000020405b401010402
+ENTRY_END
+
+STEP 27320 QUERY
+ENTRY_BEGIN
+RAW
+b84c97eb5010447043e90000000000000000
+ENTRY_END
+
+STEP 27330 QUERY
+ENTRY_BEGIN
+RAW
+b84c97eb50184470cee50000008b150c000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd28403c4ea800030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 27340 QUERY
+ENTRY_BEGIN
+RAW
+b84c97f950114462435b0000000000000000
+ENTRY_END
+
+STEP 27350 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400088fe0000020405b401010402
+ENTRY_END
+
+STEP 27360 QUERY
+ENTRY_BEGIN
+RAW
+b84c97fa50104462435a0000000000000000
+ENTRY_END
+
+STEP 27370 QUERY
+ENTRY_BEGIN
+RAW
+b84d1a6450104470de900000000000000000
+ENTRY_END
+
+STEP 27380 QUERY
+ENTRY_BEGIN
+RAW
+b84d1a645018447024660000008b5b34000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd28403c4ea800030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 27390 QUERY
+ENTRY_BEGIN
+RAW
+b84d1a7250114462de020000000000000000
+ENTRY_END
+
+STEP 27400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400086c40000020405b401010402
+ENTRY_END
+
+STEP 27410 QUERY
+ENTRY_BEGIN
+RAW
+b84d1a7350104462de010000000000000000
+ENTRY_END
+
+STEP 27420 QUERY
+ENTRY_BEGIN
+RAW
+b84df49e50104470021c0000000000000000
+ENTRY_END
+
+STEP 27430 QUERY
+ENTRY_BEGIN
+RAW
+b84df49e5018447001c90000008ba15c000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd28403c4ea800030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 27440 QUERY
+ENTRY_BEGIN
+RAW
+b84df4ac50114462018e0000000000000000
+ENTRY_END
+
+STEP 27450 QUERY
+ENTRY_BEGIN
+RAW
+b84df4ad50104462018d0000000000000000
+ENTRY_END
+
+STEP 27460 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0205200000204057a01010402
+ENTRY_END
+
+STEP 27470 QUERY
+ENTRY_BEGIN
+RAW
+b8501b4d5010fbec78320000000000000000
+ENTRY_END
+
+STEP 27480 QUERY
+ENTRY_BEGIN
+RAW
+b8501b4d5018fbec917400000089a7cd000000010001000000000e3932373731323933353935342d330000f900010e3932373731323933353935342d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd09403c4e8900030000002c4e544c4d535350000100000097b208e0050005002700000007000700200000004a5550495445525a494348540000
+ENTRY_END
+
+STEP 27490 QUERY
+ENTRY_BEGIN
+RAW
+b8501b5b5011fbde77a60000000000000000
+ENTRY_END
+
+STEP 27500 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0503500000204057a01010402
+ENTRY_END
+
+STEP 27510 QUERY
+ENTRY_BEGIN
+RAW
+b8501b5c5010fbde77a50000000000000000
+ENTRY_END
+
+STEP 27520 QUERY
+ENTRY_BEGIN
+RAW
+b850aee15010fbec14810000000000000000
+ENTRY_END
+
+STEP 27530 QUERY
+ENTRY_BEGIN
+RAW
+b850aee15018fbecf3a500000089e3ea000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd09403c4e8900030000002c4e544c4d535350000100000097b208e0050005002700000007000700200000004a5550495445525a494348540000
+ENTRY_END
+
+STEP 27540 QUERY
+ENTRY_BEGIN
+RAW
+b850aeef5011fbde13f50000000000000000
+ENTRY_END
+
+STEP 27550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf05e3000000204057a01010402
+ENTRY_END
+
+STEP 27560 QUERY
+ENTRY_BEGIN
+RAW
+b850aef05010fbde13f40000000000000000
+ENTRY_END
+
+STEP 27570 QUERY
+ENTRY_BEGIN
+RAW
+b8519e465010fbec33160000000000000000
+ENTRY_END
+
+STEP 27580 QUERY
+ENTRY_BEGIN
+RAW
+b8519e465018fbec89db000000896c4a000000010001000000000e3932373731323933353935342d320000f900010e3932373731323933353935342d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd09403c4e8900030000002c4e544c4d535350000100000097b208e0050005002700000007000700200000004a5550495445525a494348540000
+ENTRY_END
+
+STEP 27590 QUERY
+ENTRY_BEGIN
+RAW
+b8519e545011fbde328a0000000000000000
+ENTRY_END
+
+STEP 27600 QUERY
+ENTRY_BEGIN
+RAW
+b8519e555010fbde32890000000000000000
+ENTRY_END
+
+STEP 27610 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000fee80000020405b401010402
+ENTRY_END
+
+STEP 27620 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e84d00000204059801010402
+ENTRY_END
+
+STEP 27630 QUERY
+ENTRY_BEGIN
+RAW
+b8557ee25010fbb8dce50000000000000000
+ENTRY_END
+
+STEP 27640 QUERY
+ENTRY_BEGIN
+RAW
+b854aa3250104470c4a50000000000000000
+ENTRY_END
+
+STEP 27650 QUERY
+ENTRY_BEGIN
+RAW
+b854aa32501844703b560000008e31a0000000010001000000000f313238383439303138383831382d330000f900010f313238383439303138383831382d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403afce5403c4e6500030000002f4e544c4d535350000100000097b200e00800080027000000070007002000000047454c44455232494e5445524e45540000
+ENTRY_END
+
+STEP 27660 QUERY
+ENTRY_BEGIN
+RAW
+b8557ee25018fbb819b500000094158a000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403af92f403c4aaf0003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 27670 QUERY
+ENTRY_BEGIN
+RAW
+b8557ef05011fbaadc4e0000000000000000
+ENTRY_END
+
+STEP 27680 QUERY
+ENTRY_BEGIN
+RAW
+b854aa4050114462c4140000000000000000
+ENTRY_END
+
+STEP 27690 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f6150000020405b401010402
+ENTRY_END
+
+STEP 27700 QUERY
+ENTRY_BEGIN
+RAW
+b8557ef15010fbaadc4d0000000000000000
+ENTRY_END
+
+STEP 27710 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0a5b400000204059801010402
+ENTRY_END
+
+STEP 27720 QUERY
+ENTRY_BEGIN
+RAW
+b856f8ee5010fbb8203f0000000000000000
+ENTRY_END
+
+STEP 27730 QUERY
+ENTRY_BEGIN
+RAW
+b854aa4150104462c4130000000000000000
+ENTRY_END
+
+STEP 27740 QUERY
+ENTRY_BEGIN
+RAW
+b85652805010447013830000000000000000
+ENTRY_END
+
+STEP 27750 QUERY
+ENTRY_BEGIN
+RAW
+b856f8ee5018fbb8972200000094dc76000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af92f403c4aaf0003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 27760 QUERY
+ENTRY_BEGIN
+RAW
+b8565280501844705c5c0000008e6078000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afce5403c4e6500030000002f4e544c4d535350000100000097b200e00800080027000000070007002000000047454c44455232494e5445524e45540000
+ENTRY_END
+
+STEP 27770 QUERY
+ENTRY_BEGIN
+RAW
+b856f8fc5011fbaa1fa80000000000000000
+ENTRY_END
+
+STEP 27780 QUERY
+ENTRY_BEGIN
+RAW
+b856528e5011446212f20000000000000000
+ENTRY_END
+
+STEP 27790 QUERY
+ENTRY_BEGIN
+RAW
+b856f8fd5010fbaa1fa70000000000000000
+ENTRY_END
+
+STEP 27800 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000d2440000020405b401010402
+ENTRY_END
+
+STEP 27810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e5ea00000204059801010402
+ENTRY_END
+
+STEP 27820 QUERY
+ENTRY_BEGIN
+RAW
+b856528f5010446212f10000000000000000
+ENTRY_END
+
+STEP 27830 QUERY
+ENTRY_BEGIN
+RAW
+b8583c905010fbb81cd20000000000000000
+ENTRY_END
+
+STEP 27840 QUERY
+ENTRY_BEGIN
+RAW
+b857977e50104470aab20000000000000000
+ENTRY_END
+
+STEP 27850 QUERY
+ENTRY_BEGIN
+RAW
+b857977e50184470f99f0000008e5a64000000010001000000000f313238383439303138383831382d320000f900010f313238383439303138383831382d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403afce5403c4e6500030000002f4e544c4d535350000100000097b200e00800080027000000070007002000000047454c44455232494e5445524e45540000
+ENTRY_END
+
+STEP 27860 QUERY
+ENTRY_BEGIN
+RAW
+b8583c905018fbb876ff00000094f92c000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403af92f403c4aaf0003000000354e544c4d535350000100000097b208e0080008002d0000000d000d00200000005345525645522d434f4d5041514b4545524b4144450000
+ENTRY_END
+
+STEP 27870 QUERY
+ENTRY_BEGIN
+RAW
+b8583c9e5011fbaa1c3b0000000000000000
+ENTRY_END
+
+STEP 27880 QUERY
+ENTRY_BEGIN
+RAW
+b857978c50114462aa210000000000000000
+ENTRY_END
+
+STEP 27890 QUERY
+ENTRY_BEGIN
+RAW
+b8583c9f5010fbaa1c3a0000000000000000
+ENTRY_END
+
+STEP 27900 QUERY
+ENTRY_BEGIN
+RAW
+b857978d50104462aa200000000000000000
+ENTRY_END
+
+STEP 27910 QUERY
+ENTRY_BEGIN
+RAW
+000000007002223853ff00000204057801010402
+ENTRY_END
+
+STEP 27920 QUERY
+ENTRY_BEGIN
+RAW
+b85a8a295010264839e30000000000000000
+ENTRY_END
+
+STEP 27930 QUERY
+ENTRY_BEGIN
+RAW
+b85a8a2950182648986c0000008d7000000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 27940 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf02bcb0000020405b401010402
+ENTRY_END
+
+STEP 27950 QUERY
+ENTRY_BEGIN
+RAW
+b85a8a375011263a39530000000000000000
+ENTRY_END
+
+STEP 27960 QUERY
+ENTRY_BEGIN
+RAW
+b85b16615010faf089c20000000000000000
+ENTRY_END
+
+STEP 27970 QUERY
+ENTRY_BEGIN
+RAW
+00000000700222384d0d00000204057801010402
+ENTRY_END
+
+STEP 27980 QUERY
+ENTRY_BEGIN
+RAW
+b85b16615018faf0b5f40000009ba618000000010001000000000f313138353431303937333731342d330000f900010f313138353431303937333731342d330000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af563403c46e300030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 27990 QUERY
+ENTRY_BEGIN
+RAW
+b85b166f5011fae289240000000000000000
+ENTRY_END
+
+STEP 28000 QUERY
+ENTRY_BEGIN
+RAW
+b85b16705010fae289230000000000000000
+ENTRY_END
+
+STEP 28010 QUERY
+ENTRY_BEGIN
+RAW
+b85a8a385010263a39520000000000000000
+ENTRY_END
+
+STEP 28020 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf087d30000020405b401010402
+ENTRY_END
+
+STEP 28030 QUERY
+ENTRY_BEGIN
+RAW
+b85bdfe450102648dd340000000000000000
+ENTRY_END
+
+STEP 28040 QUERY
+ENTRY_BEGIN
+RAW
+b85cb74e5010faf044dc0000000000000000
+ENTRY_END
+
+STEP 28050 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400075820000020405b401010402
+ENTRY_END
+
+STEP 28060 QUERY
+ENTRY_BEGIN
+RAW
+b85cb74e5018faf0b5e70000009b6240000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af563403c46e300030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 28070 QUERY
+ENTRY_BEGIN
+RAW
+b85bdfe4501826489cbf0000008d1000000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 28080 QUERY
+ENTRY_BEGIN
+RAW
+b85cb75c5011fae2443e0000000000000000
+ENTRY_END
+
+STEP 28090 QUERY
+ENTRY_BEGIN
+RAW
+b85d4c1f5010447099490000000000000000
+ENTRY_END
+
+STEP 28100 QUERY
+ENTRY_BEGIN
+RAW
+b85d4c1f5018447060e70000008aa150000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd59403c4ed900030000002d4e544c4d535350000100000097b200c00b000b002200000002000200200000004153544543484e4f50414e454c0000
+ENTRY_END
+
+STEP 28110 QUERY
+ENTRY_BEGIN
+RAW
+b85cb75d5010fae2443d0000000000000000
+ENTRY_END
+
+STEP 28120 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf03cb70000020405b401010402
+ENTRY_END
+
+STEP 28130 QUERY
+ENTRY_BEGIN
+RAW
+b85dec5d5010faf0c4af0000000000000000
+ENTRY_END
+
+STEP 28140 QUERY
+ENTRY_BEGIN
+RAW
+b85d4c2d5011446298bc0000000000000000
+ENTRY_END
+
+STEP 28150 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000dacd0000020405b401010402
+ENTRY_END
+
+STEP 28160 QUERY
+ENTRY_BEGIN
+RAW
+b85dec5d5018faf08a890000009b0d72000000010001000000000f313138353431303937333731342d320000f900010f313138353431303937333731342d320000f900ff00000000005f03677373096d6963726f736f667403636f6d00403af563403c46e300030000003c4e544c4d535350000100000097b208e00d000d002f0000000f000f0020000000474f52494e4348454d324b2d5342535656562d474f52494e4348454d0000
+ENTRY_END
+
+STEP 28170 QUERY
+ENTRY_BEGIN
+RAW
+b85bdff25011263adca40000000000000000
+ENTRY_END
+
+STEP 28180 QUERY
+ENTRY_BEGIN
+RAW
+0000000070022238441700000204057801010402
+ENTRY_END
+
+STEP 28190 QUERY
+ENTRY_BEGIN
+RAW
+b85dec6b5011fae2c4110000000000000000
+ENTRY_END
+
+STEP 28200 QUERY
+ENTRY_BEGIN
+RAW
+b85d4c2e5010446298bb0000000000000000
+ENTRY_END
+
+STEP 28210 QUERY
+ENTRY_BEGIN
+RAW
+b85ec015501044708a9d0000000000000000
+ENTRY_END
+
+STEP 28220 QUERY
+ENTRY_BEGIN
+RAW
+b85dec6c5010fae2c4100000000000000000
+ENTRY_END
+
+STEP 28230 QUERY
+ENTRY_BEGIN
+RAW
+b85ec0155018447027ef0000008acd9c000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd59403c4ed900030000002d4e544c4d535350000100000097b200c00b000b002200000002000200200000004153544543484e4f50414e454c0000
+ENTRY_END
+
+STEP 28240 QUERY
+ENTRY_BEGIN
+RAW
+b85bdff35010263adca30000000000000000
+ENTRY_END
+
+STEP 28250 QUERY
+ENTRY_BEGIN
+RAW
+b85ec023501144628a100000000000000000
+ENTRY_END
+
+STEP 28260 QUERY
+ENTRY_BEGIN
+RAW
+b85f89fe501026482a210000000000000000
+ENTRY_END
+
+STEP 28270 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240007f700000020405b401010402
+ENTRY_END
+
+STEP 28280 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400035fd0000020405b401010402
+ENTRY_END
+
+STEP 28290 QUERY
+ENTRY_BEGIN
+RAW
+b860b22450104470f3bb0000000000000000
+ENTRY_END
+
+STEP 28300 QUERY
+ENTRY_BEGIN
+RAW
+b85ec024501044628a0f0000000000000000
+ENTRY_END
+
+STEP 28310 QUERY
+ENTRY_BEGIN
+RAW
+b85f89fe50182648b9ab0000008d4000000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403afcd7403c4e5700030000002e4e544c4d535350000100000097b200e0080008002600000006000600200000005345525645524e4b4f45524945520000
+ENTRY_END
+
+STEP 28320 QUERY
+ENTRY_BEGIN
+RAW
+b860b224501844700a5d0000008b8567000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd2a403c4eaa00030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 28330 QUERY
+ENTRY_BEGIN
+RAW
+b8600c6350104470e2f00000000000000000
+ENTRY_END
+
+STEP 28340 QUERY
+ENTRY_BEGIN
+RAW
+b8600c6350184470bba00000008a903e000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403afd5a403c4eda00030000002d4e544c4d535350000100000097b200c00b000b002200000002000200200000004153544543484e4f50414e454c0000
+ENTRY_END
+
+STEP 28350 QUERY
+ENTRY_BEGIN
+RAW
+b860b23250114462f32d0000000000000000
+ENTRY_END
+
+STEP 28360 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000aa9b0000020405b401010402
+ENTRY_END
+
+STEP 28370 QUERY
+ENTRY_BEGIN
+RAW
+b860b23350104462f32c0000000000000000
+ENTRY_END
+
+STEP 28380 QUERY
+ENTRY_BEGIN
+RAW
+b8600c7150114462e2630000000000000000
+ENTRY_END
+
+STEP 28390 QUERY
+ENTRY_BEGIN
+RAW
+b861437f50104470d6fe0000000000000000
+ENTRY_END
+
+STEP 28400 QUERY
+ENTRY_BEGIN
+RAW
+b861437f50184470a8780000008bcb8f000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd2a403c4eaa00030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 28410 QUERY
+ENTRY_BEGIN
+RAW
+b85f8a0c5011263a29910000000000000000
+ENTRY_END
+
+STEP 28420 QUERY
+ENTRY_BEGIN
+RAW
+b861438d50114462d6700000000000000000
+ENTRY_END
+
+STEP 28430 QUERY
+ENTRY_BEGIN
+RAW
+b8600c7250104462e2620000000000000000
+ENTRY_END
+
+STEP 28440 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000229f0000020405b401010402
+ENTRY_END
+
+STEP 28450 QUERY
+ENTRY_BEGIN
+RAW
+b861438e50104462d66f0000000000000000
+ENTRY_END
+
+STEP 28460 QUERY
+ENTRY_BEGIN
+RAW
+b863aebd50104470e3c10000000000000000
+ENTRY_END
+
+STEP 28470 QUERY
+ENTRY_BEGIN
+RAW
+b85f8a0d5010263a29900000000000000000
+ENTRY_END
+
+STEP 28480 QUERY
+ENTRY_BEGIN
+RAW
+b863aebd501844706f140000008b11b7000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000004f03677373096d6963726f736f667403636f6d00403afd2a403c4eaa00030000002c4e544c4d535350000100000097b200e0050005002700000007000700200000005348494e4530315348494e450000
+ENTRY_END
+
+STEP 28490 QUERY
+ENTRY_BEGIN
+RAW
+b863aecb50114462e3330000000000000000
+ENTRY_END
+
+STEP 28500 QUERY
+ENTRY_BEGIN
+RAW
+b863aecc50104462e3320000000000000000
+ENTRY_END
+
+STEP 28510 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e1130000020405b401010402
+ENTRY_END
+
+STEP 28520 QUERY
+ENTRY_BEGIN
+RAW
+b8676c6a5010faf0e8f50000000000000000
+ENTRY_END
+
+STEP 28530 QUERY
+ENTRY_BEGIN
+RAW
+b8676c6a5018faf0d99f0000008f5be8000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afda7403c4f270003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000444330314148584c30324148584c30320000
+ENTRY_END
+
+STEP 28540 QUERY
+ENTRY_BEGIN
+RAW
+b8676c785011fae2e8630000000000000000
+ENTRY_END
+
+STEP 28550 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b9b20000020405b401010402
+ENTRY_END
+
+STEP 28560 QUERY
+ENTRY_BEGIN
+RAW
+b8676c795010fae2e8620000000000000000
+ENTRY_END
+
+STEP 28570 QUERY
+ENTRY_BEGIN
+RAW
+b8684f895010faf0de740000000000000000
+ENTRY_END
+
+STEP 28580 QUERY
+ENTRY_BEGIN
+RAW
+b8684f895018faf0a85b0000008f83ac000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afda7403c4f270003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000444330314148584c30324148584c30320000
+ENTRY_END
+
+STEP 28590 QUERY
+ENTRY_BEGIN
+RAW
+b8684f975011fae2dde20000000000000000
+ENTRY_END
+
+STEP 28600 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf096770000020405b401010402
+ENTRY_END
+
+STEP 28610 QUERY
+ENTRY_BEGIN
+RAW
+b8684f985010fae2dde10000000000000000
+ENTRY_END
+
+STEP 28620 QUERY
+ENTRY_BEGIN
+RAW
+b868d4a65010faf0361c0000000000000000
+ENTRY_END
+
+STEP 28630 QUERY
+ENTRY_BEGIN
+RAW
+b868d4a65018faf0bc1c0000008fc792000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afda7403c4f270003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000444330314148584c30324148584c30320000
+ENTRY_END
+
+STEP 28640 QUERY
+ENTRY_BEGIN
+RAW
+b868d4b45011fae2358a0000000000000000
+ENTRY_END
+
+STEP 28650 QUERY
+ENTRY_BEGIN
+RAW
+b868d4b55010fae235890000000000000000
+ENTRY_END
+
+STEP 28660 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0285d0000020405b401010402
+ENTRY_END
+
+STEP 28670 QUERY
+ENTRY_BEGIN
+RAW
+b86a79785010faf0232e0000000000000000
+ENTRY_END
+
+STEP 28680 QUERY
+ENTRY_BEGIN
+RAW
+b86a79785018faf049cd0000008da9c3000000010001000000000e3839333335333139373538362d330000f900010e3839333335333139373538362d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdb8403c4f380003000000304e544c4d535350000100000097b208e00700070029000000090009002000000050435f50494554455248414d41544e4c0000
+ENTRY_END
+
+STEP 28690 QUERY
+ENTRY_BEGIN
+RAW
+b86a79865011fae2229e0000000000000000
+ENTRY_END
+
+STEP 28700 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf025ca0000020405b401010402
+ENTRY_END
+
+STEP 28710 QUERY
+ENTRY_BEGIN
+RAW
+b86a79875010fae2229d0000000000000000
+ENTRY_END
+
+STEP 28720 QUERY
+ENTRY_BEGIN
+RAW
+b86b60fc5010faf039160000000000000000
+ENTRY_END
+
+STEP 28730 QUERY
+ENTRY_BEGIN
+RAW
+b86b60fc5018faf03bd00000008dcfa8000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdb8403c4f380003000000304e544c4d535350000100000097b208e00700070029000000090009002000000050435f50494554455248414d41544e4c0000
+ENTRY_END
+
+STEP 28740 QUERY
+ENTRY_BEGIN
+RAW
+b86b610a5011fae238860000000000000000
+ENTRY_END
+
+STEP 28750 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f53f0000020405b401010402
+ENTRY_END
+
+STEP 28760 QUERY
+ENTRY_BEGIN
+RAW
+b86b610b5010fae238850000000000000000
+ENTRY_END
+
+STEP 28770 QUERY
+ENTRY_BEGIN
+RAW
+b86bf32d5010faf0765a0000000000000000
+ENTRY_END
+
+STEP 28780 QUERY
+ENTRY_BEGIN
+RAW
+b86bf32d5018faf05d640000008deb58000000010001000000000e3839333335333139373538362d320000f900010e3839333335333139373538362d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afdb8403c4f380003000000304e544c4d535350000100000097b208e00700070029000000090009002000000050435f50494554455248414d41544e4c0000
+ENTRY_END
+
+STEP 28790 QUERY
+ENTRY_BEGIN
+RAW
+b86bf33b5011fae275ca0000000000000000
+ENTRY_END
+
+STEP 28800 QUERY
+ENTRY_BEGIN
+RAW
+b86bf33c5010fae275c90000000000000000
+ENTRY_END
+
+STEP 28810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf085460000020405b401010402
+ENTRY_END
+
+STEP 28820 QUERY
+ENTRY_BEGIN
+RAW
+b86cc7b65010fbec30db0000000000000000
+ENTRY_END
+
+STEP 28830 QUERY
+ENTRY_BEGIN
+RAW
+b86cc7b65018fbecbc930000008d0bd8000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff84403c510400030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 28840 QUERY
+ENTRY_BEGIN
+RAW
+b86cc7c45011fbde304b0000000000000000
+ENTRY_END
+
+STEP 28850 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf003060000020405b401010402
+ENTRY_END
+
+STEP 28860 QUERY
+ENTRY_BEGIN
+RAW
+b86cc7c55010fbde304a0000000000000000
+ENTRY_END
+
+STEP 28870 QUERY
+ENTRY_BEGIN
+RAW
+b86eaaeb5010fbeccb630000000000000000
+ENTRY_END
+
+STEP 28880 QUERY
+ENTRY_BEGIN
+RAW
+b86eaaeb5018fbec587d0000008d0b78000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff84403c510400030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 28890 QUERY
+ENTRY_BEGIN
+RAW
+b86eaaf95011fbdecad30000000000000000
+ENTRY_END
+
+STEP 28900 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d33e0000020405b401010402
+ENTRY_END
+
+STEP 28910 QUERY
+ENTRY_BEGIN
+RAW
+b86eaafa5010fbdecad20000000000000000
+ENTRY_END
+
+STEP 28920 QUERY
+ENTRY_BEGIN
+RAW
+b86f5d985010fbece8ee0000000000000000
+ENTRY_END
+
+STEP 28930 QUERY
+ENTRY_BEGIN
+RAW
+b86f5d985018fbec36500000008d4b30000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005103677373096d6963726f736f667403636f6d00403aff84403c510400030000002e4e544c4d535350000100000097b208e005000500290000000900090020000000494e5445524e455431454c414e320000
+ENTRY_END
+
+STEP 28940 QUERY
+ENTRY_BEGIN
+RAW
+b86f5da65011fbdee85e0000000000000000
+ENTRY_END
+
+STEP 28950 QUERY
+ENTRY_BEGIN
+RAW
+b86f5da75010fbdee85d0000000000000000
+ENTRY_END
+
+STEP 28960 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000ddd30000020405b401010402
+ENTRY_END
+
+STEP 28970 QUERY
+ENTRY_BEGIN
+RAW
+b86ffc6a50104470513d0000000000000000
+ENTRY_END
+
+STEP 28980 QUERY
+ENTRY_BEGIN
+RAW
+b86ffc6a50184470fc390000009600da000000010001000000000f313233363935303538313236362d330000f900010f313233363935303538313236362d330000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd2b403c4eab0003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 28990 QUERY
+ENTRY_BEGIN
+RAW
+b86ffc785011446250a40000000000000000
+ENTRY_END
+
+STEP 29000 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000f56e0000020405b401010402
+ENTRY_END
+
+STEP 29010 QUERY
+ENTRY_BEGIN
+RAW
+b86ffc795010446250a30000000000000000
+ENTRY_END
+
+STEP 29020 QUERY
+ENTRY_BEGIN
+RAW
+b870e1475010447083fa0000000000000000
+ENTRY_END
+
+STEP 29030 QUERY
+ENTRY_BEGIN
+RAW
+b870e147501844709691000000969a40000000010001000000000f313233363935303538313236362d320000f900010f313233363935303538313236362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd2b403c4eab0003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 29040 QUERY
+ENTRY_BEGIN
+RAW
+b870e1555011446283610000000000000000
+ENTRY_END
+
+STEP 29050 QUERY
+ENTRY_BEGIN
+RAW
+000000007002400031f30000020405b401010402
+ENTRY_END
+
+STEP 29060 QUERY
+ENTRY_BEGIN
+RAW
+b870e1565010446283600000000000000000
+ENTRY_END
+
+STEP 29070 QUERY
+ENTRY_BEGIN
+RAW
+b871b54f50104470ec750000000000000000
+ENTRY_END
+
+STEP 29080 QUERY
+ENTRY_BEGIN
+RAW
+b871b54f50184470e88c00000096b0c0000000010001000000000f313233363935303538313236362d320000f900010f313233363935303538313236362d320000f900ff00000000005a03677373096d6963726f736f667403636f6d00403afd2b403c4eab0003000000374e544c4d535350000100000097b208e00a000a002d0000000d000d0020000000504443544f5047524f57455253544f5047524f574552530000
+ENTRY_END
+
+STEP 29090 QUERY
+ENTRY_BEGIN
+RAW
+b871b55d50114462ebdc0000000000000000
+ENTRY_END
+
+STEP 29100 QUERY
+ENTRY_BEGIN
+RAW
+b871b55e50104462ebdb0000000000000000
+ENTRY_END
+
+STEP 29110 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0225800000204055001010402
+ENTRY_END
+
+STEP 29120 QUERY
+ENTRY_BEGIN
+RAW
+b873d47b5010ff00bda80000000000000000
+ENTRY_END
+
+STEP 29130 QUERY
+ENTRY_BEGIN
+RAW
+b873d47b5018ff002785000000923da3000000010001000000000f313531313832383438383231302d330000f900010f313531313832383438383231302d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403b0027403c51a70003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 29140 QUERY
+ENTRY_BEGIN
+RAW
+b873d4895011fef2bd130000000000000000
+ENTRY_END
+
+STEP 29150 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0f7480000020405b401010402
+ENTRY_END
+
+STEP 29160 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0332200000204055001010402
+ENTRY_END
+
+STEP 29170 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf07aff0000020405b401010402
+ENTRY_END
+
+STEP 29180 QUERY
+ENTRY_BEGIN
+RAW
+b873d48a5010fef2bd120000000000000000
+ENTRY_END
+
+STEP 29190 QUERY
+ENTRY_BEGIN
+RAW
+b8756c445010ff0036a80000000000000000
+ENTRY_END
+
+STEP 29200 QUERY
+ENTRY_BEGIN
+RAW
+b8760bd75010faf0e3650000000000000000
+ENTRY_END
+
+STEP 29210 QUERY
+ENTRY_BEGIN
+RAW
+b874af045010faf0bc830000000000000000
+ENTRY_END
+
+STEP 29220 QUERY
+ENTRY_BEGIN
+RAW
+b8756c445018ff00da670000009204c1000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b0027403c51a70003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 29230 QUERY
+ENTRY_BEGIN
+RAW
+b874af045018faf097a50000009250ac000000010001000000000f313330353637303035383030322d330000f900010f313330353637303035383030322d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e0080008002b0000000b000b002000000047454d534c44573230303047454d534c44324b0000
+ENTRY_END
+
+STEP 29240 QUERY
+ENTRY_BEGIN
+RAW
+b8760bd75018faf0c670000000955c40000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd89403c4f090003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29250 QUERY
+ENTRY_BEGIN
+RAW
+b8760be55011fae2e2cd0000000000000000
+ENTRY_END
+
+STEP 29260 QUERY
+ENTRY_BEGIN
+RAW
+b8756c525011fef236130000000000000000
+ENTRY_END
+
+STEP 29270 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0cc390000020405b401010402
+ENTRY_END
+
+STEP 29280 QUERY
+ENTRY_BEGIN
+RAW
+b874af125011fae2bbee0000000000000000
+ENTRY_END
+
+STEP 29290 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0865700000204055001010402
+ENTRY_END
+
+STEP 29300 QUERY
+ENTRY_BEGIN
+RAW
+b8760be65010fae2e2cc0000000000000000
+ENTRY_END
+
+STEP 29310 QUERY
+ENTRY_BEGIN
+RAW
+b87704245010faf03c520000000000000000
+ENTRY_END
+
+STEP 29320 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0d3060000020405b401010402
+ENTRY_END
+
+STEP 29330 QUERY
+ENTRY_BEGIN
+RAW
+b8756c535010fef236120000000000000000
+ENTRY_END
+
+STEP 29340 QUERY
+ENTRY_BEGIN
+RAW
+b8778b1f5010ff006b000000000000000000
+ENTRY_END
+
+STEP 29350 QUERY
+ENTRY_BEGIN
+RAW
+b87704245018faf0c21d00000095ba80000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd89403c4f090003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29360 QUERY
+ENTRY_BEGIN
+RAW
+b874af135010fae2bbed0000000000000000
+ENTRY_END
+
+STEP 29370 QUERY
+ENTRY_BEGIN
+RAW
+b8778b1f5018ff007616000000929d6a000000010001000000000f313531313832383438383231302d320000f900010f313531313832383438383231302d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b0027403c51a70003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 29380 QUERY
+ENTRY_BEGIN
+RAW
+b87704325011fae23bba0000000000000000
+ENTRY_END
+
+STEP 29390 QUERY
+ENTRY_BEGIN
+RAW
+b8784b705010faf0fbd10000000000000000
+ENTRY_END
+
+STEP 29400 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf035460000020405b401010402
+ENTRY_END
+
+STEP 29410 QUERY
+ENTRY_BEGIN
+RAW
+b8784b705018faf060fe00000092c7a2000000010001000000000f313330353637303035383030322d320000f900010f313330353637303035383030322d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e0080008002b0000000b000b002000000047454d534c44573230303047454d534c44324b0000
+ENTRY_END
+
+STEP 29420 QUERY
+ENTRY_BEGIN
+RAW
+b8778b2d5011fef26a6b0000000000000000
+ENTRY_END
+
+STEP 29430 QUERY
+ENTRY_BEGIN
+RAW
+b87704335010fae23bb90000000000000000
+ENTRY_END
+
+STEP 29440 QUERY
+ENTRY_BEGIN
+RAW
+b878f3165010faf0b66a0000000000000000
+ENTRY_END
+
+STEP 29450 QUERY
+ENTRY_BEGIN
+RAW
+b8778b2e5010fef26a6a0000000000000000
+ENTRY_END
+
+STEP 29460 QUERY
+ENTRY_BEGIN
+RAW
+b878f3165018faf0a036000000955680000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd89403c4f090003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29470 QUERY
+ENTRY_BEGIN
+RAW
+b8784b7e5011fae2fb3c0000000000000000
+ENTRY_END
+
+STEP 29480 QUERY
+ENTRY_BEGIN
+RAW
+b878f3245011fae2b5d20000000000000000
+ENTRY_END
+
+STEP 29490 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0ea1e0000020405b401010402
+ENTRY_END
+
+STEP 29500 QUERY
+ENTRY_BEGIN
+RAW
+b8784b7f5010fae2fb3b0000000000000000
+ENTRY_END
+
+STEP 29510 QUERY
+ENTRY_BEGIN
+RAW
+b878f3255010fae2b5d10000000000000000
+ENTRY_END
+
+STEP 29520 QUERY
+ENTRY_BEGIN
+RAW
+b87984425010faf0da160000000000000000
+ENTRY_END
+
+STEP 29530 QUERY
+ENTRY_BEGIN
+RAW
+b87984425018faf0c84d000000923e98000000010001000000000f313330353637303035383030322d320000f900010f313330353637303035383030322d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403afd0f403c4e8f0003000000334e544c4d535350000100000097b208e0080008002b0000000b000b002000000047454d534c44573230303047454d534c44324b0000
+ENTRY_END
+
+STEP 29540 QUERY
+ENTRY_BEGIN
+RAW
+b87984505011fae2d9810000000000000000
+ENTRY_END
+
+STEP 29550 QUERY
+ENTRY_BEGIN
+RAW
+b87984515010fae2d9800000000000000000
+ENTRY_END
+
+STEP 29560 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf05a680000020405b401010402
+ENTRY_END
+
+STEP 29570 QUERY
+ENTRY_BEGIN
+RAW
+b87a075c5010faf0c7450000000000000000
+ENTRY_END
+
+STEP 29580 QUERY
+ENTRY_BEGIN
+RAW
+b87a075c5018faf0598400000088bd00000000010001000000000f313432353932393134323239302d330000f900010f313432353932393134323239302d330000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe8d403c500d0003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 29590 QUERY
+ENTRY_BEGIN
+RAW
+b87a076a5011fae2c6ba0000000000000000
+ENTRY_END
+
+STEP 29600 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf01b310000020405b401010402
+ENTRY_END
+
+STEP 29610 QUERY
+ENTRY_BEGIN
+RAW
+b87a076b5010fae2c6b90000000000000000
+ENTRY_END
+
+STEP 29620 QUERY
+ENTRY_BEGIN
+RAW
+b87c49885010faf045e00000000000000000
+ENTRY_END
+
+STEP 29630 QUERY
+ENTRY_BEGIN
+RAW
+b87c49885018faf02e20000000886800000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe8d403c500d0003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 29640 QUERY
+ENTRY_BEGIN
+RAW
+b87c49965011fae245550000000000000000
+ENTRY_END
+
+STEP 29650 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf02f960000020405b401010402
+ENTRY_END
+
+STEP 29660 QUERY
+ENTRY_BEGIN
+RAW
+b87c49975010fae245540000000000000000
+ENTRY_END
+
+STEP 29670 QUERY
+ENTRY_BEGIN
+RAW
+b87d3c4e5010faf0677e0000000000000000
+ENTRY_END
+
+STEP 29680 QUERY
+ENTRY_BEGIN
+RAW
+b87d3c4e5018faf05abe000000885b00000000010001000000000f313432353932393134323239302d320000f900010f313432353932393134323239302d320000f900ff00000000004c03677373096d6963726f736f667403636f6d00403afe8e403c500e0003000000294e544c4d535350000100000097b208e0030003002600000006000600200000005345525645524442470000
+ENTRY_END
+
+STEP 29690 QUERY
+ENTRY_BEGIN
+RAW
+b87d3c5c5011fae266f30000000000000000
+ENTRY_END
+
+STEP 29700 QUERY
+ENTRY_BEGIN
+RAW
+b87d3c5d5010fae266f20000000000000000
+ENTRY_END
+
+STEP 29710 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000eb4a0000020405b401010402
+ENTRY_END
+
+STEP 29720 QUERY
+ENTRY_BEGIN
+RAW
+b87f0582501005b494490000000000000000
+ENTRY_END
+
+STEP 29730 QUERY
+ENTRY_BEGIN
+RAW
+b87f058250184470519b0000008cc780000000010001000000000f313036353135313838393432362d330000f900010f313036353135313838393432362d330000f900ff00000000005003677373096d6963726f736f667403636f6d00403af2f9403c447900030000002d4e544c4d535350000100000097b200e0080008002500000005000500200000004c55584f52494e5445524e45540000
+ENTRY_END
+
+STEP 29740 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240000e870000020405b401010402
+ENTRY_END
+
+STEP 29750 QUERY
+ENTRY_BEGIN
+RAW
+b87f97b7501005b425500000000000000000
+ENTRY_END
+
+STEP 29760 QUERY
+ENTRY_BEGIN
+RAW
+b87f97b75018447052630000008c58c0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403af2f9403c447900030000002d4e544c4d535350000100000097b200e0080008002500000005000500200000004c55584f52494e5445524e45540000
+ENTRY_END
+
+STEP 29770 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0bdf60000020405b401010402
+ENTRY_END
+
+STEP 29780 QUERY
+ENTRY_BEGIN
+RAW
+b8807c0e5010faf0b61b0000000000000000
+ENTRY_END
+
+STEP 29790 QUERY
+ENTRY_BEGIN
+RAW
+b8807c0e5018faf0e626000000950d40000000010001000000000f313231393737303731323038322d330000f900010f313231393737303731323038322d330000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd8a403c4f0a0003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29800 QUERY
+ENTRY_BEGIN
+RAW
+b8807c1c5011fae2b5830000000000000000
+ENTRY_END
+
+STEP 29810 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0c3a40000020405b401010402
+ENTRY_END
+
+STEP 29820 QUERY
+ENTRY_BEGIN
+RAW
+b8807c1d5010fae2b5820000000000000000
+ENTRY_END
+
+STEP 29830 QUERY
+ENTRY_BEGIN
+RAW
+b88124355010faf013a20000000000000000
+ENTRY_END
+
+STEP 29840 QUERY
+ENTRY_BEGIN
+RAW
+b88124355018faf0e66d000000956b80000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd8a403c4f0a0003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29850 QUERY
+ENTRY_BEGIN
+RAW
+b88124435011fae2130a0000000000000000
+ENTRY_END
+
+STEP 29860 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf018ba0000020405b401010402
+ENTRY_END
+
+STEP 29870 QUERY
+ENTRY_BEGIN
+RAW
+b88124445010fae213090000000000000000
+ENTRY_END
+
+STEP 29880 QUERY
+ENTRY_BEGIN
+RAW
+b881d8d95010faf0b4120000000000000000
+ENTRY_END
+
+STEP 29890 QUERY
+ENTRY_BEGIN
+RAW
+b881d8d95018faf04ede00000095a380000000010001000000000f313231393737303731323038322d320000f900010f313231393737303731323038322d320000f900ff00000000005903677373096d6963726f736f667403636f6d00403afd8a403c4f0a0003000000364e544c4d535350000100000097b208e00b000b002b0000000b000b002000000044432d48554e54534d414e424953475645524f4c4d450000
+ENTRY_END
+
+STEP 29900 QUERY
+ENTRY_BEGIN
+RAW
+b881d8e75011fae2b37a0000000000000000
+ENTRY_END
+
+STEP 29910 QUERY
+ENTRY_BEGIN
+RAW
+b881d8e85010fae2b3790000000000000000
+ENTRY_END
+
+STEP 29920 QUERY
+ENTRY_BEGIN
+RAW
+b87f97c550114462e6040000000000000000
+ENTRY_END
+
+STEP 29930 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000e5880000020405b401010402
+ENTRY_END
+
+STEP 29940 QUERY
+ENTRY_BEGIN
+RAW
+b87f97c650104462e6030000000000000000
+ENTRY_END
+
+STEP 29950 QUERY
+ENTRY_BEGIN
+RAW
+b8866f32501005b424d00000000000000000
+ENTRY_END
+
+STEP 29960 QUERY
+ENTRY_BEGIN
+RAW
+b8866f3250184470a3e30000008c04c0000000010001000000000f313036353135313838393432362d320000f900010f313036353135313838393432362d320000f900ff00000000005003677373096d6963726f736f667403636f6d00403af2fa403c447a00030000002d4e544c4d535350000100000097b200e0080008002500000005000500200000004c55584f52494e5445524e45540000
+ENTRY_END
+
+STEP 29970 QUERY
+ENTRY_BEGIN
+RAW
+b8866f4050114462e5840000000000000000
+ENTRY_END
+
+STEP 29980 QUERY
+ENTRY_BEGIN
+RAW
+b8866f4150104462e5830000000000000000
+ENTRY_END
+
+STEP 29990 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff00758500000204055001010402
+ENTRY_END
+
+STEP 30000 QUERY
+ENTRY_BEGIN
+RAW
+b8873df25010ff00ab5b0000000000000000
+ENTRY_END
+
+STEP 30010 QUERY
+ENTRY_BEGIN
+RAW
+b8873df25018ff001b780000008f5b0e000000010001000000000f313034373937323032303234322d330000f900010f313034373937323032303234322d330000f900ff00000000005303677373096d6963726f736f667403636f6d00403afe3d403c4fbd0003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+STEP 30020 QUERY
+ENTRY_BEGIN
+RAW
+b8873e005011fef2aac90000000000000000
+ENTRY_END
+
+STEP 30030 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff001e8b00000204055001010402
+ENTRY_END
+
+STEP 30040 QUERY
+ENTRY_BEGIN
+RAW
+b8873e015010fef2aac80000000000000000
+ENTRY_END
+
+STEP 30050 QUERY
+ENTRY_BEGIN
+RAW
+b887f30b5010ff009f470000000000000000
+ENTRY_END
+
+STEP 30060 QUERY
+ENTRY_BEGIN
+RAW
+b87f05905010446254fe0000000000000000
+ENTRY_END
+
+STEP 30070 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240003e080000020405b401010402
+ENTRY_END
+
+STEP 30080 QUERY
+ENTRY_BEGIN
+RAW
+b8888b9e5010447022250000000000000000
+ENTRY_END
+
+STEP 30090 QUERY
+ENTRY_BEGIN
+RAW
+b8888b9e50184470c7750000008e386c000000010001000000000e3936323037323637343332322d330000f900010e3936323037323637343332322d330000f900ff00000000005403677373096d6963726f736f667403636f6d0032f53d9532f68f150003000000314e544c4d535350000100000097b200c00b000b002600000006000600200000004d455849434f57454e4e454b45534e45540000
+ENTRY_END
+
+STEP 30100 QUERY
+ENTRY_BEGIN
+RAW
+b8888bac5011446221940000000000000000
+ENTRY_END
+
+STEP 30110 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a7870000020405b401010402
+ENTRY_END
+
+STEP 30120 QUERY
+ENTRY_BEGIN
+RAW
+b8888bad5010446221930000000000000000
+ENTRY_END
+
+STEP 30130 QUERY
+ENTRY_BEGIN
+RAW
+b88953b450104470c38d0000000000000000
+ENTRY_END
+
+STEP 30140 QUERY
+ENTRY_BEGIN
+RAW
+b88953b450184470223e0000008e810c000000010001000000000e3936323037323637343332322d320000f900010e3936323037323637343332322d320000f900ff00000000005403677373096d6963726f736f667403636f6d0032f53d9532f68f150003000000314e544c4d535350000100000097b200c00b000b002600000006000600200000004d455849434f57454e4e454b45534e45540000
+ENTRY_END
+
+STEP 30150 QUERY
+ENTRY_BEGIN
+RAW
+b88953c250114462c2fc0000000000000000
+ENTRY_END
+
+STEP 30160 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000525e0000020405b401010402
+ENTRY_END
+
+STEP 30170 QUERY
+ENTRY_BEGIN
+RAW
+b88953c350104462c2fb0000000000000000
+ENTRY_END
+
+STEP 30180 QUERY
+ENTRY_BEGIN
+RAW
+b88b7a195010447047fd0000000000000000
+ENTRY_END
+
+STEP 30190 QUERY
+ENTRY_BEGIN
+RAW
+b88b7a195018447009840000008e1e36000000010001000000000e3936323037323637343332322d320000f900010e3936323037323637343332322d320000f900ff00000000005403677373096d6963726f736f667403636f6d0032f53d9532f68f150003000000314e544c4d535350000100000097b200c00b000b002600000006000600200000004d455849434f57454e4e454b45534e45540000
+ENTRY_END
+
+STEP 30200 QUERY
+ENTRY_BEGIN
+RAW
+b88b7a2750114462476c0000000000000000
+ENTRY_END
+
+STEP 30210 QUERY
+ENTRY_BEGIN
+RAW
+b88b7a2850104462476b0000000000000000
+ENTRY_END
+
+STEP 30220 QUERY
+ENTRY_BEGIN
+RAW
+b87f05905011446254fe0000000000000000
+ENTRY_END
+
+STEP 30230 QUERY
+ENTRY_BEGIN
+RAW
+b87f05915010446254fd0000000000000000
+ENTRY_END
+
+STEP 30240 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf089aa00000204055001010402
+ENTRY_END
+
+STEP 30250 QUERY
+ENTRY_BEGIN
+RAW
+b89059d55010ff009f840000000000000000
+ENTRY_END
+
+STEP 30260 QUERY
+ENTRY_BEGIN
+RAW
+b89059d55018ff00bd6e000000927286000000010001000000000f313436303238383838303635382d330000f900010f313436303238383838303635382d330000f900ff00000000005603677373096d6963726f736f667403636f6d00403b002b403c51ab0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 30270 QUERY
+ENTRY_BEGIN
+RAW
+b89059e35011fef29eef0000000000000000
+ENTRY_END
+
+STEP 30280 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf08e5d00000204055001010402
+ENTRY_END
+
+STEP 30290 QUERY
+ENTRY_BEGIN
+RAW
+b89059e45010fef29eee0000000000000000
+ENTRY_END
+
+STEP 30300 QUERY
+ENTRY_BEGIN
+RAW
+b89138d85010ff00c5330000000000000000
+ENTRY_END
+
+STEP 30310 QUERY
+ENTRY_BEGIN
+RAW
+b89138d85018ff00a8dc00000092adc8000000010001000000000f313436303238383838303635382d320000f900010f313436303238383838303635382d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b002b403c51ab0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 30320 QUERY
+ENTRY_BEGIN
+RAW
+b89138e65011fef2c49e0000000000000000
+ENTRY_END
+
+STEP 30330 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0622900000204055001010402
+ENTRY_END
+
+STEP 30340 QUERY
+ENTRY_BEGIN
+RAW
+b89138e75010fef2c49d0000000000000000
+ENTRY_END
+
+STEP 30350 QUERY
+ENTRY_BEGIN
+RAW
+b893d5bc5010ff00fc180000000000000000
+ENTRY_END
+
+STEP 30360 QUERY
+ENTRY_BEGIN
+RAW
+b893d5bc5018ff004d31000000924059000000010001000000000f313436303238383838303635382d320000f900010f313436303238383838303635382d320000f900ff00000000005603677373096d6963726f736f667403636f6d00403b002b403c51ab0003000000334e544c4d535350000100000097b208e0090009002a0000000a000a002000000057324b5345525645523150524b564457494c440000
+ENTRY_END
+
+STEP 30370 QUERY
+ENTRY_BEGIN
+RAW
+b893d5ca5011fef2fb830000000000000000
+ENTRY_END
+
+STEP 30380 QUERY
+ENTRY_BEGIN
+RAW
+b893d5cb5010fef2fb820000000000000000
+ENTRY_END
+
+;STEP 30390 QUERY
+;ENTRY_BEGIN
+;RAW
+;2c4801000001000000000000056b6f726e6f026e6c00000f000100
+;ENTRY_END
+
+STEP 30400 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240005b1100000204055001010402
+ENTRY_END
+
+STEP 30410 QUERY
+ENTRY_BEGIN
+RAW
+b887f30b5018ff0072d80000008ff89a000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afe3d403c4fbd0003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+STEP 30420 QUERY
+ENTRY_BEGIN
+RAW
+b887f3195011fef29eb50000000000000000
+ENTRY_END
+
+STEP 30430 QUERY
+ENTRY_BEGIN
+RAW
+000000007002ff00e15100000204055001010402
+ENTRY_END
+
+STEP 30440 QUERY
+ENTRY_BEGIN
+RAW
+b887f31a5010fef29eb40000000000000000
+ENTRY_END
+
+STEP 30450 QUERY
+ENTRY_BEGIN
+RAW
+b8971ae65010ff003a240000000000000000
+ENTRY_END
+
+STEP 30460 QUERY
+ENTRY_BEGIN
+RAW
+b8971ae65018ff00a9f90000008f5656000000010001000000000f313034373937323032303234322d320000f900010f313034373937323032303234322d320000f900ff00000000005303677373096d6963726f736f667403636f6d00403afe40403c4fc00003000000304e544c4d535350000100000097b208e0060006002a0000000a000a0020000000524f4353455256455232524f435655450000
+ENTRY_END
+
+STEP 30470 QUERY
+ENTRY_BEGIN
+RAW
+b8971af45011fef239920000000000000000
+ENTRY_END
+
+STEP 30480 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06fb40000020405b401010402
+ENTRY_END
+
+STEP 30490 QUERY
+ENTRY_BEGIN
+RAW
+b8971af55010fef239910000000000000000
+ENTRY_END
+
+STEP 30500 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf07bee0000020405b401010402
+ENTRY_END
+
+STEP 30510 QUERY
+ENTRY_BEGIN
+RAW
+b898e9c85010faf006410000000000000000
+ENTRY_END
+
+STEP 30520 QUERY
+ENTRY_BEGIN
+RAW
+00000000700240002fbf00000204057a01010402
+ENTRY_END
+
+STEP 30530 QUERY
+ENTRY_BEGIN
+RAW
+b89baf9f501041b8f2450000000000000000
+ENTRY_END
+
+STEP 30540 QUERY
+ENTRY_BEGIN
+RAW
+b89baf9f501841b8f68800000094b100000000010001000000000f313133333837313336363136322d330000f900010f313133333837313336363136322d330000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa7e403c4bfe0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 30550 QUERY
+ENTRY_BEGIN
+RAW
+b89bafad501141aaf1ae0000000000000000
+ENTRY_END
+
+STEP 30560 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000a23a00000204057a01010402
+ENTRY_END
+
+STEP 30570 QUERY
+ENTRY_BEGIN
+RAW
+b89bafae501041aaf1ad0000000000000000
+ENTRY_END
+
+STEP 30580 QUERY
+ENTRY_BEGIN
+RAW
+b89c5852501041b8bc0d0000000000000000
+ENTRY_END
+
+STEP 30590 QUERY
+ENTRY_BEGIN
+RAW
+b89c5852501841b8f051000000948200000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa7e403c4bfe0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 30600 QUERY
+ENTRY_BEGIN
+RAW
+b89c5860501141aabb760000000000000000
+ENTRY_END
+
+STEP 30610 QUERY
+ENTRY_BEGIN
+RAW
+0000000070024000da6600000204057a01010402
+ENTRY_END
+
+STEP 30620 QUERY
+ENTRY_BEGIN
+RAW
+b89c5861501041aabb750000000000000000
+ENTRY_END
+
+STEP 30630 QUERY
+ENTRY_BEGIN
+RAW
+b89cfce5501041b84fa60000000000000000
+ENTRY_END
+
+STEP 30640 QUERY
+ENTRY_BEGIN
+RAW
+b89cfce5501841b8b2ea000000945300000000010001000000000f313133333837313336363136322d320000f900010f313133333837313336363136322d320000f900ff00000000005803677373096d6963726f736f667403636f6d00403afa7e403c4bfe0003000000354e544c4d535350000100000097b200e0090009002c0000000c000c0020000000534253504952414d4944454e504952414d4944454e0000
+ENTRY_END
+
+STEP 30650 QUERY
+ENTRY_BEGIN
+RAW
+b89cfcf3501141aa4f0f0000000000000000
+ENTRY_END
+
+STEP 30660 QUERY
+ENTRY_BEGIN
+RAW
+b89cfcf4501041aa4f0e0000000000000000
+ENTRY_END
+
+STEP 30670 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf06c420000020405b401010402
+ENTRY_END
+
+STEP 30680 QUERY
+ENTRY_BEGIN
+RAW
+b89f748d5010faf06bc90000000000000000
+ENTRY_END
+
+STEP 30690 QUERY
+ENTRY_BEGIN
+RAW
+b89f748d5018faf029bd0000008ed048000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403af976403c4af600030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005453444f43554f4c59534c414745520000
+ENTRY_END
+
+STEP 30700 QUERY
+ENTRY_BEGIN
+RAW
+b89f749b5011fae26b380000000000000000
+ENTRY_END
+
+STEP 30710 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf091260000020405b401010402
+ENTRY_END
+
+STEP 30720 QUERY
+ENTRY_BEGIN
+RAW
+b89f749c5010fae26b370000000000000000
+ENTRY_END
+
+STEP 30730 QUERY
+ENTRY_BEGIN
+RAW
+b8a055e75010faf0af520000000000000000
+ENTRY_END
+
+STEP 30740 QUERY
+ENTRY_BEGIN
+RAW
+b8a055e75018faf0a56c0000008e9923000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af976403c4af600030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005453444f43554f4c59534c414745520000
+ENTRY_END
+
+STEP 30750 QUERY
+ENTRY_BEGIN
+RAW
+b8a055f55011fae2aec10000000000000000
+ENTRY_END
+
+STEP 30760 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0a72f0000020405b401010402
+ENTRY_END
+
+STEP 30770 QUERY
+ENTRY_BEGIN
+RAW
+b8a055f65010fae2aec00000000000000000
+ENTRY_END
+
+STEP 30780 QUERY
+ENTRY_BEGIN
+RAW
+b8a134165010faf0e72b0000000000000000
+ENTRY_END
+
+STEP 30790 QUERY
+ENTRY_BEGIN
+RAW
+b8a134165018faf0631b0000008e134e000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af976403c4af600030000002f4e544c4d535350000100000097b208e0090009002600000006000600200000005453444f43554f4c59534c414745520000
+ENTRY_END
+
+STEP 30800 QUERY
+ENTRY_BEGIN
+RAW
+b8a134245011fae2e69a0000000000000000
+ENTRY_END
+
+STEP 30810 QUERY
+ENTRY_BEGIN
+RAW
+b8a134255010fae2e6990000000000000000
+ENTRY_END
+
+STEP 30820 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0b79b0000020405b401010402
+ENTRY_END
+
+STEP 30830 QUERY
+ENTRY_BEGIN
+RAW
+b8a596575010faf095520000000000000000
+ENTRY_END
+
+STEP 30840 QUERY
+ENTRY_BEGIN
+RAW
+b8a596575018faf088240000008e42e5000000010001000000000f313038323333313735383631302d330000f900010f313038323333313735383631302d330000f900ff00000000005203677373096d6963726f736f667403636f6d00403af53e403c46be00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 30850 QUERY
+ENTRY_BEGIN
+RAW
+b8a596655011fae294c10000000000000000
+ENTRY_END
+
+STEP 30860 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf07bfa00000204056401010402
+ENTRY_END
+
+STEP 30870 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0ae140000020405b401010402
+ENTRY_END
+
+STEP 30880 QUERY
+ENTRY_BEGIN
+RAW
+b8a596665010fae294c00000000000000000
+ENTRY_END
+
+STEP 30890 QUERY
+ENTRY_BEGIN
+RAW
+b8a674795010fd5c78d20000000000000000
+ENTRY_END
+
+STEP 30900 QUERY
+ENTRY_BEGIN
+RAW
+b8a70de15010faf014400000000000000000
+ENTRY_END
+
+STEP 30910 QUERY
+ENTRY_BEGIN
+RAW
+b8a70de15018faf0b7340000008e93c3000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af53e403c46be00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 30920 QUERY
+ENTRY_BEGIN
+RAW
+b8a674795018fd5c78830000008f059c000000010001000000000e3931303533333036363737302d330000f900010e3931303533333036363737302d330000f900ff00000000005503677373096d6963726f736f667403636f6d00403af386403c45060003000000324e544c4d535350000100000097b208e00a000a0028000000080008002000000050434f4f535431314f4f535445494e4445520000
+ENTRY_END
+
+STEP 30930 QUERY
+ENTRY_BEGIN
+RAW
+b8a70def5011fae213af0000000000000000
+ENTRY_END
+
+STEP 30940 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0e3ce0000020405b401010402
+ENTRY_END
+
+STEP 30950 QUERY
+ENTRY_BEGIN
+RAW
+b8a674875011fd4e78400000000000000000
+ENTRY_END
+
+STEP 30960 QUERY
+ENTRY_BEGIN
+RAW
+000000007002faf0fefc00000204056401010402
+ENTRY_END
+
+STEP 30970 QUERY
+ENTRY_BEGIN
+RAW
+b8a70df05010fae213ae0000000000000000
+ENTRY_END
+
+STEP 30980 QUERY
+ENTRY_BEGIN
+RAW
+b8a674885010fd4e783f0000000000000000
+ENTRY_END
+
+STEP 30990 QUERY
+ENTRY_BEGIN
+RAW
+b8a7ad145010faf0aac60000000000000000
+ENTRY_END
+
+STEP 31000 QUERY
+ENTRY_BEGIN
+RAW
+b8a87d065010fd5cf3450000000000000000
+ENTRY_END
+
+STEP 31010 QUERY
+ENTRY_BEGIN
+RAW
+b8a7ad145018faf0518f0000008e8fef000000010001000000000f313038323333313735383631302d320000f900010f313038323333313735383631302d320000f900ff00000000005203677373096d6963726f736f667403636f6d00403af53e403c46be00030000002f4e544c4d535350000100000097b208e00600060029000000090009002000000049572d303031373232544b544553540000
+ENTRY_END
+
+STEP 31020 QUERY
+ENTRY_BEGIN
+RAW
+b8a87d065018fd5cc9920000008f3100000000010001000000000e3931303533333036363737302d320000f900010e3931303533333036363737302d320000f900ff00000000005503677373096d6963726f736f667403636f6d00403af386403c45060003000000324e544c4d535350000100000097b208e00a000a0028000000080008002000000050434f4f535431314f4f535445494e4445520000
+ENTRY_END
+
+STEP 31030 QUERY
+ENTRY_BEGIN
+RAW
+b8a7ad225011fae2aa350000000000000000
+ENTRY_END
+
+STEP 40010 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN A
+ENTRY_END
+
+; copy of iter_formerr.rpl
+; root prime
+STEP 40030 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 40050 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; this is the formerr answer
+STEP 40060 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA FORMERR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; this is the correct answer
+STEP 40070 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; is the final answer correct?
+STEP 40100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cname_badauth.rpl b/tests/deckard/sets/resolver/iter_cname_badauth.rpl
new file mode 100644
index 0000000..b250aee
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cname_badauth.rpl
@@ -0,0 +1,267 @@
+; config options
+; target-fetch-policy: "3 2 1 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with NS sending CNAME answer and authority of CNAME target.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+au. IN NS
+SECTION AUTHORITY
+au. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com.au. IN NS
+SECTION AUTHORITY
+com.au. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ncfphywebgtm01-c.ingdirect.com.au. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+ingdirect.com.au. IN A
+SECTION AUTHORITY
+ingdirect.com.au. IN NS l4.nstld.com.
+SECTION ADDITIONAL
+l4.nstld.com. IN A 209.112.114.33
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+l4.nstld.com. IN A
+SECTION ANSWER
+l4.nstld.com. IN A 209.112.114.33
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+l4.nstld.com. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+RANGE_END
+
+; l4.nstld.com.
+RANGE_BEGIN 0 100
+ ADDRESS 209.112.114.33
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ingdirect.com.au. IN NS
+SECTION ANSWER
+ingdirect.com.au. IN NS l4.nstld.com.
+SECTION ADDITIONAL
+l4.nstld.com. IN A 209.112.114.33
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+www.ingdirect.com.au. IN A
+SECTION ANSWER
+www.ingdirect.com.au. IN CNAME www.clb.ingdirect.com.au.
+SECTION AUTHORITY
+clb.ingdirect.com.au. IN NS ncfphywebgtm01-c.ingdirect.com.au.
+SECTION ADDITIONAL
+ncfphywebgtm01-c.ingdirect.com.au. IN A 203.92.27.132
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+clb.ingdirect.com.au. IN A
+SECTION AUTHORITY
+clb.ingdirect.com.au. IN NS ncfphywebgtm01-c.ingdirect.com.au.
+SECTION ADDITIONAL
+ncfphywebgtm01-c.ingdirect.com.au. IN A 203.92.27.132
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ncfphywebgtm01-c.ingdirect.com.au. IN A
+SECTION ANSWER
+ncfphywebgtm01-c.ingdirect.com.au. IN A 203.92.27.132
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ncfphywebgtm01-c.ingdirect.com.au. IN AAAA
+SECTION AUTHORITY
+ingdirect.com.au. IN SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+RANGE_END
+
+; ncfphywebgtm01-c.ingdirect.com.au.
+RANGE_BEGIN 0 100
+ ADDRESS 203.92.27.132
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+clb.ingdirect.com.au. IN NS
+SECTION AUTHORITY
+clb.ingdirect.com.au. IN NS ncfphywebgtm01-c.ingdirect.com.au.
+SECTION ADDITIONAL
+ncfphywebgtm01-c.ingdirect.com.au. IN A 203.92.27.132
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.clb.ingdirect.com.au. IN A
+SECTION ANSWER
+www.clb.ingdirect.com.au. IN A 203.31.183.134
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+www.ingdirect.com.au. IN A
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.ingdirect.com.au. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.ingdirect.com.au. IN A
+SECTION ANSWER
+www.ingdirect.com.au. IN CNAME www.clb.ingdirect.com.au.
+www.clb.ingdirect.com.au. IN A 203.31.183.134
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cname_cache.rpl b/tests/deckard/sets/resolver/iter_cname_cache.rpl
new file mode 100644
index 0000000..2d0dca9
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cname_cache.rpl
@@ -0,0 +1,297 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test iterative resolve with cached cname for nameserver
+; example.com NS ns.example.com en ns2.example.com
+; ns.example.com CNAME ns.bla.nl
+; ns.bla.nl A ....
+; dan timeout van A record uit cache - refetch.
+; ns2.example.com timeed niet uit ; maar geeft altijd servfail.
+
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nl. IN A
+SECTION AUTHORITY
+nl. IN NS ns2.nic.nl.
+SECTION ADDITIONAL
+ns2.nic.nl. IN A 192.1.1.2
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. ".com"
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+;;; but really a CNAME in child server
+ns.example.com. 1 IN A 1.2.3.4
+ns2.example.com. IN A 1.2.3.5
+ns2.example.com. IN AAAA 2002::5
+ENTRY_END
+
+; lame answers back to root for .nl (.com server not authoritative for .nl)
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nl. IN A
+SECTION AUTHORITY
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+RANGE_END
+
+; ns2.nic.nl ".nl"
+RANGE_BEGIN 0 100
+ ADDRESS 192.1.1.2
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+bla.nl. IN A
+SECTION AUTHORITY
+bla.nl. IN NS ns.bla.nl.
+SECTION ADDITIONAL
+ns.bla.nl. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.bla.nl "bla..nl"
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.bla.nl. IN A
+SECTION ANSWER
+ns.bla.nl. IN A 1.2.3.6
+SECTION AUTHORITY
+bla.nl. IN NS ns.bla.nl.
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.bla.nl. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.bla.nl. IN MX
+SECTION ANSWER
+ns.bla.nl. IN MX 10 bla.nl.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+; ns.example.com "example.com"
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN MX
+SECTION ANSWER
+ns.example.com IN CNAME ns.bla.nl.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+; ns2.example.com "example.com"
+; bad failing server
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com. IN MX
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns2.example.com "example.com"
+; bad failing server
+RANGE_BEGIN 0 100
+ ADDRESS 2002::5
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com. IN MX
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; get cname in cache. use MX query
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.com. IN MX
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.com. IN MX
+SECTION ANSWER
+ns.example.com. IN CNAME ns.bla.nl
+ns.bla.nl. IN MX 10 bla.nl.
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; get seconds to pass to timeout the A record
+STEP 15 TIME_PASSES ELAPSE 5
+
+; get into trouble getting cname for nameserver.
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; there may still be pending ns.bla.nl AAAA queries ; get rid of them like this
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.bla.nl. IN AAAA
+ENTRY_END
+
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.bla.nl. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
+;SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cname_double.rpl b/tests/deckard/sets/resolver/iter_cname_double.rpl
new file mode 100644
index 0000000..031dccb
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cname_double.rpl
@@ -0,0 +1,294 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test double cname in reply.
+; this is in response to an error report from Robert Edmonds,
+; about resolution of images-na.ssl-images-amazon.com.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; test domains
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN A
+SECTION AUTHORITY
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ADDITIONAL
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; two CNAMEs for one name?
+www.example.com. IN CNAME www.next.com.
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.next.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+www.next.com. IN A
+SECTION ANSWER
+www.next.com. IN A 10.20.30.40
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN NS
+SECTION ANSWER
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+www.next.com. IN A 10.20.30.40
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cname_nx.rpl b/tests/deckard/sets/resolver/iter_cname_nx.rpl
new file mode 100644
index 0000000..6dac1e2
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cname_nx.rpl
@@ -0,0 +1,288 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test cname followed by nxdomain reply rcode.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; test domains
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN A
+SECTION AUTHORITY
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ADDITIONAL
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.next.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+www.next.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN NS
+SECTION ANSWER
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cname_qnamecopy.rpl b/tests/deckard/sets/resolver/iter_cname_qnamecopy.rpl
new file mode 100644
index 0000000..e446c6c
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cname_qnamecopy.rpl
@@ -0,0 +1,331 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test cname to nodata and if qname is set to orig after prepend
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN A
+SECTION AUTHORITY
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ADDITIONAL
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.next.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.next.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+next.com. IN NS
+SECTION ANSWER
+next.com. IN NS ns.next.com.
+SECTION ADDITIONAL
+ns.next.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD CD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 3 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD CD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION ADDITIONAL
+ENTRY_END
+
+; query it from cache again
+STEP 5 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 7 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME www.next.com.
+SECTION AUTHORITY
+next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION ADDITIONAL
+ENTRY_END
+
+; query answer to cname from cache again, test if stored under wrong qname.
+STEP 9 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.next.com. IN A
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.next.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cycle.rpl b/tests/deckard/sets/resolver/iter_cycle.rpl
new file mode 100644
index 0000000..3c2a097
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cycle.rpl
@@ -0,0 +1,258 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with dependency cycle
+; query for ns.example.com, needs ns.example.net, needs ns.example.com.
+
+; Invalid server
+RANGE_BEGIN 0 100 1.2.3.1
+
+ENTRY_BEGIN
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+ENTRY_END
+
+RANGE_END
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+; note this will be scrubbed off
+ns.example.net. IN A 1.2.3.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+; note this will be scrubbed off
+ns.example.net. IN A 1.2.3.1
+ENTRY_END
+
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. IN A 192.12.94.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.com.
+SECTION ADDITIONAL
+; note this will be scrubbed off
+ns.example.com. IN A 1.2.3.2
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+; cycle detected and it fails.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_cycle_noh.rpl b/tests/deckard/sets/resolver/iter_cycle_noh.rpl
new file mode 100644
index 0000000..eaf30bb
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_cycle_noh.rpl
@@ -0,0 +1,414 @@
+; config options
+ harden-glue: "no"
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution where disabled scrubber avoids cycle
+; query for ns.example.com, needs ns.example.net, needs ns.example.com.
+; scrubber disabled, so extra glue is trusted.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.1
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+gtld-servers.net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. IN A 192.12.94.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.2
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+gtld-servers.net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. IN A 192.12.94.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.2
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.1
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+; cycle detected and it fails.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.2
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+; scrubbed off
+; SECTION ADDITIONAL
+; ns.example.net. IN A 1.2.3.1
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_dnsseclame_ds_ok.rpl b/tests/deckard/sets/resolver/iter_dnsseclame_ds_ok.rpl
new file mode 100644
index 0000000..36433e1
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_dnsseclame_ds_ok.rpl
@@ -0,0 +1,369 @@
+; config options
+;server:
+ trust-anchor: "example.com. 3600 IN DS 8378 7 1 0FCD3F3031F437036CA53411FD4B43BAB303B450 "
+val-override-date: "20181130121807"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at ds point, which is ok.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 54180 5 1 67360E6697A9066D6904EE6E9879FB5990C6A724
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAcXhoXQxDzxHC1U3t6ayuYVk2ufLVk59LEzGA2fYWBQiPbx0ay46 r0cuafuY1ueEB2KavEO7Esb9Tvo9ynWKg0DOIOpV4iNDVMUoNbZQj8X1 0WKgBHdaXc2aGC+EM9ozSnLKuV02+eNT/PxPsijqzkC7cJ32k4n1+sZ1 5Cywbo3Z ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101806 20181130101806 54180 sub.example.com. unaHKPTSK0hncZIN8FVjcCtELPlo968TVskOpvMjhe3IgiTXMoVzBzW8 XNalW4wnelZVv1PYW0+6MGukDBBzJBRn9qKKrFyayMppIelbpC52SFqI H58AhMUJb2GlPJW9Xg19eF7FmSLrrYO0GMkfH5pAvd1aNOCckj4LJ1PS Sfg= ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101806 20181130101806 54180 sub.example.com. dtxWwVO+T0vfjdrU9/COBJR6oshgdO8gkGusq573eBe8QzaXrV1cRLya Zj3qXUBrn61iOi2xEu0yEtfJx8++XGtzHrmTIFUGWOQW3BoyfLAVZC3b WrNKVljMMVAIWzwOBQguIVczW7vLAG6QAMICrI/es5xx8IMTYmoZOgXN RMo= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101806 20181130101806 54180 sub.example.com. oGdNeh2GTFMtDsCIuJ6dTfwWjb7IpslFiUnH71I2a0X5E3acfvQ/3Xhs Paivy1SbIb2kaf3DMXYAbLBIhcyWGP45kXaP+5CRXkyt69gDcSVxKdZP rugy6m4LwaitTRlV44jDu6GxVZjXlAjd2d4rrz8qixRQIfEfk8IMX0L4 30U= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcPpAFo67izrkhRxtGyVSpusyG5WmkRQ5UaJ+wdgqCFiDZtZoaY2 TLWnxkqm1shmK2ef+M9aUpbz2L8LpdDPJcUf+9tcR37/vVh5+RzhjAkD /V/wVQw4DincwuSXtk6yOfXXUyRBx9JDV9Y+R7Dg0MUeSDYwwd2ne2tz 5v8D+Hi/ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101806 20181130101806 8378 example.com. d54yctvAg31OPD9tML4Boh4u8/T9SZZtQfSaEyXq8Ean4MYtdVYzPp72 ZW6OuUXHxjPULWLoHA/y/vSNOmC5O5M9LZ1vU1kbPRwR/p7lzFtQuVYv Nmhpr8ohNuqms+wZue9akZXTv5gN8HL3eg/nqEuqVPHwrNhLX+okuNLK E50= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101806 20181130101806 8378 example.com. d8xIochwH3oB29TjGvSXOsJOzdBm+5O/Yttdbcxy2S0psh/IBAyMZBqH QVkubqiM0Fj7kDdcEJFFqiDDZzKSlREQyaU9TY78bSjga5ZYXnoiy1Kc KKkvvwIXfzWkqyG1vm4wZtEOBDO9ho1sKoZrGVg/rEVhAnZTj/a25B9Q Ka8= ;{id = 2854}
+ENTRY_END
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 54180 5 1 67360E6697A9066D6904EE6E9879FB5990C6A724
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101806 20181130101806 8378 example.com. hnexEP0ej6KmZ3BYYOAqs8WgbSFS0psOYvcjJdeQPymmFYJgXdkkHznV cxTL8TrsS+2uD8gUEC/g4k8eEPc4my1wswalm1+d+KYan15inHzkRrko oC7kD705RvSEl6F5L7NbpmEYgqVjZb3PJAhppS54UYxsRdqhEZop3MmV KuA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 54180 5 1 67360E6697A9066D6904EE6E9879FB5990C6A724
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101806 20181130101806 8378 example.com. hnexEP0ej6KmZ3BYYOAqs8WgbSFS0psOYvcjJdeQPymmFYJgXdkkHznV cxTL8TrsS+2uD8gUEC/g4k8eEPc4my1wswalm1+d+KYan15inHzkRrko oC7kD705RvSEl6F5L7NbpmEYgqVjZb3PJAhppS54UYxsRdqhEZop3MmV KuA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; server is not DNSSEC lame.
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101806 20181130101806 54180 sub.example.com. mCLLh1oDYHUCNY9nRUCe/j0yxPZDidmpNcoeIJlH9JxwV2TqHKgjBLzo awGJukxoAQgyY9v76ITVSRGreDKYe5GQ7beDKq/nIsZSB3S4kIDqXHGz 4Rr2GQvyNWuWRfsnqW09SL3yKET8QYkaIxdXarJrw/dA2gR/g0BGnv39 iEI= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101806 20181130101806 54180 sub.example.com. dtxWwVO+T0vfjdrU9/COBJR6oshgdO8gkGusq573eBe8QzaXrV1cRLya Zj3qXUBrn61iOi2xEu0yEtfJx8++XGtzHrmTIFUGWOQW3BoyfLAVZC3b WrNKVljMMVAIWzwOBQguIVczW7vLAG6QAMICrI/es5xx8IMTYmoZOgXN RMo= ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 54180 5 1 67360E6697A9066D6904EE6E9879FB5990C6A724
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAcXhoXQxDzxHC1U3t6ayuYVk2ufLVk59LEzGA2fYWBQiPbx0ay46 r0cuafuY1ueEB2KavEO7Esb9Tvo9ynWKg0DOIOpV4iNDVMUoNbZQj8X1 0WKgBHdaXc2aGC+EM9ozSnLKuV02+eNT/PxPsijqzkC7cJ32k4n1+sZ1 5Cywbo3Z ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101806 20181130101806 54180 sub.example.com. unaHKPTSK0hncZIN8FVjcCtELPlo968TVskOpvMjhe3IgiTXMoVzBzW8 XNalW4wnelZVv1PYW0+6MGukDBBzJBRn9qKKrFyayMppIelbpC52SFqI H58AhMUJb2GlPJW9Xg19eF7FmSLrrYO0GMkfH5pAvd1aNOCckj4LJ1PS Sfg= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101806 20181130101806 54180 sub.example.com. oGdNeh2GTFMtDsCIuJ6dTfwWjb7IpslFiUnH71I2a0X5E3acfvQ/3Xhs Paivy1SbIb2kaf3DMXYAbLBIhcyWGP45kXaP+5CRXkyt69gDcSVxKdZP rugy6m4LwaitTRlV44jDu6GxVZjXlAjd2d4rrz8qixRQIfEfk8IMX0L4 30U= ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101806 20181130101806 54180 sub.example.com. oGdNeh2GTFMtDsCIuJ6dTfwWjb7IpslFiUnH71I2a0X5E3acfvQ/3Xhs Paivy1SbIb2kaf3DMXYAbLBIhcyWGP45kXaP+5CRXkyt69gDcSVxKdZP rugy6m4LwaitTRlV44jDu6GxVZjXlAjd2d4rrz8qixRQIfEfk8IMX0L4 30U= ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_dnsseclame_ta_ok.rpl b/tests/deckard/sets/resolver/iter_dnsseclame_ta_ok.rpl
new file mode 100644
index 0000000..8ec72b8
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_dnsseclame_ta_ok.rpl
@@ -0,0 +1,305 @@
+; config options
+;server:
+ trust-anchor: "example.com. 3600 IN DS 63215 7 1 9B2A4B4CE971A6D1A2DFD23C03467F053F1D2D9C "
+val-override-date: "20181130121809"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection with anchor point that is ok.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101809 20181130101809 63215 example.com. ldaJ3pZ4qtnwcT+SudZ4G05ye0+FbtGoXuAxjRUVef/nee+8pgMLtK1a 0j1Ejg3IAit/nUKD58Ccfuo45Qwf/BnJvKeKltksGhOSEw+yoqD+QOHN ByiphD1qsmaECbLHgXm/1Wmrp5kLm15HvErBJv1nGp6aALaHkao3tkl4 ZAY= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101809 20181130101809 63215 example.com. dwaG446dWfL78qWJxkp9MO1SeV4xEt6MF3jYcpM6HGWgmn0peGy+zvzq TpeyMRCQFi52+MIGDPOnRtVVYpFnsUmH9dkoYGG+5ut9RUoyef4p7EsE BJncC/S5iMYaeEoU9yIwV/CZq/cdz465RroMKKJuI2NQW9gZn+MbFojY T3E= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbeLIHEf7lEpCP1+GPvzCTJUDjUCMggHlkNWFbsT2xQsG3QVKInt h6KWLbfdgKp9RU1L5vyerphhEIsRwAGF/PZsIWc/kQsdXMWyiKcRwLHS l3JNydyTkl5oIhWu6SDaK51KWSaopxwhLZAtKWoQRKSRSdnlQg9B98sj ZWpAhm6V ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101809 20181130101809 63215 example.com. PxtUfqGNISnTuabiNbxdZcPABScYoElxSp6CC5TIN8MNkMCsq4mMKqHw ECFdHX+s4K9frWEOVZT0uSvJFsVdhomtOR6zfc1jcc4p+SuDlIRfrAEL jREika0hP04tPwzDnQzZbswJK9lpwAglTvH4OSjZhHUEMuelZxTF8GyA WMc= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101809 20181130101809 63215 example.com. gRONsGpAzHBTe8PKGcxPo9mmvZZNOjZC/4Xn/36WIe8VTf1T67KDPHuz zeYpkxT6x1Fc5JzBWPOTvL+leugJ2p4N0tFTnYWmu0gVcYqRCa4KX5Yz ek9wkGdDS9yTZhQFWXe0ckWulaZb5f9Hxq/UpE2LdnLSLwUcmRATefML TvE= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; the response is not lame at all.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbeLIHEf7lEpCP1+GPvzCTJUDjUCMggHlkNWFbsT2xQsG3QVKInt h6KWLbfdgKp9RU1L5vyerphhEIsRwAGF/PZsIWc/kQsdXMWyiKcRwLHS l3JNydyTkl5oIhWu6SDaK51KWSaopxwhLZAtKWoQRKSRSdnlQg9B98sj ZWpAhm6V ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101809 20181130101809 63215 example.com. PxtUfqGNISnTuabiNbxdZcPABScYoElxSp6CC5TIN8MNkMCsq4mMKqHw ECFdHX+s4K9frWEOVZT0uSvJFsVdhomtOR6zfc1jcc4p+SuDlIRfrAEL jREika0hP04tPwzDnQzZbswJK9lpwAglTvH4OSjZhHUEMuelZxTF8GyA WMc= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101809 20181130101809 63215 example.com. ldaJ3pZ4qtnwcT+SudZ4G05ye0+FbtGoXuAxjRUVef/nee+8pgMLtK1a 0j1Ejg3IAit/nUKD58Ccfuo45Qwf/BnJvKeKltksGhOSEw+yoqD+QOHN ByiphD1qsmaECbLHgXm/1Wmrp5kLm15HvErBJv1nGp6aALaHkao3tkl4 ZAY= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101809 20181130101809 63215 example.com. dwaG446dWfL78qWJxkp9MO1SeV4xEt6MF3jYcpM6HGWgmn0peGy+zvzq TpeyMRCQFi52+MIGDPOnRtVVYpFnsUmH9dkoYGG+5ut9RUoyef4p7EsE BJncC/S5iMYaeEoU9yIwV/CZq/cdz465RroMKKJuI2NQW9gZn+MbFojY T3E= ;{id = 2854}
+ENTRY_END
+
+; response is not lame.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101809 20181130101809 63215 example.com. gRONsGpAzHBTe8PKGcxPo9mmvZZNOjZC/4Xn/36WIe8VTf1T67KDPHuz zeYpkxT6x1Fc5JzBWPOTvL+leugJ2p4N0tFTnYWmu0gVcYqRCa4KX5Yz ek9wkGdDS9yTZhQFWXe0ckWulaZb5f9Hxq/UpE2LdnLSLwUcmRATefML TvE= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101809 20181130101809 63215 example.com. gRONsGpAzHBTe8PKGcxPo9mmvZZNOjZC/4Xn/36WIe8VTf1T67KDPHuz zeYpkxT6x1Fc5JzBWPOTvL+leugJ2p4N0tFTnYWmu0gVcYqRCa4KX5Yz ek9wkGdDS9yTZhQFWXe0ckWulaZb5f9Hxq/UpE2LdnLSLwUcmRATefML TvE= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_domain_sale.rpl b/tests/deckard/sets/resolver/iter_domain_sale.rpl
new file mode 100644
index 0000000..27220e9
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_domain_sale.rpl
@@ -0,0 +1,269 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolver with a domain sale
+; and the old operator is nasty, keeps running his server with the old data.
+; and lots of lookups keep going towards the domain.
+; eventually, the NS record has to timeout.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. (before sale of domain)
+RANGE_BEGIN 0 20
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. (after sale of domain)
+RANGE_BEGIN 30 200
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 8.8.8.8
+ENTRY_END
+RANGE_END
+
+; ns.example.com. first owner
+RANGE_BEGIN 0 200
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; nxdomains for any name,type
+; last in RANGE so that it matches everything left over.
+; it includes the NS record.
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com. new owner
+RANGE_BEGIN 0 200
+ ADDRESS 8.8.8.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 8.8.8.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 88.88.88.88
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 8.8.8.8
+ENTRY_END
+RANGE_END
+
+; Fetch the old record from the old owner.
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 5 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 3600 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; the domain is sold (right at this time).
+; but the information stays in the cache.
+
+; after 1800 secs still the cached answer
+STEP 20 TIME_PASSES ELAPSE 1800
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 1800 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 1800 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 1800 IN A 1.2.3.4
+ENTRY_END
+
+; and ask another query
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nx1.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+nx1.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 1800 IN A 1.2.3.4
+ENTRY_END
+
+; after another 1900 seconds the domain must have timed out.
+STEP 70 TIME_PASSES ELAPSE 1900
+
+; the NS record should have timed out.
+STEP 80 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 90 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 88.88.88.88
+;SECTION AUTHORITY
+;example.com. 3600 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 8.8.8.8
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_domain_sale_nschange.rpl b/tests/deckard/sets/resolver/iter_domain_sale_nschange.rpl
new file mode 100644
index 0000000..d260bcd
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_domain_sale_nschange.rpl
@@ -0,0 +1,348 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolver with a domain sale and NS changes
+; and the old operator is nasty, keeps running his server with the old data.
+; and lots of lookups keep going towards the domain.
+; and the old server is changing the NS record of the old domain.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. (before sale of domain)
+RANGE_BEGIN 0 20
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net. (after sale of domain)
+RANGE_BEGIN 30 200
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 8.8.8.8
+ENTRY_END
+RANGE_END
+
+; ns.example.com. first owner
+RANGE_BEGIN 0 30
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; nxdomains for any name,type
+; last in RANGE so that it matches everything left over.
+; it includes the NS record.
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com. first owner, NS changed
+RANGE_BEGIN 40 200
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS nsb.example.com.
+SECTION ADDITIONAL
+nsb.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 3600 IN NS nsb.example.com.
+SECTION ADDITIONAL
+nsb.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; nxdomains for any name,type
+; last in RANGE so that it matches everything left over.
+; it includes the NS record.
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS nsb.example.com.
+SECTION ADDITIONAL
+nsb.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com. new owner
+RANGE_BEGIN 0 200
+ ADDRESS 8.8.8.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 8.8.8.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 88.88.88.88
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 8.8.8.8
+ENTRY_END
+RANGE_END
+
+; Fetch the old record from the old owner.
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 5 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 3600 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; the domain is sold (right at this time).
+; but the information stays in the cache.
+
+; after 1800 secs still the cached answer
+STEP 20 TIME_PASSES ELAPSE 1800
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 1800 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 1800 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 1800 IN A 1.2.3.4
+ENTRY_END
+
+; and ask another query
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nx1.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+nx1.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS nsb.example.com.
+;SECTION ADDITIONAL
+;nsb.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+STEP 62 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nx1.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 63 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+nx1.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA a. b. 1 2 3 4 5
+example.com. 3600 IN NS nsb.example.com.
+;SECTION ADDITIONAL
+;nsb.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+; after another 1900 seconds the domain must have timed out.
+STEP 70 TIME_PASSES ELAPSE 1900
+
+; the NS record should have timed out.
+STEP 80 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+; recursion happens here.
+STEP 90 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 88.88.88.88
+;SECTION AUTHORITY
+;example.com. 3600 IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 8.8.8.8
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_donotq127.rpl b/tests/deckard/sets/resolver/iter_donotq127.rpl
new file mode 100644
index 0000000..c1eb487
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_donotq127.rpl
@@ -0,0 +1,196 @@
+; config options
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator donotquery of 127/8.
+; The scenario presents an iteration chain that has 127.0.0.2 and
+; 127.255.255.255 as nameserver IPs, like a spam-blocklist.
+; these are 127/8 localhost and should be blocked, causing servfail.
+; if not blocked, they cause a lookup, but this file does not specify
+; 127.* responses, so testbound will fail the test.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns2.example.com. IN AAAA
+SECTION AUTHORITY
+com. SOA bla bla 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ns.example.com. IN A 127.255.255.255
+ns2.example.com. IN A 127.0.0.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ns.example.com. IN A 127.255.255.255
+ns2.example.com. IN A 127.0.0.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+; ns.example.com trap
+RANGE_BEGIN 0 100
+ ADDRESS 127.255.255.255
+RANGE_END
+
+; ns.example.com trap
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.2
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ds_locate_ns.rpl b/tests/deckard/sets/resolver/iter_ds_locate_ns.rpl
new file mode 100644
index 0000000..fa2c535
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ds_locate_ns.rpl
@@ -0,0 +1,144 @@
+; config options
+;server:
+; target-fetch-policy: "0 0 0 0 0"
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for parent nameservers of DS
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; content of root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-servers.net. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ds_locate_ns_nosoa.rpl b/tests/deckard/sets/resolver/iter_ds_locate_ns_nosoa.rpl
new file mode 100644
index 0000000..caca222
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ds_locate_ns_nosoa.rpl
@@ -0,0 +1,144 @@
+; config options
+;server:
+; target-fetch-policy: "0 0 0 0 0"
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for DS without a SOA record
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; content of root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+;root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-servers.net. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_escape_bailiwick.rpl b/tests/deckard/sets/resolver/iter_escape_bailiwick.rpl
new file mode 100644
index 0000000..cef641a
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_escape_bailiwick.rpl
@@ -0,0 +1,218 @@
+stub-addr: 193.0.14.129
+CONFIG_END
+SCENARIO_BEGIN Test a case where parent NS advertises non-existent zone cut, and the final NS tries to answer from its parent's zone cut.
+; That is treated as an attempt to escape bailiwick and is treated specially.
+; The NS from final answer MUST NOT be cached, but it should still be used for resolution.
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+www.example.com. IN NS ns.example.com. ; Introduce non-existing zone cut
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_formerr.rpl b/tests/deckard/sets/resolver/iter_formerr.rpl
new file mode 100644
index 0000000..54f5296
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_formerr.rpl
@@ -0,0 +1,83 @@
+; config options
+; harden-referral-path: no
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Disable EDNS0 and fancy stuff when the server replies with FORMERR.
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN A
+ENTRY_END
+
+; root prime
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; this is the formerr answer
+STEP 60 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA FORMERR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; this is the correct answer
+STEP 70 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; is the final answer correct?
+STEP 100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_hint_lame.rpl b/tests/deckard/sets/resolver/iter_hint_lame.rpl
new file mode 100644
index 0000000..8dda093
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_hint_lame.rpl
@@ -0,0 +1,160 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ ; minimization does not affect priming query
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test iterative resolve with lame hints (RA flag on but no AA flag)
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+; flags are intentionally weird: it should have AA instead of RA
+REPLY QR RA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RA NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_lame_aaaa.rpl b/tests/deckard/sets/resolver/iter_lame_aaaa.rpl
new file mode 100644
index 0000000..7eeef60
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_lame_aaaa.rpl
@@ -0,0 +1,178 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test iterator lameness detection of AAAA-only lameness
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN AAAA
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+
+; response to AAAA query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+. 3600000 IN NS a.root-servers.net.
+. 3600000 IN NS b.root-servers.net.
+. 3600000 IN NS c.root-servers.net.
+. 3600000 IN NS d.root-servers.net.
+. 3600000 IN NS e.root-servers.net.
+. 3600000 IN NS f.root-servers.net.
+. 3600000 IN NS g.root-servers.net.
+. 3600000 IN NS h.root-servers.net.
+. 3600000 IN NS i.root-servers.net.
+. 3600000 IN NS j.root-servers.net.
+. 3600000 IN NS k.root-servers.net.
+. 3600000 IN NS l.root-servers.net.
+. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+b.root-servers.net. 3600000 IN A 128.9.0.107
+c.root-servers.net. 3600000 IN A 192.33.4.12
+ENTRY_END
+
+; response to A query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 120 IN A 204.14.213.188
+ENTRY_END
+RANGE_END
+
+; Now try the A type, which works, and is not LAME.
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+; this doesn't fail
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 120 IN A 204.14.213.188
+ENTRY_END
+
+; this fails; it is LAME
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN AAAA
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_lame_noaa.rpl b/tests/deckard/sets/resolver/iter_lame_noaa.rpl
new file mode 100644
index 0000000..ceb05c0
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_lame_noaa.rpl
@@ -0,0 +1,124 @@
+; config options
+; harden-referral-path: no
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ ; test with pre-scripted replies does not make sense with qmin
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test lame detection if AA bit is omitted
+; the query is answered with a reply that has
+; no AA bit
+; no SOA record
+; noanswer/noerror
+; NS record in there which is not a down delegation (==).
+; the query is not sent to a forward zone
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; root prime is sent
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; query sent to .com server
+STEP 70 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns2.example.com. IN A 168.192.3.3
+ENTRY_END
+
+; no matter which one the iterator tries first, we present it as 'lame'
+; query to ns1.example.com or ns2.example.com.
+STEP 90 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+; This is the BROKEN ANSWER here.
+; it is lame. A delegation to example.com. itself.
+example.com. IN NS ns1.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns2.example.com. IN A 168.192.3.3
+ENTRY_END
+
+; iterator should try again and ask the other nameserver.
+STEP 110 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns2.example.com. IN A 168.192.3.3
+ENTRY_END
+
+
+; is the final answer correct?
+STEP 200 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;example.com. IN NS ns2.example.com.
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+;ns2.example.com. IN A 168.192.3.3
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_lame_nosoa.rpl b/tests/deckard/sets/resolver/iter_lame_nosoa.rpl
new file mode 100644
index 0000000..54e4088
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_lame_nosoa.rpl
@@ -0,0 +1,291 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with lame reply looks like nodata with noSOA
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+; advertises +RA so it is REC_LAME.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+; is like a BIND server that is LAME, authoritative for other domains,
+; but not this one, and somehow got this NS record in its cache.
+; trying to give 'lame referral' but to the same name, not up.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; store bad timing for one server to influence server selection
+; 1.2.3.44 (ns.example.net) gets 900 msec.
+; so the 376 ns.example.com is preferred.
+;STEP 1 INFRA_RTT 1.2.3.44 example.net. 900
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+; scrubbed off
+;ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+; query to recursion-lame server
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+; It's somewhat OK if resolver accepts the only upstream lame server,
+; it's also OK if it ignores lame upstream, because it's not
+; provably authoritative for this zone. (kresd is the latter)
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_lame_root.rpl b/tests/deckard/sets/resolver/iter_lame_root.rpl
new file mode 100644
index 0000000..c94bbec
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_lame_root.rpl
@@ -0,0 +1,33 @@
+stub-addr: 193.0.14.129
+CONFIG_END
+SCENARIO_BEGIN Test iterative resolve with lame root.
+
+; broken root server: K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR RA SERVFAIL
+SECTION QUESTION
+. IN NS
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_lamescrub.rpl b/tests/deckard/sets/resolver/iter_lamescrub.rpl
new file mode 100644
index 0000000..4543091
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_lamescrub.rpl
@@ -0,0 +1,150 @@
+; config options
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test lameness detection after scrubber.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+ENTRY_BEGIN
+
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+; This server is Lame!
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+com. 155182 IN NS a.gtld-servers.net.
+com. 155182 IN NS b.gtld-servers.net.
+com. 155182 IN NS c.gtld-servers.net.
+com. 155182 IN NS d.gtld-servers.net.
+com. 155182 IN NS e.gtld-servers.net.
+com. 155182 IN NS f.gtld-servers.net.
+com. 155182 IN NS g.gtld-servers.net.
+com. 155182 IN NS h.gtld-servers.net.
+com. 155182 IN NS i.gtld-servers.net.
+com. 155182 IN NS j.gtld-servers.net.
+com. 155182 IN NS k.gtld-servers.net.
+com. 155182 IN NS l.gtld-servers.net.
+com. 155182 IN NS m.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 155182 IN A 192.5.6.30
+b.gtld-servers.net. 155182 IN A 192.33.14.30
+c.gtld-servers.net. 155182 IN A 192.26.92.30
+d.gtld-servers.net. 155182 IN A 192.31.80.30
+e.gtld-servers.net. 155182 IN A 192.12.94.30
+f.gtld-servers.net. 155182 IN A 192.35.51.30
+g.gtld-servers.net. 155182 IN A 192.42.93.30
+h.gtld-servers.net. 155182 IN A 192.54.112.30
+i.gtld-servers.net. 155182 IN A 192.43.172.30
+j.gtld-servers.net. 155182 IN A 192.48.79.30
+k.gtld-servers.net. 155182 IN A 192.52.178.30
+l.gtld-servers.net. 155182 IN A 192.41.162.30
+m.gtld-servers.net. 155182 IN A 192.55.83.30
+a.gtld-servers.net. 155182 IN AAAA 2001:503:a83e::2:30
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursin happens here
+
+; check that the answer is a failure (lame server)
+; and not a nodata-noerror message (false answer classification).
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_minim_a.rpl b/tests/deckard/sets/resolver/iter_minim_a.rpl
new file mode 100644
index 0000000..1eff485
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_minim_a.rpl
@@ -0,0 +1,93 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: on
+; name: "."
+ stub-addr: 127.0.0.10 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic query minimization www.example.com.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 127.0.0.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_minim_a_nxdomain.rpl b/tests/deckard/sets/resolver/iter_minim_a_nxdomain.rpl
new file mode 100644
index 0000000..c1293aa
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_minim_a_nxdomain.rpl
@@ -0,0 +1,104 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: on
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic query minimization sub.www.example.com. when NS doesn't show empty non-terminal.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.www.example.com. IN A
+SECTION ANSWER
+sub.www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+sub.www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+sub.www.example.com. IN A
+SECTION ANSWER
+sub.www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_minim_nonempty.rpl b/tests/deckard/sets/resolver/iter_minim_nonempty.rpl
new file mode 100644
index 0000000..38812fd
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_minim_nonempty.rpl
@@ -0,0 +1,132 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: on
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test query minimization with terminal in resolution path.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS lame-addr.gtld-servers.net.
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+lame-addr.gtld-servers.net. IN A 1.1.1.1
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; lame.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.1.1.1
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+. IN NS
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN CNAME nowhere.cdn.example.com.
+SECTION AUTHORITY
+; Suggest authority of 'nowhere' (which must not be followed)
+cdn.example.com. IN NS ns01.cdn.example.com.
+SECTION ADDITIONAL
+ns01.cdn.example.com. IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com. IN NS blackhole.
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+FLAGS RD
+SECTION QUESTION
+www.example.com. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com. IN NS blackhole.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_minim_ns.rpl b/tests/deckard/sets/resolver/iter_minim_ns.rpl
new file mode 100644
index 0000000..b642165
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_minim_ns.rpl
@@ -0,0 +1,126 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: on
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test query minimization with empty-nonterminal in path.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS lame-addr.gtld-servers.net.
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+lame-addr.gtld-servers.net. IN A 1.1.1.1
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; lame.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.1.1.1
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com. IN NS blackhole.
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com. IN NS blackhole.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_minmaxttl.rpl b/tests/deckard/sets/resolver/iter_minmaxttl.rpl
new file mode 100644
index 0000000..7ba7caa
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_minmaxttl.rpl
@@ -0,0 +1,191 @@
+; config options
+ features: min_ttl = 300
+ features: max_ttl = 600
+ ; the test is purely about cache so we do not need qmin complexity
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test configurable minimum and maximum TTL
+
+; minimum TTL
+; time 0
+RANGE_BEGIN 1 2
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 0 IN A 5.6.7.8 ; TTL smaller than min_ttl
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 4 8
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. 0 IN A 9.10.11.12
+ENTRY_END
+RANGE_END
+
+
+
+
+; maximum TTL
+; time 0
+RANGE_BEGIN 9 10
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. 3600 IN A 13.14.15.16 ; TTL bigger than max_ttl
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 12 16
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. 3600 IN A 17.18.19.20
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 5.6.7.8
+ENTRY_END
+
+
+STEP 3 TIME_PASSES ELAPSE 200
+; time 200
+
+STEP 4 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+; time 200 < min_ttl 300: returns cached answer
+STEP 5 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 5.6.7.8
+ENTRY_END
+
+STEP 6 TIME_PASSES ELAPSE 200
+; time 400
+
+STEP 7 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+; time 400 > min_ttl 300: returns new answer
+STEP 8 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 9.10.11.12
+ENTRY_END
+
+
+STEP 9 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 13.14.15.16
+ENTRY_END
+
+
+STEP 11 TIME_PASSES ELAPSE 500
+; time 500
+
+STEP 12 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+; time 500 < max_ttl 600: returns cached answer
+STEP 13 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 13.14.15.16
+ENTRY_END
+
+STEP 14 TIME_PASSES ELAPSE 500
+; time 1000
+
+STEP 15 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+; time 1000 > max_ttl 600: returns new answer
+STEP 16 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 17.18.19.20
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_mod.rpl b/tests/deckard/sets/resolver/iter_mod.rpl
new file mode 100644
index 0000000..8e8b058
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_mod.rpl
@@ -0,0 +1,217 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; module-config: "iterator"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic iterative resolve without validator module
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_multiple_A.rpl b/tests/deckard/sets/resolver/iter_multiple_A.rpl
new file mode 100644
index 0000000..3eb9636
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_multiple_A.rpl
@@ -0,0 +1,170 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Multiple A records test.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.example.com. IN A
+SECTION ANSWER
+a.example.com. 3600 IN CNAME b.example.com.
+a.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. uiI9SNK74X//ACbllDC5LD49gjTmyL08CrtK1++I3rNPFFRChyJYAkUM wXBOXVW+fqBWOrXr835KCvUK/JJiSy/vvqE2+xI370OL8d9MvjR9vjIw Y2VusLWr3KmI4ixR7bAdG+FnMedapykOi8CJnbpkltU60QprQetcKGSv /Gk=
+b.example.com. 3600 IN A 1.2.3.5
+b.example.com. 3600 IN A 1.2.3.6
+b.example.com. 3600 IN A 1.2.3.7
+b.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. s5QtOdtBldJK1tdYNeWfQjoqVALI8eqcCRGOD1VocXRfDs3pgzowqtu5 rU/5vUxcN535/Z8nRPXEF7Ub5pgzEWupETiUvpEQP/Y+mNTaXrsgHTlc YCsCqbaPDNJ6wxfaicTiSYL9i2DDpMyNot+HUfhrYdyfaVcNsfy2/z2R TZ0=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+a.example.com. IN A
+SECTION ANSWER
+a.example.com. 3600 IN CNAME b.example.com.
+a.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. uiI9SNK74X//ACbllDC5LD49gjTmyL08CrtK1++I3rNPFFRChyJYAkUM wXBOXVW+fqBWOrXr835KCvUK/JJiSy/vvqE2+xI370OL8d9MvjR9vjIw Y2VusLWr3KmI4ixR7bAdG+FnMedapykOi8CJnbpkltU60QprQetcKGSv /Gk=
+b.example.com. 3600 IN A 1.2.3.5
+b.example.com. 3600 IN A 1.2.3.6
+b.example.com. 3600 IN A 1.2.3.7
+b.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. s5QtOdtBldJK1tdYNeWfQjoqVALI8eqcCRGOD1VocXRfDs3pgzowqtu5 rU/5vUxcN535/Z8nRPXEF7Ub5pgzEWupETiUvpEQP/Y+mNTaXrsgHTlc YCsCqbaPDNJ6wxfaicTiSYL9i2DDpMyNot+HUfhrYdyfaVcNsfy2/z2R TZ0=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; Cache hit
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+a.example.com. IN A
+SECTION ANSWER
+a.example.com. 3600 IN CNAME b.example.com.
+a.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. uiI9SNK74X//ACbllDC5LD49gjTmyL08CrtK1++I3rNPFFRChyJYAkUM wXBOXVW+fqBWOrXr835KCvUK/JJiSy/vvqE2+xI370OL8d9MvjR9vjIw Y2VusLWr3KmI4ixR7bAdG+FnMedapykOi8CJnbpkltU60QprQetcKGSv /Gk=
+b.example.com. 3600 IN A 1.2.3.5
+b.example.com. 3600 IN A 1.2.3.6
+b.example.com. 3600 IN A 1.2.3.7
+b.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. s5QtOdtBldJK1tdYNeWfQjoqVALI8eqcCRGOD1VocXRfDs3pgzowqtu5 rU/5vUxcN535/Z8nRPXEF7Ub5pgzEWupETiUvpEQP/Y+mNTaXrsgHTlc YCsCqbaPDNJ6wxfaicTiSYL9i2DDpMyNot+HUfhrYdyfaVcNsfy2/z2R TZ0=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ns_badaa.rpl b/tests/deckard/sets/resolver/iter_ns_badaa.rpl
new file mode 100644
index 0000000..aad267b
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ns_badaa.rpl
@@ -0,0 +1,174 @@
+; config options
+; target-fetch-policy: "3 2 1 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with NS falsely declaring referral answer as authoritative.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+; False declaration here
+REPLY QR AA NOERROR
+SECTION QUESTION
+MORECOWBELL. IN A
+SECTION AUTHORITY
+MORECOWBELL. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+CATALYST.MORECOWBELL. IN A
+SECTION ANSWER
+CATALYST.MORECOWBELL. IN A 10.20.30.40
+SECTION AUTHORITY
+CATALYST.MORECOWBELL. IN NS a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+catalyst.morecowbell. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+catalyst.morecowbell. IN A
+SECTION ANSWER
+catalyst.morecowbell. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ns_badglue.rpl b/tests/deckard/sets/resolver/iter_ns_badglue.rpl
new file mode 100644
index 0000000..a5998ed
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ns_badglue.rpl
@@ -0,0 +1,238 @@
+; config options
+; target-fetch-policy: "3 2 1 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with delagation with bad glue.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.gtld-servers.net. IN A
+SECTION ANSWER
+x.gtld-servers.net. IN A 192.5.6.31
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+; This is the offending NS (it must be ignored)
+com. IN NS x.gtld-servers.net.
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+x.gtld-servers.net. IN A 192.5.6.31
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY AA QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 3600 IN NS a.gtld-servers.net.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY AA QR NOERROR
+SECTION QUESTION
+foo.com. IN NS
+SECTION ANSWER
+foo.com. 3600 IN NS a.gtld-servers.net.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.foo.com. IN A
+SECTION ANSWER
+www.foo.com. 10 IN A 10.20.30.40
+SECTION AUTHORITY
+www.foo.com. 3600 IN NS a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+; x.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.31
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS x.gtld-servers.net.
+SECTION ADDITIONAL
+; Keep suggesting address records for this server
+x.gtld-servers.net. IN A 192.5.6.31
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.foo.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.foo.com. IN A
+SECTION ANSWER
+www.foo.com. 10 IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ns_badip.rpl b/tests/deckard/sets/resolver/iter_ns_badip.rpl
new file mode 100644
index 0000000..1d395df
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ns_badip.rpl
@@ -0,0 +1,261 @@
+; config options
+; target-fetch-policy: "3 2 1 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with delagation with bad IP address
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+; Intentional bad address
+a.gtld-servers.net. IN AAAA 1:2:3::4
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. - intentionally broken over IPv6
+RANGE_BEGIN 0 100
+ ADDRESS 1:2:3::4
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+. IN A
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net. - works over IPv4
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns.example.com. 10 IN A 1.2.3.4
+ns2.example.com. 3600 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+foo.com. IN A
+SECTION AUTHORITY
+foo.com. IN NS ns.example.com.
+foo.com. IN NS ns2.example.com.
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 10 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns.example.com. 10 IN A 1.2.3.4
+ns2.example.com. 3600 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. 10 IN A 1.2.3.4
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns2.example.com. 3600 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns2.example.com. IN A
+SECTION ANSWER
+ns2.example.com. 3600 IN A 1.2.3.5
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN NS ns2.example.com.
+SECTION ADDITIONAL
+ns.example.com. 10 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA bla. bla. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns2.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA bla. bla. 1 2 3 4 5
+ENTRY_END
+
+; foo.com contents.
+ENTRY_BEGIN
+ADJUST copy_id
+MATCH opcode qtype qname
+REPLY QR NOERROR
+SECTION QUESTION
+www.foo.com. IN A
+SECTION ANSWER
+www.foo.com. 10 IN A 10.20.30.40
+SECTION AUTHORITY
+foo.com. 3600 IN NS ns.example.com.
+foo.com. 3600 IN NS ns2.example.com.
+ENTRY_END
+
+RANGE_END
+
+; ns2.example.com. (lame)
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.foo.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.foo.com. IN A
+SECTION ANSWER
+www.foo.com. 10 IN A 10.20.30.40
+;SECTION AUTHORITY
+;foo.com. 3600 IN NS ns.example.com.
+;foo.com. 3600 IN NS ns2.example.com.
+ENTRY_END
+
+; Now move the time so good server times out and bad remains.
+STEP 20 TIME_PASSES ELAPSE 20
+
+; Try query again.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.foo.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.foo.com. IN A
+SECTION ANSWER
+www.foo.com. 10 IN A 10.20.30.40
+;SECTION AUTHORITY
+;foo.com. 3600 IN NS ns.example.com.
+;foo.com. 3600 IN NS ns2.example.com.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ns_noglue.rpl b/tests/deckard/sets/resolver/iter_ns_noglue.rpl
new file mode 100644
index 0000000..0895652
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ns_noglue.rpl
@@ -0,0 +1,220 @@
+; config options
+; target-fetch-policy: "3 2 1 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with delagation with missing mandatory glue.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+; This is the offending NS (it must be ignored)
+com. IN NS a.gtld-servers.com.
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+; False declaration here
+REPLY QR AA NOERROR
+SECTION QUESTION
+MORECOWBELL. IN A
+SECTION AUTHORITY
+MORECOWBELL. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+; This is the offending NS (it must be ignored)
+com. IN NS a.gtld-servers.com.
+com. IN NS a.gtld-servers.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY AA QR NOERROR
+SECTION QUESTION
+gtld-servers.com. IN NS
+SECTION AUTHORITY
+com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+foo.com. IN NS
+SECTION AUTHORITY
+foo.com. 3600 IN NS a.gtld-servers.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY AA QR NOERROR
+SECTION QUESTION
+foo.com. IN A
+SECTION ANSWER
+foo.com. 10 IN A 10.20.30.40
+SECTION AUTHORITY
+foo.com. 3600 IN NS a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+foo.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+foo.com. IN A
+SECTION ANSWER
+foo.com. 10 IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_ns_spoof.rpl b/tests/deckard/sets/resolver/iter_ns_spoof.rpl
new file mode 100644
index 0000000..1b81ed2
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_ns_spoof.rpl
@@ -0,0 +1,274 @@
+; config options
+; harden-referral-path: yes
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test NS record spoof protection.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; for simplicity the root server is authoritative for root-servers.net
+; and also for gtld-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+;; answer to the spoofed query ; spoofed reply answer.
+; here we put it in the nameserver for ease.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+bad123.example.com. IN A
+SECTION ANSWER
+bad123.example.com. IN A 6.6.6.6
+SECTION AUTHORITY
+; evil NS set.
+example.com. IN NS bad123.example.com.
+ENTRY_END
+
+RANGE_END
+
+; evil server
+RANGE_BEGIN 0 100
+ ADDRESS 6.6.6.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 6.6.6.6
+SECTION AUTHORITY
+example.com. IN NS bad123.example.com.
+SECTION ADDITIONAL
+bad123.example.com. IN A 6.6.6.6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 6.6.6.6
+SECTION AUTHORITY
+example.com. IN NS bad123.example.com.
+SECTION ADDITIONAL
+bad123.example.com. IN A 6.6.6.6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+bad123.example.com. IN A
+SECTION ANSWER
+bad123.example.com. IN A 6.6.6.6
+SECTION AUTHORITY
+; evil NS set.
+example.com. IN NS bad123.example.com.
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; spoofed query
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+bad123.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+; resolver gets address to spoofed server here
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+bad123.example.com. IN A
+SECTION ANSWER
+bad123.example.com. IN A 6.6.6.6
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; a new query
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.50
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pc_a.rpl b/tests/deckard/sets/resolver/iter_pc_a.rpl
new file mode 100644
index 0000000..606fc3b
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pc_a.rpl
@@ -0,0 +1,230 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ for type A.
+; the parent has the correct A record.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; the working version.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ftp.example.com. IN A
+SECTION ANSWER
+ftp.example.com. IN A 10.20.30.10
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+; now that the bad child NS record is in cache, ask something else.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+; test cache of parent data
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ftp.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ftp.example.com. IN A
+SECTION ANSWER
+ftp.example.com. IN A 10.20.30.10
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pc_aaaa.rpl b/tests/deckard/sets/resolver/iter_pc_aaaa.rpl
new file mode 100644
index 0000000..adee9a6
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pc_aaaa.rpl
@@ -0,0 +1,230 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ for type AAAA.
+; the parent has the correct A record.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::44
+ENTRY_END
+RANGE_END
+
+; the working version.
+RANGE_BEGIN 0 100
+ ADDRESS 2002:b44d::44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ns.example.com. IN AAAA 2002:b44d::55
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ftp.example.com. IN A
+SECTION ANSWER
+ftp.example.com. IN A 10.20.30.10
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+RANGE_END
+
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 2002:b44d::55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+; now that the bad child NS record is in cache, ask something else.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+; test cache of parent data
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ftp.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ftp.example.com. IN A
+SECTION ANSWER
+ftp.example.com. IN A 10.20.30.10
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN AAAA 2002:b44d::55
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcdiff.rpl b/tests/deckard/sets/resolver/iter_pcdiff.rpl
new file mode 100644
index 0000000..864f2aa
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcdiff.rpl
@@ -0,0 +1,208 @@
+; config options
+;server:
+; target-fetch-policy: "0 0 0 0 0"
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with recursion and parent child differ.
+; and the child gives bad information.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; The parent-IP version
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; The child IP version. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcdirect.rpl b/tests/deckard/sets/resolver/iter_pcdirect.rpl
new file mode 100644
index 0000000..c805ed0
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcdirect.rpl
@@ -0,0 +1,311 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolver with parent-child diff for direct impact
+; the trouble is resolving this right away.
+; otherwise it gets picked out of the cache.
+; i.e. on a failed lookup, pickup lame stuff from the cache.
+; the nameserver lookup may have failed but produced some (lame) addresses.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+; parent-side working address.
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+RANGE_END
+
+; a0.org.afilias-nst.org.
+RANGE_BEGIN 0 100
+ ADDRESS 199.19.56.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+org. IN NS
+SECTION ANSWER
+org. IN NS a0.org.afilias-nst.org.
+SECTION ADDITIONAL
+a0.org.afilias-nst.org. IN A 199.19.56.1
+ENTRY_END
+
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+; correct answer: ns.example.net. IN A 1.2.3.4
+SECTION AUTHORITY
+ns.example.net. IN NS 1.2.3.4.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RA NXDOMAIN
+SECTION QUESTION
+4.example.net. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.net. IN SOA ns.example.net. root.example.net. 2009111400 14400 3600 1209600 86400
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+ENTRY_END
+
+; perhaps some messages are still pending - allow those to resolve.
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.50
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcname.rpl b/tests/deckard/sets/resolver/iter_pcname.rpl
new file mode 100644
index 0000000..a45d823
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcname.rpl
@@ -0,0 +1,276 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ in names.
+; the parent has an extra name that is the only working one.
+; To understand the commented-out authority records see
+; https://mailarchive.ietf.org/arch/msg/dnsop/CYjPDlwtpxzdQV_qycB-WfnW6CI
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; the working version.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+; now that the bad child NS record is in cache, ask something else.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcnamech.rpl b/tests/deckard/sets/resolver/iter_pcnamech.rpl
new file mode 100644
index 0000000..723d3dc
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcnamech.rpl
@@ -0,0 +1,421 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ with extra child name.
+; child has extra name and it has to be used once the other one stops working.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+RANGE_END
+
+; the working version, until time 50.
+RANGE_BEGIN 0 50
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.44
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 50
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 50 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 50 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.44
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.example.net.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+; server stops working.
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.example.net.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+; still pending query needs removal.
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+STEP 71 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+;SECTION AUTHORITY
+;example.net. IN NS ns.example.net.
+;SECTION ADDITIONAL
+;ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcnamechrec.rpl b/tests/deckard/sets/resolver/iter_pcnamechrec.rpl
new file mode 100644
index 0000000..85a8376
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcnamechrec.rpl
@@ -0,0 +1,400 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ with pc child name.
+; child has extra name and it has to be used once the other one stops working.
+; the extra child name has parent-child trouble and needs its parent version.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+RANGE_END
+
+; the working version, until time 50.
+RANGE_BEGIN 0 50
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.44
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 50
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 50 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 50 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.44
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.example.net.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+; server stops working.
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.example.net.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcnamerec.rpl b/tests/deckard/sets/resolver/iter_pcnamerec.rpl
new file mode 100644
index 0000000..f53be60
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcnamerec.rpl
@@ -0,0 +1,274 @@
+; config options
+;server:
+; target-fetch-policy: "0 0 0 0 0"
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ names recursive.
+; the parent has an extra name that is the only working one.
+; and that name needs its parent-side glue to work.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; the working version.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; now that the bad child NS record is in cache, ask something else.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_pcttl.rpl b/tests/deckard/sets/resolver/iter_pcttl.rpl
new file mode 100644
index 0000000..93b588b
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_pcttl.rpl
@@ -0,0 +1,353 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; do-ip6: no
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test cache ttls where parent child differ in ttl
+; and the lameness for parent suddenly becomes the only information point.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.foo.com.
+SECTION ADDITIONAL
+;ns.foo.com. 200 IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+foo.com. IN NS
+SECTION AUTHORITY
+foo.com. 200 IN NS ns.foo.com.
+SECTION ADDITIONAL
+ns.foo.com. 200 IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. IN A 192.12.94.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+
+RANGE_END
+
+; ns.foo.com.
+; The parent-IP version
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+foo.com. IN NS
+SECTION ANSWER
+foo.com. 200 IN NS ns.foo.com.
+SECTION ADDITIONAL
+ns.foo.com. 100 IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.foo.com. IN A
+SECTION ANSWER
+ns.foo.com. 100 IN A 1.2.3.44
+SECTION AUTHORITY
+foo.com. 200 IN NS ns.foo.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.foo.com. IN AAAA
+SECTION AUTHORITY
+foo.com. 100 IN SOA . . 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 200 IN NS ns.foo.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 100 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 200 IN NS ns.foo.com.
+SECTION ADDITIONAL
+ns.foo.com 100 IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; NOT USED. The parent side equals child side but not in the cache.
+; and they have different TTLs only.
+; ns.foo.com
+; The child IP version. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+foo.com. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 100 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 100 IN NS ns.foo.com.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.foo.com IN A 1.2.3.44
+ENTRY_END
+
+; Now we wait 101 seconds, and the child data is gone,
+; but the parent-side was cached for 200 and it still there.
+
+STEP 30 TIME_PASSES ELAPSE 101
+
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 100 IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. 100 IN NS ns.foo.com.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.foo.com IN A 1.2.3.44
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_reclame_one.rpl b/tests/deckard/sets/resolver/iter_reclame_one.rpl
new file mode 100644
index 0000000..c569955
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_reclame_one.rpl
@@ -0,0 +1,316 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterative resolve with a recursion lame server.
+; The scenario has a domain with two servers, one is lame the other doesn't
+; so depending on the randomly chosen server that goes first, it may
+; select the nonlame or the lame server first.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+; parent-side working address.
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+lame.example.com. IN A
+SECTION ANSWER
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+lame.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; lame.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS lame.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_reclame_two.rpl b/tests/deckard/sets/resolver/iter_reclame_two.rpl
new file mode 100644
index 0000000..7d4aa4e
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_reclame_two.rpl
@@ -0,0 +1,355 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterative resolve with two recursion lame servers.
+; both servers are recursion lame. The iterator tries both servers,
+; but they are both lame. Then it concludes that it only has reclame.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+; parent-side working address.
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+lame.example.com. IN A
+SECTION ANSWER
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+lame.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; lame.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS lame.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+lame.example.com. IN A
+SECTION ANSWER
+lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+lame.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN SOA . . 0 0 0 0 0
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS lame.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;lame.example.com. IN A 1.2.3.5
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_recurse.rpl b/tests/deckard/sets/resolver/iter_recurse.rpl
new file mode 100644
index 0000000..2a30ee7
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_recurse.rpl
@@ -0,0 +1,312 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with recursion for NS target.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. IN A 192.12.94.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+; due to ordering of answer packets, this is still outstanding, remove it
+STEP 21 CHECK_OUT_QUERY
+ENTRY_BEGIN
+ADJUST copy_id
+MATCH qname qtype
+REPLY QR
+SECTION QUESTION
+ns.example.net IN AAAA
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_refuse.rpl b/tests/deckard/sets/resolver/iter_refuse.rpl
new file mode 100644
index 0000000..ead7537
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_refuse.rpl
@@ -0,0 +1,191 @@
+; config options
+;server:
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Iteration over ns server list.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. IN NS ns2.example.com.
+example.com. IN NS ns3.example.com.
+example.com. IN NS ns4.example.com.
+example.com. IN NS ns5.example.com.
+example.com. IN NS ns6.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 1.2.3.4
+ns2.example.com. IN A 1.2.3.5
+ns3.example.com. IN A 1.2.3.6
+ns4.example.com. IN A 1.2.3.7
+ns5.example.com. IN A 1.2.3.8
+ns6.example.com. IN A 1.2.3.9
+ENTRY_END
+RANGE_END
+
+; ns1.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+; ns2.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns3.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns4.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.7
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns5.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.8
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns6.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.9
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_req_qname.rpl b/tests/deckard/sets/resolver/iter_req_qname.rpl
new file mode 100644
index 0000000..e6840fb
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_req_qname.rpl
@@ -0,0 +1,120 @@
+; config options
+;server:
+; target-fetch-policy: "0 0 0 0 0"
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test a query name in the reply is required by resolver
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; always the same reply since we cannot match anything from the qsection.
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+; no query section!
+; www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+
+; the query name is echoed properly to *our* client
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_resolve.rpl b/tests/deckard/sets/resolver/iter_resolve.rpl
new file mode 100644
index 0000000..4cbf5e5
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_resolve.rpl
@@ -0,0 +1,219 @@
+; config options
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic iterative resolve of www.example.com.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; net.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; root-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. IN A 193.0.14.129
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+root-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; gtld-servers.net.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION AUTHORITY
+gtld-servers.net. IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_tcbit.rpl b/tests/deckard/sets/resolver/iter_tcbit.rpl
new file mode 100644
index 0000000..249c735
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_tcbit.rpl
@@ -0,0 +1,87 @@
+; config options
+; harden-referral-path: no
+; target-fetch-policy: "0 0 0 0 0"
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test TCP failover when reply contains TC=1.
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN A
+ENTRY_END
+
+; root prime
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+cz. IN NS ns2.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ns2.cz. IN A 168.192.3.3
+ENTRY_END
+
+; this is the truncated answer
+STEP 60 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA TC NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; this is the correct answer
+STEP 70 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+cz. IN NS ns2.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ns2.cz. IN A 168.192.3.3
+ENTRY_END
+
+; is the final answer correct?
+STEP 100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_timeouted_ns.rpl b/tests/deckard/sets/resolver/iter_timeouted_ns.rpl
new file mode 100644
index 0000000..70a3ed1
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_timeouted_ns.rpl
@@ -0,0 +1,316 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN fail.net has two NSs in different zones. One of them suddently stop responding, address of other one is unknown.
+
+RANGE_BEGIN 1 100 193.0.14.129; root
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. NS
+SECTION ANSWER
+. NS k.root-servers.net
+SECTION ADDITIONAL
+k.root-servers.net A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net NS
+SECTION AUTHORITY
+net NS m.gtld-servers.net.
+SECTION ADDITIONAL
+m.gtld-servers.net. A 192.55.83.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com NS
+SECTION AUTHORITY
+com NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 100 192.55.83.30; net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net NS
+SECTION ANSWER
+net NS m.gtld-servers.net.
+SECTION ADDITIONAL
+m.gtld-servers.net. A 192.55.83.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+m.gtld-servers.net. A
+SECTION ANSWER
+m.gtld-servers.net. A 192.55.83.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+fail.net NS
+SECTION AUTHORITY
+fail.net NS ns.fail.net
+fail.net NS ns.fail.com
+SECTION ADDITIONAL
+ns.fail.net 20 A 1.1.1.1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 100 192.5.6.30; com
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+com NS
+SECTION ANSWER
+com NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. A
+SECTION ANSWER
+a.gtld-servers.net. A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+fail.com NS
+SECTION AUTHORITY
+fail.com NS ns.fail.com
+SECTION ADDITIONAL
+ns.fail.com 10 A 1.1.2.1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 10 1.1.1.1; fail.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.net NS
+SECTION ANSWER
+fail.net NS ns.fail.net
+fail.net NS ns.fail.com
+SECTION ADDITIONAL
+ns.fail.net 20 A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.net A
+SECTION ANSWER
+ns.fail.net 20 A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.net AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.net A
+SECTION ANSWER
+fail.net 10 A 1.1.1.2
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 100 1.1.2.1; fail.com & fail.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.net NS
+SECTION ANSWER
+fail.net NS ns.fail.net
+fail.net NS ns.fail.com
+SECTION ADDITIONAL
+ns.fail.com 10 A 1.1.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.net A
+SECTION ANSWER
+ns.fail.net 20 A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.net AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+fail.com NS
+SECTION AUTHORITY
+fail.com NS ns.fail.com
+SECTION ADDITIONAL
+ns.fail.com 10 A 1.1.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.com A
+SECTION ANSWER
+ns.fail.com 10 A 1.1.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.fail.com AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.net A
+SECTION ANSWER
+fail.net 10 A 1.1.1.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.com A
+SECTION ANSWER
+fail.com 10 A 1.1.2.2
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 11 20 1.1.1.1; fail.net
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query do_not_answer
+REPLY QR AA NOERROR
+SECTION QUESTION
+fail.net A
+SECTION ANSWER
+fail.net 10 A 1.1.1.2
+ENTRY_END
+RANGE_END
+
+; Cache zonecuts for fail.net and fail.com
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+fail.net A
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+fail.net A
+SECTION ANSWER
+fail.net 10 A 1.1.1.2
+ENTRY_END
+
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+fail.com A
+ENTRY_END
+
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+fail.com A
+SECTION ANSWER
+fail.com 10 A 1.1.2.2
+ENTRY_END
+
+; Allow to expire ns.fail.com, fail.net, fail.com
+; Note that ns.fail.net isn't expired yet
+STEP 5 TIME_PASSES ELAPSE 15
+
+; Allow ns.fail.net to be timeouted
+; kresd must get right answer using ns.fail.com
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+fail.net A
+ENTRY_END
+
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+fail.net A
+SECTION ANSWER
+fail.net 10 A 1.1.1.2
+ENTRY_END
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_unexpectedrrtype.rpl b/tests/deckard/sets/resolver/iter_unexpectedrrtype.rpl
new file mode 100644
index 0000000..a94bef9
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_unexpectedrrtype.rpl
@@ -0,0 +1,59 @@
+stub-addr: 1.1.1.1
+CONFIG_END
+
+SCENARIO_BEGIN Test ignoring answers with unexpected RRType
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.1.1.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+example.com. 0 IN A 2.2.2.2 ; returns A record
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 1.1.1.1
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN AAAA
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END \ No newline at end of file
diff --git a/tests/deckard/sets/resolver/iter_validate.rpl b/tests/deckard/sets/resolver/iter_validate.rpl
new file mode 100644
index 0000000..5970a13
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_validate.rpl
@@ -0,0 +1,209 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-timestamp: "1437625000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 198.41.0.4 # a.root-servers.net.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic validation of NS cz. (two levels)
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20150802050000 20150723040000 1518 . JSoL4/wQXh7vzoY/m98WYbpr2/S66u4RQi/UhkSrR3JmPZaWRRERDFm6 RRrFY6GWt4CP61X9rvshuVT+0OhluXqYpEatoHEDgur+PKf3+dTAmcgQ 4RzsahwhQ42Y9fDgJ2nNVMcN97HEIH+qMv0FWjU9b7wJ2iYlDL1ZoAVu TKE=
+SECTION ADDITIONAL
+a.root-servers.net. 518400 IN A 198.41.0.4
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAa67bQck1JjopOOFc+iMISFcp/osWrEst2wbKbuQSUWu77QC9UHL ipiHgWN7JlqVAEjKITZz49hhkLmOpmLK55pTq+RD2kwoyNWk9cvpc+tS nIxT7i93O+3oVeLYjMWrkDAz7K45rObbHDuSBwYZKrcSIUCZnCpNMUtn PFl/04cb
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20150804235959 20150721000000 19036 . n9FwNj80Zik2Rr2zTB4F17ydFpiZfUIv8v/XAz4EbSgRxQgFT+TCz3FW i4O7tW5REXUVNHtULiS7fxKLsHZNDPev8DA20DXAw3eEIDi9pDi01O/e 4GnljpkPnP8d5zA62Dob4cxgmhjjFTvhIjtDsH5Dd4jmyHsgBboy4grZ uJNdsez76gD4Ad6WlosZn5Hj5JwqaxZlRph/6I3va4rkp4c32w5DwaQ7 WSne8ffMHX9r7Dn6EbT3FfvnXFDNPE1P6r+qzTzC0t+M/F4R3H+VOdqg cRJcBG6zGCh9ZErhAeoiJh1WAfpjpzx+TUMzqxZCjSC/XL+l2YMKVHtF 8WNg/w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+RANGE_END
+
+;a.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAbwKeyKB5fuLe16/N5MR6OoG/PO8uxEob7HoIjK0w0wNjwINYb2w edLtzhVlA4HJ0AUUBuZiNj41hlJ474SOBlsAA7BQdtbL1V0Ksk8IC5Z8 3ldU9Mp+ynkj9p9Cl2UOBmoVFYfkbwz0BsOptcXruYA52Ayc9rHrmDPI /0Y8gZAL
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150802000000 20150719000000 54576 cz. K04ONpLX3wseqHhUu2QLBY7wzSUszVlut5mC6jpCAqbfhgIvGMnyoWP5 lKwSvCLmjie0j1HSv8Q4OmoYGz8L+P/FGAzK4LhMturHrDtHkpuGvQJ6 //UsHQhf4iwCg5tEeHI4ZvaMmqRZI3FhBnSh0OyFjGO73FRbBU9nDrOM sPB1iCUfRfZhQU0sB/rj82ykBUma280sO1aRp3gmQHc/SVNbFfCL1Z8D htBP6sy4Jh0z3Z40d4CFZ8ZCBsIloHO44/GvXGePtr2dW4gJsoU1619B Jz+6cuTRh5RJBiweUNb/nwjBP8fNRkzH1CbjomC2FpDMnBXw7jE1GUiY vLW9Gg==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150805131929 20150723140842 39788 cz. KhyRPt4TYVYH7VAsfn39tY66+5P8bgZhG83d33oogLuqQEPgsxt/tu0c snrUA11Ub+4wOK3MslD5/gTyBuDtT9dk4FbRr3WeUZ4DNn5laYO3AcYx SAU3Vn3dZ8orWFxEwTKNhH5QthPdHj8p8097KRHiPo/DGEnFpYdocEws WJ4=
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+cz. 18000 IN RRSIG NS 10 1 18000 20150802132511 20150721120844 39788 cz. pf5UzinUesHzGQTav/1NxGW0AifCmzLW3S8X9tWDRwx7XSKGac7QVXgp nMNyb/NiSho9oj+ZTaQpBZQaTri+brHT4W/nE0TofqZlyYiaABb9xgxJ LgjLkt+OVcJsM3a+q+QEGSt+skNlZVDQeR+sztbuORiZXAqhxumxD8iy zZ8=
+SECTION ADDITIONAL
+a.ns.nic.cz. 18000 IN A 194.0.12.1
+b.ns.nic.cz. 18000 IN A 194.0.12.1
+c.ns.nic.cz. 18000 IN A 194.0.12.1
+d.ns.nic.cz. 18000 IN A 194.0.12.1
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION ANSWER
+; It's okay to lie here as the resolver can't check if we have provided every RRSIG, because there is no RRSIG of RRSIGs
+cz. 18000 IN RRSIG SOA 10 1 18000 20151221212655 20151208120941 37310 cz. ZsKG0TImVm+nAuWvn+Kg61WIet0E++Bt1mxIIywCxtZs/JQlhbjzFPvA ICdYLoqZ06JTwit1nD9xx6jdrfguSVB55G3LGuQiXz4JwEdCWhoVcC3Y Aq6jG1Eor3dhAF8dSIYkE21J3A6oC3O1rDYymKiXpkekFMaaBE0JEvUJ ut8=
+ENTRY_END
+
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN RRSIG
+ENTRY_END
+
+; check that it answers a query for RRSIG (unauthenticated)
+; digests are swapped, i.e. signatures are invalid, server shouldn't use them later
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION ANSWER
+cz. 18000 IN RRSIG SOA 10 1 18000 20151221212655 20151208120941 37310 cz. ZsKG0TImVm+nAuWvn+Kg61WIet0E++Bt1mxIIywCxtZs/JQlhbjzFPvA ICdYLoqZ06JTwit1nD9xx6jdrfguSVB55G3LGuQiXz4JwEdCWhoVcC3Y Aq6jG1Eor3dhAF8dSIYkE21J3A6oC3O1rDYymKiXpkekFMaaBE0JEvUJ ut8=
+ENTRY_END
+
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN NS
+ENTRY_END
+
+; check that it answers a plain query
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+ENTRY_END
+
+STEP 5 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+cz. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 6 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+cz. 18000 IN RRSIG NS 10 1 18000 20150802132511 20150721120844 39788 cz. pf5UzinUesHzGQTav/1NxGW0AifCmzLW3S8X9tWDRwx7XSKGac7QVXgp nMNyb/NiSho9oj+ZTaQpBZQaTri+brHT4W/nE0TofqZlyYiaABb9xgxJ LgjLkt+OVcJsM3a+q+QEGSt+skNlZVDQeR+sztbuORiZXAqhxumxD8iy zZ8=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_validate_child_zone_noaddr.rpl b/tests/deckard/sets/resolver/iter_validate_child_zone_noaddr.rpl
new file mode 100644
index 0000000..4d885ad
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_validate_child_zone_noaddr.rpl
@@ -0,0 +1,207 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-timestamp: "1441892800"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 198.41.0.4 # a.root-servers.net.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic validation of AAAA nic.cz.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20150920050000 20150910040000 1518 . ZCytFZO9aWv+135mNVaH+qdlXz1t2VyhaOx4GVbydiRuEMVKvjauxXMb OfnCK451G95AjxaL00eCi68Z19B3+pa6Ud8X81M69fHeB4/Eh+KIjl+d YvmUw3DxVQJknj/sHBVihjgsiMsiw03lE+dX+g2ms9TQbOo5VohLPgpC 82A=
+SECTION ADDITIONAL
+a.root-servers.net. 518400 IN A 198.41.0.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 172800 IN DNSKEY 256 3 8 AwEAAa67bQck1JjopOOFc+iMISFcp/osWrEst2wbKbuQSUWu77QC9UHL ipiHgWN7JlqVAEjKITZz49hhkLmOpmLK55pTq+RD2kwoyNWk9cvpc+tS nIxT7i93O+3oVeLYjMWrkDAz7K45rObbHDuSBwYZKrcSIUCZnCpNMUtn PFl/04cb
+. 172800 IN RRSIG DNSKEY 8 0 172800 20150924000000 20150909000000 19036 . XGBRtnftNzxfk4LFyMzQXv9ZSV//SuiHlUYfnK8i0Hg3bHuOR2oEJ+JN P5HBlg+BGLTYHYBTuQYwn0FZd81gF7nVPDcQmHPwPzgwPWH00RDt46dK J1LwJ5KsAbNT5FOVuYRO2Rm15eajwaYGtJHSOyxHEegzuklvMgVVSiBr rPbNTF2/1Qi4c1y1gPXuxkifENbxlbHMvWxcVnG0v2xko/MazQnzSStv i1TtKUKDNT/jLyAv24wALWsPhOcNoVl1uRr9IJX7Ov9wbvSVCoEuBeKC hgy0KO1lRffnqR1YRRqjabKXB161T/fepLkwkxqa0Uidk+rRL3jxulJa nL2TMQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nic.cz. IN MX
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150920050000 20150910040000 1518 . LRx9WQ8KhcUHOCe+eY7jvw1QIm1aRrin02Qn9YtImOGf4V1MVhf1ZYoF mP7GOBDXAbAJhrb5fPKumLsuRLgmA+5VyFhBMmzgqwRjdec1Tu7mWHoQ EukoZp4y2Mmw4NuAs1pBJQOZzLxhYUk+vbjK9mZm5u+mTtt/EFUu8QfG bp8=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150920050000 20150910040000 1518 . LRx9WQ8KhcUHOCe+eY7jvw1QIm1aRrin02Qn9YtImOGf4V1MVhf1ZYoF mP7GOBDXAbAJhrb5fPKumLsuRLgmA+5VyFhBMmzgqwRjdec1Tu7mWHoQ EukoZp4y2Mmw4NuAs1pBJQOZzLxhYUk+vbjK9mZm5u+mTtt/EFUu8QfG bp8=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150920050000 20150910040000 1518 . LRx9WQ8KhcUHOCe+eY7jvw1QIm1aRrin02Qn9YtImOGf4V1MVhf1ZYoF mP7GOBDXAbAJhrb5fPKumLsuRLgmA+5VyFhBMmzgqwRjdec1Tu7mWHoQ EukoZp4y2Mmw4NuAs1pBJQOZzLxhYUk+vbjK9mZm5u+mTtt/EFUu8QfG bp8=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+RANGE_END
+
+;a.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAdORJsCVmI4NZRmgtDDRoULmnP6JsA/wR68Z5gO8XD/awSiqsKEB 6BXNC2jvBiPFA94oXroeLXxCjLN+GS/fE1zCKklKfdY5wOHNIlfekWOO 4rbgJtmDzL3IuTbGmNSSIZ0TJkk5NVzpo+Zon9peX2nPdacytQ36hHup GlJMKTxH
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150917000000 20150903000000 54576 cz. Ei0P45gSw4Vp4u4/H74vm58ehU5JlB4SGLnXXw1U6qVq8EwYrRHv3gV6 9RrUt2GgCqfUlvlJr1Q4WYAJkkiW5zhXJAzCzamtHGuxo3lZuqV1oyw2 zzL4khvmzT0wMxm13TaeSqjbrAEth/00oHIJPqDzrhYlJX74V1q49mD/ 2VoMIVctnTOyE4A+swlyMLOBD8mmjXr47+a5VuwE3bkzBKn1rdHiePl5 MJQjT9Es+qcyMEFZb31/ZOa6MWci1+P28bKFG6mKLVyyiK8sDCkqw/l3 1CTlxRyFdxQc6cBc5KrZwsfApNi5bXXuaJvuOW/YSRbI72HGUNtbbN2v ttsiBw==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150922144030 20150910120939 45182 cz. CajFqhmkoOnO9S1HG/o5TTz2nk8fuaKYSZw6aW7vBcVsUAu3PB2fBCpj zRA2JNtX9ebwXPP4WQR+DPgh+hkOneSUK0hNkp5CguUUr+kiJy8a2IXm 3mmvt7yldkq3Xr3Ygqk9yGW5Sd7NiXT4jOXSMmBueNJFnPf9WThEPpqV zc4=
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN MX
+SECTION ANSWER
+nic.cz. 1800 IN MX 20 mx.nic.cz.
+nic.cz. 1800 IN MX 30 bh.nic.cz.
+nic.cz. 1800 IN MX 10 mail.nic.cz.
+nic.cz. 1800 IN RRSIG MX 5 2 1800 20150917230532 20150904125503 46296 nic.cz. qzyjltVcO33Jisn5RVxSAy8D8QHv71hpKgX9D4TBKe/Yrr7aI7rB6tLQ JCLJlYdq7m0w2N+QZCczV67OK3ZTDPErl/N0IKbxK84EVp5/NqgzKivl h95Z1T1jRf9iGdauDMjz8QTFpnOs62/CuOuEJwAIXeIuH2eT25AoBRDe sXM=
+SECTION AUTHORITY
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 5 2 1800 20150917134944 20150904125503 46296 nic.cz. gPCmMHvHl+76p6ERWuKS9tH/xwD5Or0ZON866yRy1hM0YCzOO0lIsSU9 fxHTKlx3gx0pgz4EGH3Doi54lT9XRZDyp/XiZ6j4+q+583cFJ05ISQHM Sp4QTMqAYCN1XchH2li+YWCgZqUqK1C+D+OO4Zbfu3YVTEaox82+OkCg 0Uo=
+SECTION ADDITIONAL
+a.ns.nic.cz. 18000 IN A 194.0.12.1
+b.ns.nic.cz. 18000 IN A 194.0.12.1
+d.ns.nic.cz. 18000 IN A 194.0.12.1
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION ANSWER
+nic.cz. 18000 IN DS 59916 5 1 144130216E45C4EC2BB8595E817916E8B060D87B
+nic.cz. 18000 IN RRSIG DS 10 2 18000 20150918193553 20150905063845 45182 cz. leMkrTPUUrO6CmBU9pTMTT2f+0V4DV8P/uY8ZyDa0YHSUZVoFzW4cXZy xzZfgE0y/Q6eJYOeqPOPOoFKs4g8JhdcmFwOrf6Pnmfk5eOhgJVtg5nX xW+j1G3n24a2H4u6ITEzheTcYj00/l8tfPPzS+JW+2yyPALxmQqx4pKP N6I=
+ENTRY_END
+
+;a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz. 1800 IN DNSKEY 257 3 5 BQEAAAABt3LenoCVTV0okqKYPDnnVJqvwCD9MKJNXg8fcOCdLQYncyoe hpwM5RK2UkZDcDxWkMo7yMa35ej+Mhpaji9si4xXD+Syl4Q06LFiFkdN /5GlVlrIdE3GW7zC7Z4sS14Vz8FbYfcRmhsh19Ob718jGZneGfw2UPbv kyxUR8wD7mguZn02fQ6tjj/Ktp4uSW9tpz3bjGMo2rX+iZk4xgbPaesA OlR/AaHdatGZsWC9CPon8mnLZeu6czm8CBDgBmnf3PE8c5+uyWj1Pw4p p0VQmnX5UrnuGpErg7qXhJm7wY2CRVRMcLX3zmjVWXW1uT9JFh2G+/pZ zxnASfKKltZpuw==
+nic.cz. 1800 IN DNSKEY 256 3 5 AwEAAcrwqogrgLUrCRzhbXoMEBPy/55Zeg+yyOYodLGT9ts9UhGYRSgI BJQq6aX/6QOf042niK809bglBRid56ioSV7BlMQeuJx9+87AEiqEupS1 Zg5CzLHx/JLGloCWeCT5bwL4hAmT8gCu8xjHvLFqQjr4QX71Et4MfrJG rOgGpcRJ
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150918013842 20150904125503 46296 nic.cz. J92bm8JmPiF3JVyqlmXpBMgVkiIxLfZq+M1fpRMTiemSrC/S5Fj8RHXU 4qVy/wbToegcd6ivqxKNa4IjIrjQ7L5FSfBjcVkBxarWgXp70k7UEc23 K1ZvLHGwa6efmb/RILjdi2YptQzA52f43mwF5qHfWFkEWVXVgNbqm+Zu arY=
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150918082556 20150904125503 59916 nic.cz. Zc5XVLTa41lxbOhRkL+PsY3HIpBe43yTrvr9qKRMMuZeyhWsN8YDzUho Otsq3ujf6HyRhJVZrh9Y0Eh2yrvvi+lVSc1ez1kMaqmB+MZxx+d7/f3E 150jW4nGm6T09pyLcKR0sOPV2dRcdgLeeI29wA1S99jr+FWc4AWmQ8/c jjWOW+78EFlDhSu76gUEHi+R/VYhhzW97R4kqaKzqITLhG4luql2s/5E MuHX3MAbFFq6bq5RqS4rxuqxj59VvUSGSWhsxS0HGDrJIsYsrqvRFcg/ yWiEIhTPr/RvmDkNf57p+wWEbI9GkUDE4K53RSKz2jg+z8kcw/FiO731 yMvdcQ==
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+nic.cz. IN DNSKEY
+ENTRY_END
+
+; check if fetching DNSKEY works (tests processing with same server authoritative for both parent and child)
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz. 1800 IN DNSKEY 256 3 5 AwEAAcrwqogrgLUrCRzhbXoMEBPy/55Zeg+yyOYodLGT9ts9UhGYRSgI BJQq6aX/6QOf042niK809bglBRid56ioSV7BlMQeuJx9+87AEiqEupS1 Zg5CzLHx/JLGloCWeCT5bwL4hAmT8gCu8xjHvLFqQjr4QX71Et4MfrJG rOgGpcRJ
+nic.cz. 1800 IN DNSKEY 257 3 5 BQEAAAABt3LenoCVTV0okqKYPDnnVJqvwCD9MKJNXg8fcOCdLQYncyoe hpwM5RK2UkZDcDxWkMo7yMa35ej+Mhpaji9si4xXD+Syl4Q06LFiFkdN /5GlVlrIdE3GW7zC7Z4sS14Vz8FbYfcRmhsh19Ob718jGZneGfw2UPbv kyxUR8wD7mguZn02fQ6tjj/Ktp4uSW9tpz3bjGMo2rX+iZk4xgbPaesA OlR/AaHdatGZsWC9CPon8mnLZeu6czm8CBDgBmnf3PE8c5+uyWj1Pw4p p0VQmnX5UrnuGpErg7qXhJm7wY2CRVRMcLX3zmjVWXW1uT9JFh2G+/pZ zxnASfKKltZpuw==
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150918013842 20150904125503 46296 nic.cz. J92bm8JmPiF3JVyqlmXpBMgVkiIxLfZq+M1fpRMTiemSrC/S5Fj8RHXU 4qVy/wbToegcd6ivqxKNa4IjIrjQ7L5FSfBjcVkBxarWgXp70k7UEc23 K1ZvLHGwa6efmb/RILjdi2YptQzA52f43mwF5qHfWFkEWVXVgNbqm+Zu arY=
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150918082556 20150904125503 59916 nic.cz. Zc5XVLTa41lxbOhRkL+PsY3HIpBe43yTrvr9qKRMMuZeyhWsN8YDzUho Otsq3ujf6HyRhJVZrh9Y0Eh2yrvvi+lVSc1ez1kMaqmB+MZxx+d7/f3E 150jW4nGm6T09pyLcKR0sOPV2dRcdgLeeI29wA1S99jr+FWc4AWmQ8/c jjWOW+78EFlDhSu76gUEHi+R/VYhhzW97R4kqaKzqITLhG4luql2s/5E MuHX3MAbFFq6bq5RqS4rxuqxj59VvUSGSWhsxS0HGDrJIsYsrqvRFcg/ yWiEIhTPr/RvmDkNf57p+wWEbI9GkUDE4K53RSKz2jg+z8kcw/FiO731 yMvdcQ==
+ENTRY_END
+
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+nic.cz. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+nic.cz. IN MX
+SECTION ANSWER
+nic.cz. 1800 IN MX 20 mx.nic.cz.
+nic.cz. 1800 IN MX 30 bh.nic.cz.
+nic.cz. 1800 IN MX 10 mail.nic.cz.
+nic.cz. 1800 IN RRSIG MX 5 2 1800 20150917230532 20150904125503 46296 nic.cz. qzyjltVcO33Jisn5RVxSAy8D8QHv71hpKgX9D4TBKe/Yrr7aI7rB6tLQ JCLJlYdq7m0w2N+QZCczV67OK3ZTDPErl/N0IKbxK84EVp5/NqgzKivl h95Z1T1jRf9iGdauDMjz8QTFpnOs62/CuOuEJwAIXeIuH2eT25AoBRDe sXM=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_validate_extradata.rpl b/tests/deckard/sets/resolver/iter_validate_extradata.rpl
new file mode 100644
index 0000000..e32af3a
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_validate_extradata.rpl
@@ -0,0 +1,212 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-timestamp: "1437625000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 198.41.0.4 # a.root-servers.net.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic validation, answer contains an extra A record which must be ignored.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20150802050000 20150723040000 1518 . JSoL4/wQXh7vzoY/m98WYbpr2/S66u4RQi/UhkSrR3JmPZaWRRERDFm6 RRrFY6GWt4CP61X9rvshuVT+0OhluXqYpEatoHEDgur+PKf3+dTAmcgQ 4RzsahwhQ42Y9fDgJ2nNVMcN97HEIH+qMv0FWjU9b7wJ2iYlDL1ZoAVu TKE=
+SECTION ADDITIONAL
+a.root-servers.net. 518400 IN A 198.41.0.4
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAa67bQck1JjopOOFc+iMISFcp/osWrEst2wbKbuQSUWu77QC9UHL ipiHgWN7JlqVAEjKITZz49hhkLmOpmLK55pTq+RD2kwoyNWk9cvpc+tS nIxT7i93O+3oVeLYjMWrkDAz7K45rObbHDuSBwYZKrcSIUCZnCpNMUtn PFl/04cb
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20150804235959 20150721000000 19036 . n9FwNj80Zik2Rr2zTB4F17ydFpiZfUIv8v/XAz4EbSgRxQgFT+TCz3FW i4O7tW5REXUVNHtULiS7fxKLsHZNDPev8DA20DXAw3eEIDi9pDi01O/e 4GnljpkPnP8d5zA62Dob4cxgmhjjFTvhIjtDsH5Dd4jmyHsgBboy4grZ uJNdsez76gD4Ad6WlosZn5Hj5JwqaxZlRph/6I3va4rkp4c32w5DwaQ7 WSne8ffMHX9r7Dn6EbT3FfvnXFDNPE1P6r+qzTzC0t+M/F4R3H+VOdqg cRJcBG6zGCh9ZErhAeoiJh1WAfpjpzx+TUMzqxZCjSC/XL+l2YMKVHtF 8WNg/w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150802050000 20150723040000 1518 . fEz3NpYRzgeBjKrLMpht3KFOQ0t6U2wikIaOt1HcmFvurxtPkZVvqdb0 QBQfvh8DoEXDbvpcikzMIO9XYLzzs10X/m91ybGiWzcTVcU+prVGZJP9 zZrvYAIWrpxoC4deKD+vOoNZXGnLfffi6lmGn7QRZaH0LVKjn33cIaPQ 9EM=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+
+RANGE_END
+
+;a.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAbwKeyKB5fuLe16/N5MR6OoG/PO8uxEob7HoIjK0w0wNjwINYb2w edLtzhVlA4HJ0AUUBuZiNj41hlJ474SOBlsAA7BQdtbL1V0Ksk8IC5Z8 3ldU9Mp+ynkj9p9Cl2UOBmoVFYfkbwz0BsOptcXruYA52Ayc9rHrmDPI /0Y8gZAL
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150802000000 20150719000000 54576 cz. K04ONpLX3wseqHhUu2QLBY7wzSUszVlut5mC6jpCAqbfhgIvGMnyoWP5 lKwSvCLmjie0j1HSv8Q4OmoYGz8L+P/FGAzK4LhMturHrDtHkpuGvQJ6 //UsHQhf4iwCg5tEeHI4ZvaMmqRZI3FhBnSh0OyFjGO73FRbBU9nDrOM sPB1iCUfRfZhQU0sB/rj82ykBUma280sO1aRp3gmQHc/SVNbFfCL1Z8D htBP6sy4Jh0z3Z40d4CFZ8ZCBsIloHO44/GvXGePtr2dW4gJsoU1619B Jz+6cuTRh5RJBiweUNb/nwjBP8fNRkzH1CbjomC2FpDMnBXw7jE1GUiY vLW9Gg==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150805131929 20150723140842 39788 cz. KhyRPt4TYVYH7VAsfn39tY66+5P8bgZhG83d33oogLuqQEPgsxt/tu0c snrUA11Ub+4wOK3MslD5/gTyBuDtT9dk4FbRr3WeUZ4DNn5laYO3AcYx SAU3Vn3dZ8orWFxEwTKNhH5QthPdHj8p8097KRHiPo/DGEnFpYdocEws WJ4=
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+cz. 18000 IN RRSIG NS 10 1 18000 20150802132511 20150721120844 39788 cz. pf5UzinUesHzGQTav/1NxGW0AifCmzLW3S8X9tWDRwx7XSKGac7QVXgp nMNyb/NiSho9oj+ZTaQpBZQaTri+brHT4W/nE0TofqZlyYiaABb9xgxJ LgjLkt+OVcJsM3a+q+QEGSt+skNlZVDQeR+sztbuORiZXAqhxumxD8iy zZ8=
+SECTION AUTHORITY
+extra-a. 3600 IN A 1.2.3.4
+extra-ns. 3600 IN NS target-extra-ns.
+SECTION ADDITIONAL
+a.ns.nic.cz. 18000 IN A 194.0.12.1
+b.ns.nic.cz. 18000 IN A 194.0.12.1
+c.ns.nic.cz. 18000 IN A 194.0.12.1
+d.ns.nic.cz. 18000 IN A 194.0.12.1
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION ANSWER
+; It's okay to lie here as the resolver can't check if we have provided every RRSIG, because there is no RRSIG of RRSIGs
+cz. 18000 IN RRSIG SOA 10 1 18000 20151221212655 20151208120941 37310 cz. ZsKG0TImVm+nAuWvn+Kg61WIet0E++Bt1mxIIywCxtZs/JQlhbjzFPvA ICdYLoqZ06JTwit1nD9xx6jdrfguSVB55G3LGuQiXz4JwEdCWhoVcC3Y Aq6jG1Eor3dhAF8dSIYkE21J3A6oC3O1rDYymKiXpkekFMaaBE0JEvUJ ut8=
+ENTRY_END
+
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN RRSIG
+ENTRY_END
+
+; check that it answers a query for RRSIG (unauthenticated)
+; digests are swapped, i.e. signatures are invalid, server shouldn't use them later
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+cz. IN RRSIG
+SECTION ANSWER
+cz. 18000 IN RRSIG SOA 10 1 18000 20151221212655 20151208120941 37310 cz. ZsKG0TImVm+nAuWvn+Kg61WIet0E++Bt1mxIIywCxtZs/JQlhbjzFPvA ICdYLoqZ06JTwit1nD9xx6jdrfguSVB55G3LGuQiXz4JwEdCWhoVcC3Y Aq6jG1Eor3dhAF8dSIYkE21J3A6oC3O1rDYymKiXpkekFMaaBE0JEvUJ ut8=
+ENTRY_END
+
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN NS
+ENTRY_END
+
+; check that it answers a plain query
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+ENTRY_END
+
+STEP 5 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+cz. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 6 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+cz. 18000 IN RRSIG NS 10 1 18000 20150802132511 20150721120844 39788 cz. pf5UzinUesHzGQTav/1NxGW0AifCmzLW3S8X9tWDRwx7XSKGac7QVXgp nMNyb/NiSho9oj+ZTaQpBZQaTri+brHT4W/nE0TofqZlyYiaABb9xgxJ LgjLkt+OVcJsM3a+q+QEGSt+skNlZVDQeR+sztbuORiZXAqhxumxD8iy zZ8=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/iter_validate_nsec_nxdomain.rpl b/tests/deckard/sets/resolver/iter_validate_nsec_nxdomain.rpl
new file mode 100644
index 0000000..9f04456
--- /dev/null
+++ b/tests/deckard/sets/resolver/iter_validate_nsec_nxdomain.rpl
@@ -0,0 +1,152 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-timestamp: "1438783903"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 198.41.0.4 # a.root-servers.net.
+CONFIG_END
+
+SCENARIO_BEGIN Test basic validation of MX xxx.nic.cz.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20150809050000 20150730040000 1518 . ntWgyA7SjlVedxDStbRA6fXl0Hq5pyBgVtBb6l+LbqgLs8/2mwPhzaEw A/BMM+wr7KQLvNSyxTl/SZny94uMVu7o2fnI6+bCP5C+lo7PWni/GvMU yj3JSq2hPv3iO/D1ch8yaKddtYL/NCwPBn9CgpW0jWIWp8FvwwCR4RAs GzA=
+SECTION ADDITIONAL
+a.root-servers.net. 518400 IN A 198.41.0.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAa67bQck1JjopOOFc+iMISFcp/osWrEst2wbKbuQSUWu77QC9UHL ipiHgWN7JlqVAEjKITZz49hhkLmOpmLK55pTq+RD2kwoyNWk9cvpc+tS nIxT7i93O+3oVeLYjMWrkDAz7K45rObbHDuSBwYZKrcSIUCZnCpNMUtn PFl/04cb
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20150814235959 20150731000000 19036 . GW5z3/PgUahqXvFy4UKqc+gxl6b1T4MwHP6E08PUd1KSyFAy/7cltOP6 dfavtYwP9HWIadti7w0GkK560vWEe0aneJCqn9VvSWLI7wrrTLTDd03v WRFk0qxEaVZ22MxqA2AxHMEnEgbLJ9oTJL8eUZDRetKeCgk3w8zypq4f 3xnh0QO7p5F8mBUlAcrCy8B20ZqItvq9irdeeWOSvvJWs35XnPY497xz WVLrF4hOLQnhmgxJpIDwNRGlkqmbNAmVIICOkrG9S9mvZdhhQqogzHhn k6T7Ws1ZQ2FTYBLc5/QA3urEAn8H6TCm5D+wURcfy5x++hXBOIxipkyh 4yfsgw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+missing.nic.cz. IN MX
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20150815050000 20150805040000 1518 . jeryA8jj+yf2X9exz5Ka/Nfifr+k5++Se1klItsut3Jvy1d0X6TI5pjr ABzXbhOUGz6M4cUKhLjM3XDTRspu/VT4DhJUE2pRITKBzeAabDN6dkO/ KHbB/Klrc5DjSeq3RNA3zj39U/TxT+gO8F/fzn6FQKIGkcxwSzSD4Xov K5Q=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+RANGE_END
+
+;a.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAbwKeyKB5fuLe16/N5MR6OoG/PO8uxEob7HoIjK0w0wNjwINYb2w edLtzhVlA4HJ0AUUBuZiNj41hlJ474SOBlsAA7BQdtbL1V0Ksk8IC5Z8 3ldU9Mp+ynkj9p9Cl2UOBmoVFYfkbwz0BsOptcXruYA52Ayc9rHrmDPI /0Y8gZAL
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150814000000 20150731000000 54576 cz. T/q1zripqILs8CdStXtf/GRpDhgbduHC6AEoGfnK+lfxk9okn6amwhho j464OUtH1wGlS9pikWQ02O6BX5CRaaaZjgMeIJugj3w4MZMPbSk1tV5y JaRXaec/uZI5h91iJtQzNAP5rbMj5liIYQV02nrN8+5SVBwxnrJ9JvQ/ tOetsoP2eh1wlgb+Tu+GgrYVrO/4EwOUk+5RUuMVKofGvY+vyYaEuRip rr6pSjH+dhjKegMv2IQ9rBEI1MKWcFA3+6ZqaMazNShgeEJgBI3GKPog AFiZFijDl5Pd5+4/HftGYpXnUlon266ilvCCS1RzE3pynnHPFFRVBmd6 Q38sIQ==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20150818181624 20150805140846 39788 cz. dmYD4pzcswSWyVEqEaCKXN1a58uP2b7/fscNn24wAhQ891sTZi3kNhS8 BvoYIncoAppi+Kkw9vRfXNB26YhBgalCDBxHdwg1vxMD/uHiTrQ1KFFM ZjeM+CYTmULK6PY06NN8IyauL87gcx8k2/r9GVr71yUC1nNjNum4ZRZD EiQ=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing.nic.cz. IN MX
+SECTION AUTHORITY
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1438786503 10800 3600 1209600 7200
+nic.cz. 1800 IN RRSIG SOA 5 2 1800 20150819080542 20150805135503 24582 nic.cz. TDX7klpEuTI2vUQdmNzacxND0p828AD1HNxzTop0MJqKTehn8XgPoSK0 ZRWITLIMTtmC9UFLh/nb9I06HqUVdirxCKWvSzO840wjoVF7SjLWZysB 3VhPn84NA/9m8N8dmpTIt2IpN2N/T0lZVIIg/SSeru/dPNKH1uNtKekv 1eg=
+nic.cz. 7200 IN NSEC 6to4.nic.cz. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nic.cz. 7200 IN RRSIG NSEC 5 2 7200 20150818164706 20150805135503 24582 nic.cz. dqZiT0kHOtrap/aNq/M4u6KCGAS+f1yrAa6aDVBnqIopJ4DJJjnh67WF LedeHae5JLDNwuZV8SlkicIwW5K2ET4//2bJ6FCJcw89s40s3h/QnVxB +wV6hNhqfVnOjtHO4TWK96uNhf/B+A4N/voSpA21zYBMTV8mFvynj7oy ozk=
+*.mirrors.nic.cz. 7200 IN NSEC akuma.mnt.nic.cz. CNAME RRSIG NSEC
+*.mirrors.nic.cz. 7200 IN RRSIG NSEC 5 3 7200 20150819054509 20150805135503 24582 nic.cz. BDT/Rw1F7/QJd76/KWL0jdkdHkzWNxxZ2Hdgba6o1okc0mgqz2ag1P3s BkYtzWMwql4U7Au/KcLtq6P8X2/T9xytqmYfpn2O1dCaBzHubeTiz/aP wcPaYEC+jPR7JwmHpZlxs+KirS4yo7aVF1OPP7ZjtuqDeNLvmF4W7mHl r/A=
+ENTRY_END
+
+; a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION ANSWER
+nic.cz. 18000 IN DS 59916 5 1 144130216E45C4EC2BB8595E817916E8B060D87B
+nic.cz. 18000 IN RRSIG DS 10 2 18000 20150817213510 20150804233901 39788 cz. sxyJEb5Aqpk65VNqxI6bIbyB2UweVjAMf4YvyMJh6MAOGeii8tRbHoJN CntFpaW8sDrw1dgv/xQMFB04Yl3B518n1vMHspweuT3GX5MVV8dEED+9 MdDC0LvhrcPhcoY7ZEz4koywHN39J51tzeSiAPIyQPpMv/b1E3YLwPou lOQ=
+ENTRY_END
+
+;a.ns.nic.cz.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz. 1800 IN DNSKEY 256 3 5 AwEAAatglK6e9CpmATmEDtjQfOMqSEGB2KT3xciP+ZuBH3qYQDggHxao Hk9cfL5uXHxEr8AqmiTNA2CJ9oVm2wlZFCTUtQS2Vxz+i30XQpIPoh1y 0fU/XHKmrVmdVGzc9OdgDyZT+8CbUInAyUin+tWM9M7ekUXAllUw5bd8 VC4SJO3z
+nic.cz. 1800 IN DNSKEY 257 3 5 BQEAAAABt3LenoCVTV0okqKYPDnnVJqvwCD9MKJNXg8fcOCdLQYncyoe hpwM5RK2UkZDcDxWkMo7yMa35ej+Mhpaji9si4xXD+Syl4Q06LFiFkdN /5GlVlrIdE3GW7zC7Z4sS14Vz8FbYfcRmhsh19Ob718jGZneGfw2UPbv kyxUR8wD7mguZn02fQ6tjj/Ktp4uSW9tpz3bjGMo2rX+iZk4xgbPaesA OlR/AaHdatGZsWC9CPon8mnLZeu6czm8CBDgBmnf3PE8c5+uyWj1Pw4p p0VQmnX5UrnuGpErg7qXhJm7wY2CRVRMcLX3zmjVWXW1uT9JFh2G+/pZ zxnASfKKltZpuw==
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150818153605 20150805135503 59916 nic.cz. iDP/U4c8zJF085/V/CAlRU4Hs1RugPkzJdaYVCXwnpZ5vjArAY5wzUtx 88626FvBgVD/hnCUrSoN8eNz8ISSsyk3Ql3bTp5Cmxi+hgIqWd1Q3H3u RY3TlsMM0rpsVBalz3f77pia8s7e3kFsjee2z7iadj/ILSfzYQTghSaO 0B6pDaWoUhhwbGWR1Fz0YdhaiYO21Tvxa5/DD3R3fsTWZQ773GENhNhE 1LM6L82770F+VGfbIhG/wBqiRM1FXiikPixvbmgRco2dff/3w/ns2WXI yFjlr7WwaHlrlyIhgI30CYDs3Xe3jI+sxwNG64XqnwVgBIaN7GVbUulb 9RFxkg==
+nic.cz. 1800 IN RRSIG DNSKEY 5 2 1800 20150818221347 20150805135503 24582 nic.cz. nrW0y70a7urskICTXafO/39Dd+sWU9gY/xQeeMLHuOTyJc5xPeKfPY61 6xUrfZveYy/dj3quDP+RB5hZCxK2gBDjRDBoDfJayaWmGoPJ4ima42KF wpyR8MMbcnha2Z+hP82Q/pVs7DsC3rJFg9Q5VHP5qzyQcRONYXWBjnM7 y54=
+ENTRY_END
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing.nic.cz. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NXDOMAIN
+SECTION QUESTION
+missing.nic.cz. IN MX
+SECTION AUTHORITY
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1438786503 10800 3600 1209600 7200
+nic.cz. 1800 IN RRSIG SOA 5 2 1800 20150819080542 20150805135503 24582 nic.cz. TDX7klpEuTI2vUQdmNzacxND0p828AD1HNxzTop0MJqKTehn8XgPoSK0 ZRWITLIMTtmC9UFLh/nb9I06HqUVdirxCKWvSzO840wjoVF7SjLWZysB 3VhPn84NA/9m8N8dmpTIt2IpN2N/T0lZVIIg/SSeru/dPNKH1uNtKekv 1eg=
+nic.cz. 7200 IN NSEC 6to4.nic.cz. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nic.cz. 7200 IN RRSIG NSEC 5 2 7200 20150818164706 20150805135503 24582 nic.cz. dqZiT0kHOtrap/aNq/M4u6KCGAS+f1yrAa6aDVBnqIopJ4DJJjnh67WF LedeHae5JLDNwuZV8SlkicIwW5K2ET4//2bJ6FCJcw89s40s3h/QnVxB +wV6hNhqfVnOjtHO4TWK96uNhf/B+A4N/voSpA21zYBMTV8mFvynj7oy ozk=
+*.mirrors.nic.cz. 7200 IN NSEC akuma.mnt.nic.cz. CNAME RRSIG NSEC
+*.mirrors.nic.cz. 7200 IN RRSIG NSEC 5 3 7200 20150819054509 20150805135503 24582 nic.cz. BDT/Rw1F7/QJd76/KWL0jdkdHkzWNxxZ2Hdgba6o1okc0mgqz2ag1P3s BkYtzWMwql4U7Au/KcLtq6P8X2/T9xytqmYfpn2O1dCaBzHubeTiz/aP wcPaYEC+jPR7JwmHpZlxs+KirS4yo7aVF1OPP7ZjtuqDeNLvmF4W7mHl r/A=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_dns64.rpl b/tests/deckard/sets/resolver/module_dns64.rpl
new file mode 100644
index 0000000..0e50dbb
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_dns64.rpl
@@ -0,0 +1,204 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ features: dns64_prefix = fe80::21b:aabb:0:0
+CONFIG_END
+
+SCENARIO_BEGIN Test dns64 features
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. IN NS d.ns.nic.cz.
+SECTION ADDITIONAL
+d.ns.nic.cz. IN A 193.29.206.1
+;d.ns.nic.cz. IN AAAA 2001:678:1::1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.29.206.1
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.cz. IN NS
+SECTION AUTHORITY
+example.cz. IN NS ns.example.cz.
+SECTION ADDITIONAL
+ns.example.cz. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+www.example.cz. IN A 1.2.3.5
+www.example.cz. IN A 1.2.3.6
+SECTION AUTHORITY
+example.cz. IN NS ns.example.cz.
+SECTION ADDITIONAL
+ns.example.cz. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.cz. IN AAAA
+SECTION AUTHORITY
+example.cz. 3600 IN SOA bla. bla. 1 2 3 4 5
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www6.example.cz. IN AAAA
+SECTION ANSWER
+www6.example.cz. 3600 IN AAAA 2001:db8::1
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+cname.example.cz. IN CNAME
+SECTION ANSWER
+cname.example.cz. IN CNAME www.example.cz.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+fail6.example.cz. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.cz. IN AAAA
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.cz. IN AAAA
+SECTION ANSWER
+www.example.cz. IN AAAA fe80::21b:aabb:102:305
+www.example.cz. IN AAAA fe80::21b:aabb:102:306
+ENTRY_END
+
+; Do not synthesize on +CD queries, sec. 5.5.3.
+STEP 12 QUERY
+ENTRY_BEGIN
+REPLY RD DO CD
+SECTION QUESTION
+www.example.cz. IN AAAA
+ENTRY_END
+
+STEP 13 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer authority
+REPLY QR RD RA DO CD NOERROR
+SECTION QUESTION
+www.example.cz. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.cz. 3600 IN SOA bla. bla. 1 2 3 4 5
+ENTRY_END
+
+; Do not synthesize if AAAA exists.
+STEP 14 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www6.example.cz. IN AAAA
+ENTRY_END
+
+STEP 15 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www6.example.cz. IN AAAA
+SECTION ANSWER
+www6.example.cz. 3600 IN AAAA 2001:db8::1
+ENTRY_END
+
+; Generate from simple NODATA behind a CNAME.
+STEP 16 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cname.example.cz. IN AAAA
+ENTRY_END
+
+STEP 17 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+cname.example.cz. IN AAAA
+SECTION ANSWER
+cname.example.cz. IN CNAME www.example.cz.
+www.example.cz. IN AAAA fe80::21b:aabb:102:305
+www.example.cz. IN AAAA fe80::21b:aabb:102:306
+ENTRY_END
+
+; Fail for AAAA won't cause query for A (answer not defined).
+STEP 18 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+fail6.example.cz. IN AAAA
+ENTRY_END
+
+STEP 19 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+fail6.example.cz. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_hint_static.rpl b/tests/deckard/sets/resolver/module_hint_static.rpl
new file mode 100644
index 0000000..7a1bb73
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_hint_static.rpl
@@ -0,0 +1,43 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ features: static_hint_name = www.nic.cz
+ features: static_hint_addr = 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Simple static hint test
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.nic.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.nic.cz. IN A
+SECTION ANSWER
+www.nic.cz. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+4.3.2.1.in-addr.arpa. IN PTR
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+4.3.2.1.in-addr.arpa. IN PTR
+SECTION ANSWER
+4.3.2.1.in-addr.arpa. IN PTR www.nic.cz
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_deny_all.rpl b/tests/deckard/sets/resolver/module_policy_deny_all.rpl
new file mode 100644
index 0000000..4c068e7
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_deny_all.rpl
@@ -0,0 +1,96 @@
+; config options
+ stub-addr: 1.2.3.4
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ feature-list: policy=policy:add(policy.all(policy.DENY))
+CONFIG_END
+
+SCENARIO_BEGIN DENY policy test, uses policy.all
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+dummy.example.cz. IN A 5.6.7.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+dummy.nic.cz. IN A 9.10.11.12
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD AD DO
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.example.cz. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nic.cz. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.nic.cz. IN A
+ENTRY_END
+
+STEP 80 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_deny_suff_comm.rpl b/tests/deckard/sets/resolver/module_policy_deny_suff_comm.rpl
new file mode 100644
index 0000000..320ac33
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_deny_suff_comm.rpl
@@ -0,0 +1,148 @@
+; config options
+ stub-addr: 1.2.3.4
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ feature-list: policy=policy:add(policy.suffix_common(policy.DENY, policy.todnames({'example.cz', 'nic.cz'}), todname('cz')))
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN DENY policy test, uses policy.common_suffix and policy.todnames
+
+RANGE_BEGIN 0 110
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+dummy.example.cz. IN A 9.10.11.12
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+nic.cz. IN A 13.14.15.16
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+dummy.nic.cz. IN A 17.18.19.20
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 21.22.23.24
+ENTRY_END
+RANGE_END
+
+; blocked by policy, must return NXDOMAIN
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; blocked by policy, must return NXDOMAIN
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.example.cz. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; blocked by policy, must return NXDOMAIN
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nic.cz. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; blocked by policy, must return NXDOMAIN
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.nic.cz. IN A
+ENTRY_END
+
+STEP 80 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; does not match the policy, so script must retun valid answer
+STEP 90 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+STEP 100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 21.22.23.24
+ENTRY_END
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_deny_suff_patt.rpl b/tests/deckard/sets/resolver/module_policy_deny_suff_patt.rpl
new file mode 100644
index 0000000..98b4cc6
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_deny_suff_patt.rpl
@@ -0,0 +1,148 @@
+; config options
+ stub-addr: 1.2.3.4
+ feature-list: policy=policy:add(policy.suffix(policy.DENY, {todname('nic.cz')}))
+ feature-list: policy=policy:add(policy.pattern(policy.DENY, '\8example[0-8]\2cz'))
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN DENY policy test; uses policy.suffix, policy.pattern, todname
+
+RANGE_BEGIN 0 110
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+nic.cz. IN A 5.6.7.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+dummy.nic.cz. IN A 9.10.11.12
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example0.cz. IN A
+SECTION ANSWER
+example0.cz. IN A 13.14.15.16
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example0.cz. IN A
+SECTION ANSWER
+dummy.example0.cz. IN A 17.18.19.20
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example9.cz. IN A
+SECTION ANSWER
+example9.cz. IN A 21.22.23.24
+ENTRY_END
+RANGE_END
+
+; denied by policy.suffix(policy.DENY, {todname('nic.cz')})
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nic.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; denied by policy.suffix(policy.DENY, {todname('nic.cz')})
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.nic.cz. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; denied by policy.pattern(policy.DENY, todname('example[0-8].cz')
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example0.cz. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example0.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; denied by policy.pattern(policy.DENY, todname('example[0-8].cz')
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.example0.cz. IN A
+ENTRY_END
+
+STEP 80 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.example0.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; does not match any policy; allowed
+STEP 90 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example9.cz. IN A
+ENTRY_END
+
+STEP 100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example9.cz. IN A
+SECTION ANSWER
+example9.cz. IN A 21.22.23.24
+ENTRY_END
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_drop.rpl b/tests/deckard/sets/resolver/module_policy_drop.rpl
new file mode 100644
index 0000000..308584a
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_drop.rpl
@@ -0,0 +1,24 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ feature-list: policy=policy:add(policy.suffix(policy.DROP, {todname('example.cz')}))
+CONFIG_END
+
+SCENARIO_BEGIN Simple policy test
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_forward.rpl b/tests/deckard/sets/resolver/module_policy_forward.rpl
new file mode 100644
index 0000000..ebe0f4a
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_forward.rpl
@@ -0,0 +1,38 @@
+; config options
+ stub-addr: 1.2.3.4
+ feature-list: policy=policy:add(policy.suffix(policy.FORWARD('1.2.3.4'), {todname('example.cz')}))
+CONFIG_END
+
+SCENARIO_BEGIN Simple policy test
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+www.example.cz. IN A 5.6.7.8
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+www.example.cz. IN A 5.6.7.8
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_pass_deny.rpl b/tests/deckard/sets/resolver/module_policy_pass_deny.rpl
new file mode 100644
index 0000000..fef630c
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_pass_deny.rpl
@@ -0,0 +1,67 @@
+; config options
+ stub-addr: 1.2.3.4
+ feature-list: policy=policy:add(policy.pattern(policy.PASS, todname('dummy.example.cz')))
+ feature-list: policy=policy:add(policy.suffix(policy.DENY, {todname('example.cz')}))
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN PASS, DENY policy test; uses policy.pattern and policy.suffix
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+fake.example.cz. IN A
+SECTION ANSWER
+fake.example.cz. IN A 5.6.7.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+dummy.example.cz. IN A 9.10.11.12
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+fake.example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+fake.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.example.cz. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+dummy.example.cz. IN A 9.10.11.12
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_rpz.rpl b/tests/deckard/sets/resolver/module_policy_rpz.rpl
new file mode 100644
index 0000000..e1588f1
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_rpz.rpl
@@ -0,0 +1,153 @@
+; config options
+ stub-addr: 1.2.3.4
+ feature-list: policy=policy:add(policy.rpz(policy.DENY, '{{INSTALL_DIR}}/sets/resolver/zone.rpz'))
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN policy.rpz test
+
+RANGE_BEGIN 0 110
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+example.cz. IN A 5.6.7.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+dummy.example.cz. IN A 9.10.11.12
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+nic.cz. IN A 13.14.15.16
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+dummy.nic.cz. IN A 17.18.19.20
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 21.22.23.24
+ENTRY_END
+RANGE_END
+
+; blocked by example.cz CNAME .
+; NXDOMAIN expected
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; blocked by *.example.cz CNAME *.
+; NXDOMAIN expected
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.example.cz. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AA NXDOMAIN
+SECTION QUESTION
+dummy.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; blocked nic.cz CNAME rpz-drop.
+; SERVFAIL expected
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nic.cz. IN A
+ENTRY_END
+
+STEP 55 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; matches *.nic.cz CNAME rpz-tcp-only.
+; TC flag expected
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+dummy.nic.cz. IN A
+ENTRY_END
+
+STEP 65 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR TC RD RA NOERROR
+SECTION QUESTION
+dummy.nic.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; matches example.com CNAME rpz-passthru.
+; rpz not affected
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+
+STEP 80 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION ANSWER
+example.com. IN A 21.22.23.24
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_policy_tc.rpl b/tests/deckard/sets/resolver/module_policy_tc.rpl
new file mode 100644
index 0000000..620f531
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_policy_tc.rpl
@@ -0,0 +1,24 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ feature-list: policy=policy:add(policy.suffix(policy.TC, {todname('example.cz')}))
+CONFIG_END
+
+SCENARIO_BEGIN Simple policy test
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR TC RD RA
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_renumber.rpl b/tests/deckard/sets/resolver/module_renumber.rpl
new file mode 100644
index 0000000..b435585
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_renumber.rpl
@@ -0,0 +1,86 @@
+; config options
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ features: renumber_src = 1.2.3.0/24; renumber_dst = 4.5.6.0
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Simple renumber module test
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. IN NS d.ns.nic.cz.
+SECTION ADDITIONAL
+d.ns.nic.cz. IN A 193.29.206.1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.29.206.1
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.cz. IN NS
+SECTION AUTHORITY
+example.cz. IN NS ns.example.cz.
+SECTION ADDITIONAL
+ns.example.cz. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+www.example.cz. IN A 1.2.3.5
+SECTION AUTHORITY
+example.cz. IN NS ns.example.cz.
+SECTION ADDITIONAL
+ns.example.cz. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.cz. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.cz. IN A
+SECTION ANSWER
+www.example.cz. IN A 4.5.6.5
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/module_workarounds_disable_0x20.rpl b/tests/deckard/sets/resolver/module_workarounds_disable_0x20.rpl
new file mode 100644
index 0000000..2906ee8
--- /dev/null
+++ b/tests/deckard/sets/resolver/module_workarounds_disable_0x20.rpl
@@ -0,0 +1,81 @@
+; config options
+ features: workarounds = true
+ stub-addr: 1.1.1.1
+CONFIG_END
+
+SCENARIO_BEGIN Test module workarounds disabling 0x20 for certain domains
+RANGE_BEGIN 0 100
+ ADDRESS 1.1.1.1
+ENTRY_BEGIN
+MATCH opcode qtype qcase ; case sensitive comparison
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A ; all lowercase
+SECTION ANSWER
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A 2.2.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 1.1.1.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net. IN A 1.1.1.1
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A ; all lowercase: tests that 0x20 won't be used
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A
+SECTION ANSWER
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A 2.2.2.2
+ENTRY_END
+
+; expire cached results
+STEP 22 TIME_PASSES ELAPSE 4000
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.COM. IN A ; upper case in the TLD: tests making the name lowercase before sending the query
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A
+SECTION ANSWER
+b-0.19-23003008.1481.1518.19cf.3ea1.410.0.ekzijnekvvvg7gb38qcwur561b.avqs.mcafee.com. IN A 2.2.2.2
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec3_aggr_cache.rpl b/tests/deckard/sets/resolver/nsec3_aggr_cache.rpl
new file mode 100644
index 0000000..180ec87
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec3_aggr_cache.rpl
@@ -0,0 +1,5280 @@
+ trust-anchor: ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ trust-anchor: ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"
+ val-override-date: 20180727104904
+ stub-addr: 192.36.148.17
+CONFIG_END
+
+SCENARIO_BEGIN qlist
+
+; Scope ".
+
+; Server names:
+; f.root-servers.net.
+; a.root-servers.net.
+; j.root-servers.net.
+; e.root-servers.net.
+; i.root-servers.net.
+; d.root-servers.net.
+; m.root-servers.net.
+; h.root-servers.net.
+; c.root-servers.net.
+; l.root-servers.net.
+; g.root-servers.net.
+; b.root-servers.net.
+; k.root-servers.net.
+RANGE_BEGIN 0 1000
+ ADDRESS 192.36.148.17
+ ADDRESS 2001:7fe::53
+ ADDRESS 198.97.190.53
+ ADDRESS 2001:500:1::53
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 2001:503:c27::2:30
+ ADDRESS 2001:500:a8::e
+ ADDRESS 2001:7fd::1
+ ADDRESS 192.112.36.4
+ ADDRESS 2001:500:12::d0d
+ ADDRESS 199.7.91.13
+ ADDRESS 2001:500:2::c
+ ADDRESS 198.41.0.4
+ ADDRESS 2001:500:2d::d
+ ADDRESS 202.12.27.33
+ ADDRESS 2001:500:9f::42
+ ADDRESS 2001:dc3::35
+ ADDRESS 192.5.5.241
+ ADDRESS 192.33.4.12
+ ADDRESS 2001:500:2f::f
+ ADDRESS 199.7.83.42
+ ADDRESS 192.58.128.30
+ ADDRESS 192.203.230.10
+ ADDRESS 2001:500:200::b
+ ADDRESS 199.9.14.201
+ ADDRESS 193.0.14.129
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20180809050000 20180727040000 41656 . iPYXlPdWqSGLIBjkBHYPCkA7LpjtEq2l 3IxdgesYUMxKFrYsdxgySnyBHQ9YzAQc bl3fCtLvlx6msHw/cCqMRHhCCjDnqTa/ NqBRtr1hr8ZbPrb3pZf+1hjX+9eohhHQ OiyAiP1hVaEIBIiSt7W8aPYvjZRogQAy YPApw3dwsfTFWzTnd+EDZsuZeMz0k74x BEJmC/tzTjnzvNK8fU95Mv+pKLm09Hda eXP2i+zrAwguTZBUt30dnsrYA7dxkQcP s+SdFhfPlGYS2EWOoJsik3DGRHQpTHI5 N9sjytXS7IqWetnaNJyFL0KSpG1YdEyB JvYqCrUI6YLDopcgUSRjrA==
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAfaifSqh+9ItxYRCwuiY0FY2NkaE wd/zmyVvakixDgTOkgG/PUzlEauAiKzl xGwezjqbKFPSwrY3qHmbbsSTY6G8hZtn a8k26eCwy59Chh573cu8qtBkmUIXMYG3 fSdlUReP+uhBWBfKI2aGwhRmQYR0zSmg 7PGOde34c/rOItK1ebJhjTAJ6TmnON7q Mfk/lKvH4qOvYtzstLhr7Pn9ZOVLx/WU KQpU/nEyFyTduRbz1nZqkp6yMuHwWVsA BK8lUYXSaUrDAsuMSldhafmR/A15BxNh v9M7mzJj7UH2RVME9JbYinBEzWwW9Gpn Y+ZmBWgZiRVTaDuemCTJ5ZJWLRs=
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29 euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v 58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8 g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37 NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/E fucp2gaDX6RS6CXpoY68LsvPVjR0ZSwz z1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgu l0sGIcGOYl7OyQdXfZ57relSQageu+ip AdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1 dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 172800 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexT BAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq 7HrxRixHlFlExOLAJr5emLvN7SWXgnLh 4+B5xQlNVz8Og8kvArMtNROxVQuCaSnI DdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLr jyBxWezF0jLHwVN8efS3rCj/EWgvIWgb 9tarpVUDK/b58Da+sqqls3eNbuv7pr+e oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTId sIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6 +cn8HFRm+2hM8AnXGXws9555KrUB5qih ylGa8subX2Nn6UwNR1AkUTV74bU=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20180811000000 20180721000000 19036 . U2thj3DQzTGRF8m2ZytqANs9YF9PYb1B QC5bDHi+d7apJve5u3Ik1cCeYg9AlW2v 2vstMSUtTR0eI2mzBeZ8aBHLwPylyDhS jbe6lwxnaoZhncO4oM9bJTUha1ovCXPO oZm5dKhfI6FradAaitRfMaC7s/+XZ/Dh nlLQNe08F0qepkG52RsUJZEyiQkkOK5a /hNkV5gyKdMecjtJ7eiR1w68vWwP6iGp ohuLDlapbEniJXHhEysUtRJbE3EFYgwG EGeKwEQC3tDCb8ABYnbrkMg/OqhGP1cX aYfZwhEIUOvsplTdXU1tsVbPjGtbVBjy 4aKLY+pjsvWuT2dzMac18A==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN NULL
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN DNSKEY
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN DS
+SECTION ANSWER
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN A
+SECTION ANSWER
+f.root-servers.net. 3600000 IN A 192.5.5.241
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN AAAA
+SECTION ANSWER
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN A
+SECTION ANSWER
+a.root-servers.net. 3600000 IN A 198.41.0.4
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN AAAA
+SECTION ANSWER
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN A
+SECTION ANSWER
+j.root-servers.net. 3600000 IN A 192.58.128.30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN AAAA
+SECTION ANSWER
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN A
+SECTION ANSWER
+e.root-servers.net. 3600000 IN A 192.203.230.10
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN AAAA
+SECTION ANSWER
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN A
+SECTION ANSWER
+i.root-servers.net. 3600000 IN A 192.36.148.17
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN AAAA
+SECTION ANSWER
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN A
+SECTION ANSWER
+d.root-servers.net. 3600000 IN A 199.7.91.13
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN AAAA
+SECTION ANSWER
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN A
+SECTION ANSWER
+m.root-servers.net. 3600000 IN A 202.12.27.33
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN AAAA
+SECTION ANSWER
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN A
+SECTION ANSWER
+h.root-servers.net. 3600000 IN A 198.97.190.53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN AAAA
+SECTION ANSWER
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN A
+SECTION ANSWER
+c.root-servers.net. 3600000 IN A 192.33.4.12
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN AAAA
+SECTION ANSWER
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN A
+SECTION ANSWER
+l.root-servers.net. 3600000 IN A 199.7.83.42
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN AAAA
+SECTION ANSWER
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN A
+SECTION ANSWER
+g.root-servers.net. 3600000 IN A 192.112.36.4
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN AAAA
+SECTION ANSWER
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN A
+SECTION ANSWER
+b.root-servers.net. 3600000 IN A 199.9.14.201
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN AAAA
+SECTION ANSWER
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN DNSKEY
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN DS
+SECTION ANSWER
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "com.
+
+; Server names:
+; a.gtld-servers.net.
+; j.gtld-servers.net.
+; e.gtld-servers.net.
+; i.gtld-servers.net.
+; d.gtld-servers.net.
+; m.gtld-servers.net.
+; h.gtld-servers.net.
+; c.gtld-servers.net.
+; l.gtld-servers.net.
+; g.gtld-servers.net.
+; b.gtld-servers.net.
+; k.gtld-servers.net.
+; f.gtld-servers.net.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:503:d2d::30
+ ADDRESS 192.31.80.30
+ ADDRESS 2001:502:7094::30
+ ADDRESS 2001:501:b1f9::30
+ ADDRESS 192.35.51.30
+ ADDRESS 2001:503:39c1::30
+ ADDRESS 2001:502:1ca1::30
+ ADDRESS 2001:503:a83e::2:30
+ ADDRESS 192.55.83.30
+ ADDRESS 192.26.92.30
+ ADDRESS 2001:503:eea3::30
+ ADDRESS 192.12.94.30
+ ADDRESS 192.42.93.30
+ ADDRESS 2001:502:8cc::30
+ ADDRESS 2001:503:d414::30
+ ADDRESS 2001:503:83eb::30
+ ADDRESS 192.52.178.30
+ ADDRESS 192.54.112.30
+ ADDRESS 2001:500:856e::30
+ ADDRESS 192.5.6.30
+ ADDRESS 192.41.162.30
+ ADDRESS 192.43.172.30
+ ADDRESS 192.48.79.30
+ ADDRESS 192.33.14.30
+ ADDRESS 2001:500:d937::30
+ ADDRESS 2001:503:231d::2:30
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+net. 900 IN RRSIG SOA 8 1 900 20180803084842 20180727073842 7934 net. GaMDNiWJZrDpU6uLTjDm3xG9RH1Ltojc knesMgzdxlcYAtennPH8HUtc3lsCIKUI 0uU22sXG/dSakls2ihWIrPXm13mGjYio UdCPTCEHyBApbe5Xh6m+wMWlbI8yxSYy b6bFCsH/2fgLlGHZ7DwQy+Cji5d/1H8x iTDVF1WfLvo=
+net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532681322 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DS
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+net. 900 IN RRSIG SOA 8 1 900 20180803084842 20180727073842 7934 net. GaMDNiWJZrDpU6uLTjDm3xG9RH1Ltojc knesMgzdxlcYAtennPH8HUtc3lsCIKUI 0uU22sXG/dSakls2ihWIrPXm13mGjYio UdCPTCEHyBApbe5Xh6m+wMWlbI8yxSYy b6bFCsH/2fgLlGHZ7DwQy+Cji5d/1H8x iTDVF1WfLvo=
+net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532681322 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN A
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN DNSKEY
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN DS
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+com. 900 IN RRSIG SOA 8 1 900 20180803084843 20180727073843 46475 com. wzmp/pygt6idgcjTbWpXcNftz17R3m2G 3IPBt3h54AEI1BEwbI7oPRO+NZjmHN/W 9hsD0KUoDiHMOLndA8gJIV2ZG7ACTHvD HtRgvKIxqE1KvxDU7mmxULrWPNjNZgcg PlBUehxbf774Xcn4wE/aFNMZEjn5B2re A6MYOJoNby0=
+com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532681323 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN DNSKEY
+SECTION ANSWER
+net. 86400 IN DNSKEY 256 3 8 AQO6ELLy73I+l1XTVPuW3zfQkw5nublx oY4QgdTVOfUjdv6ooKTMRMgfKb+alpX5 8L5pfhndd+o7hisIwgiH2b6aqjdljzTf dV4XeZ/2CROv1ki/BRWwD61P/w688bpu Bl/u3vsTjvjq6FdVZVf3/afMXtSO1RR7 uaQ7qn8oupY/6w==
+net. 86400 IN DNSKEY 257 3 8 AQOYBnzqWXIEj6mlgXg4LWC0HP2n8eK8 XqgHlmJ/69iuIHsa1TrHDG6TcOra/pye GKwH0nKZhTmXSuUFGh9BCNiwVDuyyb6O BGy2Nte9Kr8NwWg4q+zhSoOf4D+gC9dE zg0yFdwT0DKEvmNPt0K4jbQDS4Yimb+u PKuF6yieWWrPYYCrv8C9KC8JMze2uT6N uWBfsl2fDUoV4l65qMww06D7n+p7Rbdw WkAZ0fA63mXVXBZF6kpDtsYD7SUB9jhh fLQE/r85bvg3FaSs5Wi2BaqN06SzGWI1 DHu7axthIOeHwg00zxlhTpoYCH0ldoQz +S65zWYi/fRJiyLSBb6JZOvn
+net. 86400 IN RRSIG DNSKEY 8 1 86400 20180808153857 20180724153357 35886 net. lmab/pWDgNRz6BN1BFZmkwiZz0qay0rz +46JXwgzI/g8eadEAev1OaIfsply91iM Sn+87NMPDN1Spjr3LKSXQB7+nc8n3yrf h1gxPRsjwuWxvPc3dJwlB4P8NvXTk4B5 vzjSpcfzvb+6YuAoC171yFcIcER1RN5d j3y1NRx1EAnuanMfoHIm+2dcu14a2hKn fB0zc/hm4L/rO/Qm8c3z97d1OffQs0L0 MGCU/kBDm/UyjymSFobMlIcn0bIha7A1 QN753OY+LEOWq0flQgUrKeuXvAe2o46g GebT+8euJahn/HmgmHD/bCNn+GC/KRJJ L1wFQH3x8uqlq9loQMPjwQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN DNSKEY
+SECTION ANSWER
+com. 86400 IN DNSKEY 256 3 8 AQPeabgR6Fgrk5FSLilDYUedwsHA0HH2 2e8+Zp/uvp4aj1dVDAy5C9bkRA+xot3s G1KaT5hvgoE7eNV93F7pBW9rvVE3A/BN vJbLXxKhkAJV5KMFC10NRcdb+xF+sM4X TMPESPrYwTLUEpSFntMIVLAtUzLaBo6Y pTVR20osgGgc3Q==
+com. 86400 IN DNSKEY 257 3 8 AQPDzldNmMvZFX4NcNJ0uEnKDg7tmv/F 3MyQR0lpBmVcNcsIszxNFxsBfKNW9JYC Yqpik8366LE7VbIcNRzfp2h9OO8HRl+H +E08zauK8k7evWEmu/6od+2boggPoiEf GNyvNPaSI7FOIroDsnw/taggzHRX1Z7S OiOiPWPNIwSUyWOZ79VmcQ1GLkC6NlYv G3HwYmynQv6oFwGv/KELSw7ZSdrbTQ0H XvZbqMUI7BaMskmvgm1G7oKZ1YiF7O9i oVNc0+7ASbqmZN7Z98EGU/Qh2K/BgUe8 Hs0XVcdPKrtyYnoQHd2ynKPcMMlTEih2 /2HDHjRPJ2aywIpKNnv4oPo/
+com. 86400 IN RRSIG DNSKEY 8 1 86400 20180810182533 20180726182033 30909 com. pytllCSmnIFN69hPKx3IcJSV3ZD+4qoF CXIuN+LXSJpkWmpD4gOWKgAytIBMImbh iUrfLECS2c3TJkjWjthKjL+GpYIHN1Z/ UY2zdSqKr0JqBQjHs456zBsJIrRriQKh e7MEFWV+JLSYAHQi/8+ot3l9GKO9nSK6 zqP+FrMtkPtZbJeNo1muSQ4lrdvYw4/t k0FADV0DK8p8/D/OQEPg2+Mpwx9GjCVN VOlKS5vuGHGAKI0gXlhJoe28i5McJVc5 O/evqbRX37xmfX01F8W4f6lZBt3qVIVq gW9iJAjY5vd4l4m53lTzYKTLeJTFH358 TsJO93q0NpaWL78xLxkVrg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN NS
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 172800 IN RRSIG NS 8 1 172800 20180802053055 20180726042055 7934 net. KR3mBpGrNgRPgB/LuPhUC4sjhy9F+GPU BXemSi46ZJlIWc7sK40AQ2rccrU5MDSa puWa2pVvx74pSU2w3gqeW9RH9E3wNh9t toAxJYJBNvTlXv3D1qG0LIXEsold+cvQ 0VqnFhVePojFFtFqE19H5OHaa87LVUOB Ib0gTx7i73Y=
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 172800 IN RRSIG NS 8 1 172800 20180731044815 20180724033815 46475 com. JgH5uVQ8OQlpGeX/UJQRQHvQJjXOlQoZ o87eG2e/PP2y1R5Td93n/BckALIzqxT9 UyZsfIKDbRbK5junHSwV8FL5HC+3Hj0K QX8k4+yrpeYB1EM/Upkb5Db1E6F4NCcs iUyDsLNUS3trL+X7/ohrTM3ScPKdMux0 a0kAzuZMWJk=
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "nstld.com.
+
+; Server names:
+; av1.nstld.com.
+; av2.nstld.com.
+; av3.nstld.com.
+; av4.nstld.com.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:500:126::30
+ ADDRESS 2001:500:124::30
+ ADDRESS 192.82.134.30
+ ADDRESS 192.82.133.30
+ ADDRESS 2001:500:125::30
+ ADDRESS 2001:500:127::30
+ ADDRESS 192.42.177.30
+ ADDRESS 192.42.178.30
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+a.gtld-servers.net. 86400 IN AAAA 2001:503:a83e::2:30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN A
+SECTION ANSWER
+j.gtld-servers.net. 86400 IN A 192.48.79.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN AAAA
+SECTION ANSWER
+j.gtld-servers.net. 86400 IN AAAA 2001:502:7094::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. 86400 IN A 192.12.94.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+e.gtld-servers.net. 86400 IN AAAA 2001:502:1ca1::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN A
+SECTION ANSWER
+i.gtld-servers.net. 86400 IN A 192.43.172.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN AAAA
+SECTION ANSWER
+i.gtld-servers.net. 86400 IN AAAA 2001:503:39c1::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN A
+SECTION ANSWER
+d.gtld-servers.net. 86400 IN A 192.31.80.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN AAAA
+SECTION ANSWER
+d.gtld-servers.net. 86400 IN AAAA 2001:500:856e::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN A
+SECTION ANSWER
+m.gtld-servers.net. 86400 IN A 192.55.83.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN AAAA
+SECTION ANSWER
+m.gtld-servers.net. 86400 IN AAAA 2001:501:b1f9::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN A
+SECTION ANSWER
+h.gtld-servers.net. 86400 IN A 192.54.112.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN AAAA
+SECTION ANSWER
+h.gtld-servers.net. 86400 IN AAAA 2001:502:8cc::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN A
+SECTION ANSWER
+c.gtld-servers.net. 86400 IN A 192.26.92.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN AAAA
+SECTION ANSWER
+c.gtld-servers.net. 86400 IN AAAA 2001:503:83eb::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN A
+SECTION ANSWER
+l.gtld-servers.net. 86400 IN A 192.41.162.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN AAAA
+SECTION ANSWER
+l.gtld-servers.net. 86400 IN AAAA 2001:500:d937::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN A
+SECTION ANSWER
+g.gtld-servers.net. 86400 IN A 192.42.93.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN AAAA
+SECTION ANSWER
+g.gtld-servers.net. 86400 IN AAAA 2001:503:eea3::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN A
+SECTION ANSWER
+b.gtld-servers.net. 86400 IN A 192.33.14.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN AAAA
+SECTION ANSWER
+b.gtld-servers.net. 86400 IN AAAA 2001:503:231d::2:30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN A
+SECTION ANSWER
+k.gtld-servers.net. 86400 IN A 192.52.178.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN AAAA
+SECTION ANSWER
+k.gtld-servers.net. 86400 IN AAAA 2001:503:d2d::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN A
+SECTION ANSWER
+f.gtld-servers.net. 86400 IN A 192.35.51.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN AAAA
+SECTION ANSWER
+f.gtld-servers.net. 86400 IN AAAA 2001:503:d414::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN A
+SECTION ANSWER
+av1.nstld.com. 300 IN A 192.42.177.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN AAAA
+SECTION ANSWER
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN A
+SECTION ANSWER
+av2.nstld.com. 300 IN A 192.42.178.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN AAAA
+SECTION ANSWER
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN A
+SECTION ANSWER
+av3.nstld.com. 300 IN A 192.82.133.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN AAAA
+SECTION ANSWER
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN A
+SECTION ANSWER
+av4.nstld.com. 300 IN A 192.82.134.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN AAAA
+SECTION ANSWER
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN NS
+SECTION ANSWER
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "cz.
+
+; Server names:
+; b.ns.nic.cz.
+; d.ns.nic.cz.
+; a.ns.nic.cz.
+; c.ns.nic.cz.
+RANGE_BEGIN 0 1000
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:1::1
+ ADDRESS 2001:678:11::1
+ ADDRESS 194.0.12.1
+ ADDRESS 194.0.13.1
+ ADDRESS 2001:678:f::1
+ ADDRESS 2001:678:10::1
+ ADDRESS 194.0.14.1
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN NULL
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN DNSKEY
+SECTION ANSWER
+knot-resolver.cz. 1800 IN DNSKEY 256 3 13 a85wAU1EB4C7Xl82/BuF/gkkNwrQPdAF w1f9uqkz3qjLXK3S+21F4SJOSWHgIW6I 8GHuBZeCMvimvj/KscrVhw==
+knot-resolver.cz. 1800 IN DNSKEY 257 3 13 KDAJfPGWgvNAEHUMzmmSa+c3gHfoGIsX nhIO1iAYGTAyVBo+CLTyIk3wxDtt4Yn3 eCrCiYsEAHBJgQvA3pwJ8w==
+knot-resolver.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20180808043000 20180725030000 54959 knot-resolver.cz. Yc3LFy9LfuakNaC9AJDIikUtjDocgdUV WiQ2b/A3YQ7+uExdT5oJHTY0JDfhdHXt 4bSy8G+yYlIYYKXUPIToBg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN DS
+SECTION ANSWER
+knot-resolver.cz. 3600 IN DS 54959 13 2 a4e5db1e2e4607243c4fe4ee79a77d3538791b7ecab85a52290878de1224d7d4
+knot-resolver.cz. 3600 IN RRSIG DS 13 2 3600 20180803113206 20180720153540 62295 cz. ttYnNfVXQw5sKc2YobPQ1rknQjPi2a5f smkJssgzQOpMT16RKyZML9SpmNM17Xng bPpPseWR94HuFgIME4A+YA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN A
+SECTION ANSWER
+knot-resolver.cz. 1800 IN A 217.31.192.18
+knot-resolver.cz. 1800 IN RRSIG A 13 2 1800 20180808033000 20180725020000 34376 knot-resolver.cz. uO0N7ttfRoQsS9McxAWJTIZqyJOl3WAo Pkc9QJrlrS/UG0KwJzBFBCWMxX+k5o7n C2Fi5GaDwmrcG1l+f+TTtA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN AAAA
+SECTION ANSWER
+knot-resolver.cz. 1800 IN AAAA 2001:1488:ac15:ff30::18
+knot-resolver.cz. 1800 IN RRSIG AAAA 13 2 1800 20180808033000 20180725020000 34376 knot-resolver.cz. Y/wxR2e0nfYSfpYGJV6CMekYSuIIt2Jl bFl/oOhE9eiSTlXSEfT8GWxy5Q8dhhkR en+NEXApI31ZX4I5EGEXtg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+nic.cz. 1800 IN A 217.31.205.50
+nic.cz. 1800 IN RRSIG A 13 2 1800 20180809122156 20180727064002 33494 nic.cz. p0uxXNMUIA1Zf6x/wqAdlNTSiLKrYs8P nNYlBe0SPQ8kTSGp49BlEaiy+B9ewcYp YbPTgjIpmvoMFeIOShUqgw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz. 1800 IN DNSKEY 256 3 13 a10sJr/8DQL8M1nLPzWfNoASGTsm4cKE P577ZX3c3lruiWZiUL78fUp0B2YJh8U9 DyiZsq18i6CM9eYTDVemzA==
+nic.cz. 1800 IN DNSKEY 257 3 13 LM4zvjUgZi2XZKsYooDE0HFYGfWp242f KB+O8sLsuox8S6MJTowY8lBDjZD7JKbm aNot3+1H8zU9TrDzWmmHwQ==
+nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20180809084714 20180727064002 61281 nic.cz. zotLLX9vPojjz21OSVfMGNspvWIVzzcW ZGJTTYOPlIHmrxAfE3GxHqV7QK8QO1W5 8rGsf9eebQw3+aJ+QGaNSA==
+nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20180810022459 20180727064002 33494 nic.cz. Ol85KlI1HVLYmVRmD2q0QBCqLZM5bUDr sECC2XN0gmtkbEPfI1HmhylvM9sur3kE 4kCxCKOAOCozExhDZtgV2w==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION ANSWER
+nic.cz. 3600 IN DS 61281 13 2 4104d40c8fe2030bf7a09a199fcf37b36f7ec8ddd16f5a84f2e61c248d3afd0f
+nic.cz. 3600 IN RRSIG DS 13 2 3600 20180805030735 20180722073550 62295 cz. iF+/iu01Jx4ls0md5OHm25GHCuaLkEmd U4N8pzQRw0WYTmP71ZuMEqd4e5KPeGS2 hLqh134rBssNSGagGazLNw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+knot-s-01.nic.cz. IN A
+SECTION AUTHORITY
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 03keq03alogetpm9cgasqk7bremd66d1 A RRSIG
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810043745 20180727064002 33494 nic.cz. qfSOy12hZJf/gtPn3k+34fhT3RTZgsq2 27nLVIx4DBHB2vzVTnXiZyqyU7D7LrO8 jXu43W5aNvtZzOK8RWPwkA==
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 4i3o1eq9upce2qv1rkubgt7v5qgb90s4 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810054917 20180727064002 33494 nic.cz. SVSQya2mV73pXk5HeXrJXgKSGRiVo/LP PcCjihQqRzfQKK5XWDRgas7+Ve7khf/H wMBk2jSTLOKbvHJLW14K+Q==
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 lb5verduef1iorjs8glp93io39d6aib4 A AAAA RRSIG
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810063920 20180727064002 33494 nic.cz. p8egKoFkZcK1M81lCEaestRHkuFWxp4k lmNZv05NdyCSZd4juLFGGgfWcl49eE/j UyIOQwouuaVrn5OjuvBilA==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+knot-s-01.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 03keq03alogetpm9cgasqk7bremd66d1 A RRSIG
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810043745 20180727064002 33494 nic.cz. qfSOy12hZJf/gtPn3k+34fhT3RTZgsq2 27nLVIx4DBHB2vzVTnXiZyqyU7D7LrO8 jXu43W5aNvtZzOK8RWPwkA==
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 4i3o1eq9upce2qv1rkubgt7v5qgb90s4 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810054917 20180727064002 33494 nic.cz. SVSQya2mV73pXk5HeXrJXgKSGRiVo/LP PcCjihQqRzfQKK5XWDRgas7+Ve7khf/H wMBk2jSTLOKbvHJLW14K+Q==
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 lb5verduef1iorjs8glp93io39d6aib4 A AAAA RRSIG
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810063920 20180727064002 33494 nic.cz. p8egKoFkZcK1M81lCEaestRHkuFWxp4k lmNZv05NdyCSZd4juLFGGgfWcl49eE/j UyIOQwouuaVrn5OjuvBilA==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+knot-s-01.nic.cz. IN NS
+SECTION AUTHORITY
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 03keq03alogetpm9cgasqk7bremd66d1 A RRSIG
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810043745 20180727064002 33494 nic.cz. qfSOy12hZJf/gtPn3k+34fhT3RTZgsq2 27nLVIx4DBHB2vzVTnXiZyqyU7D7LrO8 jXu43W5aNvtZzOK8RWPwkA==
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 4i3o1eq9upce2qv1rkubgt7v5qgb90s4 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810054917 20180727064002 33494 nic.cz. SVSQya2mV73pXk5HeXrJXgKSGRiVo/LP PcCjihQqRzfQKK5XWDRgas7+Ve7khf/H wMBk2jSTLOKbvHJLW14K+Q==
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 lb5verduef1iorjs8glp93io39d6aib4 A AAAA RRSIG
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810063920 20180727064002 33494 nic.cz. p8egKoFkZcK1M81lCEaestRHkuFWxp4k lmNZv05NdyCSZd4juLFGGgfWcl49eE/j UyIOQwouuaVrn5OjuvBilA==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+knot-s-01.nic.cz. IN DS
+SECTION AUTHORITY
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 03keq03alogetpm9cgasqk7bremd66d1 A RRSIG
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810043745 20180727064002 33494 nic.cz. qfSOy12hZJf/gtPn3k+34fhT3RTZgsq2 27nLVIx4DBHB2vzVTnXiZyqyU7D7LrO8 jXu43W5aNvtZzOK8RWPwkA==
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 4i3o1eq9upce2qv1rkubgt7v5qgb90s4 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810054917 20180727064002 33494 nic.cz. SVSQya2mV73pXk5HeXrJXgKSGRiVo/LP PcCjihQqRzfQKK5XWDRgas7+Ve7khf/H wMBk2jSTLOKbvHJLW14K+Q==
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 lb5verduef1iorjs8glp93io39d6aib4 A AAAA RRSIG
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810063920 20180727064002 33494 nic.cz. p8egKoFkZcK1M81lCEaestRHkuFWxp4k lmNZv05NdyCSZd4juLFGGgfWcl49eE/j UyIOQwouuaVrn5OjuvBilA==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+knot-s-01.nic.cz. IN AAAA
+SECTION AUTHORITY
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 03keq03alogetpm9cgasqk7bremd66d1 A RRSIG
+01bgrmosedn3jh21oq2cq3obvl9q56k8.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810043745 20180727064002 33494 nic.cz. qfSOy12hZJf/gtPn3k+34fhT3RTZgsq2 27nLVIx4DBHB2vzVTnXiZyqyU7D7LrO8 jXu43W5aNvtZzOK8RWPwkA==
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 4i3o1eq9upce2qv1rkubgt7v5qgb90s4 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM
+4g0hefga47i70br94ljss5us62b0ln71.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810054917 20180727064002 33494 nic.cz. SVSQya2mV73pXk5HeXrJXgKSGRiVo/LP PcCjihQqRzfQKK5XWDRgas7+Ve7khf/H wMBk2jSTLOKbvHJLW14K+Q==
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 lb5verduef1iorjs8glp93io39d6aib4 A AAAA RRSIG
+l80r74a5vjicpcbvnlpa2bk6bbvs5jjn.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810063920 20180727064002 33494 nic.cz. p8egKoFkZcK1M81lCEaestRHkuFWxp4k lmNZv05NdyCSZd4juLFGGgfWcl49eE/j UyIOQwouuaVrn5OjuvBilA==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN A
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f rgofdsarih9kv8kcht41osd09tkl8o7v NS DS RRSIG
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x /H4aDF24oVFrRn2XTNNghu2OzmcVJV0E QlNIHd8aXfdQwLEz4FUAhw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN DNSKEY
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f rgofdsarih9kv8kcht41osd09tkl8o7v NS DS RRSIG
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x /H4aDF24oVFrRn2XTNNghu2OzmcVJV0E QlNIHd8aXfdQwLEz4FUAhw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN NS
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f rgofdsarih9kv8kcht41osd09tkl8o7v NS DS RRSIG
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x /H4aDF24oVFrRn2XTNNghu2OzmcVJV0E QlNIHd8aXfdQwLEz4FUAhw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN DS
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f rgofdsarih9kv8kcht41osd09tkl8o7v NS DS RRSIG
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x /H4aDF24oVFrRn2XTNNghu2OzmcVJV0E QlNIHd8aXfdQwLEz4FUAhw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN AAAA
+SECTION AUTHORITY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f ei8u933svpm4qdfn713b66buji430uc7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux 2/X8SwY2PmrcK/ff6wmFejIrGUHvrG1U NS9icqQqTV3swNymGz4Dbw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN NSEC3 1 0 10 f49e445b0b4ad67f rgofdsarih9kv8kcht41osd09tkl8o7v NS DS RRSIG
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x /H4aDF24oVFrRn2XTNNghu2OzmcVJV0E QlNIHd8aXfdQwLEz4FUAhw==
+knot-resolver.cz. 1800 IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mh yueV6+fJI1V5N3dEoczePO5yBZiffk91 Xi2d4aYHRf2DLyfEX0HDVA==
+knot-resolver.cz. 1800 IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+labs.nic.cz. IN A
+SECTION ANSWER
+labs.nic.cz. 1800 IN A 217.31.192.130
+labs.nic.cz. 1800 IN RRSIG A 13 3 1800 20180808225840 20180725212840 5070 labs.nic.cz. GYUF3qBsSa9Zi8ijUnwijskJxjtVlUHC fj5qMOCg1tfsg7jf2nV8Au4llaWEAsxp AR0Hh/R808odDxyONg2wwA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+labs.nic.cz. IN DNSKEY
+SECTION ANSWER
+labs.nic.cz. 1800 IN DNSKEY 256 3 13 EGR6/v4U4maTcZF6Gprv1oXZPmph09UL 5AX1gwt5AaIPh6X8Eti7ccgMH5vsHdvQ isdW1HmgGLPwEQAyO/W/MA==
+labs.nic.cz. 1800 IN DNSKEY 257 3 13 3Lk0VNzQzj9EDPJQwSPCVixCc+oyz0nr Uzik6UqtvCA0OLDd4v4sQjXmwxWniPrm aSGlEHCOXkrnQ455xgT2Pg==
+labs.nic.cz. 1800 IN RRSIG DNSKEY 13 3 1800 20180808235840 20180725222840 13482 labs.nic.cz. yCe+PodZZ4pqopxX0gTKf3LEKhOnDaV6 23kCc0Op4mzV+fASs6NrrkQVVSsdfv0G qAi/ThM3yXLvnsGB0XVnIA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+labs.nic.cz. IN DS
+SECTION ANSWER
+labs.nic.cz. 1800 IN DS 13482 13 2 708b193611d70021885f8499d3b3de25b3c11a6c6801d62ef74cc87905428dc6
+labs.nic.cz. 1800 IN RRSIG DS 13 3 1800 20180810013825 20180727064002 33494 nic.cz. aM0ZTi5msMd2UOKvJv7sTQWLZP22B5dj NqfuvLf88vuW46gKokVGkOOSAgx7CeaH VVq7Ma4bzMuuXCqnjQiDcQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent7.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+SECTION AUTHORITY
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 61q3lko2dr2vnmncn1sh2vdiv449lmg3 A RRSIG
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180808122435 20180725105435 5070 labs.nic.cz. jrf7jm1Bc6YgN7WsYv1OBPFsOIfFxc2e kZZC9n2oMuyUgXV6KzYTJaHr8fvGOCKR GUWpo16osMQI1mdfcHskTw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN DNSKEY
+SECTION ANSWER
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent7.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+SECTION AUTHORITY
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 61q3lko2dr2vnmncn1sh2vdiv449lmg3 A RRSIG
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180808122435 20180725105435 5070 labs.nic.cz. jrf7jm1Bc6YgN7WsYv1OBPFsOIfFxc2e kZZC9n2oMuyUgXV6KzYTJaHr8fvGOCKR GUWpo16osMQI1mdfcHskTw==
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN NS
+SECTION ANSWER
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent7.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+SECTION AUTHORITY
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 61q3lko2dr2vnmncn1sh2vdiv449lmg3 A RRSIG
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180808122435 20180725105435 5070 labs.nic.cz. jrf7jm1Bc6YgN7WsYv1OBPFsOIfFxc2e kZZC9n2oMuyUgXV6KzYTJaHr8fvGOCKR GUWpo16osMQI1mdfcHskTw==
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN DS
+SECTION ANSWER
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent7.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+SECTION AUTHORITY
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 61q3lko2dr2vnmncn1sh2vdiv449lmg3 A RRSIG
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180808122435 20180725105435 5070 labs.nic.cz. jrf7jm1Bc6YgN7WsYv1OBPFsOIfFxc2e kZZC9n2oMuyUgXV6KzYTJaHr8fvGOCKR GUWpo16osMQI1mdfcHskTw==
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN AAAA
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN AAAA 2001:1488:ac15:ff90::133
+gitlab.labs.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. MkeWa5P2vNXqAxc1B7u8OEdbtadhLbsY Yy8IRlOcb6y2pn9xyjFyplyDqDMskX/6 J9kILbyTQCvxv2dOZ9prDQ==
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent7.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+SECTION AUTHORITY
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 61q3lko2dr2vnmncn1sh2vdiv449lmg3 A RRSIG
+4o5ekull1peq8leuf98l9iudrraqmqs4.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180808122435 20180725105435 5070 labs.nic.cz. jrf7jm1Bc6YgN7WsYv1OBPFsOIfFxc2e kZZC9n2oMuyUgXV6KzYTJaHr8fvGOCKR GUWpo16osMQI1mdfcHskTw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gitlab.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gitlab.labs.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gitlab.labs.nic.cz. IN NS
+SECTION AUTHORITY
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gitlab.labs.nic.cz. IN DS
+SECTION AUTHORITY
+labs.nic.cz. 1800 IN RRSIG SOA 13 3 1800 20180809143632 20180726130632 5070 labs.nic.cz. 3ZHmg1c9QRZSwroHmnLMYkJsxl2OiaS9 jPsfDZ2Ckm7MiQXUS4lXqXf+sfqMhcyP gpHwqhckCJOemCyaV/thfw==
+labs.nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532615793 10800 3600 1209600 7200
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN NSEC3 1 0 10 31ae62a0971eb1e7 pts6cg332bg2eqir8ga7efdju4elnad0 A AAAA SSHFP RRSIG
+pqats6gslj1en2mqjg1nok27ljrn62r3.labs.nic.cz. 7200 IN RRSIG NSEC3 13 4 7200 20180803103542 20180720090542 5070 labs.nic.cz. GK/DcFwOUvYfq02jwezQWLZhTSH1xSfl 8o1v0bi+7Vy40W70tra5ZvO6+UlQxnNN j5s6Fw5eenYl5qa/AmsNow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gitlab.labs.nic.cz. IN AAAA
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN AAAA 2001:1488:ac15:ff90::133
+gitlab.labs.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. MkeWa5P2vNXqAxc1B7u8OEdbtadhLbsY Yy8IRlOcb6y2pn9xyjFyplyDqDMskX/6 J9kILbyTQCvxv2dOZ9prDQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN A
+SECTION AUTHORITY
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN NS
+SECTION AUTHORITY
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN DS
+SECTION AUTHORITY
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN A
+SECTION ANSWER
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN NS
+SECTION AUTHORITY
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN DS
+SECTION AUTHORITY
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN AAAA
+SECTION ANSWER
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN A
+SECTION ANSWER
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN NS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN DS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN AAAA
+SECTION ANSWER
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN A
+SECTION ANSWER
+c.ns.nic.cz. 1800 IN A 194.0.14.1
+c.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809230245 20180727064002 33494 nic.cz. vlIESyKHWExpovMlpGstO7X8Qk1YnJYc w8i6u28JjABo/2qa20s3wFXVgenziyEn 3VTsenqk6TTTi8RutaSmhA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN NS
+SECTION AUTHORITY
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN DS
+SECTION AUTHORITY
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN AAAA
+SECTION ANSWER
+c.ns.nic.cz. 1800 IN AAAA 2001:678:11::1
+c.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809162728 20180727064002 33494 nic.cz. QRpoOGOlRV5YZkfr8rvOdGVZDqaFY4hV WsjpEl2cB1A9Rkw9/aX2toXhBoHTD7SX djgg2xiJzfNqtbBZNcpCrw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN A
+SECTION ANSWER
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN NS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN DS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN AAAA
+SECTION ANSWER
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 13 LSpU2wluEwbQLak1XGlg3KEYygKfIiAu Q8iJxgDDSKuPLIA/BIn40LC1nPzfLwoa zmL7sPJRetzjxwtErBLCmw==
+cz. 18000 IN DNSKEY 257 3 13 nqzH7xP1QU5UOVy/VvxFSlrB/XgX9JDJ zj51PzIj35TXjZTyalTlAT/f7PAfaSD5 mEG1N8Vk9NmI2nxgQqhzDQ==
+cz. 18000 IN RRSIG DNSKEY 13 1 18000 20180803000000 20180720000000 20237 cz. 2KI6brDc06P9gKXv+omp0NDfgxwMa2DD NnMNf7sE97/vGyCVdu0FkA3NdtpUs3UC RwD3Nb5+jh7O45sLwyu6yw==
+cz. 18000 IN RRSIG DNSKEY 13 1 18000 20180808205901 20180727070544 62295 cz. ICIV0ZsxkXXW4GBBHszAaNu09H00KyVB MNm6/DZOBzz/hwnkM9XUYVboyEwrXoSC FfMdDZlHNmrhpseHnkKjYg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+labs.nic.cz. IN NS
+SECTION ANSWER
+labs.nic.cz. 1800 IN NS a.ns.nic.cz.
+labs.nic.cz. 1800 IN NS b.ns.nic.cz.
+labs.nic.cz. 1800 IN NS d.ns.nic.cz.
+labs.nic.cz. 1800 IN RRSIG NS 13 3 1800 20180808225840 20180725212840 5070 labs.nic.cz. 4jhEp7GYmfxSSYschJjwKX8W/m03rDut 926G5kUJNNhaZLxTz4ORJ6IEMUz9OS6m 8tijL+7grvRjTk7bY6XQkQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN NS
+SECTION ANSWER
+knot-resolver.cz. 1800 IN NS a.ns.nic.cz.
+knot-resolver.cz. 1800 IN NS b.ns.nic.cz.
+knot-resolver.cz. 1800 IN NS d.ns.nic.cz.
+knot-resolver.cz. 1800 IN RRSIG NS 13 2 1800 20180808033000 20180725020000 34376 knot-resolver.cz. R/b3f4usP/+xCuNPKdTmG1twtSrvTOeM s9xyUn9538B2PPEhV0SHdnuzDMcgFgbw AmnDJMLqEMNce2Io76txDA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN NS
+SECTION ANSWER
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 3600 IN NS a.ns.nic.cz.
+cz. 3600 IN NS b.ns.nic.cz.
+cz. 3600 IN NS c.ns.nic.cz.
+cz. 3600 IN NS d.ns.nic.cz.
+cz. 3600 IN RRSIG NS 13 1 3600 20180806013233 20180724063548 62295 cz. NYwbiceGXv+yKrhwwMPUO5WihpVt4nip dQpjpbVxJfUp4s+j5lOHsxcbCm4EEaBx x1+UXCK6Gnw9TCnaZaOiBQ==
+SECTION ADDITIONAL
+a.ns.nic.cz. 3600 IN A 194.0.12.1
+a.ns.nic.cz. 3600 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 3600 IN A 194.0.13.1
+b.ns.nic.cz. 3600 IN AAAA 2001:678:10::1
+d.ns.nic.cz. 3600 IN A 193.29.206.1
+d.ns.nic.cz. 3600 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+RANGE_END
+
+; fill in cache with negative proofs
+
+; name exists but RRtype NULL does not
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+knot-resolver.cz. IN NULL
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags question rcode
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN NULL
+ENTRY_END
+
+; name does not exist
+; NSEC3 interval ei8u933svpm4qdfn713b66buji430uc7..rgofdsarih9kv8kcht41osd09tkl8o7v
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+nonexistent1123.knot-resolver.cz. IN A
+ENTRY_END
+
+; name does not exist BUT wildcard exists
+; NSEC3 interval 4o5ekull1peq8leuf98l9iudrraqmqs4..61q3lko2dr2vnmncn1sh2vdiv449lmg3
+STEP 31 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN A
+ENTRY_END
+
+STEP 32 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+nonexistent7.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+;gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+nonexistent7.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+ENTRY_END
+
+
+; check that other negative answers are generated from cache
+; (authoritative servers do not respond anymore)
+
+; name exists but RRtype TYPE65534 does not
+STEP 1010 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+knot-resolver.cz. IN TYPE65534
+ENTRY_END
+
+STEP 1011 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+knot-resolver.cz. IN TYPE65534
+ENTRY_END
+
+
+; second name which does not exist - must be synthesized because it is in the same
+; NSEC3 interval ei8u933svpm4qdfn713b66buji430uc7..rgofdsarih9kv8kcht41osd09tkl8o7v
+STEP 1020 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+nonexistent2.knot-resolver.cz. IN A
+ENTRY_END
+
+STEP 1021 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question
+REPLY QR RD RA AD NXDOMAIN
+SECTION QUESTION
+nonexistent2.knot-resolver.cz. IN A
+ENTRY_END
+
+; deeper names from the same
+; NSEC3 interval ei8u933svpm4qdfn713b66buji430uc7..rgofdsarih9kv8kcht41osd09tkl8o7v
+STEP 1022 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deep.nonexistent5.knot-resolver.cz. IN A
+ENTRY_END
+
+STEP 1023 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question authority
+REPLY QR RD RA DO AD NXDOMAIN
+SECTION QUESTION
+deep.nonexistent5.knot-resolver.cz. IN A
+SECTION AUTHORITY
+knot-resolver.cz. IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+knot-resolver.cz. IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mhyueV6+fJI1V5N3dEoczePO5y BZiffk91Xi2d4aYHRf2DLyfEX0HDVA==
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 1800 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux2/X8SwY2PmrcK/ff6wmFejIr GUHvrG1UNS9icqQqTV3swNymGz4Dbw==
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. IN NSEC3 1 0 10 F49E445B0B4AD67F EI8U933SVPM4QDFN713B66BUJI430UC7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x/H4aDF24oVFrRn2XTNNghu2O zmcVJV0EQlNIHd8aXfdQwLEz4FUAhw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. IN NSEC3 1 0 10 F49E445B0B4AD67F RGOFDSARIH9KV8KCHT41OSD09TKL8O7V NS DS RRSIG
+ENTRY_END
+
+STEP 1024 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deeper.deep.nonexistent5.knot-resolver.cz. IN A
+ENTRY_END
+
+STEP 1025 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question authority
+REPLY QR RD RA DO AD NXDOMAIN
+SECTION QUESTION
+deeper.deep.nonexistent5.knot-resolver.cz. IN A
+SECTION AUTHORITY
+knot-resolver.cz. IN SOA knot-s-01.nic.cz. hostmaster.nic.cz. 2018042353 10800 3600 1209600 7200
+knot-resolver.cz. IN RRSIG SOA 13 2 1800 20180809085235 20180726072235 34376 knot-resolver.cz. Yvpm+c/R4Y/Kj1a2Bz3JQBu+5admt4mhyueV6+fJI1V5N3dEoczePO5y BZiffk91Xi2d4aYHRf2DLyfEX0HDVA==
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. 1800 IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. KjH6+xM1sFW05x4sND+cIr2KTttyKiux2/X8SwY2PmrcK/ff6wmFejIr GUHvrG1UNS9icqQqTV3swNymGz4Dbw==
+0b1klvkf05j25j32u97kue78u2ejhm0s.knot-resolver.cz. IN NSEC3 1 0 10 F49E445B0B4AD67F EI8U933SVPM4QDFN713B66BUJI430UC7 A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. IN RRSIG NSEC3 13 3 7200 20180809085235 20180726072235 34376 knot-resolver.cz. 6wMAvVzU6xeyDZV1bDa/Av4n9k0kRB/x/H4aDF24oVFrRn2XTNNghu2O zmcVJV0EQlNIHd8aXfdQwLEz4FUAhw==
+ei8u933svpm4qdfn713b66buji430uc7.knot-resolver.cz. IN NSEC3 1 0 10 F49E445B0B4AD67F RGOFDSARIH9KV8KCHT41OSD09TKL8O7V NS DS RRSIG
+ENTRY_END
+
+
+; name does not exist BUT wildcard exists - must be synthesized from the same
+; NSEC3 interval 4o5ekull1peq8leuf98l9iudrraqmqs4..61q3lko2dr2vnmncn1sh2vdiv449lmg3
+STEP 1031 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+nonexistent899.labs.nic.cz. IN A
+ENTRY_END
+
+STEP 1032 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+nonexistent899.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+nonexistent899.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+nonexistent899.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+ENTRY_END
+
+; wildcard synthesis for deeper names from the same
+; NSEC3 interval 4o5ekull1peq8leuf98l9iudrraqmqs4..61q3lko2dr2vnmncn1sh2vdiv449lmg3
+STEP 1033 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deep.nonexistent47.labs.nic.cz. IN A
+ENTRY_END
+
+STEP 1034 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+deep.nonexistent47.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+deep.nonexistent47.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+deep.nonexistent47.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+ENTRY_END
+
+STEP 1035 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deeper.deep.nonexistent73.labs.nic.cz. IN A
+ENTRY_END
+
+STEP 1036 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+deeper.deep.nonexistent73.labs.nic.cz. IN A
+SECTION ANSWER
+gitlab.labs.nic.cz. 1800 IN A 217.31.192.133
+gitlab.labs.nic.cz. 1800 IN RRSIG A 13 4 1800 20180808062633 20180725045633 5070 labs.nic.cz. vIOy8SJPTE1CdRk71JAo+MxzbVhDvnh/ NQfkgdY5KOW081Jhrz74HJsAUsfJk4dD bTKY1DFVoUYYX49o0R7GGA==
+deeper.deep.nonexistent73.labs.nic.cz. 30 IN CNAME gitlab.labs.nic.cz.
+deeper.deep.nonexistent73.labs.nic.cz. 30 IN RRSIG CNAME 13 3 30 20180808062633 20180725045633 5070 labs.nic.cz. UPdL0dAWPX68OawblUE27nbM3drLu3yE 4jTQpefbhjTTmjs3I1dJ9IXgO6AEXHFx eWnlfK2r/45KZF7v/1NN6A==
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec3_wildcard_no_data_response.rpl b/tests/deckard/sets/resolver/nsec3_wildcard_no_data_response.rpl
new file mode 100644
index 0000000..45d7bac
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec3_wildcard_no_data_response.rpl
@@ -0,0 +1,110 @@
+; config options
+;server:
+ stub-addr: 193.0.14.129
+ trust-anchor: ". 3600 IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-timestamp: "1450794800"
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC wildcard answer response.
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 15182 IN DNSKEY 256 3 8 AwEAAbr/RV0stAWYbmKOldjShp4AOQGOyY3ATI1NUpP4X1qBs6lsXpc+1ABgv6zkg02IktjZrHnmD0HsElu3wqXMrT5KL1W7Spmg0Pou9WZ8QttdTKXwrVXrASsaGI2z/pLBSnK8EdzqUrTVxY4TEGZtxV519isM06CCMihxTn5cfFBF
+. 15182 IN DNSKEY 256 3 8 AwEAAbgVvZmZibtBpha3AIykU0OY4gcCXTcskYJUxGsdmV/awfmKcHlSrjNMioSgy4sByj+HpcbsyrZVGPp+JBXzYwwuEF/6w1k7vKYTK6vMSqgVcgooNkfb5MaRF2y7MEpPxfStnfwu8knE24ExB0hYE1URxJ9CqB3zMSl/vicXYXXl
+. 15182 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 15182 IN RRSIG DNSKEY 8 0 172800 20160105235959 20151221000000 19036 . BfU0HEA1JUuZA0+4EXsFhwW7iH03vwPD+u9DtjF5mmeITV7kkJyg8IguzAlPsLDNFfe+hudz+NZafgaGq1bMUT3Ax4/qlH5qxVBfJi/n8fWeF4hEcyGtIsDVBsTUwqez7ZXVVoUffHcLAE+xuXaKeqdiz9bU70vsCMNu+DmIWXi8G1AFV/fjqtN1UtxF91R2XajWvSFm2tfOnGUJ6iS4tvxWe2Qi133CNMP1P3zd7oWiFg2bTwt2OjlhGH3CAg2WvDt72t/9hGNDy/dk2ukOZv4V1lsv2X4cW5NVN6ZmVf/UMyTdD/YGumHkTMbGKHHbTyBlJjYdBf0yXBTXD9Hulg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20160101050000 20151222040000 62530 . RW66z4Mh1Z97WHCw9exQB24SvNQ9nFC6zYZ+Ta6MuiLXLQnrn5OcEeZia0cotsa1W/7N55a/JzS0PCOBuQoGEZyRhWva9Cdl6PcKzAskD4UEWLeWnBDZfSL21a+fxl/aPDslfxhG78ZB7nTj0PRdqE6HK97DHwDyF5HNNzq7r4E=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+qwr.cz. IN A
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20160101050000 20151222040000 62530 . RW66z4Mh1Z97WHCw9exQB24SvNQ9nFC6zYZ+Ta6MuiLXLQnrn5OcEeZia0cotsa1W/7N55a/JzS0PCOBuQoGEZyRhWva9Cdl6PcKzAskD4UEWLeWnBDZfSL21a+fxl/aPDslfxhG78ZB7nTj0PRdqE6HK97DHwDyF5HNNzq7r4E=
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAdptcFzJsHzR4xeGi3Cyq5FG9N0S3Ch9qrSIa3rQHsKwsdgfNZ5UX5v91AROH9lZo60d/fIxtuDefnID+uIJDAsiwIAzWFzJbmCBPJ24jqhCJ03N6ejrIM1qvvwjnoh655wh2LfaejnDMdjPth0L+q+vRoJL0cjv0dhdDs532ch/
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5HeRVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYhT2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPjOZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJxES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20151230000000 20151216000000 54576 cz. d1tJTXuUjtEa5JO07K7clczFvUgSNHHO0o6LT8HL2i0a2K6P6A9g9pWywarBNYpRJrwlq243Pub5cU2Tr+MNwzyYgORVO7gFPTTLDZlRAWmE3ujGNrzsVcalQHBQzwji5JN20ujnps1jj7Xy17pHJCLbnNEZP6HkQR4b7GkSI5iAFYSZ8vYzWup5Ei57EIlpPRVJtB6K6Sa4vPaRhXQgwFZBtcmgfBLMI7YQrMpjKMftpHsabzB4gjTB8TLofJR8hPWCR2x7+X9HMtj9O6U93WyIYCC41hCCLON8yNIxhp8tjKN/ZxTy5JycElxMHvGaxFl8kuVBAySdVRsxx+Ffwg==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20160105041723 20151222140958 50870 cz. sr+1HKa9BqRSNLDF8hpcKL9MVm6vR3WMeEpOokYK4ij2wCGcv8fzdFJg6Wc7dSKhs5Jt3+toq4ypFtkcIjN7UTgokWD87Du3oKeZUsrISCSpoMpz3Q5ozpLSU/aqmuXrAFqMKNAXQ6uEf6vfJoHuESmouH7r9muNv9AetYCG0S4=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+qwr.cz. IN A
+SECTION AUTHORITY
+cz. 900 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1450796998 900 300 604800 900
+e07bsbm6cddl06sj99fmff7td56savbn.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 E07G4NAI26HIBP3R8NEJGTUVV1JPT11N NS SOA RRSIG DNSKEY NSEC3PARAM
+9tjfc6416bffr8mbna7d52ke1hpes293.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 9TJLDJIGE8VDG8MMHORIG0DCLM4NA5F5 NS
+4qk800tsde3b9rihkgedb581mv504cha.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 4QK94GS2KQ6T0C5HTJROTGVJMBQK7RFC NS
+cz. 18000 IN RRSIG SOA 10 1 18000 20160104010623 20151222140958 50870 cz. RhhKmE9ZAoqiAFoSH6ZFSomqVFmHF99xKgPGxf+3QSLrohPOYiuLL/CVEEjUxiITDd7g3jfRN/ZzHNOm6cU0kLqmSf4kaOfBE+bJ/5w6NBAARvWsirk3M//IVJ7G603Dizsykt9fkEaLpstAtJXdhLq1pUqAEXYmyEOKlgYOe+A=
+e07bsbm6cddl06sj99fmff7td56savbn.cz. 900 IN RRSIG NSEC3 10 2 900 20160104070356 20151222070953 50870 cz. yzP9bcqgS1KoHJCY7qi/NEvtkUAKTN70dbMJKZAWAmNJX9RYsGEV+VNg2D8ifZ2jxxcMXbO0kPjFiJXNg7Jz1ekmpEBC+wYMVvgVhtVhKzAIfMIweiSwiOqKFTmyyb0Tk/WukrYAqDFaeQ7nTJzl+kLU8sH72yOiYyWUJDDQHpo=
+9tjfc6416bffr8mbna7d52ke1hpes293.cz. 900 IN RRSIG NSEC3 10 2 900 20151230104714 20151216200951 50870 cz. n4hQwoX3aOVNNEei/46RCkR+J4TOwCq9Pe+ikEIsXBrj+xOOf0bAd/bthUq2wBX05e2SVem6YnzW9UyaRqwOS0pRvtypAdcmgrTXtaKVI+0+EiwaZHPF1fLi3+p9kxrGkJ5wkyKiFUrfa4zstEoQMnMxTU4eQUBDYgN3LlrEQcc=
+4qk800tsde3b9rihkgedb581mv504cha.cz. 900 IN RRSIG NSEC3 10 2 900 20151230070920 20151217171007 50870 cz. ZR76bT+u5t5tJ1qoYhS8Ak6OgHRfY9T0FjQrEuRd9U7ROTytxGDupH+nZZfnMyTC48ELrZRCHvxwFYskbI2XtBWyE3Vaid43ntq9b+eAvjqYYXJu5V1wC8+K56LlmStdCL/U4OEliwfPHuUnS/AcX0hci2XSslGWRfJzTVLjQcc=
+ENTRY_END
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+qwr.cz. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NXDOMAIN
+SECTION QUESTION
+qwr.cz. IN A
+SECTION AUTHORITY
+cz. 900 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1450796998 900 300 604800 900
+e07bsbm6cddl06sj99fmff7td56savbn.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 E07G4NAI26HIBP3R8NEJGTUVV1JPT11N NS SOA RRSIG DNSKEY NSEC3PARAM
+9tjfc6416bffr8mbna7d52ke1hpes293.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 9TJLDJIGE8VDG8MMHORIG0DCLM4NA5F5 NS
+4qk800tsde3b9rihkgedb581mv504cha.cz. 900 IN NSEC3 1 0 10 FC6C06CB130A4809 4QK94GS2KQ6T0C5HTJROTGVJMBQK7RFC NS
+cz. 18000 IN RRSIG SOA 10 1 18000 20160104010623 20151222140958 50870 cz. RhhKmE9ZAoqiAFoSH6ZFSomqVFmHF99xKgPGxf+3QSLrohPOYiuLL/CVEEjUxiITDd7g3jfRN/ZzHNOm6cU0kLqmSf4kaOfBE+bJ/5w6NBAARvWsirk3M//IVJ7G603Dizsykt9fkEaLpstAtJXdhLq1pUqAEXYmyEOKlgYOe+A=
+e07bsbm6cddl06sj99fmff7td56savbn.cz. 900 IN RRSIG NSEC3 10 2 900 20160104070356 20151222070953 50870 cz. yzP9bcqgS1KoHJCY7qi/NEvtkUAKTN70dbMJKZAWAmNJX9RYsGEV+VNg2D8ifZ2jxxcMXbO0kPjFiJXNg7Jz1ekmpEBC+wYMVvgVhtVhKzAIfMIweiSwiOqKFTmyyb0Tk/WukrYAqDFaeQ7nTJzl+kLU8sH72yOiYyWUJDDQHpo=
+9tjfc6416bffr8mbna7d52ke1hpes293.cz. 900 IN RRSIG NSEC3 10 2 900 20151230104714 20151216200951 50870 cz. n4hQwoX3aOVNNEei/46RCkR+J4TOwCq9Pe+ikEIsXBrj+xOOf0bAd/bthUq2wBX05e2SVem6YnzW9UyaRqwOS0pRvtypAdcmgrTXtaKVI+0+EiwaZHPF1fLi3+p9kxrGkJ5wkyKiFUrfa4zstEoQMnMxTU4eQUBDYgN3LlrEQcc=
+4qk800tsde3b9rihkgedb581mv504cha.cz. 900 IN RRSIG NSEC3 10 2 900 20151230070920 20151217171007 50870 cz. ZR76bT+u5t5tJ1qoYhS8Ak6OgHRfY9T0FjQrEuRd9U7ROTytxGDupH+nZZfnMyTC48ELrZRCHvxwFYskbI2XtBWyE3Vaid43ntq9b+eAvjqYYXJu5V1wC8+K56LlmStdCL/U4OEliwfPHuUnS/AcX0hci2XSslGWRfJzTVLjQcc=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_aggr_cache.rpl b/tests/deckard/sets/resolver/nsec_aggr_cache.rpl
new file mode 100644
index 0000000..6230de7
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_aggr_cache.rpl
@@ -0,0 +1,6355 @@
+ trust-anchor: ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ trust-anchor: ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"
+ val-override-date: 20180727184403
+ stub-addr: 2001:7fe::53
+CONFIG_END
+
+SCENARIO_BEGIN qlist
+
+; Scope ".
+
+; Server names:
+; f.root-servers.net.
+; a.root-servers.net.
+; j.root-servers.net.
+; e.root-servers.net.
+; i.root-servers.net.
+; d.root-servers.net.
+; m.root-servers.net.
+; h.root-servers.net.
+; c.root-servers.net.
+; l.root-servers.net.
+; g.root-servers.net.
+; b.root-servers.net.
+; k.root-servers.net.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:7fe::53
+ ADDRESS 192.203.230.10
+ ADDRESS 2001:500:2d::d
+ ADDRESS 193.0.14.129
+ ADDRESS 202.12.27.33
+ ADDRESS 192.112.36.4
+ ADDRESS 2001:500:2f::f
+ ADDRESS 198.97.190.53
+ ADDRESS 192.5.5.241
+ ADDRESS 199.7.91.13
+ ADDRESS 199.9.14.201
+ ADDRESS 192.58.128.30
+ ADDRESS 2001:500:a8::e
+ ADDRESS 198.41.0.4
+ ADDRESS 2001:500:9f::42
+ ADDRESS 2001:dc3::35
+ ADDRESS 192.33.4.12
+ ADDRESS 199.7.83.42
+ ADDRESS 2001:500:1::53
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 2001:7fd::1
+ ADDRESS 2001:500:2::c
+ ADDRESS 2001:500:200::b
+ ADDRESS 2001:503:c27::2:30
+ ADDRESS 2001:500:12::d0d
+ ADDRESS 192.36.148.17
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN DS
+SECTION AUTHORITY
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+hm. IN DNSKEY
+SECTION AUTHORITY
+hm. 172800 IN NS ns1.registry.hm.
+hm. 172800 IN NS ns2.registry.hm.
+hm. 172800 IN NS ns3.registry.hm.
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+SECTION ADDITIONAL
+ns1.registry.hm. 172800 IN A 208.70.79.25
+ns2.registry.hm. 172800 IN A 208.70.79.24
+ns3.registry.hm. 172800 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+hm. IN A
+SECTION AUTHORITY
+hm. 172800 IN NS ns1.registry.hm.
+hm. 172800 IN NS ns2.registry.hm.
+hm. 172800 IN NS ns3.registry.hm.
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+SECTION ADDITIONAL
+ns1.registry.hm. 172800 IN A 208.70.79.25
+ns2.registry.hm. 172800 IN A 208.70.79.24
+ns3.registry.hm. 172800 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+hm. IN SOA
+SECTION AUTHORITY
+hm. 172800 IN NS ns1.registry.hm.
+hm. 172800 IN NS ns2.registry.hm.
+hm. 172800 IN NS ns3.registry.hm.
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+SECTION ADDITIONAL
+ns1.registry.hm. 172800 IN A 208.70.79.25
+ns2.registry.hm. 172800 IN A 208.70.79.24
+ns3.registry.hm. 172800 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+sk2. IN DS
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+sk2. IN DNSKEY
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+sk2. IN NS
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+sk2. IN A
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NXDOMAIN
+SECTION QUESTION
+sk2. IN AAAA
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN TYPE65535
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN DNSKEY
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN DS
+SECTION ANSWER
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN A
+SECTION ANSWER
+f.root-servers.net. 3600000 IN A 192.5.5.241
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.root-servers.net. IN AAAA
+SECTION ANSWER
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN A
+SECTION ANSWER
+a.root-servers.net. 3600000 IN A 198.41.0.4
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.root-servers.net. IN AAAA
+SECTION ANSWER
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN A
+SECTION ANSWER
+j.root-servers.net. 3600000 IN A 192.58.128.30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.root-servers.net. IN AAAA
+SECTION ANSWER
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN A
+SECTION ANSWER
+e.root-servers.net. 3600000 IN A 192.203.230.10
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.root-servers.net. IN AAAA
+SECTION ANSWER
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN A
+SECTION ANSWER
+i.root-servers.net. 3600000 IN A 192.36.148.17
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.root-servers.net. IN AAAA
+SECTION ANSWER
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN A
+SECTION ANSWER
+d.root-servers.net. 3600000 IN A 199.7.91.13
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.root-servers.net. IN AAAA
+SECTION ANSWER
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN A
+SECTION ANSWER
+m.root-servers.net. 3600000 IN A 202.12.27.33
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.root-servers.net. IN AAAA
+SECTION ANSWER
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN A
+SECTION ANSWER
+h.root-servers.net. 3600000 IN A 198.97.190.53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.root-servers.net. IN AAAA
+SECTION ANSWER
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN A
+SECTION ANSWER
+c.root-servers.net. 3600000 IN A 192.33.4.12
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.root-servers.net. IN AAAA
+SECTION ANSWER
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN A
+SECTION ANSWER
+l.root-servers.net. 3600000 IN A 199.7.83.42
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.root-servers.net. IN AAAA
+SECTION ANSWER
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN A
+SECTION ANSWER
+g.root-servers.net. 3600000 IN A 192.112.36.4
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.root-servers.net. IN AAAA
+SECTION ANSWER
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN A
+SECTION ANSWER
+b.root-servers.net. 3600000 IN A 199.9.14.201
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.root-servers.net. IN AAAA
+SECTION ANSWER
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN NS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN DS
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+SECTION AUTHORITY
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN DNSKEY
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN DS
+SECTION ANSWER
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20180809050000 20180727040000 41656 . iPYXlPdWqSGLIBjkBHYPCkA7LpjtEq2l 3IxdgesYUMxKFrYsdxgySnyBHQ9YzAQc bl3fCtLvlx6msHw/cCqMRHhCCjDnqTa/ NqBRtr1hr8ZbPrb3pZf+1hjX+9eohhHQ OiyAiP1hVaEIBIiSt7W8aPYvjZRogQAy YPApw3dwsfTFWzTnd+EDZsuZeMz0k74x BEJmC/tzTjnzvNK8fU95Mv+pKLm09Hda eXP2i+zrAwguTZBUt30dnsrYA7dxkQcP s+SdFhfPlGYS2EWOoJsik3DGRHQpTHI5 N9sjytXS7IqWetnaNJyFL0KSpG1YdEyB JvYqCrUI6YLDopcgUSRjrA==
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAfaifSqh+9ItxYRCwuiY0FY2NkaE wd/zmyVvakixDgTOkgG/PUzlEauAiKzl xGwezjqbKFPSwrY3qHmbbsSTY6G8hZtn a8k26eCwy59Chh573cu8qtBkmUIXMYG3 fSdlUReP+uhBWBfKI2aGwhRmQYR0zSmg 7PGOde34c/rOItK1ebJhjTAJ6TmnON7q Mfk/lKvH4qOvYtzstLhr7Pn9ZOVLx/WU KQpU/nEyFyTduRbz1nZqkp6yMuHwWVsA BK8lUYXSaUrDAsuMSldhafmR/A15BxNh v9M7mzJj7UH2RVME9JbYinBEzWwW9Gpn Y+ZmBWgZiRVTaDuemCTJ5ZJWLRs=
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29 euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v 58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8 g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37 NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/E fucp2gaDX6RS6CXpoY68LsvPVjR0ZSwz z1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgu l0sGIcGOYl7OyQdXfZ57relSQageu+ip AdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1 dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 172800 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexT BAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq 7HrxRixHlFlExOLAJr5emLvN7SWXgnLh 4+B5xQlNVz8Og8kvArMtNROxVQuCaSnI DdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLr jyBxWezF0jLHwVN8efS3rCj/EWgvIWgb 9tarpVUDK/b58Da+sqqls3eNbuv7pr+e oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTId sIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6 +cn8HFRm+2hM8AnXGXws9555KrUB5qih ylGa8subX2Nn6UwNR1AkUTV74bU=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20180811000000 20180721000000 19036 . U2thj3DQzTGRF8m2ZytqANs9YF9PYb1B QC5bDHi+d7apJve5u3Ik1cCeYg9AlW2v 2vstMSUtTR0eI2mzBeZ8aBHLwPylyDhS jbe6lwxnaoZhncO4oM9bJTUha1ovCXPO oZm5dKhfI6FradAaitRfMaC7s/+XZ/Dh nlLQNe08F0qepkG52RsUJZEyiQkkOK5a /hNkV5gyKdMecjtJ7eiR1w68vWwP6iGp ohuLDlapbEniJXHhEysUtRJbE3EFYgwG EGeKwEQC3tDCb8ABYnbrkMg/OqhGP1cX aYfZwhEIUOvsplTdXU1tsVbPjGtbVBjy 4aKLY+pjsvWuT2dzMac18A==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+root-servers.net. 3600000 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018070900 14400 7200 1209600 3600000
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. 3600000 IN NS a.root-servers.net.
+root-servers.net. 3600000 IN NS b.root-servers.net.
+root-servers.net. 3600000 IN NS c.root-servers.net.
+root-servers.net. 3600000 IN NS d.root-servers.net.
+root-servers.net. 3600000 IN NS e.root-servers.net.
+root-servers.net. 3600000 IN NS f.root-servers.net.
+root-servers.net. 3600000 IN NS g.root-servers.net.
+root-servers.net. 3600000 IN NS h.root-servers.net.
+root-servers.net. 3600000 IN NS i.root-servers.net.
+root-servers.net. 3600000 IN NS j.root-servers.net.
+root-servers.net. 3600000 IN NS k.root-servers.net.
+root-servers.net. 3600000 IN NS l.root-servers.net.
+root-servers.net. 3600000 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 199.9.14.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:200::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+hm. IN NS
+SECTION AUTHORITY
+hm. 172800 IN NS ns1.registry.hm.
+hm. 172800 IN NS ns2.registry.hm.
+hm. 172800 IN NS ns3.registry.hm.
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+SECTION ADDITIONAL
+ns1.registry.hm. 172800 IN A 208.70.79.25
+ns2.registry.hm. 172800 IN A 208.70.79.24
+ns3.registry.hm. 172800 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 20237 13 2 cff0f3ecdbc529c1f0031ba1840bfb835853b9209ed1e508fff48451d7b778e2
+cz. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . BkGaXhVOBlSGZkRo6m6xYxeXSEIqVZKa 7wHxKdNn+6F/DDJoD0aEgEg6H7yhjKs2 tt4uyp9l8/L8r/mWoFPjYsSsQgc2hpxJ Ql2wTDRNaRpQ+spbiefndoyr1/5YBMFv mItzzMSg93ekx3gebfVqMpe0fpvs7NjA +33vGJO3e3ficaYDIf9HY/npnHgjOtpE wiFPYmLTb+zLlIHd4hhXOXg/Kv5CNGvN aBdBE2s2GXJbYI3Zd5FDHxhZ+qLuhL5J qjtrGDokRgM0Jk8dDroIk0yQHfNU022s ZAhIeEZJhwiuh4bNuJJCKoB+a5UIiNx+ rCUU2ntIsqLbxbnpKLamow==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862b27f5f516ebe19680444d4ce5e762981931842c465f00236401d8bd973ee
+net. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . 0Uvgipa8bRqTwVpcmpPngKx1brdQ0rIB H8QbEl4KyFE+CI8nB3jNk9rHF15WYQm1 Xov0E1uCMvYfv1w96LvC+N4w7hPsCpgG sK3+pT90vhsLRqoP7dws5MU0fsXfpmGP X3utMPZGwk7JDSUhQAbIWiCD81JAi05y I5xbaeveUSSvMbyXJKyzsbHWVP6997BX 4Las1O8H/1Eds743+Cfc5hPULqH5ZUWB EPIKN+MZQM9DjmgUUJSlktWQwK42BeXU 9O4DUGP2oxwbQ8uw4PlRhhxYp3UCP9b5 B2d4fqlaalhiPY86u7TkzEbEJJlW2tf+ 3bGAiX9a9icfbsrdS9hsuw==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 86400 IN DS 30909 8 2 e2d3c916f6deeac73294e8268fb5885044a833fc5459588f4a9184cfc41a5766
+com. 86400 IN RRSIG DS 8 1 86400 20180809050000 20180727040000 41656 . eGyv2a7tzQdljtzCX0sF211why7uD3PI c1rSQxJKfd0AbhZKvcl6jQW+rRHHQHui ljjsXG1fp35P7P02269xj5Hbu2eNV5vr jRdXTzAQ+waZZHBn87mNOiURZwh0sG44 7XQYdpkC656acDJ8TP6Szox1gCkBo6eM /SquL8Jmtl6IQSszxT71auHUytVRL8NR bv57T/PXQ9fSAjq5+lgZ7ZVvCs6sVjRl KvtaGLixnb7pR9C08jLWA/j2jAG0RBV2 pOz7BVDm7V34FIjJ9yd8BbSKeEJFcQWl m9x26nQREBmpKp8AmUiUoxfyuZvMxu// EGVxIEh71OHxT46+AhCipg==
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+RANGE_END
+
+; Scope "com.
+
+; Server names:
+; a.gtld-servers.net.
+; j.gtld-servers.net.
+; e.gtld-servers.net.
+; i.gtld-servers.net.
+; d.gtld-servers.net.
+; m.gtld-servers.net.
+; h.gtld-servers.net.
+; c.gtld-servers.net.
+; l.gtld-servers.net.
+; g.gtld-servers.net.
+; b.gtld-servers.net.
+; k.gtld-servers.net.
+; f.gtld-servers.net.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:500:d937::30
+ ADDRESS 2001:503:eea3::30
+ ADDRESS 192.26.92.30
+ ADDRESS 192.33.14.30
+ ADDRESS 192.54.112.30
+ ADDRESS 2001:503:d414::30
+ ADDRESS 2001:503:231d::2:30
+ ADDRESS 192.42.93.30
+ ADDRESS 2001:502:7094::30
+ ADDRESS 192.43.172.30
+ ADDRESS 192.41.162.30
+ ADDRESS 192.12.94.30
+ ADDRESS 192.31.80.30
+ ADDRESS 192.35.51.30
+ ADDRESS 192.48.79.30
+ ADDRESS 2001:501:b1f9::30
+ ADDRESS 192.55.83.30
+ ADDRESS 2001:503:a83e::2:30
+ ADDRESS 192.5.6.30
+ ADDRESS 2001:503:83eb::30
+ ADDRESS 192.52.178.30
+ ADDRESS 2001:502:8cc::30
+ ADDRESS 2001:503:39c1::30
+ ADDRESS 2001:500:856e::30
+ ADDRESS 2001:502:1ca1::30
+ ADDRESS 2001:503:d2d::30
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DNSKEY
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+net. 900 IN RRSIG SOA 8 1 900 20180803164343 20180727153343 7934 net. saMkeHnnZmFjMmrWJIcMIWfKP8XuvHyF 9S27EbEZJOze88EKxPoMirhwWptR9wge NZraLn79mYdFOYaxEWG3BmxablU7/0e4 4UUivo2svI8/0olxwD2jb7/VtF9e7FCv RpUuMeQZMarVejw343R4GcKPDMbpeEyh 0SbIk3mrhng=
+net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532709823 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN A
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DS
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+net. 900 IN RRSIG SOA 8 1 900 20180803164328 20180727153328 7934 net. ZWXeaMxei6TLZhNkc4cXpocES6HhF1gb COvQ/kMTDUs5xK/d9gxxKcKje1hWmbUM 4rx00UkmCD6LrMkBKA0dfNFQVcQ1RAkN TWw21eotUZ0zisthm4LD2vG9fQ9q9X1n MhurnN4hOURgFcaeBzTcK63HXA/iMziH ICsuOHsJxa4=
+net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532709808 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN A
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN DNSKEY
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN DS
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+com. 900 IN RRSIG SOA 8 1 900 20180803164344 20180727153344 46475 com. mBKTxHc1L8vSbi+fiS0UNrRFChdlnFyM 63qD+GwUugwtsu9uNhTA+9SrwhgSdM1O MOwX2B/Erqt7e68Ur+4BfCzD9SuaZVS2 7rfb5wFQeumdHJs4wZyXk/jL9DbjdnHL 5y8b0uGkv8H2YmnWMEVo7pCWQbOphrhz pbNXp+c3mb8=
+com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1532709824 1800 900 604800 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN DNSKEY
+SECTION ANSWER
+net. 86400 IN DNSKEY 256 3 8 AQO6ELLy73I+l1XTVPuW3zfQkw5nublx oY4QgdTVOfUjdv6ooKTMRMgfKb+alpX5 8L5pfhndd+o7hisIwgiH2b6aqjdljzTf dV4XeZ/2CROv1ki/BRWwD61P/w688bpu Bl/u3vsTjvjq6FdVZVf3/afMXtSO1RR7 uaQ7qn8oupY/6w==
+net. 86400 IN DNSKEY 257 3 8 AQOYBnzqWXIEj6mlgXg4LWC0HP2n8eK8 XqgHlmJ/69iuIHsa1TrHDG6TcOra/pye GKwH0nKZhTmXSuUFGh9BCNiwVDuyyb6O BGy2Nte9Kr8NwWg4q+zhSoOf4D+gC9dE zg0yFdwT0DKEvmNPt0K4jbQDS4Yimb+u PKuF6yieWWrPYYCrv8C9KC8JMze2uT6N uWBfsl2fDUoV4l65qMww06D7n+p7Rbdw WkAZ0fA63mXVXBZF6kpDtsYD7SUB9jhh fLQE/r85bvg3FaSs5Wi2BaqN06SzGWI1 DHu7axthIOeHwg00zxlhTpoYCH0ldoQz +S65zWYi/fRJiyLSBb6JZOvn
+net. 86400 IN RRSIG DNSKEY 8 1 86400 20180808153857 20180724153357 35886 net. lmab/pWDgNRz6BN1BFZmkwiZz0qay0rz +46JXwgzI/g8eadEAev1OaIfsply91iM Sn+87NMPDN1Spjr3LKSXQB7+nc8n3yrf h1gxPRsjwuWxvPc3dJwlB4P8NvXTk4B5 vzjSpcfzvb+6YuAoC171yFcIcER1RN5d j3y1NRx1EAnuanMfoHIm+2dcu14a2hKn fB0zc/hm4L/rO/Qm8c3z97d1OffQs0L0 MGCU/kBDm/UyjymSFobMlIcn0bIha7A1 QN753OY+LEOWq0flQgUrKeuXvAe2o46g GebT+8euJahn/HmgmHD/bCNn+GC/KRJJ L1wFQH3x8uqlq9loQMPjwQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN DNSKEY
+SECTION ANSWER
+com. 86400 IN DNSKEY 256 3 8 AQPeabgR6Fgrk5FSLilDYUedwsHA0HH2 2e8+Zp/uvp4aj1dVDAy5C9bkRA+xot3s G1KaT5hvgoE7eNV93F7pBW9rvVE3A/BN vJbLXxKhkAJV5KMFC10NRcdb+xF+sM4X TMPESPrYwTLUEpSFntMIVLAtUzLaBo6Y pTVR20osgGgc3Q==
+com. 86400 IN DNSKEY 257 3 8 AQPDzldNmMvZFX4NcNJ0uEnKDg7tmv/F 3MyQR0lpBmVcNcsIszxNFxsBfKNW9JYC Yqpik8366LE7VbIcNRzfp2h9OO8HRl+H +E08zauK8k7evWEmu/6od+2boggPoiEf GNyvNPaSI7FOIroDsnw/taggzHRX1Z7S OiOiPWPNIwSUyWOZ79VmcQ1GLkC6NlYv G3HwYmynQv6oFwGv/KELSw7ZSdrbTQ0H XvZbqMUI7BaMskmvgm1G7oKZ1YiF7O9i oVNc0+7ASbqmZN7Z98EGU/Qh2K/BgUe8 Hs0XVcdPKrtyYnoQHd2ynKPcMMlTEih2 /2HDHjRPJ2aywIpKNnv4oPo/
+com. 86400 IN RRSIG DNSKEY 8 1 86400 20180810182533 20180726182033 30909 com. pytllCSmnIFN69hPKx3IcJSV3ZD+4qoF CXIuN+LXSJpkWmpD4gOWKgAytIBMImbh iUrfLECS2c3TJkjWjthKjL+GpYIHN1Z/ UY2zdSqKr0JqBQjHs456zBsJIrRriQKh e7MEFWV+JLSYAHQi/8+ot3l9GKO9nSK6 zqP+FrMtkPtZbJeNo1muSQ4lrdvYw4/t k0FADV0DK8p8/D/OQEPg2+Mpwx9GjCVN VOlKS5vuGHGAKI0gXlhJoe28i5McJVc5 O/evqbRX37xmfX01F8W4f6lZBt3qVIVq gW9iJAjY5vd4l4m53lTzYKTLeJTFH358 TsJO93q0NpaWL78xLxkVrg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION AUTHORITY
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN NSEC3 1 1 0 - t2ukct9k5i0uhv7b3m3na6jaigdjm0gr NS DS RRSIG
+T2UF21DR03E0BNPB42UQMVUF38P2TA8D.net. 86400 IN RRSIG NSEC3 8 2 86400 20180802052514 20180726041514 7934 net. LDVOVqnK+2HRKN6dUmVP3pP2RE0dCKTQ oE0d2w1AiDAOhn3Ye9Aq0yUjkz+frcUj ZqvTdiC58q0mXpyLUbqWiGmazUVG5qT7 zx5mhp1Leetq1wVJH8KGYLEmTstTCT56 oMbtWugGmZeY2B47rCsCeaWPNdH/b8qb UrwpfdPbhJE=
+root-servers.net. 172800 IN NS a.root-servers.net.
+root-servers.net. 172800 IN NS b.root-servers.net.
+root-servers.net. 172800 IN NS c.root-servers.net.
+root-servers.net. 172800 IN NS d.root-servers.net.
+root-servers.net. 172800 IN NS e.root-servers.net.
+root-servers.net. 172800 IN NS f.root-servers.net.
+root-servers.net. 172800 IN NS g.root-servers.net.
+root-servers.net. 172800 IN NS h.root-servers.net.
+root-servers.net. 172800 IN NS i.root-servers.net.
+root-servers.net. 172800 IN NS j.root-servers.net.
+root-servers.net. 172800 IN NS k.root-servers.net.
+root-servers.net. 172800 IN NS l.root-servers.net.
+root-servers.net. 172800 IN NS m.root-servers.net.
+SECTION ADDITIONAL
+a.root-servers.net. 172800 IN A 198.41.0.4
+a.root-servers.net. 172800 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 172800 IN A 199.9.14.201
+b.root-servers.net. 172800 IN AAAA 2001:500:200::b
+c.root-servers.net. 172800 IN A 192.33.4.12
+c.root-servers.net. 172800 IN AAAA 2001:500:2::c
+d.root-servers.net. 172800 IN A 199.7.91.13
+d.root-servers.net. 172800 IN AAAA 2001:500:2d::d
+e.root-servers.net. 172800 IN A 192.203.230.10
+e.root-servers.net. 172800 IN AAAA 2001:500:a8::e
+f.root-servers.net. 172800 IN A 192.5.5.241
+f.root-servers.net. 172800 IN AAAA 2001:500:2f::f
+g.root-servers.net. 172800 IN A 192.112.36.4
+g.root-servers.net. 172800 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 172800 IN A 198.97.190.53
+h.root-servers.net. 172800 IN AAAA 2001:500:1::53
+i.root-servers.net. 172800 IN A 192.36.148.17
+i.root-servers.net. 172800 IN AAAA 2001:7fe::53
+j.root-servers.net. 172800 IN A 192.58.128.30
+j.root-servers.net. 172800 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 172800 IN A 193.0.14.129
+k.root-servers.net. 172800 IN AAAA 2001:7fd::1
+l.root-servers.net. 172800 IN A 199.7.83.42
+l.root-servers.net. 172800 IN AAAA 2001:500:9f::42
+m.root-servers.net. 172800 IN A 202.12.27.33
+m.root-servers.net. 172800 IN AAAA 2001:dc3::35
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION AUTHORITY
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5qdppotuk27kkp9ligtrb0k1cbvm9cim NS DS RRSIG
+5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20180801102320 20180725091320 7934 net. ZKWDEle0ZQbeLFqJNnGWN9zZNZ4qXpns WEmuTMy1Ou9IRpBl0YU1RQRdjRJ4aFWM 5Kcl/UIOgeN4yD+B8HludqzhxRGDxqZ1 N1ObndmMNLbokcgyIYVnmhoe3doOnedK KRU5F6YcJpEOQ4jcJsjQd9ekQTB9aBP3 j33L4T3A1PM=
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - a1ruuffjkct2q54p78f8ejgj8jbk7i8b NS SOA RRSIG DNSKEY NSEC3PARAM
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20180731053505 20180724042505 7934 net. aQ1+tOFuT3esonx3VUVqcQGwUlcby0Wa Rit1P1ikFjowshfV9AUsn/bkka2dFgxC PgDtmMiQ6TzAKiwciFJ5mZitfFZSEoS/ Z3pnsZsvB062GrKNup9+x4SBiRB3HH8T xMMd6sVV9LjOE2iOm4ekIUHieMwJjfnY 7yG7obH6OFI=
+gtld-servers.net. 172800 IN NS av1.nstld.com.
+gtld-servers.net. 172800 IN NS av2.nstld.com.
+gtld-servers.net. 172800 IN NS av3.nstld.com.
+gtld-servers.net. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+nstld.com. IN NS
+SECTION AUTHORITY
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN NSEC3 1 1 0 - 5v13q049b9ittui4fbdtm34dtev47bgj NS DS RRSIG
+5V12UURISSGGLPAS52GE1V3R0V7KR5BS.com. 86400 IN RRSIG NSEC3 8 2 86400 20180802050635 20180726035635 46475 com. lF01rDWQAlm2v2Pfut1so+I6lSb4bLUA SXn21EAw0lSKAMPg5sOQHElu8EEcJInY zTFRpTOtCs6QGRlk//3+IpFK3nNunJrD GFS9A8XP5l4z8Z4/ZtQDsPhrfSZTizwA M7Un8JL9LniZ1ueo8409gEFbA8Xqw4sP ojwW8QIrt7Y=
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - ck0q1gin43n1arrc9osm6qpqr81h5m9a NS SOA RRSIG DNSKEY NSEC3PARAM
+CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20180731044815 20180724033815 46475 com. fM3ga8tkCx9ZVu/L/hQGXNcPxPVEGLfC gCgTtsJyUNefVSPOCMdqneA70UMVn06T bkGLDe85cA8ZViEnqc3iG6zhZIAwqas1 /5G509o4Ppf4lDI5CsH3iEhL5ofH+xfL t+wWEaTCLsUtmJN/VrSdqwpgJTNIJCcM QNF5A4J5btQ=
+nstld.com. 172800 IN NS av1.nstld.com.
+nstld.com. 172800 IN NS av2.nstld.com.
+nstld.com. 172800 IN NS av3.nstld.com.
+nstld.com. 172800 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 172800 IN A 192.42.177.30
+av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+av2.nstld.com. 172800 IN A 192.42.178.30
+av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+av3.nstld.com. 172800 IN A 192.82.133.30
+av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+av4.nstld.com. 172800 IN A 192.82.134.30
+av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. 172800 IN NS a.gtld-servers.net.
+net. 172800 IN NS b.gtld-servers.net.
+net. 172800 IN NS c.gtld-servers.net.
+net. 172800 IN NS d.gtld-servers.net.
+net. 172800 IN NS e.gtld-servers.net.
+net. 172800 IN NS f.gtld-servers.net.
+net. 172800 IN NS g.gtld-servers.net.
+net. 172800 IN NS h.gtld-servers.net.
+net. 172800 IN NS i.gtld-servers.net.
+net. 172800 IN NS j.gtld-servers.net.
+net. 172800 IN NS k.gtld-servers.net.
+net. 172800 IN NS l.gtld-servers.net.
+net. 172800 IN NS m.gtld-servers.net.
+net. 172800 IN RRSIG NS 8 1 172800 20180802053055 20180726042055 7934 net. KR3mBpGrNgRPgB/LuPhUC4sjhy9F+GPU BXemSi46ZJlIWc7sK40AQ2rccrU5MDSa puWa2pVvx74pSU2w3gqeW9RH9E3wNh9t toAxJYJBNvTlXv3D1qG0LIXEsold+cvQ 0VqnFhVePojFFtFqE19H5OHaa87LVUOB Ib0gTx7i73Y=
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 172800 IN NS a.gtld-servers.net.
+com. 172800 IN NS b.gtld-servers.net.
+com. 172800 IN NS c.gtld-servers.net.
+com. 172800 IN NS d.gtld-servers.net.
+com. 172800 IN NS e.gtld-servers.net.
+com. 172800 IN NS f.gtld-servers.net.
+com. 172800 IN NS g.gtld-servers.net.
+com. 172800 IN NS h.gtld-servers.net.
+com. 172800 IN NS i.gtld-servers.net.
+com. 172800 IN NS j.gtld-servers.net.
+com. 172800 IN NS k.gtld-servers.net.
+com. 172800 IN NS l.gtld-servers.net.
+com. 172800 IN NS m.gtld-servers.net.
+com. 172800 IN RRSIG NS 8 1 172800 20180731044815 20180724033815 46475 com. JgH5uVQ8OQlpGeX/UJQRQHvQJjXOlQoZ o87eG2e/PP2y1R5Td93n/BckALIzqxT9 UyZsfIKDbRbK5junHSwV8FL5HC+3Hj0K QX8k4+yrpeYB1EM/Upkb5Db1E6F4NCcs iUyDsLNUS3trL+X7/ohrTM3ScPKdMux0 a0kAzuZMWJk=
+SECTION ADDITIONAL
+a.gtld-servers.net. 172800 IN A 192.5.6.30
+a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+b.gtld-servers.net. 172800 IN A 192.33.14.30
+b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+c.gtld-servers.net. 172800 IN A 192.26.92.30
+c.gtld-servers.net. 172800 IN AAAA 2001:503:83eb::30
+d.gtld-servers.net. 172800 IN A 192.31.80.30
+d.gtld-servers.net. 172800 IN AAAA 2001:500:856e::30
+e.gtld-servers.net. 172800 IN A 192.12.94.30
+e.gtld-servers.net. 172800 IN AAAA 2001:502:1ca1::30
+f.gtld-servers.net. 172800 IN A 192.35.51.30
+f.gtld-servers.net. 172800 IN AAAA 2001:503:d414::30
+g.gtld-servers.net. 172800 IN A 192.42.93.30
+g.gtld-servers.net. 172800 IN AAAA 2001:503:eea3::30
+h.gtld-servers.net. 172800 IN A 192.54.112.30
+h.gtld-servers.net. 172800 IN AAAA 2001:502:8cc::30
+i.gtld-servers.net. 172800 IN A 192.43.172.30
+i.gtld-servers.net. 172800 IN AAAA 2001:503:39c1::30
+j.gtld-servers.net. 172800 IN A 192.48.79.30
+j.gtld-servers.net. 172800 IN AAAA 2001:502:7094::30
+k.gtld-servers.net. 172800 IN A 192.52.178.30
+k.gtld-servers.net. 172800 IN AAAA 2001:503:d2d::30
+l.gtld-servers.net. 172800 IN A 192.41.162.30
+l.gtld-servers.net. 172800 IN AAAA 2001:500:d937::30
+m.gtld-servers.net. 172800 IN A 192.55.83.30
+m.gtld-servers.net. 172800 IN AAAA 2001:501:b1f9::30
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "nstld.com.
+
+; Server names:
+; av1.nstld.com.
+; av2.nstld.com.
+; av3.nstld.com.
+; av4.nstld.com.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:500:124::30
+ ADDRESS 2001:500:126::30
+ ADDRESS 192.42.177.30
+ ADDRESS 192.82.134.30
+ ADDRESS 2001:500:127::30
+ ADDRESS 2001:500:125::30
+ ADDRESS 192.42.178.30
+ ADDRESS 192.82.133.30
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+a.gtld-servers.net. 86400 IN AAAA 2001:503:a83e::2:30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN A
+SECTION ANSWER
+j.gtld-servers.net. 86400 IN A 192.48.79.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+j.gtld-servers.net. IN AAAA
+SECTION ANSWER
+j.gtld-servers.net. 86400 IN AAAA 2001:502:7094::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN A
+SECTION ANSWER
+e.gtld-servers.net. 86400 IN A 192.12.94.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+e.gtld-servers.net. 86400 IN AAAA 2001:502:1ca1::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN A
+SECTION ANSWER
+i.gtld-servers.net. 86400 IN A 192.43.172.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+i.gtld-servers.net. IN AAAA
+SECTION ANSWER
+i.gtld-servers.net. 86400 IN AAAA 2001:503:39c1::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN A
+SECTION ANSWER
+d.gtld-servers.net. 86400 IN A 192.31.80.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.gtld-servers.net. IN AAAA
+SECTION ANSWER
+d.gtld-servers.net. 86400 IN AAAA 2001:500:856e::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN A
+SECTION ANSWER
+m.gtld-servers.net. 86400 IN A 192.55.83.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+m.gtld-servers.net. IN AAAA
+SECTION ANSWER
+m.gtld-servers.net. 86400 IN AAAA 2001:501:b1f9::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN A
+SECTION ANSWER
+h.gtld-servers.net. 86400 IN A 192.54.112.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+h.gtld-servers.net. IN AAAA
+SECTION ANSWER
+h.gtld-servers.net. 86400 IN AAAA 2001:502:8cc::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN A
+SECTION ANSWER
+c.gtld-servers.net. 86400 IN A 192.26.92.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.gtld-servers.net. IN AAAA
+SECTION ANSWER
+c.gtld-servers.net. 86400 IN AAAA 2001:503:83eb::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN A
+SECTION ANSWER
+l.gtld-servers.net. 86400 IN A 192.41.162.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+l.gtld-servers.net. IN AAAA
+SECTION ANSWER
+l.gtld-servers.net. 86400 IN AAAA 2001:500:d937::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN A
+SECTION ANSWER
+g.gtld-servers.net. 86400 IN A 192.42.93.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+g.gtld-servers.net. IN AAAA
+SECTION ANSWER
+g.gtld-servers.net. 86400 IN AAAA 2001:503:eea3::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN A
+SECTION ANSWER
+b.gtld-servers.net. 86400 IN A 192.33.14.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.gtld-servers.net. IN AAAA
+SECTION ANSWER
+b.gtld-servers.net. 86400 IN AAAA 2001:503:231d::2:30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN A
+SECTION ANSWER
+k.gtld-servers.net. 86400 IN A 192.52.178.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+k.gtld-servers.net. IN AAAA
+SECTION ANSWER
+k.gtld-servers.net. 86400 IN AAAA 2001:503:d2d::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN A
+SECTION ANSWER
+f.gtld-servers.net. 86400 IN A 192.35.51.30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN NS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN DS
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+f.gtld-servers.net. IN AAAA
+SECTION ANSWER
+f.gtld-servers.net. 86400 IN AAAA 2001:503:d414::30
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN A
+SECTION ANSWER
+av1.nstld.com. 300 IN A 192.42.177.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av1.nstld.com. IN AAAA
+SECTION ANSWER
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN A
+SECTION ANSWER
+av2.nstld.com. 300 IN A 192.42.178.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av2.nstld.com. IN AAAA
+SECTION ANSWER
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN A
+SECTION ANSWER
+av3.nstld.com. 300 IN A 192.82.133.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av3.nstld.com. IN AAAA
+SECTION ANSWER
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN A
+SECTION ANSWER
+av4.nstld.com. 300 IN A 192.82.134.30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN NS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN DS
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+av4.nstld.com. IN AAAA
+SECTION ANSWER
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+SECTION AUTHORITY
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN DNSKEY
+SECTION AUTHORITY
+gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2017061500 3600 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN DNSKEY
+SECTION AUTHORITY
+nstld.com. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2018062000 7200 900 1209600 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+SECTION ANSWER
+gtld-servers.net. 86400 IN NS av1.nstld.com.
+gtld-servers.net. 86400 IN NS av2.nstld.com.
+gtld-servers.net. 86400 IN NS av3.nstld.com.
+gtld-servers.net. 86400 IN NS av4.nstld.com.
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nstld.com. IN NS
+SECTION ANSWER
+nstld.com. 86400 IN NS av1.nstld.com.
+nstld.com. 86400 IN NS av2.nstld.com.
+nstld.com. 86400 IN NS av3.nstld.com.
+nstld.com. 86400 IN NS av4.nstld.com.
+SECTION ADDITIONAL
+av1.nstld.com. 300 IN A 192.42.177.30
+av1.nstld.com. 300 IN AAAA 2001:500:124::30
+av2.nstld.com. 300 IN A 192.42.178.30
+av2.nstld.com. 300 IN AAAA 2001:500:125::30
+av3.nstld.com. 300 IN A 192.82.133.30
+av3.nstld.com. 300 IN AAAA 2001:500:126::30
+av4.nstld.com. 300 IN A 192.82.134.30
+av4.nstld.com. 300 IN AAAA 2001:500:127::30
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "cz.
+
+; Server names:
+; b.ns.nic.cz.
+; d.ns.nic.cz.
+; a.ns.nic.cz.
+; c.ns.nic.cz.
+RANGE_BEGIN 0 1000
+ ADDRESS 2001:678:11::1
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:10::1
+ ADDRESS 2001:678:f::1
+ ADDRESS 194.0.12.1
+ ADDRESS 217.31.205.50
+ ADDRESS 2001:678:1::1
+ ADDRESS 194.0.14.1
+ ADDRESS 194.0.13.1
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root.cz. IN TYPE65535
+SECTION AUTHORITY
+root.cz. 3600 IN DS 21523 5 2 b73053df8858181e1940ee6160e75d5339103264b9e56a9a1ecd64adabb2e54f
+root.cz. 3600 IN NS ns.iinfo.cz.
+root.cz. 3600 IN NS ns6.adminit.cz.
+root.cz. 3600 IN RRSIG DS 13 2 3600 20180809020236 20180727093611 62295 cz. vQCM/GJGJky3kC1IcQZpFddgl0iTTvzq EPV6FPEttgS59K3TnAd9jHKqQrXi7cEW yQ8eO7k27czWZ1UyA4wM2g==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root.cz. IN DNSKEY
+SECTION AUTHORITY
+root.cz. 3600 IN DS 21523 5 2 b73053df8858181e1940ee6160e75d5339103264b9e56a9a1ecd64adabb2e54f
+root.cz. 3600 IN NS ns.iinfo.cz.
+root.cz. 3600 IN NS ns6.adminit.cz.
+root.cz. 3600 IN RRSIG DS 13 2 3600 20180809020236 20180727093611 62295 cz. vQCM/GJGJky3kC1IcQZpFddgl0iTTvzq EPV6FPEttgS59K3TnAd9jHKqQrXi7cEW yQ8eO7k27czWZ1UyA4wM2g==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN DS
+SECTION ANSWER
+root.cz. 3600 IN DS 21523 5 2 b73053df8858181e1940ee6160e75d5339103264b9e56a9a1ecd64adabb2e54f
+root.cz. 3600 IN RRSIG DS 13 2 3600 20180809020236 20180727093611 62295 cz. vQCM/GJGJky3kC1IcQZpFddgl0iTTvzq EPV6FPEttgS59K3TnAd9jHKqQrXi7cEW yQ8eO7k27czWZ1UyA4wM2g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN A
+SECTION AUTHORITY
+iinfo.cz. 3600 IN DS 21523 5 2 1f3ad3f9eace2aacf2cca9464e6642fe4bafce5a2817da25faef31e59c1fb74e
+iinfo.cz. 3600 IN NS ns.iinfo.cz.
+iinfo.cz. 3600 IN NS ns6.adminit.cz.
+iinfo.cz. 3600 IN RRSIG DS 13 2 3600 20180809121603 20180727063545 62295 cz. 7Y0LIeZxiEPiUqrOxA+SOmEdSCKjlehi hq+64xyIatKjPMWIK77Hh/rywef10beV NzWngBAx6lCKKj0jQJZn8Q==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN DNSKEY
+SECTION AUTHORITY
+iinfo.cz. 3600 IN DS 21523 5 2 1f3ad3f9eace2aacf2cca9464e6642fe4bafce5a2817da25faef31e59c1fb74e
+iinfo.cz. 3600 IN NS ns.iinfo.cz.
+iinfo.cz. 3600 IN NS ns6.adminit.cz.
+iinfo.cz. 3600 IN RRSIG DS 13 2 3600 20180809121603 20180727063545 62295 cz. 7Y0LIeZxiEPiUqrOxA+SOmEdSCKjlehi hq+64xyIatKjPMWIK77Hh/rywef10beV NzWngBAx6lCKKj0jQJZn8Q==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN DS
+SECTION ANSWER
+iinfo.cz. 3600 IN DS 21523 5 2 1f3ad3f9eace2aacf2cca9464e6642fe4bafce5a2817da25faef31e59c1fb74e
+iinfo.cz. 3600 IN RRSIG DS 13 2 3600 20180809121603 20180727063545 62295 cz. 7Y0LIeZxiEPiUqrOxA+SOmEdSCKjlehi hq+64xyIatKjPMWIK77Hh/rywef10beV NzWngBAx6lCKKj0jQJZn8Q==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+root.cz. IN A
+SECTION AUTHORITY
+root.cz. 3600 IN DS 21523 5 2 b73053df8858181e1940ee6160e75d5339103264b9e56a9a1ecd64adabb2e54f
+root.cz. 3600 IN NS ns.iinfo.cz.
+root.cz. 3600 IN NS ns6.adminit.cz.
+root.cz. 3600 IN RRSIG DS 13 2 3600 20180809020236 20180727093611 62295 cz. vQCM/GJGJky3kC1IcQZpFddgl0iTTvzq EPV6FPEttgS59K3TnAd9jHKqQrXi7cEW yQ8eO7k27czWZ1UyA4wM2g==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN A
+SECTION ANSWER
+nic.cz. 1800 IN A 217.31.205.50
+nic.cz. 1800 IN RRSIG A 13 2 1800 20180809122156 20180727064002 33494 nic.cz. p0uxXNMUIA1Zf6x/wqAdlNTSiLKrYs8P nNYlBe0SPQ8kTSGp49BlEaiy+B9ewcYp YbPTgjIpmvoMFeIOShUqgw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN DNSKEY
+SECTION ANSWER
+nic.cz. 1800 IN DNSKEY 256 3 13 a10sJr/8DQL8M1nLPzWfNoASGTsm4cKE P577ZX3c3lruiWZiUL78fUp0B2YJh8U9 DyiZsq18i6CM9eYTDVemzA==
+nic.cz. 1800 IN DNSKEY 257 3 13 LM4zvjUgZi2XZKsYooDE0HFYGfWp242f KB+O8sLsuox8S6MJTowY8lBDjZD7JKbm aNot3+1H8zU9TrDzWmmHwQ==
+nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20180809084714 20180727064002 61281 nic.cz. zotLLX9vPojjz21OSVfMGNspvWIVzzcW ZGJTTYOPlIHmrxAfE3GxHqV7QK8QO1W5 8rGsf9eebQw3+aJ+QGaNSA==
+nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20180810022459 20180727064002 33494 nic.cz. Ol85KlI1HVLYmVRmD2q0QBCqLZM5bUDr sECC2XN0gmtkbEPfI1HmhylvM9sur3kE 4kCxCKOAOCozExhDZtgV2w==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN DS
+SECTION ANSWER
+nic.cz. 3600 IN DS 61281 13 2 4104d40c8fe2030bf7a09a199fcf37b36f7ec8ddd16f5a84f2e61c248d3afd0f
+nic.cz. 3600 IN RRSIG DS 13 2 3600 20180805030735 20180722073550 62295 cz. iF+/iu01Jx4ls0md5OHm25GHCuaLkEmd U4N8pzQRw0WYTmP71ZuMEqd4e5KPeGS2 hLqh134rBssNSGagGazLNw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN A
+SECTION AUTHORITY
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7d87lcrpk6rt27kalh4sqt2rurekmmti.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN NS
+SECTION AUTHORITY
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.nic.cz. IN DS
+SECTION AUTHORITY
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 7dios8rb1rae9ugm9mubblifgm1pdql0
+7D87LCRPK6RT27KALH4SQT2RUREKMMTI.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809215742 20180727064002 33494 nic.cz. rGSwaAjCkz0BBxXgIv+Aq1rq/0gAnxkr Kx+eOR6h0iJDuUKoOogBdCD/XbNihwEr 3RjU+GlaxFjDVqb59fPE4g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN A
+SECTION ANSWER
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN NS
+SECTION AUTHORITY
+0PEAUR41J22DBMN7U135FQ4FTAUCUJHF.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0PEAUR41J22DBMN7U135FQ4FTAUCUJHF.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN DS
+SECTION AUTHORITY
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 0pr0tt6lsanr7gh1a7b43qfgll0ce3m7 A AAAA RRSIG
+0peaur41j22dbmn7u135fq4ftaucujhf.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809114457 20180727064002 33494 nic.cz. JVwfhA8YvpMShhq+ZkjOjPwGTwqw0U+7 vgK0Dt+RaW9KhFydcmohq0YLO207c0Sm UnYvWvDBSu+PHAOSL+Hgkw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+a.ns.nic.cz. IN AAAA
+SECTION ANSWER
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN A
+SECTION ANSWER
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+QO01QT0TH20IVKDANQ04F4G7V2EAJ3UR.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+QO01QT0TH20IVKDANQ04F4G7V2EAJ3UR.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN NS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+qo01qt0th20ivkdanq04f4g7v2eaj3ur.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN DS
+SECTION AUTHORITY
+QO01QT0TH20IVKDANQ04F4G7V2EAJ3UR.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 qrn61qbmo7ba8fufp4f15q8v233rd7s1 A AAAA RRSIG
+QO01QT0TH20IVKDANQ04F4G7V2EAJ3UR.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180810053445 20180727064002 33494 nic.cz. NPU0frxy34iY0tCv3Kvgew+zKlulbVF9 4y1Ml0ohKTr659CYBmX0y0C9Kt9vBfzz oDoYnIslWIwouM+u7186yw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+b.ns.nic.cz. IN AAAA
+SECTION ANSWER
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN A
+SECTION ANSWER
+c.ns.nic.cz. 1800 IN A 194.0.14.1
+c.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809230245 20180727064002 33494 nic.cz. vlIESyKHWExpovMlpGstO7X8Qk1YnJYc w8i6u28JjABo/2qa20s3wFXVgenziyEn 3VTsenqk6TTTi8RutaSmhA==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+ccueinlfu0s4ji2bgsprv30rcletotkq.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN NS
+SECTION AUTHORITY
+CCUEINLFU0S4JI2BGSPRV30RCLETOTKQ.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+CCUEINLFU0S4JI2BGSPRV30RCLETOTKQ.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN DS
+SECTION AUTHORITY
+CCUEINLFU0S4JI2BGSPRV30RCLETOTKQ.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 cem50d1dfrtnfqk2gdjo4405j9lvostb A AAAA RRSIG
+CCUEINLFU0S4JI2BGSPRV30RCLETOTKQ.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809155831 20180727064002 33494 nic.cz. 9kekS/gKCcN1h0h5JhWV+r+tq9p0RpY4 QXT8aVrcxaD0LbXR+tGc8laMcdxOmrbd kXCxuSt6FVPmueKlCZj1Kw==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+c.ns.nic.cz. IN AAAA
+SECTION ANSWER
+c.ns.nic.cz. 1800 IN AAAA 2001:678:11::1
+c.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809162728 20180727064002 33494 nic.cz. QRpoOGOlRV5YZkfr8rvOdGVZDqaFY4hV WsjpEl2cB1A9Rkw9/aX2toXhBoHTD7SX djgg2xiJzfNqtbBZNcpCrw==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN A
+SECTION ANSWER
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN DNSKEY
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN NS
+SECTION AUTHORITY
+VF5FP77TRRD78PATQGIAVTGGUM6CAJH9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+VF5FP77TRRD78PATQGIAVTGGUM6CAJH9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN DS
+SECTION AUTHORITY
+nic.cz. 1800 IN RRSIG SOA 13 2 1800 20180809064029 20180727064002 33494 nic.cz. fErlGowdWxs4Fouw84ToJt02qqX+qnY+ ieVzHu+w01jj0z3tMK8uLid0G04ZRLA2 CHnO0NKCAPfRVX+K5X+yFQ==
+nic.cz. 1800 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532677202 10800 3600 1209600 7200
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN NSEC3 1 0 10 6d024fda550cdd61 vg8e7aak4v5n8qc7q065is15lgndiok5 A AAAA RRSIG
+vf5fp77trrd78patqgiavtggum6cajh9.nic.cz. 7200 IN RRSIG NSEC3 13 3 7200 20180809144711 20180727064002 33494 nic.cz. qGRXKiwS8f+uEggVDFRUqt27euEuDV+T 2rrwkPqlCXvHiaKYI/P0eTkHe2SamKZT Fe2nbLIeuppDRzKo9DPx+g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+d.ns.nic.cz. IN AAAA
+SECTION ANSWER
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+SECTION AUTHORITY
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+adminit.cz. IN A
+SECTION AUTHORITY
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN NSEC3 1 0 10 10e824b15ffa0abd 9hfku52m3alurnj3eavfg458gn3418f6 NS
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN RRSIG NSEC3 13 2 900 20180804023913 20180721053541 62295 cz. rJ/nyZPYNwZxgjf7asIyASKmSX+dHt4S nIRGX3ROuIqHp5k9TVkeW0XxAOYgRpAJ Gm1C9gayX3JGikaPZeYXuQ==
+adminit.cz. 3600 IN NS ns.adminit.cz.
+adminit.cz. 3600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 3600 IN A 89.185.231.140
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR RD NOERROR
+SECTION QUESTION
+adminit.cz. IN DNSKEY
+SECTION AUTHORITY
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN NSEC3 1 0 10 10e824b15ffa0abd 9hfku52m3alurnj3eavfg458gn3418f6 NS
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN RRSIG NSEC3 13 2 900 20180804023913 20180721053541 62295 cz. rJ/nyZPYNwZxgjf7asIyASKmSX+dHt4S nIRGX3ROuIqHp5k9TVkeW0XxAOYgRpAJ Gm1C9gayX3JGikaPZeYXuQ==
+adminit.cz. 3600 IN NS ns.adminit.cz.
+adminit.cz. 3600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 3600 IN A 89.185.231.140
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+adminit.cz. IN DS
+SECTION AUTHORITY
+9hfklgvaurtdmcotlk0nh1nsrj43deje.cz. 900 IN NSEC3 1 0 10 10e824b15ffa0abd 9hfku52m3alurnj3eavfg458gn3418f6 NS
+9hfklgvaurtdmcotlk0nh1nsrj43deje.cz. 900 IN RRSIG NSEC3 13 2 900 20180804023913 20180721053541 62295 cz. rJ/nyZPYNwZxgjf7asIyASKmSX+dHt4S nIRGX3ROuIqHp5k9TVkeW0XxAOYgRpAJ Gm1C9gayX3JGikaPZeYXuQ==
+cz. 900 IN RRSIG SOA 13 1 3600 20180809150540 20180727150545 62295 cz. UEx5NuZh+/viBicZcEp4A+zBy93jYDYL TW5QjK7B1NW978PJ+KY1so6ErplYU51Q ME8009WszzXXObYR3+kwdw==
+cz. 900 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1532707545 900 300 604800 900
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 13 LSpU2wluEwbQLak1XGlg3KEYygKfIiAu Q8iJxgDDSKuPLIA/BIn40LC1nPzfLwoa zmL7sPJRetzjxwtErBLCmw==
+cz. 18000 IN DNSKEY 257 3 13 nqzH7xP1QU5UOVy/VvxFSlrB/XgX9JDJ zj51PzIj35TXjZTyalTlAT/f7PAfaSD5 mEG1N8Vk9NmI2nxgQqhzDQ==
+cz. 18000 IN RRSIG DNSKEY 13 1 18000 20180803000000 20180720000000 20237 cz. 2KI6brDc06P9gKXv+omp0NDfgxwMa2DD NnMNf7sE97/vGyCVdu0FkA3NdtpUs3UC RwD3Nb5+jh7O45sLwyu6yw==
+cz. 18000 IN RRSIG DNSKEY 13 1 18000 20180809010634 20180727150545 62295 cz. RlVw07JKCfgZCR2i09sgK7V43KFl7xpb Rzyg0Z9pD9nO/bvenRHgnpWUyFXM+1Ma kjVQkrHxmw5vVvDu8Er/fA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+root.cz. IN NS
+SECTION AUTHORITY
+root.cz. 3600 IN DS 21523 5 2 b73053df8858181e1940ee6160e75d5339103264b9e56a9a1ecd64adabb2e54f
+root.cz. 3600 IN NS ns.iinfo.cz.
+root.cz. 3600 IN NS ns6.adminit.cz.
+root.cz. 3600 IN RRSIG DS 13 2 3600 20180809020236 20180727093611 62295 cz. vQCM/GJGJky3kC1IcQZpFddgl0iTTvzq EPV6FPEttgS59K3TnAd9jHKqQrXi7cEW yQ8eO7k27czWZ1UyA4wM2g==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN NS
+SECTION AUTHORITY
+iinfo.cz. 3600 IN DS 21523 5 2 1f3ad3f9eace2aacf2cca9464e6642fe4bafce5a2817da25faef31e59c1fb74e
+iinfo.cz. 3600 IN NS ns.iinfo.cz.
+iinfo.cz. 3600 IN NS ns6.adminit.cz.
+iinfo.cz. 3600 IN RRSIG DS 13 2 3600 20180809121603 20180727063545 62295 cz. 7Y0LIeZxiEPiUqrOxA+SOmEdSCKjlehi hq+64xyIatKjPMWIK77Hh/rywef10beV NzWngBAx6lCKKj0jQJZn8Q==
+SECTION ADDITIONAL
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nic.cz. IN NS
+SECTION ANSWER
+nic.cz. 1800 IN NS a.ns.nic.cz.
+nic.cz. 1800 IN NS b.ns.nic.cz.
+nic.cz. 1800 IN NS d.ns.nic.cz.
+nic.cz. 1800 IN RRSIG NS 13 2 1800 20180809162254 20180727064002 33494 nic.cz. UOY4VdLFGrtMr22EaYes+1lbCAjFkhlt N5Q+0jpGucbyEFXrbxN4lFoQGpkX/+aU IWuKxWQI8VVmBKYLFBqSTw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 1800 IN A 194.0.12.1
+a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180810011809 20180727064002 33494 nic.cz. dlRCgD1PxXFCid2m1djf5URx+SbMMFtR aaeNB5G7jj9nqFv252cwhnOz7NLPqEBG yr+h8eEOqFKbV92ZfzygLw==
+a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809213334 20180727064002 33494 nic.cz. TQvt6opeQKp4V/VTYgEsw25AFAD3l9I6 UE5HhJUVGpnn8YzmZZs1QTNC1ZVf0MCs Flr3H2mTNm0r/Mb3m6Q+Yw==
+b.ns.nic.cz. 1800 IN A 194.0.13.1
+b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809112828 20180727064002 33494 nic.cz. GO5Wc2EWoV4yRvc3ktazw+lNZ7nGtR6S 4MsumQDKuADSGMLAhwm+htASUXxWZtV+ wWv74LD2g2cNjHpXHH1PBg==
+b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809130835 20180727064002 33494 nic.cz. sesuNekVgD2YLYl51sKLEYZeDmcxtQKl oFYnpXMUBVlqLTUGjn0RRcDvpJCxj/Ac isifFcEwvZ4W0B5/Ry1oVQ==
+d.ns.nic.cz. 1800 IN A 193.29.206.1
+d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20180809211641 20180727064002 33494 nic.cz. yLSqZnGG2G5+StFxEPpuV3I5slNKLF3o 7QahlX4mKk/iN74C7zh62cR+Q/s3SDxE fFF2M/owNT3T2wspOh4L/g==
+d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20180809225253 20180727064002 33494 nic.cz. Rm0kQ0l//ZsEDNi1M3Hmns4C2aWzcGI/ oUBN92egsGSvQ0EGVgZMWZp/Pun+Tgr/ AHHCsD4lW8ZNNxHh5CCtZQ==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR RD NOERROR
+SECTION QUESTION
+adminit.cz. IN NS
+SECTION AUTHORITY
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN NSEC3 1 0 10 10e824b15ffa0abd 9hfku52m3alurnj3eavfg458gn3418f6 NS
+9HFKLGVAURTDMCOTLK0NH1NSRJ43DEJE.cz. 900 IN RRSIG NSEC3 13 2 900 20180804023913 20180721053541 62295 cz. rJ/nyZPYNwZxgjf7asIyASKmSX+dHt4S nIRGX3ROuIqHp5k9TVkeW0XxAOYgRpAJ Gm1C9gayX3JGikaPZeYXuQ==
+adminit.cz. 3600 IN NS ns.adminit.cz.
+adminit.cz. 3600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 3600 IN A 89.185.231.140
+ns.iinfo.cz. 3600 IN A 91.213.160.5
+ns.iinfo.cz. 3600 IN AAAA 2001:67c:68::5
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 3600 IN NS a.ns.nic.cz.
+cz. 3600 IN NS b.ns.nic.cz.
+cz. 3600 IN NS c.ns.nic.cz.
+cz. 3600 IN NS d.ns.nic.cz.
+cz. 3600 IN RRSIG NS 13 1 3600 20180806013233 20180724063548 62295 cz. NYwbiceGXv+yKrhwwMPUO5WihpVt4nip dQpjpbVxJfUp4s+j5lOHsxcbCm4EEaBx x1+UXCK6Gnw9TCnaZaOiBQ==
+SECTION ADDITIONAL
+a.ns.nic.cz. 3600 IN A 194.0.12.1
+a.ns.nic.cz. 3600 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 3600 IN A 194.0.13.1
+b.ns.nic.cz. 3600 IN AAAA 2001:678:10::1
+d.ns.nic.cz. 3600 IN A 193.29.206.1
+d.ns.nic.cz. 3600 IN AAAA 2001:678:1::1
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "root.cz.
+
+; Server names:
+; ns6.adminit.cz.
+; ns.iinfo.cz.
+RANGE_BEGIN 0 1000
+ ADDRESS 46.101.163.95
+ ADDRESS 2001:67c:68::5
+ ADDRESS 91.213.160.5
+ ADDRESS 2a03:b0c0:3:d0::4c:2001
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN A
+SECTION ANSWER
+root.cz. 600 IN A 91.213.160.118
+root.cz. 600 IN RRSIG A 5 2 600 20190528123431 20180528123431 8130 root.cz. VbfAvnvnwmW04evIkjQTSeJN5J9Gtfum 2m13VOQCetKK01G4h5yS18qS5Yl4dZQh zftnYpQ1WJlkM6a3RXAgPw==
+SECTION AUTHORITY
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN AAAA
+SECTION ANSWER
+root.cz. 600 IN AAAA 2001:67c:68::76
+root.cz. 600 IN RRSIG AAAA 5 2 600 20190528123431 20180528123431 8130 root.cz. DUKH/DmP1XFWtKXHpCLJ49786krOOqO0 cIeEn+5sFsKx+ZS96WRyNpYyy0VQyvqm /D+y2HwZFpxRQMM3oAa+IQ==
+SECTION AUTHORITY
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN TYPE65535
+SECTION AUTHORITY
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.iinfo.cz. IN A
+SECTION ANSWER
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+SECTION AUTHORITY
+iinfo.cz. 600 IN NS ns.iinfo.cz.
+iinfo.cz. 600 IN NS ns6.adminit.cz.
+iinfo.cz. 600 IN RRSIG NS 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. pnOulEq9+lsY62m4J7rnsVL5JojezXVo BpX0aNCbJ/L4786RSE4no5KBZPfLvDns gmWQqT/WaMqYQTWQd/AfyA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.iinfo.cz. IN DNSKEY
+SECTION AUTHORITY
+iinfo.cz. 600 IN RRSIG SOA 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. j0qa9fTHdIXHZl72BcOfokHxk8LzxxpY x3LULH7xBsRMEGgBg9BYDYyJChyibjoo PSACAn8wfCATJbaST26lbQ==
+iinfo.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 1800 3600 604800 600
+ns.iinfo.cz. 600 IN NSEC ocelot.iinfo.cz. A AAAA RRSIG NSEC
+ns.iinfo.cz. 600 IN RRSIG NSEC 5 3 600 20190528123437 20180528123437 8130 iinfo.cz. s5VnlUMkC1MVFJooQRhhZ6abt5pBvvfl hiMWNjrE13MeSpdjwQho4aTTIlvV+ewR Vo5rr1uj+h3Z5TA2eClzWg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.iinfo.cz. IN NS
+SECTION AUTHORITY
+iinfo.cz. 600 IN RRSIG SOA 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. j0qa9fTHdIXHZl72BcOfokHxk8LzxxpY x3LULH7xBsRMEGgBg9BYDYyJChyibjoo PSACAn8wfCATJbaST26lbQ==
+iinfo.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 1800 3600 604800 600
+ns.iinfo.cz. 600 IN NSEC ocelot.iinfo.cz. A AAAA RRSIG NSEC
+ns.iinfo.cz. 600 IN RRSIG NSEC 5 3 600 20190528123437 20180528123437 8130 iinfo.cz. s5VnlUMkC1MVFJooQRhhZ6abt5pBvvfl hiMWNjrE13MeSpdjwQho4aTTIlvV+ewR Vo5rr1uj+h3Z5TA2eClzWg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.iinfo.cz. IN DS
+SECTION AUTHORITY
+iinfo.cz. 600 IN RRSIG SOA 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. j0qa9fTHdIXHZl72BcOfokHxk8LzxxpY x3LULH7xBsRMEGgBg9BYDYyJChyibjoo PSACAn8wfCATJbaST26lbQ==
+iinfo.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 1800 3600 604800 600
+ns.iinfo.cz. 600 IN NSEC ocelot.iinfo.cz. A AAAA RRSIG NSEC
+ns.iinfo.cz. 600 IN RRSIG NSEC 5 3 600 20190528123437 20180528123437 8130 iinfo.cz. s5VnlUMkC1MVFJooQRhhZ6abt5pBvvfl hiMWNjrE13MeSpdjwQho4aTTIlvV+ewR Vo5rr1uj+h3Z5TA2eClzWg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.iinfo.cz. IN AAAA
+SECTION ANSWER
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+SECTION AUTHORITY
+iinfo.cz. 600 IN NS ns.iinfo.cz.
+iinfo.cz. 600 IN NS ns6.adminit.cz.
+iinfo.cz. 600 IN RRSIG NS 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. pnOulEq9+lsY62m4J7rnsVL5JojezXVo BpX0aNCbJ/L4786RSE4no5KBZPfLvDns gmWQqT/WaMqYQTWQd/AfyA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN A
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+root.cz. 600 IN A 91.213.160.118
+root.cz. 600 IN RRSIG A 5 2 600 20190528123431 20180528123431 8130 root.cz. VbfAvnvnwmW04evIkjQTSeJN5J9Gtfum 2m13VOQCetKK01G4h5yS18qS5Yl4dZQh zftnYpQ1WJlkM6a3RXAgPw==
+SECTION AUTHORITY
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN DNSKEY
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+root.cz. 600 IN DNSKEY 256 3 5 AwEAAdX9H0Z0zTYKmh4NjmMARj16ThCn et8JUvivs+/+0QidPtCyW8ww0CUDyeqo rXOw0CI5otOccm2Es4v1SuFwMPs=
+root.cz. 600 IN DNSKEY 257 3 5 AwEAAd0gb4uhOraiCsHKE6JjR6HKOeRq Ry8Nxj4cg2AmKtaSF78rmvN27vtU8tKD LUGtiGgg33pcAOp+bvtd9ACu5s//Dch0 MHJpCDHFGoR4WVLbqBz9isTs3DLVLxWQ luMKeo/Kxed7sR3fMyPxAP1+FFi3esdX xANsVur/h9gGI5WVNtyXhq+qkWqLX0Y6 Q0jGzIuDrd5I4cVrWOei1OM4xV53Gh6D h98lptCA2ek35RuW3tPb7zHGXF3s+Baf gq7H8QJjnWmcFJh8ACdmbT63afQchYWT oyWdWUOeSpm/Uu0JOcbodAUD4m44P1Ed V1hzwwrHQIFUfdyA6He8mBPxS1k=
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 21523 root.cz. FifAZ5ePqDd5e5/oMiUeCZ2wA0OAqz03 I5ZkHb1OgKnZEpbI3yCHnF+3V4RS7ILu qJB/j04fXTiBwLsbBB+ZITUJ/PMA0VJ+ EA5hPJ0Cyei9cWKHw71peaLLCbH1T06g BntUshxxtKhGVjzhvaBqKw039HDu/2m3 RCj/pKSw71Lc+uLwR9lkaxmLeO9YfK/m 8SHdP6EOhadPIe4525iPGktWiLCDbdey DbdrlF8k1nXLtzWwFTwYl/L2n2NrJxSy GNJ7iHFzvfNCm6EWvhvdSijA9hSaFl2S D1IgD0kdix1F4wzRZpyzNlB2LsCYAH9q WkMyoKF0aH67YraYre44Nw==
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 8130 root.cz. GBADhpGGSxw8B+ke+K0rOAYwYL3KmweD j1PKaSleBOmftpFjb8gyvKX3LJgn66m/ UrKAOccPTriwkN+4ZJgq7g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN DS
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+SECTION AUTHORITY
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN A
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+root.cz. 600 IN A 91.213.160.118
+root.cz. 600 IN RRSIG A 5 2 600 20190528123431 20180528123431 8130 root.cz. VbfAvnvnwmW04evIkjQTSeJN5J9Gtfum 2m13VOQCetKK01G4h5yS18qS5Yl4dZQh zftnYpQ1WJlkM6a3RXAgPw==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN DNSKEY
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+root.cz. 600 IN DNSKEY 256 3 5 AwEAAdX9H0Z0zTYKmh4NjmMARj16ThCn et8JUvivs+/+0QidPtCyW8ww0CUDyeqo rXOw0CI5otOccm2Es4v1SuFwMPs=
+root.cz. 600 IN DNSKEY 257 3 5 AwEAAd0gb4uhOraiCsHKE6JjR6HKOeRq Ry8Nxj4cg2AmKtaSF78rmvN27vtU8tKD LUGtiGgg33pcAOp+bvtd9ACu5s//Dch0 MHJpCDHFGoR4WVLbqBz9isTs3DLVLxWQ luMKeo/Kxed7sR3fMyPxAP1+FFi3esdX xANsVur/h9gGI5WVNtyXhq+qkWqLX0Y6 Q0jGzIuDrd5I4cVrWOei1OM4xV53Gh6D h98lptCA2ek35RuW3tPb7zHGXF3s+Baf gq7H8QJjnWmcFJh8ACdmbT63afQchYWT oyWdWUOeSpm/Uu0JOcbodAUD4m44P1Ed V1hzwwrHQIFUfdyA6He8mBPxS1k=
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 21523 root.cz. FifAZ5ePqDd5e5/oMiUeCZ2wA0OAqz03 I5ZkHb1OgKnZEpbI3yCHnF+3V4RS7ILu qJB/j04fXTiBwLsbBB+ZITUJ/PMA0VJ+ EA5hPJ0Cyei9cWKHw71peaLLCbH1T06g BntUshxxtKhGVjzhvaBqKw039HDu/2m3 RCj/pKSw71Lc+uLwR9lkaxmLeO9YfK/m 8SHdP6EOhadPIe4525iPGktWiLCDbdey DbdrlF8k1nXLtzWwFTwYl/L2n2NrJxSy GNJ7iHFzvfNCm6EWvhvdSijA9hSaFl2S D1IgD0kdix1F4wzRZpyzNlB2LsCYAH9q WkMyoKF0aH67YraYre44Nw==
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 8130 root.cz. GBADhpGGSxw8B+ke+K0rOAYwYL3KmweD j1PKaSleBOmftpFjb8gyvKX3LJgn66m/ UrKAOccPTriwkN+4ZJgq7g==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN DS
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN AAAA
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+root.cz. 600 IN AAAA 2001:67c:68::76
+root.cz. 600 IN RRSIG AAAA 5 2 600 20190528123431 20180528123431 8130 root.cz. DUKH/DmP1XFWtKXHpCLJ49786krOOqO0 cIeEn+5sFsKx+ZS96WRyNpYyy0VQyvqm /D+y2HwZFpxRQMM3oAa+IQ==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN AAAA
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+root.cz. 600 IN AAAA 2001:67c:68::76
+root.cz. 600 IN RRSIG AAAA 5 2 600 20190528123431 20180528123431 8130 root.cz. DUKH/DmP1XFWtKXHpCLJ49786krOOqO0 cIeEn+5sFsKx+ZS96WRyNpYyy0VQyvqm /D+y2HwZFpxRQMM3oAa+IQ==
+SECTION AUTHORITY
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN TYPE65535
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+SECTION AUTHORITY
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN TYPE65535
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns6.adminit.cz. IN A
+SECTION ANSWER
+ns6.adminit.cz. 600 IN A 46.101.163.95
+SECTION AUTHORITY
+adminit.cz. 600 IN NS ns.adminit.cz.
+adminit.cz. 600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 600 IN A 89.185.231.140
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns6.adminit.cz. IN DNSKEY
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns6.adminit.cz. IN NS
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns6.adminit.cz. IN DS
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns6.adminit.cz. IN AAAA
+SECTION ANSWER
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+SECTION AUTHORITY
+adminit.cz. 600 IN NS ns.adminit.cz.
+adminit.cz. 600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 600 IN A 89.185.231.140
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.adminit.cz. IN A
+SECTION ANSWER
+ns.adminit.cz. 600 IN A 89.185.231.140
+SECTION AUTHORITY
+adminit.cz. 600 IN NS ns.adminit.cz.
+adminit.cz. 600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.adminit.cz. IN DNSKEY
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.adminit.cz. IN NS
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.adminit.cz. IN DS
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns.adminit.cz. IN AAAA
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN DNSKEY
+SECTION ANSWER
+root.cz. 600 IN DNSKEY 256 3 5 AwEAAdX9H0Z0zTYKmh4NjmMARj16ThCn et8JUvivs+/+0QidPtCyW8ww0CUDyeqo rXOw0CI5otOccm2Es4v1SuFwMPs=
+root.cz. 600 IN DNSKEY 257 3 5 AwEAAd0gb4uhOraiCsHKE6JjR6HKOeRq Ry8Nxj4cg2AmKtaSF78rmvN27vtU8tKD LUGtiGgg33pcAOp+bvtd9ACu5s//Dch0 MHJpCDHFGoR4WVLbqBz9isTs3DLVLxWQ luMKeo/Kxed7sR3fMyPxAP1+FFi3esdX xANsVur/h9gGI5WVNtyXhq+qkWqLX0Y6 Q0jGzIuDrd5I4cVrWOei1OM4xV53Gh6D h98lptCA2ek35RuW3tPb7zHGXF3s+Baf gq7H8QJjnWmcFJh8ACdmbT63afQchYWT oyWdWUOeSpm/Uu0JOcbodAUD4m44P1Ed V1hzwwrHQIFUfdyA6He8mBPxS1k=
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 21523 root.cz. FifAZ5ePqDd5e5/oMiUeCZ2wA0OAqz03 I5ZkHb1OgKnZEpbI3yCHnF+3V4RS7ILu qJB/j04fXTiBwLsbBB+ZITUJ/PMA0VJ+ EA5hPJ0Cyei9cWKHw71peaLLCbH1T06g BntUshxxtKhGVjzhvaBqKw039HDu/2m3 RCj/pKSw71Lc+uLwR9lkaxmLeO9YfK/m 8SHdP6EOhadPIe4525iPGktWiLCDbdey DbdrlF8k1nXLtzWwFTwYl/L2n2NrJxSy GNJ7iHFzvfNCm6EWvhvdSijA9hSaFl2S D1IgD0kdix1F4wzRZpyzNlB2LsCYAH9q WkMyoKF0aH67YraYre44Nw==
+root.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123431 20180528123431 8130 root.cz. GBADhpGGSxw8B+ke+K0rOAYwYL3KmweD j1PKaSleBOmftpFjb8gyvKX3LJgn66m/ UrKAOccPTriwkN+4ZJgq7g==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN DNSKEY
+SECTION ANSWER
+iinfo.cz. 600 IN DNSKEY 256 3 5 AwEAAdX9H0Z0zTYKmh4NjmMARj16ThCn et8JUvivs+/+0QidPtCyW8ww0CUDyeqo rXOw0CI5otOccm2Es4v1SuFwMPs=
+iinfo.cz. 600 IN DNSKEY 257 3 5 AwEAAd0gb4uhOraiCsHKE6JjR6HKOeRq Ry8Nxj4cg2AmKtaSF78rmvN27vtU8tKD LUGtiGgg33pcAOp+bvtd9ACu5s//Dch0 MHJpCDHFGoR4WVLbqBz9isTs3DLVLxWQ luMKeo/Kxed7sR3fMyPxAP1+FFi3esdX xANsVur/h9gGI5WVNtyXhq+qkWqLX0Y6 Q0jGzIuDrd5I4cVrWOei1OM4xV53Gh6D h98lptCA2ek35RuW3tPb7zHGXF3s+Baf gq7H8QJjnWmcFJh8ACdmbT63afQchYWT oyWdWUOeSpm/Uu0JOcbodAUD4m44P1Ed V1hzwwrHQIFUfdyA6He8mBPxS1k=
+iinfo.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123437 20180528123437 21523 iinfo.cz. gK/B0ceILXhEGpXHL9o/0aAAw9FWKa8T 2775dB9FlzpfQsmmhedDY+swXpYpieXp nHtchHe0n0AiWjmQ4pYQ9f+ABX9/1w6e kmsQEQ4BH7oD2iHWFzCwEnjbGfE78nVx rcGyaq6VQ50yoRFn6KdVSvydtHtR7jtN 4cAzz9z6AgL41goi89SEUMB6XtA1puKZ yOq9QXXQ31bU/3pb9oitGIh8hrpaPnpC APLHMdNo9ixQCzdOY4zHXOYRoSkeoh0E skWuBDw9xaA3PpiAhW1YuWRqsM5ogn2T wF4NCOhQD8JP7o8jbCS75+KySaWILznl vapvUu8P//OVfLvb3KmQBA==
+iinfo.cz. 600 IN RRSIG DNSKEY 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. uFrBPh3dsFIbmOE5m9VuHeuxhPEnNQE0 DwoeoZsre7RwSPWtqEvENypioV1goDIf 0cZmsNrK5Q5lgIBOo4rKug==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+adminit.cz. IN DNSKEY
+SECTION AUTHORITY
+adminit.cz. 600 IN SOA ns.adminit.cz. hostmaster.adminit.cz. 2018072003 10800 3600 604800 600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN NS
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+random1.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+blog.root.cz. IN NS
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+root.cz. IN NS
+SECTION ANSWER
+root.cz. 600 IN NS ns.iinfo.cz.
+root.cz. 600 IN NS ns6.adminit.cz.
+root.cz. 600 IN RRSIG NS 5 2 600 20190528123431 20180528123431 8130 root.cz. SXqkv2rcKBDAYKzsn3FL+2djE4ob+BbJ OjNcHcihIQFaCLHfvTpmh7bKDyDrtyBj xAB/EPVJWdn1Gvu8PUKGOA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+iinfo.cz. IN NS
+SECTION ANSWER
+iinfo.cz. 600 IN NS ns.iinfo.cz.
+iinfo.cz. 600 IN NS ns6.adminit.cz.
+iinfo.cz. 600 IN RRSIG NS 5 2 600 20190528123437 20180528123437 8130 iinfo.cz. pnOulEq9+lsY62m4J7rnsVL5JojezXVo BpX0aNCbJ/L4786RSE4no5KBZPfLvDns gmWQqT/WaMqYQTWQd/AfyA==
+SECTION ADDITIONAL
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ns6.adminit.cz. 600 IN A 46.101.163.95
+ns6.adminit.cz. 600 IN AAAA 2a03:b0c0:3:d0::4c:2001
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+adminit.cz. IN NS
+SECTION ANSWER
+adminit.cz. 600 IN NS ns.adminit.cz.
+adminit.cz. 600 IN NS ns.iinfo.cz.
+SECTION ADDITIONAL
+ns.adminit.cz. 600 IN A 89.185.231.140
+ns.iinfo.cz. 360 IN A 91.213.160.5
+ns.iinfo.cz. 360 IN AAAA 2001:67c:68::5
+ns.iinfo.cz. 360 IN RRSIG A 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. Rf//ObuX0E/s5d7Z1Ld0MjHa+q+tVdl8 GwY4pZTW7DHRivIEij+owDnmDNID62EB MpURuInEPV5FaF/9sT6X8A==
+ns.iinfo.cz. 360 IN RRSIG AAAA 5 3 360 20190528123437 20180528123437 8130 iinfo.cz. q5hoFF0ldADkVxxKTgXgh3RUL+JseejX tcUvRqaD+VTwbJO5J0Kl+tJufKw7tRVt EJP8opneZsIsKamQhdWrDg==
+ENTRY_END
+
+
+RANGE_END
+
+
+; Scope "hm.
+
+; Server names:
+; ns1.registry.hm.
+; ns2.registry.hm.
+; ns3.registry.hm.
+RANGE_BEGIN 0 1000
+ ADDRESS 208.70.79.24
+ ADDRESS 208.70.79.25
+ ADDRESS 128.199.180.188
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN A
+SECTION AUTHORITY
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN DS
+SECTION AUTHORITY
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN AAAA
+SECTION AUTHORITY
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+registry.hm. IN A
+SECTION ANSWER
+registry.hm. 86400 IN A 208.70.79.55
+SECTION AUTHORITY
+registry.hm. 86400 IN NS ns1.registry.hm.
+registry.hm. 86400 IN NS ns2.registry.hm.
+registry.hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+registry.hm. IN DNSKEY
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+registry.hm. IN DS
+SECTION AUTHORITY
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns1.registry.hm. IN A
+SECTION ANSWER
+ns1.registry.hm. 86400 IN A 208.70.79.25
+SECTION AUTHORITY
+registry.hm. 86400 IN NS ns1.registry.hm.
+registry.hm. 86400 IN NS ns2.registry.hm.
+registry.hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns1.registry.hm. IN DNSKEY
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns1.registry.hm. IN NS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns1.registry.hm. IN DS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns1.registry.hm. IN AAAA
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN SOA
+SECTION ANSWER
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+SECTION AUTHORITY
+hm. 86400 IN NS ns1.registry.hm.
+hm. 86400 IN NS ns2.registry.hm.
+hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns2.registry.hm. IN A
+SECTION ANSWER
+ns2.registry.hm. 86400 IN A 208.70.79.24
+SECTION AUTHORITY
+registry.hm. 86400 IN NS ns1.registry.hm.
+registry.hm. 86400 IN NS ns2.registry.hm.
+registry.hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns2.registry.hm. IN DNSKEY
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns2.registry.hm. IN NS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns2.registry.hm. IN DS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns2.registry.hm. IN AAAA
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns3.registry.hm. IN A
+SECTION ANSWER
+ns3.registry.hm. 86400 IN A 128.199.180.188
+SECTION AUTHORITY
+registry.hm. 86400 IN NS ns1.registry.hm.
+registry.hm. 86400 IN NS ns2.registry.hm.
+registry.hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns3.registry.hm. IN DNSKEY
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns3.registry.hm. IN NS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns3.registry.hm. IN DS
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+ns3.registry.hm. IN AAAA
+SECTION AUTHORITY
+registry.hm. 3600 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2015072302 10800 3600 604800 3600
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH qname qtype
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN DNSKEY
+SECTION AUTHORITY
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+registry.hm. IN NS
+SECTION ANSWER
+registry.hm. 86400 IN NS ns1.registry.hm.
+registry.hm. 86400 IN NS ns2.registry.hm.
+registry.hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+hm. IN NS
+SECTION ANSWER
+hm. 86400 IN NS ns1.registry.hm.
+hm. 86400 IN NS ns2.registry.hm.
+hm. 86400 IN NS ns3.registry.hm.
+SECTION ADDITIONAL
+ns1.registry.hm. 86400 IN A 208.70.79.25
+ns2.registry.hm. 86400 IN A 208.70.79.24
+ns3.registry.hm. 86400 IN A 128.199.180.188
+ENTRY_END
+
+
+RANGE_END
+
+
+
+; hm. DS in the root does not exist
+STEP 100 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+hm. IN DS
+ENTRY_END
+
+STEP 101 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+hm. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+hm. 86400 IN NSEC hn. NS RRSIG NSEC
+hm. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . vI+rf8FDWlQOpAPeJTvoMH7bceC0qe2U hzdXApcCQK50pacs356TAcnKRKsNu+wa qR0+pM51vnG1AT+pPSK0M70soXrbh8uI TfFMV6u+/6qgU9TzzzQk49UK4Ww6m4l6 uh7/I302reJjTsc9mpCrjkRX7lk96c31 xzcYMlbADfzQsCfofoZDw7bS45mY6nRH /zTNUuEtFZGef0XtkNK9Op32Sf7Qqqqu YuzKBWa1irDaYCCLeyaqSmXQDzl7xKQa szrWtZeA1pwxJ2KKzCfuaYsRk/R6INLv i4tfJ73oKHl7nhKxH/K1fWUrWTuxkR1q R1zQb7VOg0Jf9GUqXxPVXg==
+ENTRY_END
+
+; negative cache in parent zone must not mask data in child
+STEP 102 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+hm. IN SOA
+ENTRY_END
+
+STEP 103 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+hm. IN SOA
+SECTION ANSWER
+hm. 86400 IN SOA ns1.registry.hm. hostmaster.registry.hm. 2018072709 10800 600 6048000 86400
+ENTRY_END
+
+
+; fill new NSEC interval sk..ski
+STEP 200 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sk2. IN DS
+ENTRY_END
+
+STEP 201 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question authority
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+sk2. IN DS
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+; deeper answers for interval sk..ski must be generated from cache
+STEP 202 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deep.sk2. IN A
+ENTRY_END
+
+STEP 203 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question authority
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+deep.sk2. IN A
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+STEP 204 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+deeper.deep.sk2. IN DS
+ENTRY_END
+
+STEP 205 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question authority
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+deeper.deep.sk2. IN DS
+SECTION AUTHORITY
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180809050000 20180727040000 41656 . CU1vfnY07l8A4bd60jFERRzilD9G1Glp Cx5l/o65fIh2fvCTt/pn4C1W1MfpHIOv j23gN/HS3m64+UE6lYPbJlrOcCLOslgK C+8tfmqWjDbI2C5jnDK0shibLIU2MW3L +0PxOZWOeU2a6XRUYYkqyI9jpfQIEDcZ fuQWiBXOtneXsLKNfQf4YxwC+WCxHGPu mc1g9hza83iziIfgmzxFU5Hg05HjAnni Uw4PL8sNrAZsv4sRZqtfoM6KHo84RCP+ Y2pIR97bPW0dspAtTjD9WAbTz0DpvC3f o3flnVlnWxdJhDEBRASUzAGc2d4FwzPO JdbCJNde9bc9VKSx1jEHpQ==
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+; sk. DS record does not exist in root and this answer must be synthesized from cache as well
+STEP 206 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sk. IN DS
+ENTRY_END
+
+STEP 207 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sk. IN DS
+SECTION AUTHORITY
+. 86400 IN RRSIG SOA 8 0 86400 20180809050000 20180727040000 41656 . zo+cNHA1N9Av53qwpB/bCmnTxAWj6ubo 58W4VkEPk9jzrOKvCm9dVJv7P+JJOX5C t5yx4zch+DBRSRR1U9mmrbegEX4hXtec L3Ev9ZpxYAYUFd7gQ/oM5ZyrUZ08wLYg pYV6vE4qYdxP58dtknbpGUQKz4H3l0SQ eWoSyhOtYK9nNovCNN0swXdkmogEhDxP gY1nhEZiLXFH8W8/G96IgAa2hineMnqV 0z8/K2m7EGjwszDOyCD05Z77cMAryvjL X6Jm7I83+D8UwtfAck8ZGDJFz3l+w08G oeB9ntD1OicidpLtHmeSsN+1nuEL3s1M U47kwIJMAHu8bcyvm4HGRw==
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018072700 1800 900 604800 86400
+sk. 86400 IN NSEC ski. NS RRSIG NSEC
+sk. 86400 IN RRSIG NSEC 8 1 86400 20180809050000 20180727040000 41656 . Z7ihB8GIbqYBTvBPWxq22UkxSfJf/1I5 eIQ0E3cCVB+srJs2mECa3FmiPkzaYEZv mGzDNGlr5T2BHunJHWVED3gN6Y9Mn0YD 8v+0sIfPTTO74uWxHZFQsudZSzBqWaEI S2zHlM8VTiE6/x6QrAyDNIdjLSI5563X q/qVCsYxx10bRKIog4g73ZwBvlmwd1wa Rd/IIaEDCRO/ed6yFMOL5dhhMERrcJVY HdbNCpSb27LT4HFoqXtBMt1Z8VJVqDI3 NMojUq7a0JWMrFhBEiNwgNJ5xHCiiDuc 4nvszt1wiZAebsr8Qcniy4PrDDs+3XOg lBDRhozaOZYS436/Bs27Xw==
+ENTRY_END
+
+
+; ask for type which does not exist
+STEP 400 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root.cz. IN TYPE65535
+ENTRY_END
+
+STEP 401 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root.cz. IN TYPE65535
+ENTRY_END
+
+; ask for another type which does not exist
+; answer must be generated from cache (is not present in any RANGE)
+STEP 402 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+root.cz. IN TYPE65530
+ENTRY_END
+
+STEP 403 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+root.cz. IN TYPE65530
+SECTION ANSWER
+SECTION AUTHORITY
+root.cz. 600 IN NSEC 10.root.cz. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY
+root.cz. 600 IN RRSIG NSEC 5 2 600 20190528123431 20180528123431 8130 root.cz. zyNxcRCooKSKBrLYS+o8ZXZXqN+OakCK 3/A06vZsprPaKyy1Q67Zu7J8I1WW0faX SB5Zvv7ka+TeoE4HfYZmQQ==
+root.cz. 600 IN RRSIG SOA 5 2 600 20190528123431 20180528123431 8130 root.cz. BEf0O/YUhGy6Xoh15SYLu5K/BKmlOW/x g39vk0ficFELb7FYzHUEKghXaSCAtjzL 41ZhRQqB6yHXMBSxujHxeA==
+root.cz. 600 IN SOA ns.iinfo.cz. hostmaster.iinfo.cz. 2018052801 86400 3600 3600000 600
+ENTRY_END
+
+; synthesized answer must not block other data at the same node
+STEP 405 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root.cz. IN A
+ENTRY_END
+
+STEP 406 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root.cz. IN A
+SECTION ANSWER
+root.cz. 600 IN A 91.213.160.118
+ENTRY_END
+
+; fill cache with *.blog.root.cz. CNAME
+STEP 501 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+random1.blog.root.cz. IN A
+ENTRY_END
+
+STEP 502 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN A
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+root.cz. 600 IN A 91.213.160.118
+ENTRY_END
+
+; test final NODATA answer from wildcard
+STEP 503 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+random1.blog.root.cz. IN TYPE65535
+ENTRY_END
+
+STEP 504 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+random1.blog.root.cz. IN TYPE65535
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+random1.blog.root.cz. 600 IN CNAME blog.root.cz.
+ENTRY_END
+
+; complete answer must be synthesized from wildcard
+STEP 505 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+random2.blog.root.cz. IN A
+ENTRY_END
+
+STEP 506 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+random2.blog.root.cz. IN A
+SECTION ANSWER
+blog.root.cz. 600 IN CNAME root.cz.
+blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. DSHP4iTt49vRSsPjtBBxXj876UXSZukv 5Uko/B3GfLujWV/fOwZIQaHJTmfwzmT0 l4I+FSGkhwwHRQpCpqvzOQ==
+random2.blog.root.cz. 600 IN CNAME blog.root.cz.
+random2.blog.root.cz. 600 IN RRSIG CNAME 5 3 600 20190528123431 20180528123431 8130 root.cz. db6OwEqbgywxPO8tTqz/nh9yj1mY/hYZ KmHhH4HH1v2eH1wIU/S1jvD1ZHGAssVw xbh9LoY0x0mSPdCciX1WvQ==
+root.cz. 600 IN A 91.213.160.118
+root.cz. 600 IN RRSIG A 5 2 600 20190528123431 20180528123431 8130 root.cz. VbfAvnvnwmW04evIkjQTSeJN5J9Gtfum 2m13VOQCetKK01G4h5yS18qS5Yl4dZQh zftnYpQ1WJlkM6a3RXAgPw==
+SECTION AUTHORITY
+*.blog.root.cz. 600 IN NSEC blog-beta.root.cz. CNAME RRSIG NSEC
+*.blog.root.cz. 600 IN RRSIG NSEC 5 3 600 20190528123431 20180528123431 8130 root.cz. dq9cWL5b4ogXMDfVhICOc6uBAuV8YnlA +eNB09aH8vjwJlNtiKPZknER3foS8bVx OEhJrYXGtldnMFP3rLlcKA==
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_name_error_response-part2.rpl b/tests/deckard/sets/resolver/nsec_name_error_response-part2.rpl
new file mode 100644
index 0000000..af91839
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_name_error_response-part2.rpl
@@ -0,0 +1,227 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 17272 13 4 B87AD8C76DC2244E7AA57285057BF533F2E248CC8D7E1A071D8A3837A711A5EA705C4707E6E8911DA653BE1AE019927B"
+ val-override-timestamp: "1442323400"
+ do-not-query-localhost: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 127.0.0.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC name error responses.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+. 3600 IN RRSIG NS 13 0 3600 20151014142315 20150914142315 17272 . aEIYUS4S8Hd7vAVYvHwFyV97lKx4xt2PgAUbM4A7JUXHkTJDHUQEDVQh LWGxK6e+AUeuq4qlDo4vSz3IedmOBQ==
+SECTION ADDITIONAL
+ns. 3600 IN A 127.0.0.1
+ns. 3600 IN RRSIG A 13 1 3600 20151014142315 20150914142315 17272 . 27h0pFJyb5t/2cZsFjynp0TRIdUlQwPYcAwCer2UbXTiBBaD8n15hfh8 PFU0if8X0ikqHusz6rCNTx/aBraYdQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600 IN DNSKEY 256 3 13 qKlBZ0TvdY8C8+7bTcdnQdrLZxEwvxEwlGmIOTd/ccL5Jiei1whNktoE /Qzo1lJ0cXfVssy4EVMaqEdzIa+pkA==
+. 3600 IN RRSIG DNSKEY 13 0 3600 20151014142315 20150914142315 17272 . FaY+kslqSPIRZsk65z8SrROt7kfx+RGUEBGbVgLQxKruJxc9+MMrl4e4 +RefYIlwpecj4jXwb75RTbT0g7OGGg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN MX
+SECTION AUTHORITY
+example. 3600 IN NS ns.example.
+example. 3600 IN DS 11225 13 4 B4BDAB0B3751300BFB9D0D240649279B4BA0E67A308E1B0BFE2931D9 47F7FD71A2BD807D84CDE24286D955A35752484F
+example. 3600 IN RRSIG DS 13 1 3600 20151014143533 20150914143533 17272 . b0+fXKmsBBXkzf+Myr5eRsXWDvY75oMlr4Yi5j+3iF7cOviVGKz3Dw8u bfKW+OmyHiuTeL71gez/84P+vHEvHA==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.2
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+example. 3600 IN NS ns.example.
+example. 3600 IN RRSIG NS 13 1 3600 20151014143225 20150914143225 11225 example. C6KOyVJzeRh/3KL9BxSVOVZN0RIyBhlBmmmnVEFT5qPUrn3m5FjcIBtI hi7cAl2FeY1rqstztvKAY6UOBE0kGQ==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ns.example. 3600 IN RRSIG A 13 2 3600 20151014143225 20150914143225 11225 example. fM/mwUOtyIbKTxgxaekZf5A8kV3qYIFADtvhcQi0TUh09nfkHQtUqhew zVBXCEtjKMnYFvNhWF6PyiirtOeM8w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. 3600 IN DNSKEY 256 3 13 d9Qb4Tj90Y2cvdWcZfu45clfoLKqGbJn2vQKqZv07nc4FMf2oRkrNXtP fixVTLfbbWAFtbbFf3mhCNUsetRUVQ==
+example. 3600 IN RRSIG DNSKEY 13 1 3600 20151015124839 20150915124839 11225 example. 4DemFjvys9Gfq+gG1i8IB6GPBUw9lIv3F082JwW7O8tqNIn45n2z14gg ieeJTRhU9xXOVIfj6amITZWbjvGyFA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN DS 54343 13 4 90ABD4FB9F053CF67F6D838DD2437FB16104B8BF127319706223004F 2ED72AF2872B4E507EB483A303BF60BF08C87364
+nsec.example. 3600 IN RRSIG DS 13 2 3600 20151015124611 20150915124611 11225 example. HYzlEdyYugggsEwUVyyY4XHFVUZZ8yiIh4vnuViGBQQJP+yryYh1aLyN ap2Q51nkmSG1fXDb2IySiAYuqUJyLw==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ENTRY_END
+
+RANGE_END
+
+; ns.nsec.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.3
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION ANSWER
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN RRSIG NS 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 6s75LEuylIKAxqAbcPmmnkOMC7jxF6cPZGW5EFbhOOeR63ENyh642GE1 71WtJc7Ta4Y/PsnAT+/dTv8NSTDCHQ==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ns.nsec.example. 3600 IN RRSIG A 13 3 3600 20151015124917 20150915124917 54343 nsec.example. oJpF87bjXR0DjIoNvEAo+Wu+p9jF+URX5lxi+g53OFCX1Q1lxqj5ujGd KOPsNAbKvTCsoFFW4tQyhCYJYD1HlQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN DNSKEY
+SECTION ANSWER
+nsec.example. 3600 IN DNSKEY 256 3 13 HA6nKf+X7/mYkmmRO8qS2tIKT0B60P7COAiRs25xKs/rAP+tDtGWkrkG NQx2D3ajccC9whjRaKz2JVS3ItTFQg==
+nsec.example. 3600 IN RRSIG DNSKEY 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 965Mfxs1QtgxwzyhfxXyKyOZ9iT1DXpvypBBR10sLyjHe/w7cRhgcyev Cza6K+2jJwHJBmbknc3Qhi+1dd+AJw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+aaa.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+mail.nsec.example. 3600 IN NSEC multiple.nsec.example. A AAAA RRSIG NSEC
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+mail.nsec.example. 3600 IN RRSIG NSEC 13 3 3600 20151015124917 20150915124917 54343 nsec.example. kM+Z63RDn377szwbOqPPinkH98BuCljY7hoeM8jGJcnQ90fA3NFi72Jg k/0T1bo4r0cNMn6lm9OUotawa6BOqw==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing1.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing2.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+mail.nsec.example. 3600 IN NSEC multiple.nsec.example. A AAAA RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+mail.nsec.example. 3600 IN RRSIG NSEC 13 3 3600 20151015124917 20150915124917 54343 nsec.example. kM+Z63RDn377szwbOqPPinkH98BuCljY7hoeM8jGJcnQ90fA3NFi72Jg k/0T1bo4r0cNMn6lm9OUotawa6BOqw==
+ENTRY_END
+
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+
+
+STEP 5 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing1.nsec.example. IN MX
+ENTRY_END
+
+STEP 6 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing1.nsec.example. IN MX
+SECTION AUTHORITY
+ENTRY_END
+
+STEP 7 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing2.nsec.example. IN MX
+ENTRY_END
+
+STEP 8 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing2.nsec.example. IN MX
+SECTION AUTHORITY
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_name_error_response.rpl b/tests/deckard/sets/resolver/nsec_name_error_response.rpl
new file mode 100644
index 0000000..80deb25
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_name_error_response.rpl
@@ -0,0 +1,240 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 17272 13 4 B87AD8C76DC2244E7AA57285057BF533F2E248CC8D7E1A071D8A3837A711A5EA705C4707E6E8911DA653BE1AE019927B"
+ val-override-timestamp: "1442323400"
+ do-not-query-localhost: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 127.0.0.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC name error responses.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+. 3600 IN RRSIG NS 13 0 3600 20151014142315 20150914142315 17272 . aEIYUS4S8Hd7vAVYvHwFyV97lKx4xt2PgAUbM4A7JUXHkTJDHUQEDVQh LWGxK6e+AUeuq4qlDo4vSz3IedmOBQ==
+SECTION ADDITIONAL
+ns. 3600 IN A 127.0.0.1
+ns. 3600 IN RRSIG A 13 1 3600 20151014142315 20150914142315 17272 . 27h0pFJyb5t/2cZsFjynp0TRIdUlQwPYcAwCer2UbXTiBBaD8n15hfh8 PFU0if8X0ikqHusz6rCNTx/aBraYdQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600 IN DNSKEY 256 3 13 qKlBZ0TvdY8C8+7bTcdnQdrLZxEwvxEwlGmIOTd/ccL5Jiei1whNktoE /Qzo1lJ0cXfVssy4EVMaqEdzIa+pkA==
+. 3600 IN RRSIG DNSKEY 13 0 3600 20151014142315 20150914142315 17272 . FaY+kslqSPIRZsk65z8SrROt7kfx+RGUEBGbVgLQxKruJxc9+MMrl4e4 +RefYIlwpecj4jXwb75RTbT0g7OGGg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN MX
+SECTION AUTHORITY
+example. 3600 IN NS ns.example.
+example. 3600 IN DS 11225 13 4 B4BDAB0B3751300BFB9D0D240649279B4BA0E67A308E1B0BFE2931D9 47F7FD71A2BD807D84CDE24286D955A35752484F
+example. 3600 IN RRSIG DS 13 1 3600 20151014143533 20150914143533 17272 . b0+fXKmsBBXkzf+Myr5eRsXWDvY75oMlr4Yi5j+3iF7cOviVGKz3Dw8u bfKW+OmyHiuTeL71gez/84P+vHEvHA==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.2
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+example. 3600 IN NS ns.example.
+example. 3600 IN RRSIG NS 13 1 3600 20151014143225 20150914143225 11225 example. C6KOyVJzeRh/3KL9BxSVOVZN0RIyBhlBmmmnVEFT5qPUrn3m5FjcIBtI hi7cAl2FeY1rqstztvKAY6UOBE0kGQ==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ns.example. 3600 IN RRSIG A 13 2 3600 20151014143225 20150914143225 11225 example. fM/mwUOtyIbKTxgxaekZf5A8kV3qYIFADtvhcQi0TUh09nfkHQtUqhew zVBXCEtjKMnYFvNhWF6PyiirtOeM8w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. 3600 IN DNSKEY 256 3 13 d9Qb4Tj90Y2cvdWcZfu45clfoLKqGbJn2vQKqZv07nc4FMf2oRkrNXtP fixVTLfbbWAFtbbFf3mhCNUsetRUVQ==
+example. 3600 IN RRSIG DNSKEY 13 1 3600 20151015124839 20150915124839 11225 example. 4DemFjvys9Gfq+gG1i8IB6GPBUw9lIv3F082JwW7O8tqNIn45n2z14gg ieeJTRhU9xXOVIfj6amITZWbjvGyFA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN DS 54343 13 4 90ABD4FB9F053CF67F6D838DD2437FB16104B8BF127319706223004F 2ED72AF2872B4E507EB483A303BF60BF08C87364
+nsec.example. 3600 IN RRSIG DS 13 2 3600 20151015124611 20150915124611 11225 example. HYzlEdyYugggsEwUVyyY4XHFVUZZ8yiIh4vnuViGBQQJP+yryYh1aLyN ap2Q51nkmSG1fXDb2IySiAYuqUJyLw==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ENTRY_END
+
+RANGE_END
+
+; ns.nsec.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.3
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION ANSWER
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN RRSIG NS 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 6s75LEuylIKAxqAbcPmmnkOMC7jxF6cPZGW5EFbhOOeR63ENyh642GE1 71WtJc7Ta4Y/PsnAT+/dTv8NSTDCHQ==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ns.nsec.example. 3600 IN RRSIG A 13 3 3600 20151015124917 20150915124917 54343 nsec.example. oJpF87bjXR0DjIoNvEAo+Wu+p9jF+URX5lxi+g53OFCX1Q1lxqj5ujGd KOPsNAbKvTCsoFFW4tQyhCYJYD1HlQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN DNSKEY
+SECTION ANSWER
+nsec.example. 3600 IN DNSKEY 256 3 13 HA6nKf+X7/mYkmmRO8qS2tIKT0B60P7COAiRs25xKs/rAP+tDtGWkrkG NQx2D3ajccC9whjRaKz2JVS3ItTFQg==
+nsec.example. 3600 IN RRSIG DNSKEY 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 965Mfxs1QtgxwzyhfxXyKyOZ9iT1DXpvypBBR10sLyjHe/w7cRhgcyev Cza6K+2jJwHJBmbknc3Qhi+1dd+AJw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+aaa.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+mail.nsec.example. 3600 IN NSEC multiple.nsec.example. A AAAA RRSIG NSEC
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+mail.nsec.example. 3600 IN RRSIG NSEC 13 3 3600 20151015124917 20150915124917 54343 nsec.example. kM+Z63RDn377szwbOqPPinkH98BuCljY7hoeM8jGJcnQ90fA3NFi72Jg k/0T1bo4r0cNMn6lm9OUotawa6BOqw==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing1.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+missing2.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+mail.nsec.example. 3600 IN NSEC multiple.nsec.example. A AAAA RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+mail.nsec.example. 3600 IN RRSIG NSEC 13 3 3600 20151015124917 20150915124917 54343 nsec.example. kM+Z63RDn377szwbOqPPinkH98BuCljY7hoeM8jGJcnQ90fA3NFi72Jg k/0T1bo4r0cNMn6lm9OUotawa6BOqw==
+ENTRY_END
+
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+aaa.nsec.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NXDOMAIN
+SECTION QUESTION
+aaa.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing.nsec.example. IN MX
+ENTRY_END
+
+STEP 4 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NXDOMAIN
+SECTION QUESTION
+missing.nsec.example. IN MX
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 2 60 60 120 3600
+mail.nsec.example. 3600 IN NSEC multiple.nsec.example. A AAAA RRSIG NSEC
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151015124917 20150915124917 54343 nsec.example. AcjIOhRgJMRILo06O2yl/G4Q6gTuA0NIGpnejpgcoVHg8kZy6xmURhTc kYf//qbx/WPB9k+8j+ymmQPe1phJCQ==
+mail.nsec.example. 3600 IN RRSIG NSEC 13 3 3600 20151015124917 20150915124917 54343 nsec.example. kM+Z63RDn377szwbOqPPinkH98BuCljY7hoeM8jGJcnQ90fA3NFi72Jg k/0T1bo4r0cNMn6lm9OUotawa6BOqw==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+;; TODO: use INCLUDE when it's available.
+;; Aggressive cache can answer STEP 5 and 7 without asking,
+;; from the record in previous answer, as `missing*` is between `mail` and `multiple`.
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_no_data_response.rpl b/tests/deckard/sets/resolver/nsec_no_data_response.rpl
new file mode 100644
index 0000000..aa8deaa
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_no_data_response.rpl
@@ -0,0 +1,201 @@
+; config options
+;server:
+ trust-anchor: ". 3600 IN DS 17272 13 4 B87AD8C76DC2244E7AA57285057BF533F2E248CC8D7E1A071D8A3837A711A5EA705C4707E6E8911DA653BE1AE019927B"
+ val-override-timestamp: "1442839270"
+ do-not-query-localhost: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 127.0.0.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC name error responses.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+. 3600 IN RRSIG NS 13 0 3600 20151014142315 20150914142315 17272 . aEIYUS4S8Hd7vAVYvHwFyV97lKx4xt2PgAUbM4A7JUXHkTJDHUQEDVQh LWGxK6e+AUeuq4qlDo4vSz3IedmOBQ==
+SECTION ADDITIONAL
+ns. 3600 IN A 127.0.0.1
+ns. 3600 IN RRSIG A 13 1 3600 20151014142315 20150914142315 17272 . 27h0pFJyb5t/2cZsFjynp0TRIdUlQwPYcAwCer2UbXTiBBaD8n15hfh8 PFU0if8X0ikqHusz6rCNTx/aBraYdQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600 IN DNSKEY 256 3 13 qKlBZ0TvdY8C8+7bTcdnQdrLZxEwvxEwlGmIOTd/ccL5Jiei1whNktoE /Qzo1lJ0cXfVssy4EVMaqEdzIa+pkA==
+. 3600 IN RRSIG DNSKEY 13 0 3600 20151014142315 20150914142315 17272 . FaY+kslqSPIRZsk65z8SrROt7kfx+RGUEBGbVgLQxKruJxc9+MMrl4e4 +RefYIlwpecj4jXwb75RTbT0g7OGGg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION AUTHORITY
+example. 3600 IN NS ns.example.
+example. 3600 IN DS 11225 13 4 B4BDAB0B3751300BFB9D0D240649279B4BA0E67A308E1B0BFE2931D9 47F7FD71A2BD807D84CDE24286D955A35752484F
+example. 3600 IN RRSIG DS 13 1 3600 20151014143533 20150914143533 17272 . b0+fXKmsBBXkzf+Myr5eRsXWDvY75oMlr4Yi5j+3iF7cOviVGKz3Dw8u bfKW+OmyHiuTeL71gez/84P+vHEvHA==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.2
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+example. 3600 IN NS ns.example.
+example. 3600 IN RRSIG NS 13 1 3600 20151014143225 20150914143225 11225 example. C6KOyVJzeRh/3KL9BxSVOVZN0RIyBhlBmmmnVEFT5qPUrn3m5FjcIBtI hi7cAl2FeY1rqstztvKAY6UOBE0kGQ==
+SECTION ADDITIONAL
+ns.example. 3600 IN A 127.0.0.2
+ns.example. 3600 IN RRSIG A 13 2 3600 20151014143225 20150914143225 11225 example. fM/mwUOtyIbKTxgxaekZf5A8kV3qYIFADtvhcQi0TUh09nfkHQtUqhew zVBXCEtjKMnYFvNhWF6PyiirtOeM8w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. 3600 IN DNSKEY 256 3 13 d9Qb4Tj90Y2cvdWcZfu45clfoLKqGbJn2vQKqZv07nc4FMf2oRkrNXtP fixVTLfbbWAFtbbFf3mhCNUsetRUVQ==
+example. 3600 IN RRSIG DNSKEY 13 1 3600 20151015124839 20150915124839 11225 example. 4DemFjvys9Gfq+gG1i8IB6GPBUw9lIv3F082JwW7O8tqNIn45n2z14gg ieeJTRhU9xXOVIfj6amITZWbjvGyFA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN DS 54343 13 4 90ABD4FB9F053CF67F6D838DD2437FB16104B8BF127319706223004F 2ED72AF2872B4E507EB483A303BF60BF08C87364
+nsec.example. 3600 IN RRSIG DS 13 2 3600 20151015124611 20150915124611 11225 example. HYzlEdyYugggsEwUVyyY4XHFVUZZ8yiIh4vnuViGBQQJP+yryYh1aLyN ap2Q51nkmSG1fXDb2IySiAYuqUJyLw==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ENTRY_END
+
+RANGE_END
+
+; ns.nsec.example.
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.3
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION ANSWER
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN RRSIG NS 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 6s75LEuylIKAxqAbcPmmnkOMC7jxF6cPZGW5EFbhOOeR63ENyh642GE1 71WtJc7Ta4Y/PsnAT+/dTv8NSTDCHQ==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 127.0.0.3
+ns.nsec.example. 3600 IN RRSIG A 13 3 3600 20151015124917 20150915124917 54343 nsec.example. oJpF87bjXR0DjIoNvEAo+Wu+p9jF+URX5lxi+g53OFCX1Q1lxqj5ujGd KOPsNAbKvTCsoFFW4tQyhCYJYD1HlQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN DNSKEY
+SECTION ANSWER
+nsec.example. 3600 IN DNSKEY 256 3 13 HA6nKf+X7/mYkmmRO8qS2tIKT0B60P7COAiRs25xKs/rAP+tDtGWkrkG NQx2D3ajccC9whjRaKz2JVS3ItTFQg==
+nsec.example. 3600 IN RRSIG DNSKEY 13 2 3600 20151015124917 20150915124917 54343 nsec.example. 965Mfxs1QtgxwzyhfxXyKyOZ9iT1DXpvypBBR10sLyjHe/w7cRhgcyev Cza6K+2jJwHJBmbknc3Qhi+1dd+AJw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151017113144 20150917113144 54343 nsec.example. /3orb3cezQbBCZsFP9rx6Col9AB2QxHQtzQ32BYe09MfN7YZxtTE/HZJ aSXGWD3D7sLBdEkg8TGP8JPQtbW2yQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN TYPE1000
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151017113144 20150917113144 54343 nsec.example. /3orb3cezQbBCZsFP9rx6Col9AB2QxHQtzQ32BYe09MfN7YZxtTE/HZJ aSXGWD3D7sLBdEkg8TGP8JPQtbW2yQ==
+ENTRY_END
+
+RANGE_END
+
+;STEP 0 TIME_PASSES ELAPSE 1000
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+nsec.example. IN CNAME
+ENTRY_END
+
+; recursion happens here.
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN NSEC alias.nsec.example. A NS SOA MX AAAA RRSIG NSEC DNSKEY
+nsec.example. 3600 IN RRSIG SOA 13 2 3600 20151017113144 20150917113144 54343 nsec.example. /3orb3cezQbBCZsFP9rx6Col9AB2QxHQtzQ32BYe09MfN7YZxtTE/HZJ aSXGWD3D7sLBdEkg8TGP8JPQtbW2yQ==
+nsec.example. 3600 IN RRSIG NSEC 13 2 3600 20151015124917 20150915124917 54343 nsec.example. STcV7Lc1a794i9DTgflI+d0N0KXTMws0G8VGc0Wo4tVI8lvFJcG1SFXW /jJaXkQstdZ2EM63fIs/u1hhBaV2Gw==
+ENTRY_END
+
+; TODO: aggressive caching can return the same answer as in STEP 2, without asking again.
+;STEP 3 QUERY
+;ENTRY_BEGIN
+;REPLY RD DO
+;SECTION QUESTION
+;nsec.example. IN TYPE1000
+;ENTRY_END
+;
+;STEP 4 CHECK_ANSWER
+;ENTRY_BEGIN
+;MATCH all
+;ADJUST copy_id
+;REPLY QR RD RA SERVFAIL
+;SECTION QUESTION
+;nsec.example. IN TYPE1000
+;SECTION AUTHORITY
+;ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_ref_to_unsigned1.rpl b/tests/deckard/sets/resolver/nsec_ref_to_unsigned1.rpl
new file mode 100644
index 0000000..3570eb7
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_ref_to_unsigned1.rpl
@@ -0,0 +1,196 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN NSEC, referral to unsigned subzone, no ds, nsec.
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2016022600 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 10 2 3600 20251231235959 20160308093040 2843 example.com. s3pCq6ZK3DEUkWYX3XKvr5v9Z4AhbJ4P7/AKQkhe3zymnTba7Bo5Uhmb Vav/A+u8gsoo9yBumReXLAv047btO+jdCOLD/yXvmaSt/yGGcipFoX6r 4kQWzUHby4NlQEdO3YykiZx7FtCGsMp0cfwPae4glkDsAPnIhhQurzzE VP4=
+sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+a.sub.example.com. 3600 IN A 1.2.3.11
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.sub.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+a.sub.example.com. 3600 IN A 1.2.3.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_ref_to_unsigned2.rpl b/tests/deckard/sets/resolver/nsec_ref_to_unsigned2.rpl
new file mode 100644
index 0000000..fdf8e06
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_ref_to_unsigned2.rpl
@@ -0,0 +1,197 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN NSEC, referral to unsigned subzone, no ds, no nsec, ds soa.
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+; no ds, no nsec
+;sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+;sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2016022600 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 10 2 3600 20251231235959 20160308093040 2843 example.com. s3pCq6ZK3DEUkWYX3XKvr5v9Z4AhbJ4P7/AKQkhe3zymnTba7Bo5Uhmb Vav/A+u8gsoo9yBumReXLAv047btO+jdCOLD/yXvmaSt/yGGcipFoX6r 4kQWzUHby4NlQEdO3YykiZx7FtCGsMp0cfwPae4glkDsAPnIhhQurzzE VP4=
+sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+a.sub.example.com. 3600 IN A 1.2.3.11
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.sub.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+a.sub.example.com. 3600 IN A 1.2.3.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_ref_to_unsigned3.rpl b/tests/deckard/sets/resolver/nsec_ref_to_unsigned3.rpl
new file mode 100644
index 0000000..bd9ffc0
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_ref_to_unsigned3.rpl
@@ -0,0 +1,197 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN NSEC, referral to unsigned subzone, no ds, no nsec, bad ds soa.
+
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+; no ds, no nsec
+;sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+;sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2016022600 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 10 2 3600 20251231235959 20160308093040 2843 example.com. s3pCq6ZK3DEUkWYX3XKvr5v9Z4AhbJ4P7/AKQkhe3zymnTba7Bo5Uhmb Vav/A+u8gsoo9yBumReXLAv047btO+jdCOLD/yXvmaSt/yGGcipFoX6r 4kQWzUHby4NlQEdO3YykiZx7FtCGsMp0cfwPae4glkDsAPnIhhQurzzE VP4=
+; no nsec
+;sub.example.com. 3600 IN NSEC example.com. NS RRSIG NSEC
+;sub.example.com. 3600 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. extoqd9mqaALMQf5kY5deuxZDL6INjsEKEUSfDibHTEAdNxfnmOJ9wcf hfpQfmgFLUAHsN0V/YB8qq6JhzkEkMV9f7BI/nZpuKCbSHo4ZOEUTflX mGM+VRBQc8gb25K03N0nwb6AvueSVA1PRizrRpQm/wvVWfDNZ+rM/lO6 +i4=
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+a.sub.example.com. 3600 IN A 1.2.3.11
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.sub.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_answer_response.rpl b/tests/deckard/sets/resolver/nsec_wildcard_answer_response.rpl
new file mode 100644
index 0000000..e51d351
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_answer_response.rpl
@@ -0,0 +1,418 @@
+; config options
+;server:
+ trust-anchor: ". IN DS 41524 8 2 5175938255D97A88F9D16A5A46ED3AE373441DF5058C1666D953005D A6BD57F3"
+ val-override-date: "20170401000000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 192.0.2.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC wildcard answer response.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+. 3600 IN RRSIG NS 8 0 3600 20170418124934 20170319124934 41524 . cclqaWsABHoHHSVEjxvWUkj7WBJQGdxvEj2/brtPw9wh42JsedoAsu9g e7885/LSxVOSFf5mZ3eHN1dfxHF5QLYVO2oKgDOl8kM7Hyb3rkqmOp7L lqVS4v4iH4etaonhIW6qwqZTLlets59Z48sF/qurX6EVE/xTc7Kc917c 7oUgHoPoKa8RXkBvXFOuSgXA+OkewLrBcdGaokSLD92/+wZKLAWopc32 mTbZMSImdywm4CvePEZUyXeeQASc7H4eCKE6LFw/4577YrHzDYp2QVnq meJfYg46NXm7xC4bJni/zHmnjKxIS+vi2CdqA7uJviTFpj5XF3g+73aj LHI99Q==
+SECTION ADDITIONAL
+ns. 3600 IN A 192.0.2.1
+ns. 3600 IN RRSIG A 8 1 3600 20170418124934 20170319124934 41524 . r+kPV+Qp088ifM2RRJd9/kTwlFV4Ejuhb8G8VAPmWwkiXSJSrS7HXR9n xkO1CHSzwGYumIDoZsPqZ+RQwY4EBd6xPuAdMAmN/zbebmz+UtNTGLz3 8KVjZoRsJt0BftJs/o3SogiV6cfUtFVnRJN4sCRzAQcyywtKxhtKgHjX 1A47NKzjkbkm2TlUeVwXJjkp0FleZaiNP6wEoxE2cr1hKX4HutXzegzr PaiNGgQhY3yLohBmoSozFLYUN8YPMw6BTf0CLAqyU6N51fVaPZIlARbd V9Ia48AGz44324WrvssuaW2wb0OQie0RAPrHlXg5Ly5I9DeE6m6Czc+M fHBZUQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 192.0.2.1
+ns. 3600 IN RRSIG A 8 1 3600 20170418124934 20170319124934 41524 . r+kPV+Qp088ifM2RRJd9/kTwlFV4Ejuhb8G8VAPmWwkiXSJSrS7HXR9n xkO1CHSzwGYumIDoZsPqZ+RQwY4EBd6xPuAdMAmN/zbebmz+UtNTGLz3 8KVjZoRsJt0BftJs/o3SogiV6cfUtFVnRJN4sCRzAQcyywtKxhtKgHjX 1A47NKzjkbkm2TlUeVwXJjkp0FleZaiNP6wEoxE2cr1hKX4HutXzegzr PaiNGgQhY3yLohBmoSozFLYUN8YPMw6BTf0CLAqyU6N51fVaPZIlARbd V9Ia48AGz44324WrvssuaW2wb0OQie0RAPrHlXg5Ly5I9DeE6m6Czc+M fHBZUQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+ns. 0 IN NSEC . A RRSIG NSEC
+. 3600 IN RRSIG SOA 8 0 3600 20170418124934 20170319124934 41524 . njTin0/F2e0rVDB1tR4Qf3Fy7yFhsEQBjBP0tLbjAGxkXXmkf3RQAQI6 2OzbNgFH+v+SlupN03LwNbGgxVpvgpEC9X9wh5/l6t+YgMFEHwzVu5Qv 9Mybiqe0gMU8KBtYnTcFkUGs+gE+t7Z/DhPx88zBixYTNGXbDNUWI5nl /xq4FlIAcEb1r+bKpFbpAHyVTrqjy1ZIpn5lYrQPwfrQ/g0iL76SgwT+ 8oBF9LDmrgeVZA5lzzjfu7jp7/N7eYAA6YYZCaK6tca33xTc2RUbmyKQ VJMN8wets+iPxrwAAbHVc5FmxmdlDVQlh4AXkgDahFoUtZwzvLCuphj/ D66dsA==
+ns. 0 IN RRSIG NSEC 8 1 0 20170418124934 20170319124934 41524 . ELuSBQbX8wpCTnUBj2OC/if7HEc0DyekwfNccg84kG9vCfn4PS+AcwJB ZbjJjRWGIIYJBesXuRbaZ1P0yYWSlPfwqbWhO1amSmqOgKEMKgVDmQ3g Qc3e3qqRi5YiGpAnQen7EOnbtUuFKH/OTd5Valq+sKxaYVpJxz53tgTm 42nYuWJg/9aDr9P6NNtl1XoTV+84ApFSxQ9EM9WHsYkVzYTrLZQhMmlQ K1zAsUoUcLISTf5q0T7npsMY7bjaoWfNvGeuUT2VMz44sevivR39Wy3o utWn9zcXa2hXPXW3XXrzIQfkQN9CDkJ5IAwKRPWq1a5vFmbyXN8GfBR3 6le6qA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600 IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
+. 3600 IN RRSIG DNSKEY 8 0 3600 20170418124934 20170319124934 41524 . j/TFYuMrE2Hw4fVUjyIeawIGjuPSGYpmaPQO6fo6B36LG+Fi+GsdrR8x 0OltpfgM7K6QXXZvvPe8IiBACfwPhjUbDgocjkT3VfXONO2wg3xI4pbh rBP7va2otZxPKnnOHWg78l9wcDdaJePOvRv9XjqW6TxO1tugskUy612/ fZpaCrqqQPnCxmjxso8VbKYJHy5dRJFVGX0q2BTsoK55x6+Ecao4eDFo d5VFP9R+oMFlMHV9GPF+NPpfWp3lvQa+6jEikJlZXIExx4x0vUzHgrfZ 2V+4C8Hn0Bc9JfyLqYk6aulbfqkxs+Ao9fm+aNkQVJR4+1PLXnqSCH+/ iP0FVQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+. 0 IN NSEC *.nsec.example. NS SOA RRSIG NSEC DNSKEY
+. 3600 IN RRSIG SOA 8 0 3600 20170418145253 20170319145253 41524 . GrQu0mY+qRcyVrfn2tp3IpLLZhXUEVCEIg6oVa+wlS5eNULJIJ4xZLG8 T8Dt/ca7XYiWz5Hbv5FP2UG8vbME9Qi3W4pghCSeUq+r0Z+sKJ//BS20 wcX9gpv3KeenLCiLggZDuDvhIJ0Ce8V+p9p+BFbpL4rSESEOLR7VDt5q 2bXgra5ukVp94OF6mCuMSTv2uPfgoNV5b53waJ2TS98E2yOPnNd/LgYa XWqao2a0en3odQPGy+5sdg+Z+UkLS1ySn6hB50Xl6f1CMYVPU7X8+bub g2bHD3yK2Sy5bkNipyohcW8P7tNnR78HhlJyOOGeHzOS2975B6E34mjV zSumrA==
+. 0 IN RRSIG NSEC 8 0 0 20170418145253 20170319145253 41524 . C0tKsifl3qXK5OqpVW4boQleYwtWtT3P7UeVZhBSqEMAIV7UcEWMnnUW wUgtgA181pwvyqwcDYmbz1sM+1GfewfjQY1ulZyj3bjgOy7/w+0BT8JX +FFXrE6j2vRvHFHF0nyfNHwJHAYxaoEl1m5uobPYQy8Cb61MfbRGfj1Q rF5OcSI1O0ExXoPIcIuS3WN2wAqLGLwzSsrltp6K8N81+bbMHZD4TIlA ED3Rl+hL6eg/kx1IcY5PEKI+T6gaqbRlfXicyk+Z4ZYnMn5nH7k5s6Hw CaMUYMsJLpU5ZUfjgQUFbUyKOU5ivTbPQEcujy9yXJ5dX3K2JP4u7MrY sIpuCA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+name.example. IN NS
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+. 0 IN NSEC *.nsec.example. NS SOA RRSIG NSEC DNSKEY
+. 3600 IN RRSIG SOA 8 0 3600 20170418145253 20170319145253 41524 . GrQu0mY+qRcyVrfn2tp3IpLLZhXUEVCEIg6oVa+wlS5eNULJIJ4xZLG8 T8Dt/ca7XYiWz5Hbv5FP2UG8vbME9Qi3W4pghCSeUq+r0Z+sKJ//BS20 wcX9gpv3KeenLCiLggZDuDvhIJ0Ce8V+p9p+BFbpL4rSESEOLR7VDt5q 2bXgra5ukVp94OF6mCuMSTv2uPfgoNV5b53waJ2TS98E2yOPnNd/LgYa XWqao2a0en3odQPGy+5sdg+Z+UkLS1ySn6hB50Xl6f1CMYVPU7X8+bub g2bHD3yK2Sy5bkNipyohcW8P7tNnR78HhlJyOOGeHzOS2975B6E34mjV zSumrA==
+. 0 IN RRSIG NSEC 8 0 0 20170418145253 20170319145253 41524 . C0tKsifl3qXK5OqpVW4boQleYwtWtT3P7UeVZhBSqEMAIV7UcEWMnnUW wUgtgA181pwvyqwcDYmbz1sM+1GfewfjQY1ulZyj3bjgOy7/w+0BT8JX +FFXrE6j2vRvHFHF0nyfNHwJHAYxaoEl1m5uobPYQy8Cb61MfbRGfj1Q rF5OcSI1O0ExXoPIcIuS3WN2wAqLGLwzSsrltp6K8N81+bbMHZD4TIlA ED3Rl+hL6eg/kx1IcY5PEKI+T6gaqbRlfXicyk+Z4ZYnMn5nH7k5s6Hw CaMUYMsJLpU5ZUfjgQUFbUyKOU5ivTbPQEcujy9yXJ5dX3K2JP4u7MrY sIpuCA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+. 0 IN NSEC *.nsec.example. NS SOA RRSIG NSEC DNSKEY
+*.nsec.example. 0 IN NSEC explicita.nsec.example. A RRSIG NSEC
+. 3600 IN RRSIG SOA 8 0 3600 20170418145253 20170319145253 41524 . GrQu0mY+qRcyVrfn2tp3IpLLZhXUEVCEIg6oVa+wlS5eNULJIJ4xZLG8 T8Dt/ca7XYiWz5Hbv5FP2UG8vbME9Qi3W4pghCSeUq+r0Z+sKJ//BS20 wcX9gpv3KeenLCiLggZDuDvhIJ0Ce8V+p9p+BFbpL4rSESEOLR7VDt5q 2bXgra5ukVp94OF6mCuMSTv2uPfgoNV5b53waJ2TS98E2yOPnNd/LgYa XWqao2a0en3odQPGy+5sdg+Z+UkLS1ySn6hB50Xl6f1CMYVPU7X8+bub g2bHD3yK2Sy5bkNipyohcW8P7tNnR78HhlJyOOGeHzOS2975B6E34mjV zSumrA==
+. 0 IN RRSIG NSEC 8 0 0 20170418145253 20170319145253 41524 . C0tKsifl3qXK5OqpVW4boQleYwtWtT3P7UeVZhBSqEMAIV7UcEWMnnUW wUgtgA181pwvyqwcDYmbz1sM+1GfewfjQY1ulZyj3bjgOy7/w+0BT8JX +FFXrE6j2vRvHFHF0nyfNHwJHAYxaoEl1m5uobPYQy8Cb61MfbRGfj1Q rF5OcSI1O0ExXoPIcIuS3WN2wAqLGLwzSsrltp6K8N81+bbMHZD4TIlA ED3Rl+hL6eg/kx1IcY5PEKI+T6gaqbRlfXicyk+Z4ZYnMn5nH7k5s6Hw CaMUYMsJLpU5ZUfjgQUFbUyKOU5ivTbPQEcujy9yXJ5dX3K2JP4u7MrY sIpuCA==
+*.nsec.example. 0 IN RRSIG NSEC 8 2 0 20170418145253 20170319145253 41524 . A60R/W7nJnrOGnESzKm1//8kydq91hlsk9+2r5z/AT3vuyLdrDVRmmZg LzIdcJ/9qIt4XrfvaGWmqhs2qmm5EbjFoXh+AoRqaetaK1auuAGHqH9U KdMOuxlkoJ4z6sDpSxumbgVxKq7kj7nKGYF/dyCHTcJhKuo498XYh+MQ MDKu82CfmLPdwroqgQyyux/9oimLbYDo/fz09w+/uzApnOWgyM5WiE/M Q6tgHL+UTi5hdZ7jIF2gCtp+V5YcWLI/wcmuJ7lkCh3B9UoCy0box8PB V4U2chvK7pR3DG8slgEaag5wiPto6fwru7PShfp0oC6d6m0x4jsuT6u1 j6GmIw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+local.nsec.example. IN A
+SECTION ANSWER
+local.nsec.example. 3600 IN A 10.6.6.6
+local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418145253 20170319145253 41524 . aHyII7vYA6ELENm2C+88GLhJ0D+WBO/TaabT4jnHpyPaVlg+KXOg7Ar1 s04vcPDczmzft178ZcQYbeY2/UR7LsDZoj8j+86MTkVP/FIyNt/8rHch r/AFQQvXvjqD1XTho+3Fyk1HLD+VKI8Rkq894cfc9rAPb1+H3PPz6JWb EwM7S6Ox2OixUEVNKStrsEIDzYSyWmdpRXFC8CVR5zEv1OxBlNBUvza2 KNJHTxwEIcFQY5MdKkGIa25TckAYhncboI1j79VdRa0xqymO81E7AR/D HTBVLD/gENvgN7HGAduC834SuZ1ReDhlbSD1KHw5GPgBGw9e7kzpsoYH MASASg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+local.nsec.example. IN NS
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+*.nsec.example. 0 IN NSEC explicita.nsec.example. A RRSIG NSEC
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+. 3600 IN RRSIG SOA 8 0 3600 20170418145253 20170319145253 41524 . GrQu0mY+qRcyVrfn2tp3IpLLZhXUEVCEIg6oVa+wlS5eNULJIJ4xZLG8 T8Dt/ca7XYiWz5Hbv5FP2UG8vbME9Qi3W4pghCSeUq+r0Z+sKJ//BS20 wcX9gpv3KeenLCiLggZDuDvhIJ0Ce8V+p9p+BFbpL4rSESEOLR7VDt5q 2bXgra5ukVp94OF6mCuMSTv2uPfgoNV5b53waJ2TS98E2yOPnNd/LgYa XWqao2a0en3odQPGy+5sdg+Z+UkLS1ySn6hB50Xl6f1CMYVPU7X8+bub g2bHD3yK2Sy5bkNipyohcW8P7tNnR78HhlJyOOGeHzOS2975B6E34mjV zSumrA==
+*.nsec.example. 0 IN RRSIG NSEC 8 2 0 20170418145253 20170319145253 41524 . A60R/W7nJnrOGnESzKm1//8kydq91hlsk9+2r5z/AT3vuyLdrDVRmmZg LzIdcJ/9qIt4XrfvaGWmqhs2qmm5EbjFoXh+AoRqaetaK1auuAGHqH9U KdMOuxlkoJ4z6sDpSxumbgVxKq7kj7nKGYF/dyCHTcJhKuo498XYh+MQ MDKu82CfmLPdwroqgQyyux/9oimLbYDo/fz09w+/uzApnOWgyM5WiE/M Q6tgHL+UTi5hdZ7jIF2gCtp+V5YcWLI/wcmuJ7lkCh3B9UoCy0box8PB V4U2chvK7pR3DG8slgEaag5wiPto6fwru7PShfp0oC6d6m0x4jsuT6u1 j6GmIw==
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.local.nsec.example. IN A
+SECTION ANSWER
+a.local.nsec.example. 3600 IN A 10.6.6.6
+a.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+; Missing NSEC covering the wildcard.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN A
+SECTION ANSWER
+missing-nsec.local.nsec.example. 3600 IN A 10.6.6.6
+missing-nsec.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+ENTRY_END
+
+; kresd will detect validation failure and query for RRSIG
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN RRSIG
+SECTION ANSWER
+missing-nsec.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+ENTRY_END
+
+; NSEC record was attached to another answer created by copying wildcard data to different owner name
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+incorrect.name.example. IN A
+SECTION ANSWER
+incorrect.name.example. 3600 IN A 10.6.6.6
+incorrect.name.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+; kresd will detect validation failure and query for RRSIG
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+incorrect.name.example. IN RRSIG
+SECTION ANSWER
+incorrect.name.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+ENTRY_END
+
+; explicita.nsec.example.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+explicita.nsec.example. IN A
+SECTION ANSWER
+explicita.nsec.example. 3600 IN A 203.0.113.1
+explicita.nsec.example. 3600 IN RRSIG A 8 3 3600 20170418134059 20170319134059 41524 . Nn0DZ1gwzj0FLrgmoeePfKJbvJvTpwtmw6CPehUHyNW7pUOYG8HE45qt tcvx4LWvzYAKy9TY6B7c4D5eMu8+rXXyLg21DX3zFKABEYIeMaJPqPpF WxYqhbP0qQwI/w29B7n3blzzbMOkNvNI4y4RZyBqyqBBfKu/xXYljZG2 MyDlRyEAeV1vewMdhlr6TJoclE6PqYvxiMuXc1f9Nu/TwB22Pp29OTrN A3HFieYVbfWM1F3HtoO6aAk2FVCEveYQOsQ81mgweMKF2OMIK4rjCwlL ffziuSYwF5TcheNATYlaQQZTxKhKsdmGM4BZNprQ/MzoutqIS7j7Vdxs O4N+1Q==
+ENTRY_END
+
+; explicita2.nsec.example. - fake answer attempting to replace explicit record with wildcard data
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+explicita2.nsec.example. IN A
+SECTION ANSWER
+; this was copied from wildcard answer for a.local.nsec.example. IN A
+explicits2.nsec.example. 3600 IN A 10.6.6.6
+explicita2.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.local.nsec.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+a.local.nsec.example. IN A
+SECTION ANSWER
+a.local.nsec.example. 3600 IN A 10.6.6.6
+a.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+; test answer from cache
+STEP 12 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.local.nsec.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 13 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+a.local.nsec.example. IN A
+SECTION ANSWER
+a.local.nsec.example. 3600 IN A 10.6.6.6
+a.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170418134059 20170319134059 41524 . KMkFd5M1F8wVtVhXUnyPZMhY6dGj3g54tX+wgRiGSnqlRICCUdc8NCKG w+lJ1HvDrfNduth5De82MwCfgu2qORDGRF1H0DaoLlYOzy7pNPV1kA9R sXals6EyoFw0pEJkdW/pI5/EJz611c5Oy94iz5LbhkM/kwosmtK1ln3Z N+zGGDRj8xAaWsvmAvPXQoIJhHEblPp/Mcs4V6vX0b7plfkdDxa0hCgf 4UYipsqHo6BXksCEkRznIlDWym9jpVqD7TNAIbO/03TpvhnD50C0Wusb k75cTy24NDD7PTmAZwBlT6qZGnODdc1/ECTnq3kYniN6ceevMZQYEVqw S9haUg==
+SECTION AUTHORITY
+explicita2.nsec.example. 0 IN NSEC ns. A RRSIG NSEC
+explicita2.nsec.example. 0 IN RRSIG NSEC 8 3 0 20170418145253 20170319145253 41524 . kam1hKBwoeTPR0wpvPs2Jyik3hB+Q0Ek4rpD3BNhUa+gTbBk1Z0q5yEs RFVsp6EZlpcP357QiipC2wrPfd3SunGVTVfAD4h6gn1/e5mPN4kJJfOa nMgwZQATF/vilnGu2+5Xtup3blFhg43UJB//iyTcn8c+phMaySbyT5uG xXaM1Gv2maHeJQNOB8cwFWHpYy/Uoph5rpEcZoxGjGkTLNE8pvhlSAgB wYEtMvli3KJH6hjBnOzhMAtOl+ZHy3VFo/UVm/Lwyzmlg+OQ8LCz+NY0 kmAH8z7ZNKZMxyvBpLzxAU2O+j4uSmp5ENuLcqvEyofr2xrq5Fm7OSoH qZvQ1A==
+ENTRY_END
+
+; missing-nsec.local.nsec.example. is covered by explicita2.nsec.example. -> ns.
+; and then the *.nsec.example. wildcard applies (both from the last answer above)
+; kresd by default caches even zero-TTL records for 5 seconds, so let's expire those,
+; so that the aggressive cache won't use them.
+STEP 19 TIME_PASSES ELAPSE 10
+
+; NSEC record is missing
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN A
+ENTRY_END
+
+STEP 22 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN A
+ENTRY_END
+
+; test answer from cache
+STEP 23 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing-nsec.local.nsec.example. IN A
+ENTRY_END
+
+
+; NSEC answer was copied to another name in the same zone
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+incorrect.name.example. IN A
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+incorrect.name.example. IN A
+ENTRY_END
+
+; test answer from cache
+STEP 32 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+incorrect.name.example. IN A
+ENTRY_END
+
+STEP 33 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+incorrect.name.example. IN A
+ENTRY_END
+
+; explicitly defined records gets properly validated even with cached wildcard
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD DO AD
+SECTION QUESTION
+explicita.nsec.example. IN A
+ENTRY_END
+
+STEP 41 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO AD
+SECTION QUESTION
+explicita.nsec.example. IN A
+SECTION ANSWER
+explicita.nsec.example. 3600 IN A 203.0.113.1
+explicita.nsec.example. 3600 IN RRSIG A 8 3 3600 20170418134059 20170319134059 41524 . Nn0DZ1gwzj0FLrgmoeePfKJbvJvTpwtmw6CPehUHyNW7pUOYG8HE45qt tcvx4LWvzYAKy9TY6B7c4D5eMu8+rXXyLg21DX3zFKABEYIeMaJPqPpF WxYqhbP0qQwI/w29B7n3blzzbMOkNvNI4y4RZyBqyqBBfKu/xXYljZG2 MyDlRyEAeV1vewMdhlr6TJoclE6PqYvxiMuXc1f9Nu/TwB22Pp29OTrN A3HFieYVbfWM1F3HtoO6aAk2FVCEveYQOsQ81mgweMKF2OMIK4rjCwlL ffziuSYwF5TcheNATYlaQQZTxKhKsdmGM4BZNprQ/MzoutqIS7j7Vdxs O4N+1Q==
+ENTRY_END
+
+; test answer from cache
+STEP 42 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+explicita.nsec.example. IN A
+ENTRY_END
+
+STEP 43 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO AD
+SECTION QUESTION
+explicita.nsec.example. IN A
+SECTION ANSWER
+explicita.nsec.example. 3600 IN A 203.0.113.1
+explicita.nsec.example. 3600 IN RRSIG A 8 3 3600 20170418134059 20170319134059 41524 . Nn0DZ1gwzj0FLrgmoeePfKJbvJvTpwtmw6CPehUHyNW7pUOYG8HE45qt tcvx4LWvzYAKy9TY6B7c4D5eMu8+rXXyLg21DX3zFKABEYIeMaJPqPpF WxYqhbP0qQwI/w29B7n3blzzbMOkNvNI4y4RZyBqyqBBfKu/xXYljZG2 MyDlRyEAeV1vewMdhlr6TJoclE6PqYvxiMuXc1f9Nu/TwB22Pp29OTrN A3HFieYVbfWM1F3HtoO6aAk2FVCEveYQOsQ81mgweMKF2OMIK4rjCwlL ffziuSYwF5TcheNATYlaQQZTxKhKsdmGM4BZNprQ/MzoutqIS7j7Vdxs O4N+1Q==
+ENTRY_END
+
+; check that explicit record cannot be masked by wildcard
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+explicita2.nsec.example. IN A
+ENTRY_END
+
+STEP 51 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+explicita2.nsec.example. IN A
+ENTRY_END
+
+; it has to work even if wildcard is not in the cache
+STEP 53 TIME_PASSES ELAPSE 4000
+
+STEP 54 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+explicita2.nsec.example. IN A
+ENTRY_END
+
+STEP 55 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+explicita2.nsec.example. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.key b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.key
new file mode 100644
index 0000000..1511e45
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 41524, for .
+; Created: 20170319134901 (Sun Mar 19 14:49:01 2017)
+; Publish: 20170319134901 (Sun Mar 19 14:49:01 2017)
+; Activate: 20170319134901 (Sun Mar 19 14:49:01 2017)
+. IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.private b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.private
new file mode 100644
index 0000000..2811b2b
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/K.+008+41524.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: uDK9hDZWV9/+Kem/g1kuUiTb6XWwvQmh45SVYdnd55ZdkrFAlqRAhfIaLzGy4A3O79hK0unfVJ9T8WPimJRyKoD5Tvgui3VL+Nwzv/V5zOHr1ioZQA9mSt5nfPYOlbME3iWA9H/DQ69Np1rcPja5XZvO5Ir+dcyIylm8/W9nXKQ1GZuSxPMD4eet59GLbK4xJSowdu19t8XCpVNDV11XBIruognTaOj3lglRJkM9RRCVzMiwWxrtnGfqBBmX6JpG4NjqcvHFK1hiVypmFUAblTwPHgjOdDQWQQmn1Fe2/mua0KVxCm50KXWATQYL9b5NNQBreEPn3t+icf6z8590IQ==
+PublicExponent: AQAB
+PrivateExponent: HEH8fPnxCQ4d6cQoUzgtOQDak9gwQu/lXAqBWD+aIVsaA9UZeYK9O09G4RKYxHKZ2oWuBOlID61ZrWCLdKjhUs/yb0D3swFNpGHztnEsPFg0W+idcwxpvvabnboJxsFt776FJ/0psYqFOTVhMFIo4clzVfBU1TGJkrFtotuiWb28eZ85pFJiQUR+agbWjstXaXMmXeSRPYAueBD/bo6u5DqDagH1fzNxhKUxC9nhpeoIj1AtH4bJuO0v4oxq6yrcGEn6Jus5wku9goLCJqykfRikYwQzyUCP/AQMVC++qiQJ89A66psa0F2lcmps5/2skBEM9QB5Vv12jbIw6j6TeQ==
+Prime1: 6AkeSU4ZcvsxDem0IJLhC4zYEpCN+ZAr/757pkv6oIfQv2PhJmXQ1bmiCsYD/uoRDUFNtNGOFjIlmnGHKIefvCSHlZRxCDDzDAvZ6IthkMQEzDcSQkZIpprCt7QMl1Kz2gjEs84+DNxozB54UbEYG908PrF7CF7ix3RHHEDcX6M=
+Prime2: yzjUYzFjM52Q5cwtMHL8gHnacpzQSUidYLZF+xA4dYjc0pjSRMo87sfp2r6wdm3ZOcfOy0SZl4LvO0Kcrz/VB2v0yiBqanDcM3SBg6n7lz/l5Xaoj5rw9JmYj981nJe8vcerZvJl8MLT00uikr1gqoABxKIvHyt7kYcYB2qqSWs=
+Exponent1: Sjzgm8OJEOidQT5Miz9zESb22rm1MuuVqDVhiks03LeXaiSinI5mynqiBaBlFuH8oqkKG5gQRbm1njxEags6aA+n8YuUvnIq0OfZyDUP+ik8/7l+9gVWqTdKpUvN23xyXof/pyeNYsACJ4x4Imrus7uM0uIl4v+4vufM+JUn7NE=
+Exponent2: HUmqakVC27x4lnWviYz40Pc+wUfSSM17SOXb/gvfZyj7UiqOGzXeRDdxf4H94oOAS/B84BSZ4hkPq0W1WRhk9jXbyImVbJOpWI0Q4U3NIYYm9sP8FP4qfcXpE8sCafgAToWJMUP75w/dAVWkL2u1k7zxBEqvadmVbGrAzsjTk9M=
+Coefficient: ms+SW3tNI975ejCbI1vIB31uUqVfvVvxv7eWtzJEdyxBVQKb0aQnXaTMdXiESNc+H5HMau3lbDOw5IcQkp79fKdxLt3SjMYPdnQmBWg7StY3fV1FJcPEEJeFQjWXxioY8rdvMUTMk1FfjxlllBkCyMWuIE4cbRTNdcq76ozM60g=
+Created: 20170319134901
+Publish: 20170319134901
+Activate: 20170319134901
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_answer_response/root.zone b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/root.zone
new file mode 100644
index 0000000..557c92a
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_answer_response/root.zone
@@ -0,0 +1,8 @@
+*.nsec.example. 3600 IN A 10.6.6.6
+
+explicita.nsec.example. 3600 IN A 203.0.113.1
+explicita2.nsec.example. 3600 IN A 203.0.113.2
+
+. 3600 IN SOA . . 0 0 0 0 0
+. 3600 IN NS ns.
+ns. 3600 IN A 192.0.2.1
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_no_data_response-part2.rpl b/tests/deckard/sets/resolver/nsec_wildcard_no_data_response-part2.rpl
new file mode 100644
index 0000000..fbb802a
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_no_data_response-part2.rpl
@@ -0,0 +1,257 @@
+; config options
+;server:
+ trust-anchor: "nsec.example. IN DS 41524 8 2 D6B102667845D6CDDC05B44466426D9CCC189989BF67ADB23605EED0 BFE2A443"
+ val-override-date: "20170401000000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 192.0.2.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC name error responses.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+SECTION ADDITIONAL
+ns. 3600 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION AUTHORITY
+. 3600 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN CNAME
+SECTION AUTHORITY
+example. 3600 IN NS ns.example.
+SECTION ADDITIONAL
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.2
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+example. 3600 IN NS ns.example.
+SECTION ADDITIONAL
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example. IN A
+SECTION ANSWER
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example. IN AAAA
+SECTION AUTHORITY
+example. 3600 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN NS ns.nsec.example.
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 192.0.2.3
+ENTRY_END
+
+RANGE_END
+
+; ns.nsec.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.3
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION ANSWER
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN RRSIG NS 8 2 3600 20170419140236 20170320140236 41524 nsec.example. KECif/B3ckfo5d9Qd/5dtIDt/8nIpTfTMxeJU3qw1U8jzQ/+nQ6qZAvr GH4MeGwY0M9kj2Jj3h2tdI+uhfLaGC7LStXIG0Q+PfalGdddDQwwd/p0 oOQ6bt0eilZN5OKF7Frzn4jmV1x7R/iieWp65xB7OByvguYoXOlzuoU1 ikaL43rm/whxn6iHf0K7NfaVqQwO26N/P3EBFFZMwuhHOB2+bVXKoE7r O4bC04tF7wG7CRUlc44xNs08L512RXRuFIrkHg932BFVlEYmPwbflE6+ zfpZafFzYutEHx7XZw2+gAklynmcAXltPCOiqThkDJzw2rpyUmiH0ztm lG76Tg==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 192.0.2.3
+ns.nsec.example. 3600 IN RRSIG A 8 3 3600 20170419140236 20170320140236 41524 nsec.example. E6Cx+MIElwAbw4Hg48Ee4CC4pKSjPkW8fmcHVoTqNwMyRs4Jjyymf1tE mNdjYkoN0kxI8PEgbGxzuwlFLpGncQhuZ0dyTzCPvnYFPLIkDmdtyIcj 4MVZiJpdyc5yRTC+Aja1Ik9cQ25QsSGAg4z54Zv0o6uqodppCHILgBzm Q833AQFh6hOQE3BFM3c8h3PCsH6HJOOIlgqculfT5d0S1XPFGmtjVW4G gZNsNeBtLB/SkvYKzNS+Yw38J9VTtWMlgTUwkjVXzC+f83AgzXHM3neq QhRhf72VO/xP5sd33VXDVBtOqbFSDZHLpGLfaXJSrnzKX5H8nCMuIXbs kWK60w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.nsec.example. IN A
+SECTION ANSWER
+ns.nsec.example. 3600 IN A 192.0.2.3
+ns.nsec.example. 3600 IN RRSIG A 8 3 3600 20170419140236 20170320140236 41524 nsec.example. E6Cx+MIElwAbw4Hg48Ee4CC4pKSjPkW8fmcHVoTqNwMyRs4Jjyymf1tE mNdjYkoN0kxI8PEgbGxzuwlFLpGncQhuZ0dyTzCPvnYFPLIkDmdtyIcj 4MVZiJpdyc5yRTC+Aja1Ik9cQ25QsSGAg4z54Zv0o6uqodppCHILgBzm Q833AQFh6hOQE3BFM3c8h3PCsH6HJOOIlgqculfT5d0S1XPFGmtjVW4G gZNsNeBtLB/SkvYKzNS+Yw38J9VTtWMlgTUwkjVXzC+f83AgzXHM3neq QhRhf72VO/xP5sd33VXDVBtOqbFSDZHLpGLfaXJSrnzKX5H8nCMuIXbs kWK60w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.nsec.example. IN AAAA
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+ns.nsec.example. 3600 IN NSEC nsec.example. A RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ns.nsec.example. 3600 IN RRSIG NSEC 8 3 3600 20170419140236 20170320140236 41524 nsec.example. iOfnQqIT9V87emJsd/Aym6JqU4H8bzjNq3cbWUmiohgdKr2pkqdt3RV1 r/LGbhSm+seWC/xWuBinEH2WAwXwQMUGrYi5htGazk9C97gkSvle/gXT NZweNC7SkrkBv1VXHG/PrinzFP/YWRn7zMn7fOj/uYWDaYAi0Fzh+Ctn fx2hsHIXC9LduIs+Uv9B58tr9tkF5JNYapoZO59Wtiz1GPaPnfUg9X2u 2T+J5rWpYHJkzKulW+yi0YpipfJY+9J9KWGr2PorChm/W1mc83MptyK2 Po+IbX/I0YStNv+nCLccBo94y/DGOLVnF0XpJZnR5ZDcb8ZmbZIP7uD3 GBFKMg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN DNSKEY
+SECTION ANSWER
+nsec.example. 3600 IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
+nsec.example. 3600 IN RRSIG DNSKEY 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Z1kUmre0LJX76zuKEYhCN5bNNPvXONZK8LElwgNqEQW4kPApz8+vfLmb 4Xlz6D9ChG6J0Pp/JHdKn+S+Le4B5dUOPzuOksfkHTmRsh9oN2ccSEq3 eJK1VhWwRN69xs1LZgXzVJk7DnDnPVUyIbDpb5piBCJHQVwkrIa1Ykeh hexHJb7YZBmF1B6GqTl7K9QwIvfnpKH+iM83QngepAJqpJuHSEPNWCbQ S9rfuP1SObyZD4L/Z3hBFpaZL9N25ThH7znfTc60xNCitmNMFfq68X2/ JoSrVrFLNv9nlneYNkihorhzDMlzN/i/EhrtBkdaSiRlEODnY7zN4Eax m3JkFQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+local.nsec.example. IN A
+SECTION ANSWER
+local.nsec.example. 3600 IN A 10.6.6.6
+local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+SECTION AUTHORITY
+*.nsec.example. 3600 IN NSEC ns.nsec.example. A RRSIG NSEC
+*.nsec.example. 3600 IN RRSIG NSEC 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Hp/6sgDgYZuewpSkAugLRERgVAGgAIAN9vAqfuAGcqCxfQXLIXcXD8ji o4rjuSMmAaRw0AQ70pEWldc2Yqre+++/lnEJt5tpGrIhH2raJU9RS/Ix NaN40vwspRdN7tDNLH1T0oTDll76bVc/D4VFtnpGOlM3eIGjFVVdACvZ V0oVW8xp686xwB3uP2DqA0fxMjs4p9PC1FrnTAlGvTX0ThgZR6EmmWJH HCy4kpjfTFR93k/nuAendDVVZNkHL+EncojmUX+U0PRSZPXWBWXbb0kq h1OVaT4HpyWKet+PxKkTGaoNbXRk0BAKC/4Qg4A/+kRk+1OXG4dQMdsS zLnt/Q==
+ENTRY_END
+
+; missing NSEC proof
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN CNAME
+SECTION ANSWER
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN RRSIG
+SECTION ANSWER
+missing-nsec-nodata.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+ENTRY_END
+
+; synthesized A record was removed and replaced with SOA but no NSEC
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN A
+SECTION ANSWER
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN RRSIG
+SECTION ANSWER
+missing-nsec-masked-data.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+local.nsec.example. IN NS
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+*.nsec.example. 3600 IN NSEC ns.nsec.example. A RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+*.nsec.example. 3600 IN RRSIG NSEC 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Hp/6sgDgYZuewpSkAugLRERgVAGgAIAN9vAqfuAGcqCxfQXLIXcXD8ji o4rjuSMmAaRw0AQ70pEWldc2Yqre+++/lnEJt5tpGrIhH2raJU9RS/Ix NaN40vwspRdN7tDNLH1T0oTDll76bVc/D4VFtnpGOlM3eIGjFVVdACvZ V0oVW8xp686xwB3uP2DqA0fxMjs4p9PC1FrnTAlGvTX0ThgZR6EmmWJH HCy4kpjfTFR93k/nuAendDVVZNkHL+EncojmUX+U0PRSZPXWBWXbb0kq h1OVaT4HpyWKet+PxKkTGaoNbXRk0BAKC/4Qg4A/+kRk+1OXG4dQMdsS zLnt/Q==
+ENTRY_END
+
+RANGE_END
+
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN CNAME
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN CNAME
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/nsec_wildcard_no_data_response.rpl b/tests/deckard/sets/resolver/nsec_wildcard_no_data_response.rpl
new file mode 100644
index 0000000..0882917
--- /dev/null
+++ b/tests/deckard/sets/resolver/nsec_wildcard_no_data_response.rpl
@@ -0,0 +1,282 @@
+; config options
+;server:
+ trust-anchor: "nsec.example. IN DS 41524 8 2 D6B102667845D6CDDC05B44466426D9CCC189989BF67ADB23605EED0 BFE2A443"
+ val-override-date: "20170401000000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 192.0.2.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of NSEC name error responses.
+
+; ns.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+SECTION ADDITIONAL
+ns. 3600 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION AUTHORITY
+. 3600 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN CNAME
+SECTION AUTHORITY
+example. 3600 IN NS ns.example.
+SECTION ADDITIONAL
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+RANGE_END
+
+; ns.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.2
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+example. 3600 IN NS ns.example.
+SECTION ADDITIONAL
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example. IN A
+SECTION ANSWER
+ns.example. 3600 IN A 192.0.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example. IN AAAA
+SECTION AUTHORITY
+example. 3600 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN NS ns.nsec.example.
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 192.0.2.3
+ENTRY_END
+
+RANGE_END
+
+; ns.nsec.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.3
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN NS
+SECTION ANSWER
+nsec.example. 3600 IN NS ns.nsec.example.
+nsec.example. 3600 IN RRSIG NS 8 2 3600 20170419140236 20170320140236 41524 nsec.example. KECif/B3ckfo5d9Qd/5dtIDt/8nIpTfTMxeJU3qw1U8jzQ/+nQ6qZAvr GH4MeGwY0M9kj2Jj3h2tdI+uhfLaGC7LStXIG0Q+PfalGdddDQwwd/p0 oOQ6bt0eilZN5OKF7Frzn4jmV1x7R/iieWp65xB7OByvguYoXOlzuoU1 ikaL43rm/whxn6iHf0K7NfaVqQwO26N/P3EBFFZMwuhHOB2+bVXKoE7r O4bC04tF7wG7CRUlc44xNs08L512RXRuFIrkHg932BFVlEYmPwbflE6+ zfpZafFzYutEHx7XZw2+gAklynmcAXltPCOiqThkDJzw2rpyUmiH0ztm lG76Tg==
+SECTION ADDITIONAL
+ns.nsec.example. 3600 IN A 192.0.2.3
+ns.nsec.example. 3600 IN RRSIG A 8 3 3600 20170419140236 20170320140236 41524 nsec.example. E6Cx+MIElwAbw4Hg48Ee4CC4pKSjPkW8fmcHVoTqNwMyRs4Jjyymf1tE mNdjYkoN0kxI8PEgbGxzuwlFLpGncQhuZ0dyTzCPvnYFPLIkDmdtyIcj 4MVZiJpdyc5yRTC+Aja1Ik9cQ25QsSGAg4z54Zv0o6uqodppCHILgBzm Q833AQFh6hOQE3BFM3c8h3PCsH6HJOOIlgqculfT5d0S1XPFGmtjVW4G gZNsNeBtLB/SkvYKzNS+Yw38J9VTtWMlgTUwkjVXzC+f83AgzXHM3neq QhRhf72VO/xP5sd33VXDVBtOqbFSDZHLpGLfaXJSrnzKX5H8nCMuIXbs kWK60w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.nsec.example. IN A
+SECTION ANSWER
+ns.nsec.example. 3600 IN A 192.0.2.3
+ns.nsec.example. 3600 IN RRSIG A 8 3 3600 20170419140236 20170320140236 41524 nsec.example. E6Cx+MIElwAbw4Hg48Ee4CC4pKSjPkW8fmcHVoTqNwMyRs4Jjyymf1tE mNdjYkoN0kxI8PEgbGxzuwlFLpGncQhuZ0dyTzCPvnYFPLIkDmdtyIcj 4MVZiJpdyc5yRTC+Aja1Ik9cQ25QsSGAg4z54Zv0o6uqodppCHILgBzm Q833AQFh6hOQE3BFM3c8h3PCsH6HJOOIlgqculfT5d0S1XPFGmtjVW4G gZNsNeBtLB/SkvYKzNS+Yw38J9VTtWMlgTUwkjVXzC+f83AgzXHM3neq QhRhf72VO/xP5sd33VXDVBtOqbFSDZHLpGLfaXJSrnzKX5H8nCMuIXbs kWK60w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.nsec.example. IN AAAA
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+ns.nsec.example. 3600 IN NSEC nsec.example. A RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ns.nsec.example. 3600 IN RRSIG NSEC 8 3 3600 20170419140236 20170320140236 41524 nsec.example. iOfnQqIT9V87emJsd/Aym6JqU4H8bzjNq3cbWUmiohgdKr2pkqdt3RV1 r/LGbhSm+seWC/xWuBinEH2WAwXwQMUGrYi5htGazk9C97gkSvle/gXT NZweNC7SkrkBv1VXHG/PrinzFP/YWRn7zMn7fOj/uYWDaYAi0Fzh+Ctn fx2hsHIXC9LduIs+Uv9B58tr9tkF5JNYapoZO59Wtiz1GPaPnfUg9X2u 2T+J5rWpYHJkzKulW+yi0YpipfJY+9J9KWGr2PorChm/W1mc83MptyK2 Po+IbX/I0YStNv+nCLccBo94y/DGOLVnF0XpJZnR5ZDcb8ZmbZIP7uD3 GBFKMg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+nsec.example. IN DNSKEY
+SECTION ANSWER
+nsec.example. 3600 IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
+nsec.example. 3600 IN RRSIG DNSKEY 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Z1kUmre0LJX76zuKEYhCN5bNNPvXONZK8LElwgNqEQW4kPApz8+vfLmb 4Xlz6D9ChG6J0Pp/JHdKn+S+Le4B5dUOPzuOksfkHTmRsh9oN2ccSEq3 eJK1VhWwRN69xs1LZgXzVJk7DnDnPVUyIbDpb5piBCJHQVwkrIa1Ykeh hexHJb7YZBmF1B6GqTl7K9QwIvfnpKH+iM83QngepAJqpJuHSEPNWCbQ S9rfuP1SObyZD4L/Z3hBFpaZL9N25ThH7znfTc60xNCitmNMFfq68X2/ JoSrVrFLNv9nlneYNkihorhzDMlzN/i/EhrtBkdaSiRlEODnY7zN4Eax m3JkFQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+local.nsec.example. IN A
+SECTION ANSWER
+local.nsec.example. 3600 IN A 10.6.6.6
+local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+SECTION AUTHORITY
+*.nsec.example. 3600 IN NSEC ns.nsec.example. A RRSIG NSEC
+*.nsec.example. 3600 IN RRSIG NSEC 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Hp/6sgDgYZuewpSkAugLRERgVAGgAIAN9vAqfuAGcqCxfQXLIXcXD8ji o4rjuSMmAaRw0AQ70pEWldc2Yqre+++/lnEJt5tpGrIhH2raJU9RS/Ix NaN40vwspRdN7tDNLH1T0oTDll76bVc/D4VFtnpGOlM3eIGjFVVdACvZ V0oVW8xp686xwB3uP2DqA0fxMjs4p9PC1FrnTAlGvTX0ThgZR6EmmWJH HCy4kpjfTFR93k/nuAendDVVZNkHL+EncojmUX+U0PRSZPXWBWXbb0kq h1OVaT4HpyWKet+PxKkTGaoNbXRk0BAKC/4Qg4A/+kRk+1OXG4dQMdsS zLnt/Q==
+ENTRY_END
+
+; missing NSEC proof
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN CNAME
+SECTION ANSWER
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-nodata.local.nsec.example. IN RRSIG
+SECTION ANSWER
+missing-nsec-nodata.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+ENTRY_END
+
+; synthesized A record was removed and replaced with SOA but no NSEC
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN A
+SECTION ANSWER
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN RRSIG
+SECTION ANSWER
+missing-nsec-masked-data.local.nsec.example. 3600 IN RRSIG A 8 2 3600 20170419140236 20170320140236 41524 nsec.example. H6auzgGxcWIcfhki7px+Iza4QRw5V47GXpPFDofXoORBdGtVYOhx+ILM pYA8ng4rzYCRFh/g9j8lIzU9y9WDfJyy8CMAJUsjiin/b9iJ0heQQU9r GmV1v+MvNxlcfMdJrec2O31RKBt7bK/FFesD4l3c3+XauwsOIsry+4t6 48uzUO48QVsbuw0PPDH82fPpSNgWyiAIEVwzz/tgrekk4eDwTVUkle4A 9ntjr5CFyKuoeDVTr0rZdJ90W6j4KYRUuk3x1V5w8eil7pNIN3arBzEv OXg4Du3AYskQ98a1VWz7MO/MX9u5WciXSbpDdI/2VtxMeKzkPotDds65 zLIsTA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+local.nsec.example. IN NS
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+*.nsec.example. 3600 IN NSEC ns.nsec.example. A RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+*.nsec.example. 3600 IN RRSIG NSEC 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Hp/6sgDgYZuewpSkAugLRERgVAGgAIAN9vAqfuAGcqCxfQXLIXcXD8ji o4rjuSMmAaRw0AQ70pEWldc2Yqre+++/lnEJt5tpGrIhH2raJU9RS/Ix NaN40vwspRdN7tDNLH1T0oTDll76bVc/D4VFtnpGOlM3eIGjFVVdACvZ V0oVW8xp686xwB3uP2DqA0fxMjs4p9PC1FrnTAlGvTX0ThgZR6EmmWJH HCy4kpjfTFR93k/nuAendDVVZNkHL+EncojmUX+U0PRSZPXWBWXbb0kq h1OVaT4HpyWKet+PxKkTGaoNbXRk0BAKC/4Qg4A/+kRk+1OXG4dQMdsS zLnt/Q==
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+aaa.local.nsec.example. IN CNAME
+ENTRY_END
+
+; recursion happens here, we expect NODATA with wildcard proof
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+aaa.local.nsec.example. IN CNAME
+SECTION AUTHORITY
+nsec.example. 3600 IN SOA ns.nsec.example. root.nsec.example. 6 60 60 120 3600
+*.nsec.example. 3600 IN NSEC ns.nsec.example. A RRSIG NSEC
+nsec.example. 3600 IN RRSIG SOA 8 2 3600 20170419140236 20170320140236 41524 nsec.example. gZCIxxFWL04vgzuNbZYq3Ghb7OZsZCp1WCcByM602yEgf0IUk8KSqkol pTem3IXQELhFTzbddGFV3Cis5MxZq8XjNbSwXelbUkOkKE4EzDcpldtR yqGnp+ZdZhBrymZvS8dOhwOGllF6AobXx7iFHaY7wtC17XvODduxOBdV mQ/t2QDUnl+Io3s1KfDRf4e22WvtatlQNr9NW+PueeGtGhEdDeyR7VMA fxEqL6Lds7NWN7DPKfsCVgUNkwHzy9opQ64AyVyQAmwRohuon652jKiu MbvJ1vaLxJLeDBnnT3hbMrI/CIfmjqucSOgM9JNXXggIcfBxok5Ze2R5 SL35VA==
+*.nsec.example. 3600 IN RRSIG NSEC 8 2 3600 20170419140236 20170320140236 41524 nsec.example. Hp/6sgDgYZuewpSkAugLRERgVAGgAIAN9vAqfuAGcqCxfQXLIXcXD8ji o4rjuSMmAaRw0AQ70pEWldc2Yqre+++/lnEJt5tpGrIhH2raJU9RS/Ix NaN40vwspRdN7tDNLH1T0oTDll76bVc/D4VFtnpGOlM3eIGjFVVdACvZ V0oVW8xp686xwB3uP2DqA0fxMjs4p9PC1FrnTAlGvTX0ThgZR6EmmWJH HCy4kpjfTFR93k/nuAendDVVZNkHL+EncojmUX+U0PRSZPXWBWXbb0kq h1OVaT4HpyWKet+PxKkTGaoNbXRk0BAKC/4Qg4A/+kRk+1OXG4dQMdsS zLnt/Q==
+ENTRY_END
+
+;; TODO: use INCLUDE when it's available.
+;; Aggressive cache can answer STEP20 without asking,
+;; from the record in previous answer, so it has been split-out for now.
+
+; missing data in NOERROR answer synthtesized from wildcard must be detected
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN A
+ENTRY_END
+
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+missing-nsec-masked-data.local.nsec.example. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/rfc5011/README b/tests/deckard/sets/resolver/rfc5011/README
new file mode 100644
index 0000000..f762956
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/README
@@ -0,0 +1,5 @@
+Start with `genkeyszones.sh` and generate DNSSEC keys + signed versions of `unsigned.db`.
+Then use `dns2rpl.py` to run Knot DNS server with signed zone
+and to generate RPL file from server's answers.
+
+See comments in script headers to further details.
diff --git a/tests/deckard/sets/resolver/rfc5011/dns2rpl.py b/tests/deckard/sets/resolver/rfc5011/dns2rpl.py
new file mode 100755
index 0000000..5a12743
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/dns2rpl.py
@@ -0,0 +1,182 @@
+#!/usr/bin/python3
+"""
+Generate RFC 5011 test simulating succesfull KSK roll-over in 2017.
+
+Depedencies: Knot DNS server + Deckard library.
+Environment: Set PYTHONPATH variable so "import pydnstest" will use module from Deckard.
+Input: Root zone files, presumably created by genkeyszones.sh.
+Output: RPL file for Deckard on standard output.
+"""
+
+import copy
+import datetime
+import os.path
+import subprocess
+import time
+
+import dns.resolver
+
+import pydnstest.scenario
+
+
+def store_answer(qname, qtype, template):
+ answ = dns.resolver.query(qname, qtype, raise_on_no_answer=False)
+ entr = copy.copy(template)
+ entr.message = answ.response
+ return entr
+
+
+def resolver_init():
+ """
+ Configure dns.resolver to ask ::1@5353 with EDNS0 DO set.
+ """
+ dns.resolver.reset_default_resolver()
+ dns.resolver.default_resolver.use_edns(0, dns.flags.DO, 4096)
+ dns.resolver.default_resolver.nameservers = ['::1']
+ dns.resolver.default_resolver.nameserver_ports = {'::1': 5353}
+ dns.resolver.default_resolver.flags = 0
+
+
+def get_templates():
+ """
+ Return empty objects for RANGE and ENTRY suitable as object templates.
+ """
+ empty_case, _ = pydnstest.scenario.parse_file(os.path.realpath('empty.rpl'))
+
+ rng = copy.copy(empty_case.ranges[0])
+
+ entry = copy.copy(rng.stored[0])
+ entry.adjust_fields = ['copy_id']
+ entry.match_fields = ['opcode', 'question']
+
+ rng.addresses = {'198.41.0.4', '2001:503:ba3e::2:30'}
+ rng.stored = []
+
+ return rng, entry
+
+
+def generate_range(filename, rng_templ, entry_templ):
+ """
+ Run Knot DNS server with specified zone file and generate RANGE object.
+ """
+ assert filename.startswith('20')
+ assert filename.endswith('.db')
+ try:
+ os.unlink('root.db')
+ except FileNotFoundError:
+ pass
+ os.link(filename, 'root.db')
+
+ # run server
+ knotd = subprocess.Popen(['/usr/local/sbin/knotd', '-c', 'knot.root.conf'])
+ time.sleep(0.1) # give kresd time to start so we do not wait for first timeout
+
+ # query data
+ rng = copy.copy(rng_templ)
+ rng.stored = []
+ rng.stored.append(store_answer('.', 'SOA', entry_templ))
+ rng.stored.append(store_answer('.', 'DNSKEY', entry_templ))
+ rng.stored.append(store_answer('.', 'NS', entry_templ))
+ rng.stored.append(store_answer('rootns.', 'NS', entry_templ))
+ rng.stored.append(store_answer('rootns.', 'A', entry_templ))
+ rng.stored.append(store_answer('rootns.', 'AAAA', entry_templ))
+ rng.stored.append(store_answer('test.', 'TXT', entry_templ))
+ rng.a = int(filename[:-len('.db')])
+
+ # kill server
+ knotd.kill()
+
+ return rng
+
+
+def generate_step_query(tcurr, id_prefix):
+ out = '; {0}'.format(tcurr.isoformat())
+ out += '''
+STEP {0}000000 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+test. IN TXT
+ENTRY_END
+'''.format(id_prefix)
+ return out
+
+
+def generate_step_check(id_prefix):
+ return '''STEP {0}000001 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+test. IN TXT
+SECTION ANSWER
+test. IN TXT "it works"
+ENTRY_END
+'''.format(id_prefix)
+
+
+def generate_step_elapse(tstep, id_prefix):
+ out = '; move time by {0}\n'.format(tstep)
+ out += '''STEP {0}000099 TIME_PASSES ELAPSE {1}\n\n'''.format(
+ id_prefix, int(tstep.total_seconds()))
+ return out
+
+
+def main():
+ resolver_init()
+ rng_templ, entry_templ = get_templates()
+ ranges = []
+
+ # transform data in zones files into RANGEs
+ files = os.listdir()
+ files.sort()
+ for fn in files:
+ if not fn.endswith('.db') or not fn.startswith('20'):
+ continue
+ ranges.append(generate_range(fn, rng_templ, entry_templ))
+
+ # connect ranges
+ for i in range(1, len(ranges)):
+ ranges[i - 1].b = ranges[i].a - 1
+ ranges[-1].b = 99999999999999
+
+ # steps
+ steps = []
+ tstart = datetime.datetime(year=2017, month=7, day=1)
+ tend = datetime.datetime(year=2017, month=12, day=31, hour=23, minute=59, second=59)
+ tstep = datetime.timedelta(days=1)
+ tcurr = tstart
+ while tcurr < tend:
+ id_prefix = tcurr.strftime('%Y%m%d')
+ steps.append(generate_step_query(tcurr, id_prefix))
+ steps.append(generate_step_check(id_prefix))
+ steps.append(generate_step_elapse(tstep, id_prefix))
+ tcurr += tstep
+
+ # generate output
+ with open('keys/ds') as dsfile:
+ ta = dsfile.read().strip()
+
+ # constant RPL file header
+ print("""stub-addr: 2001:503:ba3e::2:30
+ trust-anchor: {ta}
+ val-override-date: 20170701000000
+ query-minimization: off
+ CONFIG_END
+
+ SCENARIO_BEGIN Simulation of successfull RFC 5011 KSK roll-over during 2017
+ """.format(ta=ta))
+ for rng in ranges:
+ print(rng)
+
+ for step in steps:
+ print(step)
+
+ # constant RPL file footer
+ print('''
+ SCENARIO_END
+ ''')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/deckard/sets/resolver/rfc5011/empty.rpl b/tests/deckard/sets/resolver/rfc5011/empty.rpl
new file mode 100644
index 0000000..295d5a5
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/empty.rpl
@@ -0,0 +1,20 @@
+stub-addr: 127.0.0.10
+CONFIG_END
+
+SCENARIO_BEGIN empty replies
+
+RANGE_BEGIN 0 100
+ ADDRESS 127.0.0.10
+ENTRY_BEGIN
+MATCH subdomain
+ADJUST copy_id copy_query
+SECTION QUESTION
+. IN A
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/rfc5011/genkeyszones.sh b/tests/deckard/sets/resolver/rfc5011/genkeyszones.sh
new file mode 100755
index 0000000..8e650cb
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/genkeyszones.sh
@@ -0,0 +1,90 @@
+#!/usr/bin/bash
+
+# First, generate DNSSEC keys with timers set to simulate 2017 KSK roll-over.
+# Second, fake system time to pretend that we are at the beginning on time slots
+# used during 2017 and sign our fake root zone.
+
+# Depends on libfaketime + dnssec-keygen and dnssec-signzone from BIND 9.11.
+
+# Output: Bunch of DNSSEC keys + several versions of signed root zone.
+
+set -o nounset -o errexit -o xtrace
+
+GEN="dnssec-keygen -r /dev/urandom -K keys/ -a RSASHA256 -b 2048 -L 21d"
+
+function sign {
+ OUTFILE="$(echo "$1" | sed 's/[- :]//g').db"
+ TZ=UTC \
+ LD_PRELOAD="/usr/lib64/faketime/libfaketimeMT.so.1" \
+ FAKETIME="$1" \
+ dnssec-signzone \
+ -r /dev/urandom \
+ -K keys/ \
+ -o . \
+ -S \
+ -T 21d \
+ -s now \
+ -e +14d \
+ -X +21d \
+ -O full \
+ -f "${OUTFILE}" \
+ unsigned.db
+
+ # DS for the very first KSK
+ test ! -f keys/ds && dnssec-dsfromkey -2 -f "${OUTFILE}" . > keys/ds || : initial DS RR already exists
+}
+
+rm -f 20*.db
+rm -f keys/K*
+rm -f keys/ds
+mkdir -p keys/
+
+# old KSK
+${GEN} -f KSK -P 20100715000000 -A 20100715000000 -I 20171011000000 -R 20180111000000 -D 20180322000000 .
+# new KSK
+${GEN} -f KSK -P 20170711000000 -A 20171011000000 .
+
+# ZSK before roll-over: 2017-Q2
+${GEN} -P 20170320000000 -A 20170401000000 -I 20170701000000 -D 20170711000000 .
+# ZSK-q1: 2017-Q3
+${GEN} -P 20170621000000 -A 20170701000000 -I 20171001000000 -D 20171011000000 .
+# ZSK-q2: 2017-Q4
+${GEN} -P 20170919000000 -A 20171001000000 -I 20180101000000 -D 20180111000000 .
+# ZSK-q3: 2018-Q1
+${GEN} -P 20171220000000 -A 20180101000000 -I 20180401000000 -D 20180411000000 .
+# ZSK: 2018-Q2
+${GEN} -P 20180322000000 -A 20180401000000 .
+
+
+# hopefully slots according to
+# https://www.icann.org/en/system/files/files/ksk-rollover-operational-implementation-plan-22jul16-en.pdf
+# https://data.iana.org/ksk-ceremony/29/KC29_Script_Annotated.pdf
+sign "2017-07-01 00:00:00" # 2017 Q3 slot 1
+sign "2017-07-11 00:00:00" # 2017 Q3 slot 2
+sign "2017-07-21 00:00:00" # 2017 Q3 slot 3
+sign "2017-07-31 00:00:00" # 2017 Q3 slot 4
+sign "2017-08-10 00:00:00" # 2017 Q3 slot 5
+sign "2017-08-20 00:00:00" # 2017 Q3 slot 6
+sign "2017-08-30 00:00:00" # 2017 Q3 slot 7
+sign "2017-09-09 00:00:00" # 2017 Q3 slot 8
+sign "2017-09-19 00:00:00" # 2017 Q3 slot 9
+
+sign "2017-10-01 00:00:00" # 2017 Q4 slot 1
+sign "2017-10-11 00:00:00" # 2017 Q4 slot 2
+sign "2017-10-21 00:00:00" # 2017 Q4 slot 3
+sign "2017-10-31 00:00:00" # 2017 Q4 slot 4
+sign "2017-11-10 00:00:00" # 2017 Q4 slot 5
+sign "2017-11-20 00:00:00" # 2017 Q4 slot 6
+sign "2017-11-30 00:00:00" # 2017 Q4 slot 7
+sign "2017-12-10 00:00:00" # 2017 Q4 slot 8
+sign "2017-12-20 00:00:00" # 2017 Q4 slot 9
+
+# 2018-01-01 00:00:00 # 2018 Q1 slot 1
+# 2018-01-11 00:00:00 # 2018 Q1 slot 2
+# 2018-01-21 00:00:00 # 2018 Q1 slot 3
+# 2018-01-31 00:00:00 # 2018 Q1 slot 4
+# 2018-02-10 00:00:00 # 2018 Q1 slot 5
+# 2018-02-20 00:00:00 # 2018 Q1 slot 6
+# 2018-03-02 00:00:00 # 2018 Q1 slot 7
+# 2018-03-12 00:00:00 # 2018 Q1 slot 8
+# 2018-03-22 00:00:00 # 2018 Q1 slot 9
diff --git a/tests/deckard/sets/resolver/rfc5011/knot.root.conf b/tests/deckard/sets/resolver/rfc5011/knot.root.conf
new file mode 100644
index 0000000..5e20747
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/knot.root.conf
@@ -0,0 +1,26 @@
+#
+# Minimal configuration file for Knot DNS server used by dns2rpl.py.
+#
+
+server:
+ # Listen on all configured IPv4 interfaces.
+ listen: 0.0.0.0@5353
+ # Listen on all configured IPv6 interfaces.
+ listen: ::@5353
+ # User for running the server.
+ # user: knot:knot
+# Log info and more serious events to syslog.
+log:
+ - target: stderr
+ any: debug
+
+template:
+# - id: default
+# storage: "/usr/local/var/lib/knot"
+
+zone:
+# Master zone.
+ - domain: .
+ storage: "."
+ file: "root.db"
+
diff --git a/tests/deckard/sets/resolver/rfc5011/unsigned.db b/tests/deckard/sets/resolver/rfc5011/unsigned.db
new file mode 100644
index 0000000..b837acd
--- /dev/null
+++ b/tests/deckard/sets/resolver/rfc5011/unsigned.db
@@ -0,0 +1,8 @@
+. 86400 IN SOA rootns. you.test. 2017071100 1800 900 604800 86400
+
+. 518400 IN NS rootns.
+
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+
+test. 1 IN TXT "it works"
diff --git a/tests/deckard/sets/resolver/val_ad_qtype_ds.rpl b/tests/deckard/sets/resolver/val_ad_qtype_ds.rpl
new file mode 100644
index 0000000..365b33e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ad_qtype_ds.rpl
@@ -0,0 +1,196 @@
+; config options
+ stub-addr: 193.0.14.129
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD0888 5C36700F"
+ val-override-date: "20170807130000"
+CONFIG_END
+
+SCENARIO_BEGIN Test setting AD bit in secured answer which contains proof of DS record non-existence
+
+RANGE_BEGIN 1 2
+ ADDRESS 193.0.14.129 ;k.root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+. IN SOA
+SECTION ANSWER
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170831093859 20170801093859 20661 . wYDoBQrcHODYzOxqM+P+gOfgi4HCFNtdhnIZtuoc2vujg6J9U3zYUg3H u78cOyqEJ/H6iTxnVGmJvGYSh+Cf0TiDfgDL0TbQrfisTtAKOGNbLVb0 wfGzroQ08c2i/R2xXyN6ZA/0ywYdyJe1bhRlWcDGhbUTDpKBhMAFxCZe NaIt/gT1TCODgjgHsRMjj3uxxtPef3/A3+x4iUt9PdQxTJoPXo21nEin PY4ByO80QYYa8iomOJG7PauhhZk4/md03bSU1F+AlniiuiFHNsvdpyxO qimsB9sQW5sr1wVgQ25BKlUrwwqeTE+gEECR5BGF29YjRHLN5OEban4N 1Lv3SA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170831093859 20170801093859 20661 . tRUB/UNRUgLH8jn9wda2CjPW3+2IuahZXB3LyPiP+ENd8Tu37WuYr9R9 a0Pi1/WSrliQtmxNCbmbPi36EBo0Wi4YXAEuaD6ip3ARC0QBWstzlMnN ea1IgiWoP61NtauuElQzRb6PL03cmg1ouElvlncMNkhkzupHIee060Ok OSHPk4scXnAaxJ4dASLZCYza6C2k0VqCMI2qJ8kDlfm2/Lt8PPFyhGYa bQaO4zzOecg2dvDDSdw4STBjL3K84enZ/ilTo81zrM1O4SNe2TYm8C37 cMlNXQ+XB0O4+18UzjNDKCMfJ1H6rXt6A52MU2ZONOT6U+eanM7RKfZd 6NSTYw==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170831093859 20170801093859 20661 . q3gs2/4X9gIYWZ0nR/ADRFFgeJaaJ/jmXysnMa2I+uuuPutjegwudOCe qEG7NKc/S0Sb90KspvAfWBb4E8UeBlkgNk4aGrzM5lNWinEJ7lszUn7Z 3kpg7m1xyzgt0YxOxrQiyznA4x2wom/66G7Bc8XkajSV7+6+ZIHxQqid hVFq2zg2UdfNVMTXHfaCrtQrTxQJZ19M+IJmGIjFjomIyrE4BEiL6IcM vyK9/kdWL892wMwYxlAoMWIHPz2mU5WbmOPqgEzd8Wwc7RwTZFgE6wqL vo6JZDRME70ScN4iIXQHfVcJMYJscoFiMfhnrlOfbeB1dDKjBcWimCf4 uJ2hDw==
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170831093859 20170801093859 49060 . lpsdS4U/p63Jl4YimV5+S0jxuMZoFPGiskKCUOhdUS6pN2yoFAHDVsx6 MmbswhIw9NFSmjuxuWvz4iSuLIEL4L7CFSK0g/RNJx2MabJJS40ZONJy sDFRNvBROwPI8AgOdXuimWausYHwJU3MG+q15GC0k31WTA3JPhDXpfCx ULusODH4FwjrvuQMVSZId0hF7LLrH4/rTEVE/EkXohQ2/all51v8OEn3 8zulw9nol1w0rAYpGV3BNWUYtHKY64eZHOxlArvWFZbf5R1JV0MAsa2U zqjBwI3dMTyVPIerLcR77dPNCMXNxo/81Ye37YA/H8ABTda67SPhD+hf GcP6Tg==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+. IN RRSIG
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+test. IN NS
+SECTION ANSWER
+test. IN NS ns.net
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+test. IN DS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+test. 86400 IN NSEC . NS RRSIG NSEC
+. 86400 IN RRSIG SOA 8 0 86400 20170831093859 20170801093859 20661 . wYDoBQrcHODYzOxqM+P+gOfgi4HCFNtdhnIZtuoc2vujg6J9U3zYUg3H u78cOyqEJ/H6iTxnVGmJvGYSh+Cf0TiDfgDL0TbQrfisTtAKOGNbLVb0 wfGzroQ08c2i/R2xXyN6ZA/0ywYdyJe1bhRlWcDGhbUTDpKBhMAFxCZe NaIt/gT1TCODgjgHsRMjj3uxxtPef3/A3+x4iUt9PdQxTJoPXo21nEin PY4ByO80QYYa8iomOJG7PauhhZk4/md03bSU1F+AlniiuiFHNsvdpyxO qimsB9sQW5sr1wVgQ25BKlUrwwqeTE+gEECR5BGF29YjRHLN5OEban4N 1Lv3SA==
+test. 86400 IN RRSIG NSEC 8 1 86400 20170831093859 20170801093859 20661 . BjSarwsXmvmeIXuEZyCKpFpB6eU8w+Nz98pGxp7B18BZGysjjAHEV+Y+ +aqGX0KP9S3ZdKO4zc8p4iBUbCzprN80Zkn/1eIZnbil4zZsnxkqXgZG 0hcUK/H2ximacRtL0ITEmQ0iTykFzo9OVgv+OgKigyBqZvziahPVhN8/ zl/wbqGdVx8UUgvvMUsTITSWdfZt3UK6KKVpQIrwuJroaVLvc69uxkLm 1ZCHe1FTf385yf7pKLD3vkJ2rWh4MZHwls6YQXUCDv4jf7D+rXIde/Jk SB9yko98xcu+ccdoCoFWzoBI2Ep0Io4bV40Izq+NwiYmMOpPL03SQrOq WRImyQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA REFUSED
+SECTION QUESTION
+test. IN RRSIG
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170831093859 20170801093859 20661 . wYDoBQrcHODYzOxqM+P+gOfgi4HCFNtdhnIZtuoc2vujg6J9U3zYUg3H u78cOyqEJ/H6iTxnVGmJvGYSh+Cf0TiDfgDL0TbQrfisTtAKOGNbLVb0 wfGzroQ08c2i/R2xXyN6ZA/0ywYdyJe1bhRlWcDGhbUTDpKBhMAFxCZe NaIt/gT1TCODgjgHsRMjj3uxxtPef3/A3+x4iUt9PdQxTJoPXo21nEin PY4ByO80QYYa8iomOJG7PauhhZk4/md03bSU1F+AlniiuiFHNsvdpyxO qimsB9sQW5sr1wVgQ25BKlUrwwqeTE+gEECR5BGF29YjRHLN5OEban4N
+. 86400 IN NSEC ns.net. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20170831093859 20170801093859 20661 . o4mpXOChyzVuB08Yu18oUFyNw+rYlia6nNe05ESNkW3sx+umUTX7SvzO 4QrpOIGqflr2Jxks5kLMK6b3q0pDq/d1Z5zAMIlOHsjtMYvVqz4LJHiu kqsoKKBSxY6LEfsalcRE02VhSNuQLZXiUDbeErO1kBU05fIAc7lfefS1 iNqUvZ2u6u3SiEJISWu0l7+IVPCd/0DaoQUsp2ja3MuYOM36sYsa8yxE /lDqHzgSj+qBn2fMUcu9CEzNwVXhAK65ngu6rSlbhG+NdAkpHRgsKXxL qSC/iFoGm2cZ1idMCijIdoj6/qf2aMPh7ThrfXaHmf5ZhePXxdqIrmPO IpU3Ww==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170831093859 20170801093859 20661 . wYDoBQrcHODYzOxqM+P+gOfgi4HCFNtdhnIZtuoc2vujg6J9U3zYUg3H u78cOyqEJ/H6iTxnVGmJvGYSh+Cf0TiDfgDL0TbQrfisTtAKOGNbLVb0 wfGzroQ08c2i/R2xXyN6ZA/0ywYdyJe1bhRlWcDGhbUTDpKBhMAFxCZe NaIt/gT1TCODgjgHsRMjj3uxxtPef3/A3+x4iUt9PdQxTJoPXo21nEin PY4ByO80QYYa8iomOJG7PauhhZk4/md03bSU1F+AlniiuiFHNsvdpyxO qimsB9sQW5sr1wVgQ25BKlUrwwqeTE+gEECR5BGF29YjRHLN5OEban4N
+. 86400 IN NSEC ns.net. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20170831093859 20170801093859 20661 . o4mpXOChyzVuB08Yu18oUFyNw+rYlia6nNe05ESNkW3sx+umUTX7SvzO 4QrpOIGqflr2Jxks5kLMK6b3q0pDq/d1Z5zAMIlOHsjtMYvVqz4LJHiu kqsoKKBSxY6LEfsalcRE02VhSNuQLZXiUDbeErO1kBU05fIAc7lfefS1 iNqUvZ2u6u3SiEJISWu0l7+IVPCd/0DaoQUsp2ja3MuYOM36sYsa8yxE /lDqHzgSj+qBn2fMUcu9CEzNwVXhAK65ngu6rSlbhG+NdAkpHRgsKXxL qSC/iFoGm2cZ1idMCijIdoj6/qf2aMPh7ThrfXaHmf5ZhePXxdqIrmPO IpU3Ww==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+ns.net. IN A
+SECTION ANSWER
+ns.net. 600 IN A 1.1.1.1
+ns.net. 600 IN RRSIG A 8 2 600 20170831093859 20170801093859 20661 . mOCn7tQWemwBfXtGUSexyMARUQFmWH6Sk6Z6U1HRB3dn7yZxHYf+tw/+ 3bLHv38zeqdOU0cgUMDsthWkzFfKDL+CgW/dNO6oY/9UmX0p8mqgQ5Yw J4uH82il0TBlbnr4TkNz27EQgGiQvKdOyEPW5/+Ogh1M0b228jMY0DzV gzk9shaGZGH7mzJyKX9JPtG+sEvx6YsNTN3MP4s5JBaIk3sMczz+szb4 nmx+AvIuJnTQXq/dH/emTR/JzPsSZryadtf/Y+zOQnVg3YcaUs9yaIFj 4aq1aRMPPX6asCKliOeixC4qPR/fJkaVtN7Q3oiE0M3ci2jAj1JJLL6g /fDfZA==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170831093859 20170801093859 20661 . WkAHLRnyepbR5iqggYRyFmUIgXhZpnyEL/CUlQ/AEf5c6so1cmWlzVXd TuuUtkNbkVEq8bbvOxa1jFF01vVituLlwn1wEuTdfpgOBDOHxf5/jASm CZ+/31Lln3scmDVRuAyKDO9tvR0O6N/WKFOYcGhrtfQ21P4f58aFLy11 F4kKpARwyhBMhB4/MpmOMKcWhTx8Fyackwl20uBZMi85+aBhR2eJMloN YEvphzLvBwvNTaNrXBlDrtz6Kbrr0akRdd2jFoyRe+0DGSEvI7ujaMuo +v+yxg6qW6q125R7++69vis2HRbm1Hjb23EbH+AH7H9mL+royo0+GY3C 5fYUeg==
+
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 2
+ ADDRESS 1.1.1.1 ;ns.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+test. IN SOA
+SECTION ANSWER
+test. 86400 IN SOA ns.net. hostmaster.example.com. 1234 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+test. IN NS
+SECTION ANSWER
+test. IN NS ns.net
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.net. IN A
+SECTION ANSWER
+ns.net. 86400 IN A 1.1.1.1
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD AD DO
+SECTION QUESTION
+test. IN DS
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR ; AD flag is set
+SECTION QUESTION
+test. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+test. 86400 IN NSEC . NS RRSIG NSEC
+. 86400 IN RRSIG SOA 8 0 86400 20170831093859 20170801093859 20661 . wYDoBQrcHODYzOxqM+P+gOfgi4HCFNtdhnIZtuoc2vujg6J9U3zYUg3H u78cOyqEJ/H6iTxnVGmJvGYSh+Cf0TiDfgDL0TbQrfisTtAKOGNbLVb0 wfGzroQ08c2i/R2xXyN6ZA/0ywYdyJe1bhRlWcDGhbUTDpKBhMAFxCZe NaIt/gT1TCODgjgHsRMjj3uxxtPef3/A3+x4iUt9PdQxTJoPXo21nEin PY4ByO80QYYa8iomOJG7PauhhZk4/md03bSU1F+AlniiuiFHNsvdpyxO qimsB9sQW5sr1wVgQ25BKlUrwwqeTE+gEECR5BGF29YjRHLN5OEban4N 1Lv3SA==
+test. 86400 IN RRSIG NSEC 8 1 86400 20170831093859 20170801093859 20661 . BjSarwsXmvmeIXuEZyCKpFpB6eU8w+Nz98pGxp7B18BZGysjjAHEV+Y+ +aqGX0KP9S3ZdKO4zc8p4iBUbCzprN80Zkn/1eIZnbil4zZsnxkqXgZG 0hcUK/H2ximacRtL0ITEmQ0iTykFzo9OVgv+OgKigyBqZvziahPVhN8/ zl/wbqGdVx8UUgvvMUsTITSWdfZt3UK6KKVpQIrwuJroaVLvc69uxkLm 1ZCHe1FTf385yf7pKLD3vkJ2rWh4MZHwls6YQXUCDv4jf7D+rXIde/Jk SB9yko98xcu+ccdoCoFWzoBI2Ep0Io4bV40Izq+NwiYmMOpPL03SQrOq WRImyQ==
+
+ENTRY_END
+
+SCENARIO_END \ No newline at end of file
diff --git a/tests/deckard/sets/resolver/val_adbit.rpl b/tests/deckard/sets/resolver/val_adbit.rpl
new file mode 100644
index 0000000..2823e81
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_adbit.rpl
@@ -0,0 +1,172 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 6224 7 1 79120CA22E585593836A1F7F261ED6295627C77A "
+val-override-date: "20181130121814"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator AD bit signaling
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101814 20181130101814 6224 example.com. ESn6yJxsNZI197N+QTzEanisVKGGIc6mUugEBCcFOA7UUL6mbqx7It1k Yg/sFKnjpsmRYCPVR7Wa3K5f2yj7HOKXEcJ+7iNJ3lNG2QtgtaAIkBqa f9BFs1JVJqnlJ3w6XCUfxTmjtLepYKXgOwGg+SGI3GNLGx7EBkOJie1F JYo= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101814 20181130101814 6224 example.com. lgLIbRjRpUYJ6WuSWSpOljVYdDoWQiC+NndpFpPb9EIlk3tXgbE3gmpk hbQ4Nj2tRoje9UpDV3GNath1ZBZEKBovVGCCb8n7d5e+VvuIJMHreD3i 33VTfIaM3NOS6v+vZM5ZUGC7QTkczqHwrC8SPZMUqM9EA4cABYhkSMFy yoU= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAa+IW+C5GZhaOvN6/UjjowGAVDC2/BoGwILcFw5c6RL/30LHrM1f b3Qs9s9Z2u8xZz0VVwrb70eQlYkcdgMUXqI+eplu0OdXI2skN4nHkSkr OeEfA1ISNCchqRmLdONRobPTcBEYYbJWDiuwDmShpitVYT4KZhpIJErh Vzqf5e2V ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101814 20181130101814 6224 example.com. WidInu/eUjNWNA6oF+TspmaUHXTx3TLpmA2ET4QPeRVvH3K0YIBGuVfA NLZvawiKvWfkwZfgVj9As/T2PBOK+9HENOMIXkxMQWcXVBy8KompOGOR T9ENoMWto3CXZEmc7kMtYZtxr5CXsGf4eEJ4AKZNbnwFCaHCtIhlhSIP pa8= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101814 20181130101814 6224 example.com. ESn6yJxsNZI197N+QTzEanisVKGGIc6mUugEBCcFOA7UUL6mbqx7It1k Yg/sFKnjpsmRYCPVR7Wa3K5f2yj7HOKXEcJ+7iNJ3lNG2QtgtaAIkBqa f9BFs1JVJqnlJ3w6XCUfxTmjtLepYKXgOwGg+SGI3GNLGx7EBkOJie1F JYo= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101814 20181130101814 6224 example.com. lgLIbRjRpUYJ6WuSWSpOljVYdDoWQiC+NndpFpPb9EIlk3tXgbE3gmpk hbQ4Nj2tRoje9UpDV3GNath1ZBZEKBovVGCCb8n7d5e+VvuIJMHreD3i 33VTfIaM3NOS6v+vZM5ZUGC7QTkczqHwrC8SPZMUqM9EA4cABYhkSMFy yoU= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101814 20181130101814 6224 example.com. WBUrYLsgHSpl6O4O0WsXydo4AfgF3n2YbLQV9ViOv7CQIeucPMKedjqZ hpr1rmmd8gZU+IGd/RBwIXsiNyC0Y7npNnuBX8Na3FOTWXRiJaorboxh 1UpP6cyEvgMWuV5JqeAql75/8m5Qo/e7pcTQllUoooRuS+HJejkU6R66 Bjo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101814 20181130101814 6224 example.com. ESn6yJxsNZI197N+QTzEanisVKGGIc6mUugEBCcFOA7UUL6mbqx7It1k Yg/sFKnjpsmRYCPVR7Wa3K5f2yj7HOKXEcJ+7iNJ3lNG2QtgtaAIkBqa f9BFs1JVJqnlJ3w6XCUfxTmjtLepYKXgOwGg+SGI3GNLGx7EBkOJie1F JYo= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101814 20181130101814 6224 example.com. lgLIbRjRpUYJ6WuSWSpOljVYdDoWQiC+NndpFpPb9EIlk3tXgbE3gmpk hbQ4Nj2tRoje9UpDV3GNath1ZBZEKBovVGCCb8n7d5e+VvuIJMHreD3i 33VTfIaM3NOS6v+vZM5ZUGC7QTkczqHwrC8SPZMUqM9EA4cABYhkSMFy yoU= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; ask from cache too
+STEP 21 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 23 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_adcopy.rpl b/tests/deckard/sets/resolver/val_adcopy.rpl
new file mode 100644
index 0000000..76b5e9e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_adcopy.rpl
@@ -0,0 +1,164 @@
+; config options
+; The island of trust is at example.com
+;server:
+; trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator AD bit sent by untrusted upstream
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RA AD NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RA AD NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+; ask from cache too
+STEP 21 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 23 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_anchor_nx_nosig.rpl b/tests/deckard/sets/resolver/val_anchor_nx_nosig.rpl
new file mode 100644
index 0000000..74178ae
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_anchor_nx_nosig.rpl
@@ -0,0 +1,218 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with unsigned denial of trust anchor
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response for sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854}
+blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC
+blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854}
+example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854}
+blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC
+blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854}
+example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION AUTHORITY
+example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854}
+blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC
+blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854}
+example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NXDOMAIN
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854}
+blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC
+blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854}
+example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ans_dsent.rpl b/tests/deckard/sets/resolver/val_ans_dsent.rpl
new file mode 100644
index 0000000..d016ce8
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ans_dsent.rpl
@@ -0,0 +1,246 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 5969 7 1 A4AC909154F325EA3F437CD0626ABB2C039E9C50 "
+val-override-date: "20181130121817"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with empty nonterminals on the trust chain.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101817 20181130101817 5969 example.com. Wg9pfH674/AQOaiB7c4EKHYPJp81/v3o5w4GreQBjCr6nx759rE74DLg uLyeldgMaAO+PZD6EXcyuV9acrfLbR+unhUbWHXRktkRrUwJf/5+WsCp yITuzmCezNL7bRrW+f8mxa5pkm7IfaSAoUmu54c/dP5QnbwGZoUK3ObY Ztg= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101817 20181130101817 5969 example.com. TYw9E6WMcbN6izjKoga5IEBGweWCXVpgKEjcWYZcBkEcFZX/hr7eyHok qnGsOi+hHwyMt6EatU2JU0A9WAQzosDxw3xib8F9mk2GlNlpbmrsRwec x6MuPCD5Ur4+GKwevmQOe8mxsqMXdbLKXT56WU2tPBtKsFxQlAS7JA9t pAY= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAeDMFHMvUzUDUFCAAJryyhH1w3V/mHk+Y2wpcMy37G+Ur1JTrIS+ fz1USHOaoNO+ynyCq3XqRbik8vXHUi3oOyLjEu+xTRjLuEgtB4GrEZSV 8umKzMVJZI335YOuAfvPrvA+Ish2hRg+H0otRnNAwqUshFgMRGX1UnjL oo9EwWu1 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101817 20181130101817 5969 example.com. jHGQFzBToq7eUEWW30SDECUfcQJagrP8IbREf+hwKBHEWLEY2E0acQN6 ce/+3DJJHwVF0VTX4Jdo0l43hlOp+bRUBLzsvoWToWtdt2S3nJy1Ay4e +DdockqRbUvs4X16HuYBIL2wxnispH1PRoUUvnF6Aeq4egCQiIx4+SOF pRs= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101817 20181130101817 5969 example.com. Wg9pfH674/AQOaiB7c4EKHYPJp81/v3o5w4GreQBjCr6nx759rE74DLg uLyeldgMaAO+PZD6EXcyuV9acrfLbR+unhUbWHXRktkRrUwJf/5+WsCp yITuzmCezNL7bRrW+f8mxa5pkm7IfaSAoUmu54c/dP5QnbwGZoUK3ObY Ztg= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101817 20181130101817 5969 example.com. TYw9E6WMcbN6izjKoga5IEBGweWCXVpgKEjcWYZcBkEcFZX/hr7eyHok qnGsOi+hHwyMt6EatU2JU0A9WAQzosDxw3xib8F9mk2GlNlpbmrsRwec x6MuPCD5Ur4+GKwevmQOe8mxsqMXdbLKXT56WU2tPBtKsFxQlAS7JA9t pAY= ;{id = 2854}
+ENTRY_END
+
+; responses to DS empty nonterminal queries.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+194.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101817 20181130101817 5969 example.com. CdUsF1NFbkBgKLO10zT/ecIDU/059ZKRK/qsMTp2mTDMLY5BL4Q1cV+f HZWXLkz7eCgvQw4jhaycEKh65I+LdBPFGQBOPM6IJzzqjpMNZkNIAiC/ 98FfWN5MQCD9Rf/Xary2oRbQ6Hzacvc9sRABX1sY9w0n/xIpeRXQ4Zaf eV8= ;{id = 2854}
+
+; This NSEC proves the NOERROR/NODATA case.
+194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC
+194.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101817 20181130101817 5969 example.com. r/fKSY1tFbI3PkF/OvDavn08S6YCx0HJDk5Qyi0mt2sOcD2/c/Rqe+d3 FqR4OFAPQcf405CV7oScQ1/rWMqNFeJxRX1CisY3bRwFhCckXLgCCLKD dZbGNidxQtc7WbiFKZMMmfqEmS1UbpaXNycmlbH7oDmLpqLdzURKFVDM kTw= ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+; this should be NOERROR.
+REPLY QR AA NOERROR
+SECTION QUESTION
+0.194.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101817 20181130101817 5969 example.com. CdUsF1NFbkBgKLO10zT/ecIDU/059ZKRK/qsMTp2mTDMLY5BL4Q1cV+f HZWXLkz7eCgvQw4jhaycEKh65I+LdBPFGQBOPM6IJzzqjpMNZkNIAiC/ 98FfWN5MQCD9Rf/Xary2oRbQ6Hzacvc9sRABX1sY9w0n/xIpeRXQ4Zaf eV8= ;{id = 2854}
+
+; This NSEC proves the NOERROR/NODATA case.
+194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC
+194.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101817 20181130101817 5969 example.com. r/fKSY1tFbI3PkF/OvDavn08S6YCx0HJDk5Qyi0mt2sOcD2/c/Rqe+d3 FqR4OFAPQcf405CV7oScQ1/rWMqNFeJxRX1CisY3bRwFhCckXLgCCLKD dZbGNidxQtc7WbiFKZMMmfqEmS1UbpaXNycmlbH7oDmLpqLdzURKFVDM kTw= ;{id = 2854}
+
+ENTRY_END
+
+; response for delegation to sub zone.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN DS 23400 5 1 F98448C953B01B087D505FB4FCA99DFF9FF37DBD
+0.0.194.example.com. 3600 IN RRSIG DS 7 5 3600 20181230101817 20181130101817 5969 example.com. 1V7MTc/3CMbqswXWDzxwRM9sTNVKNt+W9fTWu6Zn72xDl26r3GRhYgAV 5L7JI/qmDsMSebz6qXojzf58Ev1EO9avxemg6cNQBK+Lrxo1LhFzbzyC LYwRRShPP2D+eTNlgBh6TBNpUfeBDUHGt7hOPqDUqKm7Iru3kvAEY9T1 Fqk= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub zone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN DS 23400 5 1 F98448C953B01B087D505FB4FCA99DFF9FF37DBD
+0.0.194.example.com. 3600 IN RRSIG DS 7 5 3600 20181230101817 20181130101817 5969 example.com. 1V7MTc/3CMbqswXWDzxwRM9sTNVKNt+W9fTWu6Zn72xDl26r3GRhYgAV 5L7JI/qmDsMSebz6qXojzf58Ev1EO9avxemg6cNQBK+Lrxo1LhFzbzyC LYwRRShPP2D+eTNlgBh6TBNpUfeBDUHGt7hOPqDUqKm7Iru3kvAEY9T1 Fqk= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com. for zone 0.0.194.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN NS
+SECTION ANSWER
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20181230101817 20181130101817 23400 0.0.194.example.com. cUuqSDfttEihyAPLyjzQgLqo5j3dtmQE+xNJ9stwFFL4bNr7bjlux3MS mZcGzOY5skzIK2B+ufkXh+XJVk0HOD/VjEdSyTQCO8elzKbSv6pjsx5E 48FA5scTeX67GFdiJji9Ssk/dQtIWrsmoRLzWITtVANxtrN6mvSHCKVM gHc= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+; response to DNSKEY priming query
+; 0.0.194.example.com. 3600 IN DS 23400 5 1 F98448C953B01B087D505FB4FCA99DFF9FF37DBD
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN DNSKEY
+SECTION ANSWER
+0.0.194.example.com. 3600 IN DNSKEY 256 3 5 AwEAAccLvnsSmtCYMulOPc34e+ZK1eQM6EyCmCZ0hh1dD1MD5tCR2qu5 AROP3GARZDnC14wcTFuTmX7U9JJGw7UXb+V7bNHw91v/DTr3dJkJkqYY wL08wwLPbl9jK9q6P+GcZErucXwugK+eSDdWdwZ3u0DHllby0euw7VM1 o+3oFvsZ ;{id = 30899 (zsk), size = 512b}
+0.0.194.example.com. 3600 IN RRSIG DNSKEY 5 5 3600 20181230101817 20181130101817 23400 0.0.194.example.com. EBz3F9s6y1zo2TT21XqfMmqddYaiicUjDSDDYgqTCnocF+8It4AXAf+X 85zJV08+x4APyCs5ROcYkcdtwXMC7Uj5sgPtn5UkxIF8G1UkdQzh5WSr yr0DBhqQOGNTEntIz35xQv+r3GfoXnsE2BqV8TBQ7V1AM6bnfHmQ2lHs F5I= ;{id = 30899}
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20181230101817 20181130101817 23400 0.0.194.example.com. cUuqSDfttEihyAPLyjzQgLqo5j3dtmQE+xNJ9stwFFL4bNr7bjlux3MS mZcGzOY5skzIK2B+ufkXh+XJVk0HOD/VjEdSyTQCO8elzKbSv6pjsx5E 48FA5scTeX67GFdiJji9Ssk/dQtIWrsmoRLzWITtVANxtrN6mvSHCKVM gHc= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+328.0.0.194.example.com. IN A 11.11.11.11
+328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20181230101817 20181130101817 23400 0.0.194.example.com. XqdIgy6JxkR9DYPhI4hJHZqWbHVyoqLk4Arq69Sa7SSvnIhE/Nsf0BrF /EK1XMoepiN8kR9QMnrQWk7fsE9w3PzzcecWQrQ/4Bps8g+gu6DtgNOx k5Cm6b+caRJ2oT3z+n2/7r7VdPndk1bzHOwQINOUJiQN1Q1ya4M5Nw/I c9U= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+328.0.0.194.example.com. 3600 IN A 11.11.11.11
+328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20181230101817 20181130101817 23400 0.0.194.example.com. XqdIgy6JxkR9DYPhI4hJHZqWbHVyoqLk4Arq69Sa7SSvnIhE/Nsf0BrF /EK1XMoepiN8kR9QMnrQWk7fsE9w3PzzcecWQrQ/4Bps8g+gu6DtgNOx k5Cm6b+caRJ2oT3z+n2/7r7VdPndk1bzHOwQINOUJiQN1Q1ya4M5Nw/I c9U= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ans_nx.rpl b/tests/deckard/sets/resolver/val_ans_nx.rpl
new file mode 100644
index 0000000..0223abc
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ans_nx.rpl
@@ -0,0 +1,248 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 53207 7 1 ED9E33A0CCBFAE631929D9064C69EAF91E9872E3 "
+val-override-date: "20181130121819"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DS nodata as nxdomain on trust chain
+; This is a bug in ANS 2.8.1.0 where it gives an NXDOMAIN instead of
+; NOERROR for an empty nonterminal DS query. The proof for this NXDOMAIN
+; is the NSEC that proves emptynonterminal.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101819 20181130101819 53207 example.com. 0lXU7ewAPEKEpwxF+qH+N99cfG/SFw3S+BGgky/UFgtFpzQip2o+xkOB 0Kr2e8coW7MTMMAtb4XNFqk26liB2klncvAmy8OrZBgCoz0n9RMDpiU5 5U3DCdJOonBkLZp7r/QjdwIY2RAN2ooTR5CnBxTvU8TqsFuK+qvIPZoc 1GU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101819 20181130101819 53207 example.com. ro/KUUe+1uPXGO0Y/sbylsbh26miTgZgLEBLhQPrKLpjl1l4Jcuph+4m NRYJoOnXwsqYHoAZiNIGCagi2LqIZ8hgiLSZnkFSI21xw7uZ1UKjw1yx MY0UXtWf7tF2NGY8wXctKRXkLPkP0D0vZXDIiVHRmAA3RJILXV6VSuyk ZQs= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAeENZGV8/uWkUDIdb5on+NfJs19ejJpnPECDh8pR++7WQl8fk0xm 87kirUT8v1gZzwsbr0Vb0zBi4YewFG3Xe8Ei1d57cJRHKf2uoJ6L93xm C+IPfurFRcGfJDUIWdMH1lth6GbEilxesKdt3lnqSNOln0/rU99jZ+kJ QGGn+M+7 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101819 20181130101819 53207 example.com. ScZ8gDOVfCumrFANbTXFgFFp+0uOR6r9MzJJQWYQZY1omSXUrc8dpx8a 6MEP+hJGydmMjXmL09l2ZzsKlzjGm7kdCtXZLBAnJiZ0e3+tQdpb/mJ4 cRUIrGfQF7VOckzN0oW7hlTqJjkdbfvKW7paRgMBil97Y9J0AcMj0GjW UIA= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101819 20181130101819 53207 example.com. 0lXU7ewAPEKEpwxF+qH+N99cfG/SFw3S+BGgky/UFgtFpzQip2o+xkOB 0Kr2e8coW7MTMMAtb4XNFqk26liB2klncvAmy8OrZBgCoz0n9RMDpiU5 5U3DCdJOonBkLZp7r/QjdwIY2RAN2ooTR5CnBxTvU8TqsFuK+qvIPZoc 1GU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101819 20181130101819 53207 example.com. ro/KUUe+1uPXGO0Y/sbylsbh26miTgZgLEBLhQPrKLpjl1l4Jcuph+4m NRYJoOnXwsqYHoAZiNIGCagi2LqIZ8hgiLSZnkFSI21xw7uZ1UKjw1yx MY0UXtWf7tF2NGY8wXctKRXkLPkP0D0vZXDIiVHRmAA3RJILXV6VSuyk ZQs= ;{id = 2854}
+ENTRY_END
+
+; responses to DS empty nonterminal queries.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+194.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101819 20181130101819 53207 example.com. ypY/mUi4F0lXJ5dp2XmUG2yiP/CN5EPvCHTNUCxkXGkFYA298WkvA16V u3yj/DLzDXm0x70QHWzLqNawdo3v8GzRGRJmvVSf7dXzNzOxC/SUyTdT ad8H/5XwYpQDAMy5pLlk6DC8I8xXyQIChv133eCIn6uVqjIH/Nr1lj6j +n8= ;{id = 2854}
+
+; This NSEC proves the NOERROR/NODATA case.
+194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC
+194.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101819 20181130101819 53207 example.com. mVuTRbUXm5qZJZzH980ndaNBJDgUJ57o30lNKeir6AhM2GY4Fkttntz3 p1FWDkWCX5PGBVdnUsMxA9d5tMU+hQKuAD1pv41xq8KuQYc5Csbk0GgX N0HJ5gqP9SRXdSIvHl+DM5euM3b9eA/p0a7oCJ24dwMw4mRd5vdL7CD5 SAA= ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+; Bad NXDOMAIN response, this should be NOERROR.
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+0.194.example.com. IN DS
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101819 20181130101819 53207 example.com. ypY/mUi4F0lXJ5dp2XmUG2yiP/CN5EPvCHTNUCxkXGkFYA298WkvA16V u3yj/DLzDXm0x70QHWzLqNawdo3v8GzRGRJmvVSf7dXzNzOxC/SUyTdT ad8H/5XwYpQDAMy5pLlk6DC8I8xXyQIChv133eCIn6uVqjIH/Nr1lj6j +n8= ;{id = 2854}
+
+; This NSEC proves the NOERROR/NODATA case.
+194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC
+194.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101819 20181130101819 53207 example.com. mVuTRbUXm5qZJZzH980ndaNBJDgUJ57o30lNKeir6AhM2GY4Fkttntz3 p1FWDkWCX5PGBVdnUsMxA9d5tMU+hQKuAD1pv41xq8KuQYc5Csbk0GgX N0HJ5gqP9SRXdSIvHl+DM5euM3b9eA/p0a7oCJ24dwMw4mRd5vdL7CD5 SAA= ;{id = 2854}
+
+ENTRY_END
+
+; response for delegation to sub zone.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN DS 22635 5 1 042026877E24C586D775608A2AFEE6179F5C43AF
+0.0.194.example.com. 3600 IN RRSIG DS 7 5 3600 20181230101819 20181130101819 53207 example.com. NxLJhRVh78CARarasz3Ks4lanafpN8+AsJgbiYnCQQPmn9X3fq9jbG5n KO0AlyvvcCy/W7z7KMFsMNVD1CvKCDzM2DKbTm17HaPAGXONkxGj53a1 OLn1+hXQ3O+4Th2lNfsUDmk0cMCIyRJetNVBTnz0ywXBHNiQIfyzsGHY UEs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub zone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN DS 22635 5 1 042026877E24C586D775608A2AFEE6179F5C43AF
+0.0.194.example.com. 3600 IN RRSIG DS 7 5 3600 20181230101819 20181130101819 53207 example.com. NxLJhRVh78CARarasz3Ks4lanafpN8+AsJgbiYnCQQPmn9X3fq9jbG5n KO0AlyvvcCy/W7z7KMFsMNVD1CvKCDzM2DKbTm17HaPAGXONkxGj53a1 OLn1+hXQ3O+4Th2lNfsUDmk0cMCIyRJetNVBTnz0ywXBHNiQIfyzsGHY UEs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com. for zone 0.0.194.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN NS
+SECTION ANSWER
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20181230101818 20181130101818 22635 0.0.194.example.com. OEIHwyYg+Yp9hF/P10nwxq5Lv0pz5RLjtv3hP3N4dpUPQTEwKL0e4hVG 68s6d6RSKNMzhOFrO7PA+QePRzC4ksC7+2SgKA+XvaGP9kRsjWou9jv0 8SdyaV8Agjx7OwRpbZNFs//wdX0l0RU6XHcQ0ZwkcfseK0RE6btI/YvL oA4= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to DNSKEY priming query
+; 0.0.194.example.com. 3600 IN DS 22635 5 1 042026877E24C586D775608A2AFEE6179F5C43AF
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+0.0.194.example.com. IN DNSKEY
+SECTION ANSWER
+0.0.194.example.com. 3600 IN DNSKEY 256 3 5 AwEAAdYRWdf35UAjLYIYyuKr5Cnb17qGYZ3mC1CZjOt3j7muMunvFjGw a75XHGOUVj4CXW4J4TqjeL86foJx8DcqLbwreTHPfJyqcjsjGIVhSDyB Xjb0vImIj7baOOaFnXlolcx8ljob3GUIv5R/sTGcPIQGVk5T0VHLqrnp bdNyyk9/ ;{id = 30899 (zsk), size = 512b}
+0.0.194.example.com. 3600 IN RRSIG DNSKEY 5 5 3600 20181230101818 20181130101818 22635 0.0.194.example.com. OaXVEJcwCQwfYS1QFfPz8Se0NN7uEPUHUk3Ty0eiO0j40mKwCvm7ZFzl Q1xufxJATYXO9rV1wZl1dzN+Vv68tQmmByinvEomUpqsyuAtVbFqsNDT NOSK6TwKYKDo9/g7Xr10KfjCvLXdR4BgUYQwG9XZu+t1z4Qgu4vob0iq bLw= ;{id = 30899}
+SECTION AUTHORITY
+0.0.194.example.com. IN NS ns.sub.example.com.
+0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20181230101818 20181130101818 22635 0.0.194.example.com. OEIHwyYg+Yp9hF/P10nwxq5Lv0pz5RLjtv3hP3N4dpUPQTEwKL0e4hVG 68s6d6RSKNMzhOFrO7PA+QePRzC4ksC7+2SgKA+XvaGP9kRsjWou9jv0 8SdyaV8Agjx7OwRpbZNFs//wdX0l0RU6XHcQ0ZwkcfseK0RE6btI/YvL oA4= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+328.0.0.194.example.com. IN A 11.11.11.11
+328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20181230101818 20181130101818 22635 0.0.194.example.com. gQKa5rIogGvzHsC+oKjjNY5X1wp3NGUm8jj7Dxn8/x0wd8z7GmcMQCVV 6xR18r8t5m6uCFQ2USLFadWPWei6OnPmMw0KDKxrTs3sG6HKe4yMtLcO NY1IZ6pdHpCc8btAhw5DfYEilo+6Mod2KD6ulRJKcY4rE7jFosLdpwM7 5hw= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+328.0.0.194.example.com. IN A
+SECTION ANSWER
+328.0.0.194.example.com. 3600 IN A 11.11.11.11
+328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20181230101818 20181130101818 22635 0.0.194.example.com. gQKa5rIogGvzHsC+oKjjNY5X1wp3NGUm8jj7Dxn8/x0wd8z7GmcMQCVV 6xR18r8t5m6uCFQ2USLFadWPWei6OnPmMw0KDKxrTs3sG6HKe4yMtLcO NY1IZ6pdHpCc8btAhw5DfYEilo+6Mod2KD6ulRJKcY4rE7jFosLdpwM7 5hw= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_loop1.rpl b/tests/deckard/sets/resolver/val_cname_loop1.rpl
new file mode 100644
index 0000000..45e233f
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_loop1.rpl
@@ -0,0 +1,142 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN CNAME loop.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. gMjZEEynrC1cW2t6s6bpRRxSmlq2Jt+7+vIHYP4pq9pqGHg6EM+Nexob au3wmIJv7c5vMmlQmk2z63HLXIEYHFjSzAHgyhfRVM9iEkK8Ules0k6H y5xuE3Z4aE3kGU5d7oNOQs4RlcNEI13bF7dxQ6c+41mNd3ihX9ZqCeXF O8E=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_loop1_3.rpl b/tests/deckard/sets/resolver/val_cname_loop1_3.rpl
new file mode 100644
index 0000000..d75ffbf
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_loop1_3.rpl
@@ -0,0 +1,182 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN CNAME loop.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+bar.example.com. 3600 IN CNAME www.example.com.
+bar.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. azRcQFNDdj0HVMR4CS4cSX1039MJIqsFPP2Fxnr1DLwlvTPxOkqWGumu PKhBkcnX8JMFyJpVBD+3qHrOOuz7BOKvu6Subj0ku+qCdVmrDsdxwabP 7lf63j92EE0ofGoYtN7sdkH6c89OHxTfR5CsALFyT+syABYjyl/tKx9n 8JA=
+foo.example.com. 3600 IN CNAME bar.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. ke8Jzx4GK1yIfiVJjMTrhP5OJihx0g3iwBGk9qz8XiV4/K9Z6KztlPut KVAqlKIXWgvKshyvWG/fGrCr9NZZ2+h8LfxRopvYRArh5mP2QN5kLV6O DhRkKJFYthsyU0swGZXJAd2CZ2plz1qauQYmrzGCRK336vu4+b/lzJP8 D4M=
+www.example.com. 3600 IN CNAME foo.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. Bn3zMkt2HEfIt5kLCEmcT6Kj/20qcvob2RdQaaTtZD+xrbDmqjFkiW09 d+RGP4g7ydXxIDczs4d3dTaSjEp2mgzd8GG0yegG1wiLzObp+gXTLaIT LLz53neab4yS0ZOaformDeWSCx3//U8guRRfOSnPHLQGAmqrVG7Dr30D RKU=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.example.com. IN A
+SECTION ANSWER
+foo.example.com. 3600 IN CNAME bar.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. ke8Jzx4GK1yIfiVJjMTrhP5OJihx0g3iwBGk9qz8XiV4/K9Z6KztlPut KVAqlKIXWgvKshyvWG/fGrCr9NZZ2+h8LfxRopvYRArh5mP2QN5kLV6O DhRkKJFYthsyU0swGZXJAd2CZ2plz1qauQYmrzGCRK336vu4+b/lzJP8 D4M=
+www.example.com. 3600 IN CNAME foo.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. Bn3zMkt2HEfIt5kLCEmcT6Kj/20qcvob2RdQaaTtZD+xrbDmqjFkiW09 d+RGP4g7ydXxIDczs4d3dTaSjEp2mgzd8GG0yegG1wiLzObp+gXTLaIT LLz53neab4yS0ZOaformDeWSCx3//U8guRRfOSnPHLQGAmqrVG7Dr30D RKU=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+bar.example.com. IN A
+SECTION ANSWER
+bar.example.com. 3600 IN CNAME www.example.com.
+bar.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. azRcQFNDdj0HVMR4CS4cSX1039MJIqsFPP2Fxnr1DLwlvTPxOkqWGumu PKhBkcnX8JMFyJpVBD+3qHrOOuz7BOKvu6Subj0ku+qCdVmrDsdxwabP 7lf63j92EE0ofGoYtN7sdkH6c89OHxTfR5CsALFyT+syABYjyl/tKx9n 8JA=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_loop3.rpl b/tests/deckard/sets/resolver/val_cname_loop3.rpl
new file mode 100644
index 0000000..a9d9092
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_loop3.rpl
@@ -0,0 +1,164 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN CNAME loop.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME foo.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. Bn3zMkt2HEfIt5kLCEmcT6Kj/20qcvob2RdQaaTtZD+xrbDmqjFkiW09 d+RGP4g7ydXxIDczs4d3dTaSjEp2mgzd8GG0yegG1wiLzObp+gXTLaIT LLz53neab4yS0ZOaformDeWSCx3//U8guRRfOSnPHLQGAmqrVG7Dr30D RKU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.example.com. IN A
+SECTION ANSWER
+foo.example.com. 3600 IN CNAME bar.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. ke8Jzx4GK1yIfiVJjMTrhP5OJihx0g3iwBGk9qz8XiV4/K9Z6KztlPut KVAqlKIXWgvKshyvWG/fGrCr9NZZ2+h8LfxRopvYRArh5mP2QN5kLV6O DhRkKJFYthsyU0swGZXJAd2CZ2plz1qauQYmrzGCRK336vu4+b/lzJP8 D4M=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+bar.example.com. IN A
+SECTION ANSWER
+bar.example.com. 3600 IN CNAME www.example.com.
+bar.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. azRcQFNDdj0HVMR4CS4cSX1039MJIqsFPP2Fxnr1DLwlvTPxOkqWGumu PKhBkcnX8JMFyJpVBD+3qHrOOuz7BOKvu6Subj0ku+qCdVmrDsdxwabP 7lf63j92EE0ofGoYtN7sdkH6c89OHxTfR5CsALFyT+syABYjyl/tKx9n 8JA=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_new_signer.rpl b/tests/deckard/sets/resolver/val_cname_new_signer.rpl
new file mode 100644
index 0000000..fe50d3b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_new_signer.rpl
@@ -0,0 +1,239 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN CNAME chain with different signer names in RRSIGs.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 38364 7 1 66DC14443014B2727261B50B447170DE18CF43A9
+sub.example.com. 3600 IN DS 38364 7 2 719A6680950A624D2C71A67981A7AF884C23E3C21074FF1CF8FB7EFE 20C52F97
+sub.example.com. 3600 IN RRSIG DS 10 3 3600 20251231235959 20160308093040 438 example.com. mu/x2yR8nFrwOnnfN7dMQ2e2MAAuZigua0wakXaPT0j4pe5AjQhriZXU pWLk5z77ck8Kswt+O23v1sUxmq1bUsIc2kw6N02UyiHnPoxmcu0rg0Kc ustfA++YT5/L+fpq5PRm3kKfHLo81WdZ/VJoaafH/kXHnZTcP62ZoteQ sqw=
+sub.example.com. 3600 IN RRSIG DS 10 3 3600 20251231235959 20160308093040 2843 example.com. ZLx28ZpzPpaafVH3hqV9h6AZJH7Zn0ELOfFxodogJfWue86xjuWhzpBV O9jCOqyURitiBgKNYazghmciNw4wzANbz+hhtc4rIPsfOr/8Vn3pjyev yScX227d16hXKBNKTrAeKNvM8fVPT0E7cG3CY0mzVp3SVqrr+6hl+dgb gXU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME foo.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. Bn3zMkt2HEfIt5kLCEmcT6Kj/20qcvob2RdQaaTtZD+xrbDmqjFkiW09 d+RGP4g7ydXxIDczs4d3dTaSjEp2mgzd8GG0yegG1wiLzObp+gXTLaIT LLz53neab4yS0ZOaformDeWSCx3//U8guRRfOSnPHLQGAmqrVG7Dr30D RKU=
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. FpyDEo49Y1b5Hb112BDCohW+93sDTmBrYc1rRfI8QrfLPXRwpMFVZBhU fDk8aG6qyKVlCa3DhpcHRyPi9SAz1nNPNhstcSqmmj7vNWjBVY5wtt1m 9AqEXFca5liXxVhuijpW9GBMm1LFyNYzuNqQszyje8/NZSumaIbqJiJy f6c=
+foo.example.com. 3600 IN CNAME foo.sub.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. aD8FHTvx3sL/prnJ5tfeZG1Tb7gUknU7GGJg8H5W4MkZKteMsF+Vydy9 LI/yTMjk+43Hmsim1lqtzL4GLoegG9xJCMVo14QVqsAwSzzyA/ySfWox Hw/tiltI8VBfOmRDL9V3qRhW6ZaYbXFHY1AbIapIsO/gFPcJ/nVsnugZ tHc=
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. ht4bE1Q5IevG+F0qvLDjbEaRvNRsnEKnEm3ntcXemtrtIpCLM5KsM2Bc oPrl3+ayQAv2NJM8GsJM9xWzZYAKEQk+THhusCE4j8/lX6Ngmb4M3x0R CI6sBxmN84v4HFXqk4W7dMW7BL9NlEMY2bgQe9g2kUcfA7FHaUQofrqS ASQ=
+foo.sub.example.com. 3600 IN CNAME www.sub.example.com.
+foo.sub.example.com. 3600 IN RRSIG CNAME 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. vd1rVNNnARpWt7AmfKL1Kt2tqD5/v52tmwJHabpDegmMZ9sW3cZ3u+VF zypg545TnxtRBJAKmhEooDAOt4oNaP7u8K83HUCwlZOYz2bu0lrZU5wL ALi4jX880lWc/AR9z1FzG6ZXEcK9lu+1nC5x09jedaUFOG5bEMSMmdN+ 2N1Rdf75l3CiJIigiUE2y5pS4rDemsTJqgF/QK8XBbBNaz6c2f6XRKnc fC40jsfcufR0wTrhZw7/7FthKoaLBi/xE11mItQkBGDbCAgyM3ftV3mZ ArmlCg8expcTRuGIvhpvMbTf4m3/zBHPxsxO75QvD84ysBz0C6hnquJH 1BfrNA==
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.example.com. IN A
+SECTION ANSWER
+foo.example.com. 3600 IN CNAME foo.sub.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. aD8FHTvx3sL/prnJ5tfeZG1Tb7gUknU7GGJg8H5W4MkZKteMsF+Vydy9 LI/yTMjk+43Hmsim1lqtzL4GLoegG9xJCMVo14QVqsAwSzzyA/ySfWox Hw/tiltI8VBfOmRDL9V3qRhW6ZaYbXFHY1AbIapIsO/gFPcJ/nVsnugZ tHc=
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. ht4bE1Q5IevG+F0qvLDjbEaRvNRsnEKnEm3ntcXemtrtIpCLM5KsM2Bc oPrl3+ayQAv2NJM8GsJM9xWzZYAKEQk+THhusCE4j8/lX6Ngmb4M3x0R CI6sBxmN84v4HFXqk4W7dMW7BL9NlEMY2bgQe9g2kUcfA7FHaUQofrqS ASQ=
+foo.sub.example.com. 3600 IN CNAME www.sub.example.com.
+foo.sub.example.com. 3600 IN RRSIG CNAME 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. vd1rVNNnARpWt7AmfKL1Kt2tqD5/v52tmwJHabpDegmMZ9sW3cZ3u+VF zypg545TnxtRBJAKmhEooDAOt4oNaP7u8K83HUCwlZOYz2bu0lrZU5wL ALi4jX880lWc/AR9z1FzG6ZXEcK9lu+1nC5x09jedaUFOG5bEMSMmdN+ 2N1Rdf75l3CiJIigiUE2y5pS4rDemsTJqgF/QK8XBbBNaz6c2f6XRKnc fC40jsfcufR0wTrhZw7/7FthKoaLBi/xE11mItQkBGDbCAgyM3ftV3mZ ArmlCg8expcTRuGIvhpvMbTf4m3/zBHPxsxO75QvD84ysBz0C6hnquJH 1BfrNA==
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 7 AwEAAfXXu2eDy9QsjLuHgEMWmG03TVauwmITCq520ANujsTZlPKyQKJe xyrYm61e0RuQJb5dB5JnE0O3YYJOpnrl8keieAqVt1efnNtcn8V1em48 et146ZYFAUb/PMdTOgd2XJnhVEWD3VsZbWNMCxP1KcJTATAaLDVCY//E sc9K3CvGUizNcSoTK2rGS73A6GqmvVNnGir6AQIZifkvb6PKzF/hVpS8 cgvKF/UP8hu+0Glbq1YYTFrXMUBzKUH+X19lRvk3eLHurSvGjDEM3ZO6 tp1QdpzIRPzYKENG+qs07dhgCZyb4zqwEycmL9/Vot0ByTGbeHvHN93P PrLxcM5zlVk=
+sub.example.com. 3600 IN DNSKEY 257 3 7 AwEAAfTD+gzZ2g7c9VoOUR2ekQiPNEyqcyl0MZ4sD3bleU8D8hQdDgAI 1G38raY3xmNea8yLCQYF0x00QbmKtzMjpZqKfsCFZDX6lBV5dP8IwJ0D F6L4hjO819IInf6upH9tfQNnueflWyKzfg2zitV+ILZ4YtZViyCKqayw CSPE8OkFlszZyCESzhrXqoPdJ0oHdZCG4lOlRIgZfrMLC4yTI56iiwFc UsKy7BhNPW+hcc4r+0WB9BCpsiei/FjPMcyeMrx1W+s/xgW7/55Nq+dM PUn9v24uCptZUupn/7CRgMGM5DmWe94QIswAQjH2mXNfOgVPOiceLYzU mcNoKudvSUu1hbzJbVHA4UNWDm2vvsdsEzrOEzqO0ZVczLoZzWU4WpLf IlKm481OKkzAP9Y5F4iTTSIrbVcAuEW/iz5zfqWirgGniiTCszAie8lH u1EPBgGnfotqhq9IbNA6aKNUreJPLvJnds7J/aQmiSdm15pAq71B26X5 BmoZVhbNmh6MHXkq99EIt0yRMEOfPLRN7euza8Idd4mA+E8jpdgtYdJD LC7f2SoQxaN4RMr5MC/Z1ENQgLMYRkd87pEQycAlNAoWMPJMuoDNdwhV 15F8+pvkvfu5cm9FoEWvgS+onibUM9EC9L9EDdfDdW1Hf1QfUinVoMf/ Szf1urkPVNl0nNYF
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308093040 27527 sub.example.com. CzB+UmU98ArL/HRIOMyHV87PPYoH3G/KKdJlbjtNZAaHG+K6Lad0pKW5 wZR3By1AMlIN9ta8374q+nCEtY+ryM7yBFpzSTmBqrf7ZhkxWh2OSnrI CllC3CsSeltsOq/AEQZwJLQG/gQiCqqQnJY4mneKhcg0Bzc0hpe8c1Dq C5eaHKqt7BaVRO1Ix6OKqEqjHzwd5HpKd2pzU91HyfvHsWrOnKyIwHJP nyOcuHESKN97YLey9Onw0eXjUYdbG5GM12OV1qawShOthcm7XUQiJ0Xl V7y0pNekCxXZdQQI/XhVj8XyLa5pLy8PaOLqypbMBg19J5diLUZYAt/f Dj/EzQ==
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308093040 38364 sub.example.com. xzyO85eLRwVsg9VI4RnXnjrwf0/TCMub7UcOr7TWWhwt9iR8KFSenx17 EVG1OlgEzRrdZLQWJBPlNBR5aLpsNlzUj+cnCpdG6NtUjcdqRJxb+64Y RktG5Hz35AV7Iegs3L6tFdE4J2moGCDC0y8Rm9wyL+mCUNylpnXUOo8D NDpd7VcYKoieGWxLd8OK5aCYUlB2ziL9yIMOZR+sGEPZWR6ABXDbUF6S ddj7lbZ7y+GHp2XpjDvpmbRSrznNmopzn71O59sCiog8obnGif02EXEn 3L2a8eGx3tMhCZZAPaqJrocTIAmye0vLt0xT22WFPxmcButV1UYZd00m KwJaKgUB450wdub4aAXVvtTx7Us++6zRepZ3VtXARDT+qGzBUkISEuSM FbLHlqqdQeLTcfdu7azEfyCWudoDTbXejFQjFtWkSo6SwEV8sC64rMV6 AFytMBvksBD0tjGrWvPkdDxWa43SQja8BiTlKugtM7zJgqBH9pi1MN4o asc3hyBHBKEiX8ilK7GBTqFph8tdRxawWsaK273pATBLeQfHM2jKcg5p ULhSLxYDvJ+TgYKJkFyFd4C78HffgrashJvrxNsK1QQk05bpTGk9j6ja fzzyB6mDhWGLux1/i++akwTOKsWmFnNe6MXKTN1gnEw4pny3m7zBmh0x gFkbfEo1aDU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.sub.example.com. IN A
+SECTION ANSWER
+foo.sub.example.com. 3600 IN CNAME www.sub.example.com.
+foo.sub.example.com. 3600 IN RRSIG CNAME 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. vd1rVNNnARpWt7AmfKL1Kt2tqD5/v52tmwJHabpDegmMZ9sW3cZ3u+VF zypg545TnxtRBJAKmhEooDAOt4oNaP7u8K83HUCwlZOYz2bu0lrZU5wL ALi4jX880lWc/AR9z1FzG6ZXEcK9lu+1nC5x09jedaUFOG5bEMSMmdN+ 2N1Rdf75l3CiJIigiUE2y5pS4rDemsTJqgF/QK8XBbBNaz6c2f6XRKnc fC40jsfcufR0wTrhZw7/7FthKoaLBi/xE11mItQkBGDbCAgyM3ftV3mZ ArmlCg8expcTRuGIvhpvMbTf4m3/zBHPxsxO75QvD84ysBz0C6hnquJH 1BfrNA==
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME foo.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. Bn3zMkt2HEfIt5kLCEmcT6Kj/20qcvob2RdQaaTtZD+xrbDmqjFkiW09 d+RGP4g7ydXxIDczs4d3dTaSjEp2mgzd8GG0yegG1wiLzObp+gXTLaIT LLz53neab4yS0ZOaformDeWSCx3//U8guRRfOSnPHLQGAmqrVG7Dr30D RKU=
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. FpyDEo49Y1b5Hb112BDCohW+93sDTmBrYc1rRfI8QrfLPXRwpMFVZBhU fDk8aG6qyKVlCa3DhpcHRyPi9SAz1nNPNhstcSqmmj7vNWjBVY5wtt1m 9AqEXFca5liXxVhuijpW9GBMm1LFyNYzuNqQszyje8/NZSumaIbqJiJy f6c=
+foo.example.com. 3600 IN CNAME foo.sub.example.com.
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. aD8FHTvx3sL/prnJ5tfeZG1Tb7gUknU7GGJg8H5W4MkZKteMsF+Vydy9 LI/yTMjk+43Hmsim1lqtzL4GLoegG9xJCMVo14QVqsAwSzzyA/ySfWox Hw/tiltI8VBfOmRDL9V3qRhW6ZaYbXFHY1AbIapIsO/gFPcJ/nVsnugZ tHc=
+foo.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. ht4bE1Q5IevG+F0qvLDjbEaRvNRsnEKnEm3ntcXemtrtIpCLM5KsM2Bc oPrl3+ayQAv2NJM8GsJM9xWzZYAKEQk+THhusCE4j8/lX6Ngmb4M3x0R CI6sBxmN84v4HFXqk4W7dMW7BL9NlEMY2bgQe9g2kUcfA7FHaUQofrqS ASQ=
+foo.sub.example.com. 3600 IN CNAME www.sub.example.com.
+foo.sub.example.com. 3600 IN RRSIG CNAME 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. vd1rVNNnARpWt7AmfKL1Kt2tqD5/v52tmwJHabpDegmMZ9sW3cZ3u+VF zypg545TnxtRBJAKmhEooDAOt4oNaP7u8K83HUCwlZOYz2bu0lrZU5wL ALi4jX880lWc/AR9z1FzG6ZXEcK9lu+1nC5x09jedaUFOG5bEMSMmdN+ 2N1Rdf75l3CiJIigiUE2y5pS4rDemsTJqgF/QK8XBbBNaz6c2f6XRKnc fC40jsfcufR0wTrhZw7/7FthKoaLBi/xE11mItQkBGDbCAgyM3ftV3mZ ArmlCg8expcTRuGIvhpvMbTf4m3/zBHPxsxO75QvD84ysBz0C6hnquJH 1BfrNA==
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_oob.rpl b/tests/deckard/sets/resolver/val_cname_oob.rpl
new file mode 100644
index 0000000..0dd3d4a
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_oob.rpl
@@ -0,0 +1,181 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN OOB CNAME to wrong name.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN A
+SECTION ANSWER
+a.gtld-servers.net. IN A 192.5.6.30
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+farfaraway.com. IN A
+SECTION AUTHORITY
+com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1479809979 1800 900 604800 86400
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+alfa.example.com. IN A
+SECTION ANSWER
+alfa.example.com. 3600 IN CNAME www.farfaraway.com.
+alfa.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 438 example.com. yKZk1/bXS2mjUqJ9bS2KVrf1Cq/bsNoHj7VD3R8sp2Rn63vBEoxzqBxo 8lYuXlNw3sMAQFQYhaloVrNnDPwlAfY+qXuLutsAtKxql/FxdRWIjjMk fvO9zNbqzCpP1FtCO0PpFgJXYH5wkkq8/sBDRW8CbDotruSJPbJ1/OGn JPc=
+alfa.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. SglKK7SovflRnQVz1leE94Dez+obX9nWR5eAQ6ggun2xkZbUjK22UHbl ihP5F0PpqnTdgPNyEgCR1P/HON2VYMlB1CT2J/fm3ZriLyBEOEils98J UkWZYy5Kt3eXcye17YKBXIW9ivIWTh5brRWaPEbzXy73ID3HZYyKVM52 3UU=
+www.farfaraway.com. 3600 IN A 1.2.3.123
+www.farfaraway.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111110=
+SECTION AUTHORITY
+farfaraway.com. 3600 IN NS ns.farfaraway.com.
+SECTION ADDITIONAL
+ns.farfaraway.com. 3600 IN A 1.2.3.10
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+alfa.example.com. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question
+REPLY QR RD RA DO NXDOMAIN
+SECTION QUESTION
+alfa.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_to_unsigned.rpl b/tests/deckard/sets/resolver/val_cname_to_unsigned.rpl
new file mode 100644
index 0000000..66e795d
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_to_unsigned.rpl
@@ -0,0 +1,202 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN CNAME to unsigned subzone.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.sub.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. msZaF29s99toR+WhRyQsRR63Nclwvic7dOMKH3KW3g/mamiN22g9dJ7L VPdG1FX9+4qosyn37d/+jUXy2UIryBXuXBojpPU3UrPq/gJOYtp1y23e dHgeGpCv7Tmp/TDDWJPNSUL/rWjl64MK1Dkd+O4plU+SMgqN1wuTgBg8 fsk=
+ENTRY_END
+
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2016022600 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 10 2 3600 20251231235959 20160308093040 2843 example.com. s3pCq6ZK3DEUkWYX3XKvr5v9Z4AhbJ4P7/AKQkhe3zymnTba7Bo5Uhmb Vav/A+u8gsoo9yBumReXLAv047btO+jdCOLD/yXvmaSt/yGGcipFoX6r 4kQWzUHby4NlQEdO3YykiZx7FtCGsMp0cfwPae4glkDsAPnIhhQurzzE VP4=
+sub.example.com. 18000 IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 18000 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. vA2GpUEeAnbvg8t35VEZybJoJvxlu9UGXHNEzIohxKetvLTp761NaCW5 NIhYnVv/b9GDmu5sU9cvQxN+7nEGqLXKnzlGbzIdSedrzBgjOnQNOGO5 BJTollsCG71OfTs2/4kzi04N11yWqSaJyidWLXPH2lElTFQX/3dMcP2m 5uE=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.5
+ENTRY_END
+
+RANGE_END
+
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+ENTRY_END
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.sub.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. msZaF29s99toR+WhRyQsRR63Nclwvic7dOMKH3KW3g/mamiN22g9dJ7L VPdG1FX9+4qosyn37d/+jUXy2UIryBXuXBojpPU3UrPq/gJOYtp1y23e dHgeGpCv7Tmp/TDDWJPNSUL/rWjl64MK1Dkd+O4plU+SMgqN1wuTgBg8 fsk=
+www.sub.example.com. 3600 IN A 1.2.3.123
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; Cache hit
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.sub.example.com.
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. msZaF29s99toR+WhRyQsRR63Nclwvic7dOMKH3KW3g/mamiN22g9dJ7L VPdG1FX9+4qosyn37d/+jUXy2UIryBXuXBojpPU3UrPq/gJOYtp1y23e dHgeGpCv7Tmp/TDDWJPNSUL/rWjl64MK1Dkd+O4plU+SMgqN1wuTgBg8 fsk=
+www.sub.example.com. 3600 IN A 1.2.3.123
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_to_unsigned_fake_rrsig.rpl b/tests/deckard/sets/resolver/val_cname_to_unsigned_fake_rrsig.rpl
new file mode 100644
index 0000000..bc2a5c8
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_to_unsigned_fake_rrsig.rpl
@@ -0,0 +1,213 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN CNAME with invalid RRSIG to unsigned subzone must produce SERVFAIL
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME fake.sub.example.com.
+; following RRSIG was generated for www.example.com. 3600 IN CNAME www.sub.example.com.
+; -> rdata "fake.sub.example.com." == an attack!
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. msZaF29s99toR+WhRyQsRR63Nclwvic7dOMKH3KW3g/mamiN22g9dJ7L VPdG1FX9+4qosyn37d/+jUXy2UIryBXuXBojpPU3UrPq/gJOYtp1y23e dHgeGpCv7Tmp/TDDWJPNSUL/rWjl64MK1Dkd+O4plU+SMgqN1wuTgBg8 fsk=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN RRSIG
+SECTION ANSWER
+; following RRSIG was generated for www.example.com. 3600 IN CNAME www.sub.example.com.
+; -> rdata "fake.sub.example.com." obtained from previous query == an attack!
+www.example.com. 3600 IN RRSIG CNAME 10 3 3600 20251231235959 20160308093040 2843 example.com. msZaF29s99toR+WhRyQsRR63Nclwvic7dOMKH3KW3g/mamiN22g9dJ7L VPdG1FX9+4qosyn37d/+jUXy2UIryBXuXBojpPU3UrPq/gJOYtp1y23e dHgeGpCv7Tmp/TDDWJPNSUL/rWjl64MK1Dkd+O4plU+SMgqN1wuTgBg8 fsk=
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fake.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MANDATORY
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2016022600 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 10 2 3600 20251231235959 20160308093040 2843 example.com. s3pCq6ZK3DEUkWYX3XKvr5v9Z4AhbJ4P7/AKQkhe3zymnTba7Bo5Uhmb Vav/A+u8gsoo9yBumReXLAv047btO+jdCOLD/yXvmaSt/yGGcipFoX6r 4kQWzUHby4NlQEdO3YykiZx7FtCGsMp0cfwPae4glkDsAPnIhhQurzzE VP4=
+sub.example.com. 18000 IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 18000 IN RRSIG NSEC 10 3 18000 20251231235959 20160308093040 2843 example.com. vA2GpUEeAnbvg8t35VEZybJoJvxlu9UGXHNEzIohxKetvLTp761NaCW5 NIhYnVv/b9GDmu5sU9cvQxN+7nEGqLXKnzlGbzIdSedrzBgjOnQNOGO5 BJTollsCG71OfTs2/4kzi04N11yWqSaJyidWLXPH2lElTFQX/3dMcP2m 5uE=
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+; it should not be reached because of invalid RRSIG
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+fake.sub.example.com. IN A
+SECTION ANSWER
+fake.sub.example.com. 3600 IN A 1.2.3.123
+ENTRY_END
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; Cache hit
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cname_trust_domains.rpl b/tests/deckard/sets/resolver/val_cname_trust_domains.rpl
new file mode 100644
index 0000000..3120216
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cname_trust_domains.rpl
@@ -0,0 +1,438 @@
+; config options
+; The island of trust is at example.com and example.net; example.org is insecure
+trust-anchor: "example.com. 3600 IN DS 11901 7 1 4b5c9e50ad931b35fc507e0a20d141a056c19227"
+trust-anchor: "example.net. 3600 IN DS 59835 7 1 1fb3f5d45f4ffbf160e0f4fb75e3a1e8d34b6a67"
+val-override-date: "20170214000000"
+stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with a CNAMEs between sub-trees with different TAs
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; subtree with own trust anchor
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; subtree with own trust anchor
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; insecure subtree
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+org. IN A
+SECTION AUTHORITY
+org. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+org. IN NS
+SECTION ANSWER
+org. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.org. IN A
+SECTION AUTHORITY
+example.org. IN NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.org. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20170313131924 20170213131924 11901 example.com. B4VToCUqVSDSaOG1sK+p+WC1Ece0tB+0UZTBfD+zgfbkHv+nI0ehsBEFlcubMiWZ9qZJ37824b44qapOOvfzuuhtkk/z5VPVljfWz4vj/t+fYQjWqfNN+oVp+ul7ULsDNNNWO6rPJmtmEjUq/7QrGb1iFereC5oaH2J5D13y5hCMPxtepQ7EjsGSHGhT0nAuWJwV5iNcUUm0kRIiBZqIGCVx16G5S3kxBebcoDA+yjMiA5xmFoxEf4I4Vk0Ut7rh4TOStEQdZAW6VCD4e65gWwNu2dTHpdqctA8ppjOA3nVamjPlVQ0z0Cqxm6UHj+su7CnS7lg2fjGYfP0ebUTSYg==
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20170313131924 20170213131924 11901 example.com. LEvYqarAR/IXWSOknuV7DobkmjcvIIe1lFlJSucRp9v2GkdE384vMrSPmvRxItpEWgnnKlEZIYvMDcKT71muIlv7+0PmIPMtdBkB2rBL0s5dZxH//u9tWmgPAkG+BLJelr5iB63w8VhXJsiRiNGjCBc6t5MJHk7nTNK/8LLUZYDyi8YsiIxxy+emUwOW/LLfSECSBlz4QbyD1tQ0dErk48jAH56GwLJehmtMKbyF/negRLO9jOrzSOGiszw3VjyLfzkkfLJBNheSECGo3aN+/r/GPHr2CisgfROeR46PXs56ooGkO4x/PsplFTc+eZQioHuIPkv4sScyz2/2shxTLA==
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 257 3 7 AwEAAb7hP8/oYI+DGLG/Khpe0roTWUdmAEMRAaUbiFAMrMf1AiSTBf5oNrVPMFvM/MmqoAZ6Ku2AhyAnb6pfCrG1TQq5uuFYrp4h2u6jUxFT3OPNHb+gDlKRSqDzOXBImCf1SDz7bx4xw+zS/rYOF2mPk8YWi+jI3HzIkqCjw++oIu+Zwzcmc9fRTruDMDhFGcVMvdD97CbD0QpBDvgh2vQikZvmD4wwzrvjJC7SmkNPTYA2RaJj2GSggnYMcgPBNHBJzLqfCbciU1jUBazsAafQbnXfy3jz5Eh/X6vKlAtejMhoCqd9iXE7EqYWI9F4ny/a/17z/aEYrWsJsVIlnJ10nlE= ;{id = 11901 (ksk), size = 2048b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20170313131924 20170213131924 11901 example.com. V99TYdJIpoy6pJuFQx/VgK05YifhPcuuqdTzHM67ORzhpOpQj/2/aFWYPu7WoRhNOw895I41VIDuX0ljKXNUbAl+YF7+eRWDyrRsnWWhxWcTL0yWH71/b8U0IHFus++HKiYU+6pq148k0Pk4LmINWv7qDqOv+XVdfLqjRSWgZxEEXOaRgNp6m6UTJy9n9qvXejdxXBFLLsSRTHXBM3amyEl2LyXLyG4C8MNJPMMcwmBQASlj9AaUxewXQssacbagHy9CJtZcUjwco76dfyM/X2tgRfdXrVz1QCuA8D1o8FRtddnRugOSUqfF73dBVEoljWYNm6V2xR5uXnFyRZdyAQ==
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20170313131924 20170213131924 11901 example.com. B4VToCUqVSDSaOG1sK+p+WC1Ece0tB+0UZTBfD+zgfbkHv+nI0ehsBEFlcubMiWZ9qZJ37824b44qapOOvfzuuhtkk/z5VPVljfWz4vj/t+fYQjWqfNN+oVp+ul7ULsDNNNWO6rPJmtmEjUq/7QrGb1iFereC5oaH2J5D13y5hCMPxtepQ7EjsGSHGhT0nAuWJwV5iNcUUm0kRIiBZqIGCVx16G5S3kxBebcoDA+yjMiA5xmFoxEf4I4Vk0Ut7rh4TOStEQdZAW6VCD4e65gWwNu2dTHpdqctA8ppjOA3nVamjPlVQ0z0Cqxm6UHj+su7CnS7lg2fjGYfP0ebUTSYg==
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20170313131924 20170213131924 11901 example.com. LEvYqarAR/IXWSOknuV7DobkmjcvIIe1lFlJSucRp9v2GkdE384vMrSPmvRxItpEWgnnKlEZIYvMDcKT71muIlv7+0PmIPMtdBkB2rBL0s5dZxH//u9tWmgPAkG+BLJelr5iB63w8VhXJsiRiNGjCBc6t5MJHk7nTNK/8LLUZYDyi8YsiIxxy+emUwOW/LLfSECSBlz4QbyD1tQ0dErk48jAH56GwLJehmtMKbyF/negRLO9jOrzSOGiszw3VjyLfzkkfLJBNheSECGo3aN+/r/GPHr2CisgfROeR46PXs56ooGkO4x/PsplFTc+eZQioHuIPkv4sScyz2/2shxTLA==
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313131924 20170213131924 11901 example.com. TyWar/GZu4Vw5t4YTnxF8XRJAmHTWAA0snal0I6qH4pBxqmmYMHdFuGmiKwQNUpNlntOaAHj2UElkHa07eF+/Hb7mwf926bzGa13of2zS3rmwaqNi0nDns6PNWmzmpG65jKXqug5X7QrKIO00KeFWPM3T6LXp3TyZ9v1c5wtze1UGvK3OsSBs9aV9ovRcMjGA8ttPZbStM6VlblzdWfha+RY9Yt61OkAbS1ooQ2TRB1esGyd3EZgV0jTMtkbymitPog7XXEViIl5lp76clBOvUHCRhSO3XhU9ir840pQ+SOFTQBRK5OOhKOar2IX/n3smk+teqRbZ1zEa0cyrV/2Fg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+insecure.example.com. IN A
+SECTION ANSWER
+insecure.example.com. 3600 IN CNAME insecure.example.net.
+insecure.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313140157 20170213140157 11901 example.com. PwYkM20oqzXrK+48AJgJUQP5MNbVjV9Xt9PG5ag2U7DrckQbVvuZ6dorouqUbVvLXhpbfInGazxgGGSE+hObhkhJcrRcmg2pKHWbRpBJqNnMeXk/w5zzlIOBq+Hu+ZpyUsbfJeax0S+gOyKLSeqRLDzOxWsSiFfPD2PSdfHcdslDxWLt92J8Yr2/wqh5aW7HOYDRZbvZkfP+0J4FWfWI6j25flbR7/Kt8SBAcqvg4cFREVua847iAItKGZGqa6XWnUX9JSskBl97RG0T3jBel+nz3MjMVSDl5HYaazv+VuUcF4NbjIcZHt8QxVOLw6IF/XxwPunqLPGByIYrBreUJQ==
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. 3600 IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS 7 2 3600 20170313131043 20170213131043 59835 example.net. XLDyXC3D0yyq3VOwjbHlI5QBl5pvmiGw 72k1nZIZbBSj6xJkGl0LXzRBO8gXbvYJ 2N1K2DwNQzR2ZPxoDzo60Mwe2gt7RjJt xMgLny0p6qWCvW1VYEyODvvnKrwcDvKm fbMPXmUaf2UuCj4OlaljJXDYACUG9+X2 yA+ipcop7rR+z4spnOfQIao1dzsH8itp yCRkV+X4jzDNaj9CN6nDfpCJsDDt4//5 V//3LQfAwmBBFOesnM3r68uCRqQySRzj UILvpWnu7T71FEHqIHSQmRUHAZRBsxGu IgWrEEHbcg5+eCvVe3X5lNMFAuU5ysXb mb2ENkyFPhfmytLLE/a96A==
+SECTION ADDITIONAL
+ns.example.net. 3600 IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. ewYu0740p/BWH2RRU+L7QXhj44AnFNaobCCSYxl3gEqLNQI3MSJffXle2JVsEpgMySHfDZQSBy5iAqOA7zQLUmtABWCjKb74nlngPWklneibxQiSGphf8OyVJTrYtcNvk458eBfyyMWQy7HYwDYtYBlGIqHzU7FUkONHteDGlb5aGtAbqib9LzsHExfJdRuy5l1NX+/cLqHeRDceSX4g7F2Xn+i4SLBTHa4HODiklB8ugjHuFHLVBJAm55aIDSmrSrDliL2QZ/aXtVhRh1lMaD+YdsaW7Gny9EGygnFGolmzmVxjeCQ1sfmAjd8VS+x979VLy9tT2GWQWv39dfBejA==
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net. 3600 IN DNSKEY 257 3 7 AwEAAZiIoYj0BuA2FiduSeydlfGOpKfK38KvFB5jHASrr1YIXOB3ky1WMzedwL6sti6EtMDNBZTnqr+4+b01zuAGDDuQvsVrd5y07lrc+8Y1S61s4QVo2r5P1+I54AucFCX+ZeqGhKkEhhu74LHbmKn32d9MUGHbazZ2+l7hrROVEljmrL/2waHOVu1flHxN5TfIcA9+UghA/aoT9p/oT8EzJ/oEbX2GT7hfvOmmOVUfEIgBlIKwwqaYIxjjzex2bPzkm/SN3oU3gwVcJv6q3R5a+4AeLv5lrsNL1qc7Juth4miiiwJpv8COBSFgBEhSqAjkurx+cXzYClBz+yxJJSsRYFs= ;{id = 59835 (ksk), size = 2048b}
+example.net. 3600 IN RRSIG DNSKEY 7 2 3600 20170313131043 20170213131043 59835 example.net. aQLRerV6GBcQY6dm4bYr7cCr6rkdl+GYPyyfw09d20FW/JuqiljvqKMQtfzVXBrqYIB/DMdGkSJ87w19vlPzey8CtI8oXk1AFwHD/aFqS3cv/2oFS71cm/eGhmf87led51NrqW6dQPkQZ2xOZ4cDxtmkrLMJy3OWIwH8+1rpy4dOg/aHw4+K7qARWJtj3iS9GmiZW88LRdSvJR14reAlM4XYhivdGZcEe+UQNymz+NY7KG1DwWU2AQCBq/QID+f5Zpxbfw2fEH7X1aMzjEj/HGZ3BXcXahM0wGQzRXmXNcXYqzST/RhrJ1g34xsgMFLk/Kfj+cQCOW8aK7/Zt9vRIg==
+SECTION AUTHORITY
+example.net. 3600 IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS 7 2 3600 20170313131043 20170213131043 59835 example.net. XLDyXC3D0yyq3VOwjbHlI5QBl5pvmiGw 72k1nZIZbBSj6xJkGl0LXzRBO8gXbvYJ 2N1K2DwNQzR2ZPxoDzo60Mwe2gt7RjJt xMgLny0p6qWCvW1VYEyODvvnKrwcDvKm fbMPXmUaf2UuCj4OlaljJXDYACUG9+X2 yA+ipcop7rR+z4spnOfQIao1dzsH8itp yCRkV+X4jzDNaj9CN6nDfpCJsDDt4//5 V//3LQfAwmBBFOesnM3r68uCRqQySRzj UILvpWnu7T71FEHqIHSQmRUHAZRBsxGu IgWrEEHbcg5+eCvVe3X5lNMFAuU5ysXb mb2ENkyFPhfmytLLE/a96A==
+SECTION ADDITIONAL
+ns.example.net. 3600 IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. ewYu0740p/BWH2RRU+L7QXhj44AnFNaobCCSYxl3gEqLNQI3MSJffXle2JVsEpgMySHfDZQSBy5iAqOA7zQLUmtABWCjKb74nlngPWklneibxQiSGphf8OyVJTrYtcNvk458eBfyyMWQy7HYwDYtYBlGIqHzU7FUkONHteDGlb5aGtAbqib9LzsHExfJdRuy5l1NX+/cLqHeRDceSX4g7F2Xn+i4SLBTHa4HODiklB8ugjHuFHLVBJAm55aIDSmrSrDliL2QZ/aXtVhRh1lMaD+YdsaW7Gny9EGygnFGolmzmVxjeCQ1sfmAjd8VS+x979VLy9tT2GWQWv39dfBejA==
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR DO NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.0.0.1
+www.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. F0OiqJtl9nOonZePqV+boFuj5i1zTyDdj5yxZ80J7BQOoB0wGvcx105mriIW3mAQPmgq2K/lK317IejuP+kKBr8oGr82apCyP7NihAHr/dnqe4cTJJjQU1cjLJcIJHY6jg99DR6HkCZFRjEA8TI761E2GBfvxK0yPKEW1m8N9G9Wl5KZOHq8pQ1ZNDm4MR0rt2lvsuVaf+iGiw4HJkaD7Kceq3y9ukilsuP6Zl0dWMIeTqcs7UT3OS16HV21A9VL3rJGRLUonmJo7mUq8hpxKnFYK6/96IfXCf/XX1YI6rK0DVp1OE0S8s+teLG4UsE2p2+dC2arVwhHUGzlZMvO/A==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR DO NOERROR
+SECTION QUESTION
+insecure.example.net. IN A
+SECTION ANSWER
+insecure.example.net. 3600 IN CNAME insecure.example.org.
+insecure.example.net. 3600 IN RRSIG CNAME 7 3 3600 20170313140150 20170213140150 59835 example.net. L1NmsrbewJeWS4ZC07jR9EWPg5QqKwH8BklJIWnMYlfR1xaLcMS5hHeDQN3OUK8D79mxmoBQVIXPMig3CLJPkewJoOZMKD/UwHVosFbG9NbRbWtY6tTZtQnzLy45+AsoQeF0tnoJM+5pvE3wMyXLBgZWbZDGRd0/Uk5/wxddu7NkxAZ0U3zarFxpVnQgP+MKifaplfHko599psQ58BnoSMUB1FjeFsy78zkXd3PjX/VWevGNlABGmlpvWdQou8c6V9ihGVRmsha6ABW04cLgevDjgorrn1AAI88c1H/pRDoWjO5zyQ9PPFPusCTYTEWcuSDpN43RFCxrA7ENP2g1rw==
+ENTRY_END
+
+RANGE_END
+
+
+; ns.example.org.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.org. IN NS
+SECTION ANSWER
+example.org. 3600 IN NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.org. 3600 IN A 1.2.3.6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.org. IN A
+SECTION ANSWER
+www.example.org. 3600 IN CNAME www.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+insecure.example.org. IN A
+SECTION ANSWER
+insecure.example.org. 3600 IN A 10.2.2.2
+ENTRY_END
+RANGE_END
+
+
+; CNAME from one trusted sub-tree to another trusted sub-tree
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313131924 20170213131924 11901 example.com. TyWar/GZu4Vw5t4YTnxF8XRJAmHTWAA0snal0I6qH4pBxqmmYMHdFuGmiKwQNUpNlntOaAHj2UElkHa07eF+/Hb7mwf926bzGa13of2zS3rmwaqNi0nDns6PNWmzmpG65jKXqug5X7QrKIO00KeFWPM3T6LXp3TyZ9v1c5wtze1UGvK3OsSBs9aV9ovRcMjGA8ttPZbStM6VlblzdWfha+RY9Yt61OkAbS1ooQ2TRB1esGyd3EZgV0jTMtkbymitPog7XXEViIl5lp76clBOvUHCRhSO3XhU9ir840pQ+SOFTQBRK5OOhKOar2IX/n3smk+teqRbZ1zEa0cyrV/2Fg==
+www.example.net. 3600 IN A 10.0.0.1
+www.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. F0OiqJtl9nOonZePqV+boFuj5i1zTyDdj5yxZ80J7BQOoB0wGvcx105mriIW3mAQPmgq2K/lK317IejuP+kKBr8oGr82apCyP7NihAHr/dnqe4cTJJjQU1cjLJcIJHY6jg99DR6HkCZFRjEA8TI761E2GBfvxK0yPKEW1m8N9G9Wl5KZOHq8pQ1ZNDm4MR0rt2lvsuVaf+iGiw4HJkaD7Kceq3y9ukilsuP6Zl0dWMIeTqcs7UT3OS16HV21A9VL3rJGRLUonmJo7mUq8hpxKnFYK6/96IfXCf/XX1YI6rK0DVp1OE0S8s+teLG4UsE2p2+dC2arVwhHUGzlZMvO/A==
+ENTRY_END
+
+; cache test
+STEP 12 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 13 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313131924 20170213131924 11901 example.com. TyWar/GZu4Vw5t4YTnxF8XRJAmHTWAA0snal0I6qH4pBxqmmYMHdFuGmiKwQNUpNlntOaAHj2UElkHa07eF+/Hb7mwf926bzGa13of2zS3rmwaqNi0nDns6PNWmzmpG65jKXqug5X7QrKIO00KeFWPM3T6LXp3TyZ9v1c5wtze1UGvK3OsSBs9aV9ovRcMjGA8ttPZbStM6VlblzdWfha+RY9Yt61OkAbS1ooQ2TRB1esGyd3EZgV0jTMtkbymitPog7XXEViIl5lp76clBOvUHCRhSO3XhU9ir840pQ+SOFTQBRK5OOhKOar2IX/n3smk+teqRbZ1zEa0cyrV/2Fg==
+www.example.net. 3600 IN A 10.0.0.1
+www.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. F0OiqJtl9nOonZePqV+boFuj5i1zTyDdj5yxZ80J7BQOoB0wGvcx105mriIW3mAQPmgq2K/lK317IejuP+kKBr8oGr82apCyP7NihAHr/dnqe4cTJJjQU1cjLJcIJHY6jg99DR6HkCZFRjEA8TI761E2GBfvxK0yPKEW1m8N9G9Wl5KZOHq8pQ1ZNDm4MR0rt2lvsuVaf+iGiw4HJkaD7Kceq3y9ukilsuP6Zl0dWMIeTqcs7UT3OS16HV21A9VL3rJGRLUonmJo7mUq8hpxKnFYK6/96IfXCf/XX1YI6rK0DVp1OE0S8s+teLG4UsE2p2+dC2arVwhHUGzlZMvO/A==
+ENTRY_END
+
+
+; CNAME from untrusted to trusted sub-tree
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.org. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.org. IN A
+SECTION ANSWER
+www.example.org. IN CNAME www.example.com.
+www.example.com. 3600 IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313131924 20170213131924 11901 example.com. TyWar/GZu4Vw5t4YTnxF8XRJAmHTWAA0snal0I6qH4pBxqmmYMHdFuGmiKwQNUpNlntOaAHj2UElkHa07eF+/Hb7mwf926bzGa13of2zS3rmwaqNi0nDns6PNWmzmpG65jKXqug5X7QrKIO00KeFWPM3T6LXp3TyZ9v1c5wtze1UGvK3OsSBs9aV9ovRcMjGA8ttPZbStM6VlblzdWfha+RY9Yt61OkAbS1ooQ2TRB1esGyd3EZgV0jTMtkbymitPog7XXEViIl5lp76clBOvUHCRhSO3XhU9ir840pQ+SOFTQBRK5OOhKOar2IX/n3smk+teqRbZ1zEa0cyrV/2Fg==
+www.example.net. 3600 IN A 10.0.0.1
+www.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. F0OiqJtl9nOonZePqV+boFuj5i1zTyDdj5yxZ80J7BQOoB0wGvcx105mriIW3mAQPmgq2K/lK317IejuP+kKBr8oGr82apCyP7NihAHr/dnqe4cTJJjQU1cjLJcIJHY6jg99DR6HkCZFRjEA8TI761E2GBfvxK0yPKEW1m8N9G9Wl5KZOHq8pQ1ZNDm4MR0rt2lvsuVaf+iGiw4HJkaD7Kceq3y9ukilsuP6Zl0dWMIeTqcs7UT3OS16HV21A9VL3rJGRLUonmJo7mUq8hpxKnFYK6/96IfXCf/XX1YI6rK0DVp1OE0S8s+teLG4UsE2p2+dC2arVwhHUGzlZMvO/A==
+ENTRY_END
+
+; cache test
+STEP 22 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.org. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 23 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.org. IN A
+SECTION ANSWER
+www.example.org. IN CNAME www.example.com.
+www.example.com. 3600 IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313131924 20170213131924 11901 example.com. TyWar/GZu4Vw5t4YTnxF8XRJAmHTWAA0snal0I6qH4pBxqmmYMHdFuGmiKwQNUpNlntOaAHj2UElkHa07eF+/Hb7mwf926bzGa13of2zS3rmwaqNi0nDns6PNWmzmpG65jKXqug5X7QrKIO00KeFWPM3T6LXp3TyZ9v1c5wtze1UGvK3OsSBs9aV9ovRcMjGA8ttPZbStM6VlblzdWfha+RY9Yt61OkAbS1ooQ2TRB1esGyd3EZgV0jTMtkbymitPog7XXEViIl5lp76clBOvUHCRhSO3XhU9ir840pQ+SOFTQBRK5OOhKOar2IX/n3smk+teqRbZ1zEa0cyrV/2Fg==
+www.example.net. 3600 IN A 10.0.0.1
+www.example.net. 3600 IN RRSIG A 7 3 3600 20170313131043 20170213131043 59835 example.net. F0OiqJtl9nOonZePqV+boFuj5i1zTyDdj5yxZ80J7BQOoB0wGvcx105mriIW3mAQPmgq2K/lK317IejuP+kKBr8oGr82apCyP7NihAHr/dnqe4cTJJjQU1cjLJcIJHY6jg99DR6HkCZFRjEA8TI761E2GBfvxK0yPKEW1m8N9G9Wl5KZOHq8pQ1ZNDm4MR0rt2lvsuVaf+iGiw4HJkaD7Kceq3y9ukilsuP6Zl0dWMIeTqcs7UT3OS16HV21A9VL3rJGRLUonmJo7mUq8hpxKnFYK6/96IfXCf/XX1YI6rK0DVp1OE0S8s+teLG4UsE2p2+dC2arVwhHUGzlZMvO/A==
+ENTRY_END
+
+
+; CNAME from trusted to untrusted sub-tree
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+insecure.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 31 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+insecure.example.com. IN A
+SECTION ANSWER
+insecure.example.com. 3600 IN CNAME insecure.example.net.
+insecure.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313140157 20170213140157 11901 example.com. PwYkM20oqzXrK+48AJgJUQP5MNbVjV9Xt9PG5ag2U7DrckQbVvuZ6dorouqUbVvLXhpbfInGazxgGGSE+hObhkhJcrRcmg2pKHWbRpBJqNnMeXk/w5zzlIOBq+Hu+ZpyUsbfJeax0S+gOyKLSeqRLDzOxWsSiFfPD2PSdfHcdslDxWLt92J8Yr2/wqh5aW7HOYDRZbvZkfP+0J4FWfWI6j25flbR7/Kt8SBAcqvg4cFREVua847iAItKGZGqa6XWnUX9JSskBl97RG0T3jBel+nz3MjMVSDl5HYaazv+VuUcF4NbjIcZHt8QxVOLw6IF/XxwPunqLPGByIYrBreUJQ==
+insecure.example.net. 3600 IN CNAME insecure.example.org.
+insecure.example.net. 3600 IN RRSIG CNAME 7 3 3600 20170313140150 20170213140150 59835 example.net. L1NmsrbewJeWS4ZC07jR9EWPg5QqKwH8BklJIWnMYlfR1xaLcMS5hHeDQN3OUK8D79mxmoBQVIXPMig3CLJPkewJoOZMKD/UwHVosFbG9NbRbWtY6tTZtQnzLy45+AsoQeF0tnoJM+5pvE3wMyXLBgZWbZDGRd0/Uk5/wxddu7NkxAZ0U3zarFxpVnQgP+MKifaplfHko599psQ58BnoSMUB1FjeFsy78zkXd3PjX/VWevGNlABGmlpvWdQou8c6V9ihGVRmsha6ABW04cLgevDjgorrn1AAI88c1H/pRDoWjO5zyQ9PPFPusCTYTEWcuSDpN43RFCxrA7ENP2g1rw==
+insecure.example.org. 3600 IN A 10.2.2.2
+ENTRY_END
+
+; cache test
+STEP 32 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+insecure.example.com. IN A
+ENTRY_END
+
+STEP 33 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+insecure.example.com. IN A
+SECTION ANSWER
+insecure.example.com. 3600 IN CNAME insecure.example.net.
+insecure.example.com. 3600 IN RRSIG CNAME 7 3 3600 20170313140157 20170213140157 11901 example.com. PwYkM20oqzXrK+48AJgJUQP5MNbVjV9Xt9PG5ag2U7DrckQbVvuZ6dorouqUbVvLXhpbfInGazxgGGSE+hObhkhJcrRcmg2pKHWbRpBJqNnMeXk/w5zzlIOBq+Hu+ZpyUsbfJeax0S+gOyKLSeqRLDzOxWsSiFfPD2PSdfHcdslDxWLt92J8Yr2/wqh5aW7HOYDRZbvZkfP+0J4FWfWI6j25flbR7/Kt8SBAcqvg4cFREVua847iAItKGZGqa6XWnUX9JSskBl97RG0T3jBel+nz3MjMVSDl5HYaazv+VuUcF4NbjIcZHt8QxVOLw6IF/XxwPunqLPGByIYrBreUJQ==
+insecure.example.net. 3600 IN CNAME insecure.example.org.
+insecure.example.net. 3600 IN RRSIG CNAME 7 3 3600 20170313140150 20170213140150 59835 example.net. L1NmsrbewJeWS4ZC07jR9EWPg5QqKwH8BklJIWnMYlfR1xaLcMS5hHeDQN3OUK8D79mxmoBQVIXPMig3CLJPkewJoOZMKD/UwHVosFbG9NbRbWtY6tTZtQnzLy45+AsoQeF0tnoJM+5pvE3wMyXLBgZWbZDGRd0/Uk5/wxddu7NkxAZ0U3zarFxpVnQgP+MKifaplfHko599psQ58BnoSMUB1FjeFsy78zkXd3PjX/VWevGNlABGmlpvWdQou8c6V9ihGVRmsha6ABW04cLgevDjgorrn1AAI88c1H/pRDoWjO5zyQ9PPFPusCTYTEWcuSDpN43RFCxrA7ENP2g1rw==
+insecure.example.org. 3600 IN A 10.2.2.2
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cnamenx_dblnsec.rpl b/tests/deckard/sets/resolver/val_cnamenx_dblnsec.rpl
new file mode 100644
index 0000000..5c6f423
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cnamenx_dblnsec.rpl
@@ -0,0 +1,178 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 21485 7 1 D0AED7DEAE346B008881F31F9ABBB055DF94CBD5 "
+val-override-date: "20181130121821"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with cname-nxdomain for duplicate NSEC detection
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cname.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cname.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101821 20181130101821 21485 example.com. cdC5PUdx8wOzA3Ffx0jI2KrGMpU0VmxM/Y7RpFM0JgCMO3aeYsGbtcpR pvS6i9sSFUTA3XNp0tiGqpS1iH07CJy67U0g1qKh/peHn07TWCrR9Kqy 0OXGlNfZQL4BG5i7hq0VXvUeBvyquMeTd0c6n/yni8DDFx0l95lvu5nr k5w= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101821 20181130101821 21485 example.com. soIpMtGzUOKCj5F6RjqQxrrhSJwhWLv9plOIEfGyI9OLgTYaTYgqC1R9 /4IIVPjzk4mB5VJSLcLNN2/QP8Qa/gO/dIb5o6nnHKdfDS4IPpG6ikeM T9cS2EMJ0+5rI5nLTCIofvGmsYTtjMuT3ysJ8xM4/9p1A7yjd49Mrkeb JWo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdHIjtVPYHtA3eUV5xOLpXVDAxdm16vsbjbfA4zFA9h2i1snUhCo fZV3hnOzn6WGpJkn/K2FBioTbwqhtQgEKnAg4+wxr+FnE/D89hdTF3CJ av/DRtw5pOu7PK5LbVZWWE2ztmok57RoMr31ecQGJ3S/B2rCZDaEDbYg EK+MoKHZ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101821 20181130101821 21485 example.com. gHeTNDlfGHqlxNke2s0TIm4x6fFdV64FgkCyc9CVf+eR5gMqpnhkRBk5 DdDK1Gi5MO3XnbzRcUrC2Y+7i20M+nTA+KD9ZlQsXWszevLYJY3TJmnQ cz9d5hQJexrAx1+G0C78vDO6vWZNJz3J0LzvDQcmH23R3j9ow2wM1W7x f4k= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101821 20181130101821 21485 example.com. cdC5PUdx8wOzA3Ffx0jI2KrGMpU0VmxM/Y7RpFM0JgCMO3aeYsGbtcpR pvS6i9sSFUTA3XNp0tiGqpS1iH07CJy67U0g1qKh/peHn07TWCrR9Kqy 0OXGlNfZQL4BG5i7hq0VXvUeBvyquMeTd0c6n/yni8DDFx0l95lvu5nr k5w= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101821 20181130101821 21485 example.com. soIpMtGzUOKCj5F6RjqQxrrhSJwhWLv9plOIEfGyI9OLgTYaTYgqC1R9 /4IIVPjzk4mB5VJSLcLNN2/QP8Qa/gO/dIb5o6nnHKdfDS4IPpG6ikeM T9cS2EMJ0+5rI5nLTCIofvGmsYTtjMuT3ysJ8xM4/9p1A7yjd49Mrkeb JWo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+cname.example.com. IN A
+SECTION ANSWER
+cname.example.com. 3600 IN CNAME www.example.com.
+cname.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101821 20181130101821 21485 example.com. KSB4An66g0tVndlXTHPjpRzQmsM6TMvV54THQJmiPqiI9UNTQwIwgEPI zSG5lUZwqORK7h4fTStwAosDl+dKFtPWoiW3yV0XytaJqJBfB5eOr6/X 665Qp876He3ZhVBYfekFVZnO+amzv8oycjngPsSHxpMZ760HNFRSgacy bDc= ;{id = 2854}
+SECTION AUTHORITY
+; already includes the necessary NSECs
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101821 20181130101821 21485 example.com. kvapB5PKSev/ZKLrVqexb3HPFftCrdE7a5fYzzAlSmW85Wzj4b7Pi3pU Jyh6W+9Wo7iTkT9NdBy93RgApoW38CHVh4/FiGJlbIs+cJFgpMfG1kdu Q2j3xn5P4TUlRX9PNtkjDdy13FqpiSMPHNU1ZdLq5oQ/wL2vNSsJ83zq ZZw= ;{id = 2854}
+; wildcard denial
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101821 20181130101821 21485 example.com. W4RWRKbmCTSKQZuIaDybI+dEwB+wKs24C9f5h01XRuhj9OKTEeomaHCN 4AsK+DdsU7Z6QBYedn+rbYjaCjbTQqztc7Qi8fAF/dw9wRG+WMdATnqD 0uJGRsQLzJmzjttKp64Njtgl4eiNuhOwYzsZpDANKwMv1Rlg7P7HVsZU T+g= ;{id = 2854}
+; qname denial
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101821 20181130101821 21485 example.com. WFil25/HtvZtJ3QUa9toox+C+qcJOKJwcZ2ylTOlSJzJrJB99oTKN1ZW XLDIRHPX81TTEp0edigErhyLO+xna1+L96Ze4tN9nP/0+N7gzY3bhzmg sms/ojtjuqKSf0ac1ZAUU3aGSdA/rgBYfeTh/2wMaLcQC1BUBZFsztAs sUg= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101821 20181130101821 21485 example.com. kvapB5PKSev/ZKLrVqexb3HPFftCrdE7a5fYzzAlSmW85Wzj4b7Pi3pU Jyh6W+9Wo7iTkT9NdBy93RgApoW38CHVh4/FiGJlbIs+cJFgpMfG1kdu Q2j3xn5P4TUlRX9PNtkjDdy13FqpiSMPHNU1ZdLq5oQ/wL2vNSsJ83zq ZZw= ;{id = 2854}
+; wildcard denial
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101821 20181130101821 21485 example.com. W4RWRKbmCTSKQZuIaDybI+dEwB+wKs24C9f5h01XRuhj9OKTEeomaHCN 4AsK+DdsU7Z6QBYedn+rbYjaCjbTQqztc7Qi8fAF/dw9wRG+WMdATnqD 0uJGRsQLzJmzjttKp64Njtgl4eiNuhOwYzsZpDANKwMv1Rlg7P7HVsZU T+g= ;{id = 2854}
+; qname denial
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101821 20181130101821 21485 example.com. WFil25/HtvZtJ3QUa9toox+C+qcJOKJwcZ2ylTOlSJzJrJB99oTKN1ZW XLDIRHPX81TTEp0edigErhyLO+xna1+L96Ze4tN9nP/0+N7gzY3bhzmg sms/ojtjuqKSf0ac1ZAUU3aGSdA/rgBYfeTh/2wMaLcQC1BUBZFsztAs sUg= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+cname.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+cname.example.com. IN A
+SECTION ANSWER
+cname.example.com. 3600 IN CNAME www.example.com.
+cname.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101821 20181130101821 21485 example.com. KSB4An66g0tVndlXTHPjpRzQmsM6TMvV54THQJmiPqiI9UNTQwIwgEPI zSG5lUZwqORK7h4fTStwAosDl+dKFtPWoiW3yV0XytaJqJBfB5eOr6/X 665Qp876He3ZhVBYfekFVZnO+amzv8oycjngPsSHxpMZ760HNFRSgacy bDc= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101821 20181130101821 21485 example.com. kvapB5PKSev/ZKLrVqexb3HPFftCrdE7a5fYzzAlSmW85Wzj4b7Pi3pU Jyh6W+9Wo7iTkT9NdBy93RgApoW38CHVh4/FiGJlbIs+cJFgpMfG1kdu Q2j3xn5P4TUlRX9PNtkjDdy13FqpiSMPHNU1ZdLq5oQ/wL2vNSsJ83zq ZZw= ;{id = 2854}
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101821 20181130101821 21485 example.com. W4RWRKbmCTSKQZuIaDybI+dEwB+wKs24C9f5h01XRuhj9OKTEeomaHCN 4AsK+DdsU7Z6QBYedn+rbYjaCjbTQqztc7Qi8fAF/dw9wRG+WMdATnqD 0uJGRsQLzJmzjttKp64Njtgl4eiNuhOwYzsZpDANKwMv1Rlg7P7HVsZU T+g= ;{id = 2854}
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101821 20181130101821 21485 example.com. WFil25/HtvZtJ3QUa9toox+C+qcJOKJwcZ2ylTOlSJzJrJB99oTKN1ZW XLDIRHPX81TTEp0edigErhyLO+xna1+L96Ze4tN9nP/0+N7gzY3bhzmg sms/ojtjuqKSf0ac1ZAUU3aGSdA/rgBYfeTh/2wMaLcQC1BUBZFsztAs sUg= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_cnameqtype.rpl b/tests/deckard/sets/resolver/val_cnameqtype.rpl
new file mode 100644
index 0000000..3723c93
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_cnameqtype.rpl
@@ -0,0 +1,230 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 6497 7 1 E91FB78CB1A0ADB57A05FC8B495EA748B24375AB "
+ trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AwEAAcpXb9Fxep3BvyNndHR3k28yz1zSqgGntKz60tQf8t2jm2l1F3LO 7Oc3FdllY/FS8VACyIZTbU4WiEfoOToHF6KX5mj8n82wJKkZLKx0w52x jrUbASX0sm2rEwwcjAsDkXSIGUkSm5b7SY5KvXpuwTYl7Ql1gxdTgqou vnSCK+99 ;{id = 30899 (zsk), size = 512b}"
+val-override-date: "20181130121824"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with a query for type cname
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN CNAME
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN CNAME
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN CNAME
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101823 20181130101823 6497 example.com. ky4ZB/3l28EQx3cFbU4lWHNp5GI+Ca9S9z+M6kr9UqOkPk+bJN4VilR0 ng8u9D36mLzYJtWktdnrexcIGyba+c5dVul1yJYBQNxca1+Gdv0ObVb5 hhIAZ9psrKJglkAMTnsrokHgdDryfzII8mlZNWJCQHGPnIJLf583nYxe pks= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101823 20181130101823 6497 example.com. kj86vWDY5SK8oz/F3sbJjU1sVfdRjD90zUGS7xB0TI31UVel6Ww7PB36 nyHddUcTQ3SEJOETsnub6x8ZtOhxd2kRgkORhz84EeN+1bnOQLpnpTXQ wY7yOXIgf1sY1JzWTIhxXUnDftvpn05Y/C3Srfou1uFnv/5V29P1Q0Or GN0= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbosaUoM51nu1Bfb1SBXWBd5RLicFoYgKEoqBVkd0gpyTQV2hwLx wIhKx5m5hYBmy9MU8zT2vTaYsafTNhYABl4gzMjLV4h2gx6P3o0OCcBq Fl6xuYEzbdrbavedO3wSzGNk8tBhmtQW8hbBsbEkFBgZaM06Y4T5D89a Wroa46nh ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101823 20181130101823 6497 example.com. Iompwlf1+hL5mUrLLUTki8/zwt8CDLsLjAMyZfx4ojiTTR9y1uIDuJm+ qgSkS69OOVjaEw9ZaBRTZh7Km4xjLauZsRdBf6jFJeDttkDsASQDHG4T ooMAF/pNYjBK5+4YSJexbfr9KY1ICrBslJUKMFgVOdu5ICLZdon5kOBc wVo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101823 20181130101823 6497 example.com. ky4ZB/3l28EQx3cFbU4lWHNp5GI+Ca9S9z+M6kr9UqOkPk+bJN4VilR0 ng8u9D36mLzYJtWktdnrexcIGyba+c5dVul1yJYBQNxca1+Gdv0ObVb5 hhIAZ9psrKJglkAMTnsrokHgdDryfzII8mlZNWJCQHGPnIJLf583nYxe pks= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101823 20181130101823 6497 example.com. kj86vWDY5SK8oz/F3sbJjU1sVfdRjD90zUGS7xB0TI31UVel6Ww7PB36 nyHddUcTQ3SEJOETsnub6x8ZtOhxd2kRgkORhz84EeN+1bnOQLpnpTXQ wY7yOXIgf1sY1JzWTIhxXUnDftvpn05Y/C3Srfou1uFnv/5V29P1Q0Or GN0= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN CNAME
+SECTION ANSWER
+www.example.com. IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101823 20181130101823 6497 example.com. QFHRboEy5RNC87lRlKaXgWDJFzQXl3GKED1G4xvCRl3BfSK3toI9ADRE ykjnW1XgmQ5YJrP9aQBHDognOrvJ6sMYArRsbH1HSWjyeYgWibhkZvwl JNzCdNhptCjTJw7fP7sc1XMqMO5REBzFmW7lWIgrzwRJhCLLQ1g7D+46 38U= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS 5 2 3600 20181230101823 20181130101823 31500 example.net. akNwK5ythyddy+MMl0/n3DPfIVGM31xj3TCE3xr9N6l0Ue9puoc2ad5U QwNUp0F+7DJABPnx8DKBsctPJSR4dSJ02s7IVAueLWjzUiBTE+NEioEC pfmzBaNqjt0JrdtZgwz5oCxfqovfnHC7sQTtnArlpMcmnTghuHKeWRaj yYQ= ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A 5 3 3600 20181230101823 20181130101823 31500 example.net. gDeBSHmtmO4x9o4X7A9YLCAprLak7E79QR//ajPY+Ih2OAx1EKVK8ftJ 2ihAdt4IR80akLJizbGf/iCTRaSkUwYwCZB/nwRaxO0Z9cH1h3HENFSt WmM4GybIHk8Q6uC3Jowirenjfhm4EnR813FMLmrwYcxs5YbyN3kl7tqu PrY= ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net. 3600 IN DNSKEY 256 3 5 AwEAAcpXb9Fxep3BvyNndHR3k28yz1zSqgGntKz60tQf8t2jm2l1F3LO 7Oc3FdllY/FS8VACyIZTbU4WiEfoOToHF6KX5mj8n82wJKkZLKx0w52x jrUbASX0sm2rEwwcjAsDkXSIGUkSm5b7SY5KvXpuwTYl7Ql1gxdTgqou vnSCK+99 ;{id = 30899 (zsk), size = 512b}
+example.net. 3600 IN RRSIG DNSKEY 5 2 3600 20181230101823 20181130101823 31500 example.net. p3olaCEfXPEmJR5JS9DrYRbzIrPWAE5VBVPRHCKZ1geQNjCgSTr956oI p64LHodGZRc5dUWA79DYdK1xNtUZIJVpw5CudQGn/c11QJRSdT57A7yZ G7ikneZrkJHMn5+fbJLPeLhxTOKjKRXAHiohG7jEH+2q70KfZCobQ0GX +e4= ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS 5 2 3600 20181230101823 20181130101823 31500 example.net. akNwK5ythyddy+MMl0/n3DPfIVGM31xj3TCE3xr9N6l0Ue9puoc2ad5U QwNUp0F+7DJABPnx8DKBsctPJSR4dSJ02s7IVAueLWjzUiBTE+NEioEC pfmzBaNqjt0JrdtZgwz5oCxfqovfnHC7sQTtnArlpMcmnTghuHKeWRaj yYQ= ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A 5 3 3600 20181230101823 20181130101823 31500 example.net. gDeBSHmtmO4x9o4X7A9YLCAprLak7E79QR//ajPY+Ih2OAx1EKVK8ftJ 2ihAdt4IR80akLJizbGf/iCTRaSkUwYwCZB/nwRaxO0Z9cH1h3HENFSt WmM4GybIHk8Q6uC3Jowirenjfhm4EnR813FMLmrwYcxs5YbyN3kl7tqu PrY= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. IN A 11.12.13.14
+www.example.net. 3600 IN RRSIG A 5 3 3600 20181230101823 20181130101823 31500 example.net. J+nuJ0xEW3wgDh0lO6sVMfcY1NGvM9gtd3dV+nc2wBKmnGfeJfGDDcVq SibPV3NXo1N9vj3Cp8v0oT2e/vGzc20VpeWi7e24tchRL4DLnP8YvFjE P4pEoCv4J0pikYz3L2AdH0PYtpJR1KsweZbeDC3XgpPi/uqcGOLzs4gK JIE= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN CNAME
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN CNAME
+SECTION ANSWER
+www.example.com. IN CNAME www.example.net.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101823 20181130101823 6497 example.com. QFHRboEy5RNC87lRlKaXgWDJFzQXl3GKED1G4xvCRl3BfSK3toI9ADRE ykjnW1XgmQ5YJrP9aQBHDognOrvJ6sMYArRsbH1HSWjyeYgWibhkZvwl JNzCdNhptCjTJw7fP7sc1XMqMO5REBzFmW7lWIgrzwRJhCLLQ1g7D+46 38U= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_deleg_nons.rpl b/tests/deckard/sets/resolver/val_deleg_nons.rpl
new file mode 100644
index 0000000..c589db6
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_deleg_nons.rpl
@@ -0,0 +1,271 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with unsigned delegation with no NS bit in NSEC
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns3.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.www.example.com. IN A
+SECTION ANSWER
+foo.www.example.com. IN A 1.2.3.4
+; unsigned, no delegation.
+ENTRY_END
+
+; DS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+; NSEC3 here: 1 0 1 1234
+; www.example.com. -> h8c0nvkuibedn7ia997iegdl7h0i6h8b.
+h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. IN NSEC3 1 0 1 1234 h8c0nvkuibedn7ia997iegdl7h0i6h8c TXT
+h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. AH+bPQZST3COwJ1vSe05N7E5BM2GmXzJUKsiWwXKrmm/XjYKSxSuNPE=
+
+;www.example.com. IN NSEC zzz.example.com. RRSIG NSEC
+;www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AA9Dm626WvHXHPQXJkVyjyTqJ/dCHfZgt6PWCn9gd8ZmPxyl3STW3iI=
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+; DS query for foo.www.example.com returns the referral without record.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+foo.www.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+mipf0g23547qunto04vboegh9vadsrpo.example.com. IN NSEC3 1 0 1 1234 mipf0g23547qunto04vboegh9vadsrpq TXT
+mipf0g23547qunto04vboegh9vadsrpo.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. ADc6JrdKuTmIJe4sAjpKZSUZKdHdfhmREk2F5A5cftU9053b0/3ILQM=
+
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+
+
+;www.example.com. IN NS ns3.example.com.
+;h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. IN NSEC3 1 0 1 1234 h8c0nvkuibedn7ia997iegdl7h0i6h8c TXT
+;h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. AH+bPQZST3COwJ1vSe05N7E5BM2GmXzJUKsiWwXKrmm/XjYKSxSuNPE=
+;SECTION ADDITIONAL
+;ns3.example.com. IN A 1.2.3.5
+
+
+; NSEC3 here: 1 0 1 1234
+; www.example.com. -> h8c0nvkuibedn7ia997iegdl7h0i6h8b.
+; *.www.example.com. -> cg2lpgpr8k7ck69h7bqu3od9pkht2o79.
+; foo.www.example.com. -> mipf0g23547qunto04vboegh9vadsrpo.
+
+;h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. IN NSEC3 1 0 1 1234 h8c0nvkuibedn7ia997iegdl7h0i6h8c TXT
+;h8c0nvkuibedn7ia997iegdl7h0i6h8b.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. AH+bPQZST3COwJ1vSe05N7E5BM2GmXzJUKsiWwXKrmm/XjYKSxSuNPE=
+;cg2lpgpr8k7ck69h7bqu3od9pkht2o78.example.com. IN NSEC3 1 0 1 1234 cg2lpgpr8k7ck69h7bqu3od9pkht2o89 TXT
+;cg2lpgpr8k7ck69h7bqu3od9pkht2o78.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. ACzxBHMyDB5tTrXijboPSsB0ws1lJe3/B62QNAMcZv7l9DYNDEDKsXY=
+;mipf0g23547qunto04vboegh9vadsrph.example.com. IN NSEC3 1 0 1 1234 mipf0g23547qunto04vboegh9vadsrpp TXT
+;mipf0g23547qunto04vboegh9vadsrph.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134150 20070829134150 2854 example.com. AG2B7lrIVtBgg+WIt0yNYekGDBKkY7xkKfI0GLQ8q3brGy/+jubxba0=
+
+;www.example.com. IN NSEC zzz.example.com. RRSIG NSEC
+;www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AA9Dm626WvHXHPQXJkVyjyTqJ/dCHfZgt6PWCn9gd8ZmPxyl3STW3iI=
+
+;example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+;example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+; ns3.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+foo.www.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+foo.www.example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+foo.www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+foo.www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ds_afterprime.rpl b/tests/deckard/sets/resolver/val_ds_afterprime.rpl
new file mode 100644
index 0000000..2a232d5
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ds_afterprime.rpl
@@ -0,0 +1,181 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 15287 7 1 19F0E0DB8795AEC6205262B1E0CBF978874E2179 "
+val-override-date: "20181130121843"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+query-minimization: off
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test DS lookup after key prime is done.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DS
+SECTION AUTHORITY
+com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101842 20181130101842 15287 example.com. byFJB2kc/MA/v3BaJzKJduu+yUO8CGmW5P9hJv21Ha5O2pfbWg8ykdc1 XzBuWCis2rvVoVXaurZNjaqc/WGxSHWG1MM16vz28Y3SsE3f0FouMkXe cgfoIb2S2FTF4yttMw9u7fnOCOqqar7i/bxp7y60Ep+oNrpZ5wOSr4Vv 1co= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. B3wtuzeTzVA5dMZPNKhGQtI4DXkirjI4MxsBMC0MYw7LX3hBddYCHTMF DwshRpz19PHU+0neisSXxYo1PScJW46nCjixwf5gPHhKR8up1d4evM+l ciKW0FAGIBkpvrpnoSXlk6FBGvkyNdyrEdBuZxC/SWrLQizndZ+we8LQ cJc= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdi6IgbGvRjV6ufAZtyfKXEV/rzEUm/zOYwcpLnpNkof20KxdX+g Tv0SJpdlbH/cRjnpIyeeKhTDfaHwG+3NXeJ01SR+tFl1sBNZOWDEu8wy htRv7Q/J+ZwzXCg4yBXSAuVzxfdyOTZK/r1HSHXeY1KJ+naBZXEPvkCY 8OqPkNSN ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101842 20181130101842 15287 example.com. IK5CbBIOLacwoEzRk0SFvd4MV6SLh8N0muBFd4uDaZ5nllUfX9umT4iN YlkIdkeXNVGsHzo4u8oxYfg/dL1FAtuJGjRQUijngKuWP5qzj3+niDvB BDDHHrukFLteNs/taAOILuGgyccTpWLXbAyK77QbsMMVAsZH5s9Kqhws XOU= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101842 20181130101842 15287 example.com. byFJB2kc/MA/v3BaJzKJduu+yUO8CGmW5P9hJv21Ha5O2pfbWg8ykdc1 XzBuWCis2rvVoVXaurZNjaqc/WGxSHWG1MM16vz28Y3SsE3f0FouMkXe cgfoIb2S2FTF4yttMw9u7fnOCOqqar7i/bxp7y60Ep+oNrpZ5wOSr4Vv 1co= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. B3wtuzeTzVA5dMZPNKhGQtI4DXkirjI4MxsBMC0MYw7LX3hBddYCHTMF DwshRpz19PHU+0neisSXxYo1PScJW46nCjixwf5gPHhKR8up1d4evM+l ciKW0FAGIBkpvrpnoSXlk6FBGvkyNdyrEdBuZxC/SWrLQizndZ+we8LQ cJc= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. IcYBBoimvXzuLUujq3+nt7mmKK6Qk1bxGi4KV0011efmrvo0voeRNb9G 5ZEPtYilUGYOKUu3PMKcCnXlPYARm4dUChaDKkjG/rCvWumVv6YgZquc YqnrMBOurMoqEeMST42v61RuLUqlQDqSdMTKoTRi4Q5EjHSpqnrzG1a3 8SY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101842 20181130101842 15287 example.com. byFJB2kc/MA/v3BaJzKJduu+yUO8CGmW5P9hJv21Ha5O2pfbWg8ykdc1 XzBuWCis2rvVoVXaurZNjaqc/WGxSHWG1MM16vz28Y3SsE3f0FouMkXe cgfoIb2S2FTF4yttMw9u7fnOCOqqar7i/bxp7y60Ep+oNrpZ5wOSr4Vv 1co= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. B3wtuzeTzVA5dMZPNKhGQtI4DXkirjI4MxsBMC0MYw7LX3hBddYCHTMF DwshRpz19PHU+0neisSXxYo1PScJW46nCjixwf5gPHhKR8up1d4evM+l ciKW0FAGIBkpvrpnoSXlk6FBGvkyNdyrEdBuZxC/SWrLQizndZ+we8LQ cJc= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. IcYBBoimvXzuLUujq3+nt7mmKK6Qk1bxGi4KV0011efmrvo0voeRNb9G 5ZEPtYilUGYOKUu3PMKcCnXlPYARm4dUChaDKkjG/rCvWumVv6YgZquc YqnrMBOurMoqEeMST42v61RuLUqlQDqSdMTKoTRi4Q5EjHSpqnrzG1a3 8SY= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 7 2 3600 20181230101842 20181130101842 15287 example.com. byFJB2kc/MA/v3BaJzKJduu+yUO8CGmW5P9hJv21Ha5O2pfbWg8ykdc1 XzBuWCis2rvVoVXaurZNjaqc/WGxSHWG1MM16vz28Y3SsE3f0FouMkXe cgfoIb2S2FTF4yttMw9u7fnOCOqqar7i/bxp7y60Ep+oNrpZ5wOSr4Vv 1co= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101842 20181130101842 15287 example.com. B3wtuzeTzVA5dMZPNKhGQtI4DXkirjI4MxsBMC0MYw7LX3hBddYCHTMF DwshRpz19PHU+0neisSXxYo1PScJW46nCjixwf5gPHhKR8up1d4evM+l ciKW0FAGIBkpvrpnoSXlk6FBGvkyNdyrEdBuZxC/SWrLQizndZ+we8LQ cJc= ;{id = 2854}
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+example.com. IN DS
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+example.com. IN DS
+SECTION AUTHORITY
+com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ds_cname.rpl b/tests/deckard/sets/resolver/val_ds_cname.rpl
new file mode 100644
index 0000000..ce69795
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ds_cname.rpl
@@ -0,0 +1,204 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 55850 7 1 B3DEDE56E5386B588339D978A1B173B8B10366B8 "
+val-override-date: "20181130121844"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with CNAME response to DS
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+; not legal NOERROR/NODATA response, but leniently accepted (not validated)
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101843 20181130101843 55850 example.com. rSyN+LKU0kF6GBRW/L0R1siq0SrS0s/zOJge//1VXqRit+vtrRFjoHVa EytY4CfTZKj8YKkFnTIvKL30/Uxi2+t4uTtYLCBAnFFINRpjzuXhntiB +QWfkQruu/9NgFSb9Jb4xbSqB8khHxV3vN8lLr3WIFIAHbMWyBYmerm+ g3c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101843 20181130101843 55850 example.com. Mi0XLYyAfzvfbudd7gfWE5aBeY5cmQVIcgoJMeduX5Z9/bWeLepyFvaW ClDqbNz59yms4xxhOKg5xLS/rzTneVk3Y1VtoiZBbr0h6fSkEYoMAk52 lWKFTjEJujKCb6rxeh9lKh7XrKELbJEC90in+0ESILIvnNfltK4aCbKS 3aY= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101843 20181130101843 55850 example.com. rSyN+LKU0kF6GBRW/L0R1siq0SrS0s/zOJge//1VXqRit+vtrRFjoHVa EytY4CfTZKj8YKkFnTIvKL30/Uxi2+t4uTtYLCBAnFFINRpjzuXhntiB +QWfkQruu/9NgFSb9Jb4xbSqB8khHxV3vN8lLr3WIFIAHbMWyBYmerm+ g3c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101843 20181130101843 55850 example.com. Mi0XLYyAfzvfbudd7gfWE5aBeY5cmQVIcgoJMeduX5Z9/bWeLepyFvaW ClDqbNz59yms4xxhOKg5xLS/rzTneVk3Y1VtoiZBbr0h6fSkEYoMAk52 lWKFTjEJujKCb6rxeh9lKh7XrKELbJEC90in+0ESILIvnNfltK4aCbKS 3aY= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbm150kVuAzpvRlnxNCv10c1j7JIhpap2sCGfPpvMEr8jB6lxYQz GhnnnpD58hcuKwVQpptSKM+AOiyN4ZM72GWSKchxxBL8/9MBLCPY9BI8 I3d447MlB6FKnnJlN30MBUql17gIh8zAvdgGFj6tPzUkQDCHZuMASXLy 8OE2LdtL ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101843 20181130101843 55850 example.com. LAKGmWjHK74ndtynMkRHPUTLrQJSW6me7CFTWTXtlfa1e510cFCA/0XY quFECNj6qzqUNIgsoLOv4Rox29SrvhBHBvbCt98ylWr29DPY6UofvZhC 7g5Ss89GFEzj+RV/ffdqnts1Lxpd2PGzUZIAFWwfx7h1/Jxw89Vl7YFK /3U= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101843 20181130101843 55850 example.com. rSyN+LKU0kF6GBRW/L0R1siq0SrS0s/zOJge//1VXqRit+vtrRFjoHVa EytY4CfTZKj8YKkFnTIvKL30/Uxi2+t4uTtYLCBAnFFINRpjzuXhntiB +QWfkQruu/9NgFSb9Jb4xbSqB8khHxV3vN8lLr3WIFIAHbMWyBYmerm+ g3c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101843 20181130101843 55850 example.com. Mi0XLYyAfzvfbudd7gfWE5aBeY5cmQVIcgoJMeduX5Z9/bWeLepyFvaW ClDqbNz59yms4xxhOKg5xLS/rzTneVk3Y1VtoiZBbr0h6fSkEYoMAk52 lWKFTjEJujKCb6rxeh9lKh7XrKELbJEC90in+0ESILIvnNfltK4aCbKS 3aY= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; nothing here, not even NSECs
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101843 20181130101843 55850 example.com. rSyN+LKU0kF6GBRW/L0R1siq0SrS0s/zOJge//1VXqRit+vtrRFjoHVa EytY4CfTZKj8YKkFnTIvKL30/Uxi2+t4uTtYLCBAnFFINRpjzuXhntiB +QWfkQruu/9NgFSb9Jb4xbSqB8khHxV3vN8lLr3WIFIAHbMWyBYmerm+ g3c= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+; DS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN DS
+SECTION ANSWER
+www.example.com. IN CNAME zzz.example.com.
+www.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101843 20181130101843 55850 example.com. T7yHaZwPh18N8a+6811mVm4r9MBcBMWHEnUnpKi6ZYZRrwVzLBJLB6Bz DQxg6oy5qmdWaij595a4U22vV6aX4eIROGa3vUkGE6xaiwyry/YNCDdf fCnNBpAAUcmMdnYTE8pbQi7yrR00xUjC7qYO7kzOSJ0kIhHTINrqzoZd XNw= ;{id = 2854}
+;*.example.com. IN CNAME zzz.example.com.
+;*.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101843 20181130101843 55850 example.com. T7yHaZwPh18N8a+6811mVm4r9MBcBMWHEnUnpKi6ZYZRrwVzLBJLB6Bz DQxg6oy5qmdWaij595a4U22vV6aX4eIROGa3vUkGE6xaiwyry/YNCDdf fCnNBpAAUcmMdnYTE8pbQi7yrR00xUjC7qYO7kzOSJ0kIhHTINrqzoZd XNw= ;{id = 2854}
+
+SECTION AUTHORITY
+*.example.com. IN NSEC zzz.example.com. CNAME RRSIG NSEC
+*.example.com. 3600 IN RRSIG NSEC 7 2 86400 20181230101843 20181130101843 55850 example.com. PMydg/KuumF/r2eVJNxYyi58Ft+wPHRBYFEXyuDHtFel39O/vhvx8cWB oQvX7FhDp3LdODA056gtcpQsgGSX3sTuKdUpDnR4jdJv9XIXRxrYtGa/ MOuS/4+gE67xmEzhZ2Ezyn3IDVPfVfEiUFPqdOHukSiCyqWnjnj2rOgd kUY= ;{id = 2854}
+zzz.example.com. IN NSEC *.zzz.example.com. A RRSIG NSEC
+zzz.example.com. 3600 IN RRSIG NSEC 7 3 86400 20181230101843 20181130101843 55850 example.com. DwFmG+fJOcWCO33ulBLIifA8OHgVQd9hmCU8K4OSH+pI+25U4dSPXwBT blkuyU2/1GFD2OQnyG6EpwFYMnX/JmnNr70J8pd6xtL7EGb2n9DNrJHK 0i0fxbJffVVbn59dCuFsi8unHhOVRknG6nLaEny2S6CisVSRSs3uX7n+ P3A= ;{id = 2854}
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101843 20181130101843 55850 example.com. JrM30NcE8xwejtIaExsewzwtN7A2rfnpn2nVJuYBKkm6xIQSgoxv0Sz2 5SuA1ilGzUr8gmgLJET+s5qSAi3ow9tkll4mcnBrruIhGJsK+3782V1f KJaFHGVWJUbfeIastg6KOImfmH1mTNIoN7g5maNIsF0qx2W05N9/LGpC CaU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+zzz.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+zzz.example.com. IN NSEC *.zzz.example.com. A RRSIG NSEC
+zzz.example.com. 3600 IN RRSIG NSEC 7 3 86400 20181230101843 20181130101843 55850 example.com. DwFmG+fJOcWCO33ulBLIifA8OHgVQd9hmCU8K4OSH+pI+25U4dSPXwBT blkuyU2/1GFD2OQnyG6EpwFYMnX/JmnNr70J8pd6xtL7EGb2n9DNrJHK 0i0fxbJffVVbn59dCuFsi8unHhOVRknG6nLaEny2S6CisVSRSs3uX7n+ P3A= ;{id = 2854}
+example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101843 20181130101843 55850 example.com. JrM30NcE8xwejtIaExsewzwtN7A2rfnpn2nVJuYBKkm6xIQSgoxv0Sz2 5SuA1ilGzUr8gmgLJET+s5qSAi3ow9tkll4mcnBrruIhGJsK+3782V1f KJaFHGVWJUbfeIastg6KOImfmH1mTNIoN7g5maNIsF0qx2W05N9/LGpC CaU= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ds_cnamesub.rpl b/tests/deckard/sets/resolver/val_ds_cnamesub.rpl
new file mode 100644
index 0000000..ffcee53
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ds_cnamesub.rpl
@@ -0,0 +1,277 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 33632 7 1 5497C677E6B860E0BC545C7D559AC3402095D6D1 "
+val-override-date: "20181130121845"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with CNAME response to DS in chain of trust
+; the CNAME is at a nonempty nonterminal name in the parent zone.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+; not legal NOERROR/NODATA response, but leniently accepted (not validated)
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101845 20181130101845 33632 example.com. KltuV+6jsjOXtJMKJapjnppUaOZRfkShElT2nsKnwMK4h2K3h7/BteWG JtuSF43IlDDGgifXDXpfEU+ITQyT4Oqa6ruzVDV8s6oRw1rKlAXMTT5a vmRhjoOw0qUJ5gc46QkLPGfsjTib5x61geF/fx+G/U0+b35W2rqj29jo vPc= ;{id = 2854}
+;example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400
+;example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101845 20181130101845 33632 example.com. NcdCcqG4gcDU808aZADHpHjkuo7O2j2t9UVQ9KycVPClncUyqMzxmAPy BjsG3MVr0y/H2Q6GT+IpDwK7L8CvLS2hUzczIDhAY2f2N3KATcfuNbYr 9BKenU0KgSPCunIpPGCFJSMfgaC8L30Uk/ilPSAJfwAsVbzu7qQPbftN T3M= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101845 20181130101845 33632 example.com. KltuV+6jsjOXtJMKJapjnppUaOZRfkShElT2nsKnwMK4h2K3h7/BteWG JtuSF43IlDDGgifXDXpfEU+ITQyT4Oqa6ruzVDV8s6oRw1rKlAXMTT5a vmRhjoOw0qUJ5gc46QkLPGfsjTib5x61geF/fx+G/U0+b35W2rqj29jo vPc= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101845 20181130101845 33632 example.com. NcdCcqG4gcDU808aZADHpHjkuo7O2j2t9UVQ9KycVPClncUyqMzxmAPy BjsG3MVr0y/H2Q6GT+IpDwK7L8CvLS2hUzczIDhAY2f2N3KATcfuNbYr 9BKenU0KgSPCunIpPGCFJSMfgaC8L30Uk/ilPSAJfwAsVbzu7qQPbftN T3M= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAc9yX6nFxFJ1PsA6b4GsM4jKCqA3cHZn6sbszgw57mXD8g/Amn21 +tYDBzdJwv6SspmXhLO8UPJ8C1+6zoW2CZuKTIp8mjUimWLOaJjl/IlZ 2BAFoSSBsyJSr8619eqQxVH4guLIAO1wzK5lcQSFpiLXh7/hDdpDciCR M8Y9PmZd ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101845 20181130101845 33632 example.com. ioMECLagEkWue617lYuaQl4KgRURblcPcoc/4uhapKgY0ZTYGH42SQ/Z 7ez9ViwMi4IpP6DS8QNOEnaVd8EHjPOMRPvwiPIoUPbqzz/3KlaZgMOg FhhgfLzMPORsvDqPT7mJ2QGsqc4WhUAawSOyhytDCauK2TO50Oi/UpQt FwY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101845 20181130101845 33632 example.com. KltuV+6jsjOXtJMKJapjnppUaOZRfkShElT2nsKnwMK4h2K3h7/BteWG JtuSF43IlDDGgifXDXpfEU+ITQyT4Oqa6ruzVDV8s6oRw1rKlAXMTT5a vmRhjoOw0qUJ5gc46QkLPGfsjTib5x61geF/fx+G/U0+b35W2rqj29jo vPc= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101845 20181130101845 33632 example.com. NcdCcqG4gcDU808aZADHpHjkuo7O2j2t9UVQ9KycVPClncUyqMzxmAPy BjsG3MVr0y/H2Q6GT+IpDwK7L8CvLS2hUzczIDhAY2f2N3KATcfuNbYr 9BKenU0KgSPCunIpPGCFJSMfgaC8L30Uk/ilPSAJfwAsVbzu7qQPbftN T3M= ;{id = 2854}
+ENTRY_END
+
+; response to DS query for a.example.com, a CNAME
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.example.com. IN DS
+SECTION ANSWER
+a.example.com. IN CNAME zzz.example.net.
+a.example.com. 3600 IN RRSIG CNAME 7 3 3600 20181230101845 20181130101845 33632 example.com. aV8SmzDUh1bLt0FEiUKIC7BZKdzTB+TcpraOLn5CSwIFsnG/2itqavJo u2BEYP0Hay1AYeBwhA7/LJaqa4WVZUl02ExlsrNc8qxTFvs+qhNtR9fG vXCB4PrwWlABaD4/T2Uvc98+cFArn6o8JMONZIWzg8yuRkNDo9hxWHEI XR4=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; response to DS query for sub.a.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.a.example.com. IN DS
+SECTION ANSWER
+sub.a.example.com. 3600 IN DS 32886 7 1 05B70AC8C521B130A865EDE411A06135C5BC49E2
+sub.a.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101845 20181130101845 33632 example.com. YX6ThbV357iGXSf8J/D67wCUf6YQWO3cQnrX46Ws6mbtVqDPTryLUM5D h+UHJyQZRb5uI8cc/l9H2JGbhK1GoeI0vpPj+MBVHuDIIwlZIH6KjXAx tp2V8Wrq6Po4Gr3ZQrRCRKdR7kDiUbUzSRSZ1wVBpWFDvHPUQd5Vli2m ntU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; delegation down
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.a.example.com. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+sub.a.example.com. 3600 IN DS 32886 7 1 05B70AC8C521B130A865EDE411A06135C5BC49E2
+sub.a.example.com. 3600 IN RRSIG DS 7 4 3600 20181230101845 20181130101845 33632 example.com. YX6ThbV357iGXSf8J/D67wCUf6YQWO3cQnrX46Ws6mbtVqDPTryLUM5D h+UHJyQZRb5uI8cc/l9H2JGbhK1GoeI0vpPj+MBVHuDIIwlZIH6KjXAx tp2V8Wrq6Po4Gr3ZQrRCRKdR7kDiUbUzSRSZ1wVBpWFDvHPUQd5Vli2m ntU=
+sub.a.example.com. IN NS ns.sub.a.example.com.
+SECTION ADDITIONAL
+ns.sub.a.example.com. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.sub.a.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+
+; DNSKEY query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.a.example.com. IN DNSKEY
+SECTION ANSWER
+sub.a.example.com. 3600 IN DNSKEY 257 3 7 AwEAAbNmn9l9d8I1+gHbWag6QBE0tXQs7mZL+H3jB8qWaQRa5cYgFAah aQ/93LsJZK1i5Bk6dkmUcVxuKlTwP3nHp1HBoG66A8DdRmUfqWQy1hZ4 oMGcnoqXCy8+8q61JPhtpYQoiHR/Jwy7+RjrVtUr2LCwtO2S8r//YJZF D4R6KdtH ;{id = 57024 (ksk), size = 1024b}
+sub.a.example.com. 3600 IN RRSIG DNSKEY 7 4 3600 20181230101844 20181130101844 32886 sub.a.example.com. k/zVTR2I9Xg8tIksStQ2JJDQuPjA3RFuYUbJ8nyzLtIL+Hpn2Sv4G2zl NuHSWGcuSZPe6fNzBHEg6faRLCgtfHxPLcgt+OSA6KSOj7iUjcaB8ap9 cKgemoj/njtcj/vDj0KoJWI0MHCDu5jAK1ZYsYouB3hTWBX0wFN/Mj2j H34=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.a.example.com. IN A
+SECTION ANSWER
+www.sub.a.example.com. IN A 10.20.30.40
+www.sub.a.example.com. 3600 IN RRSIG A 7 5 3600 20181230101844 20181130101844 32886 sub.a.example.com. Brrsf7sDDtwR/oga9dwwIAAMjQrfVxNdpnrj1N/KNafuCm7/YIEjoLXp ftRwHF7j083djazS2ud2vTckxo1GKXbPIs4/G0ACwu6bCwuL9BimGnhj 0fdLE6WzALExHwVu/HTR0d0JvitdnmwuIZLtJXbAA04jO3wYtZx3Dler YDU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+zzz.example.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.net. IN SOA root. host. 1 2 3 4 5
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.a.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.a.example.com. IN A
+SECTION ANSWER
+www.sub.a.example.com. 3600 IN A 10.20.30.40
+www.sub.a.example.com. 3600 IN RRSIG A 7 5 3600 20181230101844 20181130101844 32886 sub.a.example.com. Brrsf7sDDtwR/oga9dwwIAAMjQrfVxNdpnrj1N/KNafuCm7/YIEjoLXp ftRwHF7j083djazS2ud2vTckxo1GKXbPIs4/G0ACwu6bCwuL9BimGnhj 0fdLE6WzALExHwVu/HTR0d0JvitdnmwuIZLtJXbAA04jO3wYtZx3Dler YDU=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_faildnskey.rpl b/tests/deckard/sets/resolver/val_faildnskey.rpl
new file mode 100644
index 0000000..7d090c7
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_faildnskey.rpl
@@ -0,0 +1,171 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+ # test that default value of harden-dnssec-stripped is still yes.
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with failed DNSKEY request
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+;REPLY QR AA NOERROR
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+;example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_mal_wc.rpl b/tests/deckard/sets/resolver/val_mal_wc.rpl
new file mode 100644
index 0000000..f03ced0
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_mal_wc.rpl
@@ -0,0 +1,151 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 16907 7 1 15491CE8EE9AC1D17E48D226C0460219546181CD "
+val-override-date: "20181130121851"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nodata, wildcards and ENT
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+b.example.com. IN DS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+b.example.com. IN DS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101851 20181130101851 16907 example.com. KXsKhCme80OQl4qekE+q0KvymkhEelk+OdOsajCsGmfG5eeCEkN58gVw 5fBgtR2Ekp15KLsV1elsyVL8i7W5Hp5f2G70/plqSQ+78n3Al5jXONgN oVFSOuf8N179F2uf3k20MpnlxQQ7W/VX6SpuAOejyVpp6il6dm2YwRHH nX4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101851 20181130101851 16907 example.com. KqDPciNi+sv+8MOP2P0C3qWpFCHjw8eu213ztGMvVDZsEvJLz9QRXkgI XuwhZIEUiKaV9C7jG+aMyOc1amX0Uo8kp+UXuL5k43gjSi0PbhO72aTG QSOZV4S1/Pa/ZN/phWItlN18HGWqBQvx26K16AzziwQvVuL7nUmu/KUj MIY= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAef0Gt81KzrbFGbFmk6VeEzLLcRbnKiDjdMBO7R+HsQWCO9YpPGx 20mBEV7ISCLva+LZulf584i30ga7qMeVsarsdh9xCYtyMXd4Ex5nMEXx V9f2Or+FjihPduL2TnAlWpvL8oc1oKVI2RISTT1yf8IYy6X/FpfmMP81 9WBN2Kit ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101851 20181130101851 16907 example.com. RPXAcaVjBdtk/geHTdTg9ZOKREpAdjZAopRE/5Kk9fdFYQWwg0uRxexL PJ11jXjnp9MKOp1FehctyvE/mm1lB/J6+YepHu3tRAzzJ9YfjVxJjUpp Qv/nA/fU55MHWYhdhXwKn7F+PXD8+MFlAqPyFz9mYZEO89lI4P2/Wf4x pv4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101851 20181130101851 16907 example.com. KXsKhCme80OQl4qekE+q0KvymkhEelk+OdOsajCsGmfG5eeCEkN58gVw 5fBgtR2Ekp15KLsV1elsyVL8i7W5Hp5f2G70/plqSQ+78n3Al5jXONgN oVFSOuf8N179F2uf3k20MpnlxQQ7W/VX6SpuAOejyVpp6il6dm2YwRHH nX4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101851 20181130101851 16907 example.com. KqDPciNi+sv+8MOP2P0C3qWpFCHjw8eu213ztGMvVDZsEvJLz9QRXkgI XuwhZIEUiKaV9C7jG+aMyOc1amX0Uo8kp+UXuL5k43gjSi0PbhO72aTG QSOZV4S1/Pa/ZN/phWItlN18HGWqBQvx26K16AzziwQvVuL7nUmu/KUj MIY= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 86394 IN SOA NS.IANA.ORG. NSTLD.IANA.ORG. 2007092000 1800 900 604800 86400
+example.com. 86394 IN RRSIG SOA 7 2 86394 20181230101851 20181130101851 16907 example.com. uQjgfvlcxQLPfqetqWjTgKTbDOK3BoqbdmrqudrEl/X/S3OR8uhTQu7P EsrJm7IP7lmKcsbF4LAFjBNRp28G4at8v5cnCpvZfKFDzO3JzCubaVnn 18rSZj9gM1e4CN5ms/aAlr5I2hDhIQnsKmhxQBTrngyTcpGgf/YQuruM RKw= ;{id = 2854}
+
+; note that b.example.com. is an empty nonterminal
+*.example.com. 3600 IN NSEC *.b.example.com. A MX RRSIG NSEC
+*.example.com. 3600 IN RRSIG NSEC 7 2 86400 20181230101851 20181130101851 16907 example.com. 5NyjMTv7p0jvYrfxQzTJXvTlf1Uy2tMSmYKEWZoBq87u6mLNBtRgpKl9 1gpVvT8o+uA2XAznujnFZYgLdE9Swk87KqQQSWkyM81458SuSVwB5hma 9afCrB38FH9D9aOCN1nfqIuoEsQi3Bu3Uvtr+eV7oE97ViROSy/1pyyK g9A= ;{id = 2854}
+
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+b.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+b.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 86394 IN SOA NS.IANA.ORG. NSTLD.IANA.ORG. 2007092000 1800 900 604800 86400
+example.com. 86394 IN RRSIG SOA 7 2 86394 20181230101851 20181130101851 16907 example.com. uQjgfvlcxQLPfqetqWjTgKTbDOK3BoqbdmrqudrEl/X/S3OR8uhTQu7P EsrJm7IP7lmKcsbF4LAFjBNRp28G4at8v5cnCpvZfKFDzO3JzCubaVnn 18rSZj9gM1e4CN5ms/aAlr5I2hDhIQnsKmhxQBTrngyTcpGgf/YQuruM RKw= ;{id = 2854}
+*.example.com. 3600 IN NSEC *.b.example.com. A MX RRSIG NSEC
+*.example.com. 3600 IN RRSIG NSEC 7 2 86400 20181230101851 20181130101851 16907 example.com. 5NyjMTv7p0jvYrfxQzTJXvTlf1Uy2tMSmYKEWZoBq87u6mLNBtRgpKl9 1gpVvT8o+uA2XAznujnFZYgLdE9Swk87KqQQSWkyM81458SuSVwB5hma 9afCrB38FH9D9aOCN1nfqIuoEsQi3Bu3Uvtr+eV7oE97ViROSy/1pyyK g9A= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_anotherdomainsignature.rpl b/tests/deckard/sets/resolver/val_minimal_anotherdomainsignature.rpl
new file mode 100644
index 0000000..a1cb63e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_anotherdomainsignature.rpl
@@ -0,0 +1,99 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Signature belongs to another domain.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+x.root-servers.net. IN A
+SECTION ANSWER
+x.root-servers.net. 3600000 IN A 193.0.14.129
+x.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ ; valid signature of k.root-servers.net IN A
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+x.root-servers.net IN A
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+x.root-servers.net IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_anotherrrtypesignature.rpl b/tests/deckard/sets/resolver/val_minimal_anotherrrtypesignature.rpl
new file mode 100644
index 0000000..562987a
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_anotherrrtypesignature.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Signature belongs to another RR type of the domain.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ== ; valid signature of k.root-servers.net IN AAAA
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+k.root-servers.net IN A
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+k.root-servers.net IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddnskeyalgorithm.rpl b/tests/deckard/sets/resolver/val_minimal_baddnskeyalgorithm.rpl
new file mode 100644
index 0000000..089db88
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddnskeyalgorithm.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed DNSKEY algorithm.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 7 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc= ; algorithm changed from 8 to 7
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddnskeyflags.rpl b/tests/deckard/sets/resolver/val_minimal_baddnskeyflags.rpl
new file mode 100644
index 0000000..3f8e48d
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddnskeyflags.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed DNSKEY flags.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 254 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc= ; flags changed from 256 to 254
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddnskeyprotocol.rpl b/tests/deckard/sets/resolver/val_minimal_baddnskeyprotocol.rpl
new file mode 100644
index 0000000..9a6d65b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddnskeyprotocol.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed DNSKEY protocol.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 2 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc= ; protocol changed from 3 to 2
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddsalgorithm.rpl b/tests/deckard/sets/resolver/val_minimal_baddsalgorithm.rpl
new file mode 100644
index 0000000..83fe386
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddsalgorithm.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 7 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F" # algorithm changed from 8 to 7
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed algorithm of trust anchor.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddsdigest.rpl b/tests/deckard/sets/resolver/val_minimal_baddsdigest.rpl
new file mode 100644
index 0000000..e365d21
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddsdigest.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 8 2 A7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F" # digest changed
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed digest of trust anchor.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddsdigesttype.rpl b/tests/deckard/sets/resolver/val_minimal_baddsdigesttype.rpl
new file mode 100644
index 0000000..5f2401e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddsdigesttype.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 8 1 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F" # digest type changed from 2 to 1
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed digest type of trust anchor.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_baddskeytag.rpl b/tests/deckard/sets/resolver/val_minimal_baddskeytag.rpl
new file mode 100644
index 0000000..50ae41a
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_baddskeytag.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49061 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F" # key tag changed from 49060 to 49061
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Chnged key tag of trust anchor.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badpublickey.rpl b/tests/deckard/sets/resolver/val_minimal_badpublickey.rpl
new file mode 100644
index 0000000..dfca431
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badpublickey.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed public key.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 BwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc= ; changed public key
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsigalgorithm.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsigalgorithm.rpl
new file mode 100644
index 0000000..7e562ce
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsigalgorithm.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG algorithm.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 7 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; algorithm changed from 8 to 7
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsigexpiration.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsigexpiration.rpl
new file mode 100644
index 0000000..771c818
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsigexpiration.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG expiration.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093828 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; expiration changed from 20170409093827 to 20170409093828
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsiginception.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsiginception.rpl
new file mode 100644
index 0000000..ad8e739
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsiginception.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG inception.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093828 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; inception changed from 20170310093827 to 20170310093828
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsiglabels.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsiglabels.rpl
new file mode 100644
index 0000000..af15124
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsiglabels.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG labels.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 1 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; labels changed from 0 to 1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsigsignature.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsigsignature.rpl
new file mode 100644
index 0000000..61c5e16
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsigsignature.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG signature.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . ABuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; changed signature
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsigtag.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsigtag.rpl
new file mode 100644
index 0000000..e587c2c
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsigtag.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG tag.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20662 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; tag changed from 20661 to 20662
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_badrrsigttl.rpl b/tests/deckard/sets/resolver/val_minimal_badrrsigttl.rpl
new file mode 100644
index 0000000..ac39109
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_badrrsigttl.rpl
@@ -0,0 +1,88 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Changed RRSIG original TTL.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518401 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ== ; original TTL changed from 518400 to 518401
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_beforeinception.rpl b/tests/deckard/sets/resolver/val_minimal_beforeinception.rpl
new file mode 100644
index 0000000..04820aa
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_beforeinception.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170308000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Date after expiration of signatures.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_expiredsignature.rpl b/tests/deckard/sets/resolver/val_minimal_expiredsignature.rpl
new file mode 100644
index 0000000..b271518
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_expiredsignature.rpl
@@ -0,0 +1,87 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170410000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Date after expiration of signatures.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_minimal_noerror.rpl b/tests/deckard/sets/resolver/val_minimal_noerror.rpl
new file mode 100644
index 0000000..193d3ca
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_minimal_noerror.rpl
@@ -0,0 +1,89 @@
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170401000000"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Right signed zone.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ ADDRESS 2001:7fd::1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170409093827 20170310093827 49060 . G7s3QiWNgOsl+LoG6OKjdBHPcFyhmCS17GFnaKjfJNdPQaFL5nM/vrXo eUIIdJXAvjj62TY7wTyFlnx3yjK93RVGKEEySpGC/1gkn5AdjVoQszog IxYjKzubizULSaX7SQ3/Ar+uHLxakdS1qgNdFu6hHCl857LJPtmC8SJt iFUmm5HFyARokMrfA88VrFRKEqojcCWajeZMfRtgBipFJZoYgPUCaFlz 8OupNdNUWCbGhnDWrXCWMzeKVXTQVlJf75PXXgtkuBUmr5RSWu7AYr+c wTJ4E4610goRqYxnZ33efKE/MuhKeY66xelPh0sirPrBMR5JAlyjV3k1 qDzhcQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+k.root-servers.net. 2592000 IN RRSIG AAAA 8 3 3600000 20170409093827 20170310093827 20661 . qjVXwuxzmoRhdrXyQvKfrrzFxGiYuTTJHxwZPasJ1nVmN48dPyU6wA55 JeqoJv1Jm+XvIL1q0WtX6Zh6KLt6vVjHuMkhmFuIZYkFi/dmsEwFY8C0 ebyXyztQT5+6FOSVTAKacYc40LfBo8FqEn8RYlCu1mkAd8ANvvLrdLWW W03LVOY7JlCzyrKlAlmPmuV8z+e9PxNkUh6KfTEvAReoAAX7wYZkdefg 2d64c7rNWXvYm6LxBX6qeQ39d5WyKc8v+G01DJuDzs2Tx368QoK86vm/ qo9ERdT7koRt+gBZNYv8V4fh2SjaFsy2TJq/tiYcSia9snGDTFj6LWVM 6sBCYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170409093827 20170310093827 20661 . feIXXjskcsyH+ALZu67GVDaPWXjUGTWsTlDwzgJcLBzSuRVY/GVD5Z1Q B4/oUW99rLKB5bNS1MuasZ+nZFV67sBwJk1+SqNB2bAe7G5Tv1sR2Qgi qDAoB37YDVk5JGHfuxByLYbAVG9PrPXT60BN17OYrD/TFPzprye65gk3 7l9kPpAlblcsqdvh5piKrWc7VBcyMhlp56qdASNAl+Lrb+i0DZYyJXh+ b8LV5g5zp9FaVGKe0Gi4+yDXVjcM6VEtuNRAu2+flLoc3ho6qQF1Po4Y wueL72I+yFoUxkIOJvK47eWb+YUBIBK/L8/ORjYoLBRsrbc79wb0I3Zj Xy6O4Q==
+ENTRY_END
+
+; QTYPE == RRSIG is not supported, https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any-04#section-7
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+. IN NS
+ENTRY_END
+
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170409093827 20170310093827 20661 . uBuJpbRh1NYVciSKK0r3SA6NFnqE4s/+CqLfTXu26/HrY5c1aOhQHXZM cCDDjfPGFa7Eh4mqF0i9I+i+bFbYQitI1Heexye599VE19REbVsK4qaU xkArvt9k6HVqd/7BXXUyzLN1N0CScdyuT5tiEI9154SDNVpnC+z8i2u0 9hW8JEk4qqVWX/I1MYQB/UOcFSeDhD1Qku/26opqDuLl/1eaShxhMQ/c rjzOb5ZYzD0x+TUJZMYSOMwAraaFuYTT84oe6QYY+EGctAk1b50nA/5E C3Tm/xGuo9ioVtYhTwoo1XDUVeHmghdILjQZvR4pOSZoRGGP9ovb08Qg OmPXuQ==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_negcache_ds.rpl b/tests/deckard/sets/resolver/val_negcache_ds.rpl
new file mode 100644
index 0000000..7aedd46
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_negcache_ds.rpl
@@ -0,0 +1,215 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 41069 7 1 2003A31BABD184BB6DB61EE19E99D1E5D2438043 "
+val-override-date: "20181130121852"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with negative cache DS response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101851 20181130101851 41069 example.com. nJ/h5Gx/vjvbFWq49FnmgYc4SdelzNqF67pN5NbGXkH80uKPdGAj5Lue 9WQb/mCExxU7LjjIZjjAnAmIKKHyK8xLY27W7eRVR9YkmQVt0XWNN1eL 1QUjURFxIFhzpadH9ympDvgS1B8siYu+vdLR1Guxip4+JgYfYFBInZG/ cPA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101851 20181130101851 41069 example.com. azi1io9bz4KCJ+6AF17yTFwjaGM6mnU9bdR91pD6lrYxMjBPERzBsUIo 5KlAxZD0PBH5/FQviucA33GVAuP3iYc9954yVF7GyjzUy4ZYgQAGb6W8 ddF8aHdi4qV4FJczROo+RDUqmsDV+KAvdGssLN2rN6zL+3yOEbwfKpjc NEk= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdbidAf3mIouRWd2XVH6Z5t+ZGClkU6bv0oAZO8Hmv5PlG8Wve8v q40Pa4F5dtODadwB3ap9Z5ELJGDJDAGCgpiOXy34xtquF0VKCBezCdyA X3fWni7EQIqV79G1T3J4cM6WXvbz6T0lJa42Um/YkjTixBnYbj/4Tsgf Szx/k/XL ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101851 20181130101851 41069 example.com. jI52HJoPTs1of36Q+d9zpdu9B0iaKd+IQtIkmW6VIliOwX0+6O47sHcf mhz8Htny/B16C2nsBnB3yoOM/j27MRLW1RNmb/TqF2QVIsn+5DnP+UMp 7sZ/3BG0Gdjg8QzY7bFGmsalAVk/BjWmVEXTeAlJRaGUsa2gWQk/6lTG nT4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101851 20181130101851 41069 example.com. nJ/h5Gx/vjvbFWq49FnmgYc4SdelzNqF67pN5NbGXkH80uKPdGAj5Lue 9WQb/mCExxU7LjjIZjjAnAmIKKHyK8xLY27W7eRVR9YkmQVt0XWNN1eL 1QUjURFxIFhzpadH9ympDvgS1B8siYu+vdLR1Guxip4+JgYfYFBInZG/ cPA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101851 20181130101851 41069 example.com. azi1io9bz4KCJ+6AF17yTFwjaGM6mnU9bdR91pD6lrYxMjBPERzBsUIo 5KlAxZD0PBH5/FQviucA33GVAuP3iYc9954yVF7GyjzUy4ZYgQAGb6W8 ddF8aHdi4qV4FJczROo+RDUqmsDV+KAvdGssLN2rN6zL+3yOEbwfKpjc NEk= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101851 20181130101851 41069 example.com. zirafH0rQfSxurfz8wUi/N6vgt5BR6ll2oAb+mFE6PgAU+9R1WharUpV JsfI2StXTg6uD/TMYDU02OxQFu44OaZMb6GUZBr7AUAE0fVsUDJAdOgn QdnNajsOZXi5rq6uEcnMdmyUVmNvtcc+yfG26aC/CiJ1dpXoglxM89TO FOw= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; query for missing DS record.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101851 20181130101851 41069 example.com. sq8e1vA5GgxT0z5+ubqTW8IjWJEvwJ0vlHXALLeSYHng7oVQ6mr+soTr vxov5kAockUaJ/rFJpBkcx0q2o5Z6RSsWl6OPxdURRe2IAQlyyX7xpcV 5RVHPoCL5PvA8HMFL94TigKTRoDIOkWnbVDJ0Ju3GwurpbrXP6E6KjzG Xus= ;{id = 2854}
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101851 20181130101851 41069 example.com. zirafH0rQfSxurfz8wUi/N6vgt5BR6ll2oAb+mFE6PgAU+9R1WharUpV JsfI2StXTg6uD/TMYDU02OxQFu44OaZMb6GUZBr7AUAE0fVsUDJAdOgn QdnNajsOZXi5rq6uEcnMdmyUVmNvtcc+yfG26aC/CiJ1dpXoglxM89TO FOw= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; the downstream validator wants the DS record.
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101851 20181130101851 41069 example.com. sq8e1vA5GgxT0z5+ubqTW8IjWJEvwJ0vlHXALLeSYHng7oVQ6mr+soTr vxov5kAockUaJ/rFJpBkcx0q2o5Z6RSsWl6OPxdURRe2IAQlyyX7xpcV 5RVHPoCL5PvA8HMFL94TigKTRoDIOkWnbVDJ0Ju3GwurpbrXP6E6KjzG Xus= ;{id = 2854}
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101851 20181130101851 41069 example.com. zirafH0rQfSxurfz8wUi/N6vgt5BR6ll2oAb+mFE6PgAU+9R1WharUpV JsfI2StXTg6uD/TMYDU02OxQFu44OaZMb6GUZBr7AUAE0fVsUDJAdOgn QdnNajsOZXi5rq6uEcnMdmyUVmNvtcc+yfG26aC/CiJ1dpXoglxM89TO FOw= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_noadwhennodo.rpl b/tests/deckard/sets/resolver/val_noadwhennodo.rpl
new file mode 100644
index 0000000..e8ef634
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_noadwhennodo.rpl
@@ -0,0 +1,151 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 5513 7 1 A82FBB092D154DB2AC65B85480D5D7722589FE65 "
+val-override-date: "20181130100653"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test if AD bit is returned on non-DO query.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230080653 20181130080653 5513 example.com. E31KJFA+CenP19oImp7zKXfMcxyoOmUyPTrE81u3qDB0wu8FgNft/Qs6 FQTG5gWDpg8i2E9BB7CbVKx/Dt5RNa7yehtc4MOEhKOMvvH48p0TdkgO sWrUr+Z5wkzst2Hrb4TN6IEM5QqXXs3GApbFsG0vXGMs1aH9+Yo6KZ7H bMA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230080653 20181130080653 5513 example.com. m42szfJDR/duAI+0VQm2okWxeaVRzSsnWztVF1lHuiZZfljYKFzZEdEp DDSpXbjtq7cobcO/9+ZQhLPrmLhhx2sj96wE06Gd3smqzykaH7PJ5Q63 vkLubkRkJ1X8j+tdykGELk2RUxfzoB5qdf34PY6aIdhX/VVTx8n051cu T+U= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcZSP3HQqzpGyFkoyriJHSRJlS8JDx3TsrnFRhbsM/Wy/gp9ubgz BPum/s/4Plb+wGz1ndpcpuhwqNahL2VGleJgEQrkeIqjj1K4lYvPSmr4 yfTcfD5O/zpzqCxrCIjWEa6/Vg7ldNA05KoV0ptx5rVXhox/Fo3BEGaq i5fVjbDf ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230080653 20181130080653 5513 example.com. fKyryysxkfOMonchYec/4g2y3qtsf6O6ilnBVcBX4f0WAvNtib/eZrTm retDviutAXM2E44rvTpitvBXMOXQ2jz4EV7/m6ZuIkdoOJ3GLk0W08wn 3TPR36VK5160sOxOH9KgWjvrfi4F24qxV30cNqOJYSXUG0nHosuKoEYx Hsg= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230080653 20181130080653 5513 example.com. E31KJFA+CenP19oImp7zKXfMcxyoOmUyPTrE81u3qDB0wu8FgNft/Qs6 FQTG5gWDpg8i2E9BB7CbVKx/Dt5RNa7yehtc4MOEhKOMvvH48p0TdkgO sWrUr+Z5wkzst2Hrb4TN6IEM5QqXXs3GApbFsG0vXGMs1aH9+Yo6KZ7H bMA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230080653 20181130080653 5513 example.com. m42szfJDR/duAI+0VQm2okWxeaVRzSsnWztVF1lHuiZZfljYKFzZEdEp DDSpXbjtq7cobcO/9+ZQhLPrmLhhx2sj96wE06Gd3smqzykaH7PJ5Q63 vkLubkRkJ1X8j+tdykGELk2RUxfzoB5qdf34PY6aIdhX/VVTx8n051cu T+U= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230080653 20181130080653 5513 example.com. S4vtvQL7JD5LDzhFuXU7xlUbr7COF3JxT5XA1kzHJRLPKQEnvTl7+Z2K bgDYOf4TC2Li+W9ptnmodVaidLvNBwiA9d/MPVJ4QQmJK6TlaLuyL0du 079NyGnSiSz5CZvVZ61Vjrt7XgpSyLiJHdq3gR0YAZ6i7ouPu8px7vgW iJQ= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230080653 20181130080653 5513 example.com. E31KJFA+CenP19oImp7zKXfMcxyoOmUyPTrE81u3qDB0wu8FgNft/Qs6 FQTG5gWDpg8i2E9BB7CbVKx/Dt5RNa7yehtc4MOEhKOMvvH48p0TdkgO sWrUr+Z5wkzst2Hrb4TN6IEM5QqXXs3GApbFsG0vXGMs1aH9+Yo6KZ7H bMA= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230080653 20181130080653 5513 example.com. m42szfJDR/duAI+0VQm2okWxeaVRzSsnWztVF1lHuiZZfljYKFzZEdEp DDSpXbjtq7cobcO/9+ZQhLPrmLhhx2sj96wE06Gd3smqzykaH7PJ5Q63 vkLubkRkJ1X8j+tdykGELk2RUxfzoB5qdf34PY6aIdhX/VVTx8n051cu T+U= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+; it is validated, but no AD bit, because no AD was requested.
+; (this is a copy of val_positive.rpl).
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nodata_hasdata.rpl b/tests/deckard/sets/resolver/val_nodata_hasdata.rpl
new file mode 100644
index 0000000..178dfea
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nodata_hasdata.rpl
@@ -0,0 +1,163 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 56837 7 1 FBEED5DCAEAE367243C36AEB8251D00C0088872A "
+val-override-date: "20181130121856"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nodata response, that proves the data.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101855 20181130101855 56837 example.com. y/lP3Ognxh+WgcwtSqo0bLUWeko1sjpCXylRLERxsTSyVSK5L8yenuB2 94iqM8fVlk7SpDg1BiuNuAPsinDMgjR8726ECJMMgSxXohiZgQSUfwQi NYxDmTq9qN/JfCrJUsdYpH387vSkjGuvvNic9k70FzDhPfI4YAjf4ZbJ E0c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101855 20181130101855 56837 example.com. AtisROBfgsg6OEetN69p9eEAQSKwovhdbOv3lZ8dq4cHryLDO4q4O2aF +h3cSpLpOO6wti94eqTbpB6HZ7eIEYqHEQKSYEGL59HuVf4N0nyTp8lN 3UAZT7DtsmDdt0NyUExh1tuHvFwYvtX3vCyvJs3F1MGCTySSK6wALmHm TLs= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdIzTUQVujDsSlkC61+pWGNqk3O6YIoP6XbaGwwKTUHx7yXf95gb 93UNAJFLt/G6ORySmAYfW/l3EYvKMX4x2YnaQeq+xXUguPq4nMMxfwyd xYubOaRd5DgETj1BEug2OV/z5PbaSuWiCqxQCJ4x9wuA04388n6r+/WR dz9uPVyl ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101855 20181130101855 56837 example.com. SsiDl8A1jtsqhA0v/wL5Hes0qRR8//xhIMPrQuBHJVSTRg5dq4EJYjIF 3rtJ+YwlLW/bfDg19sXLj/67/resY106RtI7zFdoQFoWXCkui9o+ZPJF UM+FHgjnFt4OOwNpQpJuhXeUGj6NDIgpsJhYDH8BaESNGcb0eN7bfYaH d/E= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101855 20181130101855 56837 example.com. y/lP3Ognxh+WgcwtSqo0bLUWeko1sjpCXylRLERxsTSyVSK5L8yenuB2 94iqM8fVlk7SpDg1BiuNuAPsinDMgjR8726ECJMMgSxXohiZgQSUfwQi NYxDmTq9qN/JfCrJUsdYpH387vSkjGuvvNic9k70FzDhPfI4YAjf4ZbJ E0c= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101855 20181130101855 56837 example.com. AtisROBfgsg6OEetN69p9eEAQSKwovhdbOv3lZ8dq4cHryLDO4q4O2aF +h3cSpLpOO6wti94eqTbpB6HZ7eIEYqHEQKSYEGL59HuVf4N0nyTp8lN 3UAZT7DtsmDdt0NyUExh1tuHvFwYvtX3vCyvJs3F1MGCTySSK6wALmHm TLs= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; SOA record is missing in reply.
+; Denies A, note this is the end of the NSEC chain.
+www.example.com. IN NSEC example.com. A RRSIG NSEC
+www.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101855 20181130101855 56837 example.com. NgtD5aVHLUHE1yGKHrarb7A1P5sqfwdgUjxBCEn8BwX7FW9h9QiVZs9+ jCVF7hT+wPs2PRqy5T/a5OjwZZJRtabxN6b3d6J7FSppTWTxP/8sjAf6 1c1TRf7aq4alJ8gAk/p9Yk8AsylIw15kMWjnOeiFCCKKYRHzfJi7wnAR efI= ;{id = 2854}
+; Denies wildcard
+example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY
+example.com. 3600 IN RRSIG NSEC 7 2 3600 20181230101855 20181130101855 56837 example.com. nIcNEt/oTPiVa0mopVp5BXGVnCxn3hmv233yJ0oQCRkpZV0PKVCp6p+S GyMuh+osAYNT+duVa3zs8o6pyrZjQLAZJMEeOMBoAQP33iNu4axkYGio IkW/wdabOdBAFGgtApcjUh8rk9FCNAu0Rp+knqhq9BHV89aRROqGzdkd kp0= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nodata_zonecut.rpl b/tests/deckard/sets/resolver/val_nodata_zonecut.rpl
new file mode 100644
index 0000000..132ccf8
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nodata_zonecut.rpl
@@ -0,0 +1,161 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 7508 7 1 74F83028EFB9ADE1737F8D4ABC38B6B24B820FEA "
+val-override-date: "20181130121859"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nodata response from wrong side of zonecut
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101859 20181130101859 7508 example.com. LtglVhv8M0yIXb/0El6Zuq5YlKzOiI4ELiK9UE7MgTr2taXCWzC1tng6 a5UqZXWwrxd0a8vaVy6ZcAPQkY6HeZ/IAO9ej3L+EzKyLlEJxnYXkNXb InMHUcUk99jZ1edOvaVPtaDqWdm8iuGcm5mHHpTopf7lG9L6SwdPxX6h 9DE= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101859 20181130101859 7508 example.com. yQB0cOEETYV1iE6sDl3zwJX+aqZFyzomqn0Y+KLfMgBmKZmwQWx5tA0w 3KTT3EmuW0X1TAY0gK4NiJ9DAIs0Lx8CYKEtDXa8bIQ/pelMIwZFAI7c Xj2dapGiAJXK5GDakoIeSna26Uoxebuji1ON1DbWbGno7Nl+SrGDvwsX WRY= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAeKwMBC0t6W4iXUPMRDrAn6oLaKcQQxzs7kU6eSabnPSrKiK1866 PzscrkXkkPIGNW1DXMexV+b39NavDoXzAaG3sCsQToq8ZVA/VKz6BQ5h Qy8CzzJ/fbg7eQmujS1bh0TATkKEtgVYmlfooSWniQ9wAaId/jLbeF6q C6g1nuWt ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101859 20181130101859 7508 example.com. yDhUfBwaWgV/QKLUEQ8B7ZeE/81qSJoo0mFD2zs/0PJnQey/Bi2vNZDv 7W3nIkzHtNRC3D9brV1YXi+NbfCID7nNyU90/4Js1VQAbGzxGuv9dlvx GjHfniS8UIdu8R3iqV2URi1Ux/YMFfEv2VfUInOh6hfB9nwhDKetsbAs kwc= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101859 20181130101859 7508 example.com. LtglVhv8M0yIXb/0El6Zuq5YlKzOiI4ELiK9UE7MgTr2taXCWzC1tng6 a5UqZXWwrxd0a8vaVy6ZcAPQkY6HeZ/IAO9ej3L+EzKyLlEJxnYXkNXb InMHUcUk99jZ1edOvaVPtaDqWdm8iuGcm5mHHpTopf7lG9L6SwdPxX6h 9DE= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101859 20181130101859 7508 example.com. yQB0cOEETYV1iE6sDl3zwJX+aqZFyzomqn0Y+KLfMgBmKZmwQWx5tA0w 3KTT3EmuW0X1TAY0gK4NiJ9DAIs0Lx8CYKEtDXa8bIQ/pelMIwZFAI7c Xj2dapGiAJXK5GDakoIeSna26Uoxebuji1ON1DbWbGno7Nl+SrGDvwsX WRY= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; SOA record is missing in reply.
+; Denies A, note this is the end of the NSEC chain.
+; from wrong side of zone-cut
+www.example.com. 3600 IN NSEC example.com. NS DS RRSIG NSEC
+www.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101859 20181130101859 7508 example.com. pZVPW2nRsyzqbXJ0ulwP3mS+F6s2IT87uIdfZXAYvKc4mxfVN4fVIV4d 38i2/19vWBf0JbMumZTDunzpL5+8T4ydH6AVv2UYcQh154JHi1q3Ec4G 0VTQa5bl8+fvS3rY5jmn/Pj6nqNWkYdnZPEelzzz0cLHJLdfI279a7n0 T00= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nodatawc_badce.rpl b/tests/deckard/sets/resolver/val_nodatawc_badce.rpl
new file mode 100644
index 0000000..101b6f2
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nodatawc_badce.rpl
@@ -0,0 +1,163 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 65510 7 1 562BB481B567CC7A69CA48A9020450D3EA52B6BC "
+val-override-date: "20181130121857"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with wildcard nodata, bad closest encloser
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101857 20181130101857 65510 example.com. zBeDPiE4zoUW4DnyrOXKvEKUaouz2xpD9UGCkQ2iDeNl+2ASPv9fyxY9 ChpOOcgOsM6PEonEwm013L0oPK19WOAduuZw+9IgPFFxXlo5Sq80vdtM OEKqhvy4dId/aeF+hWcFm1ug9+4f56eBP0MyeohXpm46b0qaK7756B6i pyg= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101857 20181130101857 65510 example.com. sQPchlz34VJeeRFowgrOAWcfNGuSXSzeuH2/wZ/1qFdYF6m8uf8Xl/Vy ThP1axfBvk1pKItnZZR3bQd0gnCInnmNUt70vXg/w1AjrULNiMxqs0Mj fBPhFk3/9oK+KogQfLYS0SPESU+C3raPG8MnDe0uJ6sd5SDDp3w57qan J+Y= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdUDKuLOwzbmS7/7hQIK5FyLAu5XnovMNiBRfF8u8+W7RfQ+KutQ FlDcF2GSvLzi/oN70crUU45XslCGF5hHiTPu3x9tMpO75tvzZxvo8Zvm 6cTUqa+/94vco9THeTxy6LtY93Ay5h1Y6sqfUtTBUbU1b/O18EgM1XBu Z61vzdFn ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101857 20181130101857 65510 example.com. OGov/2XXr24GVeXbdT4WcHDiAV5mKmBFYlNWjwE+FOOI7LdL0DPg1CFD AnyW5Fadn9DCkDh+zLMeKQIVSFG4vkKzjqjIOxCxninPkpSA1S6caW5q i7Xlxtbqc9U3ZZB0A9uCWqYeVL1B+dRvm+rgOEvklA4FoW5QyCpL5U83 vL8= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101857 20181130101857 65510 example.com. zBeDPiE4zoUW4DnyrOXKvEKUaouz2xpD9UGCkQ2iDeNl+2ASPv9fyxY9 ChpOOcgOsM6PEonEwm013L0oPK19WOAduuZw+9IgPFFxXlo5Sq80vdtM OEKqhvy4dId/aeF+hWcFm1ug9+4f56eBP0MyeohXpm46b0qaK7756B6i pyg= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101857 20181130101857 65510 example.com. sQPchlz34VJeeRFowgrOAWcfNGuSXSzeuH2/wZ/1qFdYF6m8uf8Xl/Vy ThP1axfBvk1pKItnZZR3bQd0gnCInnmNUt70vXg/w1AjrULNiMxqs0Mj fBPhFk3/9oK+KogQfLYS0SPESU+C3raPG8MnDe0uJ6sd5SDDp3w57qan J+Y= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; SOA record is missing in reply.
+; wildcard is *.com,
+*.com. IN NSEC com. RRSIG NSEC
+*.com. 3600 IN RRSIG NSEC 7 1 3600 20181230101857 20181130101857 65510 example.com. VkoFvmky3udLkzvZPQ7Kgb8wgWKtyHJlL4j4aWmgxeGM3jgJn+LF21yZ EA4EnrlxbPwAjyNSjpPFEGfn9b/nFnxIELvaw4JEmVAC11fJcS6LOyjP W0TAtZfaugzN1N5IoTEKC5Jd5h3oBLj98jYDnUeCJ1Rs44bku85Xlwwq Vsw= ;{id = 2854}
+; this NSEC denies original query name from a different zone
+ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC
+ns.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101857 20181130101857 65510 example.com. IhNXLScxp0p14+47J2kp4g3Q4SziflqJaBn9cjIvjOO4pYlw6ZCd6bKK foP9Ye6IUriidmrAP45C50mqx3uIJsS5S+tuIk/gPFr8qcDbynLWUQj7 U7x3XQdztNTxqwAMse/84UGxPg5aCCAqrySFJ0qTz2mo0dihI5xgEpRi 70Q= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nokeyprime.rpl b/tests/deckard/sets/resolver/val_nokeyprime.rpl
new file mode 100644
index 0000000..25143e3
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nokeyprime.rpl
@@ -0,0 +1,164 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with failed key prime, no keys.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+; barely valid nodata for AAAA
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007101500 28800 7200 604800 18000
+SECTION ADDITIONAL
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b1_nameerror.rpl b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror.rpl
new file mode 100644
index 0000000..a043d52
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror.rpl
@@ -0,0 +1,161 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off ; RFC 5155 section B.1 does not contain information necessary to cover query-minimization
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.1 name error.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that covers the "next closer" name (c.x.w.example)
+;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh
+
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+;; NSEC3 RR that matches the closest encloser (x.w.example)
+;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+
+;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example)
+;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m
+
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.c.x.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+; no AD flag due to optout, RFC5155 9.2
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.c.x.w.example. IN A
+ENTRY_END
+
+;cached answer
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_noce.rpl b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_noce.rpl
new file mode 100644
index 0000000..857fae5
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_noce.rpl
@@ -0,0 +1,145 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.1 name error without ce NSEC3.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that covers the "next closer" name (c.x.w.example)
+;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh
+
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+;; NSEC3 RR that matches the closest encloser (x.w.example)
+;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+
+; b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+; b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+
+;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example)
+;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m
+
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.c.x.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nonc.rpl b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nonc.rpl
new file mode 100644
index 0000000..ae208a3
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nonc.rpl
@@ -0,0 +1,147 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm 3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.1 name error without nc NSEC3.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89ep O6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8 Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf 3bH+QsCtg== )
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd V I2LmKusbZsT0Q== )
+
+;; NSEC3 RR that covers the "next closer" name (c.x.w.example)
+;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh
+
+;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi 47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRx K9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+;; NSEC3 RR that matches the closest encloser (x.w.example)
+;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUi wtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+
+;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example)
+;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m
+
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH +z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.c.x.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nowc.rpl b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nowc.rpl
new file mode 100644
index 0000000..62ec31c
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b1_nameerror_nowc.rpl
@@ -0,0 +1,152 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.1 name error without wc NSEC3.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NXDOMAIN
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that covers the "next closer" name (c.x.w.example)
+;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh
+
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+;; NSEC3 RR that matches the closest encloser (x.w.example)
+;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+
+;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example)
+;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m
+
+
+;35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+;35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.c.x.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;do not compare authority
+;MATCH all
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+a.c.x.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+; example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+; b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+; b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== )
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b21_nodataent.rpl b/tests/deckard/sets/resolver/val_nsec3_b21_nodataent.rpl
new file mode 100644
index 0000000..4165c10
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b21_nodataent.rpl
@@ -0,0 +1,116 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.2.1 no data empty nonterminal.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+y.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the A type bit is not set.
+ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h )
+ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+y.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+y.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h )
+ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== )
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b21_nodataent_wr.rpl b/tests/deckard/sets/resolver/val_nsec3_b21_nodataent_wr.rpl
new file mode 100644
index 0000000..632d56d
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b21_nodataent_wr.rpl
@@ -0,0 +1,136 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.2.1 no data empty nonterminal, wrong rr.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+y.w.example. IN A
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the A type bit is not set.
+;ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h )
+;ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== )
+
+; instead the wrong NSEC3 rr is included
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+y.w.example. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+y.w.example. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_nsec3_b2_nodata.rpl b/tests/deckard/sets/resolver/val_nsec3_b2_nodata.rpl
new file mode 100644
index 0000000..d475d21
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b2_nodata.rpl
@@ -0,0 +1,117 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator NSEC3 B.2 no data.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns1.example. IN MX
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the MX type bit is not set.
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ns1.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+ns1.example. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== )
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b2_nodata_nons.rpl b/tests/deckard/sets/resolver/val_nsec3_b2_nodata_nons.rpl
new file mode 100644
index 0000000..b10ee1e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b2_nodata_nons.rpl
@@ -0,0 +1,142 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator NSEC3 B.2 no data, without NSEC3.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+; response to DS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns1.example. IN DS
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns1.example. IN MX
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the MX type bit is not set.
+;2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )
+;2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ns1.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+ns1.example. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b3_optout.rpl b/tests/deckard/sets/resolver/val_nsec3_b3_optout.rpl
new file mode 100644
index 0000000..46dba06
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b3_optout.rpl
@@ -0,0 +1,206 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.3 referral to optout unsigned zone.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR DO NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+c.example. IN DS
+SECTION AUTHORITY
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+ENTRY_END
+
+RANGE_END
+
+; ns1.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.7
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+; ns2.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b3_optout_negcache.rpl b/tests/deckard/sets/resolver/val_nsec3_b3_optout_negcache.rpl
new file mode 100644
index 0000000..0352419
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b3_optout_negcache.rpl
@@ -0,0 +1,209 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.3 referral optout with negative cache.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+
+ENTRY_END
+
+
+; DS must be gotten from neg cache
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR AA DO NOERROR
+; SECTION QUESTION
+; c.example. IN DS
+; SECTION AUTHORITY
+; ;; NSEC3 RR that covers the "next closer" name (c.example)
+; ;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+;
+; ;; NSEC3 RR that matches the closest encloser (example)
+; ;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+; ENTRY_END
+
+RANGE_END
+
+; ns1.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.7
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+; ns2.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b3_optout_noce.rpl b/tests/deckard/sets/resolver/val_nsec3_b3_optout_noce.rpl
new file mode 100644
index 0000000..d6be2cb
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b3_optout_noce.rpl
@@ -0,0 +1,255 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator NSEC3 B.3 optout unsigned, without ce.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+c.example. IN DS
+SECTION AUTHORITY
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+c.example. IN MX
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+
+ENTRY_END
+RANGE_END
+
+; ns1.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.7
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns1.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns2.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+; ns2.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns1.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns2.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b3_optout_nonc.rpl b/tests/deckard/sets/resolver/val_nsec3_b3_optout_nonc.rpl
new file mode 100644
index 0000000..43b0987
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b3_optout_nonc.rpl
@@ -0,0 +1,256 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator NSEC3 B.3 optout unsigned, without nc.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+c.example. IN DS
+SECTION AUTHORITY
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+;35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+;35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+c.example. IN MX
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+
+;; NSEC3 RR that covers the "next closer" name (c.example)
+;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== )
+
+;; NSEC3 RR that matches the closest encloser (example)
+;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== )
+
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+
+ENTRY_END
+
+RANGE_END
+
+; ns1.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.7
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns1.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns2.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+; ns2.c.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns1.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns2.c.example. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.example. IN NS
+SECTION ANSWER
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+mc.c.example. IN MX
+SECTION ANSWER
+mc.c.example. IN MX 50 mx.c.example.
+SECTION AUTHORITY
+c.example. NS ns1.c.example.
+c.example. NS ns2.c.example.
+SECTION ADDITIONAL
+ns1.c.example. A 192.0.2.7
+ns2.c.example. A 192.0.2.8
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mc.c.example. IN MX
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b4_wild.rpl b/tests/deckard/sets/resolver/val_nsec3_b4_wild.rpl
new file mode 100644
index 0000000..97e6e25
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b4_wild.rpl
@@ -0,0 +1,174 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.4 wildcard expansion.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN MX
+SECTION ANSWER
+a.z.w.example. MX 1 ai.example.
+a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== )
+SECTION AUTHORITY
+;; NSEC3 RR that covers the "next closer" name (z.w.example)
+;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+
+SECTION ADDITIONAL
+ai.example. A 192.0.2.9
+ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== )
+ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9
+ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== )
+ENTRY_END
+
+; catch glue queries
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN A
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN AAAA
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.z.w.example. IN MX
+ENTRY_END
+
+; recursion happens here.
+; answer has no AD since NSEC3 has optout
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN MX
+SECTION ANSWER
+a.z.w.example. MX 1 ai.example.
+a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== )
+; SECTION AUTHORITY
+; q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+; q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+; SECTION ADDITIONAL
+; ai.example. A 192.0.2.9
+; ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== )
+; ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9
+; ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== )
+ENTRY_END
+
+; check for cached answer
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.z.w.example. IN MX
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN MX
+SECTION ANSWER
+a.z.w.example. MX 1 ai.example.
+a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== )
+; SECTION AUTHORITY
+; q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+; q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+; SECTION ADDITIONAL
+; ai.example. A 192.0.2.9
+; ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== )
+; ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9
+; ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== )
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata.rpl b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata.rpl
new file mode 100644
index 0000000..ca0242a
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata.rpl
@@ -0,0 +1,155 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that matches the closest encloser (w.example)
+;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== )
+
+;; NSEC3 RR that covers the "next closer" name (z.w.example)
+;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+
+;; NSEC3 RR that matches a wildcard at the closest encloser.
+;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+; catch glue queries
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN A
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN AAAA
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.z.w.example. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+; AD is missed due to optout
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_noce.rpl b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_noce.rpl
new file mode 100644
index 0000000..fdcfd63
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_noce.rpl
@@ -0,0 +1,165 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without ce.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that matches the closest encloser (w.example)
+;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+;k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+;k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== )
+
+;; NSEC3 RR that covers the "next closer" name (z.w.example)
+;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+
+;; NSEC3 RR that matches a wildcard at the closest encloser.
+;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+; catch glue queries
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN A
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN AAAA
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.z.w.example. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nonc.rpl b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nonc.rpl
new file mode 100644
index 0000000..5a2418d
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nonc.rpl
@@ -0,0 +1,165 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without nc.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that matches the closest encloser (w.example)
+;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== )
+
+;; NSEC3 RR that covers the "next closer" name (z.w.example)
+;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+;q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+;q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+
+;; NSEC3 RR that matches a wildcard at the closest encloser.
+;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+; catch glue queries
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN A
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN AAAA
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.z.w.example. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+;MATCH all
+;do not compare authority
+MATCH opcode qname flags rcode question answer additional
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nowc.rpl b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nowc.rpl
new file mode 100644
index 0000000..c79569a
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_b5_wcnodata_nowc.rpl
@@ -0,0 +1,165 @@
+; config options
+;server:
+ trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )"
+ val-override-date: "20120420235959"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without wc.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN A
+SECTION AUTHORITY
+example. IN NS ns1.example.
+; leave out to make unbound take ns1
+;example. IN NS ns2.example.
+SECTION ADDITIONAL
+ns1.example. IN A 192.0.2.1
+; leave out to make unbound take ns1
+;ns2.example. IN A 192.0.2.2
+ENTRY_END
+RANGE_END
+
+; ns1.example.
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+ns1.example. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR REFUSED
+SECTION QUESTION
+example. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example. IN DNSKEY
+SECTION ANSWER
+example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= )
+example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )
+example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== )
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that matches the closest encloser (w.example)
+;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== )
+
+;; NSEC3 RR that covers the "next closer" name (z.w.example)
+;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== )
+
+;; NSEC3 RR that matches a wildcard at the closest encloser.
+;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+;r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+;r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== )
+
+SECTION ADDITIONAL
+ENTRY_END
+
+; catch glue queries
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN A
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+ns2.example. IN AAAA
+SECTION ANSWER
+; nothing to make sure the ns1 server is used for queries.
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.z.w.example. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+; insecure! not bogus! (due to optout)
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+a.z.w.example. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example. 3600 IN SOA ns1.example. bugs.x.w.example. 1 3600 300 3600000 3600
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_cnametocnamewctoposwc.rpl b/tests/deckard/sets/resolver/val_nsec3_cnametocnamewctoposwc.rpl
new file mode 100644
index 0000000..3fb25d7
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_cnametocnamewctoposwc.rpl
@@ -0,0 +1,242 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DNSKEY 257 3 8 AwEAAdL6YJdvoKQJEt/SgB6MrbQ2RDwnrcQQb6bDE8FpGgLen6hvF31ntVsZ3RZzhCmwL6lvumOLFIRKaP9ZBEVutT9iMoF2dNRbT0TCUrv6uQNHcuCZ0BJhuDNBU42f3yOnfFv7PKxd0NP+yFHJkvDQAVLMB5GeUQuYnvgQGeZsf/3b"
+ val-override-date: "20121116123249"
+; target-fetch-policy: "0 0 0 0 0"
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with a regular cname to wildcard cname to wildcard response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+start.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+start.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. 120 IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 8 2 3600 20121126123249 20121029123249 64050 example.com. zxGyimwFsd39j8T7jJ+tSAQPwZ7tjk6HHmzosTMCRePM4k4newbLb5HbrpucSiW/plaEZvjRTDTJ6bPkw0msPXjPCI/22Zh236XO5vhGtMOlxDgAEazuhifVF6UsM7GZwONPBCvw705HgWQyCR1YlTK2w9ffH3GopU9f4oP7Pmk=
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 8 AwEAAdWzfjQD2bfQuoQGNYuS0ByosBxiTkoKcy9kMoWOQ/jx9rvTRhHImWxTxFtIyZOoRgn6E6mE71e5Y1q1nuyH544Em+4rNRMMW4bzecQmMmPk+B97MqW9aW6e4BwiCTt52IGfL++5GORYcaITw9UOlQLYH1oHHUNUC6ebHENofLTj ;{id = 64050 (zsk), size = 1024b}
+example.com. 3600 IN DNSKEY 257 3 8 AwEAAdL6YJdvoKQJEt/SgB6MrbQ2RDwnrcQQb6bDE8FpGgLen6hvF31ntVsZ3RZzhCmwL6lvumOLFIRKaP9ZBEVutT9iMoF2dNRbT0TCUrv6uQNHcuCZ0BJhuDNBU42f3yOnfFv7PKxd0NP+yFHJkvDQAVLMB5GeUQuYnvgQGeZsf/3b ;{id = 46426 (ksk), size = 1024b}
+example.com. 3600 IN RRSIG DNSKEY 8 2 3600 20121126123249 20121029123249 46426 example.com. pisNb/A40XDEiMpcYtxc+yO6osISyfpqz+0UZ61pd70+TLXMF197zr9SqOVJHyRI6G2lSnFggxYrZDpxLbxOW0RY/KfjD3xlI14M/2DieJ1NdlQuYFGgTwxcoINUJ/wRd4YUxkF4JS0D4NBdQ0yQYR0KqDr84oyhnULEHX6WB7s=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+start.example.com. IN A
+SECTION ANSWER
+start.example.com. 3600 IN CNAME x.y.z.wc.example.com.
+start.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. LHpx5n++Z0Jgjjalac+e7wdYSbfurqSDpLRAOI1PybTJkwrMvgDKfp0ycT4HwsLVy7spumZ/Ahg/5II9pai7jCiqv1Iyh6fx19ZVeClTFMOLotCK8xMHACYJIY39BhTwD2D3r9BxbK+RopUlXypwV02yzdY2xEnPCBJVDUn5d0g=
+x.y.z.wc.example.com. 3600 IN CNAME x.y.z.end.example.com.
+x.y.z.wc.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. BCnT6CIuqvF1U9LfiHIovgvXIVFJsCXqQWmnjHtbFvzUlTlfGj+56YBSOEpyCep4CBJ0CBgZ8gl5kWip8N+sTlveU/UWMv4FAkqLXRYjp4CZegslmJIuXU5uS+Q0GlLbWdSB9ZCZcbbO0qrOtUfrJ2ozcSTCS+D+oIZ+CkwvDlQ=
+x.y.z.end.example.com. 3600 IN A 1.2.3.5
+x.y.z.end.example.com. 3600 IN RRSIG A 8 3 3600 20121126123249 20121029123249 64050 example.com. MyXXd3MvXtEYVNqWDepM3+Ra/j/b63QehzSHXZe5gL954WxW8KGHPYmeWyhDtruThpZS6s6jeARY2xt0lmEDnMgNyPJGA6UWwTIgvGD0u9Qw5kocCq3ZH4cSG4xu4rmZoi+h8OGrHxUb4jIKzipzAQDxhnAcp/wKF7e+p+OE+Fo=
+SECTION AUTHORITY
+; H(z.wc.example.com.) = isn85psesctb6afn2q105mv966tqqepi.
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN NSEC3 1 0 1 abcd isoaarjsq14bkqaamivn1t1milkv95lc A RRSIG
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123259 20121029123259 64050 example.com. Cxwzq1DUQvhkTVHEJHlb92c511Y+uJy/C0yL9br6W/5lB/usuSiK2DjW58ibPh2kLH1P3SpGqd1Y7LigptdXoPBDFakcNcimPWCN93R3J80+vrHHPkPyIsBaywwYI3SNGgfnHfPF+wmH+tZ1vfEHbigOxqPFK+T0ntKq7dkSndg=
+; H(z.end.example.com.) = a62608t4becqb6233m87ar7a3648rj3b.
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN NSEC3 1 0 1 abcd a64lt5ij9a1up15h5cdsn1u2071901hu A RRSIG
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123315 20121029123315 64050 example.com. gfBu4oqo9cVxJbqrw2Ly7mK638kGPOF8l8eh7ovalniwkU3F+PNYJyfSE9yGX8tMGbXrkEW9mAzAh39igr2+Bbzi9WPTRp4RDVM0qw+eyMmQRPWKt7FeanDtP+OcdVp0Hf2aPzsgmgTdS6s0AboUq1rX53H2M6F8xAiwPrBJXDQ=
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.y.z.wc.example.com. IN A
+SECTION ANSWER
+x.y.z.wc.example.com. 3600 IN CNAME x.y.z.end.example.com.
+x.y.z.wc.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. BCnT6CIuqvF1U9LfiHIovgvXIVFJsCXqQWmnjHtbFvzUlTlfGj+56YBSOEpyCep4CBJ0CBgZ8gl5kWip8N+sTlveU/UWMv4FAkqLXRYjp4CZegslmJIuXU5uS+Q0GlLbWdSB9ZCZcbbO0qrOtUfrJ2ozcSTCS+D+oIZ+CkwvDlQ=
+x.y.z.end.example.com. 3600 IN A 1.2.3.5
+x.y.z.end.example.com. 3600 IN RRSIG A 8 3 3600 20121126123249 20121029123249 64050 example.com. MyXXd3MvXtEYVNqWDepM3+Ra/j/b63QehzSHXZe5gL954WxW8KGHPYmeWyhDtruThpZS6s6jeARY2xt0lmEDnMgNyPJGA6UWwTIgvGD0u9Qw5kocCq3ZH4cSG4xu4rmZoi+h8OGrHxUb4jIKzipzAQDxhnAcp/wKF7e+p+OE+Fo=
+SECTION AUTHORITY
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN NSEC3 1 0 1 abcd isoaarjsq14bkqaamivn1t1milkv95lc A RRSIG
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123259 20121029123259 64050 example.com. Cxwzq1DUQvhkTVHEJHlb92c511Y+uJy/C0yL9br6W/5lB/usuSiK2DjW58ibPh2kLH1P3SpGqd1Y7LigptdXoPBDFakcNcimPWCN93R3J80+vrHHPkPyIsBaywwYI3SNGgfnHfPF+wmH+tZ1vfEHbigOxqPFK+T0ntKq7dkSndg=
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN NSEC3 1 0 1 abcd a64lt5ij9a1up15h5cdsn1u2071901hu A RRSIG
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123315 20121029123315 64050 example.com. gfBu4oqo9cVxJbqrw2Ly7mK638kGPOF8l8eh7ovalniwkU3F+PNYJyfSE9yGX8tMGbXrkEW9mAzAh39igr2+Bbzi9WPTRp4RDVM0qw+eyMmQRPWKt7FeanDtP+OcdVp0Hf2aPzsgmgTdS6s0AboUq1rX53H2M6F8xAiwPrBJXDQ=
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.y.z.end.example.com. IN A
+SECTION ANSWER
+x.y.z.end.example.com. 3600 IN A 1.2.3.5
+x.y.z.end.example.com. 3600 IN RRSIG A 8 3 3600 20121126123249 20121029123249 64050 example.com. MyXXd3MvXtEYVNqWDepM3+Ra/j/b63QehzSHXZe5gL954WxW8KGHPYmeWyhDtruThpZS6s6jeARY2xt0lmEDnMgNyPJGA6UWwTIgvGD0u9Qw5kocCq3ZH4cSG4xu4rmZoi+h8OGrHxUb4jIKzipzAQDxhnAcp/wKF7e+p+OE+Fo=
+SECTION AUTHORITY
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN NSEC3 1 0 1 abcd a64lt5ij9a1up15h5cdsn1u2071901hu A RRSIG
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123315 20121029123315 64050 example.com. gfBu4oqo9cVxJbqrw2Ly7mK638kGPOF8l8eh7ovalniwkU3F+PNYJyfSE9yGX8tMGbXrkEW9mAzAh39igr2+Bbzi9WPTRp4RDVM0qw+eyMmQRPWKt7FeanDtP+OcdVp0Hf2aPzsgmgTdS6s0AboUq1rX53H2M6F8xAiwPrBJXDQ=
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 8 2 3600 20121126123249 20121029123249 64050 example.com. zxGyimwFsd39j8T7jJ+tSAQPwZ7tjk6HHmzosTMCRePM4k4newbLb5HbrpucSiW/plaEZvjRTDTJ6bPkw0msPXjPCI/22Zh236XO5vhGtMOlxDgAEazuhifVF6UsM7GZwONPBCvw705HgWQyCR1YlTK2w9ffH3GopU9f4oP7Pmk=
+ENTRY_END
+RANGE_END
+
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+start.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+start.example.com. IN A
+SECTION ANSWER
+start.example.com. 3600 IN CNAME x.y.z.wc.example.com.
+start.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. LHpx5n++Z0Jgjjalac+e7wdYSbfurqSDpLRAOI1PybTJkwrMvgDKfp0ycT4HwsLVy7spumZ/Ahg/5II9pai7jCiqv1Iyh6fx19ZVeClTFMOLotCK8xMHACYJIY39BhTwD2D3r9BxbK+RopUlXypwV02yzdY2xEnPCBJVDUn5d0g=
+x.y.z.wc.example.com. 3600 IN CNAME x.y.z.end.example.com.
+x.y.z.wc.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. BCnT6CIuqvF1U9LfiHIovgvXIVFJsCXqQWmnjHtbFvzUlTlfGj+56YBSOEpyCep4CBJ0CBgZ8gl5kWip8N+sTlveU/UWMv4FAkqLXRYjp4CZegslmJIuXU5uS+Q0GlLbWdSB9ZCZcbbO0qrOtUfrJ2ozcSTCS+D+oIZ+CkwvDlQ=
+x.y.z.end.example.com. 3600 IN A 1.2.3.5
+x.y.z.end.example.com. 3600 IN RRSIG A 8 3 3600 20121126123249 20121029123249 64050 example.com. MyXXd3MvXtEYVNqWDepM3+Ra/j/b63QehzSHXZe5gL954WxW8KGHPYmeWyhDtruThpZS6s6jeARY2xt0lmEDnMgNyPJGA6UWwTIgvGD0u9Qw5kocCq3ZH4cSG4xu4rmZoi+h8OGrHxUb4jIKzipzAQDxhnAcp/wKF7e+p+OE+Fo=
+SECTION AUTHORITY
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN NSEC3 1 0 1 abcd isoaarjsq14bkqaamivn1t1milkv95lc A RRSIG
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123259 20121029123259 64050 example.com. Cxwzq1DUQvhkTVHEJHlb92c511Y+uJy/C0yL9br6W/5lB/usuSiK2DjW58ibPh2kLH1P3SpGqd1Y7LigptdXoPBDFakcNcimPWCN93R3J80+vrHHPkPyIsBaywwYI3SNGgfnHfPF+wmH+tZ1vfEHbigOxqPFK+T0ntKq7dkSndg=
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN NSEC3 1 0 1 abcd a64lt5ij9a1up15h5cdsn1u2071901hu A RRSIG
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123315 20121029123315 64050 example.com. gfBu4oqo9cVxJbqrw2Ly7mK638kGPOF8l8eh7ovalniwkU3F+PNYJyfSE9yGX8tMGbXrkEW9mAzAh39igr2+Bbzi9WPTRp4RDVM0qw+eyMmQRPWKt7FeanDtP+OcdVp0Hf2aPzsgmgTdS6s0AboUq1rX53H2M6F8xAiwPrBJXDQ=
+;example.com. 3600 IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 8 2 3600 20121126123249 20121029123249 64050 example.com. zxGyimwFsd39j8T7jJ+tSAQPwZ7tjk6HHmzosTMCRePM4k4newbLb5HbrpucSiW/plaEZvjRTDTJ6bPkw0msPXjPCI/22Zh236XO5vhGtMOlxDgAEazuhifVF6UsM7GZwONPBCvw705HgWQyCR1YlTK2w9ffH3GopU9f4oP7Pmk=
+ENTRY_END
+
+; check for cached answer
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+start.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qname flags rcode question answer authority
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+start.example.com. IN A
+SECTION ANSWER
+start.example.com. 3600 IN CNAME x.y.z.wc.example.com.
+start.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. LHpx5n++Z0Jgjjalac+e7wdYSbfurqSDpLRAOI1PybTJkwrMvgDKfp0ycT4HwsLVy7spumZ/Ahg/5II9pai7jCiqv1Iyh6fx19ZVeClTFMOLotCK8xMHACYJIY39BhTwD2D3r9BxbK+RopUlXypwV02yzdY2xEnPCBJVDUn5d0g=
+x.y.z.wc.example.com. 3600 IN CNAME x.y.z.end.example.com.
+x.y.z.wc.example.com. 3600 IN RRSIG CNAME 8 3 3600 20121126123316 20121029123316 64050 example.com. BCnT6CIuqvF1U9LfiHIovgvXIVFJsCXqQWmnjHtbFvzUlTlfGj+56YBSOEpyCep4CBJ0CBgZ8gl5kWip8N+sTlveU/UWMv4FAkqLXRYjp4CZegslmJIuXU5uS+Q0GlLbWdSB9ZCZcbbO0qrOtUfrJ2ozcSTCS+D+oIZ+CkwvDlQ=
+x.y.z.end.example.com. 3600 IN A 1.2.3.5
+x.y.z.end.example.com. 3600 IN RRSIG A 8 3 3600 20121126123249 20121029123249 64050 example.com. MyXXd3MvXtEYVNqWDepM3+Ra/j/b63QehzSHXZe5gL954WxW8KGHPYmeWyhDtruThpZS6s6jeARY2xt0lmEDnMgNyPJGA6UWwTIgvGD0u9Qw5kocCq3ZH4cSG4xu4rmZoi+h8OGrHxUb4jIKzipzAQDxhnAcp/wKF7e+p+OE+Fo=
+SECTION AUTHORITY
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN NSEC3 1 0 1 abcd isoaarjsq14bkqaamivn1t1milkv95lc A RRSIG
+isjq5aarcp8p5sukc56g961cccjus5u2.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123259 20121029123259 64050 example.com. Cxwzq1DUQvhkTVHEJHlb92c511Y+uJy/C0yL9br6W/5lB/usuSiK2DjW58ibPh2kLH1P3SpGqd1Y7LigptdXoPBDFakcNcimPWCN93R3J80+vrHHPkPyIsBaywwYI3SNGgfnHfPF+wmH+tZ1vfEHbigOxqPFK+T0ntKq7dkSndg=
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN NSEC3 1 0 1 abcd a64lt5ij9a1up15h5cdsn1u2071901hu A RRSIG
+a61sejfu6am5a36p628t4s089s309o44.example.com. 86400 IN RRSIG NSEC3 8 3 86400 20121126123315 20121029123315 64050 example.com. gfBu4oqo9cVxJbqrw2Ly7mK638kGPOF8l8eh7ovalniwkU3F+PNYJyfSE9yGX8tMGbXrkEW9mAzAh39igr2+Bbzi9WPTRp4RDVM0qw+eyMmQRPWKt7FeanDtP+OcdVp0Hf2aPzsgmgTdS6s0AboUq1rX53H2M6F8xAiwPrBJXDQ=
+;example.com. 3600 IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 8 2 3600 20121126123249 20121029123249 64050 example.com. cpLjgKPacNxVIGo59tYMZ98GVYpH28WHRWj3AeIHK0StYFcAlflGLdkae1LEgMwfUmzrayrA5GMe3AH8LyuTgA2Dn1oNFxGfuShQvK2MFQ+LxvQfiuoqlAlL5Aa94IWcSoU/wLrr66I1K8oSB2yK1Tyyv73c2N40D1mBbzIE70U=
+SECTION ADDITIONAL
+;ns.example.com. 3600 IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 8 2 3600 20121126123249 20121029123249 64050 example.com. zxGyimwFsd39j8T7jJ+tSAQPwZ7tjk6HHmzosTMCRePM4k4newbLb5HbrpucSiW/plaEZvjRTDTJ6bPkw0msPXjPCI/22Zh236XO5vhGtMOlxDgAEazuhifVF6UsM7GZwONPBCvw705HgWQyCR1YlTK2w9ffH3GopU9f4oP7Pmk=
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_entnodata_optout_badopt.rpl b/tests/deckard/sets/resolver/val_nsec3_entnodata_optout_badopt.rpl
new file mode 100644
index 0000000..559e383
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_entnodata_optout_badopt.rpl
@@ -0,0 +1,199 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with NSEC3 response for NODATA ENT with optout.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854}
+
+; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ent.example.com. IN DS
+SECTION AUTHORITY
+; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg.
+; OPTOUT
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig54sqg NS SOA DNSKEY RRSIG
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AHNLlpOM8cBFBBdzUO9nQC/O6mw3rDUrqcdiSwMKAIckd3k5WZvoP78=
+
+; ent.example.com. -> 2kekcu37chvrqjb272ptidu9jhk8oqag.
+; the span does not have OPTOUT
+2kekcu37chvrqjb272ptidu9jhk7oqag.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd 2kekcu37chvrqjb272ptidu9jhk9oqag
+2kekcu37chvrqjb272ptidu9jhk7oqag.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AAaGjBrmbElksOWsOAU0vdNwbRKsbsQgOwhFkONaynSk9M+2QpJQ6+k=
+ENTRY_END
+
+; refer to server one down
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ent.example.com. IN A
+SECTION AUTHORITY
+; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg.
+; OPTOUT
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig54sqg NS SOA DNSKEY RRSIG
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AHNLlpOM8cBFBBdzUO9nQC/O6mw3rDUrqcdiSwMKAIckd3k5WZvoP78=
+
+; ent.example.com. -> 2kekcu37chvrqjb272ptidu9jhk8oqag.
+; the span does not have OPTOUT
+2kekcu37chvrqjb272ptidu9jhk7oqag.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd 2kekcu37chvrqjb272ptidu9jhk9oqag
+2kekcu37chvrqjb272ptidu9jhk7oqag.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AAaGjBrmbElksOWsOAU0vdNwbRKsbsQgOwhFkONaynSk9M+2QpJQ6+k=
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ent.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+ent.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_nods_badsig.rpl b/tests/deckard/sets/resolver/val_nsec3_nods_badsig.rpl
new file mode 100644
index 0000000..28cc7cb
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_nods_badsig.rpl
@@ -0,0 +1,238 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with NSEC3 with no DS referral with bad signature.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854}
+
+; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854}
+
+ENTRY_END
+
+; refer to server one down
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG
+; bad signature:
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG
+; bad signature
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_nods_soa.rpl b/tests/deckard/sets/resolver/val_nsec3_nods_soa.rpl
new file mode 100644
index 0000000..7086177
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_nods_soa.rpl
@@ -0,0 +1,254 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with NSEC3 with no DS referral abuse of apex.
+; abusing subzone apex NSEC3.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854}
+
+; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS SOA DNSKEY RRSIG
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC4CFQCeKcyw76yvOvfa2+qtxv8bKcEyJwIVAJBeIGST4Y8Tk8YkQI0suee3Bxb1 ;{id = 2854}
+ENTRY_END
+
+; refer to server one down
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS SOA DNSKEY RRSIG
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC4CFQCeKcyw76yvOvfa2+qtxv8bKcEyJwIVAJBeIGST4Y8Tk8YkQI0suee3Bxb1 ;{id = 2854}
+
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.10
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.sub.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_noopt_ref.rpl b/tests/deckard/sets/resolver/val_nsec3_noopt_ref.rpl
new file mode 100644
index 0000000..37e67ee
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_noopt_ref.rpl
@@ -0,0 +1,230 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160308103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN NSEC3 referral to unsigned subzone, no optout.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+; sub.example.com. -> po0bgjsa0o6vivtr1pvp9ra8s54qpnsb.
+PO0BGJSA0O6VIVTR1PVP9RA8S54QPNSB.example.com. 18000 IN NSEC3 1 0 10 A7AD1394BEB94E45 CO0J7N2E081RL10GCBQ31EDR3OE33LNC NS
+PO0BGJSA0O6VIVTR1PVP9RA8S54QPNSB.example.com. 18000 IN RRSIG NSEC3 10 3 18000 20251231235959 20160308093040 2843 example.com. WepNJEmwXlC107N7E4G0qpUYBVLjLGcYSqJtFFyWU0n8wS9Mw6eH4IZY esAjOdkezqjwpDQny/z9GuTMtpKdIZvzEa8mHn9I/Bv6Gq2U9Yc5w0z8 jqRMi/0Rvy4IAAQoHZOntfcfx4ZRVd/55VeQaJevM2DQLaP6Z4e/rhPs cRs=
+ENTRY_END
+
+; refer to server one down
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+; no DS here.
+; sub.example.com. 3600 IN DS 38364 7 1 66DC14443014B2727261B50B447170DE18CF43A9
+; sub.example.com. 3600 IN DS 38364 7 2 719A6680950A624D2C71A67981A7AF884C23E3C21074FF1CF8FB7EFE 20C52F97
+; sub.example.com. 3600 IN RRSIG DS 10 3 3600 20251231235959 20160308101119 2843 example.com. nAH1Nc1yq6EfzKLq48mLOEo2ocQrxkDFVAYIl+7ZMQJ1ZXHSmwePVH+m MAxdJ8xMl9BV/EcScn3vgSG+GfKfpl6txCS59Hxc30k27x6ac/6vL+ll YS99nEZMkc9JpBk3gziLj6hH8qv0G84264lNWAP2XGv1jO/AYrXL6wti Lxg=
+; sub.example.com. -> po0bgjsa0o6vivtr1pvp9ra8s54qpnsb.
+PO0BGJSA0O6VIVTR1PVP9RA8S54QPNSB.example.com. 18000 IN NSEC3 1 0 10 A7AD1394BEB94E45 CO0J7N2E081RL10GCBQ31EDR3OE33LNC NS
+PO0BGJSA0O6VIVTR1PVP9RA8S54QPNSB.example.com. 18000 IN RRSIG NSEC3 10 3 18000 20251231235959 20160308093040 2843 example.com. WepNJEmwXlC107N7E4G0qpUYBVLjLGcYSqJtFFyWU0n8wS9Mw6eH4IZY esAjOdkezqjwpDQny/z9GuTMtpKdIZvzEa8mHn9I/Bv6Gq2U9Yc5w0z8 jqRMi/0Rvy4IAAQoHZOntfcfx4ZRVd/55VeQaJevM2DQLaP6Z4e/rhPs cRs=
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.10
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.sub.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 7 AwEAAfXXu2eDy9QsjLuHgEMWmG03TVauwmITCq520ANujsTZlPKyQKJe xyrYm61e0RuQJb5dB5JnE0O3YYJOpnrl8keieAqVt1efnNtcn8V1em48 et146ZYFAUb/PMdTOgd2XJnhVEWD3VsZbWNMCxP1KcJTATAaLDVCY//E sc9K3CvGUizNcSoTK2rGS73A6GqmvVNnGir6AQIZifkvb6PKzF/hVpS8 cgvKF/UP8hu+0Glbq1YYTFrXMUBzKUH+X19lRvk3eLHurSvGjDEM3ZO6 tp1QdpzIRPzYKENG+qs07dhgCZyb4zqwEycmL9/Vot0ByTGbeHvHN93P PrLxcM5zlVk=
+sub.example.com. 3600 IN DNSKEY 257 3 7 AwEAAfTD+gzZ2g7c9VoOUR2ekQiPNEyqcyl0MZ4sD3bleU8D8hQdDgAI 1G38raY3xmNea8yLCQYF0x00QbmKtzMjpZqKfsCFZDX6lBV5dP8IwJ0D F6L4hjO819IInf6upH9tfQNnueflWyKzfg2zitV+ILZ4YtZViyCKqayw CSPE8OkFlszZyCESzhrXqoPdJ0oHdZCG4lOlRIgZfrMLC4yTI56iiwFc UsKy7BhNPW+hcc4r+0WB9BCpsiei/FjPMcyeMrx1W+s/xgW7/55Nq+dM PUn9v24uCptZUupn/7CRgMGM5DmWe94QIswAQjH2mXNfOgVPOiceLYzU mcNoKudvSUu1hbzJbVHA4UNWDm2vvsdsEzrOEzqO0ZVczLoZzWU4WpLf IlKm481OKkzAP9Y5F4iTTSIrbVcAuEW/iz5zfqWirgGniiTCszAie8lH u1EPBgGnfotqhq9IbNA6aKNUreJPLvJnds7J/aQmiSdm15pAq71B26X5 BmoZVhbNmh6MHXkq99EIt0yRMEOfPLRN7euza8Idd4mA+E8jpdgtYdJD LC7f2SoQxaN4RMr5MC/Z1ENQgLMYRkd87pEQycAlNAoWMPJMuoDNdwhV 15F8+pvkvfu5cm9FoEWvgS+onibUM9EC9L9EDdfDdW1Hf1QfUinVoMf/ Szf1urkPVNl0nNYF
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308100552 27527 sub.example.com. yUIM3oBl8hkj8/NkHw79wpS0EHWTNA+tW8qDv3IhzpRXWQ78QjRvcLt/ PkoUpaVXydM4xwf61oy0C9nNhakiaTw99icmqbIRfOL4ZQAIEtyzKrP4 Dww/ySI8YJx5ebbEALueAOTQQG4VHk3hEfLlFgUOje01y8usi2QjiX84 uSLfW3DtHODNPWuumTBKrysWC8rs2jiXuDTcViP6IGZnZ1X4E9F8m3J6 gv7kOgqUJp9PRuwSQUuWBk2drl8psZzWuk99g/dnN1SY8B3iBc2DE4/S CHUYrHfdp5YjuKsSg8HTmPS83aks/TeKAogRZ5bEUyxO5VHMnywZUZtl YLuyJg==
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308100552 38364 sub.example.com. ewivalJKy9ahD0p0ca871A3rM302OafX1qYe6K9CjBTvFFWl3JR+tEIY idHyVBwANAS4W2LxP2jrweQ3POL9+I/a3EvadWYnaVGrSHuQr42yPL44 jPO1SBkbTKCTHTlNDgllIaOiszkjZNwE9vTiKxz+5s1kVXnGHPGQfNts LVhFgWZmcZ9AlDbieAOjS2F/P7YWp3NG8lLR3v+JWaD1S+TgClwAFWAl kEOBQ0xltRQ7MFZ92cWudJ24FnYlBEpy51XmfYx3ExmCXpGF2vKYoLGR 76CvsC5anrsaYY1znfACrdt2tYvkEE+TwYuO6/Rm1Ay+whI5wzFWpWf2 xTysJEDcx6TK5rm9PpAiPcdbahhEZPyIm8SIbHSXs9X70wqNpZwtrez5 46F2lefZZ6z9q9+o9hicTXGgPz/nITQ693nbphAl/B713kXVhgeBIcX+ ZqjFnXYQBwliU6ae22hWsFl3l+lN0S7o0w2uzMZiChA0VP3H7LKSO1e2 G17Z1bfVfMZoM2hhLOJuWozLorPJR81DrIAO1JpIKGSxP6clBIE6lhjk hvRjQAmxt/rLsebhVNpXNAEkWwxM4OatK5d5zv2HlvL9QA8Nm4NlZ9Fu pKqoRKijUr1ny4O4nwb3aQVxwCP2+MHuH7XQOtpEFxWeoDPFbu9WIunb dONPnl9ZB8Y=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308100552 27527 sub.example.com. h6RhBN/xWlVYrQVt0TNbFd2/6bvQx9oAYJFyKvzZZbcEbd2giEud1gcW B05TZDwK5p36GcyoGdA6DB9kEGFNqH44OqTsUqtOmqysFw2nsAHXGBId UetoOxT1JOvJlqd7qwC1cBhDmlRB+1u83PBCJyjb2nJ4HwEDSAf/5SRN DQJQmGTGD4FIb9ixHOH2Y3f6U2YaDz35RpJSko2j65erEcOH65dXsAiU OkKNh7g3esbQCGNnY85RyhCPGSFJ4MxLsIa+ZqTY9tvtKL0mDSrqd/51 bhNcKa2Dl99cDOwH3kXFqO+L+DdTXU5WbRxRe74SFzoum/lnyQhcrKN5 029iOA==
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 1.2.3.123
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_optout_ad.rpl b/tests/deckard/sets/resolver/val_nsec3_optout_ad.rpl
new file mode 100644
index 0000000..6e1ba90
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_optout_ad.rpl
@@ -0,0 +1,361 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. DS 57024 7 1 46d134be319b2cc910b9938f1cb25dc41abb27bf"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+ query-minimization: off
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with optout NSEC3 response that gets no AD.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20070926134150 20070829134150 57024 example.com. fIE3H2v3wAm3GPajsdgJn+A8R4Cp7dMXf1PSUQ8BfklzMBMJjpc0oM/S7u/HVLYQs1jx8CMdw2TZEpIPfo6Rl0TekDqNtVk6IBw1H+zxDFwf3v7UdOjm8s6FfoEJcZ5yEFV/Lps82NzHCR9uqprhv6ddQdAeVNA5QHis1c5Y1P0= ;{id = 57024}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. b0iX5vuTqngB5F0ORFrFLx8sAeTHGJVcPpD34iNFY71ZoFnHrHfAMWC3RAWz+nQ1NmH1oDdA8NTYN/aQQNzwEz4VmVYA2PANBSiwSY3q3gp9PWZU6CfRNf2dU/210H0y35FroQpADszmwC+Hlbcvll+bQj3fSyT2W/69kRVssj4= ;{id = 57024}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 257 3 7 AwEAAbvre/wK/WVeoj0SiwVkTD+NefvHPru9YIqLWY0m+0E5NYOpJZdc+PGQQYRzFNOlugVZtFirmv5Lmz7GNiASXtG/IFi//SlE30DxEKQOjt2F6qSZTZ1nZ5XOIMGTwWyp4OoI0egk5JavC5mQbyXqcj82ywt6F5Z3CmnThVl6MtOv ;{id = 57024 (ksk), size = 1024b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20070926134150 20070829134150 57024 example.com. lqOo8W7UffLZIKBoIJg8OAPkmCWptnstiLIg1bAtzuEZDZFr2KNZGv+5k6hbRJKYnZRLReY4v8G9Eg0GCC/44gLm8BZlnh/4jLOjMH9MKusFV/jNqz/HABITYn1pBwvVak7lzqN+bmL0KMyWf1MzPWilx4fM9YWinsQFILVLPL0= ;{id = 57024}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20070926134150 20070829134150 57024 example.com. fIE3H2v3wAm3GPajsdgJn+A8R4Cp7dMXf1PSUQ8BfklzMBMJjpc0oM/S7u/HVLYQs1jx8CMdw2TZEpIPfo6Rl0TekDqNtVk6IBw1H+zxDFwf3v7UdOjm8s6FfoEJcZ5yEFV/Lps82NzHCR9uqprhv6ddQdAeVNA5QHis1c5Y1P0= ;{id = 57024}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. b0iX5vuTqngB5F0ORFrFLx8sAeTHGJVcPpD34iNFY71ZoFnHrHfAMWC3RAWz+nQ1NmH1oDdA8NTYN/aQQNzwEz4VmVYA2PANBSiwSY3q3gp9PWZU6CfRNf2dU/210H0y35FroQpADszmwC+Hlbcvll+bQj3fSyT2W/69kRVssj4= ;{id = 57024}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+
+; optout
+; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk.
+; sub.example.com. -> kg19n32806c832kijdnglq8p9m2r5mdj.
+; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub.
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG
+
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+
+; optout
+; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk.
+; sub.example.com. -> kg19n32806c832kijdnglq8p9m2r5mdj.
+; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub.
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG
+
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+rub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+
+; optout
+; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk.
+; rub.example.com. -> c2bqk3tb4foaenfbp1v0pdk6mor3r7vo.
+; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub.
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. NSEC3 1 1 0 - f2bqk3tb4foaenfbp1v0pdk6mor3r7vo NS RRSIG
+
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jk6EYU9qTrmNeeKuQRG7iKyfNJnBt45MToPVpAQ+LoGDC3muy4bkWeKspj68cN9E5wNijfmm1eFK3khSSEnM50mfJbpiwlbKgL0VZz33Zn+Wu8b7sTtdDwDH7MUBLRwHeb7W+NtQIEXPLs4Z3BXHzAXy5ZpSjQ3PJZn6zBx4/dw= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+; wildcard expansion
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.wild.example.com. IN A
+SECTION ANSWER
+; *.wild.example.com. IN A 77.88.99.0
+a.wild.example.com. IN A 77.88.99.0
+a.wild.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. GWV6cQprrpAsaYla5z7N9tppdb+X0ZjOsiWBuBueSACHU8CzsYPMbwKUZlTNbQ4mSVRRDa0rM1niYoZF9oqyAfbn5HBLi62TRjrBLHfvatDgSiZCa4mauUfzUS+U7FfUXikNIigG0aN0xdpJ//urmecjNSKg2aW4M0DYsm7keMI= ;{id = 57024}
+SECTION AUTHORITY
+; a.wild.example.com -> ad1535hlgg914unuuaei9jfh4ofr44uo. covered by optout
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024}
+; for wild.example.com the closest encloser
+; wild.example.com -> 8aeigskl5tmraedgji7v1lqbmqs8qv7u.
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.wild.example.com. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+; wildcard no data
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+; wild.example.com -> 8aeigskl5tmraedgji7v1lqbmqs8qv7u.
+; *.wild.example.com. -> nvec78au1hpuma9eebeji5n06eq33gbk.
+; the NSEC3 for the wildcard *.wild.example.com. , with optout, A RRSIG
+nvec78au1hpuma9eebeji5n06eq33gbk.example.com. IN NSEC3 1 1 0 - ovec78au1hpuma9eebeji5n06eq33gbk A RRSIG
+nvec78au1hpuma9eebeji5n06eq33gbk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jE+b5p+stQumm+tLZdaBT+KBpwYI7wRXijRHWcqiUp2SY1uV7HxBdW8aedVTqpFe8kYbMUgI3pCOAitmiI9R6SJg3q7022QOb9y+0/xSmIDqxATVPTJbkzVBInfWrulRtn7o3HmOyoIc9/w7NnNxFYpwtFL08jTBRr8XRTWDM7Q= ;{id = 57024}
+; NSEC3 for the closest encloser, wild.example.com. (an empty nonterminal)
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024}
+; a.wild.example.com -> ad1535hlgg914unuuaei9jfh4ofr44uo. covered by optout
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024}
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN MX
+ENTRY_END
+
+; recursion happens here.
+; no AD flag on this because an optout NSEC3 is used.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+sub.example.com. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+; no AD flag here because of RFC5155 9.2 section.
+; even though we are sure there is no DS, this is what the RFC says.
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG
+jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+rub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+; no AD flag here because of RFC5155 9.2 section.
+; also for NXDOMAIN
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NXDOMAIN
+SECTION QUESTION
+rub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM
+onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024}
+22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. NSEC3 1 1 0 - f2bqk3tb4foaenfbp1v0pdk6mor3r7vo NS RRSIG
+22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jk6EYU9qTrmNeeKuQRG7iKyfNJnBt45MToPVpAQ+LoGDC3muy4bkWeKspj68cN9E5wNijfmm1eFK3khSSEnM50mfJbpiwlbKgL0VZz33Zn+Wu8b7sTtdDwDH7MUBLRwHeb7W+NtQIEXPLs4Z3BXHzAXy5ZpSjQ3PJZn6zBx4/dw= ;{id = 57024}
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.wild.example.com. IN A
+ENTRY_END
+
+; query is a wildcard expansion, covered by optout.
+; hence it is without AD flag (even though we are sure this wildcard exists,
+; we are not sure that there is no delegation covered by the optout span
+; with the name a.wild.example.com).
+STEP 70 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+a.wild.example.com. IN A
+SECTION ANSWER
+a.wild.example.com. IN A 77.88.99.0
+a.wild.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. GWV6cQprrpAsaYla5z7N9tppdb+X0ZjOsiWBuBueSACHU8CzsYPMbwKUZlTNbQ4mSVRRDa0rM1niYoZF9oqyAfbn5HBLi62TRjrBLHfvatDgSiZCa4mauUfzUS+U7FfUXikNIigG0aN0xdpJ//urmecjNSKg2aW4M0DYsm7keMI= ;{id = 57024}
+SECTION AUTHORITY
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024}
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024}
+ENTRY_END
+
+STEP 80 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.wild.example.com. IN MX
+ENTRY_END
+
+; nodata wildcard expansion, we are sure that the wildcard does not have
+; the data that is requested, but there an optout flag set on the wildcard
+; expansion denial, thus we are not sure of a.wild.example.com delegation
+; under the optout.
+STEP 90 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+a.wild.example.com. IN MX
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400
+example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024}
+nvec78au1hpuma9eebeji5n06eq33gbk.example.com. IN NSEC3 1 1 0 - ovec78au1hpuma9eebeji5n06eq33gbk A RRSIG
+nvec78au1hpuma9eebeji5n06eq33gbk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jE+b5p+stQumm+tLZdaBT+KBpwYI7wRXijRHWcqiUp2SY1uV7HxBdW8aedVTqpFe8kYbMUgI3pCOAitmiI9R6SJg3q7022QOb9y+0/xSmIDqxATVPTJbkzVBInfWrulRtn7o3HmOyoIc9/w7NnNxFYpwtFL08jTBRr8XRTWDM7Q= ;{id = 57024}
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u
+8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024}
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG
+ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nsec3_optout_ns_ad.rpl b/tests/deckard/sets/resolver/val_nsec3_optout_ns_ad.rpl
new file mode 100644
index 0000000..f364d17
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_optout_ns_ad.rpl
@@ -0,0 +1,203 @@
+; config options
+ stub-addr: 193.0.14.129
+ trust-anchor: ". IN DS 49060 8 2 E7B1EB56D7D5791B3D45630FEAA9C823DB84B385ACEEAC5F44DD08885C36700F"
+ val-override-date: "20170807130000"
+ query-minimization: off
+ harden-glue: off
+CONFIG_END
+
+SCENARIO_BEGIN Test not setting AD bit for answer which contains proof of nonexistence of NS record using NSEC3 with opt-out
+
+RANGE_BEGIN 1 2
+ ADDRESS 193.0.14.129 ;k.root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+. IN SOA
+SECTION ANSWER
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS k.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170901125744 20170802125744 20661 . VDSzCYw6B8u9cLz5BJuzDtRfmc/iGmD3Vei9TPthggi2lwE4HJ6uxYPt HRuczjHOYJcBzJSL1vh/myUHZXysGiGtEASbKZyWnk0uGf//68sPyQLX +QbhvrjHHP17HOsH8ZaCQUvGD2q7yhTtiGlLPRRxUUA7TQ4e7HRMfzo7 R2g/U3mbzfvJctGrng08r2VPdFndE7H7deef9YJjQ32vJSaDzp0qVtwA q0RO6xfMcUHvAzxFVWkWqUkhbXoBv08xz9O182g2a7lCJlxKD1NbbJ9Y Ob4PFtvK9bL8PUlS3DK4GMsZ8XpTLX2lEUedulX4Jn0fHz5pYk2TEMF6 YuJAWA==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600000 IN DNSKEY 256 3 8 AwEAAe1oA46eOLNris1CtS0qM5TdMESK6i4hpalqa6JDv57eOUkaOeje ZW1tIFUokmaK7kuKEFEosddA89CYM8rt2RbC+sfKalbHAWOus0tXZyAL efb2sW95QRzyG6LNul0jQFn9eYWBUHrVe5Wqd0zrFCbTQLUhELSfrlkI UBpO/xKaGinRHX2JjyOnle4aPZY3bEVa/+KyY2ZU6UC4SBo3aHXanP26 ok91rOTmpTWp64ybsMdCXOU8deyuQFQf6q8DhIDmJrkymhX1MXWQQlE0 fAYIYf8/t9OCwucg8oEg4FPU8Gb4Zm/l6PgO4HFkFjBT6iGFCQt3qXe2 Qe3alUWoATc=
+. 3600000 IN DNSKEY 257 3 8 AwEAAb8sZgVVa02muJ+/+SVhJAvz2EWKGEGquhPbQXuF6ALBYoF4KWTO bZVF8sIVTGoaX5+UWkwwHthg7RwS1DALT/AJymYeHhUwA04gLsfCZ/cv BjmRy5RozeSJ1uxAhoCYHCT2hQBZ0cH0n8roXFXI2Y+6708pO1IBkTPT 9MpAGfezTtGYOortbSn+vqT/Zu8jOpNwkleXON4rlZRBZPd4JUMGL9Y5 N/j6+ClYeM+eFQTKXrLi1oC+0yK1sG5OlqrBDhAhBnz+IhfZz4TOkqJ9 Li2BVMatHBeB9GQHtu0FZuC3J0EQgiZxvq1RgkefFJAiB+5uVRN8U7up 5mLDxSgmT0M=
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170901125744 20170802125744 20661 . Oq/hUNG3VoToA2eT4gd32ALxOCXcR8TQwr+vSXEe6/hReGQdANdbyhFU stwNldw61ZD61MBUORY4YEmlpOsOAEpFB9pw2Me41GHdbtLCwcr5RTD4 6e/qBAdthoglLG53jObrp0nBJclLgoWfm4Rmn3DPIKcMoch/W5MmdWGj 7bC4xChMBWDYLPaqYm5PWgpMdHl60Sq9H/dkkWBvRuqPrN2ATBCoHjUE 6UGZM60AZPRuhqHogqvSiNEEEweqN7KK60dQy65dIMFh0iUCaw2/HDB5 NS30lMqxdJY6xAX1uNMIf6UhdFYFBqHClRUqJcOA7IqskkKel6ZC8Rpg 3qruFg==
+. 2592000 IN RRSIG DNSKEY 8 0 3600000 20170901125744 20170802125744 49060 . eYrzIaVlmMtByHu35+Fu1yUlRkfwZLEPQXspIq7dZzL06H8gBz11/FBE YAvpgYrACeLmEuj3NrWp+2odPrWo23usyvbDiUC1U242trYa4F5qUBKt JtXiHVwMhu+Xg4D5JAXU27itt0XHIKyOAZx6ifuZUvYTvfEtgPm+2Bal uenCi7/ZsBLpOOvB+Wjr+xpxMJILIABvfdgPWCCRh5JiYdhhldJCTA6J MQ5yUlf57OvFOQdnUP6xz+FjTAJWPO2rlc47sRaucKr1i/cQzLaqT2ui +zlunVo7lFq2zNZPRz7zRktO1iDp2Bz7rX+o4DTFVk2gxbcF2x3VAckM +dIgWw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR RD AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NXDOMAIN
+SECTION QUESTION
+li. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+ca5qlot3gsobijfasusg7dvc5kdtgp4e. 86400 IN NSEC3 1 1 10 AE83CC9CD22A4A92 QVMFNLQ9AOEGUQEMOCFD5HGN8L8VAPHO NS SOA RRSIG DNSKEY NSEC3PARAM
+ca5qlot3gsobijfasusg7dvc5kdtgp4e. 86400 IN RRSIG NSEC3 8 1 86400 20170901125744 20170802125744 20661 . TLye07FnnjtPSZ0pUMJ4OToH9evHpuj7Yb6ktj1W1bDLqxYcmbTc1jZu IWe4wn/pLz5/78sigR+KKkP6L/Ki0ZVG8fcmR546Jp4o0+fGVkAqbRyc /kckl4QsHqR4UiMrIDhc/MQHnaje/bNrGka+7pQOnvmRyUo0jSHuVfFI LdKMZpk5seTZKI0k/WgmrDYuFii4HqT8+RB9/uoFVPlSSI/rYJ2G4Wgt t81732pO5Kqcwp7DFKvkkj7yU84zlDXtT7RuF21OCACAUseiCX/GOTGf 8OvZp8Rdfs1wT5LjjWl5Gb23Arr9o4soGsyEbXeaoyw7OVYZzXlEko1l yBm5+g==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+22n8oi3qtiud0dier2bbl2ktforlp60c. 86400 IN NSEC3 1 1 10 AE83CC9CD22A4A92 8HBQQS31TETVRFABEIIF3K7LHPOL93GD
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+22n8oi3qtiud0dier2bbl2ktforlp60c. 86400 IN RRSIG NSEC3 8 1 86400 20170901125744 20170802125744 20661 . K4bXakkrwj5gxNs4JzI/vEjHAKIyT5uYmh56g1pN8r/fOpiarYqtCAue 9oRIK7uk9p3R75n/HYZGfZnF8sfxPKOdTmFDhHtdNbQsqzAz1AOzk1bD 6US62xZQHApINFCHSLJzBch2V3o4/Vb2k5aQQp2mGe5HQzTvCn9JKgRY eRgfJbnN3acVtjT46ggIp7wqQAWNKNakaV2+ad9TgyoOO9/64IDF9Z4a oehlzT+iMHzDk9noOlf67Qvmx79x1pvUCRVA57VQpw0mNnDQCvVQ2Avq IJGiM4SQxyGyeSFqJpLTzboCl8uLy6DaSaeJvtAYIRj3x2kDrW9NfUL3 EQHBOg==
+
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+22n8oi3qtiud0dier2bbl2ktforlp60c. 86400 IN NSEC3 1 1 10 AE83CC9CD22A4A92 8HBQQS31TETVRFABEIIF3K7LHPOL93GD
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+22n8oi3qtiud0dier2bbl2ktforlp60c. 86400 IN RRSIG NSEC3 8 1 86400 20170901125744 20170802125744 20661 . K4bXakkrwj5gxNs4JzI/vEjHAKIyT5uYmh56g1pN8r/fOpiarYqtCAue 9oRIK7uk9p3R75n/HYZGfZnF8sfxPKOdTmFDhHtdNbQsqzAz1AOzk1bD 6US62xZQHApINFCHSLJzBch2V3o4/Vb2k5aQQp2mGe5HQzTvCn9JKgRY eRgfJbnN3acVtjT46ggIp7wqQAWNKNakaV2+ad9TgyoOO9/64IDF9Z4a oehlzT+iMHzDk9noOlf67Qvmx79x1pvUCRVA57VQpw0mNnDQCvVQ2Avq IJGiM4SQxyGyeSFqJpLTzboCl8uLy6DaSaeJvtAYIRj3x2kDrW9NfUL3 EQHBOg==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+ns.net. IN A
+SECTION ANSWER
+ns.net. 600 IN A 1.1.1.1
+ns.net. 600 IN RRSIG A 8 2 600 20170901125744 20170802125744 20661 . Z0VIqlE9FUERy2IRsAQ5Nv8JYhr4Mn6kz29NyAaxVQqokEf3pF760PyA UEpSoBENsnWU+x/2XDSkdlyyJQbUpwZhLDAdXgLQUCg+E+1CFFj1A9Zg zCf0oZ6PsCKyTrHCshyHDQNe+iIWO8Qn3qwoAeytIc3ztSQTkP2s8Tys ZoG/+5dqaCICPOoiVVh7usl7WC8SZn4hVRnU64w+Wxziy3anROZ/pUq9 9DI+7+zb2vEteA0sM151akjAtekFiRuqzjgnBpUiH6j4hgGkoH5NCvkD HD37jMZg4D9jmE7O7X3puAuson2DURvjuoHtZRsLRypglRDmlaRThoff l0BmAw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 2592000 IN RRSIG A 8 3 3600000 20170901125744 20170802125744 20661 . s+A2gmeRqZMgJZsuv7hn8qeHk/DIpoH1ZC5resAX7yhZwCxcQM+mNJ7E Jy7qC9PYBrta7rdeNuDKYuHJBlFZECaV/HZ7+f3SBPEiW9DYUI3SnNOR qyBaJGvuTjoQTWU4FVGe2T/ybroq6HzSx0xKSSHyMQeQFxk9wI86npjF cWm19ddCCwJ2uOrJspZwN8jidDbR//G8ntolmU2RzLKDqInLLqoBs1VF SE5Dqzx9eg4boKmUM3IQIJkVQppyGuMSIDNTh1IbPxZrtMgsh3+o9rds ZcIe5A8TRumEaRrXyJiTXQ25kZkZ0ilPyxWrjFRhjfHFcNX+aFpvwhtH cU6BSw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NXDOMAIN
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+c27sd6l4gd20p5e9ttq5br5a4q7scnf7. 86400 IN NSEC3 1 1 10 AE83CC9CD22A4A92 CA5QLOT3GSOBIJFASUSG7DVC5KDTGP4E A RRSIG
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+c27sd6l4gd20p5e9ttq5br5a4q7scnf7. 86400 IN RRSIG NSEC3 8 1 86400 20170901125744 20170802125744 20661 . NN5tdEbFFwesLYRPUETJb3VNm+90RDAG2OmIvAIheZ8aD3rHp+n3WpWm xoQKDjYBLN49jLBz6zutZVdk5xJ4xfeuyKpckwn3L/sz0ej7XTTZrlpP yvatidBHR7MAwqUiGBLWOLtU2xt+DpIp5GLDLVlQs/pE/kfO/0WF7xZB 8Cf9QFl+eGSAOcsKK5aS0evT4PCM/YMpdzVcUhbS13apzEtyroAghpoy gOx6rNc3svzYYpRpt7Is9qlAY+d7EiFUCv0hnx7MwqkGuRqZFonA4dzt D5ds/+VwPvbo5o1TPQ74ZrToiD9Lkv/x/+qRYR3z1iKaXrUWEh5kLTpb UzSJ8A==
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA AD NOERROR
+SECTION QUESTION
+. IN NSEC3PARAM
+SECTION ANSWER
+. 0 IN NSEC3PARAM 1 0 10 AE83CC9CD22A4A92
+. 0 IN RRSIG NSEC3PARAM 8 0 0 20170901125744 20170802125744 20661 . A11gI2rfHcW4SLbUVRCc2sg9wtgzICywN1hQNTyI2Un880S7PKiVzjEW woCBfSK/t1hMTtGOxSnkSGT7OILY200HZo3fJ9xEhXoeamdrtV2Ht7y2 GIO+MQ9B6y95y/N6PGNTDQIY7LC4D6JNeiSDg1j6joEiQ2LV4vwmYGQt Dl6N+Qx6S2ZSCiXCL4Gg1wvSGQK4DyDGDjYQd9KHsFnHjL6sqwHS5G09 s0JHvigAuYR0sG9/mqb0t+JyKXazpUS/MeaMYIIQnmQqDh37IZSDEPy9 IMbNd8x6El+DtCjC5TQGfDE1iCBr8NTxgkIM5zGLxl5pLzo5H4Z5QYZ2 TUy7DA==
+
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 1 2
+ ADDRESS 1.1.1.1 ;ns.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA NOERROR
+SECTION QUESTION
+li. IN SOA
+SECTION ANSWER
+li. 86400 IN SOA ns.net. hostmaster.example.com. 1234 1800 900 604800 86400
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA NOERROR
+SECTION QUESTION
+li. IN NS
+SECTION ANSWER
+li. IN NS ns.net
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD AA NOERROR
+SECTION QUESTION
+ns.net. IN A
+SECTION ANSWER
+ns.net. 86400 IN A 1.1.1.1
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD AD DO
+SECTION QUESTION
+li. IN NS
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN ; AD flag is not set
+SECTION QUESTION
+li. IN NS
+SECTION ANSWER
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017030902 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170901125744 20170802125744 20661 . uhdJY+sNwlQSb8TtF3WffXadfjNp3/XguyeJ7FKF1Rxr7WPG2asG70U+ Ltj1GFZkpcS+75ifMTJ7Ykc082KSRyh1pmMKQSiY9lPdiOX6muq+kBdX h6jkwI+FrCcrBDzhrH6A4XMcTlNj3lBxrUI7lsQyw2I/nwzsTEiTI+1/ mK5zQKA/pnMepKr4CUSS78f/tT955wm3slms5laQSfxqrakPCSwkRtlM xrXPJnjc34MLVpiItgzuQqCrCb+Rak2QNAVkNKfkvBMxJDmRXoz5BTTQ 4huaJWeOFyvIomZwBseFBDSyS5QYCEfMLo0+R/xc/KjzfVuYG8J0dClM kjnMEw==
+ca5qlot3gsobijfasusg7dvc5kdtgp4e. 86400 IN NSEC3 1 1 10 AE83CC9CD22A4A92 QVMFNLQ9AOEGUQEMOCFD5HGN8L8VAPHO NS SOA RRSIG DNSKEY NSEC3PARAM
+ca5qlot3gsobijfasusg7dvc5kdtgp4e. 86400 IN RRSIG NSEC3 8 1 86400 20170901125744 20170802125744 20661 . TLye07FnnjtPSZ0pUMJ4OToH9evHpuj7Yb6ktj1W1bDLqxYcmbTc1jZu IWe4wn/pLz5/78sigR+KKkP6L/Ki0ZVG8fcmR546Jp4o0+fGVkAqbRyc /kckl4QsHqR4UiMrIDhc/MQHnaje/bNrGka+7pQOnvmRyUo0jSHuVfFI LdKMZpk5seTZKI0k/WgmrDYuFii4HqT8+RB9/uoFVPlSSI/rYJ2G4Wgt t81732pO5Kqcwp7DFKvkkj7yU84zlDXtT7RuF21OCACAUseiCX/GOTGf 8OvZp8Rdfs1wT5LjjWl5Gb23Arr9o4soGsyEbXeaoyw7OVYZzXlEko1l yBm5+g==
+ENTRY_END
+
+SCENARIO_END \ No newline at end of file
diff --git a/tests/deckard/sets/resolver/val_nsec3_optout_unsec_cache.rpl b/tests/deckard/sets/resolver/val_nsec3_optout_unsec_cache.rpl
new file mode 100644
index 0000000..6e2df9b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nsec3_optout_unsec_cache.rpl
@@ -0,0 +1,254 @@
+; config options
+ trust-anchor: ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
+ val-override-date: "20160220000000"
+ stub-addr: 202.12.27.33 # M.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator NSEC3 B.3 referral to optout unsigned zone, cache timeout.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 202.12.27.33
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20160227170000 20160217160000 54549 . Qtgnr2k192gjdx3bLZgzkvqoEhTE4LXfFcPtrGPKawn/78LX6M4LuCZh rSXYMJERXVDQcQbX88EYh8kN3ALgLKpGdyu8HJ6B0vZiDc8yMbn2TuA0 RDqEPTp5om1LbQ0nEWa5XnrTi1fJTNzhT6eBJlcmkJ1/jMfmPG9J4dKJ x/Q=
+SECTION ADDITIONAL
+M.ROOT-SERVERS.NET. IN A 202.12.27.33
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RD RA AD
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 13943 IN DNSKEY 256 3 8 AwEAAbr/RV0stAWYbmKOldjShp4AOQGOyY3ATI1NUpP4X1qBs6lsXpc+1ABgv6zkg02IktjZrHnmD0HsElu3wqXMrT5KL1W7Spmg0Pou9WZ8QttdTKXwrVXrASsaGI2z/pLBSnK8EdzqUrTVxY4TEGZtxV519isM06CCMihxTn5cfFBF
+. 13943 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 13943 IN RRSIG DNSKEY 8 0 172800 20160224235959 20160210000000 19036 . Y2Ktm7gpEXcFg02ZlPNaRhO+GUPSvB2z8tsqe199vO9Rx7tIT/8F2A6OBjiyR6GqPGcPKaXADAt+QjmV174123QJ6UDrk2cPiGPXfEleDlJVtBV5oAVaBedeZxqnmw9WpVCIV6cY5wZbO8mYltA5oZMg8XInokVm6qGPA4wo2Miai5st/KhY+2Ke29StiXeVDdQ4p3e25dE4z1QW3ISxJ0zqvkTMHgQZZiP7IlfXKlCyyrd/Ddrxd22GWY53/oy9/Bry4K8naAw4m5+Q5tEf2zvtiAoaIbi2cM3Lf8AzQU25I6zaERJeQXhyA8cqn4WrbsAANn128Q+9Aibyiol9xg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+net. 172800 IN NS a.gtld-servers.net.
+net. 86400 IN DS 35886 8 2 7862B27F5F516EBE19680444D4CE5E762981931842C465F00236401D8BD973EE
+net. 86400 IN RRSIG DS 8 1 86400 20160228050000 20160218040000 54549 . HXdj4gjShkf/LpyxcxthJyRJE/YAB+NHsbwkfoMJvcdJa6u6J0H4K55BSB5UdR6vFGtY5NHl8tnEQIUeHOrxqMzDoMLofs05So9CdphNhsOdR25sCXLAIAL6l9KfI0+oEFXrCNA2GpU1S6SjNmk0NPzslYBSjAVY8RkTNDJGwqE=
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN DNSKEY
+SECTION ANSWER
+net. 86400 IN DNSKEY 257 3 8 AQOYBnzqWXIEj6mlgXg4LWC0HP2n8eK8XqgHlmJ/69iuIHsa1TrHDG6TcOra/pyeGKwH0nKZhTmXSuUFGh9BCNiwVDuyyb6OBGy2Nte9Kr8NwWg4q+zhSoOf4D+gC9dEzg0yFdwT0DKEvmNPt0K4jbQDS4Yimb+uPKuF6yieWWrPYYCrv8C9KC8JMze2uT6NuWBfsl2fDUoV4l65qMww06D7n+p7RbdwWkAZ0fA63mXVXBZF6kpDtsYD7SUB9jhhfLQE/r85bvg3FaSs5Wi2BaqN06SzGWI1DHu7axthIOeHwg00zxlhTpoYCH0ldoQz+S65zWYi/fRJiyLSBb6JZOvn
+net. 86400 IN DNSKEY 256 3 8 AQPAQAy1b2gx5xTywO8c6kI7OGIMt8yhN1iAemwNkd67cv8CAqNuDi0M3uOIrsVofliQFwp5HgNeIHFWbf8KxUlueZ6Wol2LTe/LnK9QKrczPSHr+q+lEH0cCoe8Cwmuc9y3GwkxqFWGHPCsHLZyVMuvdr3cenc0fvk1dDL7Rg7AlQ==
+net. 86400 IN RRSIG DNSKEY 8 1 86400 20160301173857 20160215173357 35886 net. BHm4lkpvTReitAK4JpVCLStI+JBswb9OEEmdKCCiiGe8zt3aVb6A+b2YCaJcWSA/RRrzASaOWvW7Lb5gyqxV/quEdLgB+xrMlnVUUQclLsF4EvdPMRzm+i8fVK//uo3IPDp/uyzVwR8dRpbPuJud1Mhttt0JZTNg0KqJZQEbq0odNdVWGln6PrvXd8f7L4VUaEJQI5H2SiUD8Iz56+EGmV9a6KIEJDKC0tiwPd1gQChaa5JcJBE9z1baSDX3H1f/tprOz/2H2kr0SDAL4Pztik5uer3bETQtmUK0s9Bq16AKSb3Fjs31LF/7bVwWyOVzIZJlfGk19w7c0seBr7f4gA==SECTION AUTHORITY
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sample.net. 172800 IN NS ns.sample.net.
+a1rt98bs5qgc9nfi51s9hci47uljg6jh.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+a1rt98bs5qgc9nfi51s9hci47uljg6jh.net. 86400 IN RRSIG NSEC3 8 2 86400 20160224061807 20160217050807 51128 net. N9aNNHsSDLSSXMHpw1Bo200V2dqtDc68f4JyCg4ZFCvIKSs5lNeiptWrdfbluQJmdhJK9gz6t3ITbFsnnJjLqwihBiiFbwd1FPctuMK3bGUpZfGXem+3zu4mGKzozQ8nr8KjDUX6fYoLri2vOuCv82a7vbp8RF/6QU6MqvsT4Qw=
+55j4p0id76bnr9pf6341vkh0aga83vi2.net. 86400 IN NSEC3 1 1 0 - 55JHR77O5IJ0MSJFOSIA68OGIQIN5N15 NS DS RRSIG
+55j4p0id76bnr9pf6341vkh0aga83vi2.net. 86400 IN RRSIG NSEC3 8 2 86400 20160223061458 20160216050458 51128 net. QGDWMjAF7ziCridkheQEMH42INj+mHGnPuor/UvkNr2nZz1DDSewqG6/6uQR9FFSzRXINCZT6fdwhoIyTfxfLlNNXxABSqauTFXJ4ZXaBvDh0kwPwFBYOGSeKFukNLDiBhiUVLeMa1Va0M3H7ehWcOn1jsH301KTwu+6F5n6b/Q=
+SECTION ADDITIONAL
+ns.sample.net. 172800 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sample.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+a1rt98bs5qgc9nfi51s9hci47uljg6jh.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+a1rt98bs5qgc9nfi51s9hci47uljg6jh.net. 86400 IN RRSIG NSEC3 8 2 86400 20160224061807 20160217050807 51128 net. N9aNNHsSDLSSXMHpw1Bo200V2dqtDc68f4JyCg4ZFCvIKSs5lNeiptWrdfbluQJmdhJK9gz6t3ITbFsnnJjLqwihBiiFbwd1FPctuMK3bGUpZfGXem+3zu4mGKzozQ8nr8KjDUX6fYoLri2vOuCv82a7vbp8RF/6QU6MqvsT4Qw=
+net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1455877597 1800 900 604800 86400
+net. 900 IN RRSIG SOA 8 1 900 20160226102637 20160219091637 51128 net. TDZlVntb/Dun6Ng0o5eeaXhJw+3HqEcoAEjwrd+xs1D1/+JlhIoP/bnrpcW0pkDxBf8Byg+Jx6J+y7jfPiEboL6aWzSZhX+bqgLGlKlU4oHf3ahUtuyEHxBZ0m/pPDGZQGW35U/9iZ3a1Ga1aPR4zsxoXfQLwwRpDfr3lGKGCrw=
+55j4p0id76bnr9pf6341vkh0aga83vi2.net. 86400 IN NSEC3 1 1 0 - 55JHR77O5IJ0MSJFOSIA68OGIQIN5N15 NS DS RRSIG
+55j4p0id76bnr9pf6341vkh0aga83vi2.net. 86400 IN RRSIG NSEC3 8 2 86400 20160223061458 20160216050458 51128 net. QGDWMjAF7ziCridkheQEMH42INj+mHGnPuor/UvkNr2nZz1DDSewqG6/6uQR9FFSzRXINCZT6fdwhoIyTfxfLlNNXxABSqauTFXJ4ZXaBvDh0kwPwFBYOGSeKFukNLDiBhiUVLeMa1Va0M3H7ehWcOn1jsH301KTwu+6F5n6b/Q=
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 100
+ ADDRESS 192.0.2.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+b.sample.net. 6000 IN NS ns.b.sample.net
+SECTION ADDITIONAL
+ns.b.sample.net 6000 IN A 192.0.2.2
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.sample.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+sample.net. 180 IN SOA internal.sample.net. hostmaster.sample.com. 1455875127 90000 90000 90000 180
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 10 10
+ ADDRESS 192.0.2.2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. 20 IN A 192.0.2.3
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+;; must not be fetched due to cache
+RANGE_BEGIN 30 30
+ ADDRESS 192.0.2.2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. 20 IN A 192.0.2.4
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 50 50
+ ADDRESS 192.0.2.2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. 20 IN A 192.0.2.5
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.b.sample.net. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer additional authority
+REPLY QR RD RA
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. IN A 192.0.2.3
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+;; cache hit
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.b.sample.net. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer additional authority
+REPLY QR RD RA
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. IN A 192.0.2.3
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 45 TIME_PASSES ELAPSE 25
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.b.sample.net. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer additional authority
+REPLY QR RD RA
+SECTION QUESTION
+a.b.sample.net. IN A
+SECTION ANSWER
+a.b.sample.net. IN A 192.0.2.5
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nx.rpl b/tests/deckard/sets/resolver/val_nx.rpl
new file mode 100644
index 0000000..4162ffc
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nx.rpl
@@ -0,0 +1,154 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2423 7 1 EA4E6A7A91013E6852DE309CC3CB764A4D09361A "
+val-override-date: "20181130121906"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nxdomain response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101906 20181130101906 2423 example.com. jO3CKvk4qwSCUloEXF+oavs3JC3qE0RZZpYvlitBH6SBQXn7hUDkxJha DfeLHeqKGg+hexpwxAqQZ4yHtqJbyUKVrT5S+VulRJhM99iJeG86Tc23 2z+QjyNSjtvorngs6uRCavwDbazenVLaJtnUkduMQcLIUKEQKCT4bc7z x/s= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101906 20181130101906 2423 example.com. iR4Bz61Q80rARS0h/K5W2YcrJPz9Ng7Ho+s1WxWpMnJdvGKHziITbME6 RhWgUlNZr2iu+mUvNEbU/C9Oim97BuAvTHD2RoL94ztOM4JbvsxXA4x3 REaw97F+pRGWwHU2vkm51bhldjBkSzDVMcLUNZUCChaP3QwMy6+BS3UF se4= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbtGXI8lGuiA26SCDh5c8/EkJP83aCerq4k9SGznAo4HuBlpvGLN 4m8hM0sdFIcTQLoBPyTYJi98VoXN5JcFaChlMERdnP5BSJubfPaqMYqJ EEh3knoelJrwddlgft9gC8J6n126ylu9ZYhZtadGaBshLOKHsfPDyfMn t2oJO0bV ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101906 20181130101906 2423 example.com. G+PLIk1lfmNAvY64DUKXrsRP/EKyEyQC0Zma86KvQREH+IzAOYhcFF1W eLs0ZAAbbiUspz2xj8H2UNkWI2/1nPSHCYfKZuCfkqRONb/HaBhwS7AT gs0Jw/XmFSdVKZ4rgZqA8fRLiugZKIIhp96vu2begq8g6Z8hCkmSUyUP cyM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101906 20181130101906 2423 example.com. jO3CKvk4qwSCUloEXF+oavs3JC3qE0RZZpYvlitBH6SBQXn7hUDkxJha DfeLHeqKGg+hexpwxAqQZ4yHtqJbyUKVrT5S+VulRJhM99iJeG86Tc23 2z+QjyNSjtvorngs6uRCavwDbazenVLaJtnUkduMQcLIUKEQKCT4bc7z x/s= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101906 20181130101906 2423 example.com. iR4Bz61Q80rARS0h/K5W2YcrJPz9Ng7Ho+s1WxWpMnJdvGKHziITbME6 RhWgUlNZr2iu+mUvNEbU/C9Oim97BuAvTHD2RoL94ztOM4JbvsxXA4x3 REaw97F+pRGWwHU2vkm51bhldjBkSzDVMcLUNZUCChaP3QwMy6+BS3UF se4= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101906 20181130101906 2423 example.com. nvDfwhtBRatdQHu2tyCfoaE2HkgAXCm97CZOOx8Bg36MUblQDgwm55mP gaJQKsXxU9fOG9Nd7wkXZEYPvhnKFcUxtrFhHog9ouZtEsuS0w+E9cJX HqrI9L8m7URlQ7FZBaUjqlJGJNFgQbwZzfOvWDzSSzgBqj8emafNwOBg eQ4= ;{id = 2854}
+; wildcard denial
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101906 20181130101906 2423 example.com. dabtLPYkmc3k6LXDJbp1LEi76vYrIBSvZnCl+CQeN4mNCwyu6gFotv8V GyRfSCNsA8LfCpLo3eD+3AzjzT9ZOHdGuRQriOZYPGPS4LiiU2RzzbBc crgeoPk6l+O5trLXDoZA9nxKze4Ef5lYRfw8hxDlimvkned/k2JyMfBz 8OM= ;{id = 2854}
+; qname denial
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101906 20181130101906 2423 example.com. jmkDgBxYtJJx9FuanN3mhTiTQ0ETrhY28v02vyYRw2mgFG80YNsLTq57 tw7pYxb9XBLQpZN1P+1y419pwLVNKiYMONyvjqJbvaiSxzS0xGOrhDpb kEaensygo2GvoyEnO8J7BGRhhJCxVsqC8SCeMZijkWTrNQMGazgCc2Ra n5k= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101906 20181130101906 2423 example.com. nvDfwhtBRatdQHu2tyCfoaE2HkgAXCm97CZOOx8Bg36MUblQDgwm55mP gaJQKsXxU9fOG9Nd7wkXZEYPvhnKFcUxtrFhHog9ouZtEsuS0w+E9cJX HqrI9L8m7URlQ7FZBaUjqlJGJNFgQbwZzfOvWDzSSzgBqj8emafNwOBg eQ4= ;{id = 2854}
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101906 20181130101906 2423 example.com. dabtLPYkmc3k6LXDJbp1LEi76vYrIBSvZnCl+CQeN4mNCwyu6gFotv8V GyRfSCNsA8LfCpLo3eD+3AzjzT9ZOHdGuRQriOZYPGPS4LiiU2RzzbBc crgeoPk6l+O5trLXDoZA9nxKze4Ef5lYRfw8hxDlimvkned/k2JyMfBz 8OM= ;{id = 2854}
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101906 20181130101906 2423 example.com. jmkDgBxYtJJx9FuanN3mhTiTQ0ETrhY28v02vyYRw2mgFG80YNsLTq57 tw7pYxb9XBLQpZN1P+1y419pwLVNKiYMONyvjqJbvaiSxzS0xGOrhDpb kEaensygo2GvoyEnO8J7BGRhhJCxVsqC8SCeMZijkWTrNQMGazgCc2Ra n5k= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nx_nodeny.rpl b/tests/deckard/sets/resolver/val_nx_nodeny.rpl
new file mode 100644
index 0000000..5cc20f2
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nx_nodeny.rpl
@@ -0,0 +1,164 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 46865 7 1 E6C7351C70AA8F888DACB2C1875AD1945CB22C39 "
+val-override-date: "20181130121902"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nxdomain response missing qname denial
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101902 20181130101902 46865 example.com. k6TtlPvoChJFxi4exzlziiPGCdzNU7I0y5Z1cwfskP0Hc6nGbOEw5pVP TXK15AVJ+kIjeqcUbgFRu8/DPolJbWT+yHfuYE2OhjCqxJCt+vVDrMl0 maBTa7UwJeMkR76DqzjSbPsEpRSSXKvzjtlavk/TYbv/sz6yHsVhhYW8 Wu4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101902 20181130101902 46865 example.com. WMO3vMt0WSaOXvL28iNxMK7xr7DgQLejluyrB3VrK7E8Dg3rhWxFZyJ4 ARxGCJEALLugWvH7kPBw9D2vzZh+qHBQ4X7OnHmUOPdwLQUrWfHQ535o /IEnrLWGQKbQUo5+yw+Un0RaovPvkxc6h/Qrpzz67Urx3m7XQoXITO+5 FIM= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcJUKdcSvbPNRyNs/8EtvSsu/QIVXYkAxNxhqFi2TqHG0jWCoRy4 PdX0xSd3ve4PRx0jAi/FK8oWtThJevGGmM5aM+X/ZjFBAImSEo6gP9dB G7oGlou76JfwtSC2l3GHM+WOM/D/mc0I3mmd59AOzzpTnbeLL9EQqUWS nxSsYu4L ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101902 20181130101902 46865 example.com. ZZmEktIT3fcwMOhV3G8cKabicLmqykXtEdZXGVAuCn5Di/zq/5y8l3rZ uhrolnlmPf1Zp9myG7HF/oDmbxyEEw9Vo//YMQGnQp/U7149m0kIpHbz /Os2z5qmxtfyIBIB3tfeQ9ixlBjzn/vCElQTUB83a24tWq+yhtgHIFjr L2k= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101902 20181130101902 46865 example.com. k6TtlPvoChJFxi4exzlziiPGCdzNU7I0y5Z1cwfskP0Hc6nGbOEw5pVP TXK15AVJ+kIjeqcUbgFRu8/DPolJbWT+yHfuYE2OhjCqxJCt+vVDrMl0 maBTa7UwJeMkR76DqzjSbPsEpRSSXKvzjtlavk/TYbv/sz6yHsVhhYW8 Wu4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101902 20181130101902 46865 example.com. WMO3vMt0WSaOXvL28iNxMK7xr7DgQLejluyrB3VrK7E8Dg3rhWxFZyJ4 ARxGCJEALLugWvH7kPBw9D2vzZh+qHBQ4X7OnHmUOPdwLQUrWfHQ535o /IEnrLWGQKbQUo5+yw+Un0RaovPvkxc6h/Qrpzz67Urx3m7XQoXITO+5 FIM= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101902 20181130101902 46865 example.com. KNiFDTdPOEF0+bhorTXrxLGvim8tHyRaVMXfLxP8CVVzWfnoHjVoy7Jo R/l9tVx1wkdQqtOzzBmbbhMMQSylKDii17zWStZFSoA99M1DhT11y47W gjYNT9TXe28IqWEMu/yNr+T0xyWHLRwuDUKiKMxMpPBdEcmMrBghVlcB 2tg= ;{id = 2854}
+; wildcard denial
+example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+example.com. 3600 IN RRSIG NSEC 7 2 18000 20181230101902 20181130101902 46865 example.com. EuaPkCgzpVTILpSBd4X9JMmXLaLFG3zKrXxCqUC/kZbVPgkZSA+4tDt2 Y48mmb8gicjCpe4pszczA0i/CeL+BE0ucdI1iV8GJdR7cBv5e9rG2c36 +F5oQ03pj+FQBbtKJ347XBVkxA/hy6pOFUppsXzV37MeT+VzoMLdCeir JQA= ;{id = 2854}
+; qname denial
+;wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+;wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_nx_nowc.rpl b/tests/deckard/sets/resolver/val_nx_nowc.rpl
new file mode 100644
index 0000000..90a812b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_nx_nowc.rpl
@@ -0,0 +1,164 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 22469 7 1 9A6B45A912CC69BF1BBAE8E890A6351643B58FB9 "
+val-override-date: "20181130121903"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nxdomain response missing wildcard denial
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101903 20181130101903 22469 example.com. AG9VohvKoHDb5Gg+uauHsyBo4TbM8Fc2jS6uNXykvzCnDBaz8Pv4jVgv X5Heqh0V1owcg4pEc4ntAfjAJPObpaR4nVrsR8WOozv1NKiXTixc7gIX NHC1VSo4mT1F/m9GhtyKjKAiZ+b2qE4DqwFfyq6+SC88zMEJtxBBHDF6 SYk= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101903 20181130101903 22469 example.com. AZ+ObbOQ6F/mliTCsbEaqwodaInWAUN0iYp0doBdKv1SaiBbmtJnnD48 Jpm1sJtGOR9H9n4xjQ7oOdL1p56eBqyn3pOV1bc+xLIDnOa4OqtufYqW rkcuT/odtTvd76YGe+Qtw9m7+Rh8i+qnTHPm8Hv/C28mdswEAoyVYvvG LqI= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcvGZqYpdUE7YjWyWyH4xuqH8Ano6gh3qy/zez5uKDL69HDXO7Cc I4tw3FNDtqGbTF0pR1WLQZG9h6VFIHL8IoLpiwvQz9Qc66gtY3RGxa3B OBDhIO3g4QSbGgxnopzko/PgBBhrva4Z/VtjyBZbTak4+oNKcyjDZbuk 5IK9i3wH ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101903 20181130101903 22469 example.com. xaPftZOaUQQuhq5aRlI24hX/reFOtX60Nvb8fZw0FE+bliPrsyQuwFia Rt6u8IT+URHRQJ7h+Vku8XYVdKBmufPVuVqZ7nsCtYAW5sj0OTTUK+y1 U3qH1vm2V+L/pUKPrlC1GtIk/SQzm+sLAsQzUzP8J5jU378IvEOOIDWW qXA= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101903 20181130101903 22469 example.com. AG9VohvKoHDb5Gg+uauHsyBo4TbM8Fc2jS6uNXykvzCnDBaz8Pv4jVgv X5Heqh0V1owcg4pEc4ntAfjAJPObpaR4nVrsR8WOozv1NKiXTixc7gIX NHC1VSo4mT1F/m9GhtyKjKAiZ+b2qE4DqwFfyq6+SC88zMEJtxBBHDF6 SYk= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101903 20181130101903 22469 example.com. AZ+ObbOQ6F/mliTCsbEaqwodaInWAUN0iYp0doBdKv1SaiBbmtJnnD48 Jpm1sJtGOR9H9n4xjQ7oOdL1p56eBqyn3pOV1bc+xLIDnOa4OqtufYqW rkcuT/odtTvd76YGe+Qtw9m7+Rh8i+qnTHPm8Hv/C28mdswEAoyVYvvG LqI= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101903 20181130101903 22469 example.com. r1Wz8XdHbfNhO+pR75oSYz7/WB6z/YtcKOYE0SP03AYnS7sUbiEXMBxV VxgpMjfSGi55EMQQwdWIapvveRk847U5/8wAz076VCjJ0pPWOd8IC2d/ iRjjRmWZF/+7Pl+VTCGr6TXf4ioUU9UfKPOXAFOFNW/R+yTreT0KPnOW As0= ;{id = 2854}
+; wildcard denial
+;example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG
+;example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854}
+; qname denial
+wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG
+wab.example.com. 3600 IN RRSIG NSEC 7 3 18000 20181230101903 20181130101903 22469 example.com. gelBI3JNXZKxtv9CIzlZbHUz1lTb3cN62Kvz/UOjv9+KxPfEG0TFUrQE jSRNdGL2v42x7RMYTzyf+aGmKT8esdgJ+mXcyfsqw4gUfvdQwoc9RVB9 qz24F84u8VGmXrclzHHpn1LBO+mzkz7S4LF1QNhqbvLP3eltC6IfzCPv /xw= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_pos_truncns.rpl b/tests/deckard/sets/resolver/val_pos_truncns.rpl
new file mode 100644
index 0000000..3ef16ff
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_pos_truncns.rpl
@@ -0,0 +1,150 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 8912 7 1 D78A09971CE199BEF5C312E4ABAB6D80BB05A2C3 "
+val-override-date: "20181130121910"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with badly truncated positive response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101910 20181130101910 8912 example.com. irQCG3d04884eHBfTSrzbc9DK5otN8Nx5P90cwT89btFCHG6r1RzpCmT sm4tW+KoIunBREWkhCDx2y6zDmoWyERWan0fBXaIfgbYol+qehDuynR8 ZlVXbrUr7Aou4eCHiyi/4r3zGX8jy4Ujk5fJk6TS8P4/L9fP0ZSNyMYk dEU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101910 20181130101910 8912 example.com. lrvd15HZ6FBa6JE9Me8tjyHvJ2Tgk2Dv/QkeFNOtBNC0RFEuZtRcXFTg +YaQIN1uQ3MGNscJc6vGcMewZTi0bAWfOnizrffhoTnf0eeBA+DMn+JX tGTVBtFKSS+qpF8Hg9iQj49AoM/ciNkwFdXzDqgNbI93+Z0qYRKJ2P0A bFI= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAa5f2vT9N+xcqZex8uKEC7ZMlGN5i+m7TqRu0xtp61GCGe6i83WF gFkmJ9FMHiv22mKJv2YvKgs7MM6peBDuBL/Qjdf17ENba3wT90koD/zM 0XoE61m1oGskzdt04rUTM+T7oTbYekFVILn00V7ZQKUzJTDAbW70fm/9 U5RZM6KT ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101910 20181130101910 8912 example.com. dRH3WVzuN5/hZ07WHCbn6ZMmNONBFfv3oP5BgHQDR8+gRmuwAIPMmHjZ XbKcB8/m6IjClkTEe4zKCBr5Fm3aqYR4pOq29igUVWnd8FbnDIa73vEH JnG+x9h2XgcfAA/5sL1ldv+5maNUDrbNuIa9niGUlYvgXhxrLqCEUJOp C3E= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101910 20181130101910 8912 example.com. irQCG3d04884eHBfTSrzbc9DK5otN8Nx5P90cwT89btFCHG6r1RzpCmT sm4tW+KoIunBREWkhCDx2y6zDmoWyERWan0fBXaIfgbYol+qehDuynR8 ZlVXbrUr7Aou4eCHiyi/4r3zGX8jy4Ujk5fJk6TS8P4/L9fP0ZSNyMYk dEU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101910 20181130101910 8912 example.com. lrvd15HZ6FBa6JE9Me8tjyHvJ2Tgk2Dv/QkeFNOtBNC0RFEuZtRcXFTg +YaQIN1uQ3MGNscJc6vGcMewZTi0bAWfOnizrffhoTnf0eeBA+DMn+JX tGTVBtFKSS+qpF8Hg9iQj49AoM/ciNkwFdXzDqgNbI93+Z0qYRKJ2P0A bFI= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101910 20181130101910 8912 example.com. TDZElBJgT6bazaVj6uIGz2lqvth/j9xNwgWPGtweEUMTTjYvnolL63h8 P47D6vwKxGgxQSJ84U9PpjtsyqzmLxdK+9KEz7iWfzOtUO1pdSOoCrmI a68mCi3GgAJ0raEIWmzE1rPAv+plDIYluJgzy3bCula9vdI1bdN4x/vS Bsk= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+
+; Truncated, no signature for NS record.
+;;;example.com. 3600 IN RRSIG NS 7 2 3600 20181230101910 20181130101910 8912 example.com. irQCG3d04884eHBfTSrzbc9DK5otN8Nx5P90cwT89btFCHG6r1RzpCmT sm4tW+KoIunBREWkhCDx2y6zDmoWyERWan0fBXaIfgbYol+qehDuynR8 ZlVXbrUr7Aou4eCHiyi/4r3zGX8jy4Ujk5fJk6TS8P4/L9fP0ZSNyMYk dEU= ;{id = 2854}
+;;;SECTION ADDITIONAL
+;;;ns.example.com. IN A 1.2.3.4
+;;;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101910 20181130101910 8912 example.com. TDZElBJgT6bazaVj6uIGz2lqvth/j9xNwgWPGtweEUMTTjYvnolL63h8 P47D6vwKxGgxQSJ84U9PpjtsyqzmLxdK+9KEz7iWfzOtUO1pdSOoCrmI a68mCi3GgAJ0raEIWmzE1rPAv+plDIYluJgzy3bCula9vdI1bdN4x/vS Bsk= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_positive_nosigs.rpl b/tests/deckard/sets/resolver/val_positive_nosigs.rpl
new file mode 100644
index 0000000..18e7820
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_positive_nosigs.rpl
@@ -0,0 +1,182 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with positive response, signatures removed.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+; barely valid nodata for AAAA
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DS query for subzone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN DS
+SECTION ANSWER
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_qds_oneanc.rpl b/tests/deckard/sets/resolver/val_qds_oneanc.rpl
new file mode 100644
index 0000000..b5454ab
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_qds_oneanc.rpl
@@ -0,0 +1,222 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 34694 7 1 6051ACF3BE1C7E91C09614E6237A3B6AEF997EEA "
+val-override-date: "20181130121911"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DS query and one anchor
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101911 20181130101911 34694 example.com. u92Oy+hcQjhnkA7+giV6gJlDovDUmmUrhwN3ayf9/de3EFymsGWns3rW uVBy9p9MiGuq5Gh1eBGYgBLsuxYjVQfiF3iqoXldc1La7VjmR+5YzTw0 CnTiabybAXUnEOLlyonnbCeNhN9cvn6nYLN87yPSRuzGeB2T3aFXgkUk p20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101911 20181130101911 34694 example.com. a/cISMkpWJgOLQuAmo05DxcjxUwsets7jV2y+rYMkFn+KZh7pjUDRTvd 52pCzgWlDJPVKrBcNRUQn8D1xVwp+MO/4MjonQRuhGORwdsbuqfMD55+ zeAgEJGGi7ygt5/kFr2gioZejqj1A236IXbLfFiLTmlHtV1Y2A/mvWsP cTA= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdoXMIS/blyIEUB9xHus+B60jFsJiPvHgIhOgFTmLHqwZ5mhFxug q/O9k/iKhf/3HttKed9lvZwJ9XUPzDqJFAXz5nS1oRsGBGtUMwoF/nM3 kU7Ko4oy9Gtjb1/iFuEhTkjGyom9e5m/pA9BW5eX37knNlbHSOpRlcWP zYH213gz ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101911 20181130101911 34694 example.com. HE6kf6hmJBAaDvfG9I5ZhGq7ICr5byQcYDmtEcMQwzMHPjV6bFX6G5dO ttXbxCbFh6XvznDXnsboTXSuX8YGIqtVt0IY7FsyfbF8fKmbKWCfivrb Z1Z5CG6ToA0vCx1sHMF17oa3P8moVPejicDJqOVkz9XzS9zHJxmJIWx2 8fM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101911 20181130101911 34694 example.com. u92Oy+hcQjhnkA7+giV6gJlDovDUmmUrhwN3ayf9/de3EFymsGWns3rW uVBy9p9MiGuq5Gh1eBGYgBLsuxYjVQfiF3iqoXldc1La7VjmR+5YzTw0 CnTiabybAXUnEOLlyonnbCeNhN9cvn6nYLN87yPSRuzGeB2T3aFXgkUk p20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101911 20181130101911 34694 example.com. a/cISMkpWJgOLQuAmo05DxcjxUwsets7jV2y+rYMkFn+KZh7pjUDRTvd 52pCzgWlDJPVKrBcNRUQn8D1xVwp+MO/4MjonQRuhGORwdsbuqfMD55+ zeAgEJGGi7ygt5/kFr2gioZejqj1A236IXbLfFiLTmlHtV1Y2A/mvWsP cTA= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 36540 5 1 040C7E6D3E183A894CDECC56F6A33086409692F2
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101911 20181130101911 34694 example.com. t8Ktq66BvanAwL00D3hzwIIJQXJ6NzsTBzi0Um8bESfFdxlN2WIjSVd5 hfNruVRDEsTCDlOd2r6cG3Q003NGDn7ulOUR8RLL29a4Tj9YkIJnizEw WrMUhdUU9CqbxZSq8aAKO8tIoI56NfK8FqYObZKR4aqXHOBPf0QkvPKr i+E= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 36540 5 1 040C7E6D3E183A894CDECC56F6A33086409692F2
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101911 20181130101911 34694 example.com. t8Ktq66BvanAwL00D3hzwIIJQXJ6NzsTBzi0Um8bESfFdxlN2WIjSVd5 hfNruVRDEsTCDlOd2r6cG3Q003NGDn7ulOUR8RLL29a4Tj9YkIJnizEw WrMUhdUU9CqbxZSq8aAKO8tIoI56NfK8FqYObZKR4aqXHOBPf0QkvPKr i+E= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to DS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 36540 5 1 040C7E6D3E183A894CDECC56F6A33086409692F2
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101911 20181130101911 34694 example.com. t8Ktq66BvanAwL00D3hzwIIJQXJ6NzsTBzi0Um8bESfFdxlN2WIjSVd5 hfNruVRDEsTCDlOd2r6cG3Q003NGDn7ulOUR8RLL29a4Tj9YkIJnizEw WrMUhdUU9CqbxZSq8aAKO8tIoI56NfK8FqYObZKR4aqXHOBPf0QkvPKr i+E= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101911 20181130101911 34694 example.com. u92Oy+hcQjhnkA7+giV6gJlDovDUmmUrhwN3ayf9/de3EFymsGWns3rW uVBy9p9MiGuq5Gh1eBGYgBLsuxYjVQfiF3iqoXldc1La7VjmR+5YzTw0 CnTiabybAXUnEOLlyonnbCeNhN9cvn6nYLN87yPSRuzGeB2T3aFXgkUk p20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101911 20181130101911 34694 example.com. a/cISMkpWJgOLQuAmo05DxcjxUwsets7jV2y+rYMkFn+KZh7pjUDRTvd 52pCzgWlDJPVKrBcNRUQn8D1xVwp+MO/4MjonQRuhGORwdsbuqfMD55+ zeAgEJGGi7ygt5/kFr2gioZejqj1A236IXbLfFiLTmlHtV1Y2A/mvWsP cTA= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 36540 5 1 040C7E6D3E183A894CDECC56F6A33086409692F2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAba60cKYqTClLVdFbBubhTqnnfJ3Kkbyd96JlGBAMHJ5IQ9fONnF KQYGtOZ8FkF9HBOHoz+WCqlG8mRHuuqkZ/6zei6/DP70JHUcP/cbT6NY RwDqUvAvDXr4tZPKD5yjJKCLqOI+TQo48RlGNVZjZpL5BgiEnM/lguxP DNQri8tP ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101911 20181130101911 36540 sub.example.com. fRAswfvVrez7A0MBgmusYZSOFMIhSobJlEC620/y9SrnBHc2eiWsQOFa AGaqkdprGNopP6Nzsjoz6CCzIFrTmPKizi22Df8CkSBYXdFObWbvAopQ JkFmDH82DwGjEHOu/HhhFN7IPHRXrmDltecCWSIvWD/hjyqEfi0hm0CR 27A= ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101911 20181130101911 36540 sub.example.com. J3ttMFY5LNe6C2X8qpji9Fbn9ms5iUR06VyB4mySCThZqmfaTstShe/k c/Es1nTXgH7ThbnZSE+3bCGfjBD8qu10Nmd5Q0oy8oetwQXIKtEwTETL ces7EjOQLm0XozSe4V0pQlUX5DzxSZhQYx0mTfOCvSqFeZ07Cqzk0lpj ouI= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101911 20181130101911 36540 sub.example.com. mXWfA0N8BIwMdmqIVmmyGc9qvW22Nlo2MChpvC/dwwzXYp9ZX51QUagG D6LzinILleQa3Jz4tb8Z7x/oU57Tz4j1erUvXhnqxLdM66rRi2xk+v8C zkHk3f9GgcjOtrEBy09dIJuppg0mAsBWO8oVwR5BYpGO0KGBUqcvffJt Vv0= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101911 20181130101911 36540 sub.example.com. LLCuevrbnFrzvF80jykui0rHv9Xsi7RF/qVbp6CP+xD6ywWLsUk7Uy9O p6pcq1B0/i0eWImGJT9TiFr1xlNyhtFRnM6KJveih2a/8KtFzJ/ZGgoD OwMNpGqKv+bMcJQEE5Iv4x00ReN49CxSTFm6JM8JKtpR6+WM2ydRns2R CIY= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 36540 5 1 040C7E6D3E183A894CDECC56F6A33086409692F2
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101911 20181130101911 34694 example.com. t8Ktq66BvanAwL00D3hzwIIJQXJ6NzsTBzi0Um8bESfFdxlN2WIjSVd5 hfNruVRDEsTCDlOd2r6cG3Q003NGDn7ulOUR8RLL29a4Tj9YkIJnizEw WrMUhdUU9CqbxZSq8aAKO8tIoI56NfK8FqYObZKR4aqXHOBPf0QkvPKr i+E= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101911 20181130101911 34694 example.com. u92Oy+hcQjhnkA7+giV6gJlDovDUmmUrhwN3ayf9/de3EFymsGWns3rW uVBy9p9MiGuq5Gh1eBGYgBLsuxYjVQfiF3iqoXldc1La7VjmR+5YzTw0 CnTiabybAXUnEOLlyonnbCeNhN9cvn6nYLN87yPSRuzGeB2T3aFXgkUk p20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101911 20181130101911 34694 example.com. a/cISMkpWJgOLQuAmo05DxcjxUwsets7jV2y+rYMkFn+KZh7pjUDRTvd 52pCzgWlDJPVKrBcNRUQn8D1xVwp+MO/4MjonQRuhGORwdsbuqfMD55+ zeAgEJGGi7ygt5/kFr2gioZejqj1A236IXbLfFiLTmlHtV1Y2A/mvWsP cTA= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_qds_twoanc.rpl b/tests/deckard/sets/resolver/val_qds_twoanc.rpl
new file mode 100644
index 0000000..e21c349
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_qds_twoanc.rpl
@@ -0,0 +1,223 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 56744 7 1 0B6FC412DE574014C6231DF6C97C2A370903297A "
+ trust-anchor: "sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B "
+val-override-date: "20181130121913"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DS query and two anchors
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101913 20181130101913 56744 example.com. PbI0TTbOc1OZsplLREnmRXl3zYbj4CMIk7LgavRNp9+diDWksiR1nxWo szKMYfwjN6dxlwowAgL+frC6esvLvbV5BeDhR+emsf4ayKO6OSrCHJUK 5af7jtKkrLYuVCn3Ad1RZxlecv9IIJc6cjUg5FMm3+Riuq/PrekrDZqz Si0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101913 20181130101913 56744 example.com. KgRA0DGIjVXsmx+oLWqWNrDhoTI4doL+wm1+BufgJkfcm8LstWnCre+M sY6rV9o+DM5RvtPj+5pwhrgAMJqaLgMTrEXCWsbFvEQU1jLhYpLRNJ5L 69AMOtfVUquxrdviPcXjzR8VbB+KvH5Vg1NlsuNlxtMbqS3Lex10LKlU NA0= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbKuypu/H/0cr6HwVXfbaS+Xu3Rx5bq0Sfi/lfJP+36jPL2u478E NMk9VBPqVV40r5Y/RZWUZ7YvtbQzWuFSU2jqNUtjamyfzX8AF+tUDf4C FLFUQ0sCx+/cK1t0h4+TQkYOrlR0Xkqw4+bsr0ThsxtL7ypJh2D2Ny0V YtNkob4Z ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101913 20181130101913 56744 example.com. lZJ7diaUg1AHnAljugMYZkZFKhOm/Op363Ott+kXuSPWKFPzXbD/Ezyh g8lpGPjwhxrf3mJgqLiPCkRYsnn5E+ebeCvjwB2OgKuxS09mD7NNUYF+ eYakSNa9zztYavw82dwBVT9frvLqqQg0gyeRc1W0eq7cnyy1pK4lpapl 1eA= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101913 20181130101913 56744 example.com. PbI0TTbOc1OZsplLREnmRXl3zYbj4CMIk7LgavRNp9+diDWksiR1nxWo szKMYfwjN6dxlwowAgL+frC6esvLvbV5BeDhR+emsf4ayKO6OSrCHJUK 5af7jtKkrLYuVCn3Ad1RZxlecv9IIJc6cjUg5FMm3+Riuq/PrekrDZqz Si0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101913 20181130101913 56744 example.com. KgRA0DGIjVXsmx+oLWqWNrDhoTI4doL+wm1+BufgJkfcm8LstWnCre+M sY6rV9o+DM5RvtPj+5pwhrgAMJqaLgMTrEXCWsbFvEQU1jLhYpLRNJ5L 69AMOtfVUquxrdviPcXjzR8VbB+KvH5Vg1NlsuNlxtMbqS3Lex10LKlU NA0= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101913 20181130101913 56744 example.com. G/ri3P6noC+ftYdFA35MrhZv0D/gHUISBYSuLVBir2+Bt9JukeVhqd9i zdjSXCIrxUdJUaPwSSEyLHvVOXJpR8SdtjnHR97YcxM69RSoinBpvBc4 Ey1ahaG1pOH12ipqVIwkJRIlh9C08sdyFTDALw4MwHVd8P+K+oSTEpO/ 0V4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101913 20181130101913 56744 example.com. G/ri3P6noC+ftYdFA35MrhZv0D/gHUISBYSuLVBir2+Bt9JukeVhqd9i zdjSXCIrxUdJUaPwSSEyLHvVOXJpR8SdtjnHR97YcxM69RSoinBpvBc4 Ey1ahaG1pOH12ipqVIwkJRIlh9C08sdyFTDALw4MwHVd8P+K+oSTEpO/ 0V4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to DS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101913 20181130101913 56744 example.com. G/ri3P6noC+ftYdFA35MrhZv0D/gHUISBYSuLVBir2+Bt9JukeVhqd9i zdjSXCIrxUdJUaPwSSEyLHvVOXJpR8SdtjnHR97YcxM69RSoinBpvBc4 Ey1ahaG1pOH12ipqVIwkJRIlh9C08sdyFTDALw4MwHVd8P+K+oSTEpO/ 0V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101913 20181130101913 56744 example.com. PbI0TTbOc1OZsplLREnmRXl3zYbj4CMIk7LgavRNp9+diDWksiR1nxWo szKMYfwjN6dxlwowAgL+frC6esvLvbV5BeDhR+emsf4ayKO6OSrCHJUK 5af7jtKkrLYuVCn3Ad1RZxlecv9IIJc6cjUg5FMm3+Riuq/PrekrDZqz Si0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101913 20181130101913 56744 example.com. KgRA0DGIjVXsmx+oLWqWNrDhoTI4doL+wm1+BufgJkfcm8LstWnCre+M sY6rV9o+DM5RvtPj+5pwhrgAMJqaLgMTrEXCWsbFvEQU1jLhYpLRNJ5L 69AMOtfVUquxrdviPcXjzR8VbB+KvH5Vg1NlsuNlxtMbqS3Lex10LKlU NA0= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAaVxPE0OCr9YJP75+8+TRRBbeizDX1Hc5HP92FgPdh3kglwHm7c0 2LCApXpaKOZrz8ZVAgZDMHarw1N1ADD0u4Ie9OFflkNqFc7dkNENQcqA dKFioClHFAnaUbEtphlduco7etDaoR4QPCas3YOWcRrA75z0XlYXVrf6 mqRwVqFT ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101912 20181130101912 42960 sub.example.com. iho097OZdVbSYY9CuLXsn5C6Sq5laVdU717ueVcTomb9i6aLern28/SL 1AzZbTtAkMfidyM3F9mmwfe80Mm4i+sjGfgrZXV/L8m42sdTfCPZNdCs eAP4jpr+Q8CdxdHzABFthLxFuzA0ZdtiwD3Zq3a4XBVuJQn4XH0+SxL4 Eek= ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101912 20181130101912 42960 sub.example.com. AxXFbEMc9iDGhK8EiQMuDUgpk4heb/P71IlEVQHdQM+XVgZDdLgp7iyP CTH/v0vGjPZsmyJJBjoRNl+m6IinLEF/lf6TJ7Rcir2BCoMvPRojZs7X f9M23LTRLQWaFqIk5N2gt9noR5j997VXK/E/GQ64sit8X2F/LQ+x/1Gq MEw= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101912 20181130101912 42960 sub.example.com. EAtvAOPXd+lgKXYbMzvKC1ahxQtIw15k35+6kgcR/vU7xGLqHkpU0fu0 pG1cFvhDNuxA3E16TNt8dgnNL6GIJI+OE1VgXy9wj1C+9H3ERXcl46xq 9mGG9M4YDMD/TdZMta1ZkR6aiuLeaEAXe9XF5ZfFsEABdrLhB3Diup4G w74= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101912 20181130101912 42960 sub.example.com. U4Z/wPmkVfsoxVnjWpY3nzOOq/w7lUvP+CCbVPQpIWML628yTOTbgIBs Uf/iYRarxaZEF5LwJ0lJ0gHmiw4xpEv1B1Lk0UWLiOmQP0auWUKpTufM L6y3HLeav2yuAi7klfeD/8boTzNxr2GEAcgQ4OlrrcGHkNGnzFwWY9a1 Tis= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 42960 5 1 C430C3DFF8F700A924DB9F0EB1589D47E804631B
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101913 20181130101913 56744 example.com. G/ri3P6noC+ftYdFA35MrhZv0D/gHUISBYSuLVBir2+Bt9JukeVhqd9i zdjSXCIrxUdJUaPwSSEyLHvVOXJpR8SdtjnHR97YcxM69RSoinBpvBc4 Ey1ahaG1pOH12ipqVIwkJRIlh9C08sdyFTDALw4MwHVd8P+K+oSTEpO/ 0V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101913 20181130101913 56744 example.com. PbI0TTbOc1OZsplLREnmRXl3zYbj4CMIk7LgavRNp9+diDWksiR1nxWo szKMYfwjN6dxlwowAgL+frC6esvLvbV5BeDhR+emsf4ayKO6OSrCHJUK 5af7jtKkrLYuVCn3Ad1RZxlecv9IIJc6cjUg5FMm3+Riuq/PrekrDZqz Si0= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101913 20181130101913 56744 example.com. KgRA0DGIjVXsmx+oLWqWNrDhoTI4doL+wm1+BufgJkfcm8LstWnCre+M sY6rV9o+DM5RvtPj+5pwhrgAMJqaLgMTrEXCWsbFvEQU1jLhYpLRNJ5L 69AMOtfVUquxrdviPcXjzR8VbB+KvH5Vg1NlsuNlxtMbqS3Lex10LKlU NA0= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_referral_nods.rpl b/tests/deckard/sets/resolver/val_referral_nods.rpl
new file mode 100644
index 0000000..fcb5ee5
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_referral_nods.rpl
@@ -0,0 +1,205 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. IN DS 438 10 2 33F8133EB48EDB093839E985600EB7B7009EB5AC312D11CCA9007F6B 71D94D7B"
+ val-override-date: "20160309103040"
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+ query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Referral without DS.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 438 example.com. MNa4O8/p0DQiRYjWaq7wxo5AYNHyQ7Ts6Awh3qXTr4nm6xm9pVuqOXsX CJlxHRIYZyZfbp3iQGxuUGq9Ks+/4MocFz1O4f+LNLOjVK0mjrnuJUnP Bj3+CLv0RSYmdtvClSu9I2GOTYIa3c29TTQNHjnVSe7ZdPjjsQkn1rW1 gtU=
+example.com. 3600 IN RRSIG NS 10 2 3600 20251231235959 20160308093040 2843 example.com. boNVuXxyhW+Gmiu+4ip1QQvIGqFNVsFfg1v+ywgc4+37ieQ5t+qJsHVm fJITRZrJxYQ6T/MkZKhpxLCemgFeKU6syWwoCfypnGino2G1urvqThna WTImSPhY/QsOj1ALy51d9Q+Mb5vt69XJt6SQvtNf6imepIFOT6CPSfjx BJ4=
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 438 example.com. QKgtWex7PxeyCWG2pVw6kQNxWGr8u8hxtD8Zbc5Khu6q4cMFhoiBY9aA KaJCMnxn9GbSBtaCXARk6DKPfNGVZWeqVSap0uVqmlYJGNP1EGaNBRWJ FTYCHc6HCdtvEsuuhd+VX0YCBLfCt53+zdC3bYQH0U5PxduPkUMmdBvH F+k=
+ns.example.com. 3600 IN RRSIG A 10 3 3600 20251231235959 20160308093040 2843 example.com. VSq+DkxJYr9Z+uh3KgpyPNwtuim4WVXnTdhRW7HX90CP5tyOVjDDTehA UmCxB8iFjUFE3hlwDx0Y71g+8Oso1t0JGkvDtWf5RDx1w+4K/1pQ2JMG lZTh7juaGJzXtltxqBoY67z1FBp9MI59O0hkABtz1CElj9LrhDr9wQa4 OUo=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 38364 7 1 66DC14443014B2727261B50B447170DE18CF43A9
+sub.example.com. 3600 IN DS 38364 7 2 719A6680950A624D2C71A67981A7AF884C23E3C21074FF1CF8FB7EFE 20C52F97
+sub.example.com. 3600 IN RRSIG DS 10 3 3600 20251231235959 20160308093040 438 example.com. mu/x2yR8nFrwOnnfN7dMQ2e2MAAuZigua0wakXaPT0j4pe5AjQhriZXU pWLk5z77ck8Kswt+O23v1sUxmq1bUsIc2kw6N02UyiHnPoxmcu0rg0Kc ustfA++YT5/L+fpq5PRm3kKfHLo81WdZ/VJoaafH/kXHnZTcP62ZoteQ sqw=
+sub.example.com. 3600 IN RRSIG DS 10 3 3600 20251231235959 20160308093040 2843 example.com. ZLx28ZpzPpaafVH3hqV9h6AZJH7Zn0ELOfFxodogJfWue86xjuWhzpBV O9jCOqyURitiBgKNYazghmciNw4wzANbz+hhtc4rIPsfOr/8Vn3pjyev yScX227d16hXKBNKTrAeKNvM8fVPT0E7cG3CY0mzVp3SVqrr+6hl+dgb gXU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 10 AwEAAcOHC7D2ZcG5M6MK5If/60+vvBM67BC8qUx04f6Kcvhx9GBMIMYz 87m6m2P5WKafW5AN1K9jY37m2fU/TdACQNzqu4wyVsOQefke/v2fgswg NgneP/C7cpyBVuK+8BUHjrorfLORClD3mbQMQldaaO2h6+OArAGHlFNI oFsuCjyR
+example.com. 3600 IN DNSKEY 257 3 10 AwEAAc4VCSEu1C1lAxuZMC8tSyissZNXC2lgS3zNvAvFdLtAsSbhB1cj dLCtTWUv1Ki/T+iWn10iemLQJ0S6z8wK+a7maC3ELZP1qoSFln+FiAsZ xYK72/XDEYMMp01F0gxgzZ2alWx3WKm2mELXf/ezEx+7X2ZNbwum5TKt FxtvotmT
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 438 example.com. cas8JKwtLUIItwOgrDrDG9pSkqiYw3r+8vyvt962kjHFBNG0D7AeegaO GMSWRziqA4L8xdgP750rLR5CRFQ9oPQlr/RWnsebGdJ3Yohwwa04HE6n OvR+o0u0oqNQ+P5KinxVKSv0Ru+BVMPHRDfIXN/FD5p9+nvIrnjXQlI3 vvM=
+example.com. 3600 IN RRSIG DNSKEY 10 2 3600 20251231235959 20160308093040 2843 example.com. uDLTMMTvJCcetKr6THEJ8Rn0gMLPFZTbOGJBZyZ2E5F9KkPSS01Nm6/P e+j0R3ObYXodqnZIY19fzXJKS2dJktoXkqNLBW/SpWTlFzpfHKCvTbJS VLrJ/lrEunE5cgSAqBrbAAuJrFpX/gaavqokElnUv1Mki2agTH1dTZyn X8M=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. 3600 IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. 3600 IN A 1.2.3.10
+ENTRY_END
+RANGE_END
+
+; sub.ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 7 AwEAAfXXu2eDy9QsjLuHgEMWmG03TVauwmITCq520ANujsTZlPKyQKJe xyrYm61e0RuQJb5dB5JnE0O3YYJOpnrl8keieAqVt1efnNtcn8V1em48 et146ZYFAUb/PMdTOgd2XJnhVEWD3VsZbWNMCxP1KcJTATAaLDVCY//E sc9K3CvGUizNcSoTK2rGS73A6GqmvVNnGir6AQIZifkvb6PKzF/hVpS8 cgvKF/UP8hu+0Glbq1YYTFrXMUBzKUH+X19lRvk3eLHurSvGjDEM3ZO6 tp1QdpzIRPzYKENG+qs07dhgCZyb4zqwEycmL9/Vot0ByTGbeHvHN93P PrLxcM5zlVk=
+sub.example.com. 3600 IN DNSKEY 257 3 7 AwEAAfTD+gzZ2g7c9VoOUR2ekQiPNEyqcyl0MZ4sD3bleU8D8hQdDgAI 1G38raY3xmNea8yLCQYF0x00QbmKtzMjpZqKfsCFZDX6lBV5dP8IwJ0D F6L4hjO819IInf6upH9tfQNnueflWyKzfg2zitV+ILZ4YtZViyCKqayw CSPE8OkFlszZyCESzhrXqoPdJ0oHdZCG4lOlRIgZfrMLC4yTI56iiwFc UsKy7BhNPW+hcc4r+0WB9BCpsiei/FjPMcyeMrx1W+s/xgW7/55Nq+dM PUn9v24uCptZUupn/7CRgMGM5DmWe94QIswAQjH2mXNfOgVPOiceLYzU mcNoKudvSUu1hbzJbVHA4UNWDm2vvsdsEzrOEzqO0ZVczLoZzWU4WpLf IlKm481OKkzAP9Y5F4iTTSIrbVcAuEW/iz5zfqWirgGniiTCszAie8lH u1EPBgGnfotqhq9IbNA6aKNUreJPLvJnds7J/aQmiSdm15pAq71B26X5 BmoZVhbNmh6MHXkq99EIt0yRMEOfPLRN7euza8Idd4mA+E8jpdgtYdJD LC7f2SoQxaN4RMr5MC/Z1ENQgLMYRkd87pEQycAlNAoWMPJMuoDNdwhV 15F8+pvkvfu5cm9FoEWvgS+onibUM9EC9L9EDdfDdW1Hf1QfUinVoMf/ Szf1urkPVNl0nNYF
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308093040 27527 sub.example.com. CzB+UmU98ArL/HRIOMyHV87PPYoH3G/KKdJlbjtNZAaHG+K6Lad0pKW5 wZR3By1AMlIN9ta8374q+nCEtY+ryM7yBFpzSTmBqrf7ZhkxWh2OSnrI CllC3CsSeltsOq/AEQZwJLQG/gQiCqqQnJY4mneKhcg0Bzc0hpe8c1Dq C5eaHKqt7BaVRO1Ix6OKqEqjHzwd5HpKd2pzU91HyfvHsWrOnKyIwHJP nyOcuHESKN97YLey9Onw0eXjUYdbG5GM12OV1qawShOthcm7XUQiJ0Xl V7y0pNekCxXZdQQI/XhVj8XyLa5pLy8PaOLqypbMBg19J5diLUZYAt/f Dj/EzQ==
+sub.example.com. 3600 IN RRSIG DNSKEY 7 3 3600 20251231235959 20160308093040 38364 sub.example.com. xzyO85eLRwVsg9VI4RnXnjrwf0/TCMub7UcOr7TWWhwt9iR8KFSenx17 EVG1OlgEzRrdZLQWJBPlNBR5aLpsNlzUj+cnCpdG6NtUjcdqRJxb+64Y RktG5Hz35AV7Iegs3L6tFdE4J2moGCDC0y8Rm9wyL+mCUNylpnXUOo8D NDpd7VcYKoieGWxLd8OK5aCYUlB2ziL9yIMOZR+sGEPZWR6ABXDbUF6S ddj7lbZ7y+GHp2XpjDvpmbRSrznNmopzn71O59sCiog8obnGif02EXEn 3L2a8eGx3tMhCZZAPaqJrocTIAmye0vLt0xT22WFPxmcButV1UYZd00m KwJaKgUB450wdub4aAXVvtTx7Us++6zRepZ3VtXARDT+qGzBUkISEuSM FbLHlqqdQeLTcfdu7azEfyCWudoDTbXejFQjFtWkSo6SwEV8sC64rMV6 AFytMBvksBD0tjGrWvPkdDxWa43SQja8BiTlKugtM7zJgqBH9pi1MN4o asc3hyBHBKEiX8ilK7GBTqFph8tdRxawWsaK273pATBLeQfHM2jKcg5p ULhSLxYDvJ+TgYKJkFyFd4C78HffgrashJvrxNsK1QQk05bpTGk9j6ja fzzyB6mDhWGLux1/i++akwTOKsWmFnNe6MXKTN1gnEw4pny3m7zBmh0x gFkbfEo1aDU=
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; cached answer
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 7 4 3600 20251231235959 20160308093040 27527 sub.example.com. QiGpNqXdMQWFYzXMk0FhqEJuzAYijUHOywSUS/hgDxoxBRXBam/tfb3d 1Yqv4+ZVI06ZzOvC2YHRCULjBqjzsQbxxqzPtkfBWbAP/urRFsuwo1zx OSbW9xSUYmHbHicRLFxijvZhuJXX/11tja4dj9ZOeYF/HdWP3r38H4WT /8w3vKr7h2StmL2fY43LxqQm23voNiqJ1dsXLtjyoeIqH40jdMqeLKB+ PJ9p4d3HzOg7uIhLSQYi9slUBWQ10a4uxEBEXmeCI5gLQPot8ijBxF2t TsIOMMPieGC5Zlt9YeT6fsdM6HiUDrfCGbuf9TdlmQqNwRcd8orW58HV SgGalg==
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_root_ds.rpl b/tests/deckard/sets/resolver/val_root_ds.rpl
new file mode 100644
index 0000000..e8aff25
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_root_ds.rpl
@@ -0,0 +1,86 @@
+stub-addr: 198.41.0.4 # a.root-servers.net
+trust-anchor: . 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5
+val-override-date: 20180410000000
+CONFIG_END
+
+SCENARIO_BEGIN query . DS
+; FIX ME: unbound queries way too much, so not providing all those answers
+; pdns test hangs, I don't know why
+
+RANGE_BEGIN 0 10
+ ADDRESS 198.41.0.4
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. DS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018040900 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180422050000 20180409040000 39570 . oV+H+628tDLFEEoxgZNbRDA4Die3VEdejO7iMSHLEYyX8oFwhqoWF2gp XsRlpEnrt07gRfabkPW3DSzhl8syZ+1m6pQ0JDLLBAGODuEYMOYLcJ4n b4Z4WbKwtaL7beRhLf6aLvh51Ozv8qpmV9ZAC7OmlqUt/1h5V1j0/Apq Df3DijQrXs1SVzMWRsKm3kvutfA7a1CPzMs8RK29ujtlZqm0dIEfresJ VtzN2cx1kzvppNF0pNFXzFwh+emZe/eiV4ZyJp4Fm0UrsLnGqLqoQqkE 63panwTQ7nA8VqbrMxj4DGZGgsVcQudzmPfdUYlXCbG6hLO5yyGNFn2C lehfcQ==
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180422050000 20180409040000 39570 . z4xVID27wqu5mcYobS0nFvR5gHsud2HuGKxpvx6gVcyoDMa2vFBTTEqM q2eAATusuN+VSFSgQcoyE8Z7QMVYWkm/nC1LenL4rHLhABRtuo77RwmU R9R5/xkSNoTm7ZL420FWGG3TKrSCDnpEkkloBvtVJsJ4YCg6YuM0hPd2 2P5+teSUH1Py2ODGCVNgTFiUeK6ZVkIbnvL9VfC/g7v4nGLPuDUNsMmr aJ4mgnpqZJZJr2EYKTzxtzKnadXgLEDnwUSczY7yc8ZYU9+6VIu6Hlvm lttaDagf+xwT3BaultN3xOQfQ9BG+dqTuMyA4ZwuirjKN9s7uzqUF+y0 Pl6huw==
+ENTRY_END
+
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. DNSKEY
+SECTION ANSWER
+. 172800 IN DNSKEY 256 3 8 AwEAAdU4aKlDgEpXWWpH5aXHJZI1Vm9Cm42mGAsqkz3akFctS6zsZHC3pNNMug99fKa7OW+tRHIwZEc//mX8Jt6bcw5bPgRHG6u2eT8vUpbXDPVs1ICGR6FhlwFWEOyxbIIiDfd7Eq6eALk5RNcauyE+/ZP+VdrhWZDeEWZRrPBLjByBWTHl+v/f+xvTJ3Stcq2tEqnzS2CCOr6RTJepprYhu+5Yl6aRZmEVBK27WCW1Zrk1LekJvJXfcyKSKk19C5M5JWX58px6nB1IS0pMs6aCIK2yaQQVNUEg9XyQzBSv/rMxVNNy3VAqOjvh+OASpLMm4GECbSSe8jtjwG0I78sfMZc=
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 172800 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=
+. 172800 IN DNSKEY 256 3 8 AwEAAaDJd0KOMYGCEF0/cftC2hrFtz5GSn1HOiaxEp053AfbxQ3pT8BEtahPiUkCo1Qx4PECJ23YwaFhfWWjapr6AFxhD8klfZGp95ickoRlm91ZzXX/mcfn9vlUpZK2M8qjljNMzZJSopFY+cxRvib2Irb6YeP2a0vppaLnvR4BeOyEkQolLqvVHW7UqDFiP/CM15BWBsAIdbyo8L1h3OeP63TaYIrWttjGBILeZinSaJ39amiVs8t00RjTaKVo3vY2k6dje1Rh1ELqjNj8+cKA8iWC3VU7ApkyuGDy631RDILa6wCgcBVCzfFfOthQILxQra88tNWzCVoryQ89f1WjBJc=
+. 172800 IN RRSIG DNSKEY 8 0 172800 20180422000000 20180401000000 19036 . D+U+adJuahA0uubWyJxBronfunX2Bqe6GnttiCzzxby6V5bX51IX8lcMCUHt7e6peQhSWcoKGJvsncX0gYj2PaZjUvZjwn2f08NmoV99kUJlitP6rdyk0tWu8PnYfF/6pahezkbq8Wwl0jVndl6jQ3cAskuM0UDWmpQCxAnhoQPkJjibZVp/FpYG0hJeApC8wfOAWh215pbACNwPCA4N0dj5F6KOPERViDEV8/qq7yBMebB+rp3BKT2415pIcp/CGN3cdJIpbCCiLjK786fjNeqxlXziIjFxiFaqw3Jk1cJqMhnluxF7iA2bOH315jjkj4VcDaBJDCIKrcdLv/9b5g==
+ENTRY_END
+
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD AD DO
+SECTION QUESTION
+. DS
+ENTRY_END
+
+STEP 11 CHECK_ANSWER ; unchanged from the authoritative answer
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer authority additional
+SECTION QUESTION
+. DS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018040900 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180422050000 20180409040000 39570 . oV+H+628tDLFEEoxgZNbRDA4Die3VEdejO7iMSHLEYyX8oFwhqoWF2gp XsRlpEnrt07gRfabkPW3DSzhl8syZ+1m6pQ0JDLLBAGODuEYMOYLcJ4n b4Z4WbKwtaL7beRhLf6aLvh51Ozv8qpmV9ZAC7OmlqUt/1h5V1j0/Apq Df3DijQrXs1SVzMWRsKm3kvutfA7a1CPzMs8RK29ujtlZqm0dIEfresJ VtzN2cx1kzvppNF0pNFXzFwh+emZe/eiV4ZyJp4Fm0UrsLnGqLqoQqkE 63panwTQ7nA8VqbrMxj4DGZGgsVcQudzmPfdUYlXCbG6hLO5yyGNFn2C lehfcQ==
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180422050000 20180409040000 39570 . z4xVID27wqu5mcYobS0nFvR5gHsud2HuGKxpvx6gVcyoDMa2vFBTTEqM q2eAATusuN+VSFSgQcoyE8Z7QMVYWkm/nC1LenL4rHLhABRtuo77RwmU R9R5/xkSNoTm7ZL420FWGG3TKrSCDnpEkkloBvtVJsJ4YCg6YuM0hPd2 2P5+teSUH1Py2ODGCVNgTFiUeK6ZVkIbnvL9VfC/g7v4nGLPuDUNsMmr aJ4mgnpqZJZJr2EYKTzxtzKnadXgLEDnwUSczY7yc8ZYU9+6VIu6Hlvm lttaDagf+xwT3BaultN3xOQfQ9BG+dqTuMyA4ZwuirjKN9s7uzqUF+y0 Pl6huw==
+ENTRY_END
+
+; from cache: exactly the same again, but now authoritatives do not reply
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD AD DO
+SECTION QUESTION
+. DS
+ENTRY_END
+
+STEP 21 CHECK_ANSWER ; unchanged from the authoritative answer
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer authority additional
+SECTION QUESTION
+. DS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018040900 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180422050000 20180409040000 39570 . oV+H+628tDLFEEoxgZNbRDA4Die3VEdejO7iMSHLEYyX8oFwhqoWF2gp XsRlpEnrt07gRfabkPW3DSzhl8syZ+1m6pQ0JDLLBAGODuEYMOYLcJ4n b4Z4WbKwtaL7beRhLf6aLvh51Ozv8qpmV9ZAC7OmlqUt/1h5V1j0/Apq Df3DijQrXs1SVzMWRsKm3kvutfA7a1CPzMs8RK29ujtlZqm0dIEfresJ VtzN2cx1kzvppNF0pNFXzFwh+emZe/eiV4ZyJp4Fm0UrsLnGqLqoQqkE 63panwTQ7nA8VqbrMxj4DGZGgsVcQudzmPfdUYlXCbG6hLO5yyGNFn2C lehfcQ==
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180422050000 20180409040000 39570 . z4xVID27wqu5mcYobS0nFvR5gHsud2HuGKxpvx6gVcyoDMa2vFBTTEqM q2eAATusuN+VSFSgQcoyE8Z7QMVYWkm/nC1LenL4rHLhABRtuo77RwmU R9R5/xkSNoTm7ZL420FWGG3TKrSCDnpEkkloBvtVJsJ4YCg6YuM0hPd2 2P5+teSUH1Py2ODGCVNgTFiUeK6ZVkIbnvL9VfC/g7v4nGLPuDUNsMmr aJ4mgnpqZJZJr2EYKTzxtzKnadXgLEDnwUSczY7yc8ZYU9+6VIu6Hlvm lttaDagf+xwT3BaultN3xOQfQ9BG+dqTuMyA4ZwuirjKN9s7uzqUF+y0 Pl6huw==
+ENTRY_END
+
+SCENARIO_END
+
diff --git a/tests/deckard/sets/resolver/val_rrsig.rpl b/tests/deckard/sets/resolver/val_rrsig.rpl
new file mode 100644
index 0000000..64d8fe4
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_rrsig.rpl
@@ -0,0 +1,169 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 23027 7 1 3B2616A3B46D23EA5E4D709C5D157000779D66A1 "
+val-override-date: "20181130121918"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with qtype RRSIG response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101918 20181130101918 23027 example.com. NL1XpsE+Edp+/XshOxsDvyADfCIu99Un1DSLAYU9kmVa+6GZMgIQchPl lRcC3YboPLAGp05RP24XBk/GB6pwlLCjg8BgxdJ6nwAXSUwHYTHFs/vk BMyGIbMgYp9PlB80GHSVUV9NK5A2QpIVnLLxuWXz+T3x8+HDAVa4X6mo n3M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. VW19ITdySwfn5/PP9dW5rzbKtvFs3F1LpMXcMLgPYriNM2t3xsGQZa+T qRlUERcaUPrmgLtMQJgClTg/Pd9wdn9TZmAt6gtd9PDfWe2n3r4SugCR BxJ9QHaYCCSpNOrir5CyblUpefP48VP+glDm0H3+rlSjjbG2K9bgHsKT 0iM= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAa+ON9qDV53VRATmSZhoARXGtxj0nRF6zg1/erJ9mRNlDZL7bJ/Q oDmfqIRdsTCuXSjLXsNAPVxVZI4YvSWWoe8xVTNa3S2z3PiCZIyGNnD/ d6L42/RxhBureNqf6iRD4smn2BPlf4mk3QHVAAcOvNrVITJExTcxqM7H VK/4eLgP ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101918 20181130101918 23027 example.com. K8QveHt1/E6aSUv2Xo0nPaFi9ehOrn5iQCLyo+TNdgqr6qaJTfqbXulF E05EHUacTzuWlaSlyR1AULB6IHi4/HEpRySPudVayZe6qASjeGI6v7D7 9nuJih5K/9kEBYU645291R06DhI1B5PcqlfLcKiwO2Bpax+n1Rc8v23k 600= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101918 20181130101918 23027 example.com. NL1XpsE+Edp+/XshOxsDvyADfCIu99Un1DSLAYU9kmVa+6GZMgIQchPl lRcC3YboPLAGp05RP24XBk/GB6pwlLCjg8BgxdJ6nwAXSUwHYTHFs/vk BMyGIbMgYp9PlB80GHSVUV9NK5A2QpIVnLLxuWXz+T3x8+HDAVa4X6mo n3M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. VW19ITdySwfn5/PP9dW5rzbKtvFs3F1LpMXcMLgPYriNM2t3xsGQZa+T qRlUERcaUPrmgLtMQJgClTg/Pd9wdn9TZmAt6gtd9PDfWe2n3r4SugCR BxJ9QHaYCCSpNOrir5CyblUpefP48VP+glDm0H3+rlSjjbG2K9bgHsKT 0iM= ;{id = 2854}
+ENTRY_END
+
+; response to query for A
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. VW19ITdySwfn5/PP9dW5rzbKtvFs3F1LpMXcMLgPYriNM2t3xsGQZa+T qRlUERcaUPrmgLtMQJgClTg/Pd9wdn9TZmAt6gtd9PDfWe2n3r4SugCR BxJ9QHaYCCSpNOrir5CyblUpefP48VP+glDm0H3+rlSjjbG2K9bgHsKT 0iM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101918 20181130101918 23027 example.com. NL1XpsE+Edp+/XshOxsDvyADfCIu99Un1DSLAYU9kmVa+6GZMgIQchPl lRcC3YboPLAGp05RP24XBk/GB6pwlLCjg8BgxdJ6nwAXSUwHYTHFs/vk BMyGIbMgYp9PlB80GHSVUV9NK5A2QpIVnLLxuWXz+T3x8+HDAVa4X6mo n3M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. AudSERijN/0vKfjRw0R0ER2ogfWxZlSQeRKnZSrqS0NXALQjkl0AosJO sMMdZZ3j3JOVqlrDTRFUtHgYl7BKgsy0srbE7RDsgFTjMmGAcgTZE6i1 lv+At+P93kZJemNpIypOTs0AlU8IoU/p+VnmQ8MIQ+lCxNIOQFTLRR3S Cn0= ;{id = 2854}
+ENTRY_END
+
+; RRSIG query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN RRSIG
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. AudSERijN/0vKfjRw0R0ER2ogfWxZlSQeRKnZSrqS0NXALQjkl0AosJO sMMdZZ3j3JOVqlrDTRFUtHgYl7BKgsy0srbE7RDsgFTjMmGAcgTZE6i1 lv+At+P93kZJemNpIypOTs0AlU8IoU/p+VnmQ8MIQ+lCxNIOQFTLRR3S Cn0= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101918 20181130101918 23027 example.com. NL1XpsE+Edp+/XshOxsDvyADfCIu99Un1DSLAYU9kmVa+6GZMgIQchPl lRcC3YboPLAGp05RP24XBk/GB6pwlLCjg8BgxdJ6nwAXSUwHYTHFs/vk BMyGIbMgYp9PlB80GHSVUV9NK5A2QpIVnLLxuWXz+T3x8+HDAVa4X6mo n3M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. VW19ITdySwfn5/PP9dW5rzbKtvFs3F1LpMXcMLgPYriNM2t3xsGQZa+T qRlUERcaUPrmgLtMQJgClTg/Pd9wdn9TZmAt6gtd9PDfWe2n3r4SugCR BxJ9QHaYCCSpNOrir5CyblUpefP48VP+glDm0H3+rlSjjbG2K9bgHsKT 0iM= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN RRSIG
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.com. IN RRSIG
+SECTION ANSWER
+www.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. AudSERijN/0vKfjRw0R0ER2ogfWxZlSQeRKnZSrqS0NXALQjkl0AosJO sMMdZZ3j3JOVqlrDTRFUtHgYl7BKgsy0srbE7RDsgFTjMmGAcgTZE6i1 lv+At+P93kZJemNpIypOTs0AlU8IoU/p+VnmQ8MIQ+lCxNIOQFTLRR3S Cn0= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101918 20181130101918 23027 example.com. NL1XpsE+Edp+/XshOxsDvyADfCIu99Un1DSLAYU9kmVa+6GZMgIQchPl lRcC3YboPLAGp05RP24XBk/GB6pwlLCjg8BgxdJ6nwAXSUwHYTHFs/vk BMyGIbMgYp9PlB80GHSVUV9NK5A2QpIVnLLxuWXz+T3x8+HDAVa4X6mo n3M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101918 20181130101918 23027 example.com. VW19ITdySwfn5/PP9dW5rzbKtvFs3F1LpMXcMLgPYriNM2t3xsGQZa+T qRlUERcaUPrmgLtMQJgClTg/Pd9wdn9TZmAt6gtd9PDfWe2n3r4SugCR BxJ9QHaYCCSpNOrir5CyblUpefP48VP+glDm0H3+rlSjjbG2K9bgHsKT 0iM= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_secds.rpl b/tests/deckard/sets/resolver/val_secds.rpl
new file mode 100644
index 0000000..1776de8
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_secds.rpl
@@ -0,0 +1,213 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 50354 7 1 4BAD1572F3C729F6F04749D8B19E00D8356E3871 "
+val-override-date: "20181130121919"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with secure delegation
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101919 20181130101919 50354 example.com. t69qTSQb8vTWf/DKSpTtvWAACIa9sKDKmOILmY73STpsvjo036t1sBXV iJGBtb6P0dC/gUeAXZdZYgTC2vsTJLSjOtzc8lUTVgswvn2QDSaY8eU2 5UwgGbqZF5cOW87a/NQV1pFZSWi9eFo8IBvbCP+mio6wKvFNqQH7Ja8T aNw= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101919 20181130101919 50354 example.com. Jo9iWIAFOGFQlSzoyXWSRmuZvftlr6NyyI2wFnYVa94mivyRbJViL3G9 vPbhSuP7lkD1DzFbH2nztu6LBqavrVCQCGsEixo6f5eUhywptl/hLTLp 8shS5iWfGvZKXobH9n9ryJIQfwPoVHhEfx5FpOKR+A7ORQOgsQb9TaGv EX8= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcQBfewjdxsAmqiSCuk/SB/CrZSA3C4DvikJfW9pVEqRbEwe05Ii UmGaajAfF7RtC5GD1Lq7T0wVpIJLl7VwX2oCB+jvBIjGPfQ9yvyrfEdM r/hIQlFoEuPqAOwzxJUiOyJOh6utSEwRSnWLoqd8xsxnUJWC6Q7jLgs1 VF4YEnJ7 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101919 20181130101919 50354 example.com. a2fVpjpw/Bf7coByItHRN6tUhnrSLsvAxGyYz4YyNlRJeW2erOgYvwSQ 5JYRwQQaUrtMD1AnBE9B0Fdey5gIi/9xl5LPBqYbfTR9yxcWJoUwmwBs 2JDx6dwzIr5DItXgSNjKd0x0A2cEjFO25XR6R+ukvFZfIBaZW4d41vjw AFM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101919 20181130101919 50354 example.com. t69qTSQb8vTWf/DKSpTtvWAACIa9sKDKmOILmY73STpsvjo036t1sBXV iJGBtb6P0dC/gUeAXZdZYgTC2vsTJLSjOtzc8lUTVgswvn2QDSaY8eU2 5UwgGbqZF5cOW87a/NQV1pFZSWi9eFo8IBvbCP+mio6wKvFNqQH7Ja8T aNw= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101919 20181130101919 50354 example.com. Jo9iWIAFOGFQlSzoyXWSRmuZvftlr6NyyI2wFnYVa94mivyRbJViL3G9 vPbhSuP7lkD1DzFbH2nztu6LBqavrVCQCGsEixo6f5eUhywptl/hLTLp 8shS5iWfGvZKXobH9n9ryJIQfwPoVHhEfx5FpOKR+A7ORQOgsQb9TaGv EX8= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 58437 5 1 CA63FDB4AD33BB461138E76EC4DC94DBE0F038A8
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101919 20181130101919 50354 example.com. g46bxGtNNjp5Zw4L06Yfz/GHWoZbuhlTYMjy/pwREOo1ns3YwF13EK7y juBEsnzR9t+38koZNRgQ1GGI2cAhBxt95xakkvop64zqvdQ9oLqUdapp LfbuPSruLmNUdv6iePkjBuBiSa0XDMaKzfj+gMaIti/43W2wGFDpD+5Z x88= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 58437 5 1 CA63FDB4AD33BB461138E76EC4DC94DBE0F038A8
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20181230101919 20181130101919 50354 example.com. g46bxGtNNjp5Zw4L06Yfz/GHWoZbuhlTYMjy/pwREOo1ns3YwF13EK7y juBEsnzR9t+38koZNRgQ1GGI2cAhBxt95xakkvop64zqvdQ9oLqUdapp LfbuPSruLmNUdv6iePkjBuBiSa0XDMaKzfj+gMaIti/43W2wGFDpD+5Z x88= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101919 20181130101919 58437 sub.example.com. ItcLJAYgLspxtEVeL8fZEb8j1TC6Y92edHMA2/wXO7xiQ+hz7RHJvp2x z3KAAhFX9TJgcrBbWKfpnZ51+IOTgpDLJvZMCsAmHJNmVdITbzzQc5O5 AA2mz0j5Gu9HoMFYZjgHAxRB+YJEYzqMOFAdp4kDhKyVXsqQkiZ/P2BD 41I= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101919 20181130101919 58437 sub.example.com. Al3EkHOo8/SiRqHaHxOA/d2KWRRUaTRklYFlh32mjW20m1oY6G+UpuuZ P6JoNxb7MuME2hd097u8voJlpOtPn90vlTrPgl8QfYroicHWhAepHkT1 bRdwOqVnkUtw4B3uAkz/kkSgOmKsmqvcSRMIqULTIVeSXBPHE0331hcF uGc= ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 58437 5 1 CA63FDB4AD33BB461138E76EC4DC94DBE0F038A8
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAcidUcbaG85xnWPvZBRbP2yb8hg06PeLTFOpZT2GUMRx3EaOanGC G+qffFqMx2427wBoHXXWTlN97aR1H/GBjnH65BQhXC0LFnamFpIA+5kg x8Q6qJP72mGfx0lSnvzSsdnwGJ2DYcSV44fQ/edMxW0YlQH2rkNGlzrr KBMCv3ip ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20181230101919 20181130101919 58437 sub.example.com. nhsKPftsVfsu1hx+zqQ2oCx+NEVzuyIHLAgylBnIGG/alPdfne8qUzPB f3KNGTwuCGfIhUBL7TveVAm5WcPfFi7BDW0uhHqFyJJoJvMLBuiLmCL5 tB13KS2f/HaowRAFuua7g/1e4SjJ0FXfU+/xuP0wrMsI5GI9QKZJr+Bq yi8= ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20181230101919 20181130101919 58437 sub.example.com. ItcLJAYgLspxtEVeL8fZEb8j1TC6Y92edHMA2/wXO7xiQ+hz7RHJvp2x z3KAAhFX9TJgcrBbWKfpnZ51+IOTgpDLJvZMCsAmHJNmVdITbzzQc5O5 AA2mz0j5Gu9HoMFYZjgHAxRB+YJEYzqMOFAdp4kDhKyVXsqQkiZ/P2BD 41I= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101919 20181130101919 58437 sub.example.com. Al3EkHOo8/SiRqHaHxOA/d2KWRRUaTRklYFlh32mjW20m1oY6G+UpuuZ P6JoNxb7MuME2hd097u8voJlpOtPn90vlTrPgl8QfYroicHWhAepHkT1 bRdwOqVnkUtw4B3uAkz/kkSgOmKsmqvcSRMIqULTIVeSXBPHE0331hcF uGc= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101919 20181130101919 58437 sub.example.com. gXjsKvu10zuDSjsMrDT3GN2tjkVbC4xrGjvY3VUL2+RuNI0iAdNUngTv LcHvFpS8jdgQ8AKRNXjL+I7buQmnmfA335Atlzk9plgFxjv313fn7ri6 s4mhBy6+Kyjf8v/wd3cnO9myXxSGAtp7sUcYI3D4CJaWiu8JQ4GgnE+P fuA= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20181230101919 20181130101919 58437 sub.example.com. gXjsKvu10zuDSjsMrDT3GN2tjkVbC4xrGjvY3VUL2+RuNI0iAdNUngTv LcHvFpS8jdgQ8AKRNXjL+I7buQmnmfA335Atlzk9plgFxjv313fn7ri6 s4mhBy6+Kyjf8v/wd3cnO9myXxSGAtp7sUcYI3D4CJaWiu8JQ4GgnE+P fuA= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_secds_nosig.rpl b/tests/deckard/sets/resolver/val_secds_nosig.rpl
new file mode 100644
index 0000000..e6d44ab
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_secds_nosig.rpl
@@ -0,0 +1,233 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+;test from testbound
+
+SCENARIO_BEGIN Test validator with no signatures after secure delegation
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; barely valid nodata for AAAA
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; barely valid nodata for AAAA
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN A
+SECTION ANSWER
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+;sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+;www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel.rpl b/tests/deckard/sets/resolver/val_ta_sentinel.rpl
new file mode 100644
index 0000000..2739010
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel.rpl
@@ -0,0 +1,586 @@
+stub-addr: 2001:503:ba3e::2:30
+trust-anchor: . IN DS 48409 8 2 3D63A0C25BCE86621DE63636F11B35B908EFE8E9381E0E3E9DEFD89EA952C27D
+trust-anchor: example. IN DS 4759 8 2 3384CAE149834F17054DD9150E8C33D3979C4092F5C1B8D35E17A3C36A83810F
+val-override-date: 20180601000000
+query-minimization: off
+harden-glue: off
+CONFIG_END
+
+SCENARIO_BEGIN draft-ietf-dnsop-kskroll-sentinel-14 section 2
+
+
+RANGE_BEGIN 1 1000
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 198.41.0.4
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN SOA
+SECTION ANSWER
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
+. 1814400 IN RRSIG DNSKEY 8 0 1814400 20180629135151 20180530135151 48409 . HRj68PBD0cR2p1njZcMUBecR5DiBbueyhIX1oqc9K9Rig5i+ONuozacm 3F4kg9DhUYb/1W6+PSp9YLyrJtCZOFLqkTjPiOAyiE6zVAE/U5O5LRZ/ FjqRQoWuA1cFZtrLokaWmW9GS5Kb2+PUCJY5NRz27JFSvaRRkoHIFf4o mA6eQsuWt28Itx0VGPL9+mR+2B+IcnmN+DZb7mxoRknOh0WyNop4eiep oSZcCihYHOdesCtmrxoMkwGEHZpu8a6GN7jaeNXXNUulwQYfzUZJZQo1 Zr9cN7kzIZ5tAs9ffnPRcWVO61MQTxUtuGbipFpba6RhGmML8oO4JkOJ Itp6tg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS rootns.
+. 518400 IN RRSIG NS 8 0 518400 20180629135151 20180530135151 48409 . ZBLk+sK9ky+YBmzceXbBqEUyBc6nWfAtF6vCK/6cCfL1AxBYOoxdwE/G m0oRAl5WHRrreDSM2t79jcyyUZyyOcee2j/mLPjLdJPQr0Dw9KY+843L o4VSWV0L9adSzgXgvQF/p4yW2zNbHia7doA9GTDjkQFj2+7HgdJdGk8S I2GCx822fqzMCdS3XerIZ4EMz8Lt1sWaexdCgi0sCn9SvqzNHTaIXirW /apL0ohiBNp23LGa7+/7UvNrv+Y/gHpKk2bUytnS7soOocd9XpTekBY7 jlRlmnHTAdn9b9Zj2PHn72v1RYIywP33Qb9ze7i2v7s12uUR3lJt9sd/ WVeuXQ==
+SECTION ADDITIONAL
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+rootns. 86400 IN NSEC root-key-sentinel-is-ta-00000.test. A AAAA RRSIG NSEC
+rootns. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . noqU9JO9z5QXcedzsm7E6RZ5aIIocIH/jSedo6Zy+GImRTeHpc0le399 DUOsqGlcagx7EWRerScB+xmpL7DxKl0FFyeG0ORvPjJ6IyCFTecWjaKW YVurQnzALW+LhfsPSTxBMnnRhxT5Qrw4dtO0gx7fWyssKUnsMcBdmESs tALFNSfJpiV7so9cK2ssHsC+jkM0AQoemSKJrTesxm8FP1BGT27tz/vx yWIlOUGc8/gBgHo4hoXH1oyCrw9KU9kczRqw4CoCGJtZ2/k15BfmbPlC kLrvLibEmp6OYPVWfJRG79uDHhT+Tul07j26WmA+A7IWXSye8W51WbdH 7gJTKQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN A
+SECTION ANSWER
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN AAAA
+SECTION ANSWER
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . qWJh+EE/O2w382vLo53ci9i1O/rAzJUUnZPmLF+GCwmLLhDl6tlI3y5A cALqIHkK1vrXzD+mED78YpILzZ73izRFieY6DxMtAXViqH9U8KSy6KWp tAWUASDe1gj9DGdDeiKdTAIo/2qk1PiGdZNc2E9vQLIUTJNfwV8aZGIt PTgl/efGEIMGGFQW5RPbDZpcJLQ11/RUi9FHQyseZRwkCa8EiEfgvPJ2 /rwiCPUcM6BdYzKoZ53cAHBbeKkvgAOpQ88qDvtE12aF9F8anxdHd0Ru 2DlmrPPthn7/faXSBbBECIbnjNlWTiyF7r274SQKFCrT0rJx5N9c31n4 ZSIocg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . J4gFrZRSHHDfMoA2zO22H6A55/893OnGO7h3H9znJGZtp7DxT2vxiGJw InBx5/zPubH87rqTa4AkK2GZuDEqVEDU/fjWOjGQOx16V0oeoHi5/R2R sPTzFnb+NvQnQZCRolMHD2keakdzB8b7dfEV80CrRh7uDsiO8aqhSdiV BFJLXFt5qFd+evKw2SG7l9FNMDzukUSAcFIJepM99X7qjQnKsLuzDjyF 4zhgMolAzAwIQzEi4B+G6IQknx5HsvmpNgkbBFjns+Q7ZYutNecPfiYU vaMpSXb5pztCVLbZQEymIXPgsnzdihlMbzh22TZapLbrDBUVEc2yr/QC Tz/CQA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . tl+oiYdq+UDlh6snkobPI/jQbrPM2tESEyDNIec7wCRvCEo6CLd+oMOA H4P7idKJ1Mey0eMl++YI29Vz2KVAIL0Hiamt32VDXyR5QYVVzNQquH5B /P4PDeoSadK1M+VThnSPT685+CLCbAZfu0Hi7+NulEeQLleBMtSGy0pF eG50H7fecNjqmQ2O/3jKRfD8l86+jba3B2FmpPvsxXgR7Ig5jC/XSpSY 0UMXyntDJz7QOSuhh4GcdNEeUqGVTurqnFjgRmZwReVZqeQzCS8Q+eQn cq23FtXxcAqJCFKN68yoorWmlZhZl0DPm4Zpup28wwlIapO+SGwScD0q KyHZYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . N1vrpd062YN/PGLOmdAdgPOc2iPPBadtv+DlqoCJ8OUEtFH605m7AUlX HDV99dpT7j6I/N+Sp6pDMRIRl+rB/tFXNfQFoB7UliAsKQ9UuKxH/uyc /sZWxPmYb+4Xi1AKmkzvp7M3Babq7hTGG/PnngN3386Qd0MXiw11Tdl9 +HIan1Jz2jMrHuR2NZDILZOW10wYogYD3/DAx6bVaJMjDbIky5ikK2H/ 4QajIhtjuux4GfsFc7KjGzT1/Hqa9LqdsLetvQmKF4yGNjizOgnrHlbF GoICQ1KihXF3IGYcBUyIoMcmhAjz6D0/jQz/Blwx3zvEUj2Hf7Xj+haO ShdguQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . UYk1xmrw2A7ojKSTpwuF90WXsXOfNbRI8pi9tDPLmqr0OMn29AW051vG TyLd7L3ogsaoUEDiY2vYyvyZI3kPL9fSRDYgOIk7Cq3hp7k6wMM3IXS6 iIlYnjtvUFGDaE69EpUjwII22lSWaqOo0dCFnacJYWDfShdZcv7yssWG 9nZpki6aiBAjhYXY8tdMnpDJzq9O3zXPQR8xtuFW4S0aVdrHuSPRq935 DWXThocHxOza6OQp/ZkbemkoqAYjTlu0tyITwZsTknxgK1mtM+ArRmhS eykqVs3mmAGIWMN3qIW8SXKVRHI9PPjka0j6+KK+bfmeck0bI2Wu1f3C cnk+nQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . NLK3/UMZZ+39KgwbFFoS6qR2QTEULMxDhlWpK1is+AU3CjUn1RNPRJaq m1MnfJdEq3+FFwVDkpmDGh8lQfTBn192oWlo2goHXZXwuoFN49FPHZ+l u42NWMDKtmS6r9JemJR68jH0jy/AsTMdvAbeodg06cbY6F5Q80EtAdkZ iOZPnqPenfxI+U8C2KgBNas7izGbQZF3FxHi7GZz+wrCGBcjcYX9pcD9 /rf1plZYudefFbxG+P97WfMScDD5vt0dUxz3Yt6YUC48jlyo9WYZDLC5 3qOuqah5oXS1lCGJDm+Kta4koVnm6W4pbCzT9XISwRWZ81rp0NbTrhHb Teu7Pw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . iYK8FfKFt+aD2Mh+hvFxyE0lCs/jHMT8EWlhPGuiPekHkYnbTaRbGJhT sCeL3Cg1MHrtGr8BXSq1RMyKnn6Y0/bhF1nEjk1gB+vAFHUwWe0yX32U H7E139q68ZyrcUkpV+KkY+ltMSKAjBtGRkYZ9sJhFvll7YCD2HtAMPud KEWpTZS2D0fLATDzAJzJF/2qGMvRUIn0sk5+3HqVh7R3stbl4aSEw5Zp swJoSCs1DN5eaLh6Ovas51uDAa4t6Ove6owR/gR9isqdZCbilAaJ6497 xg4r/KsCu6eG7GAAw5XGh8rkpC5YbsCBlXB565Zk5oY4yBgBUiG/iXGC wyLyJA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . QNF7LtVeew75AhniJ7S0ncsmrHWHCnRcU0H3uyCipyL20kHlpc1NOIUY md7BB02MXm+XOpJF/l/uc9v/C0iuAgOpFVp5kVjtp+gTu2mgceXstFuP 3tNmrL2pSRIWaN8+koS0MlAZCrH9+J9RSFrm5twtD7bIvGT0FVvy/RrR pRWPy9hbqjH6O5DFMdksdVTPLEYFXevAHGKvRa5beRXkrL9ANfVzvPYl q2RaO1aMX6+Cy7AquJpU7DUSReEUBr1f7mYVdd/6sjzoXrd893c+2Fc+ WFLVuWER3eTSrLAQ3b3Etz0lqM3MLrEXwjQFl2mw046nlh21T+u2Ds5s s1/b8g==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . cGVwlSItiMGEOKkCWRLUn2od/cBvOlSwj8qxCppe4O1FRyTGgEFNV2nf 2zUkhL/agQhXI3qEjFOkq2b1l+4dM3BwDOF7IGhS3yXV3JGnIcwOC7si EMjRZGIvcEenjfugpIwkwkhTZdgIFoyCUr+g6YxA3iL6L77dftAmIkAV 6gvyarwgeYs0Wi+eEGfrZp2MxJjHDXKF+NfCy/fJnYx2n8SRpXya/Uu+ DJ+S4FQDTDyjDhN/+Tvcsb++sjvNfA4ZDwx5gpgNkRF0xsLHMoxCQagH gJBBziP0cq7l2fy5FVMpGNvdkkiYYG8to/2FF/65GhV+RuNcotD91zyW aeSxWw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . YYqLZKzjD13hpj345YTNMYYEh3US2BY7DqK9YbNIZi4T0/0jAEFPamKW WcX0nPm5N5S+1VqKIdo/brqvOTaxsq7HnPxVfomg3wyaKNvwqxb2MUpa pYl25ORa7yOm3gwVZJ3NBjh65dLXzGn8t8b047ym7Fnz6JAJHUyM4/SH hZhvXYBX+i3Lojq7HDIReqAtH7zzWdKzKLCTNqAhuqfvEI3edVynpth2 SCMNDVaAUlzVfBLEAkHNp26mLSgcarc3vrb2khdDS13Kv0Ev4rj0w0v1 z0DnVs95Yl2XlnShzNTaW5w1F8f81oBbq2Ly2POxERr5cOCNSGIWMi+q XAt7bQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . mHz8sEjHOt+UrLPdGr3s+dake/eRQ6QmushFbLex2e6epkvmriVQwdWa QqG4h75UmjNnOlAwpHJA3oRyKxLJKmVgJIAQzhFc6sHLwEVl+kVyxGfu Q17Md+52E/d+mLMHohKRXljTaghp2uLHX8oDtBP+B2HhIDJK+uhfK63A MZ4k1L4jBGCvEGVMO7BhrpHV9zbY21MOb6EIp/F35jB+ftW7gilKxxBK t+Qt1pwtJcDGVC2xZST6fZ2yaR+U+YhOJ7t9j6WVVTWyFSa1CG3lzyRW PNduZeKYTYwox2uqqUxh+Nmzd1oZt7geIw8CGTYS0B++nVUdNJXJnP51 +evqJQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . SjAFtdUPy+YU4sZnst5GNNYxjzWhBOVqUAfGIUv3uBo5qZW9ePecUJ8G ZkNUkdT7m+cHd0c1ssOBOT7snjwc3Sy3zD22b6/q3N8VowhDQDPkoDlB vt9raR7eXu273cEBDZTQ9P4Ya2Meu32Aftwa6VMQmXMl+qWXhYqffEt6 bJuoohnCVqOZihqgnoT+sRiDl49RgLb+GnZNbFk5EP9LXOrWcdxczKso tY384WCrniRmg4L6NM5DjnBtUVT+Qs6fhWGqQv23fPiLV8lt4i34aIf2 jAQkIE6KD4aNLlehct7eqFo1aeaiZumqEd9/GoqSat/RE7Qsh6hiRkfA /J7MLg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-04759.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-04759.test. 1 IN A 192.0.2.33
+root-key-sentinel-is-ta-04759.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . B3RxvVwGi4W0SJPOexXga1Bm4nDiL4u/ITn30YXMPg8yOVOFWQ2axvG/ HdMFU6VSzm5GGIh0e+KR9Jzcvyt2yC3081SrclIkque3LJM1Ar5wa3GO 2M1EC3TuKs+L0WjLXfUTGie7n3mYfoiT+QBfZ4v60JQaD4U+UetZ5Ocn 2rXvuC0Rk9LI+j1Us7u2somZy/swl0Luvg4e+bueHRpTAgKf4nLHFZ8A HEAK0Vy3FG0N4q/oPWx1i9hVNxEaJQIwVcW01KDbP2sqFUNUm3bpT8aH fKRK4hy7MKkDsLrkpcbVbhI4vq8D1GKMtiUjU2kRjQ4VEMzXzXHhPcUi jMf7qw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-04759.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-04759.test. 1 IN A 192.0.2.33
+root-key-sentinel-not-ta-04759.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . sUfM6dehUU9p1QnVX9QIT3K2kvKoU9qGTMNKdVz84AdJJMGnqMbosBpE LusmcZtwcGNjU8jcFdal/t03b+z0jk5BoEG0lzgFGNSp1S1sDGHYTcrv hAHmWpN4a0BEV/ZIOuu1ZJ8s0vRajnAB75jpSGsRdPmCTG/TKeAUJoF+ gua4lLlHnDlLnIVXThL3THqWqoTwg7Ch12piwrklZXNHbSsgcKwwG4SB 8OGY13ewXpH90EYkAFgmLIsavY7Ddhu8ZcFiE5nh6JQrwi7rsAtsr3cx x2rJrMTSEGP1F103YLzxyI4sTiIOGLaxQ7rGuASLGDQW5Cy0mKGgUAXI B0e7NA==
+ENTRY_END
+RANGE_END
+
+; sentinel does not affect qtypes different than A/AAAA
+; +AD
+STEP 111 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+ENTRY_END
+
+STEP 112 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. IN TXT "it works"
+ENTRY_END
+
+STEP 121 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+ENTRY_END
+
+STEP 122 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN TXT "it works"
+ENTRY_END
+
+; RD only
+STEP 131 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 132 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. IN TXT "it works"
+ENTRY_END
+
+STEP 141 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 142 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN TXT "it works"
+ENTRY_END
+
+; +CD
+STEP 143 QUERY
+ENTRY_BEGIN
+REPLY RD CD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 144 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA CD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN TXT "it works"
+ENTRY_END
+
+; +CD+DO
+STEP 145 QUERY
+ENTRY_BEGIN
+REPLY RD CD DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 146 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA CD DO NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN TXT "it works"
+root-key-sentinel-not-ta-00000.test. IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . SjAFtdUPy+YU4sZnst5GNNYxjzWhBOVq UAfGIUv3uBo5qZW9ePecUJ8GZkNUkdT7 m+cHd0c1ssOBOT7snjwc3Sy3zD22b6/q 3N8VowhDQDPkoDlBvt9raR7eXu273cEB DZTQ9P4Ya2Meu32Aftwa6VMQmXMl+qWX hYqffEt6bJuoohnCVqOZihqgnoT+sRiD l49RgLb+GnZNbFk5EP9LXOrWcdxczKso tY384WCrniRmg4L6NM5DjnBtUVT+Qs6f hWGqQv23fPiLV8lt4i34aIf2jAQkIE6K D4aNLlehct7eqFo1aeaiZumqEd9/GoqS at/RE7Qsh6hiRkfA/J7MLg==
+ENTRY_END
+
+
+; keyid 48409 is trusted
+; is-ta hit for keyid 48409 -> NOERROR
+; +AD
+STEP 211 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+ENTRY_END
+
+STEP 212 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN A 192.0.2.1
+ENTRY_END
+
+; RD only
+STEP 221 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 222 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+
+; not-ta miss for keyid 48409 -> SERVFAIL
+; +AD
+STEP 311 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+ENTRY_END
+
+STEP 312 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA SERVFAIL
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+ENTRY_END
+
+; query without AD must SERVFAIL as well
+STEP 321 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 322 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA SERVFAIL
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+ENTRY_END
+
+; +CD must disable sentinel logic
+STEP 323 QUERY
+ENTRY_BEGIN
+REPLY RD CD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 324 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA CD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN AAAA 2001:db8::
+ENTRY_END
+
+; +CD+DO must disable sentinel logic as well
+STEP 325 QUERY
+ENTRY_BEGIN
+REPLY RD CD DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 326 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA CD DO NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN AAAA 2001:db8::
+root-key-sentinel-not-ta-48409.test. IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . UYk1xmrw2A7ojKSTpwuF90WXsXOfNbRI 8pi9tDPLmqr0OMn29AW051vGTyLd7L3o gsaoUEDiY2vYyvyZI3kPL9fSRDYgOIk7 Cq3hp7k6wMM3IXS6iIlYnjtvUFGDaE69 EpUjwII22lSWaqOo0dCFnacJYWDfShdZ cv7yssWG9nZpki6aiBAjhYXY8tdMnpDJ zq9O3zXPQR8xtuFW4S0aVdrHuSPRq935 DWXThocHxOza6OQp/ZkbemkoqAYjTlu0 tyITwZsTknxgK1mtM+ArRmhSeykqVs3m mAGIWMN3qIW8SXKVRHI9PPjka0j6+KK+ bfmeck0bI2Wu1f3Ccnk+nQ==
+ENTRY_END
+
+
+; keyid 0x0000 is not trusted
+; is-ta miss for keyid 0x0000 -> SERVFAIL
+; +AD
+STEP 411 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN A
+ENTRY_END
+
+STEP 412 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA SERVFAIL
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN A
+ENTRY_END
+
+STEP 422 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+ENTRY_END
+
+STEP 423 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA SERVFAIL
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+ENTRY_END
+
+; +CD must disable sentinel logic
+STEP 424 QUERY
+ENTRY_BEGIN
+REPLY RD CD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+ENTRY_END
+
+STEP 425 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA CD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. IN AAAA 2001:db8::
+ENTRY_END
+
+
+; not-ta hit for keyid 0x0000 -> NOERROR
+STEP 511 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN A
+ENTRY_END
+
+STEP 512 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN A 192.0.2.1
+ENTRY_END
+
+STEP 521 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN AAAA
+ENTRY_END
+
+STEP 522 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN AAAA 2001:db8::
+ENTRY_END
+
+
+; TA for non-root domains are interpreted correctly
+; not-ta ignores existing non-root TA keyid 04759 -> NOERROR
+STEP 611 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-04759.test. IN A
+ENTRY_END
+
+STEP 612 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA AD NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-04759.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-04759.test. 1 IN A 192.0.2.33
+ENTRY_END
+
+; is-ta ignores existing non-root TA keyid 04759 -> SERVFAIL
+STEP 621 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-04759.test. IN A
+ENTRY_END
+
+STEP 622 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA SERVFAIL
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-04759.test. IN A
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.key b/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.key
new file mode 100644
index 0000000..c3e520e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 48409, for .
+; Created: 20180118150418 (Thu Jan 18 16:04:18 2018)
+; Publish: 20170711000000 (Tue Jul 11 02:00:00 2017)
+; Activate: 20171011000000 (Wed Oct 11 02:00:00 2017)
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.private b/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.private
new file mode 100644
index 0000000..bb7de05
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel/K.+008+48409.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: yWIk/wmH9GMvdzx5pSPx3NV0SSwQ0q5upUDkV2sMnasLQ79sYb8xVm35ZpwTWjWZFXBNP9OuGFlQDNn6o5ykH4hbFRGxHi9WpXBqQcyfLsPZotcqhVfBOj9WEBC0cPDkb1vEaDDJs9S13lXPoQh6dSyY1hn5Kl17iXy+nDtQhJUvqrQLWbAcw3Xw//XJ8eZuRLX1voHVL1jZqm61xwXWWyjfKIUiDtQ2qoPg83FKjiMHIOdqNBI/eqD8tIlI6fMEi6ZvzBzqy/GC6DL+nGsEUqAYaTj8l0kIq5919TmMVfh8ncczfsb9Fxyu0aEh/ZnW62g7Joguhr3BPc7VZpgb9Q==
+PublicExponent: AQAB
+PrivateExponent: xnCKqjF3Ia92/1S9Pahc1VIVA2GDtkciSn7WQvn+dYMtV3XSU8N114gIwT68pyC3l3OQ+3sYS2/+vJszKnPZGiVgMzO6x1a4V8+dNPdwSEG/PIIvqTOe+UmeAbikRcJqJv1TXaPtreHF0K/YKANVwA7RD/CKIV/6srEUlpiwL+OcHJFhXIubr5Gru6tNbZGQooblQ7w5x0+01WUti6C3SkO6VROvAE10qmwQ7sRb3scIerkZzOFhO8WimJvyfwPo78RCNBmmCm89uW/yvKw4mgnarg6EwZ7wXgqu7C1ZyY6ailFJB17GTJ+y8xiVUC0HB18WAdBXttceqWpxHW9GZQ==
+Prime1: /El9AUtn4x2DthqwK9GHAHAlCbpKtm8RVRYjRae6Dr3CWDPGqGj0LJSslW8g3SnyNDwXT9Et2kbvR2FsDz5lghgjnCnI0F16VpTYbstfNN6YOBP+50JyZyOvH11C1Phn5HChcmWIvoR+GJkflV7WN03s6IG0aAUg0h9ksubh00c=
+Prime2: zFjfXFwH5vWn2Yn8VA2YPP7qteE0wWXCpbobyQrmRTn95DOEHmrX57V0Pd957OKptYpTQSTMFjdFNVp6NSi6CfZp+8sYpwwK9aI4uCEgNnLLzgz4xmCLs27hnZeDw62vuG/TMBiGwv4+7QpEKLeJ5ZzAessEL/ShEAz84o/SHOM=
+Exponent1: aoouPAm4CXVBVfnXQ+nr9Qdm3MDLJFerHh+HLbczH16LX+wdjKkl1F3EtCaF3mAEZIKr5Y0UrAUgryg5FgbnnxTKlPwgTb3sF/wrmj5QKmeGKMho8Qhif6PWJIyh2IY+eX4G7+Ro5uvUxFaFu/KczCYgUd/Ua8kenx2azOIro6k=
+Exponent2: n8PwRj6x8vInnF5UyMakOzQ2/6Km43oTGA2NAb8i0AcKKOvaJQn16fQlgOaDZiDE/Om8M9d4NPpbgt5NY9iGs5lTvYhJqvkwbGG7pMJJdCiGjX/41OjQ8KYFgXffjhLyqunLHPRgEH5FZoC7T3ZIOxw2JQsrJ+9EKc9tvBkj9m8=
+Coefficient: gNp/tXrqbPKEBmvHV744gOuZxH0D2tMKMu8U/gF0IUjbTQqmaLuLgo9wXVHWo8GpEKbUOB9fbOcoptZlNE1TEF//44IcZH3yJM1JvU3nHW24gIi0xI3B4rQrZej2XpeuFxd44S3LTkeHmZjZB3dnCcgH0CqRTrONMRvW7RqB0bw=
+Created: 20180118150418
+Publish: 20170711000000
+Activate: 20171011000000
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel/root.db b/tests/deckard/sets/resolver/val_ta_sentinel/root.db
new file mode 100644
index 0000000..a6c62f7
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel/root.db
@@ -0,0 +1,61 @@
+; File written on Wed May 30 16:51:51 2018
+; dnssec_signzone version 9.12.0
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+. 518400 IN NS rootns.
+. 518400 IN RRSIG NS 8 0 518400 20180629135151 20180530135151 48409 . ZBLk+sK9ky+YBmzceXbBqEUyBc6nWfAtF6vCK/6cCfL1AxBYOoxdwE/G m0oRAl5WHRrreDSM2t79jcyyUZyyOcee2j/mLPjLdJPQr0Dw9KY+843L o4VSWV0L9adSzgXgvQF/p4yW2zNbHia7doA9GTDjkQFj2+7HgdJdGk8S I2GCx822fqzMCdS3XerIZ4EMz8Lt1sWaexdCgi0sCn9SvqzNHTaIXirW /apL0ohiBNp23LGa7+/7UvNrv+Y/gHpKk2bUytnS7soOocd9XpTekBY7 jlRlmnHTAdn9b9Zj2PHn72v1RYIywP33Qb9ze7i2v7s12uUR3lJt9sd/ WVeuXQ==
+. 86400 IN NSEC rootns. NS SOA RRSIG NSEC DNSKEY
+. 86400 IN RRSIG NSEC 8 0 86400 20180629135151 20180530135151 48409 . J2mHopzSRvmwst3TVDwMS2wG9XDMcJhk9lYMEifgss/Zo+SR8qL8Z8TS zB89UtHAGH+58INk3DnT7tacOKZtbwNx6LFcGO/QXHHN6DwI1rghuGD9 94mQy57Rl5guKesB76HLBBrn0f+elE6lCLYNa0Unqe9XVWHYrcqAmi1K yi1nQgT1DCmmzAg0Yfq5NSkaq4AHO1b8wzkuvl4WoVS8sKpW5K+GtAK0 ox8OwaClFq6QqjXMawcftEnl3aJawS0ftz1ZBolR3889kFpC/xrvTN29 tkUjYNRNjvIYwvinznKjumL2YsMyYWmn/7FCq3NJEAHljxsRCDCW+vl0 oCG2SQ==
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
+. 1814400 IN RRSIG DNSKEY 8 0 1814400 20180629135151 20180530135151 48409 . HRj68PBD0cR2p1njZcMUBecR5DiBbueyhIX1oqc9K9Rig5i+ONuozacm 3F4kg9DhUYb/1W6+PSp9YLyrJtCZOFLqkTjPiOAyiE6zVAE/U5O5LRZ/ FjqRQoWuA1cFZtrLokaWmW9GS5Kb2+PUCJY5NRz27JFSvaRRkoHIFf4o mA6eQsuWt28Itx0VGPL9+mR+2B+IcnmN+DZb7mxoRknOh0WyNop4eiep oSZcCihYHOdesCtmrxoMkwGEHZpu8a6GN7jaeNXXNUulwQYfzUZJZQo1 Zr9cN7kzIZ5tAs9ffnPRcWVO61MQTxUtuGbipFpba6RhGmML8oO4JkOJ Itp6tg==
+root-key-sentinel-is-ta-04759.test. 1 IN A 192.0.2.33
+root-key-sentinel-is-ta-04759.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . B3RxvVwGi4W0SJPOexXga1Bm4nDiL4u/ITn30YXMPg8yOVOFWQ2axvG/ HdMFU6VSzm5GGIh0e+KR9Jzcvyt2yC3081SrclIkque3LJM1Ar5wa3GO 2M1EC3TuKs+L0WjLXfUTGie7n3mYfoiT+QBfZ4v60JQaD4U+UetZ5Ocn 2rXvuC0Rk9LI+j1Us7u2somZy/swl0Luvg4e+bueHRpTAgKf4nLHFZ8A HEAK0Vy3FG0N4q/oPWx1i9hVNxEaJQIwVcW01KDbP2sqFUNUm3bpT8aH fKRK4hy7MKkDsLrkpcbVbhI4vq8D1GKMtiUjU2kRjQ4VEMzXzXHhPcUi jMf7qw==
+root-key-sentinel-is-ta-04759.test. 86400 IN NSEC root-key-sentinel-is-ta-48409.test. A RRSIG NSEC
+root-key-sentinel-is-ta-04759.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . lEBshzTtCWvgkCFB8vyIBnnOoHj2BNxUnGs/zSfDD+pdHuaXQ+cO8Gjb DDt+9ZvzHK+Ijt2sqnC6NuNtjACc6XSiPCGM6zoKOlqrnje5tZoA3OUf 0AYxjSRM1U/IzGv2QEsRv3CRQkddPIeXufzrj/d3PL0kHwD9A0kSSiiW Ch5OBhhLPshzfQTQ3nU1TXDPdzsncpvkDtQLgTS0LQDKh0mp92yNlrpT HqMIPyUXr8e8FbtWQ4Y8fJ+IGxbjt6Ek7oKmL6mowE6B6UWwsy3d4S8c i5fZQSfJhRu7Vq5Kyq8CZLLQw1fZ7/QHacjjUTVaVdnq6ze3J9gdJlnj IdoiIg==
+root-key-sentinel-not-ta-04759.test. 1 IN A 192.0.2.33
+root-key-sentinel-not-ta-04759.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . sUfM6dehUU9p1QnVX9QIT3K2kvKoU9qGTMNKdVz84AdJJMGnqMbosBpE LusmcZtwcGNjU8jcFdal/t03b+z0jk5BoEG0lzgFGNSp1S1sDGHYTcrv hAHmWpN4a0BEV/ZIOuu1ZJ8s0vRajnAB75jpSGsRdPmCTG/TKeAUJoF+ gua4lLlHnDlLnIVXThL3THqWqoTwg7Ch12piwrklZXNHbSsgcKwwG4SB 8OGY13ewXpH90EYkAFgmLIsavY7Ddhu8ZcFiE5nh6JQrwi7rsAtsr3cx x2rJrMTSEGP1F103YLzxyI4sTiIOGLaxQ7rGuASLGDQW5Cy0mKGgUAXI B0e7NA==
+root-key-sentinel-not-ta-04759.test. 86400 IN NSEC root-key-sentinel-not-ta-48409.test. A RRSIG NSEC
+root-key-sentinel-not-ta-04759.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . eMKKf4Itgkz3mxMsl+gz4xUO1xMchTU4INlJkMG4WkgDpINFhu08RrkI AGDuZnsKZwedqCyXmm/pqiAr/IuurIF5XZSL7tocYmtEV1p/unpeKzt/ wzb34Ktm2Sv5Wu/ZgGatg4ddocjhUzVS0QX3DL9qIFCs8U+VJj7wSC6q 1qcSwksYtUmeG3io3UkBuNTqnqpqZRUieBA9XMftpCbdOES/8WdxPI53 59zFBp5TnwJ7y9Wu9ccZv8tI1QBtqz0UdLYMG09QdhoL6rzZUVRZyRpi FFrp4fdEL6perdYZd0awa2nVNCrr9jEwMSxnm5oVbFUY6Tu+M4pdG5d7 JjXUTg==
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+rootns. 86400 IN NSEC root-key-sentinel-is-ta-00000.test. A AAAA RRSIG NSEC
+rootns. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . noqU9JO9z5QXcedzsm7E6RZ5aIIocIH/jSedo6Zy+GImRTeHpc0le399 DUOsqGlcagx7EWRerScB+xmpL7DxKl0FFyeG0ORvPjJ6IyCFTecWjaKW YVurQnzALW+LhfsPSTxBMnnRhxT5Qrw4dtO0gx7fWyssKUnsMcBdmESs tALFNSfJpiV7so9cK2ssHsC+jkM0AQoemSKJrTesxm8FP1BGT27tz/vx yWIlOUGc8/gBgHo4hoXH1oyCrw9KU9kczRqw4CoCGJtZ2/k15BfmbPlC kLrvLibEmp6OYPVWfJRG79uDHhT+Tul07j26WmA+A7IWXSye8W51WbdH 7gJTKQ==
+root-key-sentinel-not-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . YYqLZKzjD13hpj345YTNMYYEh3US2BY7DqK9YbNIZi4T0/0jAEFPamKW WcX0nPm5N5S+1VqKIdo/brqvOTaxsq7HnPxVfomg3wyaKNvwqxb2MUpa pYl25ORa7yOm3gwVZJ3NBjh65dLXzGn8t8b047ym7Fnz6JAJHUyM4/SH hZhvXYBX+i3Lojq7HDIReqAtH7zzWdKzKLCTNqAhuqfvEI3edVynpth2 SCMNDVaAUlzVfBLEAkHNp26mLSgcarc3vrb2khdDS13Kv0Ev4rj0w0v1 z0DnVs95Yl2XlnShzNTaW5w1F8f81oBbq2Ly2POxERr5cOCNSGIWMi+q XAt7bQ==
+root-key-sentinel-not-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . SjAFtdUPy+YU4sZnst5GNNYxjzWhBOVqUAfGIUv3uBo5qZW9ePecUJ8G ZkNUkdT7m+cHd0c1ssOBOT7snjwc3Sy3zD22b6/q3N8VowhDQDPkoDlB vt9raR7eXu273cEBDZTQ9P4Ya2Meu32Aftwa6VMQmXMl+qWXhYqffEt6 bJuoohnCVqOZihqgnoT+sRiDl49RgLb+GnZNbFk5EP9LXOrWcdxczKso tY384WCrniRmg4L6NM5DjnBtUVT+Qs6fhWGqQv23fPiLV8lt4i34aIf2 jAQkIE6KD4aNLlehct7eqFo1aeaiZumqEd9/GoqSat/RE7Qsh6hiRkfA /J7MLg==
+root-key-sentinel-not-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . mHz8sEjHOt+UrLPdGr3s+dake/eRQ6QmushFbLex2e6epkvmriVQwdWa QqG4h75UmjNnOlAwpHJA3oRyKxLJKmVgJIAQzhFc6sHLwEVl+kVyxGfu Q17Md+52E/d+mLMHohKRXljTaghp2uLHX8oDtBP+B2HhIDJK+uhfK63A MZ4k1L4jBGCvEGVMO7BhrpHV9zbY21MOb6EIp/F35jB+ftW7gilKxxBK t+Qt1pwtJcDGVC2xZST6fZ2yaR+U+YhOJ7t9j6WVVTWyFSa1CG3lzyRW PNduZeKYTYwox2uqqUxh+Nmzd1oZt7geIw8CGTYS0B++nVUdNJXJnP51 +evqJQ==
+root-key-sentinel-not-ta-00000.test. 86400 IN NSEC root-key-sentinel-not-ta-04759.test. A TXT AAAA RRSIG NSEC
+root-key-sentinel-not-ta-00000.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . Q7l+lP5MRbXUCszYfJ/x2VUT3C9D3ei8W8/3i/EPoc81J6e35Ny3tbQ9 HH8nzN0Y/4kDtrPjlq42bhwf1J0UZLh2z/Zf1s2/9CSQ/qSUAaD9RY4I eRqHA2As1zjKH9scPDYfKOvvia66xRY5lwT7eH95TbE9Kl+Weerh9Zlq kr4jgofO7DT6UCL+DMAyJZV2qfvdgtYLbs2A4nEWPOriqXdHhsGgnWzr FLZCm4BnY7epaVzzkuC9GnZ3cygZUSc0ArmoIR4dRoQYnq3eYvFrxQ/c No6Yj3coRJGH8nFNmENh1bSuoJCEpcS7jVNd0THMnyRjoly+HYn0nD5V K6Zj2w==
+root-key-sentinel-is-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . qWJh+EE/O2w382vLo53ci9i1O/rAzJUUnZPmLF+GCwmLLhDl6tlI3y5A cALqIHkK1vrXzD+mED78YpILzZ73izRFieY6DxMtAXViqH9U8KSy6KWp tAWUASDe1gj9DGdDeiKdTAIo/2qk1PiGdZNc2E9vQLIUTJNfwV8aZGIt PTgl/efGEIMGGFQW5RPbDZpcJLQ11/RUi9FHQyseZRwkCa8EiEfgvPJ2 /rwiCPUcM6BdYzKoZ53cAHBbeKkvgAOpQ88qDvtE12aF9F8anxdHd0Ru 2DlmrPPthn7/faXSBbBECIbnjNlWTiyF7r274SQKFCrT0rJx5N9c31n4 ZSIocg==
+root-key-sentinel-is-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . tl+oiYdq+UDlh6snkobPI/jQbrPM2tESEyDNIec7wCRvCEo6CLd+oMOA H4P7idKJ1Mey0eMl++YI29Vz2KVAIL0Hiamt32VDXyR5QYVVzNQquH5B /P4PDeoSadK1M+VThnSPT685+CLCbAZfu0Hi7+NulEeQLleBMtSGy0pF eG50H7fecNjqmQ2O/3jKRfD8l86+jba3B2FmpPvsxXgR7Ig5jC/XSpSY 0UMXyntDJz7QOSuhh4GcdNEeUqGVTurqnFjgRmZwReVZqeQzCS8Q+eQn cq23FtXxcAqJCFKN68yoorWmlZhZl0DPm4Zpup28wwlIapO+SGwScD0q KyHZYQ==
+root-key-sentinel-is-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . J4gFrZRSHHDfMoA2zO22H6A55/893OnGO7h3H9znJGZtp7DxT2vxiGJw InBx5/zPubH87rqTa4AkK2GZuDEqVEDU/fjWOjGQOx16V0oeoHi5/R2R sPTzFnb+NvQnQZCRolMHD2keakdzB8b7dfEV80CrRh7uDsiO8aqhSdiV BFJLXFt5qFd+evKw2SG7l9FNMDzukUSAcFIJepM99X7qjQnKsLuzDjyF 4zhgMolAzAwIQzEi4B+G6IQknx5HsvmpNgkbBFjns+Q7ZYutNecPfiYU vaMpSXb5pztCVLbZQEymIXPgsnzdihlMbzh22TZapLbrDBUVEc2yr/QC Tz/CQA==
+root-key-sentinel-is-ta-48409.test. 86400 IN NSEC root-key-sentinel-not-ta-00000.test. A TXT AAAA RRSIG NSEC
+root-key-sentinel-is-ta-48409.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . EDUa6WBV7AoZTNu/kCroCc7ENrSU/v98WlcNy6ZAJk6e46LuBCWQwkKf EKGnJOlUh2Qoq2M24sVkRnWzaOn42IeKI3IlM8LeYVJL6nFpuImotkV4 VGQsiK//Uc1sLXBsj6x1N3xycKG+5bONyv8GSCS5MvzDwtsn0leUnyby 1G9ZKl7DX58GhBDfft++rp3EyALMasUbON4Jl2+7nzgpCfJUrdzogO0N krpqVZoNUybFomcDAQkDpgTeH5I8X0llSZkNWtpHbkwldCO4r+srq3EJ 2nf3GboKky3wMyWF0pg5XAqAYHoPq0Sz+fCog06+87ZsJBIJ0m58INHs ggiBvg==
+root-key-sentinel-is-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . iYK8FfKFt+aD2Mh+hvFxyE0lCs/jHMT8EWlhPGuiPekHkYnbTaRbGJhT sCeL3Cg1MHrtGr8BXSq1RMyKnn6Y0/bhF1nEjk1gB+vAFHUwWe0yX32U H7E139q68ZyrcUkpV+KkY+ltMSKAjBtGRkYZ9sJhFvll7YCD2HtAMPud KEWpTZS2D0fLATDzAJzJF/2qGMvRUIn0sk5+3HqVh7R3stbl4aSEw5Zp swJoSCs1DN5eaLh6Ovas51uDAa4t6Ove6owR/gR9isqdZCbilAaJ6497 xg4r/KsCu6eG7GAAw5XGh8rkpC5YbsCBlXB565Zk5oY4yBgBUiG/iXGC wyLyJA==
+root-key-sentinel-is-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . cGVwlSItiMGEOKkCWRLUn2od/cBvOlSwj8qxCppe4O1FRyTGgEFNV2nf 2zUkhL/agQhXI3qEjFOkq2b1l+4dM3BwDOF7IGhS3yXV3JGnIcwOC7si EMjRZGIvcEenjfugpIwkwkhTZdgIFoyCUr+g6YxA3iL6L77dftAmIkAV 6gvyarwgeYs0Wi+eEGfrZp2MxJjHDXKF+NfCy/fJnYx2n8SRpXya/Uu+ DJ+S4FQDTDyjDhN/+Tvcsb++sjvNfA4ZDwx5gpgNkRF0xsLHMoxCQagH gJBBziP0cq7l2fy5FVMpGNvdkkiYYG8to/2FF/65GhV+RuNcotD91zyW aeSxWw==
+root-key-sentinel-is-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . QNF7LtVeew75AhniJ7S0ncsmrHWHCnRcU0H3uyCipyL20kHlpc1NOIUY md7BB02MXm+XOpJF/l/uc9v/C0iuAgOpFVp5kVjtp+gTu2mgceXstFuP 3tNmrL2pSRIWaN8+koS0MlAZCrH9+J9RSFrm5twtD7bIvGT0FVvy/RrR pRWPy9hbqjH6O5DFMdksdVTPLEYFXevAHGKvRa5beRXkrL9ANfVzvPYl q2RaO1aMX6+Cy7AquJpU7DUSReEUBr1f7mYVdd/6sjzoXrd893c+2Fc+ WFLVuWER3eTSrLAQ3b3Etz0lqM3MLrEXwjQFl2mw046nlh21T+u2Ds5s s1/b8g==
+root-key-sentinel-is-ta-00000.test. 86400 IN NSEC root-key-sentinel-is-ta-04759.test. A TXT AAAA RRSIG NSEC
+root-key-sentinel-is-ta-00000.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . GS5Rur2pdMmvGTJZ6WnDO6RzF1MRF34M5VBvUaBIYn2XqVt7toHL4P8i 7ZXqgiWPLsR/dma4MMphXGZac624kOoCHq2hc0q7ja/8FVbBwaGGIlFN v1XHkv490pjAc+NUtcxnhm+jnT8Wb7/wv5wG1Zd3hblP4opCpANOvoC0 MqyOe8vEW1lcw5KEcE0yKAksarVgAZmmXwkQ4caC9yIG/WC9gJ3fQ70Q Dio74WRERLDS3ShLfRkc0vXr5aUGBuy0mqV4OG3ioRj2jvafxgH6Ov9h g4GYL/aJycGIJZGeXGMR0OGalz+pe8WfzNtSWEuE4l22fPnM6Ne0RfaU 5K4CkQ==
+unsigned. 86400 IN NS rootns.
+unsigned. 86400 IN NSEC . NS RRSIG NSEC
+unsigned. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . Di6tfHcpredaWGazWKUX26zYKQ+Yw34BCO2vtqufvcAZJN6PhyXct+Px cvfPN5WxTWlcXVbj6xJKYTOe/ItgV4TM1G2SzGrzTB4qs8ybSvECT59h FUUXTM5ZeXqQVIKKuhVJlmWYSneOiuQG0w6wWr/xE+sD+LE5xQ+hnWrp Z3YAbCmFdtCTwDVt8DkN3i30zExEWc/CnQj9gFYWIBPQ22OB1sfjbZSe 85ucMhUjTas7pZki7b716ZhokApLSf5mVjktjHVT+lPpivs/L2KaQKAe 2yKi05bInFJ+FHU29YoZ3zkBTd2+MeKOh9/1O+9O+hCA+yzLiSLG06Xa 1F7Pcg==
+; resign=20180629135151
+root-key-sentinel-not-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . N1vrpd062YN/PGLOmdAdgPOc2iPPBadtv+DlqoCJ8OUEtFH605m7AUlX HDV99dpT7j6I/N+Sp6pDMRIRl+rB/tFXNfQFoB7UliAsKQ9UuKxH/uyc /sZWxPmYb+4Xi1AKmkzvp7M3Babq7hTGG/PnngN3386Qd0MXiw11Tdl9 +HIan1Jz2jMrHuR2NZDILZOW10wYogYD3/DAx6bVaJMjDbIky5ikK2H/ 4QajIhtjuux4GfsFc7KjGzT1/Hqa9LqdsLetvQmKF4yGNjizOgnrHlbF GoICQ1KihXF3IGYcBUyIoMcmhAjz6D0/jQz/Blwx3zvEUj2Hf7Xj+haO ShdguQ==
+root-key-sentinel-not-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . NLK3/UMZZ+39KgwbFFoS6qR2QTEULMxDhlWpK1is+AU3CjUn1RNPRJaq m1MnfJdEq3+FFwVDkpmDGh8lQfTBn192oWlo2goHXZXwuoFN49FPHZ+l u42NWMDKtmS6r9JemJR68jH0jy/AsTMdvAbeodg06cbY6F5Q80EtAdkZ iOZPnqPenfxI+U8C2KgBNas7izGbQZF3FxHi7GZz+wrCGBcjcYX9pcD9 /rf1plZYudefFbxG+P97WfMScDD5vt0dUxz3Yt6YUC48jlyo9WYZDLC5 3qOuqah5oXS1lCGJDm+Kta4koVnm6W4pbCzT9XISwRWZ81rp0NbTrhHb Teu7Pw==
+root-key-sentinel-not-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . UYk1xmrw2A7ojKSTpwuF90WXsXOfNbRI8pi9tDPLmqr0OMn29AW051vG TyLd7L3ogsaoUEDiY2vYyvyZI3kPL9fSRDYgOIk7Cq3hp7k6wMM3IXS6 iIlYnjtvUFGDaE69EpUjwII22lSWaqOo0dCFnacJYWDfShdZcv7yssWG 9nZpki6aiBAjhYXY8tdMnpDJzq9O3zXPQR8xtuFW4S0aVdrHuSPRq935 DWXThocHxOza6OQp/ZkbemkoqAYjTlu0tyITwZsTknxgK1mtM+ArRmhS eykqVs3mmAGIWMN3qIW8SXKVRHI9PPjka0j6+KK+bfmeck0bI2Wu1f3C cnk+nQ==
+root-key-sentinel-not-ta-48409.test. 86400 IN NSEC unsigned. A TXT AAAA RRSIG NSEC
+root-key-sentinel-not-ta-48409.test. 86400 IN RRSIG NSEC 8 2 86400 20180629135151 20180530135151 48409 . DKB8iFwqz4u0QaAe/0ppPv3AzvvNVQGAfCnxfbdKkYGCjFZMtuNMef1u YsJLyY5MSS5AiNr+gAJpRrBnYnobGe4ibL2hG/HV41282p7PMu2BiCiE EZw2sTLeMjEyq+yVk5fciL/1/SwNr+fYKj9sTuzUC7L8LIndRoufuEvJ zi7PhWN6NUlWLr4X5o63a2TZqxCtS61/VUkVScfRfNKHs70SF89rXMYQ uaaUSSERcUwGBf1x1qpA7HL/8v4IwbWcLBXv44mTUIaJYvqqwCPbWJHm 5rX0J1UUYObJjj4RrPL1fxW5rZ5XNdtkKfteJLiDvNzBozX11HyTBq6E WtpJSQ==
+; resign=20180629135151
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel_insecure.rpl b/tests/deckard/sets/resolver/val_ta_sentinel_insecure.rpl
new file mode 100644
index 0000000..f22583c
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel_insecure.rpl
@@ -0,0 +1,376 @@
+stub-addr: 2001:503:ba3e::2:30
+trust-anchor: . IN DS 48409 8 2 3D63A0C25BCE86621DE63636F11B35B908EFE8E9381E0E3E9DEFD89EA952C27D
+val-override-date: 20180601000000
+; avoid the mess with one server for both "." and "unsigned."
+query-minimization: on
+CONFIG_END
+
+SCENARIO_BEGIN draft-ietf-dnsop-kskroll-sentinel-12 section 2 where root key matches but test domain is insecure
+
+
+RANGE_BEGIN 1 1000
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 198.41.0.4
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN SOA
+SECTION ANSWER
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
+. 1814400 IN RRSIG DNSKEY 8 0 1814400 20180629135151 20180530135151 48409 . HRj68PBD0cR2p1njZcMUBecR5DiBbueyhIX1oqc9K9Rig5i+ONuozacm 3F4kg9DhUYb/1W6+PSp9YLyrJtCZOFLqkTjPiOAyiE6zVAE/U5O5LRZ/ FjqRQoWuA1cFZtrLokaWmW9GS5Kb2+PUCJY5NRz27JFSvaRRkoHIFf4o mA6eQsuWt28Itx0VGPL9+mR+2B+IcnmN+DZb7mxoRknOh0WyNop4eiep oSZcCihYHOdesCtmrxoMkwGEHZpu8a6GN7jaeNXXNUulwQYfzUZJZQo1 Zr9cN7kzIZ5tAs9ffnPRcWVO61MQTxUtuGbipFpba6RhGmML8oO4JkOJ Itp6tg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS rootns.
+. 518400 IN RRSIG NS 8 0 518400 20180629135151 20180530135151 48409 . ZBLk+sK9ky+YBmzceXbBqEUyBc6nWfAtF6vCK/6cCfL1AxBYOoxdwE/G m0oRAl5WHRrreDSM2t79jcyyUZyyOcee2j/mLPjLdJPQr0Dw9KY+843L o4VSWV0L9adSzgXgvQF/p4yW2zNbHia7doA9GTDjkQFj2+7HgdJdGk8S I2GCx822fqzMCdS3XerIZ4EMz8Lt1sWaexdCgi0sCn9SvqzNHTaIXirW /apL0ohiBNp23LGa7+/7UvNrv+Y/gHpKk2bUytnS7soOocd9XpTekBY7 jlRlmnHTAdn9b9Zj2PHn72v1RYIywP33Qb9ze7i2v7s12uUR3lJt9sd/ WVeuXQ==
+SECTION ADDITIONAL
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+rootns. 86400 IN NSEC root-key-sentinel-is-ta-00000.test. A AAAA RRSIG NSEC
+rootns. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . noqU9JO9z5QXcedzsm7E6RZ5aIIocIH/jSedo6Zy+GImRTeHpc0le399 DUOsqGlcagx7EWRerScB+xmpL7DxKl0FFyeG0ORvPjJ6IyCFTecWjaKW YVurQnzALW+LhfsPSTxBMnnRhxT5Qrw4dtO0gx7fWyssKUnsMcBdmESs tALFNSfJpiV7so9cK2ssHsC+jkM0AQoemSKJrTesxm8FP1BGT27tz/vx yWIlOUGc8/gBgHo4hoXH1oyCrw9KU9kczRqw4CoCGJtZ2/k15BfmbPlC kLrvLibEmp6OYPVWfJRG79uDHhT+Tul07j26WmA+A7IWXSye8W51WbdH 7gJTKQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN A
+SECTION ANSWER
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN AAAA
+SECTION ANSWER
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+; The delegation here is slightly hacky
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+unsigned. IN NS
+SECTION ANSWER
+unsigned. 86400 IN NS rootns.
+SECTION AUTHORITY
+unsigned. 86400 IN NSEC . NS RRSIG NSEC
+unsigned. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . Di6tfHcpredaWGazWKUX26zYKQ+Yw34BCO2vtqufvcAZJN6PhyXct+Px cvfPN5WxTWlcXVbj6xJKYTOe/ItgV4TM1G2SzGrzTB4qs8ybSvECT59h FUUXTM5ZeXqQVIKKuhVJlmWYSneOiuQG0w6wWr/xE+sD+LE5xQ+hnWrp Z3YAbCmFdtCTwDVt8DkN3i30zExEWc/CnQj9gFYWIBPQ22OB1sfjbZSe 85ucMhUjTas7pZki7b716ZhokApLSf5mVjktjHVT+lPpivs/L2KaQKAe 2yKi05bInFJ+FHU29YoZ3zkBTd2+MeKOh9/1O+9O+hCA+yzLiSLG06Xa 1F7Pcg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+unsigned. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+unsigned. 86400 IN NSEC . NS RRSIG NSEC
+unsigned. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . Di6tfHcpredaWGazWKUX26zYKQ+Yw34BCO2vtqufvcAZJN6PhyXct+Px cvfPN5WxTWlcXVbj6xJKYTOe/ItgV4TM1G2SzGrzTB4qs8ybSvECT59h FUUXTM5ZeXqQVIKKuhVJlmWYSneOiuQG0w6wWr/xE+sD+LE5xQ+hnWrp Z3YAbCmFdtCTwDVt8DkN3i30zExEWc/CnQj9gFYWIBPQ22OB1sfjbZSe 85ucMhUjTas7pZki7b716ZhokApLSf5mVjktjHVT+lPpivs/L2KaQKAe 2yKi05bInFJ+FHU29YoZ3zkBTd2+MeKOh9/1O+9O+hCA+yzLiSLG06Xa 1F7Pcg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. 1 IN TXT "it works"
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. 1 IN TXT "it works"
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.unsigned. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.unsigned. 1 IN TXT "it works"
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.unsigned. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.unsigned. 1 IN TXT "it works"
+ENTRY_END
+
+RANGE_END
+
+
+; sentinel does not affect qtypes different than A/AAAA
+STEP 111 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN TXT
+ENTRY_END
+
+STEP 112 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. IN TXT "it works"
+ENTRY_END
+
+STEP 121 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN TXT
+ENTRY_END
+
+STEP 122 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. IN TXT "it works"
+ENTRY_END
+
+STEP 131 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.unsigned. IN TXT
+ENTRY_END
+
+STEP 132 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.unsigned. IN TXT "it works"
+ENTRY_END
+
+STEP 141 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.unsigned. IN TXT
+ENTRY_END
+
+STEP 142 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.unsigned. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.unsigned. IN TXT "it works"
+ENTRY_END
+
+; _is-ta does not affect queries when we do not have TA for root
+STEP 211 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN A
+ENTRY_END
+
+STEP 212 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+STEP 221 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN AAAA
+ENTRY_END
+
+STEP 222 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.unsigned. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+; _not-ta does not affect queries when we do not have TA for root
+STEP 311 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN A
+ENTRY_END
+
+STEP 312 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. 1 IN A 192.0.2.1
+ENTRY_END
+
+STEP 322 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN AAAA
+ENTRY_END
+
+STEP 323 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.unsigned. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.unsigned. IN AAAA 2001:db8::
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_ta_sentinel_nokey.rpl b/tests/deckard/sets/resolver/val_ta_sentinel_nokey.rpl
new file mode 100644
index 0000000..6485991
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_ta_sentinel_nokey.rpl
@@ -0,0 +1,361 @@
+stub-addr: 2001:503:ba3e::2:30
+; no trust-anchor for the root domain
+val-override-date: 20180601000000
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN draft-ietf-dnsop-kskroll-sentinel-12 section 2 with no root TA
+
+
+RANGE_BEGIN 1 1000
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 198.41.0.4
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN SOA
+SECTION ANSWER
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 1814400 IN DNSKEY 257 3 8 AwEAAcliJP8Jh/RjL3c8eaUj8dzVdEksENKubqVA5FdrDJ2rC0O/bGG/ MVZt+WacE1o1mRVwTT/TrhhZUAzZ+qOcpB+IWxURsR4vVqVwakHMny7D 2aLXKoVXwTo/VhAQtHDw5G9bxGgwybPUtd5Vz6EIenUsmNYZ+Spde4l8 vpw7UISVL6q0C1mwHMN18P/1yfHmbkS19b6B1S9Y2aputccF1lso3yiF Ig7UNqqD4PNxSo4jByDnajQSP3qg/LSJSOnzBIumb8wc6svxgugy/pxr BFKgGGk4/JdJCKufdfU5jFX4fJ3HM37G/RccrtGhIf2Z1utoOyaILoa9 wT3O1WaYG/U=
+. 1814400 IN RRSIG DNSKEY 8 0 1814400 20180629135151 20180530135151 48409 . HRj68PBD0cR2p1njZcMUBecR5DiBbueyhIX1oqc9K9Rig5i+ONuozacm 3F4kg9DhUYb/1W6+PSp9YLyrJtCZOFLqkTjPiOAyiE6zVAE/U5O5LRZ/ FjqRQoWuA1cFZtrLokaWmW9GS5Kb2+PUCJY5NRz27JFSvaRRkoHIFf4o mA6eQsuWt28Itx0VGPL9+mR+2B+IcnmN+DZb7mxoRknOh0WyNop4eiep oSZcCihYHOdesCtmrxoMkwGEHZpu8a6GN7jaeNXXNUulwQYfzUZJZQo1 Zr9cN7kzIZ5tAs9ffnPRcWVO61MQTxUtuGbipFpba6RhGmML8oO4JkOJ Itp6tg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS rootns.
+. 518400 IN RRSIG NS 8 0 518400 20180629135151 20180530135151 48409 . ZBLk+sK9ky+YBmzceXbBqEUyBc6nWfAtF6vCK/6cCfL1AxBYOoxdwE/G m0oRAl5WHRrreDSM2t79jcyyUZyyOcee2j/mLPjLdJPQr0Dw9KY+843L o4VSWV0L9adSzgXgvQF/p4yW2zNbHia7doA9GTDjkQFj2+7HgdJdGk8S I2GCx822fqzMCdS3XerIZ4EMz8Lt1sWaexdCgi0sCn9SvqzNHTaIXirW /apL0ohiBNp23LGa7+/7UvNrv+Y/gHpKk2bUytnS7soOocd9XpTekBY7 jlRlmnHTAdn9b9Zj2PHn72v1RYIywP33Qb9ze7i2v7s12uUR3lJt9sd/ WVeuXQ==
+SECTION ADDITIONAL
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN NS
+SECTION AUTHORITY
+. 86400 IN SOA rootns. you.test. 2017071101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20180629135151 20180530135151 48409 . vb9XrP5h9Ojhqbs1Rbdiwxvje/TVFafSZlLf372zpYdtSBI6f7x++GYI WNiUG8EFtchEmL8KNsrWbujpa8tXeWXtatW92kG1qZAnOA40Zw1DjnI8 ZI7volYyq/TMmufKcoNAXU2knAmpZhHDZ+TBOc5HK6TwKeQaRQ6hPwxB JKOjXw2mVjQFP5lck2m2LU9a7iubYRvncRDHmqfjJ9XsSfWi1AU2fmk/ ei/bhKnFMWVH2PXtQlsbxRS8+8SaEL6f4rQC1JqwQ8E03SAZdK7oJKOf GRRFOfYOx7JucTwiV18LAa/j0owSMvuPwYjGnk6BY7e4LTMK2vPgJ3yY lqLmTw==
+rootns. 86400 IN NSEC root-key-sentinel-is-ta-00000.test. A AAAA RRSIG NSEC
+rootns. 86400 IN RRSIG NSEC 8 1 86400 20180629135151 20180530135151 48409 . noqU9JO9z5QXcedzsm7E6RZ5aIIocIH/jSedo6Zy+GImRTeHpc0le399 DUOsqGlcagx7EWRerScB+xmpL7DxKl0FFyeG0ORvPjJ6IyCFTecWjaKW YVurQnzALW+LhfsPSTxBMnnRhxT5Qrw4dtO0gx7fWyssKUnsMcBdmESs tALFNSfJpiV7so9cK2ssHsC+jkM0AQoemSKJrTesxm8FP1BGT27tz/vx yWIlOUGc8/gBgHo4hoXH1oyCrw9KU9kczRqw4CoCGJtZ2/k15BfmbPlC kLrvLibEmp6OYPVWfJRG79uDHhT+Tul07j26WmA+A7IWXSye8W51WbdH 7gJTKQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN A
+SECTION ANSWER
+rootns. 518400 IN A 198.41.0.4
+rootns. 518400 IN RRSIG A 8 1 518400 20180629135151 20180530135151 48409 . QtR9Z2uVwFVlLy5xQzMVmhqdzZw5cSFbq3xOzhr42gkoD9BYfNyTuhz9 57Sc7kvyJalBHaq3OKoYvE+4anjR8bXk20nGvVjzRdiiqavK41yUpbxC xvo5fWUMj5Bg860AcApn4OOLdFjyKOjJX7ro7QvFdA/adt9WEwhQ3AJ9 PN+SHqtx35F49OUbgiNUEbShJ2VyjOL5bt41LZgffkjim+VB2OtO1hDG CqrKyUlbZ0vxGJhtVflt1Jj3atArHfHz4cuFJHLtSu9PK9piYlSQ54XH vPk0YZ2iKK9sNrVF50Vb7NmLFBCVPn/op0Kmr+u6QVREP6uWayoPtqab /NKvwQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rootns. IN AAAA
+SECTION ANSWER
+rootns. 518400 IN AAAA 2001:503:ba3e::2:30
+rootns. 518400 IN RRSIG AAAA 8 1 518400 20180629135151 20180530135151 48409 . bs+zTG/nH7uQrgW5qfY5p25uXNoPOsH94K/xNVSLm9h1165/AMekPPd8 KVPnCfyZLPhO+/XyZ5fDUd/2iMCT5m/HyjXR0+j92r6f9ePfAJVQX6U0 DJUa882LgYK7k4usmIIWpi66bpGDC1tlJF3WQ4G12Hc/cUmFTMDBTcM8 6CPPDoT00JZQL8u/66GwNYkWw4mmbiq9UAz03R7A983dUx2GLCAmXoGR Lr3hI3btZa5x+GdJhw5t6Mqi58tXSZfUmT7kpCw+K0H/RscQaVDaOLc6 kzBeVn/Lip60ZSd84kiNWKuSA56TfUbpk7VJclY8UI34COHQqNtD+lev wJ1WgQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . qWJh+EE/O2w382vLo53ci9i1O/rAzJUUnZPmLF+GCwmLLhDl6tlI3y5A cALqIHkK1vrXzD+mED78YpILzZ73izRFieY6DxMtAXViqH9U8KSy6KWp tAWUASDe1gj9DGdDeiKdTAIo/2qk1PiGdZNc2E9vQLIUTJNfwV8aZGIt PTgl/efGEIMGGFQW5RPbDZpcJLQ11/RUi9FHQyseZRwkCa8EiEfgvPJ2 /rwiCPUcM6BdYzKoZ53cAHBbeKkvgAOpQ88qDvtE12aF9F8anxdHd0Ru 2DlmrPPthn7/faXSBbBECIbnjNlWTiyF7r274SQKFCrT0rJx5N9c31n4 ZSIocg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . J4gFrZRSHHDfMoA2zO22H6A55/893OnGO7h3H9znJGZtp7DxT2vxiGJw InBx5/zPubH87rqTa4AkK2GZuDEqVEDU/fjWOjGQOx16V0oeoHi5/R2R sPTzFnb+NvQnQZCRolMHD2keakdzB8b7dfEV80CrRh7uDsiO8aqhSdiV BFJLXFt5qFd+evKw2SG7l9FNMDzukUSAcFIJepM99X7qjQnKsLuzDjyF 4zhgMolAzAwIQzEi4B+G6IQknx5HsvmpNgkbBFjns+Q7ZYutNecPfiYU vaMpSXb5pztCVLbZQEymIXPgsnzdihlMbzh22TZapLbrDBUVEc2yr/QC Tz/CQA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . tl+oiYdq+UDlh6snkobPI/jQbrPM2tESEyDNIec7wCRvCEo6CLd+oMOA H4P7idKJ1Mey0eMl++YI29Vz2KVAIL0Hiamt32VDXyR5QYVVzNQquH5B /P4PDeoSadK1M+VThnSPT685+CLCbAZfu0Hi7+NulEeQLleBMtSGy0pF eG50H7fecNjqmQ2O/3jKRfD8l86+jba3B2FmpPvsxXgR7Ig5jC/XSpSY 0UMXyntDJz7QOSuhh4GcdNEeUqGVTurqnFjgRmZwReVZqeQzCS8Q+eQn cq23FtXxcAqJCFKN68yoorWmlZhZl0DPm4Zpup28wwlIapO+SGwScD0q KyHZYQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . N1vrpd062YN/PGLOmdAdgPOc2iPPBadtv+DlqoCJ8OUEtFH605m7AUlX HDV99dpT7j6I/N+Sp6pDMRIRl+rB/tFXNfQFoB7UliAsKQ9UuKxH/uyc /sZWxPmYb+4Xi1AKmkzvp7M3Babq7hTGG/PnngN3386Qd0MXiw11Tdl9 +HIan1Jz2jMrHuR2NZDILZOW10wYogYD3/DAx6bVaJMjDbIky5ikK2H/ 4QajIhtjuux4GfsFc7KjGzT1/Hqa9LqdsLetvQmKF4yGNjizOgnrHlbF GoICQ1KihXF3IGYcBUyIoMcmhAjz6D0/jQz/Blwx3zvEUj2Hf7Xj+haO ShdguQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . UYk1xmrw2A7ojKSTpwuF90WXsXOfNbRI8pi9tDPLmqr0OMn29AW051vG TyLd7L3ogsaoUEDiY2vYyvyZI3kPL9fSRDYgOIk7Cq3hp7k6wMM3IXS6 iIlYnjtvUFGDaE69EpUjwII22lSWaqOo0dCFnacJYWDfShdZcv7yssWG 9nZpki6aiBAjhYXY8tdMnpDJzq9O3zXPQR8xtuFW4S0aVdrHuSPRq935 DWXThocHxOza6OQp/ZkbemkoqAYjTlu0tyITwZsTknxgK1mtM+ArRmhS eykqVs3mmAGIWMN3qIW8SXKVRHI9PPjka0j6+KK+bfmeck0bI2Wu1f3C cnk+nQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-48409.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . NLK3/UMZZ+39KgwbFFoS6qR2QTEULMxDhlWpK1is+AU3CjUn1RNPRJaq m1MnfJdEq3+FFwVDkpmDGh8lQfTBn192oWlo2goHXZXwuoFN49FPHZ+l u42NWMDKtmS6r9JemJR68jH0jy/AsTMdvAbeodg06cbY6F5Q80EtAdkZ iOZPnqPenfxI+U8C2KgBNas7izGbQZF3FxHi7GZz+wrCGBcjcYX9pcD9 /rf1plZYudefFbxG+P97WfMScDD5vt0dUxz3Yt6YUC48jlyo9WYZDLC5 3qOuqah5oXS1lCGJDm+Kta4koVnm6W4pbCzT9XISwRWZ81rp0NbTrhHb Teu7Pw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . iYK8FfKFt+aD2Mh+hvFxyE0lCs/jHMT8EWlhPGuiPekHkYnbTaRbGJhT sCeL3Cg1MHrtGr8BXSq1RMyKnn6Y0/bhF1nEjk1gB+vAFHUwWe0yX32U H7E139q68ZyrcUkpV+KkY+ltMSKAjBtGRkYZ9sJhFvll7YCD2HtAMPud KEWpTZS2D0fLATDzAJzJF/2qGMvRUIn0sk5+3HqVh7R3stbl4aSEw5Zp swJoSCs1DN5eaLh6Ovas51uDAa4t6Ove6owR/gR9isqdZCbilAaJ6497 xg4r/KsCu6eG7GAAw5XGh8rkpC5YbsCBlXB565Zk5oY4yBgBUiG/iXGC wyLyJA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . QNF7LtVeew75AhniJ7S0ncsmrHWHCnRcU0H3uyCipyL20kHlpc1NOIUY md7BB02MXm+XOpJF/l/uc9v/C0iuAgOpFVp5kVjtp+gTu2mgceXstFuP 3tNmrL2pSRIWaN8+koS0MlAZCrH9+J9RSFrm5twtD7bIvGT0FVvy/RrR pRWPy9hbqjH6O5DFMdksdVTPLEYFXevAHGKvRa5beRXkrL9ANfVzvPYl q2RaO1aMX6+Cy7AquJpU7DUSReEUBr1f7mYVdd/6sjzoXrd893c+2Fc+ WFLVuWER3eTSrLAQ3b3Etz0lqM3MLrEXwjQFl2mw046nlh21T+u2Ds5s s1/b8g==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-is-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . cGVwlSItiMGEOKkCWRLUn2od/cBvOlSwj8qxCppe4O1FRyTGgEFNV2nf 2zUkhL/agQhXI3qEjFOkq2b1l+4dM3BwDOF7IGhS3yXV3JGnIcwOC7si EMjRZGIvcEenjfugpIwkwkhTZdgIFoyCUr+g6YxA3iL6L77dftAmIkAV 6gvyarwgeYs0Wi+eEGfrZp2MxJjHDXKF+NfCy/fJnYx2n8SRpXya/Uu+ DJ+S4FQDTDyjDhN/+Tvcsb++sjvNfA4ZDwx5gpgNkRF0xsLHMoxCQagH gJBBziP0cq7l2fy5FVMpGNvdkkiYYG8to/2FF/65GhV+RuNcotD91zyW aeSxWw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN A 192.0.2.1
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG A 8 2 1 20180629135151 20180530135151 48409 . YYqLZKzjD13hpj345YTNMYYEh3US2BY7DqK9YbNIZi4T0/0jAEFPamKW WcX0nPm5N5S+1VqKIdo/brqvOTaxsq7HnPxVfomg3wyaKNvwqxb2MUpa pYl25ORa7yOm3gwVZJ3NBjh65dLXzGn8t8b047ym7Fnz6JAJHUyM4/SH hZhvXYBX+i3Lojq7HDIReqAtH7zzWdKzKLCTNqAhuqfvEI3edVynpth2 SCMNDVaAUlzVfBLEAkHNp26mLSgcarc3vrb2khdDS13Kv0Ev4rj0w0v1 z0DnVs95Yl2XlnShzNTaW5w1F8f81oBbq2Ly2POxERr5cOCNSGIWMi+q XAt7bQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN AAAA 2001:db8::
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG AAAA 8 2 1 20180629135151 20180530135151 48409 . mHz8sEjHOt+UrLPdGr3s+dake/eRQ6QmushFbLex2e6epkvmriVQwdWa QqG4h75UmjNnOlAwpHJA3oRyKxLJKmVgJIAQzhFc6sHLwEVl+kVyxGfu Q17Md+52E/d+mLMHohKRXljTaghp2uLHX8oDtBP+B2HhIDJK+uhfK63A MZ4k1L4jBGCvEGVMO7BhrpHV9zbY21MOb6EIp/F35jB+ftW7gilKxxBK t+Qt1pwtJcDGVC2xZST6fZ2yaR+U+YhOJ7t9j6WVVTWyFSa1CG3lzyRW PNduZeKYTYwox2uqqUxh+Nmzd1oZt7geIw8CGTYS0B++nVUdNJXJnP51 +evqJQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. 1 IN TXT "it works"
+root-key-sentinel-not-ta-00000.test. 1 IN RRSIG TXT 8 2 1 20180629135151 20180530135151 48409 . SjAFtdUPy+YU4sZnst5GNNYxjzWhBOVqUAfGIUv3uBo5qZW9ePecUJ8G ZkNUkdT7m+cHd0c1ssOBOT7snjwc3Sy3zD22b6/q3N8VowhDQDPkoDlB vt9raR7eXu273cEBDZTQ9P4Ya2Meu32Aftwa6VMQmXMl+qWXhYqffEt6 bJuoohnCVqOZihqgnoT+sRiDl49RgLb+GnZNbFk5EP9LXOrWcdxczKso tY384WCrniRmg4L6NM5DjnBtUVT+Qs6fhWGqQv23fPiLV8lt4i34aIf2 jAQkIE6KD4aNLlehct7eqFo1aeaiZumqEd9/GoqSat/RE7Qsh6hiRkfA /J7MLg==
+ENTRY_END
+
+RANGE_END
+
+
+; sentinel does not affect qtypes different than A/AAAA
+STEP 111 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+ENTRY_END
+
+STEP 112 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. IN TXT "it works"
+ENTRY_END
+
+STEP 121 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+ENTRY_END
+
+STEP 122 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN TXT "it works"
+ENTRY_END
+
+STEP 131 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 132 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-is-ta-00000.test. IN TXT "it works"
+ENTRY_END
+
+STEP 141 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+ENTRY_END
+
+STEP 142 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-00000.test. IN TXT
+SECTION ANSWER
+root-key-sentinel-not-ta-00000.test. IN TXT "it works"
+ENTRY_END
+
+; _is-ta does not affect queries when we do not have TA for root
+STEP 211 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+ENTRY_END
+
+STEP 212 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN A 192.0.2.1
+ENTRY_END
+
+STEP 221 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 222 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-is-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-is-ta-48409.test. 1 IN AAAA 2001:db8::
+ENTRY_END
+
+; _not-ta does not affect queries when we do not have TA for root
+STEP 311 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+ENTRY_END
+
+STEP 312 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN A
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN A 192.0.2.1
+ENTRY_END
+
+STEP 322 QUERY
+ENTRY_BEGIN
+REPLY RD AD
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+ENTRY_END
+
+STEP 323 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY QR RD RA NOERROR
+MATCH opcode rcode flags question answer
+SECTION QUESTION
+root-key-sentinel-not-ta-48409.test. IN AAAA
+SECTION ANSWER
+root-key-sentinel-not-ta-48409.test. IN AAAA 2001:db8::
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_unalgo_ds.rpl b/tests/deckard/sets/resolver/val_unalgo_ds.rpl
new file mode 100644
index 0000000..919c856
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unalgo_ds.rpl
@@ -0,0 +1,202 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 20009 7 1 9222285F81978C50F77DA894956E77BDCAD281F0 "
+val-override-date: "20181220170056"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with unknown algorithm delegation
+; DS has unknown algo only.
+; so subzone has to be treated as unsigned.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20190119150056 20181220150056 20009 example.com. j8376QAQiddoeX7srgtEIo61o+HTctzVFwJUtWPWHJpk20oez5HaGKHE HrOhk4MZQ5fAmtr6a83yEX4hGPvEQJCjUZBBHRHTwC50sxEPFumdV28j +jW5avFhIgkIX9uuiPbYkrh/1l6rhHtPLX8Q8OqkFMkIhFGVYfaxFIvg 4bU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20190119150056 20181220150056 20009 example.com. eHFRaqW2U4dTQhLc0CIB/JuUpoNdThLzMvXxEfIQkMdKGbxrv93q90lq xFoohvm+ODFtE6rK9ABOXwK3FycPc0sSzaXX2waNGmXOSTAMCjHj9MKv ATThTPhSpTS72qCwa6dlfno/SALheLCPX0NE/jxRAwM4fyaysqXwIPcs U0k= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbqb9jXzpXYl+9sTJ88ra4EHRrDxFcprKz3cu26/yY+3Vhq4oDSr VngEkZI3m9rMasBoGa85mHByLvt16crazzLNwGpC6dbUSz37tL+F2Wra 1N+o+yy56BRL8tteLFKGTMyzq3NCkTbXuNrdE//rkByNrKUZz/VeTK8Y z3CkMyNd ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20190119150056 20181220150056 20009 example.com. gDHM55rE/2AqgKnmvpQZTWNEWWvx+41mnBB2pH/n3SyKFre73eswv0n8 0HeJU6A3CIDj3LQxdCmz8nf4tUt1oTfBMejROM1NgdRdGWdZeojVzXH2 /bszvyFV+whX3qryw+5UL6/lo0aF8V6vsTepBeIs7GCvdEZqzKBzyRP8 42E= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20190119150056 20181220150056 20009 example.com. j8376QAQiddoeX7srgtEIo61o+HTctzVFwJUtWPWHJpk20oez5HaGKHE HrOhk4MZQ5fAmtr6a83yEX4hGPvEQJCjUZBBHRHTwC50sxEPFumdV28j +jW5avFhIgkIX9uuiPbYkrh/1l6rhHtPLX8Q8OqkFMkIhFGVYfaxFIvg 4bU= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20190119150056 20181220150056 20009 example.com. eHFRaqW2U4dTQhLc0CIB/JuUpoNdThLzMvXxEfIQkMdKGbxrv93q90lq xFoohvm+ODFtE6rK9ABOXwK3FycPc0sSzaXX2waNGmXOSTAMCjHj9MKv ATThTPhSpTS72qCwa6dlfno/SALheLCPX0NE/jxRAwM4fyaysqXwIPcs U0k= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+; algorithm 208 is unknown.
+sub.example.com. 3600 IN DS 31953 208 1 84464F35C846F53CB48251175EB351BDAAD48953
+sub.example.com. 3600 IN RRSIG DS 7 3 3600 20190119150756 20181220150756 20009 example.com. PPiE0aTaIWVV9JjoDRiliQjvyuFiehO3APeMjOMW4z/++rtLGnr66Uf7 M+0411UEndgx4/vuBqMqz6eXeivkgeKVxgoBz51OF2blNKM8JGOcgoOM mB5vjQ07DpNtVSQltDWffvLM8Meifj5shgY1m7dbiS1FHKreaQoT90nz a14= ;{id = 2854}
+;sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20190119150056 20181220150056 31953 sub.example.com. pnikDTPPngQdMmFi4RZKDEmmaTdobIYTvop2Tw8LPD2kI9LLr2IkNHn9 dP/CqTrW7Lay0824cMBJ4sHbkN2hm3cP9PPWe+5mnnuPSgPgBd4n2vpQ /RE2sxskWiwoEjIjg9+5AaipctC5Gt2jeHpqv9nA+5TA9Cyw7yUdcWzM u7E= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20190119150056 20181220150056 31953 sub.example.com. KAWpoyn0rmTzd/NMNUuEf3J0LP6vP5rmm+6TuuFjfapVssIHsQ5jCcE8 L5n/qr4nn21HVqFJgjcdmnSqWlI5kICBeQacvOA7zHyGuxI3vaf+k0m+ SdxzpBYAdWFZpTCbfd7REgVJPk3WXR4aTVO92s/JMO8xmMKSq/CjmGBd IMQ= ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AwEAAa346cld5d0e37nm5x0ic42TOBDBlSl9VhlwforF/dQCQoZmp7Ak gG3b9RVJwUQvNvtS1y9jl1IGrXbrt0HcDOKRHKYyONkk12ZVcZzxS9dC FZAe7IX6Id1N8RwEVYaJFHCiEAmL6HcpSLP2B8cfa7ey5zeZD+Wz/yXo a9MCT6WR ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20190119150056 20181220150056 31953 sub.example.com. mk+IKcijVYZ/Qp1oC7u4fLzj/fVh/yt93cdRXHr8mtrg0YbbStdJKKWr f6dEAYLXmUa6V1tFwNn/w2vg9RM2qRK+4TylxYLfVVTpOFAhg93mqgX8 rKMlTJ97MqYy0KspIXobrQaS/fap9229cMNeQyJXMfdhNrj8HU/U3fIX dAs= ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20190119150056 20181220150056 31953 sub.example.com. pnikDTPPngQdMmFi4RZKDEmmaTdobIYTvop2Tw8LPD2kI9LLr2IkNHn9 dP/CqTrW7Lay0824cMBJ4sHbkN2hm3cP9PPWe+5mnnuPSgPgBd4n2vpQ /RE2sxskWiwoEjIjg9+5AaipctC5Gt2jeHpqv9nA+5TA9Cyw7yUdcWzM u7E= ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20190119150056 20181220150056 31953 sub.example.com. KAWpoyn0rmTzd/NMNUuEf3J0LP6vP5rmm+6TuuFjfapVssIHsQ5jCcE8 L5n/qr4nn21HVqFJgjcdmnSqWlI5kICBeQacvOA7zHyGuxI3vaf+k0m+ SdxzpBYAdWFZpTCbfd7REgVJPk3WXR4aTVO92s/JMO8xmMKSq/CjmGBd IMQ= ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20190119150056 20181220150056 31953 sub.example.com. XjoXosfFOUyNzvNKM/CjiepBA9fmdkpMWF3nP7rlQyb91nZsNbxqreEB U7YepFJlAyWAK7ODbkH9LxPd+dXKAnR/1NUTPi43GzSt1W/g5YbBOrFf BqVEV6FGsLu8fX/qNQfFnzTbLk6brw7IlN6SlEkxUnTZyHqwtTY+s2Cm Iww= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20190119150056 20181220150056 31953 sub.example.com. XjoXosfFOUyNzvNKM/CjiepBA9fmdkpMWF3nP7rlQyb91nZsNbxqreEB U7YepFJlAyWAK7ODbkH9LxPd+dXKAnR/1NUTPi43GzSt1W/g5YbBOrFf BqVEV6FGsLu8fX/qNQfFnzTbLk6brw7IlN6SlEkxUnTZyHqwtTY+s2Cm Iww= ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure.rpl b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure.rpl
new file mode 100644
index 0000000..b206290
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure.rpl
@@ -0,0 +1,161 @@
+stub-addr: 198.41.0.4
+trust-anchor: . IN DS 17002 8 2 775F52082C6A93154F15799C7BC9A47C0DA27C9828BA1EBAEAE5C1F685E69839
+query-minimization: no
+val-override-date: 20170801000000
+CONFIG_END
+
+SCENARIO_BEGIN Test DNSSEC with unknown algorithm
+
+
+RANGE_BEGIN 10 40
+ ADDRESS 198.41.0.4
+ ADDRESS 2001:503:ba3e::2:30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 86400 IN DNSKEY 257 3 8 AwEAAaw5/EVELuakk5srRepPzmDsF0doS/HpE9QBEn0xqRteeRFENh74 WZjO7Zc8QeH0uKDeVXLhG0akgbjnwlAu3P225pZN4ovq0ep3MRU3Wm5t nvsD43D7QH3UdYe6I04aH+8TtAUBDiiKX5IQq6qcYIPk+xXzd3kk4kmQ wV7OnAeZBqHA2ezViSL2p+h14oZ+zvFSd2ohFN3T5RJIlCfT0mNVa+Xh V2dORjR9/gTd9WPdZj/mmLlpw4tf0HBnCRVjryvAeXgy33WZMChLVwmi Ve3FGKBgkYYjxyBVpgFvIgLPmpJiC28XSleNzfYIAU+3ntti+zCIcI7y eKYmT8mQFB0=
+. 86400 IN RRSIG DNSKEY 8 0 86400 20170815084229 20170716084229 17002 . XwUIQY7CBOvvjWiFDjH8fDY3csUTyDiixrgXPCvrK5bY5Z4HKEyPhe0p msVdtFG8h8//L3F8VG7DRJIm737aUUoDknXBvK/MdxdYMzKc2aaW8I8O yznz6Y4H91qVuUD7kxli+VUXIWfB6a/X6CdZFL+EfXo0SF1DVPMJvGLl 5FCJ+QRRknyZV16J5bhcMz42H8McKdNMABrHuK+rROhkhcwY0jH2sQFi 6LH4raijw06aR4ABtGXqo8N/L0+7kyakYR9ToBFng3yQhfncumzSARzK jL+bLKC+7kKu/fX+kmKRxOsrrUBEmQrZpuWuBoyDHWRoYTluvH8KqWcl r1WTFw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS rootns.
+. 518400 IN RRSIG NS 8 0 518400 20170815084229 20170716084229 17002 . UcQ6SwMvSPPp5R75aY11RLKpbcoJMZIByS8FSkYRhi7wav6kJufiwi3+ +CcM3waQiNMadXsqJxY7brykJkuoTjqz+/n7jV2/F63t9Ntx7k2VPVE+ pqN19bu+24Vq6AQfkBDWwP8fzIxtUIP8Yn/UUTsTA9eV7Bgtk462Fhxc hdac3D3jleit1mnpbdep3F0EmtDb50jWDUDpQzYU0N6X1ApbOV1cNdpY v2Bx4w5rR+qmSyRwHWlTcsnbVeoplIs3hxcorhIv7EGt0wAIBAKCPV+/ ecp3il7/oYpHqfIhRvzCuLkVjIdJYC1gfBSbp9/uSVVqgu9euS7yGnTy AWNamQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+rootns. IN A
+SECTION ANSWER
+rootns. 1 IN A 198.41.0.4
+rootns. 1 IN RRSIG A 8 1 1 20170815084229 20170716084229 17002 . XEdMJ2jS5yOY8hecBZDv2oPpmzFucfW08OPlXdoIvtRVyGI7gWXdnYYC ic2pO/w1cKX4NjzeE8wEiYztz2X6hECh7lEz6gf+sb1j4Z1rjdc/Wbue qwucEOs9LJ+P+6DUeBr0jVYR9Pr55IitDVyvx+aa8jlmTDJO+CUNhBMe cLErM2vWRJ3bYbS6N6o3lV2quGjDimpIfg2esa47A2sTRB4zsnlqH3dQ 6iFlUrIRyfgMxFxf9A/WbLwrp9aFOg069HmKdAAN49ITz2lMwIxb6gYO S2KJM9GSaYOGVfyVf0TvGmBYs5sD2bwyFwEBrVH7Z+I8PgGVpXRO+jtw FICQJg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+rootns. IN AAAA
+SECTION ANSWER
+rootns. 1 IN AAAA 2001:503:ba3e::2:30
+rootns. 1 IN RRSIG AAAA 8 1 1 20170815084229 20170716084229 17002 . gT1s+QQ6wubnvZkmYYO6nARX6wCjq8PATMqmXhlVqQXRZcayHq9FcnHA xBA+ZPpvbJXJSmiyDwNw09g/5mvuo1v9ZMzWoRh+qnGJ/rplD/sukDmw 4xNvTi+LV/MdGg7fid/wVpycYXZTy/+6eeE3obWrgi7i6OMdzDQlm0/u sifQt8M3aFi8gQvSIZ8cJ6Yo69hZ/X1Kh27ce5H0eOOoj/TxcI4UISEw OrJDAYzNLYHQivLzj/UJePKS3xLrHpagsAYt6JQlCYJJWubXyutOkshj rY1EwVrNJ3wgLdFwBToCymtto9HO+X4oZJIT17KwJpQ3OAwZvcBQM0gs w7hvtw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test. IN SOA
+SECTION ANSWER
+test. 86400 IN SOA rootns. you.test. 2017071100 1800 900 604800 86400
+test. 86400 IN RRSIG SOA 253 1 86400 20170815084229 20170716084229 12062 test. UNUSABLE==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test. IN DS
+SECTION ANSWER
+test. 1 IN DS 12062 253 2 E18BD6A9E00A75C0FE17CFBB300AF4A34C1F3F1CCADDF56646007565 8396477A
+test. 1 IN RRSIG DS 8 1 1 20170815084229 20170716084229 17002 . KIbj4XGbPWamI8atPM2x5EzAQu2KC+raKS5AYBuX+blxyOrIYtVhSc1Z poauPhDbofYNAMu9KqZmQkNjaOW9i5Z9NmGXQgTmC5l0TfGC4mc3a21E 3ykuQlVqVfOIkEvA+1boA19mGYw0IQ6MAP6NazDNvsOepCTAxyh0U5Va CvoD3QQMwSHImvhUwbC3Lao2kOIuIHVF1zge4SK+m9eBg6LCqtcD8nJJ gHIdO7r/o+d9miXjjfztRR0ZTaJGz4tZKXgOLJYxDcgjxLXF6unSB68e 1jsa+BncWwyvvkP75VZ9EvCpBgfCGdwg0eujFaRwa3PE1/nPqUaCgael 1qzbXQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test. IN DNSKEY
+SECTION ANSWER
+test. 86400 IN DNSKEY 257 3 253 UNUSABLE==
+test. 86400 IN RRSIG DNSKEY 253 0 86400 20170815084229 20170716084229 12062 test. UNUSABLE==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test2. IN SOA
+SECTION ANSWER
+test2. 86400 IN SOA rootns. you.test2. 2017071100 1800 900 604800 86400
+test2. 86400 IN RRSIG SOA 255 1 86400 20170815084229 20170716084229 12062 test2. UNUSABLE==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test2. IN DS
+SECTION ANSWER
+test2. 1 IN DS 12062 8 255 E18BD6A9E00A75C0FE17CFBB300AF4A34C1F3F1CCADDF56646007565 8396477A
+test2. 1 IN RRSIG DS 8 1 1 20170816080814 20170717080814 17002 . QKmpsz0Q+9n9GiVdyLosxo9gxNRWDR9RrZho5iYW+8TMkW/T4o5ifkjc 79BQkz48hEjrtKF4qvzWjSnM2YMnSGO63pjngjXSPw6zIoBuEihM9Tf/ SAvJfBFdf3m3XYfF5lleC1GbJfSxCLy8KTepS2JhZo6fvNQ+TfPOOBQT eWAVPaxd2VzbuHMz8mkF8QaNLZJhuaJ7EFx6UzcoDpBL5Lv7uPqtm/Nk ovfmu/NxOkbWsrijiB3YwcP5b/V9Qfgkt27P9o8PFx/u3NzSmirRrvm9 C0apwznU+h2xBQ8hy3VlDxkGeS4IA7cH6o7EeLmuIV7MqLsWmAfhNd6J uuVQ4Q==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+test2. IN DNSKEY
+SECTION ANSWER
+test2. 86400 IN DNSKEY 257 3 255 UNUSABLE==
+test2. 86400 IN RRSIG DNSKEY 255 0 86400 20170815084229 20170716084229 12062 test2. UNUSABLE==
+ENTRY_END
+
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test. IN SOA
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+test. IN SOA
+SECTION ANSWER
+test. 86400 IN SOA rootns. you.test. 2017071100 1800 900 604800 86400
+ENTRY_END
+
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test2. IN SOA
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+test2. IN SOA
+SECTION ANSWER
+test2. 86400 IN SOA rootns. you.test2. 2017071100 1800 900 604800 86400
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.key b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.key
new file mode 100644
index 0000000..83fa74f
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 17002, for .
+; Created: 20170716090354 (Sun Jul 16 11:03:54 2017)
+; Publish: 20170716090354 (Sun Jul 16 11:03:54 2017)
+; Activate: 20170716090354 (Sun Jul 16 11:03:54 2017)
+. IN DNSKEY 257 3 8 AwEAAaw5/EVELuakk5srRepPzmDsF0doS/HpE9QBEn0xqRteeRFENh74 WZjO7Zc8QeH0uKDeVXLhG0akgbjnwlAu3P225pZN4ovq0ep3MRU3Wm5t nvsD43D7QH3UdYe6I04aH+8TtAUBDiiKX5IQq6qcYIPk+xXzd3kk4kmQ wV7OnAeZBqHA2ezViSL2p+h14oZ+zvFSd2ohFN3T5RJIlCfT0mNVa+Xh V2dORjR9/gTd9WPdZj/mmLlpw4tf0HBnCRVjryvAeXgy33WZMChLVwmi Ve3FGKBgkYYjxyBVpgFvIgLPmpJiC28XSleNzfYIAU+3ntti+zCIcI7y eKYmT8mQFB0=
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.private b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.private
new file mode 100644
index 0000000..c68d3b0
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/K.+008+17002.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: rDn8RUQu5qSTmytF6k/OYOwXR2hL8ekT1AESfTGpG155EUQ2HvhZmM7tlzxB4fS4oN5VcuEbRqSBuOfCUC7c/bbmlk3ii+rR6ncxFTdabm2e+wPjcPtAfdR1h7ojThof7xO0BQEOKIpfkhCrqpxgg+T7FfN3eSTiSZDBXs6cB5kGocDZ7NWJIvan6HXihn7O8VJ3aiEU3dPlEkiUJ9PSY1Vr5eFXZ05GNH3+BN31Y91mP+aYuWnDi1/QcGcJFWOvK8B5eDLfdZkwKEtXCaJV7cUYoGCRhiPHIFWmAW8iAs+akmILbxdKV43N9ggBT7ee22L7MIhwjvJ4piZPyZAUHQ==
+PublicExponent: AQAB
+PrivateExponent: F2eB2r/bR8iRroKA68iQmSc8Op33xBYSdbr3kj/PZUK/XRNR7398XYGxU94Cbfxdoq7UGdpxZHYykrgb9d2IdooGZ+KJqM3uXNh5uRJenacT9bSfkdjy+KaImjs3VQPD1y9sRUnRbLzxI95UFclObF4PqPn/AF18ytZ7ELEvDvEJifyxT80VDKx27LWEUrI2xbNMS+BKF4K/RAXWbbuv60oTuBsi+txKehVw+rFNTum6omFJlYVOIXg+kXp3XH4XfXNze6in85ju4V2EbJ/uRjfQPShQFCpboQN1t+W5K9gXQGtD+OqPQGLI1fAb6iUNjKnt+mG7O9XqjMLoUyq2wQ==
+Prime1: 3Tz87rRCofb+IBdD5c3rZwSxDXGTYyaT0tWxBAXMvN2DkvvC+H2pRR784opawatfDhthm/eyNbI1qFYPmufAEge+73md2RnXAb2SWlFDuYLQsRNiyX0CUwjyeZrsgNkXMfyEY3HZcEKYnGqcRXqzdGRjLTukFVFMeeHOtywRg3k=
+Prime2: x0mQ8im68tlfY/ezTvtro3xaEd0Oh1oX696B/dW8allStZxeUz4PUjDQaXzcilnWFgbbc8s8E7f7iB44l4sEe94Saf+c6X3TAw+0n8GAC0DBSIk9GV6MGiN8gVSlqtVnmsJKTL+ZBm+7fyJrDE9TZRyyzs9cHiRgpudeZ/ojKMU=
+Exponent1: XRqZZus9T2PeNisUS9WIx2XWDM5LNGK7uvJq+EJokuK1yFljB6f6YDhWPA/1eaNg8VLclQJ8YNSKeDkfgBUfY3cXBzirEP4q2XSp7pBca+l9YcfCvwB4xfDx+fMUrHSvqj2WiTMUSoX8K3dCJIsqkkTc5+A9gSshf/ljQPqutCE=
+Exponent2: A071WQ/YSq/RJZe3IliKMOyfkixZUWXtf7zx64Tg2+MfvGQcLMWa+4JT82xfPOzA4Ry8B/AXzzv+sQPPbLSiHmxRYfEcacPs/OAF36EWvxkUHGAq44DuUoDEUGFXXr6sOaWAFkYYBENWmYW4wTuP5t3TGhvXK6ju8dZletRsQQE=
+Coefficient: hQUsEUXSZVHOlJM2Hwkkk01K0Ns4z/KOOl4EKz9UK2rt4hC7ZC48Phg40sIk81NIrChNytXkHR7VYTT4DMWX9iz8J4mgKqV8xiaYHV+ggqdW54QLg1/kRe//kn2vT3NYRakFcC1nB3fdvc2BqTZPvIIUF+CZITvy+L2oQQWiqc8=
+Created: 20170716090354
+Publish: 20170716090354
+Activate: 20170716090354
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/root_unknown_ds_algo_and_digest.db b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/root_unknown_ds_algo_and_digest.db
new file mode 100644
index 0000000..8ec23cf
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/root_unknown_ds_algo_and_digest.db
@@ -0,0 +1,11 @@
+. 86400 IN SOA rootns. you.test. 2017071100 1800 900 604800 86400
+
+. 518400 IN NS rootns.
+test. 518400 IN NS rootns.
+test2. 518400 IN NS rootns.
+
+rootns. 1 IN A 198.41.0.4
+rootns. 1 IN AAAA 2001:503:ba3e::2:30
+
+test. IN DS 12062 253 2 E18BD6A9E00A75C0FE17CFBB300AF4A34C1F3F1CCADDF566460075658396477A
+test2. IN DS 12062 8 255 E18BD6A9E00A75C0FE17CFBB300AF4A34C1F3F1CCADDF566460075658396477A
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test.db b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test.db
new file mode 100644
index 0000000..d35184e
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test.db
@@ -0,0 +1,5 @@
+test. 86400 IN SOA rootns. you.test. 2017071100 1800 900 604800 86400
+
+test. 518400 IN NS rootns.
+
+test. 86000 IN DNSKEY 257 3 253 aGVsbG93b3JsZAo=
diff --git a/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test2.db b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test2.db
new file mode 100644
index 0000000..872f988
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unknown_algorithm_insecure/test2.db
@@ -0,0 +1,5 @@
+test2. 86400 IN SOA rootns. you.test2. 2017071100 1800 900 604800 86400
+
+test2. 518400 IN NS rootns.
+
+test2. 86000 IN DNSKEY 257 3 253 aGVsbG93b3JsZAo=
diff --git a/tests/deckard/sets/resolver/val_unsecds.rpl b/tests/deckard/sets/resolver/val_unsecds.rpl
new file mode 100644
index 0000000..f530c42
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unsecds.rpl
@@ -0,0 +1,193 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 63707 7 1 26D2BF1DF3D9D9FAE39BD1CD501F9FADD2BE9B54 "
+val-override-date: "20181130121927"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with insecure delegation
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101927 20181130101927 63707 example.com. sVrUoXjVsHFV9WiQzbSaRmib8MyTFeaTwaQfDblAGpOULYd0MMHnkFmm 7WFrpyOhoAsYA5D56fKFZaahzsPjEB9xKhnaYROCUAu0rSTy7WTrUlo7 sBj+S5KEDag2UuAr+BlBaH2lzTAUJ639aMRuxbYL1J3Iz3Ik1Ek+jOu2 cN4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101927 20181130101927 63707 example.com. XIyIWLbcpJNlJ5VtaCxDp39vTXZrBgOG2+0RSBMJVcAxhTfUXRwOHGq8 7Gv3c1QAw8kecxmV+c18momoPV+xOscFAlodGzPVbHeiOHpUsTCWyplt VF0RsyYmztV6NIpX0URekh2PIDFlyN+BwFk6LB9gtwzv9UyXxn0ToEKa J1A= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcryZrR8pLOukbTLkfJG6fnZueJ0wg2t4JhAyBhsO3dx6c13dMzm DkiJ7ta5aPBXveWIR0Y616V8a6K9OZgrA828IHU6ExqjLnsLomUuWoLh bCoED1Ie4hgsH/J8lJIpBmEK1WzDZM9GY4IVkM3lZugt9gOys2IkQRXp 0Xa2jWE7 ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101927 20181130101927 63707 example.com. eHCaXqQmpmMxKbjEG3OvplZHpUGoY9+jVoJ201VIr8pA6nrOrdysoWos X/vDpyVukA7jOoswubGh2fsSnQj8wEHRxXN6dSA/TdyPy8jbeai5mg5l 2bg8LZpzHN6tV3YdJ0ck6VBiQp8F69shBgyV9YtoFrnE2jH19f1mmFWV Ggw= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101927 20181130101927 63707 example.com. sVrUoXjVsHFV9WiQzbSaRmib8MyTFeaTwaQfDblAGpOULYd0MMHnkFmm 7WFrpyOhoAsYA5D56fKFZaahzsPjEB9xKhnaYROCUAu0rSTy7WTrUlo7 sBj+S5KEDag2UuAr+BlBaH2lzTAUJ639aMRuxbYL1J3Iz3Ik1Ek+jOu2 cN4= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101927 20181130101927 63707 example.com. XIyIWLbcpJNlJ5VtaCxDp39vTXZrBgOG2+0RSBMJVcAxhTfUXRwOHGq8 7Gv3c1QAw8kecxmV+c18momoPV+xOscFAlodGzPVbHeiOHpUsTCWyplt VF0RsyYmztV6NIpX0URekh2PIDFlyN+BwFk6LB9gtwzv9UyXxn0ToEKa J1A= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101927 20181130101927 63707 example.com. SUVC+aUQJUyJX+4pSpD813Y7uPy34DpRN8y0FzmaLnGKvwaKQ4DiQY6J 8LtDFFZ8ExHVUa6xzHpGwX+KixZCj/dCUBZVv8HCkSpMLmtakC7XIFyD ojKIkxJoCbzG77r8JXgv3QyvvItgbpkjZkNClWyGd1HOgMhsnBg6oHcs w8M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; query for missing DS record.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101927 20181130101927 63707 example.com. W8OD1Z8xF+OfFDDD/F55RcMJvGduXXavFTlFCxM9H0Tis8rKgtil55eh B6ArRrLAik1NM7zE2oUMdZRx3fkCdIIuii96ceqhApbohZ0R4m8dQWr+ JGKCFXOsoNVYeyxg6Ohg/em5Hh3zdeHk7p+6XcXwv7Hncx033LH9TNr5 A58= ;{id = 2854}
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101927 20181130101927 63707 example.com. SUVC+aUQJUyJX+4pSpD813Y7uPy34DpRN8y0FzmaLnGKvwaKQ4DiQY6J 8LtDFFZ8ExHVUa6xzHpGwX+KixZCj/dCUBZVv8HCkSpMLmtakC7XIFyD ojKIkxJoCbzG77r8JXgv3QyvvItgbpkjZkNClWyGd1HOgMhsnBg6oHcs w8M= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_unsecds_negcache.rpl b/tests/deckard/sets/resolver/val_unsecds_negcache.rpl
new file mode 100644
index 0000000..28cd6d4
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unsecds_negcache.rpl
@@ -0,0 +1,194 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 21095 7 1 1A16E6CECEBF9305C5AB107B5BD5993BFF8716C5 "
+val-override-date: "20181130121925"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with insecure delegation and DS negative cache
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101925 20181130101925 21095 example.com. W2tTjoEHLswOuMEbbkRAUV3yacfvMGWiVk4Dow+tF1+yeVDGmhk+5+Pm XNJJ4KJQ3caIWjoQicEj4yUIwb7bRA4awFGbC4NoXMlx7c1rWSZ/HRf3 Iw2BuBFP+74GS/c+HMDQAL3qfkJXKToGYJq/5IfUxOYwOnus8ia9ecAB K5A= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101925 20181130101925 21095 example.com. EyF7Iiq36OLwYxp4sMaecCI/sAFrfDIg75XepCMwr8yVW+LdST0dVA9j 6tls8QaEDg5raQhtJB2RtTHe2NmvAt2pPOH+bil5zpri4FO9fAZA7B4q I9UgzxyG+eej+Ee7TgBBsw7I72kPZuv2FCGuoTqXmVNIpr5vDJ/V/q3M lkk= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAcE4pogrNoVZ7QNbp63zNoH6uzv+Ohz66upXmXfe9xFEYEYjmqI8 QEYCkuY+s7YgfoukU+XIigoE7dl8FgVyFH2rm3j76raYT+hJzKQJt4T1 B6oiSO8SR6V2fghmbxE8+L3uWjsE2n3LzzKRNM4x9nYpqLbAVLjgWCh2 4NcAXnbn ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101925 20181130101925 21095 example.com. SWWwowWn1/R2gXg4oUXL5K/71YtgYj2Q8pj10DRLGW5ZDomkbvVw9jin FaHbMgRAB+1WoY+lsbHdF3gwtva8w9QulAdn+stJeCypIS3tR0oDFIqC rR5DbiduTrS0qE/AfITERWDYtXVmQwqV4FG3L0W6j7ak4/Hj7rZjlx/a juE= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101925 20181130101925 21095 example.com. W2tTjoEHLswOuMEbbkRAUV3yacfvMGWiVk4Dow+tF1+yeVDGmhk+5+Pm XNJJ4KJQ3caIWjoQicEj4yUIwb7bRA4awFGbC4NoXMlx7c1rWSZ/HRf3 Iw2BuBFP+74GS/c+HMDQAL3qfkJXKToGYJq/5IfUxOYwOnus8ia9ecAB K5A= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101925 20181130101925 21095 example.com. EyF7Iiq36OLwYxp4sMaecCI/sAFrfDIg75XepCMwr8yVW+LdST0dVA9j 6tls8QaEDg5raQhtJB2RtTHe2NmvAt2pPOH+bil5zpri4FO9fAZA7B4q I9UgzxyG+eej+Ee7TgBBsw7I72kPZuv2FCGuoTqXmVNIpr5vDJ/V/q3M lkk= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101925 20181130101925 21095 example.com. Xkw2D18bwT1N9/584gwEPiMmUYjJgWCBqax8HIhvCHF2bSdSwAk1ZXDN muy7gkLTTkCb+J9pfkcwsr7j0HqNb8h3FJoF+vfgT3vSMx6V7kATkSVa wR/pllcYDoCq99/Y0fMdHAbGLE5fhoRCqv/6GkMic6rSIjI3RfcQ1y2p D7U= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; query for missing DS record.
+; get it from the negative cache instead!
+;ENTRY_BEGIN
+;MATCH opcode qtype qname
+;ADJUST copy_id
+;REPLY QR NOERROR
+;SECTION QUESTION
+;sub.example.com. IN DS
+;SECTION ANSWER
+;SECTION AUTHORITY
+;example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+;example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854}
+;sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+;sub.example.com. 3600 IN RRSIG NSEC 7 3 3600 20181230101925 20181130101925 21095 example.com. Xkw2D18bwT1N9/584gwEPiMmUYjJgWCBqax8HIhvCHF2bSdSwAk1ZXDN muy7gkLTTkCb+J9pfkcwsr7j0HqNb8h3FJoF+vfgT3vSMx6V7kATkSVa wR/pllcYDoCq99/Y0fMdHAbGLE5fhoRCqv/6GkMic6rSIjI3RfcQ1y2p D7U= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.sub.example.com. IN A 1.2.3.6
+;ENTRY_END
+
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. 3600 IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_unsecds_qtypeds.rpl b/tests/deckard/sets/resolver/val_unsecds_qtypeds.rpl
new file mode 100644
index 0000000..6e99715
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_unsecds_qtypeds.rpl
@@ -0,0 +1,209 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 47879 7 1 E0A42C63E663B5FD45A89D4B10AE2B8CC68A73EA "
+val-override-date: "20181130121926"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with insecure delegation and qtype DS.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101926 20181130101926 47879 example.com. MMAsjQBG4R8DD0lll4nK7IGv0olKacqEXSPobc4VH51ci+C0k0lxzlew IF/euSnmhV/AF2Y3cypNO8eC/ngpkXFEBMKGKo48t5zDBZcdRBu200oF ZSeX9bJuEwTJ98rtzIBIeD5TRNsC3ZMRjaT4pcngTgdWnslhxvl4gAp8 UOs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101926 20181130101926 47879 example.com. oUK4kGg2QKG7XtIvfRlMOqLrdJyvcZGSAFZf5Trczn20xF8JA7s7X38J ZmgZyKPm7nY5i4BSYj2qhld+T0taOrw2dTeRpSa0z1/DNXnz2F97SWhd zkFS8g+idBtP/GbaLt/oNc5fndSzTUsmMYWBi843ub+60ghiLF1ZG1L+ qrU= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAdf/3DGUDLH9AyZf8VTjS4W83QqnKvcEIPyy5JlxuG63Oytmc82s Xo+Tzf35mIKWzfzEDlaTUuKf16eaGN3IYB5kehh4tKqP1gXWWMmegFzg NhfXOR0utxgJHXdTY/wdBUrKEIuYemZYU7s5DXKx4GGqDeRTmgkUQpO6 V3FtN3Cv ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101926 20181130101926 47879 example.com. zJ7IPV9PSF7xqbZnQeiKzoo/ziklv1wvSqKnV7a/aojdAGfSNv0fRCro lcfn5lwiGeLN9UR71MNc4ynZgxxH2pSzoogU0ic40nye25oe1hR4QlBb 6hNBkuZn7LU6/+ovxfZVYsYEO7HvXhkNoRnb72amPAr+IMItifjSf+0l +Ec= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101926 20181130101926 47879 example.com. MMAsjQBG4R8DD0lll4nK7IGv0olKacqEXSPobc4VH51ci+C0k0lxzlew IF/euSnmhV/AF2Y3cypNO8eC/ngpkXFEBMKGKo48t5zDBZcdRBu200oF ZSeX9bJuEwTJ98rtzIBIeD5TRNsC3ZMRjaT4pcngTgdWnslhxvl4gAp8 UOs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101926 20181130101926 47879 example.com. oUK4kGg2QKG7XtIvfRlMOqLrdJyvcZGSAFZf5Trczn20xF8JA7s7X38J ZmgZyKPm7nY5i4BSYj2qhld+T0taOrw2dTeRpSa0z1/DNXnz2F97SWhd zkFS8g+idBtP/GbaLt/oNc5fndSzTUsmMYWBi843ub+60ghiLF1ZG1L+ qrU= ;{id = 2854}
+ENTRY_END
+
+; query for missing DS record.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101926 20181130101926 47879 example.com. FhZjZ1FHaz3TuZFJWoN/eBI3XaY9ZLPjMUKdJ4jSZmGs/OzyU9Dcg6yA QwyeqZ1bN0O+eLDfJc8SpNhEne/Yx9xlll2ITSpdExjHHx3m+/f7ZOOV W2wZDHFlj7r906znxzf4oZCVxsnnsHh/4E1ciPBumeFU8vcL1KTo8WL3 kSA= ;{id = 2854}
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101926 20181130101926 47879 example.com. pKjqniTOtDqZtoB79vxB4i7utCRwgXq5Hys2ZNhFd4fLNEnbDppX6dQ1 L2DslNkxCChV4l2Y7dCw1Zo8zhxLiaOCjz28TJR8yRIqTVKZqPs/Ui34 ZsO3uUAF4ZC4eV3lO7pvSeXS5ZJiSVbUQ+zAO4eSHrcaRvt4RPlfzTj3 y20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101926 20181130101926 47879 example.com. pKjqniTOtDqZtoB79vxB4i7utCRwgXq5Hys2ZNhFd4fLNEnbDppX6dQ1 L2DslNkxCChV4l2Y7dCw1Zo8zhxLiaOCjz28TJR8yRIqTVKZqPs/Ui34 ZsO3uUAF4ZC4eV3lO7pvSeXS5ZJiSVbUQ+zAO4eSHrcaRvt4RPlfzTj3 y20= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; query for missing DS record. on wrong side of zone cut.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN SOA ns.sub.example.com. h.sub.example.com. 2007090504 1800 1800 2419200 7200
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200
+example.com. 3600 IN RRSIG SOA 7 2 3600 20181230101926 20181130101926 47879 example.com. FhZjZ1FHaz3TuZFJWoN/eBI3XaY9ZLPjMUKdJ4jSZmGs/OzyU9Dcg6yA QwyeqZ1bN0O+eLDfJc8SpNhEne/Yx9xlll2ITSpdExjHHx3m+/f7ZOOV W2wZDHFlj7r906znxzf4oZCVxsnnsHh/4E1ciPBumeFU8vcL1KTo8WL3 kSA= ;{id = 2854}
+sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC
+sub.example.com. 3600 IN RRSIG NSEC 7 3 7200 20181230101926 20181130101926 47879 example.com. pKjqniTOtDqZtoB79vxB4i7utCRwgXq5Hys2ZNhFd4fLNEnbDppX6dQ1 L2DslNkxCChV4l2Y7dCw1Zo8zhxLiaOCjz28TJR8yRIqTVKZqPs/Ui34 ZsO3uUAF4ZC4eV3lO7pvSeXS5ZJiSVbUQ+zAO4eSHrcaRvt4RPlfzTj3 y20= ;{id = 2854}
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_wild_pos.rpl b/tests/deckard/sets/resolver/val_wild_pos.rpl
new file mode 100644
index 0000000..cef2d8b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos.rpl
@@ -0,0 +1,161 @@
+; config options
+; The island of trust is at example.com
+;server:
+ trust-anchor: "example.com. 3600 IN DS 38075 7 1 58C0ECEB4566D0E38241313B4A8CD853A42FB511 "
+val-override-date: "20181130121928"
+; target-fetch-policy: "0 0 0 0 0"
+; fake-sha1: yes
+
+;stub-zone:
+; name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+query-minimization: off
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with direct wildcard positive response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+*.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+*.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101928 20181130101928 38075 example.com. VLjbRTUiJ9qkucaMzZrX8yOwPmvBGeu2yv97i60m+eb8rn/9aXHCft8S 1oD4UTjZzNQCKcWr8nnPKFUSdf78Wnjrt3aVBFbCUYKsdz6Ru94O+kWf VUgCWLdL5vrWHgBp22KyFMNmT5jl+u6pBCYfeUR6DQNgMcB/Xk6TIp6P 3xs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101928 20181130101928 38075 example.com. EcQ0T61tBc0Wv3hnZhRO2rf8gvyX3ERzKQy/f7c881D+30gj/7f5t1G2 mNNgeORipwMdxXtimHy3aE2zPycWlYO0ixp4UTztDcePRLPKOmyF4JRZ svMiaBK65fuuBjiG8Ul5QkgBJldObCcFIYo1GjX9L6o3I3zdU3O3DsbP 1ts= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 7 AwEAAbunHwPamENL1sKnlaDimJmh7EubUP/2CelBZJ7H7PMSCz7GPt3u B5rJP7aOogioqA0yJZubiEJESzfwEsg5f14lWESGzMz8mFfe5pGryUjk tG/n43vmCkTPdyUTeSKW9RWyQAPv0PHMi0rMfe5sXs1eeAo23i7c4BAX /MKh/k5r ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20181230101928 20181130101928 38075 example.com. XSdpLw0K9ZLwZXI6/pD58YqfUWHxVr2l1EZ5uKhL2Oa+BLalYhlvJYtx SKRcD6Bc5K526HaJ08kv54j2kxeyUtjNXJf1qcC0xup4lQ3s8gjFx+OS NVhCQoEwSWIbOieL2cfDepEMYOOnxtP4WD6I6C3gIBTMluI/UwEOnRlK lIs= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101928 20181130101928 38075 example.com. VLjbRTUiJ9qkucaMzZrX8yOwPmvBGeu2yv97i60m+eb8rn/9aXHCft8S 1oD4UTjZzNQCKcWr8nnPKFUSdf78Wnjrt3aVBFbCUYKsdz6Ru94O+kWf VUgCWLdL5vrWHgBp22KyFMNmT5jl+u6pBCYfeUR6DQNgMcB/Xk6TIp6P 3xs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101928 20181130101928 38075 example.com. EcQ0T61tBc0Wv3hnZhRO2rf8gvyX3ERzKQy/f7c881D+30gj/7f5t1G2 mNNgeORipwMdxXtimHy3aE2zPycWlYO0ixp4UTztDcePRLPKOmyF4JRZ svMiaBK65fuuBjiG8Ul5QkgBJldObCcFIYo1GjX9L6o3I3zdU3O3DsbP 1ts= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+*.example.com. IN A
+SECTION ANSWER
+*.example.com. IN A 10.20.30.40
+*.example.com. 3600 IN RRSIG A 7 2 3600 20181230101928 20181130101928 38075 example.com. RkzaVAFptvrjbFcVTye2cG720T9sstFdEh6rfTb4kDDi36GlKsrWa2hZ XtXLGYf2VisO/ronIOFTN+OpqHEN4zcsft3gRAWN+v2irAWDPD4WRVKh 1DNdJMKi2fDq2A39oe15ZwyjTc+owev5RONrMZBoUdgVb0lzhri2LNgF dgY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101928 20181130101928 38075 example.com. VLjbRTUiJ9qkucaMzZrX8yOwPmvBGeu2yv97i60m+eb8rn/9aXHCft8S 1oD4UTjZzNQCKcWr8nnPKFUSdf78Wnjrt3aVBFbCUYKsdz6Ru94O+kWf VUgCWLdL5vrWHgBp22KyFMNmT5jl+u6pBCYfeUR6DQNgMcB/Xk6TIp6P 3xs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101928 20181130101928 38075 example.com. EcQ0T61tBc0Wv3hnZhRO2rf8gvyX3ERzKQy/f7c881D+30gj/7f5t1G2 mNNgeORipwMdxXtimHy3aE2zPycWlYO0ixp4UTztDcePRLPKOmyF4JRZ svMiaBK65fuuBjiG8Ul5QkgBJldObCcFIYo1GjX9L6o3I3zdU3O3DsbP 1ts= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+*.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+*.example.com. IN A
+SECTION ANSWER
+*.example.com. IN A 10.20.30.40
+*.example.com. 3600 IN RRSIG A 7 2 3600 20181230101928 20181130101928 38075 example.com. RkzaVAFptvrjbFcVTye2cG720T9sstFdEh6rfTb4kDDi36GlKsrWa2hZ XtXLGYf2VisO/ronIOFTN+OpqHEN4zcsft3gRAWN+v2irAWDPD4WRVKh 1DNdJMKi2fDq2A39oe15ZwyjTc+owev5RONrMZBoUdgVb0lzhri2LNgF dgY= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 7 2 3600 20181230101928 20181130101928 38075 example.com. VLjbRTUiJ9qkucaMzZrX8yOwPmvBGeu2yv97i60m+eb8rn/9aXHCft8S 1oD4UTjZzNQCKcWr8nnPKFUSdf78Wnjrt3aVBFbCUYKsdz6Ru94O+kWf VUgCWLdL5vrWHgBp22KyFMNmT5jl+u6pBCYfeUR6DQNgMcB/Xk6TIp6P 3xs= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 7 3 3600 20181230101928 20181130101928 38075 example.com. EcQ0T61tBc0Wv3hnZhRO2rf8gvyX3ERzKQy/f7c881D+30gj/7f5t1G2 mNNgeORipwMdxXtimHy3aE2zPycWlYO0ixp4UTztDcePRLPKOmyF4JRZ svMiaBK65fuuBjiG8Ul5QkgBJldObCcFIYo1GjX9L6o3I3zdU3O3DsbP 1ts= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi.rpl b/tests/deckard/sets/resolver/val_wild_pos_multi.rpl
new file mode 100644
index 0000000..b08e3e2
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi.rpl
@@ -0,0 +1,239 @@
+; config options
+;server:
+ trust-anchor: ". IN DS 41524 8 2 5175938255D97A88F9D16A5A46ED3AE373441DF5058C1666D953005D A6BD57F3"
+ val-override-date: "20170501000000"
+
+;stub-zone:
+; name: "."
+ stub-addr: 10.1.1.1 # ns.
+CONFIG_END
+
+SCENARIO_BEGIN Test validation of wildcard responses with multiple synthesized RRs.
+
+; ns.
+RANGE_BEGIN 0 1000
+ ADDRESS 10.1.1.1
+ ADDRESS 10.2.2.2
+ ADDRESS 10.3.3.3
+ ADDRESS ::1
+ ADDRESS ::2
+ ADDRESS ::3
+
+ENTRY_BEGIN
+MATCH opcode qtype
+ADJUST copy_id copy_query
+REPLY QR AA REFUSED
+SECTION QUESTION
+. IN RRSIG
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 3600 IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
+. 3600 IN RRSIG DNSKEY 8 0 3600 20170519062759 20170419062759 41524 . GldXJTOYlVu202Dfdn6n6+ueu59rULnFZqpGSWO1b5TWhY0Z58f8JLNq OeGS1R2OxUZHEy6MQGgiBUEbBXxUx5fZh0UI0K9D7FfwIA9A5hmHC86g Ds3YQuGM0XfHT1aVeGPnjbcIGkRvTtD2P8vc12WT0bm56xLzNu33pat8 PB7/60S5KY1quSqw0HksIEo/Brblql6DPVYRUxZE2+xObOehUhc2W1n5 v+/pEzpRJ22CJ17Bvc4Mf8sBGgFqxFzmBcgf4Ae0UG3Fz8GIjwcN80cm dYK9cuaCIKn+m/lk3/tXlNJigNxdYB0N6vr6bBhfHOuv8VhEr+0iKM2G sG0ugg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 3600 IN NS ns.
+. 3600 IN RRSIG NS 8 0 3600 20170519062759 20170419062759 41524 . VmrJp+587qjS63rXgtCzIDyja2l8Hp09GB9iUNR33C/P5nkCn3hjsu+u 67c++Ck6/jgKvn9pRW3JdhOaxTeJRZBsYUKq3JtDuHVuV9WaNvDfCJhI /wFMrNTIR1UK9GxHgAWvZ2nBjKNV/nX4w+OB8eDKeT1AGgvoF182pCI0 VX9pbYd2gsMiZsymm5KRuicFxCMxvAa0jmkg9Pua1vQ2kraVjQP/qND4 gEXZaOmGfmm1UUrXlXdnJYrf6j/0zXaVjZdK6TvNh1kEpzXfDX4GLCDa 3dwy7O/h+IRHl7d+X8d1iojdvyJ2qzPkZ9EI7hlEPc7VY2pqNCtC/2WZ c0bf5w==
+SECTION ADDITIONAL
+ns. 3600 IN A 10.1.1.1
+ns. 3600 IN A 10.2.2.2
+ns. 3600 IN A 10.3.3.3
+ns. 3600 IN RRSIG A 8 0 3600 20170519062759 20170419062759 41524 . UtmUBa+ubwWz1BlKcbg/jUhYYPj2qowEjr2IgVMeMopTgESE7Ssg2XMU YY4q2drAXsR/t1uNDIjhDaCXmsyK5yINavxgmPhypt1dnIyXf8+Lfmoi RTP1JKRvsFssQgJMrfCge82oTDYqfmav0NddGNNx829MC5+M/8JtygZU kOczXuwAKclUsFKophlmh3bn3hC6fzBWvRh59j5Voy2oYOw4yHtgDlEN qWQY1BPKYR2FKQG+sVPRhBufWN3uLK2sN8hviaE8gUluwaVx8ekjnr9t twA1h54DRYlJVU2ARCo+xN+hTQG/kt0Rqcr72Vq0LdTxpy+sERQ72tM5 fVvl9Q==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 10.1.1.1
+ns. 3600 IN A 10.2.2.2
+ns. 3600 IN A 10.3.3.3
+ns. 3600 IN RRSIG A 8 0 3600 20170519062759 20170419062759 41524 . UtmUBa+ubwWz1BlKcbg/jUhYYPj2qowEjr2IgVMeMopTgESE7Ssg2XMU YY4q2drAXsR/t1uNDIjhDaCXmsyK5yINavxgmPhypt1dnIyXf8+Lfmoi RTP1JKRvsFssQgJMrfCge82oTDYqfmav0NddGNNx829MC5+M/8JtygZU kOczXuwAKclUsFKophlmh3bn3hC6fzBWvRh59j5Voy2oYOw4yHtgDlEN qWQY1BPKYR2FKQG+sVPRhBufWN3uLK2sN8hviaE8gUluwaVx8ekjnr9t twA1h54DRYlJVU2ARCo+xN+hTQG/kt0Rqcr72Vq0LdTxpy+sERQ72tM5 fVvl9Q==
+SECTION AUTHORITY
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION ANSWER
+ns. 3600 IN AAAA ::1
+ns. 3600 IN AAAA ::2
+ns. 3600 IN AAAA ::3
+ns. 3600 IN RRSIG AAAA 8 0 3600 20170519141813 20170419141813 41524 . q256A5GuT3+3jMaDXhh7Z2w/lPYNxtSLamf4TPcAuIDm41Fnj4M1OU63 ViuoBM2GNP512YZxL9wjkTXVjbQJ3nfIT4D7vRdtNpcA48lceYRslBOP qxuFLxRNbW+a1iLA28IiouecsmJIpfLNfCR9OAMKnuFbdkDHNDYEVyKt TRDuqANfj9s8tEH5SLwoycAtLxP5nBVPqOCgNJAg7j+qNXcA/I+dhqBf xy9eMNmhMbDN09x0+k63vJcdhsgj1sxAqvnq973r+uM7T1WDBjcn71CS fDP3kplHxM4vGpmDvJ5MkStLQ/+kqGNVb9qUl65gBidsA3SYqkZ3KtxT Br/61w==
+SECTION AUTHORITY
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns. IN TXT
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+. 3600 IN RRSIG SOA 8 0 3600 20170519141813 20170419141813 41524 . iuxo0/dNl+zFK1i7CnGR0ssx39IkWTkqXWOcbm8ZrN/vnV2lt7tkRctV 4MmoCiIFfTd4R+jWorVlV0eu1FVmm8cvEAPJzZKk79hvS7DrL5cvwlDA OXSS8J2ram3h+eJH2FCHkSKPkqJUlpXPsQbnfVFf4bFTYi5rXE+Nkpij qhACwhHb8HZNay1/L/njW2DvnY40rgoArxKoJyw0lDgYWd2YYsqHjDGp Ditdeam33tEdWmn8N2oSOXOaRZ3MjDL0PL0uOanJ2wiLFs33MlGo/Y1q ncGgLBSiLFEOhpYgPP3CRu7QZxjQjinwq+tRRhwaqyfPPliHO22NblwL 7tp8qg==
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+RANGE_END
+
+; recursion happens here, we expect NODATA
+STEP 101 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns. IN TXT
+ENTRY_END
+
+STEP 102 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns. IN TXT
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+ENTRY_END
+
+; recursion happens here, we expect positive answer
+STEP 110 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns. IN A
+ENTRY_END
+
+STEP 111 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 10.1.1.1
+ns. 3600 IN A 10.2.2.2
+ns. 3600 IN A 10.3.3.3
+ENTRY_END
+
+; recursion happens here, we expect positive answer
+STEP 120 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns. IN AAAA
+ENTRY_END
+
+STEP 121 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION ANSWER
+ns. 3600 IN AAAA ::1
+ns. 3600 IN AAAA ::2
+ns. 3600 IN AAAA ::3
+ENTRY_END
+
+
+
+; retry with DNSSEC enabled
+
+; recursion happens here, we expect NODATA wildcard proof
+STEP 131 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ns. IN TXT
+ENTRY_END
+
+STEP 132 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+ns. IN TXT
+SECTION AUTHORITY
+. 0 IN SOA . . 0 0 0 0 0
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+. 3600 IN RRSIG SOA 8 0 3600 20170519141813 20170419141813 41524 . iuxo0/dNl+zFK1i7CnGR0ssx39IkWTkqXWOcbm8ZrN/vnV2lt7tkRctV 4MmoCiIFfTd4R+jWorVlV0eu1FVmm8cvEAPJzZKk79hvS7DrL5cvwlDA OXSS8J2ram3h+eJH2FCHkSKPkqJUlpXPsQbnfVFf4bFTYi5rXE+Nkpij qhACwhHb8HZNay1/L/njW2DvnY40rgoArxKoJyw0lDgYWd2YYsqHjDGp Ditdeam33tEdWmn8N2oSOXOaRZ3MjDL0PL0uOanJ2wiLFs33MlGo/Y1q ncGgLBSiLFEOhpYgPP3CRu7QZxjQjinwq+tRRhwaqyfPPliHO22NblwL 7tp8qg==
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+STEP 210 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ns. IN A
+ENTRY_END
+
+STEP 211 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+ns. IN A
+SECTION ANSWER
+ns. 3600 IN A 10.1.1.1
+ns. 3600 IN A 10.2.2.2
+ns. 3600 IN A 10.3.3.3
+ns. 3600 IN RRSIG A 8 0 3600 20170519062759 20170419062759 41524 . UtmUBa+ubwWz1BlKcbg/jUhYYPj2qowEjr2IgVMeMopTgESE7Ssg2XMU YY4q2drAXsR/t1uNDIjhDaCXmsyK5yINavxgmPhypt1dnIyXf8+Lfmoi RTP1JKRvsFssQgJMrfCge82oTDYqfmav0NddGNNx829MC5+M/8JtygZU kOczXuwAKclUsFKophlmh3bn3hC6fzBWvRh59j5Voy2oYOw4yHtgDlEN qWQY1BPKYR2FKQG+sVPRhBufWN3uLK2sN8hviaE8gUluwaVx8ekjnr9t twA1h54DRYlJVU2ARCo+xN+hTQG/kt0Rqcr72Vq0LdTxpy+sERQ72tM5 fVvl9Q==
+SECTION AUTHORITY
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+STEP 220 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ns. IN AAAA
+ENTRY_END
+
+STEP 221 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+ADJUST copy_id
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+ns. IN AAAA
+SECTION ANSWER
+ns. 3600 IN AAAA ::1
+ns. 3600 IN AAAA ::2
+ns. 3600 IN AAAA ::3
+ns. 3600 IN RRSIG AAAA 8 0 3600 20170519141813 20170419141813 41524 . q256A5GuT3+3jMaDXhh7Z2w/lPYNxtSLamf4TPcAuIDm41Fnj4M1OU63 ViuoBM2GNP512YZxL9wjkTXVjbQJ3nfIT4D7vRdtNpcA48lceYRslBOP qxuFLxRNbW+a1iLA28IiouecsmJIpfLNfCR9OAMKnuFbdkDHNDYEVyKt TRDuqANfj9s8tEH5SLwoycAtLxP5nBVPqOCgNJAg7j+qNXcA/I+dhqBf xy9eMNmhMbDN09x0+k63vJcdhsgj1sxAqvnq973r+uM7T1WDBjcn71CS fDP3kplHxM4vGpmDvJ5MkStLQ/+kqGNVb9qUl65gBidsA3SYqkZ3KtxT Br/61w==
+SECTION AUTHORITY
+*. 0 IN NSEC . A AAAA RRSIG NSEC
+*. 0 IN RRSIG NSEC 8 0 0 20170519141813 20170419141813 41524 . FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXviOPAoK/FYucZPqPxLAGs C1bQQ82YlPy1SU1HMbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtKl6YO 6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61YkvCf6p/sqxOAuWKqSkHIlyJ VUNETyfYKlp5x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S25eTAgsDb 8R0FCb5ks+AcvWZZyNTbwvstaz92EqSOCCWkGSDF3gp2Pv5SI+3xUeTy c/NuJ+f366C5w0MsaW+9oXo2zy/aOFULzwFtdH8ZizqzwwNdGS1sqvuw 1UaqkA==
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.key b/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.key
new file mode 100644
index 0000000..1511e45
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.key
@@ -0,0 +1,5 @@
+; This is a key-signing key, keyid 41524, for .
+; Created: 20170319134901 (Sun Mar 19 14:49:01 2017)
+; Publish: 20170319134901 (Sun Mar 19 14:49:01 2017)
+; Activate: 20170319134901 (Sun Mar 19 14:49:01 2017)
+. IN DNSKEY 257 3 8 AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0JoeOUlWHZ3eeWXZKxQJak QIXyGi8xsuANzu/YStLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1eczh 69YqGUAPZkreZ3z2DpWzBN4lgPR/w0OvTada3D42uV2bzuSK/nXMiMpZ vP1vZ1ykNRmbksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1ddVwSK7qIJ 02jo95YJUSZDPUUQlczIsFsa7Zxn6gQZl+iaRuDY6nLxxStYYlcqZhVA G5U8Dx4IznQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+TTUAa3hD597f onH+s/OfdCE=
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.private b/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.private
new file mode 100644
index 0000000..2811b2b
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi/K.+008+41524.private
@@ -0,0 +1,13 @@
+Private-key-format: v1.3
+Algorithm: 8 (RSASHA256)
+Modulus: uDK9hDZWV9/+Kem/g1kuUiTb6XWwvQmh45SVYdnd55ZdkrFAlqRAhfIaLzGy4A3O79hK0unfVJ9T8WPimJRyKoD5Tvgui3VL+Nwzv/V5zOHr1ioZQA9mSt5nfPYOlbME3iWA9H/DQ69Np1rcPja5XZvO5Ir+dcyIylm8/W9nXKQ1GZuSxPMD4eet59GLbK4xJSowdu19t8XCpVNDV11XBIruognTaOj3lglRJkM9RRCVzMiwWxrtnGfqBBmX6JpG4NjqcvHFK1hiVypmFUAblTwPHgjOdDQWQQmn1Fe2/mua0KVxCm50KXWATQYL9b5NNQBreEPn3t+icf6z8590IQ==
+PublicExponent: AQAB
+PrivateExponent: HEH8fPnxCQ4d6cQoUzgtOQDak9gwQu/lXAqBWD+aIVsaA9UZeYK9O09G4RKYxHKZ2oWuBOlID61ZrWCLdKjhUs/yb0D3swFNpGHztnEsPFg0W+idcwxpvvabnboJxsFt776FJ/0psYqFOTVhMFIo4clzVfBU1TGJkrFtotuiWb28eZ85pFJiQUR+agbWjstXaXMmXeSRPYAueBD/bo6u5DqDagH1fzNxhKUxC9nhpeoIj1AtH4bJuO0v4oxq6yrcGEn6Jus5wku9goLCJqykfRikYwQzyUCP/AQMVC++qiQJ89A66psa0F2lcmps5/2skBEM9QB5Vv12jbIw6j6TeQ==
+Prime1: 6AkeSU4ZcvsxDem0IJLhC4zYEpCN+ZAr/757pkv6oIfQv2PhJmXQ1bmiCsYD/uoRDUFNtNGOFjIlmnGHKIefvCSHlZRxCDDzDAvZ6IthkMQEzDcSQkZIpprCt7QMl1Kz2gjEs84+DNxozB54UbEYG908PrF7CF7ix3RHHEDcX6M=
+Prime2: yzjUYzFjM52Q5cwtMHL8gHnacpzQSUidYLZF+xA4dYjc0pjSRMo87sfp2r6wdm3ZOcfOy0SZl4LvO0Kcrz/VB2v0yiBqanDcM3SBg6n7lz/l5Xaoj5rw9JmYj981nJe8vcerZvJl8MLT00uikr1gqoABxKIvHyt7kYcYB2qqSWs=
+Exponent1: Sjzgm8OJEOidQT5Miz9zESb22rm1MuuVqDVhiks03LeXaiSinI5mynqiBaBlFuH8oqkKG5gQRbm1njxEags6aA+n8YuUvnIq0OfZyDUP+ik8/7l+9gVWqTdKpUvN23xyXof/pyeNYsACJ4x4Imrus7uM0uIl4v+4vufM+JUn7NE=
+Exponent2: HUmqakVC27x4lnWviYz40Pc+wUfSSM17SOXb/gvfZyj7UiqOGzXeRDdxf4H94oOAS/B84BSZ4hkPq0W1WRhk9jXbyImVbJOpWI0Q4U3NIYYm9sP8FP4qfcXpE8sCafgAToWJMUP75w/dAVWkL2u1k7zxBEqvadmVbGrAzsjTk9M=
+Coefficient: ms+SW3tNI975ejCbI1vIB31uUqVfvVvxv7eWtzJEdyxBVQKb0aQnXaTMdXiESNc+H5HMau3lbDOw5IcQkp79fKdxLt3SjMYPdnQmBWg7StY3fV1FJcPEEJeFQjWXxioY8rdvMUTMk1FfjxlllBkCyMWuIE4cbRTNdcq76ozM60g=
+Created: 20170319134901
+Publish: 20170319134901
+Activate: 20170319134901
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi/dsset-. b/tests/deckard/sets/resolver/val_wild_pos_multi/dsset-.
new file mode 100644
index 0000000..6c9d3b7
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi/dsset-.
@@ -0,0 +1,2 @@
+. IN DS 41524 8 1 C042815790A1423F03578E561C4DC09BF9BEC5C0
+. IN DS 41524 8 2 5175938255D97A88F9D16A5A46ED3AE373441DF5058C1666D953005D A6BD57F3
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone b/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone
new file mode 100644
index 0000000..b69eb42
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone
@@ -0,0 +1,10 @@
+. 3600 IN SOA . . 0 0 0 0 0
+. 3600 IN NS ns.
+
+*. 3600 IN A 10.1.1.1
+*. 3600 IN A 10.2.2.2
+*. 3600 IN A 10.3.3.3
+
+*. 3600 IN AAAA ::1
+*. 3600 IN AAAA ::2
+*. 3600 IN AAAA ::3
diff --git a/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone.signed b/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone.signed
new file mode 100644
index 0000000..ddb5864
--- /dev/null
+++ b/tests/deckard/sets/resolver/val_wild_pos_multi/root.zone.signed
@@ -0,0 +1,114 @@
+; File written on Wed Apr 19 17:18:13 2017
+; dnssec_signzone version 9.10.4-P6-RedHat-9.10.4-4.P6.fc25
+. 3600 IN SOA . . (
+ 0 ; serial
+ 0 ; refresh (0 seconds)
+ 0 ; retry (0 seconds)
+ 0 ; expire (0 seconds)
+ 0 ; minimum (0 seconds)
+ )
+ 3600 RRSIG SOA 8 0 3600 (
+ 20170519141813 20170419141813 41524 .
+ iuxo0/dNl+zFK1i7CnGR0ssx39IkWTkqXWOc
+ bm8ZrN/vnV2lt7tkRctV4MmoCiIFfTd4R+jW
+ orVlV0eu1FVmm8cvEAPJzZKk79hvS7DrL5cv
+ wlDAOXSS8J2ram3h+eJH2FCHkSKPkqJUlpXP
+ sQbnfVFf4bFTYi5rXE+NkpijqhACwhHb8HZN
+ ay1/L/njW2DvnY40rgoArxKoJyw0lDgYWd2Y
+ YsqHjDGpDitdeam33tEdWmn8N2oSOXOaRZ3M
+ jDL0PL0uOanJ2wiLFs33MlGo/Y1qncGgLBSi
+ LFEOhpYgPP3CRu7QZxjQjinwq+tRRhwaqyfP
+ PliHO22NblwL7tp8qg== )
+ 3600 NS ns.
+ 3600 RRSIG NS 8 0 3600 (
+ 20170519141813 20170419141813 41524 .
+ mta7nYjyM8qecNDgcuzyosmO6pwXQOJxb+oX
+ hF8yElB1FiVWwPhsxnrGlME3PhCRj9+tvE8B
+ MTW0Js42DtJ5GvD/FJ2RBYFTwXrydffIQafR
+ No3Gxsz0bX8+aIEVzIrTIXe8bMWk5bs9E1Yu
+ c6OKgqteAzfrXi5my8cfro5Bjc5m/Qo/tWbX
+ auPCv/M2N5a9oey1z13msZSpR+/XfCGH0v1e
+ rIZje/A/5PFXXTIVzKsIzazErd9OnbEI6280
+ S56ctV7SbjoDgHyM7XuyVYWzkdhN/evOwu0l
+ YuObCxtgkUR56Ba5Ii3Su4bp0+JNGf/N3yLh
+ gVF7DjoWkfvnlNIXoQ== )
+ 0 NSEC *. NS SOA RRSIG NSEC DNSKEY
+ 0 RRSIG NSEC 8 0 0 (
+ 20170519141813 20170419141813 41524 .
+ qLniiG3AKNGlsOwSCzlPrk08E6beDttOa5Aj
+ phfR90H2mt8uSqxlQD/5oWJVGqDrjAnOvjVO
+ WXDxH+zsWAWI+01ZcAxvd59+7e66qAwRqKmC
+ c/H2m4/2KzbHHZd7kZ1NAPX+dVtwuc7qM0jG
+ mc89GogQaxmRv2em1iA8h0PLCM7Vk4B/bDo3
+ xRMTtdjmUM6DYIeyAQfLxoAAIsXCoAIvXYWt
+ CQDugjWMrHvNMdMjEYzLU+RO7NHnlDKgaXzk
+ IckYe0TL0+FrP65a2lVfOkcUzTjRV6jajWeY
+ LjoaiWu+6IO5Zpm+XnTeIz496xX1RhsSKGuB
+ /NAIdfkWvJ7MGsd4/Q== )
+ 3600 DNSKEY 257 3 8 (
+ AwEAAbgyvYQ2Vlff/inpv4NZLlIk2+l1sL0J
+ oeOUlWHZ3eeWXZKxQJakQIXyGi8xsuANzu/Y
+ StLp31SfU/Fj4piUciqA+U74Lot1S/jcM7/1
+ eczh69YqGUAPZkreZ3z2DpWzBN4lgPR/w0Ov
+ Tada3D42uV2bzuSK/nXMiMpZvP1vZ1ykNRmb
+ ksTzA+HnrefRi2yuMSUqMHbtfbfFwqVTQ1dd
+ VwSK7qIJ02jo95YJUSZDPUUQlczIsFsa7Zxn
+ 6gQZl+iaRuDY6nLxxStYYlcqZhVAG5U8Dx4I
+ znQ0FkEJp9RXtv5rmtClcQpudCl1gE0GC/W+
+ TTUAa3hD597fonH+s/OfdCE=
+ ) ; KSK; alg = RSASHA256 ; key id = 41524
+ 3600 RRSIG DNSKEY 8 0 3600 (
+ 20170519141813 20170419141813 41524 .
+ jm0WoZl7B17L5OMiI4j7EwUXuoZVDuvybewY
+ Z3NfQQOK0zDsnQKZFkG4unV5gp4ORQ5OD/Kt
+ fK9A5KYqEWewqgQcWiJ+PvsyAibVEqpAqrWq
+ OIsnBYJgVzhzFyA1hQOb5j4cpYGCGe5znHoF
+ eeTdIc/ZykCAxFLUMzmHu/ivIuhni6z3gdtS
+ GqVY2eTjWXqyv6ImMZJeL/34+/cKctS7ZCwe
+ rzxmnoDAzS3cUql+hL7Oh7YUWDVfcUkDKqXX
+ 5KMcvjPQhqSERyewQN3n2F9Z4Dxf41TYL2TF
+ /cG6idUt2gLaA+l/+2+CoCwsStzug7bK9mmA
+ cXkidI+IZup7KQ/WcA== )
+*. 3600 IN A 10.1.1.1
+ 3600 IN A 10.2.2.2
+ 3600 IN A 10.3.3.3
+ 3600 RRSIG A 8 0 3600 (
+ 20170519141813 20170419141813 41524 .
+ PK9xvQqB3OB1o/nW7IOlIeZT35lHBujkK9Nq
+ aehnTX7CiYuwe5IpXY7EsGEt6ZtEB+wS54tY
+ UZ9pDyAADLwhQmYHP2jASiY/ZuQj3IL8uymL
+ A/D5xnxfHnsyzqShYEjTTK9+6cL0RQ4t2Fia
+ XkwOQb4+i9wcGTu9zJ/L/WRNzKRqsyQ/fxQB
+ gqDDyBVn47ZIjH0DBDBML7P58dH894bDiLNu
+ 2RwEntgs+bwzUrPYlOA2Le2xNlc8qqzNktWe
+ fr+6OEjn5qXnNccBkbASN9FBV8CJ7Bfl6KKT
+ CRjKv3a/y/mqYOR6pIrw97QYXmjgQvjT4HLy
+ cfu8DpZEweBX9vg5Ag== )
+ 3600 AAAA ::1
+ 3600 AAAA ::2
+ 3600 AAAA ::3
+ 3600 RRSIG AAAA 8 0 3600 (
+ 20170519141813 20170419141813 41524 .
+ q256A5GuT3+3jMaDXhh7Z2w/lPYNxtSLamf4
+ TPcAuIDm41Fnj4M1OU63ViuoBM2GNP512YZx
+ L9wjkTXVjbQJ3nfIT4D7vRdtNpcA48lceYRs
+ lBOPqxuFLxRNbW+a1iLA28IiouecsmJIpfLN
+ fCR9OAMKnuFbdkDHNDYEVyKtTRDuqANfj9s8
+ tEH5SLwoycAtLxP5nBVPqOCgNJAg7j+qNXcA
+ /I+dhqBfxy9eMNmhMbDN09x0+k63vJcdhsgj
+ 1sxAqvnq973r+uM7T1WDBjcn71CSfDP3kplH
+ xM4vGpmDvJ5MkStLQ/+kqGNVb9qUl65gBids
+ A3SYqkZ3KtxTBr/61w== )
+ 0 NSEC . A AAAA RRSIG NSEC
+ 0 RRSIG NSEC 8 0 0 (
+ 20170519141813 20170419141813 41524 .
+ FgFsXY4fdEQZlv5xd2WQuH6b0YIuDoOydNXv
+ iOPAoK/FYucZPqPxLAGsC1bQQ82YlPy1SU1H
+ MbggjMNT224sllm0WY0P1PjkPN8XkBbFRZtK
+ l6YO6Jyav58WZCjDLsRfKYMzFPXe7GqvtB61
+ YkvCf6p/sqxOAuWKqSkHIlyJVUNETyfYKlp5
+ x7CDZiCnPgAppZUEv0kEQKmTCzTgC+ctj2S2
+ 5eTAgsDb8R0FCb5ks+AcvWZZyNTbwvstaz92
+ EqSOCCWkGSDF3gp2Pv5SI+3xUeTyc/NuJ+f3
+ 66C5w0MsaW+9oXo2zy/aOFULzwFtdH8Zizqz
+ wwNdGS1sqvuw1UaqkA== )
diff --git a/tests/deckard/sets/resolver/world_cz_lidovky_www.rpl b/tests/deckard/sets/resolver/world_cz_lidovky_www.rpl
new file mode 100644
index 0000000..9f46ba3
--- /dev/null
+++ b/tests/deckard/sets/resolver/world_cz_lidovky_www.rpl
@@ -0,0 +1,910 @@
+stub-addr: 2001:dc3::35
+val-override-date: "20170228130000"
+trust-anchor: ". 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"
+CONFIG_END
+
+SCENARIO_BEGIN www.lidovky.cz CNAME c23.idnes.cz points from signed domain into unsigned domain hosted on the same server. The result must be NOERROR without AD flag.
+
+;root
+RANGE_BEGIN 0 100
+ ADDRESS 2001:dc3::35
+ ADDRESS 198.41.0.4
+ ADDRESS 192.228.79.201
+ ADDRESS 192.33.4.12
+ ADDRESS 199.7.91.13
+ ADDRESS 192.203.230.10
+ ADDRESS 192.5.5.241
+ ADDRESS 192.112.36.4
+ ADDRESS 198.97.190.53
+ ADDRESS 192.36.148.17
+ ADDRESS 192.58.128.30
+ ADDRESS 193.0.14.129
+ ADDRESS 199.7.83.42
+ ADDRESS 202.12.27.33
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 2001:500:84::b
+ ADDRESS 2001:500:2::c
+ ADDRESS 2001:500:2d::d
+ ADDRESS 2001:500:a8::e
+ ADDRESS 2001:500:2f::f
+ ADDRESS 2001:500:12::d0d
+ ADDRESS 2001:500:1::53
+ ADDRESS 2001:7fe::53
+ ADDRESS 2001:503:c27::2:30
+ ADDRESS 2001:7fd::1
+ ADDRESS 2001:500:9f::42
+ ADDRESS 2001:dc3::35
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ . IN DS
+ SECTION AUTHORITY
+ . 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017022701 1800 900 604800 86400
+ . 86400 IN RRSIG SOA 8 0 86400 20170312170000 20170227160000 61045 . GhyRFKg8xu/asiFmIMifBOFUeJlL++ncqDoBLbYoviben3WNrdU7vJxZ Cm3EZ8HEYr2gFFkupaHBZt+P6GdX9lU8aw7yOZ8ZXV48S209Jo3PkHxH iVOtaC7QzkJPiZUgh06MuWgQoeNJSVqGTCy+TlTlMLqGndNcpT0rkX7H 0gCcuaZcBv0nqEPKqZeq8XFVIfiaUCKz/kkkO0vgP9euN+WT+68hng4F oIQ0eAPIUL6XBW2uWubWS2Yd8C+g/++qeLnte7QYF+9By5HuN6fXskba 0uph3gzjWArn+SYQhEWyqbS6wb0LloAawt9LW7neJYOMFhlU1AOScGjn e8rfBw==
+ . 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+ . 86400 IN RRSIG NSEC 8 0 86400 20170312170000 20170227160000 61045 . MLiCUaeASll0V1x0imORnQodzd/6LuDpa8XfebmNE7eGMda62HCK9kB2 I5Yvcc6naw1nzJVSVNIjDQyAKHgSWy457vwvWbEdCuD5XS8A1/drP13x pfP91XG3qPswx3u1i4cLSTO5VJi1lup1Qr1UrN54kNbRp2sS65VKXOH4 4I6bwA1CBOmU6EHlyI2nymZDqCRaTdWjyoYSZ1zkucSjEgn8GtyniNiS p7AfNLnnJ6poKSCcOj2hSQTb58i7B7TJt/JQWb6ko12rcSEVxZljhqHc XzR+i8Bgfpj9ha83tcZwDFQQy4mKjSkboOEoRe8Z5qKIb5DF0wn0vB+M LClQJg==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ . IN NS
+ SECTION ANSWER
+ . 518400 IN NS m.root-servers.net.
+ . 518400 IN NS k.root-servers.net.
+ . 518400 IN NS a.root-servers.net.
+ . 518400 IN NS l.root-servers.net.
+ . 518400 IN NS j.root-servers.net.
+ . 518400 IN NS i.root-servers.net.
+ . 518400 IN NS e.root-servers.net.
+ . 518400 IN NS b.root-servers.net.
+ . 518400 IN NS h.root-servers.net.
+ . 518400 IN NS d.root-servers.net.
+ . 518400 IN NS c.root-servers.net.
+ . 518400 IN NS f.root-servers.net.
+ . 518400 IN NS g.root-servers.net.
+ . 518400 IN RRSIG NS 8 0 518400 20170312170000 20170227160000 61045 . iqk4z3W6lGfSgvbPGl4JPVDca+21mXayctqY0FO1a9YhCSxLQGsV/0eK IfYOGHMCBr2szIactoznQgFybjNG/I5bKo+EU4U0tNNVwrUHWTMsAraQ yIS/efPZyKAHSzKZjlcRVOFbFPA/DWp6JzMhfXaBYMLcsA8ZT/CwCnxF a7wInMupWskMwXXhTgGci+PJVKm+TK5hEtYYnb3Ny2lxoWtTPJuZufM9 1xg2YXs6njo1gKzj3zaTwpndeBbYN78ZfETmPsjyr7X144v9qe7qygCO dTjy+cly1JG1prI9yHaU5zJk3X9VcvWWRR3ACQOFfzthFqyEoHjQmEBe XQHCRg==
+ SECTION ADDITIONAL
+ a.root-servers.net. 3600000 IN A 198.41.0.4
+ b.root-servers.net. 3600000 IN A 192.228.79.201
+ c.root-servers.net. 3600000 IN A 192.33.4.12
+ d.root-servers.net. 3600000 IN A 199.7.91.13
+ e.root-servers.net. 3600000 IN A 192.203.230.10
+ f.root-servers.net. 3600000 IN A 192.5.5.241
+ g.root-servers.net. 3600000 IN A 192.112.36.4
+ h.root-servers.net. 3600000 IN A 198.97.190.53
+ i.root-servers.net. 3600000 IN A 192.36.148.17
+ j.root-servers.net. 3600000 IN A 192.58.128.30
+ k.root-servers.net. 3600000 IN A 193.0.14.129
+ l.root-servers.net. 3600000 IN A 199.7.83.42
+ m.root-servers.net. 3600000 IN A 202.12.27.33
+ a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+ b.root-servers.net. 3600000 IN AAAA 2001:500:84::b
+ c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+ d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+ e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+ f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+ g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+ h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+ i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+ j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+ k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+ l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+ m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ . IN DNSKEY
+ SECTION ANSWER
+ . 172800 IN DNSKEY 256 3 8 AwEAAYvgWbYkpeGgdPKaKTJU3Us4YSTRgy7+dzvfArIhi2tKoZ/WR1Df w883SOU6Uw7tpVRkLarN0oIMK/xbOBD1DcXnyfElBwKsz4sVVWmfyr/x +igD/UjrcJ5zEBUrUmVtHyjar7ccaVc1/3ntkhZjI1hcungAlOhPhHlk MeX+5Azx6GdX//An5OgrdyH3o/JmOPMDX1mt806JI/hf0EwAp1pBwo5e 8SrSuR1tD3sgNjr6IzCdrKSgqi92z49zcdis3EaY199WFW60DCS7ydu+ +T5Xa+GyOw1quagwf/JUC/mEpeBQYWrnpkBbpDB3sy4+P2i8iCvavehb RyVm9U0MlIc=
+ . 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+ . 172800 IN RRSIG DNSKEY 8 0 172800 20170313000000 20170220000000 19036 . Dgzxpg2Lr39HXuHwuJWYCGySxsm92RY8TRuSOstPVcHc7we0d4pW7Znt 33j9fzrxdvoVFAvqSioilVKiOY49M8N+sXcsfTK3cnh7ijTA7suXd4ht TClLN7Dn+ZAjhoyjLm5hf7P/jL0K9KKcOqEqS+uqX3W2WeCvUwT3BY6A t2r+pKSVnoX0uFWJX+mmCh4veYW3eoBzAqwAVbCE5hl2tVbf/vzpa8eW kHegVmm5smKzK2ciYOqExl3FtLgf6dp+HTpruS2oN1JPxm4f1IZhVwT0 pSEu8OUNOV8WSbLn3P9aUpq894Tf1i0/AEtFtx2tRCdw3lSKOugfneo0 PYo1JQ==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ cz. IN DS
+ SECTION ANSWER
+ cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+ cz. 86400 IN RRSIG DS 8 1 86400 20170312170000 20170227160000 61045 . irp/lUXakeZMwVjkZQOOt6xAB2Fcglo7nxmUkHBFjsB5lp61Pg6eyt8u xvGrTdv4mv6PH5q0c7bfKo0Ngtedbq8gZ6VHXfcKUU7vP5BUmePWPyvf khKcafAO7D2wIw9gKxPB0syd3woUP7PlQ1Rg/rUMwDnEXtS7zEqzrVbb VkjdqvdgLUsInAc9zdP72qRp9cJhuoRm0nco1uo2ZLUC04poGxSNzXTw hKhngqHDTqD1nr/Wnq7uXtmLyvFelICSpSHmkrCxnou7EtPybC+W+fna f8o7FebZBnB71t5d8s2kxlb+KrWXUMv8VOdZdZTQTN8M5LeKSBL7RnXM 1FbCiQ==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ CZ. IN NS
+ SECTION AUTHORITY
+ cz. 172800 IN NS b.ns.nic.cz.
+ cz. 172800 IN NS a.ns.nic.cz.
+ cz. 172800 IN NS c.ns.nic.cz.
+ cz. 172800 IN NS d.ns.nic.cz.
+ cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+ cz. 86400 IN RRSIG DS 8 1 86400 20170312170000 20170227160000 61045 . irp/lUXakeZMwVjkZQOOt6xAB2Fcglo7nxmUkHBFjsB5lp61Pg6eyt8u xvGrTdv4mv6PH5q0c7bfKo0Ngtedbq8gZ6VHXfcKUU7vP5BUmePWPyvf khKcafAO7D2wIw9gKxPB0syd3woUP7PlQ1Rg/rUMwDnEXtS7zEqzrVbb VkjdqvdgLUsInAc9zdP72qRp9cJhuoRm0nco1uo2ZLUC04poGxSNzXTw hKhngqHDTqD1nr/Wnq7uXtmLyvFelICSpSHmkrCxnou7EtPybC+W+fna f8o7FebZBnB71t5d8s2kxlb+KrWXUMv8VOdZdZTQTN8M5LeKSBL7RnXM 1FbCiQ==
+ SECTION ADDITIONAL
+ a.ns.nic.cz. 155678 IN A 194.0.12.1
+ b.ns.nic.cz. 155678 IN A 194.0.13.1
+ c.ns.nic.cz. 153044 IN A 194.0.14.1
+ d.ns.nic.cz. 153044 IN A 193.29.206.1
+ a.ns.nic.cz. 153051 IN AAAA 2001:678:f::1
+ b.ns.nic.cz. 153051 IN AAAA 2001:678:10::1
+ c.ns.nic.cz. 155678 IN AAAA 2001:678:11::1
+ d.ns.nic.cz. 155678 IN AAAA 2001:678:1::1
+ ENTRY_END
+
+
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ net. IN DS
+ SECTION ANSWER
+ net. 86400 IN DS 35886 8 2 7862B27F5F516EBE19680444D4CE5E762981931842C465F00236401D 8BD973EE
+ net. 86400 IN RRSIG DS 8 1 86400 20170312170000 20170227160000 61045 . bRSoCpmN/6LhmSB7i68N0zO08WwVikjm6HhOyZMhyjF4sfAaDoeTMs5E XjflCZMly1SP8CwkK6Wz6Ozb8nMUHEsYOhASVBkYC/ImBpqIV5LxaCbW 4L7g5Mwam0MBZb4hybI7JUyuiRONVy3YYk+eUvyf4/flu3Cl14a36LYv 2In/ECg9sV8cMOrYs722vigvzH5eHLIZTOhGBE2//uH8pw1YnMW9sYRj f5algDGge4hZvi0ieQyzfT3UqmQEmZZCz+vdlPtgKqIj6+I+V+SZOB2d aBkb/0NrWIx+iE+fqP6jx7I2HCobVnYUvJjL/t6O1shC4mxcDghLLUpf fSnEag==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ net. IN NS
+ SECTION AUTHORITY
+ net. 172800 IN NS j.gtld-servers.net.
+ net. 172800 IN NS e.gtld-servers.net.
+ net. 172800 IN NS c.gtld-servers.net.
+ net. 172800 IN NS m.gtld-servers.net.
+ net. 172800 IN NS d.gtld-servers.net.
+ net. 172800 IN NS i.gtld-servers.net.
+ net. 172800 IN NS a.gtld-servers.net.
+ net. 172800 IN NS g.gtld-servers.net.
+ net. 172800 IN NS h.gtld-servers.net.
+ net. 172800 IN NS b.gtld-servers.net.
+ net. 172800 IN NS k.gtld-servers.net.
+ net. 172800 IN NS f.gtld-servers.net.
+ net. 172800 IN NS l.gtld-servers.net.
+ net. 86400 IN DS 35886 8 2 7862B27F5F516EBE19680444D4CE5E762981931842C465F00236401D 8BD973EE
+ net. 86400 IN RRSIG DS 8 1 86400 20170312170000 20170227160000 61045 . bRSoCpmN/6LhmSB7i68N0zO08WwVikjm6HhOyZMhyjF4sfAaDoeTMs5E XjflCZMly1SP8CwkK6Wz6Ozb8nMUHEsYOhASVBkYC/ImBpqIV5LxaCbW 4L7g5Mwam0MBZb4hybI7JUyuiRONVy3YYk+eUvyf4/flu3Cl14a36LYv 2In/ECg9sV8cMOrYs722vigvzH5eHLIZTOhGBE2//uH8pw1YnMW9sYRj f5algDGge4hZvi0ieQyzfT3UqmQEmZZCz+vdlPtgKqIj6+I+V+SZOB2d aBkb/0NrWIx+iE+fqP6jx7I2HCobVnYUvJjL/t6O1shC4mxcDghLLUpf fSnEag==
+ SECTION ADDITIONAL
+ a.gtld-servers.net. 172800 IN A 192.5.6.30
+ b.gtld-servers.net. 172800 IN A 192.33.14.30
+ c.gtld-servers.net. 172800 IN A 192.26.92.30
+ d.gtld-servers.net. 172800 IN A 192.31.80.30
+ e.gtld-servers.net. 172800 IN A 192.12.94.30
+ f.gtld-servers.net. 172800 IN A 192.35.51.30
+ g.gtld-servers.net. 172800 IN A 192.42.93.30
+ h.gtld-servers.net. 172800 IN A 192.54.112.30
+ i.gtld-servers.net. 172800 IN A 192.43.172.30
+ j.gtld-servers.net. 172800 IN A 192.48.79.30
+ k.gtld-servers.net. 172800 IN A 192.52.178.30
+ l.gtld-servers.net. 172800 IN A 192.41.162.30
+ m.gtld-servers.net. 172800 IN A 192.55.83.30
+ a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+ b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+ ENTRY_END
+
+
+RANGE_END
+
+;cz
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ ADDRESS 194.0.13.1
+ ADDRESS 194.0.14.1
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:f::1
+ ADDRESS 2001:678:10::1
+ ADDRESS 2001:678:11::1
+ ADDRESS 2001:678:1::1
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ nic.cz. IN DS
+ SECTION ANSWER
+ nic.cz. 14400 IN DS 61281 13 2 4104D40C8FE2030BF7A09A199FCF37B36F7EC8DDD16F5A84F2E61C24 8D3AFD0F
+ nic.cz. 14400 IN RRSIG DS 10 2 14400 20170312221837 20170228130956 58211 cz. LKiLo/EqBTsv1e6s8p5UfN/qZfd3Dnf5XGO11vW2pELybdmmpD5clR/v mz+cc4zxLiQAxDnBpdUPAPdxcPlILa5mjMfJy2ExsQOZhcbIUInRala6 GhBfGy3bnniJkJCu7sAIsf+HyDM92pFSql67ErS0ROERBhSRVbfunEBy FCo=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ a.ns.nic.cz. IN A
+ SECTION ANSWER
+ a.ns.nic.cz. 1800 IN A 194.0.12.1
+ a.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20170314061428 20170228072511 16836 nic.cz. rJsAWa5cYGooRzu5+jRW5m4ebYHPkHRBwrLT5P7lIkT5VkcoIRYMcdYf gr+pXJFM9IduSZJXfomumKyOYHts7Q==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ b.ns.nic.cz. IN A
+ SECTION ANSWER
+ b.ns.nic.cz. 1800 IN A 194.0.13.1
+ b.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20170314044412 20170228072511 16836 nic.cz. 6dOVqiXZgfp1fltylhOAYvfILWCGu61cpabseUNTmb20TZR1GuI5ueTS lmYa93o46M+01ATfrkwBWZC065G8yg==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ c.ns.nic.cz. IN A
+ SECTION ANSWER
+ c.ns.nic.cz. 1800 IN A 194.0.14.1
+ c.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20170314015427 20170228072511 16836 nic.cz. 824yJyP2dWJ7phi63r1/24v0SbzU9FVi7b8IkXIrQ+3aCTyXKugE8l8C qLz6qwulzu2aG+8SyfvenXDSySqiqQ==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ d.ns.nic.cz. IN A
+ SECTION ANSWER
+ d.ns.nic.cz. 1800 IN A 193.29.206.1
+ d.ns.nic.cz. 1800 IN RRSIG A 13 4 1800 20170313233915 20170228072511 16836 nic.cz. KAlDHStrGzdtoBe9epn87lsggg6vVvHPGMPv/njWSTns7BX0//fTxfOc iOXdutsQhq/8Z2o87pKzE2F9FbE6Hw==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ a.ns.nic.cz. IN AAAA
+ SECTION ANSWER
+ a.ns.nic.cz. 1800 IN AAAA 2001:678:f::1
+ a.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20170313215345 20170228072511 16836 nic.cz. GMmWVeCiIzq2kt4VmsDXGSaAWMtDB78+Yz7qgEqu5C1PAUUBQo4o5lU/ igGhIJHk2BSljJxjaL+LlnW3uOeCDQ==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ b.ns.nic.cz. IN AAAA
+ SECTION ANSWER
+ b.ns.nic.cz. 1800 IN AAAA 2001:678:10::1
+ b.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20170314011606 20170228072511 16836 nic.cz. ALfV0l2a4D1CITaZdP5k5Mc+uTZ1dSb3SRm1Z+AQmeQLKI7YrFlOCuUa q90yMQnG+0GMS4uwSmIcT3V2cjpBXw==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ c.ns.nic.cz. IN AAAA
+ SECTION ANSWER
+ c.ns.nic.cz. 1800 IN AAAA 2001:678:11::1
+ c.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20170313184936 20170228072511 16836 nic.cz. U/tpYchWTle9loCW8fPIMoF3zto86UmFFCSnU7sFG9Qxk4I8fNUro1nT fAeJlrI7L7Yx9qlJTAllzrPjuw+3IA==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ d.ns.nic.cz. IN AAAA
+ SECTION ANSWER
+ d.ns.nic.cz. 1800 IN AAAA 2001:678:1::1
+ d.ns.nic.cz. 1800 IN RRSIG AAAA 13 4 1800 20170313124110 20170228072511 16836 nic.cz. kOI6MVJDSexQQ6uGT7KBjrTB2PDs49Cm65heInzMGZ20R75wO0JhSlce /T+Rpw3R0XpBre39h2DF7yBgePr+qg==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ cz. IN NS
+ SECTION ANSWER
+ cz. 14400 IN NS a.ns.nic.cz.
+ cz. 14400 IN NS b.ns.nic.cz.
+ cz. 14400 IN NS d.ns.nic.cz.
+ cz. 14400 IN NS c.ns.nic.cz.
+ cz. 14400 IN RRSIG NS 10 1 14400 20170307183707 20170222123920 58211 cz. Ma2XNvMziL3GtyLXtKcCBBG12+r7Uor3OFTw6c7Txk573/Y33IMnbN6B iKz0hZw0XK5c6nHciMEDkH2K772fcskHjEnOg+bJMBJlUmqskbVBmwpZ Dd156QC9OIfcE6yJYa6Y1jOegpgCaZLXRDOZodtvvTkYWNP/D01cmsF6 U+4=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ CZ. IN DNSKEY
+ SECTION ANSWER
+ cz. 18000 IN DNSKEY 256 3 10 AwEAAdWL2Br92Vx0dLEOOB8y02ss8LtKIyGlLJ2ymJ02WqR3AAEEZN0f NPKF77kdKsjlG8DlzmSIOR12aa9EhpXqyHOwWI0kHOMJVnn6ZKFIAl71 JP/dYIcshYUxKZZMe+zEAUrVtzlLVDtM6cDOPDuBNa1ujYec3eJl9Ipq eUEG6gAH
+ cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+ cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170304000000 20170218000000 54576 cz. paDUYJRI+4qBfPaGBy7nVMQnsp2hQQdiWWMnNunhfemFYi9MtXE2VTG3 DDL4Kue3ImSko/BxCRqHxHq5Sdf4LNexFWqFUlz4CjVeFobGTmmgOlak Sm2WygfZsO3w1OeO5cDCZTbi6XAhkr1cL3sgJR+/aOKIGUs8uIk1pZ5H WGNB1waF7Euxe+joEFtoj2/Tk7G7AlD1/Hw+pw5AkLTNawpHJF1/vnfT mPxdPHhJYCHlQdBE9dLkqQk7swnxMegBiUCeRd7SRiGq+1wubYsGirwl RZfYQpcqMnLH/1KITlVkKNYKnUGLjej4XRCDZOe3j8geIyS7WCJ5OPnU Lw0KDA==
+ cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170313144128 20170228113958 58211 cz. xSEKl8ttuDR9Q3YjtVX+dPfdtwd4OG6rooml9TDIKNlND9LRTceRnpEH EsxUumTrRfWh8P4HWZF+B7hdm8qvcxAS3X3TYT4T7fKV5AFQbbMh+fv9 nut2RcZF40/x/0Hxh6QPLAtMDZs4W8IovQnpiTw8am9UoJNP+tT+dsgw ndA=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ nic.cz. IN DNSKEY
+ SECTION ANSWER
+ nic.cz. 1800 IN DNSKEY 256 3 13 vtFRotT17dIOLFIWi8BVFpHu8Thf/BrslFNNWlH2PPucF1rec69vuJi2 MswwoRtYQpRehbsjsjJ7kxXlTtfaFw==
+ nic.cz. 1800 IN DNSKEY 257 3 13 LM4zvjUgZi2XZKsYooDE0HFYGfWp242fKB+O8sLsuox8S6MJTowY8lBD jZD7JKbmaNot3+1H8zU9TrDzWmmHwQ==
+ nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20170313103655 20170228072511 61281 nic.cz. mA899bEiTCULWpuF2JpVSm3wyHWmHIYuRMJj2X2E0AUhdbX2zhuSun8q EjKpr/0FfZCmlJIEC6dXmjIV+X0jhg==
+ nic.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20170313194411 20170228072511 16836 nic.cz. iYJgEoykgdz6aqrE1DwM6fyWUFI2pDShqgfg7TiMaunyuvi2JwUaSbEq Ifm2aO5gF7bqSQjM+Y0NOzZ5nAUKrg==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ lidovky.cz. IN DS
+ SECTION ANSWER
+ lidovky.cz. 14400 IN DS 1901 8 2 1ED680FFBD77C4845A9BE15286FC73A756B6E4150C65DBC52EE4799B 641DFCE3
+ lidovky.cz. 14400 IN DS 4555 8 2 E4B03345B8E0EB3CD9208D2FA60F835A1E391CC485E84CBF3CB1136B D7748913
+ lidovky.cz. 14400 IN RRSIG DS 10 2 14400 20170312182850 20170228113958 58211 cz. yw/iboH4hKxLOv+0Mbyvp4rnT14IxkiOpk6kW7ANJI2AGoBa5L7oGy6F 4eEuc2AZKrn/FP2OZL8mItt0hBCucHpaBeRyx8n78pCuMnEaYs/Buxro 0S/bpkMhTRTTJCQ2uwKHAAfi2Q3PC1CWLKB8p7MbN21JlC3S7ANu0DgL 4Ro=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ lidovky.cz. IN NS
+ SECTION AUTHORITY
+ lidovky.cz. 14400 IN NS ns.mafra.cz.
+ lidovky.cz. 14400 IN NS ns.mafracz.net.
+ lidovky.cz. 14400 IN NS ns2.mafra.cz.
+ lidovky.cz. 14400 IN DS 1901 8 2 1ED680FFBD77C4845A9BE15286FC73A756B6E4150C65DBC52EE4799B 641DFCE3
+ lidovky.cz. 14400 IN DS 4555 8 2 E4B03345B8E0EB3CD9208D2FA60F835A1E391CC485E84CBF3CB1136B D7748913
+ lidovky.cz. 14400 IN RRSIG DS 10 2 14400 20170312182850 20170228113958 58211 cz. yw/iboH4hKxLOv+0Mbyvp4rnT14IxkiOpk6kW7ANJI2AGoBa5L7oGy6F 4eEuc2AZKrn/FP2OZL8mItt0hBCucHpaBeRyx8n78pCuMnEaYs/Buxro 0S/bpkMhTRTTJCQ2uwKHAAfi2Q3PC1CWLKB8p7MbN21JlC3S7ANu0DgL 4Ro=
+ SECTION ADDITIONAL
+ ns.mafra.cz. 18000 IN A 194.79.53.77
+ ns2.mafra.cz. 18000 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ mafra.cz. IN DS
+ SECTION AUTHORITY
+ cz. 900 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1488285598 900 300 604800 900
+ cz. 900 IN RRSIG SOA 10 1 14400 20170314055727 20170228113958 58211 cz. LBUALMOXd40KawVmUNWNlfMbeR0LDwNI5DPu9HqF8rtWCtHxReSGPrYs lyaL6gzVOn+i9Zikolj2arR+XPrb3vDMBjhh1AhP83p6Dfk4z0nEeaVy bJBdCSrcXcOi72RXY1QpO6lfhkpW2rhYtKS0Pq0rPVSF6rFVSLMavD82 X9s=
+ NP199O12UJ32S0N5CTA47VUUQK1B2N6P.cz. 900 IN NSEC3 1 0 10 34817B0B5673BB5D NP19M6SR9GQ4GR722R31PHMCCMV2L47C NS
+ NP199O12UJ32S0N5CTA47VUUQK1B2N6P.cz. 900 IN RRSIG NSEC3 10 2 900 20170309110321 20170224213957 58211 cz. Brz4hpl2jq+rhJlu9tZ6Ij0Ru4+2Yyw5a4OVgN4/umq/9jPn2dWgnOPS 6Mk5WIC9Yun9ZIvncS3oE1dRhXAF+nGZS9jr1tdXLx+1Sow4o0nP8cxw 8Sl8BVjBkDpVSZfGVMN06NjJub57uw5nDF3E/AjoCYDxnb0UrVmIGCUb h7A=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ mafra.cz. IN NS
+ SECTION AUTHORITY
+ mafra.cz. 14400 IN NS ns.mafra.cz.
+ mafra.cz. 14400 IN NS ns.mafracz.net.
+ mafra.cz. 14400 IN NS ns2.mafra.cz.
+ np199o12uj32s0n5cta47vuuqk1b2n6p.cz. 900 IN NSEC3 1 0 10 34817B0B5673BB5D NP19M6SR9GQ4GR722R31PHMCCMV2L47C NS
+ np199o12uj32s0n5cta47vuuqk1b2n6p.cz. 900 IN RRSIG NSEC3 10 2 900 20170309110321 20170224213957 58211 cz. Brz4hpl2jq+rhJlu9tZ6Ij0Ru4+2Yyw5a4OVgN4/umq/9jPn2dWgnOPS 6Mk5WIC9Yun9ZIvncS3oE1dRhXAF+nGZS9jr1tdXLx+1Sow4o0nP8cxw 8Sl8BVjBkDpVSZfGVMN06NjJub57uw5nDF3E/AjoCYDxnb0UrVmIGCUb h7A=
+ SECTION ADDITIONAL
+ ns.mafra.cz. 7275 IN A 194.79.53.77
+ ns2.mafra.cz. 7275 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ idnes.cz. IN DS
+ SECTION AUTHORITY
+ cz. 900 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 1488285598 900 300 604800 900
+ cz. 900 IN RRSIG SOA 10 1 14400 20170314055727 20170228113958 58211 cz. LBUALMOXd40KawVmUNWNlfMbeR0LDwNI5DPu9HqF8rtWCtHxReSGPrYs lyaL6gzVOn+i9Zikolj2arR+XPrb3vDMBjhh1AhP83p6Dfk4z0nEeaVy bJBdCSrcXcOi72RXY1QpO6lfhkpW2rhYtKS0Pq0rPVSF6rFVSLMavD82 X9s=
+ AUOICN1434M9JOGSCEGTCFV7NUDKO603.cz. 900 IN NSEC3 1 0 10 34817B0B5673BB5D AUOJ570J8RB3057RHUJ1DAGMCO1GAUDH NS
+ AUOICN1434M9JOGSCEGTCFV7NUDKO603.cz. 900 IN RRSIG NSEC3 10 2 900 20170313031226 20170227134003 58211 cz. CMvsPy0Ce7UR692R7jMat7E9Mm2DHTcZz7b5PlwsNX3i+41Ymlh1TeAs utrGbJUR+cdKQStzN6uNsxGQ84zFmeqOvMKtZBbvdavQbXtDfwTuEplX XolQ82j/0wVYCkpYANkLmyLrwbbZxJ4sSb1sbVRtMN0daeE6y3OleQDk 2Uw=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ idnes.cz. IN NS
+ SECTION AUTHORITY
+ idnes.cz. 14400 IN NS ns.mafra.cz.
+ idnes.cz. 14400 IN NS ns.mafracz.net.
+ idnes.cz. 14400 IN NS ns2.mafra.cz.
+ auoicn1434m9jogscegtcfv7nudko603.cz. 900 IN NSEC3 1 0 10 34817B0B5673BB5D AUOJ570J8RB3057RHUJ1DAGMCO1GAUDH NS
+ auoicn1434m9jogscegtcfv7nudko603.cz. 900 IN RRSIG NSEC3 10 2 900 20170313031226 20170227134003 58211 cz. CMvsPy0Ce7UR692R7jMat7E9Mm2DHTcZz7b5PlwsNX3i+41Ymlh1TeAs utrGbJUR+cdKQStzN6uNsxGQ84zFmeqOvMKtZBbvdavQbXtDfwTuEplX XolQ82j/0wVYCkpYANkLmyLrwbbZxJ4sSb1sbVRtMN0daeE6y3OleQDk 2Uw=
+ SECTION ADDITIONAL
+ ns.mafra.cz. 18000 IN A 194.79.53.77
+ ns2.mafra.cz. 18000 IN A 194.79.55.77
+ ENTRY_END
+
+RANGE_END
+
+;net
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ ADDRESS 192.33.14.30
+ ADDRESS 192.26.92.30
+ ADDRESS 192.31.80.30
+ ADDRESS 192.12.94.30
+ ADDRESS 192.35.51.30
+ ADDRESS 192.42.93.30
+ ADDRESS 192.54.112.30
+ ADDRESS 192.43.172.30
+ ADDRESS 192.48.79.30
+ ADDRESS 192.52.178.30
+ ADDRESS 192.41.162.30
+ ADDRESS 192.55.83.30
+ ADDRESS 2001:503:a83e::2:30
+ ADDRESS 2001:503:231d::2:30
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ net. IN DNSKEY
+ SECTION ANSWER
+ net. 86400 IN DNSKEY 257 3 8 AQOYBnzqWXIEj6mlgXg4LWC0HP2n8eK8XqgHlmJ/69iuIHsa1TrHDG6T cOra/pyeGKwH0nKZhTmXSuUFGh9BCNiwVDuyyb6OBGy2Nte9Kr8NwWg4 q+zhSoOf4D+gC9dEzg0yFdwT0DKEvmNPt0K4jbQDS4Yimb+uPKuF6yie WWrPYYCrv8C9KC8JMze2uT6NuWBfsl2fDUoV4l65qMww06D7n+p7Rbdw WkAZ0fA63mXVXBZF6kpDtsYD7SUB9jhhfLQE/r85bvg3FaSs5Wi2BaqN 06SzGWI1DHu7axthIOeHwg00zxlhTpoYCH0ldoQz+S65zWYi/fRJiyLS Bb6JZOvn
+ net. 86400 IN DNSKEY 256 3 8 AQPMYWRP6GrTFoGFNQyuta0p4VYHr5Ox7yOl0Zv5ejOeRUnmoVgvHUR0 8lmmKEnBBPPZ89f/spt8VQ3GFUAbjJVzlcF5dQbY26YO/XKNcB2dlCEy quowoOQYsbASUj91c0IfFXAbK10reyShzaUi76p2VG5f0tjq/iC4iMZJ yxcpRQ==
+ net. 86400 IN RRSIG DNSKEY 8 1 86400 20170306173857 20170219173357 35886 net. Vvmjg9riU5c81z+4GEMSV4kEHf0ds2lxyD/UmGB4Vjtu0S71KldD4hh2 nA086G2Ssl1gBFEcVkLdPPpvh/c39mSITollT43u55pBLGQQcRXqPL6X 5xjlsOayD4QfwszBn5/5QTSD9pB5D9AsGQARlQTa0Vp1O9ruFDq0BuVQ F4P2QkNaxM6T+QZdFtqFOe6n3H+Qn0/TEvbM72w0hIBr1po3aSZuJleN SR3Wbubs1H7p1E6a6FH2+rRb3t7Q5DWNT/P5kZU0j+JB1PRknSwWCv7n orxIfhoYuFqU8Gw9w5KSw+Qtc7AjxlawQSAAZPLaq9ZL2cEKkeUrEGTD V41adg==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ net. IN DS
+ SECTION ANSWER
+ net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1488288307 1800 900 604800 86400
+ net. 900 IN RRSIG SOA 8 1 900 20170307132507 20170228121507 16757 net. aeKdMkRb/POrt2pw0h0O8fN8EUXFXJlPHu/aHtIihIEkj85ZpCNrEOxr Zg5jkYtPXQwx+X0cnD/uNMEWPOD3vNW3Ap9Y01RlFBzvlBHeH4YA09tr ElBPqkzN6bNrNJi3V/yJjV2dy7IUvqDO9M5cQEuPHIED2sIh1FATmB6b KMs=
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ net. IN NS
+ SECTION ANSWER
+ net. 172800 IN NS i.gtld-servers.net.
+ net. 172800 IN NS e.gtld-servers.net.
+ net. 172800 IN NS h.gtld-servers.net.
+ net. 172800 IN NS b.gtld-servers.net.
+ net. 172800 IN NS a.gtld-servers.net.
+ net. 172800 IN NS j.gtld-servers.net.
+ net. 172800 IN NS f.gtld-servers.net.
+ net. 172800 IN NS m.gtld-servers.net.
+ net. 172800 IN NS l.gtld-servers.net.
+ net. 172800 IN NS g.gtld-servers.net.
+ net. 172800 IN NS k.gtld-servers.net.
+ net. 172800 IN NS c.gtld-servers.net.
+ net. 172800 IN NS d.gtld-servers.net.
+ net. 172800 IN RRSIG NS 8 1 172800 20170304061505 20170225050505 16757 net. Pq4fze7lagq5NaKm7P4plOCY4gbFH3ZqZPvWIMojqNgHmoboqXWpth7R s2th1NzR7fxTvxngwVFlO7tR2Sf19epNimuJHEkxAKceLtSfdwxilfMz WvPq5/2tCINU8xo/SOC13ST4zq3PUi+VfPYbRF+5SakOTkU/6m1+9hlo ixo=
+ SECTION ADDITIONAL
+ a.gtld-servers.net. 172800 IN A 192.5.6.30
+ b.gtld-servers.net. 172800 IN A 192.33.14.30
+ c.gtld-servers.net. 172800 IN A 192.26.92.30
+ d.gtld-servers.net. 172800 IN A 192.31.80.30
+ e.gtld-servers.net. 172800 IN A 192.12.94.30
+ f.gtld-servers.net. 172800 IN A 192.35.51.30
+ g.gtld-servers.net. 172800 IN A 192.42.93.30
+ h.gtld-servers.net. 172800 IN A 192.54.112.30
+ i.gtld-servers.net. 172800 IN A 192.43.172.30
+ j.gtld-servers.net. 172800 IN A 192.48.79.30
+ k.gtld-servers.net. 172800 IN A 192.52.178.30
+ l.gtld-servers.net. 172800 IN A 192.41.162.30
+ m.gtld-servers.net. 172800 IN A 192.55.83.30
+ a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30
+ b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ root-servers.net. IN DS
+ SECTION AUTHORITY
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1488288412 1800 900 604800 86400
+ net. 900 IN RRSIG SOA 8 1 900 20170307132652 20170228121652 16757 net. VnpLNPVwJO8pW1+aHC5jGq17aTVQuWMfu7igBcig9XG9li1wVBtawqaB zpiT8zoUWa76qkydyhuKWNjR895eLQz1Ql0cboW8GIddDFfKacpEP9nr QWwqjiMltfXn+iGiumrDbxwHKvwllXhOIShR5uAT640UcJ7QMhrq2jrJ V+Y=
+ T2UFL481TTPOHR68HR18DHJAFU935MJU.net. 86400 IN NSEC3 1 1 0 - T2UKCT9K5I0UHV7B3M3NA6JAIGDJM0GR NS DS RRSIG
+ T2UFL481TTPOHR68HR18DHJAFU935MJU.net. 86400 IN RRSIG NSEC3 8 2 86400 20170307061346 20170228050346 16757 net. KpGr8ZrjFGZ2q39FPpGe9SBR4hJ1e8L9oyvO5JS7Eh4LVdjwsD8B13nQ 7iv6jdCWVIWXh41fB4dcCUvLYqd9d75bACQ4JQVR3ycON9Qwt2XiUyVk iBYm7cp9C78+Uj0/P3TClk90GtZaAb3+JXUZZvrK08HnivVtmTta1Laj TVk=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ gtld-servers.net. IN DS
+ SECTION AUTHORITY
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1488288457 1800 900 604800 86400
+ net. 900 IN RRSIG SOA 8 1 900 20170307132737 20170228121737 16757 net. x5j/Iiv9Bey7T4FSeICdJrAyn5tEubHlhQXGmjM4KAVEq1CybM70rL7s HrwAhyiC/9RobYaMhM4fxmji3h8vWYbWauGMZ5XXmRGL66jE6Zq/M99v zk7RDnedNS+vPAv49PJ5aICGs4hfapPg3Kwf/KKwDzzvactaRYPvptLX u74=
+ 5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5QDPPOTUK27KKP9LIGTRB0K1CBVM9CIM NS DS RRSIG
+ 5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306060531 20170227045531 16757 net. uV9O+X7Vk1+dgIdqY2qE5RvN4B4Nv+xDLjd5V30sapNI8ARrA8d9pEVY qGNU5tF8+VT3lukCjvfgfopyTjw+SO+x4fwpZenmehwgNFkMHYWAv/1l xrdZHw60JMa/jWy+Rtdqi2uBJMGldGEIiuLEHgkKAjub2wtdiEkl2Azo AeY=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ gtld-servers.net. IN NS
+
+ SECTION AUTHORITY
+ gtld-servers.net. 172800 IN NS av1.nstld.com.
+ gtld-servers.net. 172800 IN NS av2.nstld.com.
+ gtld-servers.net. 172800 IN NS av3.nstld.com.
+ gtld-servers.net. 172800 IN NS av4.nstld.com.
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ 5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN NSEC3 1 1 0 - 5QDPPOTUK27KKP9LIGTRB0K1CBVM9CIM NS DS RRSIG
+ 5QD8VL68T2I9KOBD32KJ8LJVH5OH2PQ0.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306060531 20170227045531 16757 net. uV9O+X7Vk1+dgIdqY2qE5RvN4B4Nv+xDLjd5V30sapNI8ARrA8d9pEVY qGNU5tF8+VT3lukCjvfgfopyTjw+SO+x4fwpZenmehwgNFkMHYWAv/1l xrdZHw60JMa/jWy+Rtdqi2uBJMGldGEIiuLEHgkKAjub2wtdiEkl2Azo AeY=
+
+ SECTION ADDITIONAL
+ av1.nstld.com. 172800 IN A 192.42.177.30
+ av1.nstld.com. 172800 IN AAAA 2001:500:124::30
+ av2.nstld.com. 172800 IN A 192.42.178.30
+ av2.nstld.com. 172800 IN AAAA 2001:500:125::30
+ av3.nstld.com. 172800 IN A 192.82.133.30
+ av3.nstld.com. 172800 IN AAAA 2001:500:126::30
+ av4.nstld.com. 172800 IN A 192.82.134.30
+ av4.nstld.com. 172800 IN AAAA 2001:500:127::30
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qname qtype
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ a.gtld-servers.net. IN A
+ SECTION ANSWER
+ a.gtld-servers.net. 172800 IN A 192.5.6.30
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ gtld-servers.net. IN A
+ SECTION AUTHORITY
+ gtld-servers.net. 86400 IN SOA av4.nstld.com. nstld.verisign-grs.com. 2016101000 3600 900 1209600 86400
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ a.root-servers.net. IN A
+ SECTION AUTHORITY
+ root-servers.net. 172800 IN NS a.root-servers.net.
+ SECTION ADDITIONAL
+ a.root-servers.net. 3600000 IN A 198.41.0.4
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ root-servers.net. IN AAAA
+ SECTION AUTHORITY
+ root-servers.net. 172800 IN NS a.root-servers.net.
+ SECTION ADDITIONAL
+ a.root-servers.net. 172800 IN A 198.41.0.4
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ mafracz.net. IN DS
+ SECTION AUTHORITY
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1488288547 1800 900 604800 86400
+ net. 900 IN RRSIG SOA 8 1 900 20170307132907 20170228121907 16757 net. y7pu7BBxAqE7l+JB4PIg/2l+WPgeOrSo+TRo2vKqVJFa03GttNi4BlWH s0sT3t4Mr0nvWxNf7PlUUct7KFssGGCu6kXC3RiZsXDaTeAnHjAfk9rg v/z6PM7fU3shLjEXDuIY9GtPAw65nbSeK1Sai/3gWUOnlxo1J2r3VXl3 cfE=
+ P61KBBD5BIIR8OO46HQUMTGEQAU7RAQJ.net. 86400 IN NSEC3 1 1 0 - P61TM41BB9FNGTRQ6D1PPAU0E9MD6S63 NS DS RRSIG
+ P61KBBD5BIIR8OO46HQUMTGEQAU7RAQJ.net. 86400 IN RRSIG NSEC3 8 2 86400 20170304061336 20170225050336 16757 net. QKFFK4L57Pzylgc3d/9Z5R++Cqxx5agyEG6HPcGtjCSslA7DEj+qULoy TTWNBpgzPgwwrZy0BdNYBZdC3rpdfiJqCidVXe7bRfUQDHY4NJiuouOv jLGxYf/k8gqKAElV9CriTBkkjALwXdlDvCSMnhczMlu0409YoL3XKBdE TCc=
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode subdomain
+ ADJUST copy_id copy_query
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ mafracz.net. IN NS
+ SECTION AUTHORITY
+ mafracz.net. 172800 IN NS ns.mafra.cz.
+ mafracz.net. 172800 IN NS ns2.mafra.cz.
+ mafracz.net. 172800 IN NS ns.mafracz.net.
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN NSEC3 1 1 0 - A1RUUFFJKCT2Q54P78F8EJGJ8JBK7I8B NS SOA RRSIG DNSKEY NSEC3PARAM
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net. 86400 IN RRSIG NSEC3 8 2 86400 20170306061207 20170227050207 16757 net. s53ftACmRAtcKkfowIENgWkCuHNoyesDp5kz1g62Uxm9v03ig4TkMMBW cUMvLFCp1XpmiOx9MX5klfJgFrhQPYmaRBuQaI3nrH6B57kjsphtJYvc B6wyRGPHAg+oNecZqQbUBEkzBrppoe4a5nhlOkLgbHKb5qPbN0tV5wBu x5c=
+ P61KBBD5BIIR8OO46HQUMTGEQAU7RAQJ.net. 86400 IN NSEC3 1 1 0 - P61TM41BB9FNGTRQ6D1PPAU0E9MD6S63 NS DS RRSIG
+ P61KBBD5BIIR8OO46HQUMTGEQAU7RAQJ.net. 86400 IN RRSIG NSEC3 8 2 86400 20170304061336 20170225050336 16757 net. QKFFK4L57Pzylgc3d/9Z5R++Cqxx5agyEG6HPcGtjCSslA7DEj+qULoy TTWNBpgzPgwwrZy0BdNYBZdC3rpdfiJqCidVXe7bRfUQDHY4NJiuouOv jLGxYf/k8gqKAElV9CriTBkkjALwXdlDvCSMnhczMlu0409YoL3XKBdE TCc=
+ SECTION ADDITIONAL
+ ns.mafracz.net. 165236 IN A 185.17.118.250
+ ENTRY_END
+RANGE_END
+
+
+RANGE_BEGIN 0 100
+ ADDRESS 194.79.53.77
+ ADDRESS 185.17.118.250
+ ADDRESS 194.79.55.77
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ ns.mafracz.net. IN A
+ SECTION ANSWER
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ SECTION AUTHORITY
+ mafracz.net. 600 IN NS ns2.mafra.cz.
+ mafracz.net. 600 IN NS ns.mafracz.net.
+ mafracz.net. 600 IN NS ns.mafra.cz.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id copy_query
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ lidovky.cz. IN DNSKEY
+ SECTION ANSWER
+ lidovky.cz. 3600 IN DNSKEY 256 3 8 AwEAAb8GYuVqOqVTYuppOCtctAHJ38tuSVriiptyQcxdZsU7U7s2XFVp QAuTxxoBOuvJZLMLXNikOki1KCnQx030Zz73AFx8tiPS6rFzR71TJXTC HlpwDnnK3rkdsu6Ay85cLiRtFpgW1D1WPi5oCJWGs4dJ8L5mcoIYikZt 99cfDKY/
+ lidovky.cz. 3600 IN DNSKEY 256 3 8 AwEAActfDtlHpl0/2f9qMqDt5uslMzxKDNf4FGklmcG+OO2HuhOhnQVx arB6lYxIKofy+uOvUhyGxlxCq08bVKueBpAt0x5kLMAwhc6zmn8niIE6 +UZxLg7+r2ojLTl0qQ2sMoG6ryo4/1GCEwh/TjJp8PuAzE0Q7yQOE6ed jZkWjraJ
+ lidovky.cz. 3600 IN DNSKEY 257 3 8 AwEAAeFABHDi1QXB2WaYeLP07RzSfn9IIjMFrL6+obHNgMpY32skT0fX +4YiF1vrAwI3FyvqvLERcUqZl3kMFk/mBDEBcCCP8osbndEUEEg2fVkZ gPDVWT3nCBMXRRuXmddn+L7o18wTUTBbLCxCT22ROOqahUyDEHvHpUbq LTbY+GGnSNzAD9/BWFdMIGOKzQ8oYFFyWDGZYAcznojZO7gvpduw3slg t3YLv4iDxMIgFokCw+qQhf42xtmox7H6KfCaW59PdFfRRAc20JfpGxJ4 m2PAuuacgOoVkqRLqprJ0/NCmMJgQZ3yKQWe2QWfRP9lhmF9HXAVukyy Yh3+JaqulxM=
+ lidovky.cz. 3600 IN RRSIG DNSKEY 8 2 3600 20170305034217 20170226010009 1901 lidovky.cz. ElBtNV7iyYIWDExYkKJ+pwwIcSwJ6kXfiT3yFiwp43CqXg9KxMK55UBe nCToid81/xgGQmSnmHw8w5LQXs5CjiIamoMYCX0SCie0FsfvFx1871np CvzTeSr4U876wnZVAjmM/FnDP63/4SgIICZpMb3P/MU7M+zr93JgOMXs E0Zp4uR6puh7a52VMRBLBIEx4L8mw2TW3VU9an2FD5r6GnAqI5YqEY8P FpHdkb243AvB3rZBWtDiKFSzD+WsrqrDOL3lmA/Jcb5GcxA2CGxfTSCJ +ndebgdkFSwPXQxW7FQwdS4mTuPixdzonq8XtljLZSomyJ0mnepn0j7k lwklow==
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ lidovky.cz. IN A
+ SECTION ANSWER
+ lidovky.cz. 300 IN A 185.17.119.32
+ lidovky.cz. 300 IN RRSIG A 8 2 300 20170306080352 20170227090009 61408 lidovky.cz. rDSYYHIlE4Drq4/QLXrTDk+oeY6nh+W0p7cSeH9BGojdE4qIHjWUDjOS C4sEQpZtgG6EKO5j6P2+8bJ/3SmWdFT2GPHgP5eeRHPoo3iaGQMxXebD pbyVHtN//Gb577ycKcbNys/loflzhTWL2K1QXIHk53iWOTlDBg6uJcqi HsI=
+ SECTION AUTHORITY
+ lidovky.cz. 300 IN NS ns2.mafra.cz.
+ lidovky.cz. 300 IN NS ns.mafracz.net.
+ lidovky.cz. 300 IN NS ns.mafra.cz.
+ lidovky.cz. 300 IN RRSIG NS 8 2 300 20170304164701 20170225230009 61408 lidovky.cz. QmaLuzIDTiB/QbIgyxPRTVGFG/P5wFyrzlBtK7LIUsVIk8wuM9GudvQx weBiLPbaj28YypIdkS/z12sIawYenv4R9lswSVCOqT2H1KhXMtbW+BMk p5bCyr1mEJfceas6td4gywOydtfjYwU7WBvFPpMszP22p7jrizeQQpNB dK4=
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ www.lidovky.cz. IN A
+ SECTION ANSWER
+ www.lidovky.cz. 300 IN CNAME c23.idnes.cz.
+ www.lidovky.cz. 300 IN RRSIG CNAME 8 3 300 20170305033947 20170226030009 61408 lidovky.cz. VyqkB8Fzxs+LTz9WDKLMmbyrtq+V/5R1sYfYBQJPuVa3pJ1vX2I5M6XK n7TDu9gsW2v+zquOps/8aL/e/+R8ivEJomYzdnvH3EwfgT9WCOYJtlUL +sIq8eu45jXTVsFVLa0Fy5LKeFcfic+4C6AG676o5VSucVJLTWiftW47 RPA=
+ c23.idnes.cz. 300 IN A 185.17.119.54
+ SECTION AUTHORITY
+ idnes.cz. 300 IN NS ns.mafra.cz.
+ idnes.cz. 300 IN NS ns2.mafra.cz.
+ idnes.cz. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ c23.idnes.cz. IN A
+ SECTION ANSWER
+ c23.idnes.cz. 300 IN A 185.17.119.54
+ SECTION AUTHORITY
+ idnes.cz. 300 IN NS ns.mafra.cz.
+ idnes.cz. 300 IN NS ns2.mafra.cz.
+ idnes.cz. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ ns2.mafra.cz. IN A
+ SECTION ANSWER
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ SECTION AUTHORITY
+ mafra.cz. 300 IN NS ns.mafra.cz.
+ mafra.cz. 300 IN NS ns2.mafra.cz.
+ mafra.cz. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA RD DO NOERROR
+ SECTION QUESTION
+ ns.mafra.cz. IN A
+ SECTION ANSWER
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ SECTION AUTHORITY
+ mafra.cz. 300 IN NS ns.mafra.cz.
+ mafra.cz. 300 IN NS ns2.mafra.cz.
+ mafra.cz. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ lidovky.cz. IN NS
+ SECTION ANSWER
+ lidovky.cz. 300 IN NS ns.mafra.cz.
+ lidovky.cz. 300 IN NS ns2.mafra.cz.
+ lidovky.cz. 300 IN NS ns.mafracz.net.
+ lidovky.cz. 300 IN RRSIG NS 8 2 300 20170304164701 20170225230009 61408 lidovky.cz. QmaLuzIDTiB/QbIgyxPRTVGFG/P5wFyrzlBtK7LIUsVIk8wuM9GudvQx weBiLPbaj28YypIdkS/z12sIawYenv4R9lswSVCOqT2H1KhXMtbW+BMk p5bCyr1mEJfceas6td4gywOydtfjYwU7WBvFPpMszP22p7jrizeQQpNB dK4=
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ mafra.cz. IN NS
+ SECTION ANSWER
+ mafra.cz. 300 IN NS ns.mafra.cz.
+ mafra.cz. 300 IN NS ns2.mafra.cz.
+ mafra.cz. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ mafracz.net. IN NS
+ SECTION ANSWER
+ mafracz.net. 300 IN NS ns.mafra.cz.
+ mafracz.net. 300 IN NS ns2.mafra.cz.
+ mafracz.net. 300 IN NS ns.mafracz.net.
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO AA NOERROR
+ SECTION QUESTION
+ idnes.cz. IN NS
+ SECTION ANSWER
+ idnes.cz. 300 IN NS ns2.mafra.cz.
+ idnes.cz. 300 IN NS ns.mafracz.net.
+ idnes.cz. 300 IN NS ns.mafra.cz.
+
+ SECTION ADDITIONAL
+ ns.mafra.cz. 300 IN A 194.79.53.77
+ ns.mafracz.net. 600 IN A 185.17.118.250
+ ns2.mafra.cz. 300 IN A 194.79.55.77
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ ns.mafra.cz. IN AAAA
+ SECTION AUTHORITY
+ mafra.cz. 291 IN SOA ns.mafra.cz. hostmaster.mafra.cz. 2017021601 3600 600 1209600 600
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ ns2.mafra.cz. IN AAAA
+ SECTION AUTHORITY
+ mafra.cz. 291 IN SOA ns.mafra.cz. hostmaster.mafra.cz. 2017021601 3600 600 1209600 600
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR RD DO NOERROR
+ SECTION QUESTION
+ ns.mafracz.net. IN AAAA
+ SECTION AUTHORITY
+ mafracz.net. 600 IN SOA ns.mafracz.net. hostmaster.mafra.cz. 2015061701 3600 600 86400 3600
+ ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+ REPLY RD DO
+ SECTION QUESTION
+ www.lidovky.cz IN A
+ENTRY_END
+
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH rcode question answer flags
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+ www.lidovky.cz IN A
+ SECTION ANSWER
+ www.lidovky.cz. 251 IN CNAME c23.idnes.cz.
+ www.lidovky.cz. 251 IN RRSIG CNAME 8 3 300 20170305033947 20170226030009 61408 lidovky.cz. VyqkB8Fzxs+LTz9WDKLMmbyrtq+V/5R1sYfYBQJPuVa3pJ1vX2I5M6XK n7TDu9gsW2v+zquOps/8aL/e/+R8ivEJomYzdnvH3EwfgT9WCOYJtlUL +sIq8eu45jXTVsFVLa0Fy5LKeFcfic+4C6AG676o5VSucVJLTWiftW47 RPA=
+ c23.idnes.cz. 251 IN A 185.17.119.54
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/world_cz_rhybar.rpl b/tests/deckard/sets/resolver/world_cz_rhybar.rpl
new file mode 100644
index 0000000..41a2d89
--- /dev/null
+++ b/tests/deckard/sets/resolver/world_cz_rhybar.rpl
@@ -0,0 +1,294 @@
+; test with real world Internet data
+; attempt to resolve www.rhybar.cz. A with CD first to populate BAD cache
+; and then try to resolve without any DNSSEC flag to see if it validates
+; correctly into Bogus status
+
+val-override-date: 20170201163631
+trust-anchor: ". 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"
+stub-addr: 2001:dc3::35
+CONFIG_END
+
+SCENARIO_BEGIN www.rhybar.cz.
+
+; DNS root
+RANGE_BEGIN 0 100
+ ADDRESS 192.33.4.12
+ ADDRESS 2001:500:2d::d
+ ADDRESS 2001:dc3::35
+ ADDRESS 192.36.148.17
+ ADDRESS 2001:500:12::d0d
+ ADDRESS 192.203.230.10
+ ADDRESS 199.7.83.42
+ ADDRESS 198.97.190.53
+ ADDRESS 2001:500:a8::e
+ ADDRESS 2001:500:9f::42
+ ADDRESS 2001:500:2::c
+ ADDRESS 2001:7fd::1
+ ADDRESS 193.0.14.129
+ ADDRESS 202.12.27.33
+ ADDRESS 192.58.128.30
+ ADDRESS 192.5.5.241
+ ADDRESS 2001:7fe::53
+ ADDRESS 198.41.0.4
+ ADDRESS 2001:500:2f::f
+ ADDRESS 199.7.91.13
+ ADDRESS 192.112.36.4
+ ADDRESS 2001:500:84::b
+ ADDRESS 192.228.79.201
+ ADDRESS 2001:503:c27::2:30
+ ADDRESS 2001:500:1::53
+ ADDRESS 2001:503:ba3e::2:30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170214050000 20170201040000 61045 . Ey0PFIQr/80otZwczK1hk0h+gxC8IRS9 F1BagrU8rKNcMWpp2cmYLOAeBABkkwdM c1Rg8ENJV17uDVEr32LWDWP1REjCKfI/ 2XXejWZ9jofcbDDNHQgvFX0xg+n3X+YV qG/WzOcHCmDGQNgFVhnC9K0JvO7pXmWS PJmESDO37XKLlFTdRtOYxYJ0wRaAMaBX irFD0qs/ePHyEPso4hg8cYIFeIbVzKgj jv0UrUJgc1V29GilKeYnWq7jHdJt/N0Q 18wgzEB0YlBL07zaq6DBvYCb6cjPoZQm iEKelHQ5MW297YzHGDVia03+5KgJFUhc XGcnMCQqnHxLEuQdY0syBQ==
+SECTION ADDITIONAL
+a.root-servers.net. 3600000 IN A 198.41.0.4
+a.root-servers.net. 3600000 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 3600000 IN A 192.228.79.201
+b.root-servers.net. 3600000 IN AAAA 2001:500:84::b
+c.root-servers.net. 3600000 IN A 192.33.4.12
+c.root-servers.net. 3600000 IN AAAA 2001:500:2::c
+d.root-servers.net. 3600000 IN A 199.7.91.13
+d.root-servers.net. 3600000 IN AAAA 2001:500:2d::d
+e.root-servers.net. 3600000 IN A 192.203.230.10
+e.root-servers.net. 3600000 IN AAAA 2001:500:a8::e
+f.root-servers.net. 3600000 IN A 192.5.5.241
+f.root-servers.net. 3600000 IN AAAA 2001:500:2f::f
+g.root-servers.net. 3600000 IN A 192.112.36.4
+g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 3600000 IN A 198.97.190.53
+h.root-servers.net. 3600000 IN AAAA 2001:500:1::53
+i.root-servers.net. 3600000 IN A 192.36.148.17
+i.root-servers.net. 3600000 IN AAAA 2001:7fe::53
+j.root-servers.net. 3600000 IN A 192.58.128.30
+j.root-servers.net. 3600000 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 3600000 IN A 193.0.14.129
+k.root-servers.net. 3600000 IN AAAA 2001:7fd::1
+l.root-servers.net. 3600000 IN A 199.7.83.42
+l.root-servers.net. 3600000 IN AAAA 2001:500:9f::42
+m.root-servers.net. 3600000 IN A 202.12.27.33
+m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN DS
+SECTION AUTHORITY
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017020101 1800 900 604800 86400
+. 86400 IN RRSIG SOA 8 0 86400 20170214170000 20170201160000 61045 . VD0rE7mpNaBtbxQiVerNLfdrAZc+YYPW u5GzNEOqScwW5EGamZe02t+pns6Z5LCJ dkka3yXTyIAPPrDig0z9VuYXt9pD45bf pB+9/sP0+oVtQZnuXRRsut9/Es3tuuMU 96O5RcFR8s/IeVfOmhq5hgNuSBrbWTxm 2EggbZ8RR1aUMTTTJorLver0xYQp8T6m LKrdRuC/jlgVH8/fmU+EUm0fZAtQTPDJ 5Q0XSigFYuX4aebIVn/YAtPKlG8twdq4 9tQ6QaUq8Qwx0w4fA+mizcPkufAn6/fs PYZlxhzibO+7L6/XpKR04+u1w5OCsNDy Aocf41ba1xkIJOJaqPNwVg==
+. 86400 IN RRSIG NSEC 8 0 86400 20170214170000 20170201160000 61045 . ThWu+J7xTDlcmWecgMSiRBhauX2dAHG4 RED8SZkdAw2w+0E/Du1+BNYBfnnJYJTr zkA4ThfIniNgeH5zWdlNU1ogDp0fcToI 3lz/yJ1zwJlcQFs0WNLKK0QMsjftF1wO VysIstlIu7+xgDTE/yz9fzBUMPpOh4qW 5G3xMU2Exqi4Qnn4LxPVn6jdLuygxwt+ oQ+qaMRSo3QOfBe5rwJsPQgM5S8k27mB jUmrasNHfqkWLy1nscoTtvyuOTIDh5pZ oXHCAaZbrGKAgovXjIeGCga1frtlCOOY JjUfjvahZXH0IHpP5IYkDsjM8r5iMIY7 6qrI5oHNHGeqkwV0/gJKzw==
+. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN RRSIG DNSKEY 8 0 172800 20170221000000 20170131000000 19036 . eq4bnmAmFeMpxfwZgDJcj+7oGo5XcBEK TbrXcBfztSS0RWvCzgFHyQSq7zjEV78M zgXCy/NfrN6wBLbSA7v1Q2Y3nWb9phiu SM422iqrUDdXue/iIj5JANdtDpzuiVAJ Fws/JWYl9TfzF3hfk6DjJttByUsZTKsl l6gQZsD/LcZ0cGYPNYWUz1geDXGawqjI 6o5wwdXSpEHUg2M4iN9yU0xeoz2si+E6 K+Sr6ZY20PfrWbanQrRX7Yhz3DMrwjk/ EuzQcLMxkkhqX8Lf9wlBfNk24NaK+L0q 1Fd5i3RNwlxJJP9DkEer7KTP43uoi8SU lzMfjKYd0pUUw7RES4VLdw==
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29 euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v 58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8 g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37 NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/E fucp2gaDX6RS6CXpoY68LsvPVjR0ZSwz z1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgu l0sGIcGOYl7OyQdXfZ57relSQageu+ip AdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1 dfwhYB4N7knNnulqQxA+Uk1ihz0=
+. 172800 IN DNSKEY 256 3 8 AwEAAYvgWbYkpeGgdPKaKTJU3Us4YSTR gy7+dzvfArIhi2tKoZ/WR1Dfw883SOU6 Uw7tpVRkLarN0oIMK/xbOBD1DcXnyfEl BwKsz4sVVWmfyr/x+igD/UjrcJ5zEBUr UmVtHyjar7ccaVc1/3ntkhZjI1hcungA lOhPhHlkMeX+5Azx6GdX//An5OgrdyH3 o/JmOPMDX1mt806JI/hf0EwAp1pBwo5e 8SrSuR1tD3sgNjr6IzCdrKSgqi92z49z cdis3EaY199WFW60DCS7ydu++T5Xa+Gy Ow1quagwf/JUC/mEpeBQYWrnpkBbpDB3 sy4+P2i8iCvavehbRyVm9U0MlIc=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 54576 10 2 397e50c85ede9cde33f363a9e66fd1b216d788f8dd438a57a423a386869c8f06
+cz. 86400 IN RRSIG DS 8 1 86400 20170214050000 20170201040000 61045 . KFIT2d+AO6xPTOKH4qWqTcthiqONvswz Ya+rnndNcDVOhvS9aKotG1CbyZXes489 GwfyNNsuO5N+WzDWO5Jzm37doLFFq3Yv AxWupLK8/KpM8lYc1VxlrkZ/XxODPOvJ ZEJ3WCLoyvc4PQgKmpjqxmGv+9GafFDO 7m7P0a2dJGxEH8GSDimcXS8dWf72O6DX zse532zD5mvLR8p2mXaoK7i5PbRRMzyB jHnQRVJVw3myhdNa1wB4P4Y9qUGQty9G xXHwJGsiZjADnzA+zWQYhZYQUp2suM/T Ri4JIKtdzitJHJ7psy0uwqC93L9PUnuq kWNz4YrXgWHP9TJtY5uzKw==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY NOERROR QR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397e50c85ede9cde33f363a9e66fd1b216d788f8dd438a57a423a386869c8f06
+cz. 86400 IN RRSIG DS 8 1 86400 20170214050000 20170201040000 61045 . KFIT2d+AO6xPTOKH4qWqTcthiqONvswz Ya+rnndNcDVOhvS9aKotG1CbyZXes489 GwfyNNsuO5N+WzDWO5Jzm37doLFFq3Yv AxWupLK8/KpM8lYc1VxlrkZ/XxODPOvJ ZEJ3WCLoyvc4PQgKmpjqxmGv+9GafFDO 7m7P0a2dJGxEH8GSDimcXS8dWf72O6DX zse532zD5mvLR8p2mXaoK7i5PbRRMzyB jHnQRVJVw3myhdNa1wB4P4Y9qUGQty9G xXHwJGsiZjADnzA+zWQYhZYQUp2suM/T Ri4JIKtdzitJHJ7psy0uwqC93L9PUnuq kWNz4YrXgWHP9TJtY5uzKw==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+
+; end of M.ROOT-SERVERS.NET.
+RANGE_END
+
+
+; domains: cz. ; ?.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ ADDRESS 194.0.13.1
+ ADDRESS 194.0.14.1
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:f::1
+ ADDRESS 2001:678:10::1
+ ADDRESS 2001:678:11::1
+ ADDRESS 2001:678:1::1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170208000000 20170125000000 54576 cz. NPdwGLJLADvyArolHZkv3rwBwla2txHr HKSNooiGAkLdddmkiC3+t2K7hHb54H1L fj7tVXgNwIAqx1rNK9uz/4ElQDy1k3Bz UezcPkO/FaRiDOm6Y81XLaSG6p+P5pub zEnP8/e36Vk07/cMF/aZFbqNlMQmOVQH pUezGNP8O8+80Q0OEyv9aKfVg/ahfOt8 s1vxMa6Dd67KsP8rw+VhLseOXMXST98x /QvirAeALoMXOi1AzZ6ai1aG8f0+6G9K 2lS/0ceMhdRBfoflBKz/CaEmIdEAsr7M GPH4PNMwiQ5eb32T0WIr01WQtKScNA5B vNG6PvBxxsgEHRTzOvfOCw==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170214174538 20170201143958 58211 cz. sPVcTvaLVDLnKCBtUbdZ1hkPcje55O2p HMHwnH3vfK+Z96nkbUoyNTnVhvMHCV2r LRoB9CHVxOD1O6gMVu36sO6/6xTi3g7J utvIu/+1RUXlAToVnsbqWpsKLqhAdHqL b3+V1bHYllyIhcWwrZwB465kQYwFrZEn C2TsBC1+6CM=
+cz. 18000 IN DNSKEY 256 3 10 AwEAAdWL2Br92Vx0dLEOOB8y02ss8LtK IyGlLJ2ymJ02WqR3AAEEZN0fNPKF77kd KsjlG8DlzmSIOR12aa9EhpXqyHOwWI0k HOMJVnn6ZKFIAl71JP/dYIcshYUxKZZM e+zEAUrVtzlLVDtM6cDOPDuBNa1ujYec 3eJl9IpqeUEG6gAH
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF +9ZWvr5Lewx+q+947o/GrRv4FGFfkZxf 9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux 2oeHRXUvgtLnl5HeRVLL+zgI5byx9HSN r4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K 02vLP4d1cCEzUQy30eyZto2/tG5ZwCU/ iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rIt emYMWr1f9BGAdtTWoPCPCYPjOZMPoIyA 4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG 7SUn8jo0IKQ9W7JJxES0aqFCX/0=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rhybar.cz. IN NS
+SECTION ANSWER
+rhybar.cz. 600 IN NS b.ns.nic.cz.
+rhybar.cz. 600 IN NS a.ns.nic.cz.
+rhybar.cz. 600 IN RRSIG NS 5 2 600 20081030080058 20080930080058 5172 rhybar.cz. XNIBK/CmsKZsw6lT2iAa5g+TLOVxPx39 N7vOxqW5lafaC56EuCZxUEmZT6ECvU/W zvQIqE1vqN4X6N/Z+5QTXKM3zcT+Uhay yiLNRNwdlkmG0xo/+bYACj85lhyB3UGJ +vpRWg2VVJOy9RLMyIka/S7nVYpgKUZF AZuxue6K17o=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rhybar.cz. IN RRSIG
+SECTION ANSWER
+rhybar.cz. 600 IN RRSIG NS 5 2 600 20081030080058 20080930080058 5172 rhybar.cz. XNIBK/CmsKZsw6lT2iAa5g+TLOVxPx39 N7vOxqW5lafaC56EuCZxUEmZT6ECvU/W zvQIqE1vqN4X6N/Z+5QTXKM3zcT+Uhay yiLNRNwdlkmG0xo/+bYACj85lhyB3UGJ +vpRWg2VVJOy9RLMyIka/S7nVYpgKUZF AZuxue6K17o=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rhybar.cz. IN DS
+SECTION ANSWER
+rhybar.cz. 18000 IN DS 59916 5 2 1A6516C32DCF2038E5382D77ADACADE3EDE99CDD77F019FCDF3741B4 9F8D563B
+rhybar.cz. 18000 IN RRSIG DS 10 2 18000 20170214061134 20170201163953 58211 cz. CGwqHhSb6b8JsjztqPeRDKBC/Sp4O0Igc4r53T+SheWdMwgNwvbXiFD6 krt0FGf1QU/JCkH5L5oYHFeaPXljftB2d0JbzLnA+iaI9Jy1aRmUqvTN /PiDVPYI/SRFvCfk2FLMK5LzMfjPjooiSNv9b1zZKJd8cykq8/jgijXy 5Xk=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rhybar.cz. IN DNSKEY
+SECTION ANSWER
+rhybar.cz. 600 IN RRSIG DNSKEY 5 2 600 20081030080058 20080930080058 5172 rhybar.cz. Xh5WqcWoiywSm+t4YhGqVVTb1Revz2Bv ETgb1uoY9DaREJhTUIq6zTA5xGS2WpAh YmIb8OV259NxT/jEtEdFIlTIz2nDzr1I 2ZrDoF/qwfJXvda8zy2wz3AHvou8uLeI BJLQKSpZx1YI3ee9YFFw25yfie9M4g1/ PXuMlTHpVVY=
+rhybar.cz. 600 IN RRSIG DNSKEY 5 2 600 20081030080058 20080930080058 44566 rhybar.cz. XkcudN72dM/HiqmKMZeOSjE8NavwtkXJ 2VGCQ5/RmJphEeSd/IZ4f5I67l+LZjvy +J+fplrvXTSnAx6+y5Z1xvo9HdGhCdUX uh6rIy1OScrUwOPOFJplTqccukafWngo iQZuj9mZS41ZcQA1Js+Q5EzhnmCD/7Tu IpmN6V+4eDXQcnf2uagpntWj153yjePd eb2r6NmfDDBQUu6GLIKfI6CtlmsiZWUA JvtBGLK4DxSn/5jxEA9UGHWqiRVxZKk6 ssZ71Fuxc5e2D+7j0XKZrw6kA0z3F8dg FuQQxWtVC0wyycE4H+PQbD7ZVkWeCiLg URHpDlizUB+xK1nGuHuE3Q==
+rhybar.cz. 600 IN DNSKEY 256 3 5 AwEAAb/riVUjNfP1to3wkJyul0MjwiPo jFgFmMiLj1KIKeVIYCIRNx01Q1we5M17 GQFInCXXyTyjCYJfwkL0Xe7ma6m2pHfE MkOiDl42rsgrmkShxPEvZMd5vpT+RyQW Qh26TJ42MRoCJSt6XNeFLXRyjfRcDt7Z xYD3bHNeyaDuUUGt
+rhybar.cz. 600 IN DNSKEY 256 3 5 AwEAAcrTMVXwOcFCGKtXwdt4XATP43qU 96IryyqiZ0oPtuHEEBCikuQDuJhRjNAV 4DYvR6fb/suAnd91EVNgHHTXUlAWwmJR rqIwZ6VuGaZqVG+NJh1Okif7CL8no2Z4 7j6I3HH3pyzrYH2oQVyr64O/8BV2jrk8 RteeEqa7V7gcrFfJ
+rhybar.cz. 600 IN DNSKEY 257 3 5 AwEAAeKle4K3bxJb4k9sMhdm6BmpRK2r ISAGh0egMSXgOlQnU+3TLQ0aH1th7ejZ nn6Zdkeo8MRXDxLkgp1rUSsRM1Q2SmLJ haat7L15qHmj+vCk5IuSIpAdaRsqOKxH lT6a/LWGwGvDIVxY6J9sXaJ4SInflZpa 5wZUCrhDKvpo0hAzNfoK/aFApzZGaAGA LYx6YpbG+SBW2K+s92eyoJCCrQQ+Nata 41l7K6RFAYjP+g3Kp95McNm3xlBve171 u9FUZNUuN2Rn25oEtHHlK9NcHNqWvFJ3 VmXcA6CkGrBPV6vOAwwUtPDSWSZbdolS 69092ZWYTlOJw6g0LVI2feMMrok=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+rhybar.cz. IN A
+SECTION AUTHORITY
+rhybar.cz. 600 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 2199091609 10800 3600 1209600 7200
+rhybar.cz. 600 IN RRSIG SOA 5 2 600 20081030080058 20080930080058 5172 rhybar.cz. XfQgQHW5sDA+uPzC3L1lE8Etc57iH9/6 AqC8T4Fz+J1PIbiMZKHZrAxgj10dC8xd 6NTjNe3wBPALibRRLo8pe7+XZVmw1Vz4 bCZ93MJ5qeaiZ2IbfsQoqzKtgAPP3HzE 5CYRpkktAXsSLo23Ii9/jS82RouISd0r Bc5WmHYwPRo=
+rhybar.cz. 7200 IN RRSIG NSEC 5 2 7200 20081030080058 20080930080058 5172 rhybar.cz. Xv8ZkTfbfXkJj4FHMBrbIt7afauxnhOS OB6dxwxbhYV1q3wV9vlkUutNoWbChBRu UQVn6f2nCLQ63Zif6MLFKMWHgf91uRby w5JX0IOXbrOyW6sAAUggavNsJcfNpD19 SVRMCRZmIQQ/j8ft5+t703babL+iOiD/ tSbRgZnFpkU=
+rhybar.cz. 7200 IN NSEC www.rhybar.cz. NS SOA RRSIG NSEC DNSKEY
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+www.rhybar.cz. IN A
+SECTION ANSWER
+www.rhybar.cz. 600 IN A 217.31.205.55
+www.rhybar.cz. 600 IN RRSIG A 5 3 600 20081030080058 20080930080058 5172 rhybar.cz. XVkut4l9mw2MhodZFIOD2L57AU2u+I6w GVlK1fr6w5locFC5NIe8ukw79jYdOCH3 WwFgSMscumIz1sGqRPrN/CrhXiU0ymFG Fju9x/k10lv6SGS6lslgnZluet04Cyib GQ2HBnwTx7qK3j+bNzxKLvjpn7DY9f+Y KB8F2FtwNOc=
+ENTRY_END
+
+; end of domain cz.: servers ?.ns.nic.cz.
+RANGE_END
+
+
+; first two steps need to be commented out if you want to reproduce repeated
+; => querying: '2001:dc3::35' score: 93 zone cut: '.' m12n: '.' type: 'DS' proto: 'udp'
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD CD DO
+SECTION QUESTION
+rhybar.cz. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA CD NOERROR
+SECTION QUESTION
+rhybar.cz. IN A
+SECTION AUTHORITY
+rhybar.cz. 600 IN SOA a.ns.nic.cz. hostmaster.nic.cz. 2199091609 10800 3600 1209600 7200
+rhybar.cz. 600 IN RRSIG SOA 5 2 600 20081030080058 20080930080058 5172 rhybar.cz. XfQgQHW5sDA+uPzC3L1lE8Etc57iH9/6AqC8T4Fz+J1PIbiMZKHZrAxg j10dC8xd6NTjNe3wBPALibRRLo8pe7+XZVmw1Vz4bCZ93MJ5qeaiZ2Ib fsQoqzKtgAPP3HzE5CYRpkktAXsSLo23Ii9/jS82RouISd0rBc5WmHYw PRo=
+rhybar.cz. 7200 IN NSEC www.rhybar.cz. NS SOA RRSIG NSEC DNSKEY
+rhybar.cz. 7200 IN RRSIG NSEC 5 2 7200 20081030080058 20080930080058 5172 rhybar.cz. Xv8ZkTfbfXkJj4FHMBrbIt7afauxnhOSOB6dxwxbhYV1q3wV9vlkUutN oWbChBRuUQVn6f2nCLQ63Zif6MLFKMWHgf91uRbyw5JX0IOXbrOyW6sA AUggavNsJcfNpD19SVRMCRZmIQQ/j8ft5+t703babL+iOiD/tSbRgZnF pkU=
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+rhybar.cz. IN A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+rhybar.cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/world_cz_turris_api.rpl b/tests/deckard/sets/resolver/world_cz_turris_api.rpl
new file mode 100644
index 0000000..2e48077
--- /dev/null
+++ b/tests/deckard/sets/resolver/world_cz_turris_api.rpl
@@ -0,0 +1,323 @@
+val-override-date: 20170213100700
+trust-anchor: ". 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"
+stub-addr: 2001:dc3::35
+CONFIG_END
+
+SCENARIO_BEGIN api.turris.cz A/AAAA sanity check
+
+RANGE_BEGIN 0 1000
+ ADDRESS 192.33.4.12
+ ADDRESS 2001:500:2d::d
+ ADDRESS 2001:dc3::35
+ ADDRESS 192.36.148.17
+ ADDRESS 2001:500:12::d0d
+ ADDRESS 192.203.230.10
+ ADDRESS 199.7.83.42
+ ADDRESS 198.97.190.53
+ ADDRESS 2001:500:84::b
+ ADDRESS 2001:500:2::c
+ ADDRESS 2001:7fd::1
+ ADDRESS 193.0.14.129
+ ADDRESS 202.12.27.33
+ ADDRESS 192.58.128.30
+ ADDRESS 192.5.5.241
+ ADDRESS 2001:7fe::53
+ ADDRESS 198.41.0.4
+ ADDRESS 2001:500:2f::f
+ ADDRESS 199.7.91.13
+ ADDRESS 192.112.36.4
+ ADDRESS 2001:500:9f::42
+ ADDRESS 192.228.79.201
+ ADDRESS 2001:503:c27::2:30
+ ADDRESS 2001:500:1::53
+ ADDRESS 2001:503:ba3e::2:30
+ ADDRESS 2001:500:a8::e
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. 518400 IN NS a.root-servers.net.
+. 518400 IN NS b.root-servers.net.
+. 518400 IN NS c.root-servers.net.
+. 518400 IN NS d.root-servers.net.
+. 518400 IN NS e.root-servers.net.
+. 518400 IN NS f.root-servers.net.
+. 518400 IN NS g.root-servers.net.
+. 518400 IN NS h.root-servers.net.
+. 518400 IN NS i.root-servers.net.
+. 518400 IN NS j.root-servers.net.
+. 518400 IN NS k.root-servers.net.
+. 518400 IN NS l.root-servers.net.
+. 518400 IN NS m.root-servers.net.
+. 518400 IN RRSIG NS 8 0 518400 20170226050000 20170213040000 61045 . X7mYRt9jWw1QDQPQNcFehtDLtWX8MnxE MPF8bhuH8pFhd2cEBNu3X2j9eYt/z76B PAzoblrdW5vvfD4ZEnInjp486i4HPpFQ ZtrfZ1Lbu/wwOZ0cjxE56xZuBRQZ0xUk /pzTYGDwpAEWgOOYlSCVq2v6JVIWgpgW WD3qn43QXEhpuTSi2Xp7K4TKp5dlh7wy dbuQ1BjI0mDIqZ7dRGKX2va3sVMNypsF HQsPTnooTCIWKu+zp0/NXo2XnBgdohJF xCrwcAuuPY3f6FAOAhmTmThNFvmE/2D8 7T1sLtJhGfMt7BCTQ01hKu76MOQL3Xfz E2LmzaTHj9w9oHUEoIXJEg==
+SECTION ADDITIONAL
+a.root-servers.net. 518400 IN A 198.41.0.4
+a.root-servers.net. 518400 IN AAAA 2001:503:ba3e::2:30
+b.root-servers.net. 518400 IN A 192.228.79.201
+b.root-servers.net. 518400 IN AAAA 2001:500:84::b
+c.root-servers.net. 518400 IN A 192.33.4.12
+c.root-servers.net. 518400 IN AAAA 2001:500:2::c
+d.root-servers.net. 518400 IN A 199.7.91.13
+d.root-servers.net. 518400 IN AAAA 2001:500:2d::d
+e.root-servers.net. 518400 IN A 192.203.230.10
+e.root-servers.net. 518400 IN AAAA 2001:500:a8::e
+f.root-servers.net. 518400 IN A 192.5.5.241
+f.root-servers.net. 518400 IN AAAA 2001:500:2f::f
+g.root-servers.net. 518400 IN A 192.112.36.4
+g.root-servers.net. 518400 IN AAAA 2001:500:12::d0d
+h.root-servers.net. 518400 IN A 198.97.190.53
+h.root-servers.net. 518400 IN AAAA 2001:500:1::53
+i.root-servers.net. 518400 IN A 192.36.148.17
+i.root-servers.net. 518400 IN AAAA 2001:7fe::53
+j.root-servers.net. 518400 IN A 192.58.128.30
+j.root-servers.net. 518400 IN AAAA 2001:503:c27::2:30
+k.root-servers.net. 518400 IN A 193.0.14.129
+k.root-servers.net. 518400 IN AAAA 2001:7fd::1
+l.root-servers.net. 518400 IN A 199.7.83.42
+l.root-servers.net. 518400 IN AAAA 2001:500:9f::42
+m.root-servers.net. 518400 IN A 202.12.27.33
+m.root-servers.net. 518400 IN AAAA 2001:dc3::35
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 172800 IN RRSIG DNSKEY 8 0 172800 20170303000000 20170210000000 19036 . KHz7GVvg5DxUv70bUhSjRy1JO5soL+h6 M08g8bSKecd+4NmZI87Sn20puZNRuiAS bnG63i89Z2S45NBAR8KtqB6N5CrRhLhf xZcRo5k3Ts6zsC1EJ58upPKzFtu/sJBs PDjcRJJKbXlB4hLukQwVhn/MbsXxZdZG I57WoLFxbbR49NlFJrlrbTi2gieRR1SC LfT9aiBGsJA3T4jXap9FIsikNf1DJA8H cnQTW7hFi8l/O2ni2hbjsIE4S3GRTMyp qDR/s7piy/qukfWwSknk6YZTbzld6Zgb ZK+oOhRgj/W6XW78bJl0onov0F1wD0NQ sec+sk2P+JNMc4xgvQmn9g==
+. 172800 IN DNSKEY 256 3 8 AwEAAYvgWbYkpeGgdPKaKTJU3Us4YSTR gy7+dzvfArIhi2tKoZ/WR1Dfw883SOU6 Uw7tpVRkLarN0oIMK/xbOBD1DcXnyfEl BwKsz4sVVWmfyr/x+igD/UjrcJ5zEBUr UmVtHyjar7ccaVc1/3ntkhZjI1hcungA lOhPhHlkMeX+5Azx6GdX//An5OgrdyH3 o/JmOPMDX1mt806JI/hf0EwAp1pBwo5e 8SrSuR1tD3sgNjr6IzCdrKSgqi92z49z cdis3EaY199WFW60DCS7ydu++T5Xa+Gy Ow1quagwf/JUC/mEpeBQYWrnpkBbpDB3 sy4+P2i8iCvavehbRyVm9U0MlIc=
+. 172800 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29 euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v 58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8 g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37 NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/E fucp2gaDX6RS6CXpoY68LsvPVjR0ZSwz z1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgu l0sGIcGOYl7OyQdXfZ57relSQageu+ip AdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1 dfwhYB4N7knNnulqQxA+Uk1ihz0=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+cz. IN DS
+SECTION ANSWER
+cz. 86400 IN DS 54576 10 2 397e50c85ede9cde33f363a9e66fd1b216d788f8dd438a57a423a386869c8f06
+cz. 86400 IN RRSIG DS 8 1 86400 20170226050000 20170213040000 61045 . GozD7iz2HauQt8xFZzS3ednnBCXLdwAS edCXa5mIvbDARxYzEaC6/+XcgBXu26h0 pMyxGcikiifIurQkrzEBtGa/30yiIegy FDXronn44ni5s1lhRtMmFwBYptGDZo15 /g2uDynqfifMGhMbU/IlQJW6QWPRdxS7 bKm4wj/RtE38+CcsZ6fHudvKDJV9xBip 4hqOuu3IdAcrr64OPIJxuwOhXz+NLGEN bDo7tWpKp/vHx5PJTl3SRilxHVTx4f94 FLr2VijkqsuYmG+pYMj6hwPy56/5whaW tP2jLDot0cihVy5229YIf1S4n7zcR+XP 8wOVGu+WQa5wbX4ONucqmg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY NOERROR QR DO
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397e50c85ede9cde33f363a9e66fd1b216d788f8dd438a57a423a386869c8f06
+cz. 86400 IN RRSIG DS 8 1 86400 20170226050000 20170213040000 61045 . GozD7iz2HauQt8xFZzS3ednnBCXLdwAS edCXa5mIvbDARxYzEaC6/+XcgBXu26h0 pMyxGcikiifIurQkrzEBtGa/30yiIegy FDXronn44ni5s1lhRtMmFwBYptGDZo15 /g2uDynqfifMGhMbU/IlQJW6QWPRdxS7 bKm4wj/RtE38+CcsZ6fHudvKDJV9xBip 4hqOuu3IdAcrr64OPIJxuwOhXz+NLGEN bDo7tWpKp/vHx5PJTl3SRilxHVTx4f94 FLr2VijkqsuYmG+pYMj6hwPy56/5whaW tP2jLDot0cihVy5229YIf1S4n7zcR+XP 8wOVGu+WQa5wbX4ONucqmg==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+RANGE_END
+
+RANGE_BEGIN 0 1000
+ ADDRESS 194.0.14.1
+ ADDRESS 2001:678:11::1
+ ADDRESS 2001:678:1::1
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:f::1
+ ADDRESS 2001:678:10::1
+ ADDRESS 194.0.13.1
+ ADDRESS 194.0.12.1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+cz. IN NS
+SECTION ANSWER
+cz. 18000 IN NS a.ns.nic.cz.
+cz. 18000 IN NS b.ns.nic.cz.
+cz. 18000 IN NS c.ns.nic.cz.
+cz. 18000 IN NS d.ns.nic.cz.
+cz. 18000 IN RRSIG NS 10 1 18000 20170220104540 20170206203958 58211 cz. NNzA115UZfT3uOGUEXJkDqoqKGXwIa3V /PbeHBh39FLO6KRDD9Isy9R6+Jw4Y1v9 9ca5l9eCgXqjAJ9soEqGLBqx+SB8LBNx XDjOS46Ewdc48+KRCqQku5NxsD+xs/hD Kj0/9ck1qdBPJd+547KBxZ+wIPSBvZWL DjhappBGlgw=
+SECTION ADDITIONAL
+a.ns.nic.cz. 18000 IN A 194.0.12.1
+a.ns.nic.cz. 18000 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 18000 IN A 194.0.13.1
+b.ns.nic.cz. 18000 IN AAAA 2001:678:10::1
+d.ns.nic.cz. 18000 IN A 193.29.206.1
+d.ns.nic.cz. 18000 IN AAAA 2001:678:1::1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170220000000 20170206000000 54576 cz. JU9BdCRGVaWiL+cwmzhfurOd2tMHX3fi DweYGPPnHCUx10BtVszJ5oM/1aphMIPa 72Z1Vk681PpTsGAGgRV1uRhsJ+Agawkd P/KjjSzAot+/oWcBl+wdQfLT5E50SbgC kvIHbexSd60BwMyzS8pFuRjYkC+MoGDg g+vLq8k64AWqB5zWeaC1y4C0kolAwBSo znR1xj1bA+CbdVCkucajBndgct5AHJM4 eyN/o9Qhg3RNUFl9WJ6f8AaewZfB/9fN w8+vaxAixjy99LI0mijONZf9E3FFcDq5 qRuLUcIRB+1HzJ2ZTnj6BP8KmSQyj/Ro y/r9jP0L1v59aE5M6LfZAg==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170226022139 20170213084011 58211 cz. VSe3d54BxyxLtg/w4NWhbx5hYu4yC5WC sRi3oXE/042zoBU6ijJyl/ei1zk4x/7o S2PKunCE2SUscFG6othKoikDERM9YN3T gpv+GC4xe4llnB5dCqHSwwFApfZQnrzV AKiVFLGMbeME+R07r2vh4L9zEzFx2poV WMAii6LsB5E=
+cz. 18000 IN DNSKEY 256 3 10 AwEAAdWL2Br92Vx0dLEOOB8y02ss8LtK IyGlLJ2ymJ02WqR3AAEEZN0fNPKF77kd KsjlG8DlzmSIOR12aa9EhpXqyHOwWI0k HOMJVnn6ZKFIAl71JP/dYIcshYUxKZZM e+zEAUrVtzlLVDtM6cDOPDuBNa1ujYec 3eJl9IpqeUEG6gAH
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF +9ZWvr5Lewx+q+947o/GrRv4FGFfkZxf 9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux 2oeHRXUvgtLnl5HeRVLL+zgI5byx9HSN r4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K 02vLP4d1cCEzUQy30eyZto2/tG5ZwCU/ iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rIt emYMWr1f9BGAdtTWoPCPCYPjOZMPoIyA 4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG 7SUn8jo0IKQ9W7JJxES0aqFCX/0=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+turris.cz. IN NS
+SECTION ANSWER
+turris.cz. 1800 IN NS a.ns.nic.cz.
+turris.cz. 1800 IN NS b.ns.nic.cz.
+turris.cz. 1800 IN NS d.ns.nic.cz.
+turris.cz. 1800 IN RRSIG NS 13 2 1800 20170221145034 20170207145034 49237 turris.cz. ls7jS7uS5Oiom5djEnUrgeY0B+RdgsAG nzq5NqmnwdQBFmBm7RZNPoboBNC3vA+L pkTgNkLMURgoiZzaRnGsSA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+turris.cz. IN DS
+SECTION ANSWER
+turris.cz. 18000 IN DS 54959 13 2 afda82e687ffc58d759824274f3c3eb007eea1e46f6108886ec0fa979bfd78c3
+turris.cz. 18000 IN RRSIG DS 10 2 18000 20170225151104 20170213084011 58211 cz. mPn0h45GRfOpPRbFC7R4o1mpenSgLIZ/ pbHqqH8Fz9dyVnAow7ug9XGjhzPgiAj4 X0gG+JTb3TRxsI+FFKUeBJL+/3N392Xf zPEMbtnLupdRQRhfcCc3iGbrUli6b99z E4BAfI+g/jyR/IgRqpJyxsZjuVTcdCX8 nXCYopt/WZY=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+turris.cz. IN DNSKEY
+SECTION ANSWER
+turris.cz. 1800 IN RRSIG DNSKEY 13 2 1800 20170221145034 20170207145034 54959 turris.cz. FSqPyjAbBJY6xppLOSWj3hLUaiOGnbp4 s8utvSASyFeY1lBF+SmhOTWktIa8kMyU lHUJZUr25yDNcosb5ri6oQ==
+turris.cz. 1800 IN DNSKEY 256 3 13 3TQfQFOmvkZdZXMvK7l2nFo7UkQ48KU9 CNmx3HQOvmMS+tKyQZhTWfCFD0Yp/mSv s622xQS8qEdNbaBazXDnXg==
+turris.cz. 1800 IN DNSKEY 257 3 13 KDAJfPGWgvNAEHUMzmmSa+c3gHfoGIsX nhIO1iAYGTAyVBo+CLTyIk3wxDtt4Yn3 eCrCiYsEAHBJgQvA3pwJ8w==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+api.turris.cz. IN A
+SECTION ANSWER
+api.turris.cz. 1800 IN A 217.31.192.101
+api.turris.cz. 1800 IN RRSIG A 13 3 1800 20170221145034 20170207145034 49237 turris.cz. K78pE5gKDt9p+g9rIKXB52Ez2PuFkgum ezA9+W9JNwslrCaCQ3QdfAXd0GLwjgs7 Z9BavCCAeRPpvxDLVCDjqg==
+SECTION AUTHORITY
+turris.cz. 1800 IN NS d.ns.nic.cz.
+turris.cz. 1800 IN NS b.ns.nic.cz.
+turris.cz. 1800 IN NS a.ns.nic.cz.
+turris.cz. 1800 IN RRSIG NS 13 2 1800 20170221145034 20170207145034 49237 turris.cz. ls7jS7uS5Oiom5djEnUrgeY0B+RdgsAG nzq5NqmnwdQBFmBm7RZNPoboBNC3vA+L pkTgNkLMURgoiZzaRnGsSA==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY NOERROR QR AA DO
+SECTION QUESTION
+api.turris.cz. IN AAAA
+SECTION ANSWER
+api.turris.cz. 1800 IN AAAA 2001:1488:ac15:ff80::101
+api.turris.cz. 1800 IN RRSIG AAAA 13 3 1800 20170221145034 20170207145034 49237 turris.cz. bg+Pcv1wqjAQ63Abe2xW/+BxAEJZlHPW 01ez/I4zcnSwQpltaJNZ6oR4Jbnks43c 9TRQs5qBh2ZjaTBiRmcQ8A==
+SECTION AUTHORITY
+turris.cz. 1800 IN NS a.ns.nic.cz.
+turris.cz. 1800 IN NS b.ns.nic.cz.
+turris.cz. 1800 IN NS d.ns.nic.cz.
+turris.cz. 1800 IN RRSIG NS 13 2 1800 20170221145034 20170207145034 49237 turris.cz. ls7jS7uS5Oiom5djEnUrgeY0B+RdgsAG nzq5NqmnwdQBFmBm7RZNPoboBNC3vA+L pkTgNkLMURgoiZzaRnGsSA==
+ENTRY_END
+
+RANGE_END
+
+
+; IPv6
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+api.turris.cz. IN AAAA
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY RD RA QR
+SECTION QUESTION
+api.turris.cz. IN AAAA
+SECTION ANSWER
+api.turris.cz. 1800 IN AAAA 2001:1488:ac15:ff80::101
+ENTRY_END
+
+; do we have AD bit & RRSIGs in cache?
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+api.turris.cz. IN AAAA
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY RD RA QR AD
+SECTION QUESTION
+api.turris.cz. IN AAAA
+SECTION ANSWER
+api.turris.cz. 1800 IN AAAA 2001:1488:ac15:ff80::101
+api.turris.cz. 1800 IN RRSIG AAAA 13 3 1800 20170221145034 20170207145034 49237 turris.cz. bg+Pcv1wqjAQ63Abe2xW/+BxAEJZlHPW 01ez/I4zcnSwQpltaJNZ6oR4Jbnks43c 9TRQs5qBh2ZjaTBiRmcQ8A==
+ENTRY_END
+
+; IPv4
+STEP 110 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+api.turris.cz. IN A
+ENTRY_END
+
+STEP 111 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY RD RA QR
+SECTION QUESTION
+api.turris.cz. IN A
+SECTION ANSWER
+api.turris.cz. 1800 IN A 217.31.192.101
+ENTRY_END
+
+; do we have AD bit & RRSIGs in cache?
+STEP 120 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+api.turris.cz. IN A
+ENTRY_END
+
+STEP 121 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY RD RA QR AD
+SECTION QUESTION
+api.turris.cz. IN A
+SECTION ANSWER
+api.turris.cz. 1800 IN A 217.31.192.101
+api.turris.cz. 1800 IN RRSIG A 13 3 1800 20170221145034 20170207145034 49237 turris.cz. K78pE5gKDt9p+g9rIKXB52Ez2PuFkgum ezA9+W9JNwslrCaCQ3QdfAXd0GLwjgs7 Z9BavCCAeRPpvxDLVCDjqg==
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/world_cz_vutbr_www.rpl b/tests/deckard/sets/resolver/world_cz_vutbr_www.rpl
new file mode 100644
index 0000000..6979a20
--- /dev/null
+++ b/tests/deckard/sets/resolver/world_cz_vutbr_www.rpl
@@ -0,0 +1,296 @@
+; test with real world Internet data
+; attempt to resolve www.vutbr.cz. A leads to CNAME piranha.ro.vutbr.cz.
+; sub-trees vutbr.cz and ro.vutbr.cz. are in separate zones
+; hosted on the same servers with different DNSKEYs
+
+val-override-date: 20170124180319
+trust-anchor: ". 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"
+stub-addr: 2001:dc3::35
+CONFIG_END
+
+SCENARIO_BEGIN www.vutbr.cz. CNAME kresd issue #130
+
+; DNS root ; M.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 2001:dc3::35
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 16567 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 16567 IN DNSKEY 256 3 8 AwEAAYvgWbYkpeGgdPKaKTJU3Us4YSTRgy7+dzvfArIhi2tKoZ/WR1Df w883SOU6Uw7tpVRkLarN0oIMK/xbOBD1DcXnyfElBwKsz4sVVWmfyr/x +igD/UjrcJ5zEBUrUmVtHyjar7ccaVc1/3ntkhZjI1hcungAlOhPhHlk MeX+5Azx6GdX//An5OgrdyH3o/JmOPMDX1mt806JI/hf0EwAp1pBwo5e 8SrSuR1tD3sgNjr6IzCdrKSgqi92z49zcdis3EaY199WFW60DCS7ydu+ +T5Xa+GyOw1quagwf/JUC/mEpeBQYWrnpkBbpDB3sy4+P2i8iCvavehb RyVm9U0MlIc=
+. 16567 IN RRSIG DNSKEY 8 0 172800 20170201000000 20170111000000 19036 . Sh+EpofvZgk3J9szMD2B94FxFgyIUKz3hkbCjgWSTqPQyhqNgqVU8QlS EtOo8YLmS4AX98eit5Gmmb2ObpkGoXBmAzu5w/Qt5WsGsWzLQhYrsy9s lDmFQ2JKUoCyfdwqhlJ8VxjzdFdMUiVl+/GPnv4yjxjM8Ke3VAtBkn6n BO7JkcxxOfcgZdZ4MuvSr40K/SenZE+JlLLL1LF4TMCGqaZTTdOx6kFF KSSgy2AS884htWcK0tnwRc630g6nAI2wdvjlRLBeisbfXanI4v8iiPyT FnMmnV7wJGWJ4gtRJ0UH3u5RWXUPZ+s1tKytk3slXbLyQ9xkEDveuD+h b659gQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR DO NOERROR
+SECTION QUESTION
+cz. IN NS
+SECTION AUTHORITY
+cz. 172800 IN NS d.ns.nic.cz.
+cz. 172800 IN NS a.ns.nic.cz.
+cz. 172800 IN NS c.ns.nic.cz.
+cz. 172800 IN NS b.ns.nic.cz.
+cz. 86400 IN DS 54576 10 2 397E50C85EDE9CDE33F363A9E66FD1B216D788F8DD438A57A423A386 869C8F06
+cz. 86400 IN RRSIG DS 8 1 86400 20170202170000 20170120160000 61045 . ig2BBmA1kOuTqhVogqLciH40Ina7BCrG/fcaNARSWoaFHGOcC/7KsBZO uMttn/hKDJkH3RPsed2Oswl9bXZ+zrhjeXluUqC0zmsUJDBkS+AkiFJL HCpMSIZaXu/w1ZMADGfyQXl7XWCRbl+eyXi2eTG0SdLtRHNhm3CGJP3C xjzVuOTr9oPEyL0U81jhhlJPCFe8xDD441wLLzpEuVX8VP9N2S1QnIjO BhCEE9OTkPgpS7fMPEl0Yq2gfpRl+DCw1Dd0VB3Hh5M3hmrXuFqNYZQK b0JqDFGYhzvcpUs3EiB9IG7rJt51n6pxCTek1M2w+s6mLYzawVfq+b1Q uQD98A==
+SECTION ADDITIONAL
+a.ns.nic.cz. 172800 IN A 194.0.12.1
+b.ns.nic.cz. 172800 IN A 194.0.13.1
+c.ns.nic.cz. 172800 IN A 194.0.14.1
+d.ns.nic.cz. 172800 IN A 193.29.206.1
+a.ns.nic.cz. 172800 IN AAAA 2001:678:f::1
+b.ns.nic.cz. 172800 IN AAAA 2001:678:10::1
+c.ns.nic.cz. 172800 IN AAAA 2001:678:11::1
+d.ns.nic.cz. 172800 IN AAAA 2001:678:1::1
+ENTRY_END
+; end of M.ROOT-SERVERS.NET.
+RANGE_END
+
+
+; domains: cz. ; ?.ns.nic.cz.
+RANGE_BEGIN 0 100
+ ADDRESS 194.0.12.1
+ ADDRESS 194.0.13.1
+ ADDRESS 194.0.14.1
+ ADDRESS 193.29.206.1
+ ADDRESS 2001:678:f::1
+ ADDRESS 2001:678:10::1
+ ADDRESS 2001:678:11::1
+ ADDRESS 2001:678:1::1
+
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+cz. IN DNSKEY
+SECTION ANSWER
+cz. 18000 IN DNSKEY 256 3 10 AwEAAc9e2YFnG56xtTXu42GLGAkwsrFOBBwOZphNat7HQdBmfi0CbmDf oywCUsaSkObNmm+Zu9MYLNJDHsD+vxsZbtHClpYaSEhMEmHrbnj0BMPV A6hwY6YDGFhKudJ62RmB/rmhQ3iwmICsEdRn2w5fu1rHZv8UJOUMkeWd 6GA48mW3
+cz. 18000 IN DNSKEY 256 3 10 AwEAAdWL2Br92Vx0dLEOOB8y02ss8LtKIyGlLJ2ymJ02WqR3AAEEZN0f NPKF77kdKsjlG8DlzmSIOR12aa9EhpXqyHOwWI0kHOMJVnn6ZKFIAl71 JP/dYIcshYUxKZZMe+zEAUrVtzlLVDtM6cDOPDuBNa1ujYec3eJl9Ipq eUEG6gAH
+cz. 18000 IN DNSKEY 257 3 10 AwEAAay0hi4HN2r/BqMQTpIPIVDyjmyF+9ZWvr5Lewx+q+947o/GrRv4 FGFfkZxf9CFfYVUf0jG5Yq4i06pGVNwJl81HS9Ux2oeHRXUvgtLnl5He RVLL+zgI5byx9HSNr4bPO8ZEn5OjoayhkNyGSFr4VWrzQk/K02vLP4d1 cCEzUQy30eyZto2/tG5ZwCU/iRkS1PJOcOW98hiFIfFDZv1XjbEpqEYh T2PATs6rt+BKwSHKGISmg1PNdg+y0rItemYMWr1f9BGAdtTWoPCPCYPj OZMPoIyA4tMscD+ww54Jf/QNoHccY4hO1yHiuAXG7SUn8jo0IKQ9W7JJ xES0aqFCX/0=
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170127000000 20170120000000 54576 cz. Fdl//hMdLoZq8//gLt/+3a7LfWqB5/psW9YR3AWNPQGfvrEAcKRBcah+ ikbSCmpAZ6j834xZP1zPd5xMoN33PGXf23iqcgjHvUn50Uq48KRBVYwU H885xNJBl/Po0N8STeG0WNZz2mbUbBbPCGN7CI5yl08usvqOvf2fV8+D 0m//+Fa1cWaqMXpHc6OnhWZ+BN4VdcxxwNbGhH2TZxyiGEMMscEGoIxn yL1pVY8T93LOMwQmuFJ71f8Scij3vYouW/mNuEma/UUZM1bEn8vR1UrP /6JTGPGTG+snHvCxiVtAxCNnqoIJDD+xuonpZLeKN5XU7UDMZPDTtSgX vtzjww==
+cz. 18000 IN RRSIG DNSKEY 10 1 18000 20170205002523 20170123080953 58211 cz. MZ6KTtQisTde4iOBH6oasl7bVrRM5ly7Yxdv2l+2gk1YYk4zX6L3m6oB P26SKi+fj8pM77775bRK7uCI9FlyqXa3MJclLU/GmnRANm6T4sSdz0zs F3FK4UfUmHnzdnWXWTnueDfIZr44yF1y1+4I3E96/9/nEYGO+xsifvIj iks=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR DO NOERROR
+SECTION QUESTION
+vutbr.cz. IN NS
+SECTION AUTHORITY
+vutbr.cz. 18000 IN NS pipit.cis.vutbr.cz.
+vutbr.cz. 18000 IN NS rhino.cis.vutbr.cz.
+vutbr.cz. 18000 IN DS 5512 5 2 78510F9433A4D536A5B9099193E9D58EE5B5CF71F14D983B4DA2EB16 29CFA1E9
+vutbr.cz. 18000 IN RRSIG DS 10 2 18000 20170204213601 20170123080953 58211 cz. lXNBswz/r/1NY7VQq+BlisC+1yqFmUBIaF30L8XDAbiHLcj/AIj0dEy6 PlBlkEeDAi4W9DvR0jo9LjHvFFJLs54cuEEd3pHTdlw8x0dLd1X7Zkh7 cezfAt2EEqdux/ce/sc86lUKOpLnDtry2piWwVf2EqFg9NlW4cHTm78U gsY=
+SECTION ADDITIONAL
+pipit.cis.vutbr.cz. 18000 IN A 77.93.219.110
+rhino.cis.vutbr.cz. 18000 IN A 147.229.3.10
+pipit.cis.vutbr.cz. 18000 IN AAAA 2a01:430:120::4d5d:db6e
+rhino.cis.vutbr.cz. 18000 IN AAAA 2001:67c:1220:e000::93e5:30a
+ENTRY_END
+
+; end of domain cz.: servers ?.ns.nic.cz.
+RANGE_END
+
+
+; domains: vutbr.cz. + ro.vutbr.cz.
+; servers: pipit.cis.vutbr.cz. + rhino.cis.vutbr.cz. + shark.ro.vutbr.cz.
+; shark.ro.vutbr.cz. in fact serves both domains but is listed only in ro.vutbr.cz NS
+RANGE_BEGIN 0 100
+ ADDRESS 77.93.219.110
+ ADDRESS 147.229.3.10
+ ADDRESS 147.229.2.59
+ ADDRESS 2a01:430:120::4d5d:db6e
+ ADDRESS 2001:67c:1220:e000::93e5:30a
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+vutbr.cz. IN NS
+SECTION ANSWER
+vutbr.cz. 28800 IN NS rhino.cis.vutbr.cz.
+vutbr.cz. 28800 IN NS pipit.cis.vutbr.cz.
+vutbr.cz. 28800 IN RRSIG NS 5 2 28800 20170216060902 20170117060902 39756 vutbr.cz. y6Jj5vfvdlLeecB/++/qyhjCzfnFJyY1sX1Ja+wV0ulq3laeCVV7ICXh PKG+CjHUu/nDOrzT9QJP4qxYDCANneI0yxI82XKhhoTN5O/TxyWH/DyT k8JarRoMooHv2RwKd8jtLIxvj1SaJ+AvlP0pOPraaVgbHtn1SJ4ubxQD cFc=
+SECTION ADDITIONAL
+pipit.cis.vutbr.cz. 86400 IN A 77.93.219.110
+pipit.cis.vutbr.cz. 86400 IN AAAA 2a01:430:120::4d5d:db6e
+rhino.cis.vutbr.cz. 86400 IN A 147.229.3.10
+rhino.cis.vutbr.cz. 86400 IN AAAA 2001:67c:1220:e000::93e5:30a
+pipit.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. Cz9etHnEOQTzu+6rYJEqx/SQ1tQgPOCyf8HSj4KOsx89jtgiHNC6pep6 ZE0SphMGAs3jC/uGIhlaFNZ3i38OQIMuqwacbz+XZyW5bByvV3QZrhqh dFxMDfmPuNiCAT3crFpUkvVW1OE3YfGHzZGXX7JP5wb1b8A3X6Qih7fV +nQ=
+pipit.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. piafjh6my2fooZRrzwCu9RQ95gYaMQkhIkDaGX/fT6wXzSdmgFZkS1Nl EMIKdDCQaPrLGMG3p32ptMkAm4esPekeyNtLSMBtXwZyUkgEGn6h1QM2 Yr3TOo8cixfk5nmRRdlYadf5krLb8yI9exiqeymgEQLa1YNRz/bWArlX bn8=
+rhino.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. X/tDf8e3JEV0LxiItfpQnBzeaRIq693VG8d30iCH4/1I0uqyCfxboWmm /CBpn9A8MCJu9NEEv+4+povNlfUfqi2yjsqJEVj8ztHxD4g9cc284Cv6 ySjxrSZ9axVqoaopEXujiTwwWJUFcgF6pxqyXVksW7sgKJrboM4VSlQD +Sw=
+rhino.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. T3Yf5PAkSeJtoOH90ea9zZBG9FC3iFhiCSerDn6d9up8GRfzxDsavYJC zQu+3vnOySySn+3TMzQSSFcWdJC2iO7ulaDGr177Gof9QJbKSVSMW7jt YDE2f4/R4Go3NZVwjk/HfpCInoR6pHNA1s/9hMnWtiVopmBdfzyd3/sW YOU=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+vutbr.cz. IN DNSKEY
+SECTION ANSWER
+vutbr.cz. 28800 IN DNSKEY 256 3 5 AwEAAfwRRuGjpt9v4fzuIWFA9MtGfxDrIKhoFA7DNq6B+iCOoQb6t0HZ I9lGDUSR5DRswDGP569NJ/uVD4tJxGnaK2SBQVxIu+bEP1Ouzk+O43iO 8odw50NBWetljjNDP32B3zHpgJRpxyEqzDQaQ6B4Zer6sDZm9wo5SVJe r9LjJV9p
+vutbr.cz. 28800 IN DNSKEY 257 3 5 AwEAAfhR+s/4SLZZNA+kD2u1UgYBUu+X3Avi60QCaE1o2STterM405s8 mWMWJOlZGtjjIky3TEMxQ0+ZtMbEeJu2wNDLdV/XglX+pJAjyy728WJH 4u2/gJR8ZWsEIc0Jwb4FjwmBiF2Koz0SGVvrzEZ9T1H7dHq2X6f8KzYB otJyrAIWr9tZi/9tHrngZJ5wXELmMPWCfEFapdQMoKWoNvzrMYFli17R Mz7gJzCmNxMRV8/WkjsNPgYsTKpsAT8qEsXiTN9987AIKPHvc5j+/njq +fTXdOqGVpIgSiso+qJMddEMBcu/MBBYVFOwRQe1ez2tMwIX7y5mwDvK 0wsmyRvHugfFuxSnfiJvQr05kSnj0wxD9s9LNhrF4PocrcYqnBN/lBx9 D6633jJ3zT3T5Foe/Vj9A/X7F2oN6FOkdwO+YSEUot980pJQut6DR22U P4bLakyDMiTdOQ31c/dRIoTsccxw+838pXFyEPgiqOHRSeN/w9km6BID cl+32Xq97kXSMQH6AxOUsx9/Mxdj7ISwbS4utaAWoP460+TMcnfJfWfB NEWhuFvnfB9l63ZjZToB2PUVhrTxRwKUlfMLegSJKoZfiae82kK1pN4x FYyquKSykm/oXsM2w4OQvpqGcTwAXzZ5s95J45f7PsCap0bscGKumxsH cDswWpUz/UVosIrr
+vutbr.cz. 28800 IN RRSIG DNSKEY 5 2 28800 20170216060902 20170117060902 5512 vutbr.cz. QHw07MAjA4NFi3On8zaMw/q4IuADXVp4TODfK5PHb8OUIX2Yy+bKLrSX /Cc9ClWUpE69x80F9dFEeRZGJiYOwstNQGQVeq/EKNytm1XmhS8cp3SW CYHBpLjZGPrlhvqPhWd0S4vqPNiD8hDzgFAgaCNfwXDDKXhF2/qtpQ0V pDnytMP6pNPLPMpF2hzaLfCMzABShxcEOAr7+KTbxbffOik4YneG8seu XDtBvCVjP8lJcSU+q+UbotLnjyOgn8vV8pliTNqcvRsJTdtvTlJKHu8B iLkFeCE1DpRhyrVT5zC9NSOcoIv7tau2NE2oUPgtRzK76el6i9L9LcSs G+59j02AINefpAtc6W2khmTnGthibeOy/F9FuFkXUy6AmqIdNszMAj++ 8Mzv3A1OHfsfpIS3tLmC4drhdSHr2ab0Pe0lYQq2a9FSeQzSk6s9gwwZ gMVPVQHbouyvn6BCHaRVDjTV8GPKlk3C8GNaHcHb1hAGSPpw3kqL41dd K92Un4tLIoOYomxUYoyMtyxxwddXyR7ivToUHF7e/yv8MACMEo72N9sf y4zLEqkL1mJ1pCp3csI1bKaaA/c7sqb7PX93iqvoY06k55Pd7kT+lAF1 7QvXGg4U1kDrwytQPyocN8wmsX3//CpWUD07v8fCUqKOcIrVNGnoPmPC PpNe3AtpJoE=
+vutbr.cz. 28800 IN RRSIG DNSKEY 5 2 28800 20170216060902 20170117060902 39756 vutbr.cz. CNDE7Ht7xm8Jo9tuOlJ8N9+vI/Htfpk53MI0HG7B1EZJws/yEV7YFOOL SIAt3rzu1OHjaxr4CG/baqGRPtsaWSBHuLSdSduivxXw8xiQcMKzP6Cz 7xhJkQZxzDJ4oO5L2K2zWHcAJ8lfP1/3NHHoH1p2RATLN5sI7ofQE//W +ck=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+www.vutbr.cz. IN A
+SECTION ANSWER
+www.vutbr.cz. 300 IN CNAME piranha.ro.vutbr.cz.
+www.vutbr.cz. 300 IN RRSIG CNAME 5 3 300 20170216060902 20170117060902 39756 vutbr.cz. 9B3UC5SOEw1+yKlYlOTINEuNq0Kdglywc5IYJwzeSzQ3ykptzZo3ABSy bYhTqImVkhm/4NFM9/4HWMHPDzTmrWS0mCI/ljCd/oe/PxW/uESvo4P5 EQzlcuH6xBzc1KdEFAJOSmRzFjj3vyK1QN3k/c+1y2oMFOYOR2oOzCw+ MIE=
+piranha.ro.vutbr.cz. 3600 IN A 147.229.2.90
+piranha.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. Jz8bcAADQjCKTCcF70IK1aHGQlM4ukyN0myABlxoPaqid1mHX5jwR91b kdQmUAh2xDitlgRLbFjbUUgmjSPzQ5Qt7GAFUsVmqxvjbOLZjqHER1dh zmiWO0fDvvP647Osv3RiAP822rNUJcJrUBZU9LmeP05gwIHcpJrhdVBT b7I=
+SECTION AUTHORITY
+ro.vutbr.cz. 86400 IN NS shark.ro.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS rhino.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS pipit.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN RRSIG NS 5 3 86400 20170222120032 20170123120032 12150 ro.vutbr.cz. HAQ8A+QNsS1WIXdW/fbT3jP+IxObBBvgUmvzsmJBXo8HMtnMAcuCQGmB 2JBQsQethQXsdyLnMK8to/5A9VRkqkAa7edxUoy7SdDi/mzGeLAVhF+5 kXSPD6t1vjiNdnIYAMpiOQbodCGxAnq6jnNyrjEzffdq3qw+5IkFNdG4 7Pw=
+SECTION ADDITIONAL
+rhino.cis.vutbr.cz. 83217 IN A 147.229.3.10
+rhino.cis.vutbr.cz. 83217 IN AAAA 2001:67c:1220:e000::93e5:30a
+shark.ro.vutbr.cz. 3600 IN A 147.229.2.59
+pipit.cis.vutbr.cz. 14794 IN A 77.93.219.110
+pipit.cis.vutbr.cz. 14794 IN AAAA 2a01:430:120::4d5d:db6e
+rhino.cis.vutbr.cz. 83217 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. X/tDf8e3JEV0LxiItfpQnBzeaRIq693VG8d30iCH4/1I0uqyCfxboWmm /CBpn9A8MCJu9NEEv+4+povNlfUfqi2yjsqJEVj8ztHxD4g9cc284Cv6 ySjxrSZ9axVqoaopEXujiTwwWJUFcgF6pxqyXVksW7sgKJrboM4VSlQD +Sw=
+rhino.cis.vutbr.cz. 83217 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. T3Yf5PAkSeJtoOH90ea9zZBG9FC3iFhiCSerDn6d9up8GRfzxDsavYJC zQu+3vnOySySn+3TMzQSSFcWdJC2iO7ulaDGr177Gof9QJbKSVSMW7jt YDE2f4/R4Go3NZVwjk/HfpCInoR6pHNA1s/9hMnWtiVopmBdfzyd3/sW YOU=
+shark.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. SmhgyF48yX/6yH7AdSmGX60NL/xaiKH/oAzB0rnPfQZ6j+UfV57ginVV lj798K9A8jjucUpqE8ua2mZ6/aOhpqlV2iI0CZXG44zOupsCY1/OXBDx YNetBcjoXDQCBQRLLLEUL5FerDVxqT74ngdLdKubwRdrB0TLQlvpBr+F Tc8=
+pipit.cis.vutbr.cz. 85923 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. Cz9etHnEOQTzu+6rYJEqx/SQ1tQgPOCyf8HSj4KOsx89jtgiHNC6pep6 ZE0SphMGAs3jC/uGIhlaFNZ3i38OQIMuqwacbz+XZyW5bByvV3QZrhqh dFxMDfmPuNiCAT3crFpUkvVW1OE3YfGHzZGXX7JP5wb1b8A3X6Qih7fV +nQ=
+pipit.cis.vutbr.cz. 85923 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. piafjh6my2fooZRrzwCu9RQ95gYaMQkhIkDaGX/fT6wXzSdmgFZkS1Nl EMIKdDCQaPrLGMG3p32ptMkAm4esPekeyNtLSMBtXwZyUkgEGn6h1QM2 Yr3TOo8cixfk5nmRRdlYadf5krLb8yI9exiqeymgEQLa1YNRz/bWArlX bn8=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+ro.vutbr.cz. IN NS
+SECTION ANSWER
+ro.vutbr.cz. 86400 IN NS pipit.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS rhino.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS shark.ro.vutbr.cz.
+ro.vutbr.cz. 86400 IN RRSIG NS 5 3 86400 20170222120032 20170123120032 12150 ro.vutbr.cz. HAQ8A+QNsS1WIXdW/fbT3jP+IxObBBvgUmvzsmJBXo8HMtnMAcuCQGmB 2JBQsQethQXsdyLnMK8to/5A9VRkqkAa7edxUoy7SdDi/mzGeLAVhF+5 kXSPD6t1vjiNdnIYAMpiOQbodCGxAnq6jnNyrjEzffdq3qw+5IkFNdG4 7Pw=
+SECTION ADDITIONAL
+rhino.cis.vutbr.cz. 86400 IN A 147.229.3.10
+rhino.cis.vutbr.cz. 86400 IN AAAA 2001:67c:1220:e000::93e5:30a
+shark.ro.vutbr.cz. 3600 IN A 147.229.2.59
+pipit.cis.vutbr.cz. 86400 IN A 77.93.219.110
+pipit.cis.vutbr.cz. 86400 IN AAAA 2a01:430:120::4d5d:db6e
+rhino.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. X/tDf8e3JEV0LxiItfpQnBzeaRIq693VG8d30iCH4/1I0uqyCfxboWmm /CBpn9A8MCJu9NEEv+4+povNlfUfqi2yjsqJEVj8ztHxD4g9cc284Cv6 ySjxrSZ9axVqoaopEXujiTwwWJUFcgF6pxqyXVksW7sgKJrboM4VSlQD +Sw=
+rhino.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. T3Yf5PAkSeJtoOH90ea9zZBG9FC3iFhiCSerDn6d9up8GRfzxDsavYJC zQu+3vnOySySn+3TMzQSSFcWdJC2iO7ulaDGr177Gof9QJbKSVSMW7jt YDE2f4/R4Go3NZVwjk/HfpCInoR6pHNA1s/9hMnWtiVopmBdfzyd3/sW YOU=
+shark.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. SmhgyF48yX/6yH7AdSmGX60NL/xaiKH/oAzB0rnPfQZ6j+UfV57ginVV lj798K9A8jjucUpqE8ua2mZ6/aOhpqlV2iI0CZXG44zOupsCY1/OXBDx YNetBcjoXDQCBQRLLLEUL5FerDVxqT74ngdLdKubwRdrB0TLQlvpBr+F Tc8=
+pipit.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. Cz9etHnEOQTzu+6rYJEqx/SQ1tQgPOCyf8HSj4KOsx89jtgiHNC6pep6 ZE0SphMGAs3jC/uGIhlaFNZ3i38OQIMuqwacbz+XZyW5bByvV3QZrhqh dFxMDfmPuNiCAT3crFpUkvVW1OE3YfGHzZGXX7JP5wb1b8A3X6Qih7fV +nQ=
+pipit.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. piafjh6my2fooZRrzwCu9RQ95gYaMQkhIkDaGX/fT6wXzSdmgFZkS1Nl EMIKdDCQaPrLGMG3p32ptMkAm4esPekeyNtLSMBtXwZyUkgEGn6h1QM2 Yr3TOo8cixfk5nmRRdlYadf5krLb8yI9exiqeymgEQLa1YNRz/bWArlX bn8=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+ro.vutbr.cz. IN DS
+SECTION ANSWER
+ro.vutbr.cz. 28800 IN DS 16627 5 2 1AEE56EAF9D01A51C8C524E55A7FAE0E27207911F0FA6126052CE5B3 39335FC8
+ro.vutbr.cz. 28800 IN DS 16627 5 1 BFDFD0FB1EDFCEBFB9ECB13C93F9CA65755217BA
+ro.vutbr.cz. 28800 IN RRSIG DS 5 3 28800 20170216060902 20170117060902 39756 vutbr.cz. OOJfGI14bRHqeWhRLMOa75pfHo+clR4rMJpvO3PPjmheownqy2awA7u3 xR5FJko7A6e+difoJdAWCMzN7x1qcrd1htOOKOc7wtcb+QC2JH8B/e0G 0gNPw2UKsFL1Qw9HQkSqxyIaCGg3nMLO1hh3AVccZadw2f/jLpAzw5/1 pLA=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+ro.vutbr.cz. IN DNSKEY
+SECTION ANSWER
+ro.vutbr.cz. 3600 IN DNSKEY 256 3 5 AwEAAb4tyN4pqltB48s1xQS3ZPXnTZJMvgXxiouXU9xtzj4wnhjhZp45 H7ozslWuksrwQWhZ8AASAD5kPFbQRbwpQ7xbEb3xdKHaWCFpyRCTkrqa ZQZQy4gaVqO+oRW42dIQ9K08A/WfvRuRDtw3VWDATp9pUkgpvb1n6+lp 71YK19RX
+ro.vutbr.cz. 3600 IN DNSKEY 257 3 5 AwEAAef6bqTAl94KddNHvit41gw6QBKkiYjUeS+UP58VHybV29RC7sSE +rYmkXabaMOLmoqMQRMepBEaUdM5OoZBWibHrPAbG0Wf+vlMOoWD5+EC 2mCxrUntIlOuS4XpMTh22+l0k1xSPiMGKjY0BDR95Iu3dDezCVl9PkPp tHj/rAnRTH7Q0fH9Mip8sigosd/CmsoY03I0AcZT4z1+XpGsq5Npxwtj 7cz0SRTI/eV5nynNYK+vr6kOfU1fw7p8/wxIfXkks0Xy8ktXa26DFdw1 RoqVlTS1s1diFyF5niCOT6Ei2kAlf0fggZJBypwoK+6J42wwD2OhORX+ lKrhooaN4TU9AcHwgv25XTXhUq4tYh+veazdXNWDjEb3ZyLM8fKERCa9 YtDBFoHM7yFOHbsOhHKMn8F6T2Boi73hU/+wspjL/n8taKevyyygGg+U g4ugo2pTIouAs5DNnv+nUrpctcKZ5nMEUVl+3XBsXplIyz9QEKHWdFzL gyfIZEok8WdYHebcIy1vJrxzqCNw9ixnTn+OK1lwlMToVH1AGpvRKRPo wGSFaIrDyXxKul34j2jEhP9TWRcJqncy166Ueu3c0BKmclM29N8jeWbP 3TqRJ3RRxNj/vk6c/UGmmrHEz8YdNp2L0hv3JgItr2GujCvPApUvLNPW C7DSErQ3JsjV3gah
+ro.vutbr.cz. 3600 IN RRSIG DNSKEY 5 3 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. pN+8YElj24dhtnOQ20sjWxJTjx+FLTMrPms1lWIJKZtp2evQBG5AnAep 6w0QeMUTIh9ter58Dh6wu2IN4uA1h3ThxnSgwLraOChUFBtPTO8h5y8J mAq4KXSfqbEcHzZO/nBAtxSUk7aUz7yWf09xE+iozW3ORRWIXovMYci5 eEw=
+ro.vutbr.cz. 3600 IN RRSIG DNSKEY 5 3 3600 20170222120032 20170123120032 16627 ro.vutbr.cz. DSaIAl+iyToM8+ai9xuRVcRshYyI66XHWkOz0XEbIAwbc8aEMEeFCA91 1vpuBb6H92MXvM8hYsBhZHNIA0ApoIE4bdyEGZY05XN3GYgJ4BEhXJVM RR+inJf+vGGqdlRP6F2sPO+rCqfxWBvSoUFU7DpCpkl7hz2Ex0Clm9C9 YnWgL+tGmAH33s2Y8lTA3hG/0W0NxD5zy1LiyDa8Ls3vV4MC6gVxyloT Capd8FkDL9PmgW0gMRNtIWmc5Hw+j/HRMoy+oRCe8PIfUL/Dpx3iTAH8 iN3wV8apV2uPa0L8QgpixK4Tc87aSainCopVY+NOc5t0HErUzj8i7qA9 J/cRtQvlUzln5vBsrQsVIzIeNV4o8/cM3zFyfdKkHh1tWYKLJKkjfXc5 +7VMvF8PnoHceT/Zr2gCc8tnygRobypzgqy3p69bRJqiT0/eCAgpGusV 1DCOJY0sdiGDZEtpqeINbAgGKAMmmNwjIwYSFowRzdawip1wNd+90RhI +8hvx8Sc5+K5Mom2BF2wGHf/2Kv/ArzyXxqqcNozM61L1AjxIsBHjnLZ TzPlLntmiHUVaqET9Yc3G0K/RdsIpqz4M79N0BX66a58x2a3fLqQdrEC QshZPNxk2S4eCsrVRjHvU4a7e74Rbf/zXp89Y+jmwBbDMdnp+2/h9s6U J0sEBCYyo9M=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+piranha.ro.vutbr.cz. IN A
+SECTION ANSWER
+piranha.ro.vutbr.cz. 3600 IN A 147.229.2.90
+piranha.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. Jz8bcAADQjCKTCcF70IK1aHGQlM4ukyN0myABlxoPaqid1mHX5jwR91b kdQmUAh2xDitlgRLbFjbUUgmjSPzQ5Qt7GAFUsVmqxvjbOLZjqHER1dh zmiWO0fDvvP647Osv3RiAP822rNUJcJrUBZU9LmeP05gwIHcpJrhdVBT b7I=
+SECTION AUTHORITY
+ro.vutbr.cz. 86400 IN NS shark.ro.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS rhino.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN NS pipit.cis.vutbr.cz.
+ro.vutbr.cz. 86400 IN RRSIG NS 5 3 86400 20170222120032 20170123120032 12150 ro.vutbr.cz. HAQ8A+QNsS1WIXdW/fbT3jP+IxObBBvgUmvzsmJBXo8HMtnMAcuCQGmB 2JBQsQethQXsdyLnMK8to/5A9VRkqkAa7edxUoy7SdDi/mzGeLAVhF+5 kXSPD6t1vjiNdnIYAMpiOQbodCGxAnq6jnNyrjEzffdq3qw+5IkFNdG4 7Pw=
+SECTION ADDITIONAL
+rhino.cis.vutbr.cz. 86400 IN A 147.229.3.10
+rhino.cis.vutbr.cz. 86400 IN AAAA 2001:67c:1220:e000::93e5:30a
+shark.ro.vutbr.cz. 3600 IN A 147.229.2.59
+pipit.cis.vutbr.cz. 86400 IN A 77.93.219.110
+pipit.cis.vutbr.cz. 86400 IN AAAA 2a01:430:120::4d5d:db6e
+rhino.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. X/tDf8e3JEV0LxiItfpQnBzeaRIq693VG8d30iCH4/1I0uqyCfxboWmm /CBpn9A8MCJu9NEEv+4+povNlfUfqi2yjsqJEVj8ztHxD4g9cc284Cv6 ySjxrSZ9axVqoaopEXujiTwwWJUFcgF6pxqyXVksW7sgKJrboM4VSlQD +Sw=
+rhino.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. T3Yf5PAkSeJtoOH90ea9zZBG9FC3iFhiCSerDn6d9up8GRfzxDsavYJC zQu+3vnOySySn+3TMzQSSFcWdJC2iO7ulaDGr177Gof9QJbKSVSMW7jt YDE2f4/R4Go3NZVwjk/HfpCInoR6pHNA1s/9hMnWtiVopmBdfzyd3/sW YOU=
+shark.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. SmhgyF48yX/6yH7AdSmGX60NL/xaiKH/oAzB0rnPfQZ6j+UfV57ginVV lj798K9A8jjucUpqE8ua2mZ6/aOhpqlV2iI0CZXG44zOupsCY1/OXBDx YNetBcjoXDQCBQRLLLEUL5FerDVxqT74ngdLdKubwRdrB0TLQlvpBr+F Tc8=
+pipit.cis.vutbr.cz. 86400 IN RRSIG A 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. Cz9etHnEOQTzu+6rYJEqx/SQ1tQgPOCyf8HSj4KOsx89jtgiHNC6pep6 ZE0SphMGAs3jC/uGIhlaFNZ3i38OQIMuqwacbz+XZyW5bByvV3QZrhqh dFxMDfmPuNiCAT3crFpUkvVW1OE3YfGHzZGXX7JP5wb1b8A3X6Qih7fV +nQ=
+pipit.cis.vutbr.cz. 86400 IN RRSIG AAAA 5 4 86400 20170204080646 20170105080646 28257 cis.vutbr.cz. piafjh6my2fooZRrzwCu9RQ95gYaMQkhIkDaGX/fT6wXzSdmgFZkS1Nl EMIKdDCQaPrLGMG3p32ptMkAm4esPekeyNtLSMBtXwZyUkgEGn6h1QM2 Yr3TOo8cixfk5nmRRdlYadf5krLb8yI9exiqeymgEQLa1YNRz/bWArlX bn8=
+ENTRY_END
+
+; end of pipit.cis.vutbr.cz. & rhino.cis.vutbr.cz.
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.vutbr.cz. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.vutbr.cz. IN A
+SECTION ANSWER
+www.vutbr.cz. IN CNAME piranha.ro.vutbr.cz.
+piranha.ro.vutbr.cz. IN A 147.229.2.90
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.vutbr.cz. IN A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH flags rcode question answer
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+www.vutbr.cz. IN A
+SECTION ANSWER
+www.vutbr.cz. IN CNAME piranha.ro.vutbr.cz.
+www.vutbr.cz. IN RRSIG CNAME 5 3 300 20170216060902 20170117060902 39756 vutbr.cz. 9B3UC5SOEw1+yKlYlOTINEuNq0Kdglywc5IYJwzeSzQ3ykptzZo3ABSy bYhTqImVkhm/4NFM9/4HWMHPDzTmrWS0mCI/ljCd/oe/PxW/uESvo4P5 EQzlcuH6xBzc1KdEFAJOSmRzFjj3vyK1QN3k/c+1y2oMFOYOR2oOzCw+ MIE=
+piranha.ro.vutbr.cz. IN A 147.229.2.90
+piranha.ro.vutbr.cz. 3600 IN RRSIG A 5 4 3600 20170222120032 20170123120032 12150 ro.vutbr.cz. Jz8bcAADQjCKTCcF70IK1aHGQlM4ukyN0myABlxoPaqid1mHX5jwR91b kdQmUAh2xDitlgRLbFjbUUgmjSPzQ5Qt7GAFUsVmqxvjbOLZjqHER1dh zmiWO0fDvvP647Osv3RiAP822rNUJcJrUBZU9LmeP05gwIHcpJrhdVBT b7I=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/world_mx_nic_www.rpl b/tests/deckard/sets/resolver/world_mx_nic_www.rpl
new file mode 100644
index 0000000..c641b53
--- /dev/null
+++ b/tests/deckard/sets/resolver/world_mx_nic_www.rpl
@@ -0,0 +1,272 @@
+; test with real world Internet data
+; attempt to resolve www.nic.mx A leads to CNAME www.nicmexico.mx.
+; sub-tree nic.mx is not signed and nixmexico.mx is signed.
+; the answer must not have AD flag set!
+
+val-override-date: 20170124180319
+trust-anchor: ". 172800 IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"
+stub-addr: 2001:dc3::35
+CONFIG_END
+
+SCENARIO_BEGIN www.nic.mx. CNAME kresd issue #144
+
+; DNS root ; M.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 2001:dc3::35
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+. IN DNSKEY
+SECTION ANSWER
+. 16567 IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
+. 16567 IN DNSKEY 256 3 8 AwEAAYvgWbYkpeGgdPKaKTJU3Us4YSTRgy7+dzvfArIhi2tKoZ/WR1Df w883SOU6Uw7tpVRkLarN0oIMK/xbOBD1DcXnyfElBwKsz4sVVWmfyr/x +igD/UjrcJ5zEBUrUmVtHyjar7ccaVc1/3ntkhZjI1hcungAlOhPhHlk MeX+5Azx6GdX//An5OgrdyH3o/JmOPMDX1mt806JI/hf0EwAp1pBwo5e 8SrSuR1tD3sgNjr6IzCdrKSgqi92z49zcdis3EaY199WFW60DCS7ydu+ +T5Xa+GyOw1quagwf/JUC/mEpeBQYWrnpkBbpDB3sy4+P2i8iCvavehb RyVm9U0MlIc=
+. 16567 IN RRSIG DNSKEY 8 0 172800 20170201000000 20170111000000 19036 . Sh+EpofvZgk3J9szMD2B94FxFgyIUKz3hkbCjgWSTqPQyhqNgqVU8QlS EtOo8YLmS4AX98eit5Gmmb2ObpkGoXBmAzu5w/Qt5WsGsWzLQhYrsy9s lDmFQ2JKUoCyfdwqhlJ8VxjzdFdMUiVl+/GPnv4yjxjM8Ke3VAtBkn6n BO7JkcxxOfcgZdZ4MuvSr40K/SenZE+JlLLL1LF4TMCGqaZTTdOx6kFF KSSgy2AS884htWcK0tnwRc630g6nAI2wdvjlRLBeisbfXanI4v8iiPyT FnMmnV7wJGWJ4gtRJ0UH3u5RWXUPZ+s1tKytk3slXbLyQ9xkEDveuD+h b659gQ==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR DO NOERROR
+SECTION QUESTION
+mx. IN NS
+SECTION AUTHORITY
+mx. 172800 IN NS c.mx-ns.mx.
+mx. 172800 IN NS m.mx-ns.mx.
+mx. 172800 IN NS e.mx-ns.mx.
+mx. 172800 IN NS i.mx-ns.mx.
+mx. 172800 IN NS o.mx-ns.mx.
+mx. 172800 IN NS x.mx-ns.mx.
+mx. 86400 IN DS 55955 8 2 3d7f3313e86341ec23a02f8ed837572d62cf74bf175ac8b2f19b1e2b8930b0d5
+mx. 86400 IN RRSIG DS 8 1 86400 20170206050000 20170124040000 61045 . DYmv0z7EnlUOu081yDzeh3tourMFyYtBv7IKIiwPN5ZXuHmw0PvqT0oU//DomnA0NdfCRizOSmvDlZITNtlTffEA3mudnbPC+TEpdf1nffHLHQPnjcS0U+zfoBvRK0OHha3J7YgSXFQuCskJAg4P6ktPzgcd2ccv/FRlzzw4CrZOE3AtDWir31xt8c8DxZjysjIptblua7o9kwac+biWoszUl+sJBAXGbn0XXMloTAisYHyyZF9YeTRz3er8gyao8ynRe2KgUZPX4ieVQl+BsXDOmVRYLE8l4hLSRanjoWOR3gAqQUHJwn9xXxhGfApe5tUhaCE7v1EplCw9ykaKVA==
+SECTION ADDITIONAL
+c.mx-ns.mx. 172800 IN A 192.100.224.1
+e.mx-ns.mx. 172800 IN A 189.201.244.1
+i.mx-ns.mx. 172800 IN A 207.248.68.1
+m.mx-ns.mx. 172800 IN A 200.94.176.1
+o.mx-ns.mx. 172800 IN A 200.23.1.1
+x.mx-ns.mx. 172800 IN A 201.131.252.1
+c.mx-ns.mx. 172800 IN AAAA 2001:1258::1
+m.mx-ns.mx. 172800 IN AAAA 2001:13c7:7000::1
+ENTRY_END
+; end of M.ROOT-SERVERS.NET.
+RANGE_END
+
+; ?.mx-ns.mx.
+RANGE_BEGIN 0 100
+ ADDRESS 192.100.224.1
+ ADDRESS 189.201.244.1
+ ADDRESS 207.248.68.1
+ ADDRESS 200.94.176.1
+ ADDRESS 200.23.1.1
+ ADDRESS 201.131.252.1
+ ADDRESS 2001:1258::1
+ ADDRESS 2001:13c7:7000::1
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+mx. IN DNSKEY
+SECTION ANSWER
+mx. 86400 IN DNSKEY 257 3 8 AwEAAcokawGJMW4OI1eas0vAtfl0etrPSlqkh7n/JPpdMt5fplkWI0oo YS3kYBXYzMxXnpNOK57jp5JodELeZKDrHCrUhAzZiy5iJQDy9Qi85mSC KTHg32+JKjXiMEkTZUlOzNRrXC7apWfZbzbx98CnzkWw0Xj2wDIniptM jnwAJeb8L+Mm5AzZSkUugga/eDvpVsT5MZZnT/DuJdxS5olx+HyTKLct m/LDljtQKJya0UtXUKkVc5cv8y+ja5AivjXXrUmDcgd1P6bntcbjpcFY UuLZMsmyOZ2uViXNEhIdBcP+davulxW++DawqOtvnpuRxfLFsuYw/vDC ilfIGEdgz20=
+mx. 86400 IN DNSKEY 256 3 8 AwEAAcwqWcnh23qhQTbWsbOKbRI4btNQCYRa4ksadH8VjQ++VruqkhPu d7e/RsZMhevCWDJHrjfJ739NmiGIwS58uh1sVACfKRmxLP25/1V9frIi HBxkaVLXPAHm8+ApIhzUzaUTUrmSnDm0/wJryo34zETnA6J4czfzYDLX Vqh3KVtL
+mx. 86400 IN RRSIG DNSKEY 8 1 86400 20170223000000 20170124000000 48529 mx. BYGaUXiyB0vIi4sBwvUuL2Im+zcIpykZD96YdvA3Kpk7RlV3LcLD9L6B +HpwFWMRZ+vt09YW/jrzSR9mlXpZeWR6BhHoo9f2MGOO5dwejnUuipLD +t5wKi91XALmaRN4Z2ptdJ0wVMpfXlkfrNTB+RvYAqx/azDGw5Ewjh7C J5Y=
+mx. 86400 IN RRSIG DNSKEY 8 1 86400 20170303150000 20170102150000 55955 mx. SboaaGva7+GbfoNKa8Ov2GhSIvYStcBeudk0A0+53/LMs7sHuLegE9+P lTqih4sl/W1Yd4a4jWoVYGGYu8M4tb1fzaxvr5eTDwm3gKGirbTsQPFl Ih5gNnC6QJKYBhpN7w/Fn3JmJTBLwhd7tREygGqkNO/LdTwiHfbcIzkU 5UpD9A3/oeZoMQe71AvJstU5PIHxg3PU1CNU9YBcNhYzUfTfcr+hlbmA Nm6RaOBaWJwp4YzcS3uJcaXmpS1t/lbxWIgeOXRhql6ZHqCai0lSmNnm vAydmJI/cqXsJ23Pj22TD1QwDFKTp0u2oIiykeFzdbIG0s2thtmyY4km qh1Ulg==
+ENTRY_END
+
+; nix.mx
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+nic.mx. IN NS
+SECTION ANSWER
+nic.mx. 172800 IN NS o.mx-ns.mx.
+nic.mx. 172800 IN NS m.mx-ns.mx.
+nic.mx. 172800 IN NS c.mx-ns.mx.
+nic.mx. 172800 IN NS x.mx-ns.mx.
+nic.mx. 172800 IN NS e.mx-ns.mx.
+nic.mx. 172800 IN NS i.mx-ns.mx.
+SECTION ADDITIONAL
+c.mx-ns.mx. 172800 IN A 192.100.224.1
+c.mx-ns.mx. 172800 IN AAAA 2001:1258::1
+e.mx-ns.mx. 172800 IN A 189.201.244.1
+i.mx-ns.mx. 172800 IN A 207.248.68.1
+m.mx-ns.mx. 172800 IN A 200.94.176.1
+m.mx-ns.mx. 172800 IN AAAA 2001:13c7:7000::1
+o.mx-ns.mx. 172800 IN A 200.23.1.1
+x.mx-ns.mx. 172800 IN A 201.131.252.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+nic.mx. IN DS
+SECTION AUTHORITY
+qpcf3eq45ur6ndho0ecuj1o25g7d48pi.mx. 1800 IN NSEC3 1 1 100 FBB1D947FF931FC5 QPDGRP34SI0F3CBG41HRN7G8TLFK6C7B NS SOA RRSIG DNSKEY NSEC3PARAM
+qpcf3eq45ur6ndho0ecuj1o25g7d48pi.mx. 1800 IN RRSIG NSEC3 8 2 1800 20170223000000 20170124000000 48529 mx. RI7Ezya54VVVcCiyH2rHBjRwWzsoe2A1vBcwzFUeiKFPsoOsCkvAfpvU uZ96IEa0Ni7ZksS2XFuV9TeQotk/HirhRGq2AauGtF4RLExmZnZouAjz tLZYXhr7mZAqfKLzZV5qNzlYSia3wF9m4wkz4eSBfeJ/6u2AoQP81C3Y Dls=
+mx. 1800 IN SOA m.mx-ns.mx. hostmaster.nic.mx. 1485251802 900 900 604800 1800
+mx. 1800 IN RRSIG SOA 8 1 86400 20170223000000 20170124000000 48529 mx. Gwjg+/GJUJj32FMa9HKESM7zsPFdVVEotOIyXKhZjOX139PhfbcOdfJr bfhDvVV8weMoLHhM0rVko0Sr+H8S3+R8wNOkvoFPqd3G5YV2azS52qOQ xPq1gVT0g3bWtmgF0KV2fGQ2Lcw7ynksenBmpQCggjbh/O98zwfRJkcc Huk=
+1e790cnnc0n6fmd7hhf7o1baus5muq9l.mx. 1800 IN NSEC3 1 1 100 FBB1D947FF931FC5 1EDMBBOCRH8AB8GRQF55CMJV2IS3U6E7 NS DS RRSIG
+1e790cnnc0n6fmd7hhf7o1baus5muq9l.mx. 1800 IN RRSIG NSEC3 8 2 1800 20170223000000 20170124000000 48529 mx. xP9wMq871/wi0N99DkUhXHB1VjyjG5zds0CHIdrm1MC0JPl2atB1nliC tYC/nMC6vHGRk7bcX0kFNDgi0duGuNwKEHyTp2gHBSoMefUtDfJbOoq8 4VSQvS0WaJlK1H3eV21AdhmpZEAe0YB6e7lU5plhqNMX5mxDD5d0ZVD8 TWI=
+ENTRY_END
+
+; this entry is the one which caused kresd to return AD flag despite of missing RRSIGs
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+www.nic.mx. IN A
+SECTION ANSWER
+www.nic.mx. 300 IN CNAME www.nicmexico.mx.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO NOERROR
+SECTION QUESTION
+www.nic.mx. IN RRSIG
+SECTION AUTHORITY
+nic.mx. 1800 IN SOA m.mx-ns.mx. hostmaster.nic.mx. 2016101701 3600 900 604800 1800
+ENTRY_END
+
+; nixmexico.mx
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA RD NOERROR
+SECTION QUESTION
+nicmexico.mx. IN NS
+SECTION ANSWER
+nicmexico.mx. 172800 IN NS o.mx-ns.mx.
+nicmexico.mx. 172800 IN NS m.mx-ns.mx.
+nicmexico.mx. 172800 IN NS e.mx-ns.mx.
+nicmexico.mx. 172800 IN NS x.mx-ns.mx.
+nicmexico.mx. 172800 IN NS i.mx-ns.mx.
+nicmexico.mx. 172800 IN NS c.mx-ns.mx.
+nicmexico.mx. 172800 IN RRSIG NS 7 2 172800 20170221235959 20161221161902 14618 nicmexico.mx. MMPJ1lltyGLyE+s+V7mFb3iJzWkKgnCRtBGgVqynFaKJBgEX+0NFy8Iq o8CKWlXGXitDilaE3xy6ynYnb8CeQuEeaKVLzikUwxu+bTR/tcX1fECp 2i9uDFTl/wrYSyNU4gEy/4Ueev5GsM8XQmK5j8xgUmwc+258eRBZ129O K1E=
+SECTION ADDITIONAL
+c.mx-ns.mx. 172800 IN A 192.100.224.1
+c.mx-ns.mx. 172800 IN AAAA 2001:1258::1
+e.mx-ns.mx. 172800 IN A 189.201.244.1
+i.mx-ns.mx. 172800 IN A 207.248.68.1
+m.mx-ns.mx. 172800 IN A 200.94.176.1
+m.mx-ns.mx. 172800 IN AAAA 2001:13c7:7000::1
+o.mx-ns.mx. 172800 IN A 200.23.1.1
+x.mx-ns.mx. 172800 IN A 201.131.252.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+nicmexico.mx. IN DS
+SECTION ANSWER
+nicmexico.mx. 86400 IN DS 25953 7 1 3980E3CBB2DC1F0A39EE58454F218D695C6FCF2B
+nicmexico.mx. 86400 IN DS 25953 7 2 E390593C68F6C5BD1A38E3CF7D9643235AC9C09A1023EBEA8E6D56FC 9EF2AAA6
+nicmexico.mx. 86400 IN RRSIG DS 8 2 86400 20170223000000 20170124000000 48529 mx. kwiqOPNYD6k+CPGGewQ7YWnJqomLkr4wrIT96qnb11l1m+BBtCZnxh1X 9u1I4nQsLC9/gJh1sytYkMogObxd6CsMUwAn8lA7Pnlbz1upINis7oE5 2MoHjYDhhJnfSryTtiw5Xak+Bup3GGmi4KgNsitQXUK8rFg5xAwyjtb6 udg=
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+nicmexico.mx. IN DNSKEY
+SECTION ANSWER
+nicmexico.mx. 172800 IN DNSKEY 257 3 7 AwEAAdU7ho1gF5Swo/P3EMrcm82fE3bSvXec/q4HvGndCS+iEhOVMQgx SmjhdnILgNE23x5v7iprrQdcrC6qG3h5pWromlJt4zqqWD91OuydXGpB vkx9o3gWo9wqr+2mX4cPKsKKhiyQ1EBEbaYZP1PqEWigdTuzVB2zGWAu yCNlbgHX8Q4pgU/P+jdTB0RFkQEa7BtIu/+7JYpB09REdjtn4AgdqaVK rq9gQRxAbpuQezw5vEnK/EFiH+FIa8FWctMhRkC2IdG5THpG8lzZry+Q 04Mih/r7tsY/RbA0asG4RVOFTtHCdjIZc4f4fxNIaR4B7IzBPIWN0d3/ ILI6sObAnJs=
+nicmexico.mx. 172800 IN DNSKEY 256 3 7 AwEAAdlPfZYpM3PWP1ub8MDc4fSBVu3f+lS3ojPAaKNEgXu0mzGP9BtS Rj7kAIR2BQN61sb6b2QIT2QnGSkOjfho0TLm1UjcAMjRC6A4bwVmwYgj OMXd56jRi1zeus3nBz661inwqSOOs4+72SiVLqmbzDV0uFHAZFrSIrS0 Fp5vDTS/
+nicmexico.mx. 172800 IN DNSKEY 256 3 7 AwEAAbmZ5YmUhQKofswApd84tnITiUqh8kyN609rOanl3ga7WEjGs2bD D8RU/oOj31OzfnEFLSLH0fpIWCPWT+lvZ9HFOxAMavXnwncKsAVLNrv+ CuBGTiQ4wa2C/vQ7i/D1SbnXAUs/17Pu9onlAGeDoolgsUAgldfRwEGp tVfY8r71
+nicmexico.mx. 172800 IN RRSIG DNSKEY 7 2 172800 20170221235959 20161221161902 14618 nicmexico.mx. BTeItGos/TVLbiYrisWuJCFmdnA+p3yBHOMfUsvPAOvs5trTincG5wkY EHsq13Dvk9JNjSYh4HPlmlnsXDmUPXm6Z4bd1BXFVPiK3r4I1YGwwP/M ATNjw5V8w+my3PvOQdwyhWiF8dnd0EfeK3t+b/prwZiWs64ezaNiMxUk i5s=
+nicmexico.mx. 172800 IN RRSIG DNSKEY 7 2 172800 20170221235959 20161221161902 25953 nicmexico.mx. NPVmWrmIeGHYOjrfonov29kFG5gP2vaP0qE8sZplYt44MzgBnhLt+cZS sk6NNEhLPgYe4fiPxj3xzT+BjxTUCCQo3CT1KR4uaEIbepBmxDx8dMv6 4c1AO2wNnt8x/OBG+Nwg3gLaf4UtdJvOQsdpOsTzqKKo7WPKxeb462gw 4aZzYh4uhEjTFil8eGLXOlGe8CYThAdwxKbA6tEZxE5UEa2mIb2orSbz ro+ehp6imnn3YWtLWBtkWQqsSaqLug4HUrXgjbqNSZ+FCdO4WIxLgDsz k+jlA7tdkZknE43AQX/md6orKDalCb4OtrC0yrgYDtwVsgP1qZVAjJWW 09nUIg==
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA DO
+SECTION QUESTION
+www.nicmexico.mx. IN A
+SECTION ANSWER
+www.nicmexico.mx. 172800 IN A 200.94.180.55
+www.nicmexico.mx. 172800 IN A 200.94.180.54
+www.nicmexico.mx. 172800 IN A 200.94.180.57
+www.nicmexico.mx. 172800 IN A 200.94.180.56
+www.nicmexico.mx. 172800 IN RRSIG A 7 3 172800 20170221235959 20161221161902 14618 nicmexico.mx. s3THv+Ay2WrcOTG6bo+54Zc/rff/jhzcJKZ3ZRYMXhw3FToSvTOSqsIG 1gzW/Sk6r2oikHH3nNluaMTAXfCULu2mHiQVAuFlnajFSMPcm8KvEyV0 cCT7knkAFqb+ODkimPMufRHiOLbnhQk9/A25qK7J8rCB76IUmzk41hYR NBU=
+SECTION AUTHORITY
+nicmexico.mx. 172800 IN NS m.mx-ns.mx.
+nicmexico.mx. 172800 IN NS c.mx-ns.mx.
+nicmexico.mx. 172800 IN NS i.mx-ns.mx.
+nicmexico.mx. 172800 IN NS o.mx-ns.mx.
+nicmexico.mx. 172800 IN NS x.mx-ns.mx.
+nicmexico.mx. 172800 IN NS e.mx-ns.mx.
+nicmexico.mx. 172800 IN RRSIG NS 7 2 172800 20170221235959 20161221161902 14618 nicmexico.mx. MMPJ1lltyGLyE+s+V7mFb3iJzWkKgnCRtBGgVqynFaKJBgEX+0NFy8Iq o8CKWlXGXitDilaE3xy6ynYnb8CeQuEeaKVLzikUwxu+bTR/tcX1fECp 2i9uDFTl/wrYSyNU4gEy/4Ueev5GsM8XQmK5j8xgUmwc+258eRBZ129O K1E=
+SECTION ADDITIONAL
+c.mx-ns.mx. 172800 IN A 192.100.224.1
+e.mx-ns.mx. 172800 IN A 189.201.244.1
+i.mx-ns.mx. 172800 IN A 207.248.68.1
+m.mx-ns.mx. 172800 IN A 200.94.176.1
+o.mx-ns.mx. 172800 IN A 200.23.1.1
+x.mx-ns.mx. 172800 IN A 201.131.252.1
+c.mx-ns.mx. 172800 IN AAAA 2001:1258::1
+m.mx-ns.mx. 172800 IN AAAA 2001:13c7:7000::1
+ENTRY_END
+
+; end ?.mx-ns.mx.
+RANGE_END
+
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.nic.mx. IN A
+ENTRY_END
+
+STEP 11 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.nic.mx. IN A
+SECTION ANSWER
+www.nic.mx. 300 IN CNAME www.nicmexico.mx.
+www.nicmexico.mx. 171139 IN A 200.94.180.57
+www.nicmexico.mx. 171139 IN A 200.94.180.56
+www.nicmexico.mx. 171139 IN A 200.94.180.54
+www.nicmexico.mx. 171139 IN A 200.94.180.55
+www.nicmexico.mx. 171139 IN RRSIG A 7 3 172800 20170221235959 20161221161902 14618 nicmexico.mx. s3THv+Ay2WrcOTG6bo+54Zc/rff/jhzcJKZ3ZRYMXhw3FToSvTOSqsIG1gzW/Sk6r2oikHH3nNluaMTAXfCULu2mHiQVAuFlnajFSMPcm8KvEyV0cCT7knkAFqb+ODkimPMufRHiOLbnhQk9/A25qK7J8rCB76IUmzk41hYRNBU=
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.nicmexico.mx. IN A
+ENTRY_END
+
+STEP 21 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH rcode flags question answer
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.nicmexico.mx. IN A
+SECTION ANSWER
+www.nicmexico.mx. 170708 IN A 200.94.180.55
+www.nicmexico.mx. 170708 IN A 200.94.180.56
+www.nicmexico.mx. 170708 IN A 200.94.180.54
+www.nicmexico.mx. 170708 IN A 200.94.180.57
+www.nicmexico.mx. 172800 IN RRSIG A 7 3 172800 20170221235959 20161221161902 14618 nicmexico.mx. s3THv+Ay2WrcOTG6bo+54Zc/rff/jhzcJKZ3ZRYMXhw3FToSvTOSqsIG 1gzW/Sk6r2oikHH3nNluaMTAXfCULu2mHiQVAuFlnajFSMPcm8KvEyV0 cCT7knkAFqb+ODkimPMufRHiOLbnhQk9/A25qK7J8rCB76IUmzk41hYR NBU=
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/deckard/sets/resolver/zone.rpz b/tests/deckard/sets/resolver/zone.rpz
new file mode 100644
index 0000000..a45c53d
--- /dev/null
+++ b/tests/deckard/sets/resolver/zone.rpz
@@ -0,0 +1,10 @@
+$TTL 30
+@ SOA nonexistent.nodomain.none. dummy.nodomain.none. 1 12h 15m 3w 2h
+ NS nonexistant.nodomain.none.
+
+example.cz CNAME .
+*.example.cz CNAME *.
+nic.cz CNAME rpz-drop.
+*.nic.cz CNAME rpz-tcp-only.
+example.com CNAME rpz-passthru.
+
diff --git a/tests/deckard/setup.py b/tests/deckard/setup.py
new file mode 100644
index 0000000..9e2d532
--- /dev/null
+++ b/tests/deckard/setup.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+from distutils.core import setup
+
+version = '3.0'
+
+setup(
+ name='deckard',
+ version=version,
+ description='DNS toolkit',
+ long_description=(
+ "Deckard is a DNS software testing based on library pydnstest."
+ "It supports parsing and running Unbound-like test scenarios,"
+ "and setting up a mock DNS server. It's based on dnspython."),
+ author='CZ.NIC',
+ author_email='knot-dns-users@lists.nic.cz',
+ license='BSD',
+ url='https://gitlab.labs.nic.cz/knot/deckard',
+ packages=['pydnstest'],
+ python_requires='>=3.5',
+ install_requires=[
+ 'dnspython>=1.15',
+ 'jinja2',
+ 'PyYAML',
+ 'python-augeas'
+ ],
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Programming Language :: Python :: 3 :: Only'
+ 'Operating System :: POSIX :: Linux',
+ 'Topic :: Internet :: Name Service (DNS)',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Software Development :: Quality Assurance',
+ 'Topic :: Software Development :: Testing',
+ ]
+)
diff --git a/tests/deckard/template/dnssec_getdns.j2 b/tests/deckard/template/dnssec_getdns.j2
new file mode 100644
index 0000000..282dc9f
--- /dev/null
+++ b/tests/deckard/template/dnssec_getdns.j2
@@ -0,0 +1,3 @@
+{% for TA in TRUST_ANCHORS %}
+{{TA}}
+{% endfor %}
diff --git a/tests/deckard/template/getdns.j2 b/tests/deckard/template/getdns.j2
new file mode 100644
index 0000000..49064d4
--- /dev/null
+++ b/tests/deckard/template/getdns.j2
@@ -0,0 +1,6 @@
+{ "listen_addresses": [ {{SELF_ADDR}} ]
+, "dns_root_servers": [ {{ROOT_ADDR}} ]
+, "timeout": 2000
+, "dnssec_return_status": GETDNS_EXTENSION_TRUE
+, "dnssec_trust_anchors": "getdns-root.key"
+}
diff --git a/tests/deckard/template/hints_zone.j2 b/tests/deckard/template/hints_zone.j2
new file mode 100644
index 0000000..b46b30d
--- /dev/null
+++ b/tests/deckard/template/hints_zone.j2
@@ -0,0 +1,9 @@
+; This file holds the information on root name servers needed to
+; initialize cache of Internet domain name servers
+
+. 3600000 NS K.ROOT-SERVERS.NET.
+{% if ':' in ROOT_ADDR %}
+K.ROOT-SERVERS.NET. 3600000 AAAA {{ROOT_ADDR}}
+{% else %}
+K.ROOT-SERVERS.NET. 3600000 A {{ROOT_ADDR}}
+{% endif %}
diff --git a/tests/deckard/template/knotd_master.j2 b/tests/deckard/template/knotd_master.j2
new file mode 100644
index 0000000..ccf1f72
--- /dev/null
+++ b/tests/deckard/template/knotd_master.j2
@@ -0,0 +1,29 @@
+#
+# This is a sample of a minimal configuration file for Knot DNS.
+# For more details, see man 5 knot.conf or refer to the server documentation.
+#
+
+server:
+ listen: {{SELF_ADDR}}@53
+
+control:
+ listen: "{{WORKING_DIR}}/knotd.sock"
+
+log:
+ - target: stdout
+ any: info
+
+acl:
+ - id: acl_slave
+ address: {{ROOT_ADDR}}
+ action: transfer
+
+template:
+ - id: default
+ storage: "{{WORKING_DIR}}"
+
+zone:
+ - domain: example.com
+ file: "{{INSTALL_DIR}}/sets/knotd/master/example.com.zone"
+ acl: acl_slave
+
diff --git a/tests/deckard/template/knotd_slave.j2 b/tests/deckard/template/knotd_slave.j2
new file mode 100644
index 0000000..4ac768e
--- /dev/null
+++ b/tests/deckard/template/knotd_slave.j2
@@ -0,0 +1,28 @@
+#
+# This is a sample of a minimal configuration file for Knot DNS.
+# For more details, see man 5 knot.conf or refer to the server documentation.
+#
+
+server:
+ listen: {{SELF_ADDR}}@53
+
+control:
+ listen: "{{WORKING_DIR}}/knotd.sock"
+
+log:
+ - target: stdout
+ any: info
+
+remote:
+ - id: master
+ address: {{ROOT_ADDR}}@53
+
+template:
+ - id: default
+ storage: "{{WORKING_DIR}}"
+
+zone:
+ - domain: example.com
+ file: "{{WORKING_DIR}}/example.com.zone"
+ master: master
+
diff --git a/tests/deckard/template/kresd.j2 b/tests/deckard/template/kresd.j2
new file mode 100644
index 0000000..4d5a877
--- /dev/null
+++ b/tests/deckard/template/kresd.j2
@@ -0,0 +1,111 @@
+net = { '{{SELF_ADDR}}' }
+modules = {'stats', 'policy', 'hints'}
+-- test. domain is used by some tests, allow it
+policy.add(policy.suffix(policy.PASS, {todname('test.')}))
+-- extra verbose logging for answers received from network
+policy.add(policy.all(policy.QTRACE))
+cache.size = 2*MB
+hints.root({['k.root-servers.net'] = '{{ROOT_ADDR}}'})
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+{% if DO_NOT_QUERY_LOCALHOST == "false" %}
+option('ALLOW_LOCAL', true)
+{% else %}
+option('ALLOW_LOCAL', false)
+{% endif %}
+
+{% if HARDEN_GLUE == "true" %}
+mode('normal')
+{% else %}
+mode('permissive')
+{% endif %}
+-- Always retry failing resolver
+option('NO_THROTTLE', true)
+
+{% for TAF in TRUST_ANCHOR_FILES %}
+trust_anchors.add_file('{{TAF}}')
+{% endfor %}
+trust_anchors.set_insecure({
+{% for DI in NEGATIVE_TRUST_ANCHORS %}
+"{{DI}}",
+{% endfor %}
+})
+
+
+{% if FEATURES.min_ttl is defined %}
+cache.min_ttl({{FEATURES.min_ttl}})
+{% endif %}
+
+{% if FEATURES.max_ttl is defined %}
+cache.max_ttl({{FEATURES.max_ttl}})
+{% endif %}
+
+{% if FEATURES.dns64_prefix is defined %}
+modules.load( 'dns64')
+dns64.config('{{FEATURES.dns64_prefix}}')
+{% endif %}
+
+{% if FEATURES.static_hint_name is defined %}
+{% if FEATURES.static_hint_addr is defined %}
+hints['{{FEATURES.static_hint_name}}'] = '{{FEATURES.static_hint_addr}}'
+{% endif %}
+{% endif %}
+
+{% if FEATURES.renumber_src is defined %}
+{% if FEATURES.renumber_dst is defined %}
+modules.load( 'renumber')
+renumber.config({{ '{{' }}'{{FEATURES.renumber_src}}','{{FEATURES.renumber_dst}}' {{ '}}' }})
+{% endif %}
+{% endif %}
+
+{% for policy in FEATURES.policy %}
+{{policy}}
+{% endfor %}
+
+{% if FEATURES.view is defined %}
+modules.load( 'view')
+{% for view in FEATURES.view %}
+{{view}}
+{% endfor %}
+{% endif %}
+
+{% if FEATURES.workarounds is defined %}
+modules = { 'workarounds < iterate' }
+{% endif %}
+
+-- Disable RFC8145 signaling, scenario doesn't provide expected ansers
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+
+-- Disable RFC8109 priming, scenario doesn't provide expected ansers
+if priming then
+ modules.unload('priming')
+end
+
+-- Disable this module because it make one priming query.
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+verbose(true)
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/tests/deckard/template/pdns_dnssec.j2 b/tests/deckard/template/pdns_dnssec.j2
new file mode 100644
index 0000000..fbb00d9
--- /dev/null
+++ b/tests/deckard/template/pdns_dnssec.j2
@@ -0,0 +1,5 @@
+-- only DS records are accepted, DNSKEY records will cause errors
+-- addDS takes 2 arguments, the node in the DNS-tree and the data of the corresponding DS record
+{% for TA in TRUST_ANCHORS %}
+addDS('{{TA.split()[0]}}', '{{' '.join(TA.split()[-4:])}}')
+{% endfor %}
diff --git a/tests/deckard/template/pdns_recursor.j2 b/tests/deckard/template/pdns_recursor.j2
new file mode 100644
index 0000000..5e6c091
--- /dev/null
+++ b/tests/deckard/template/pdns_recursor.j2
@@ -0,0 +1,312 @@
+# Autogenerated configuration file template
+#################################
+# aaaa-additional-processing turn on to do AAAA additional processing (slow)
+#
+# aaaa-additional-processing=off
+
+#################################
+# allow-from If set, only allow these comma separated netmasks to recurse
+#
+#allow-from=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10
+allow-from=
+
+#################################
+# allow-from-file If set, load allowed netmasks from this file
+#
+# allow-from-file=
+
+#################################
+# auth-can-lower-ttl If we follow RFC 2181 to the letter, an authoritative server can lower the TTL of NS records
+#
+# auth-can-lower-ttl=off
+
+#################################
+# auth-zones Zones for which we have authoritative data, comma separated domain=file pairs
+#
+# auth-zones=
+
+#################################
+# chroot switch to chroot jail
+#
+# chroot=
+
+#################################
+# client-tcp-timeout Timeout in seconds when talking to TCP clients
+#
+# client-tcp-timeout=2
+
+#################################
+# config-dir Location of configuration directory (recursor.conf)
+#
+# config-dir=/etc/powerdns/
+config-dir={{WORKING_DIR}}
+
+#################################
+# daemon Operate as a daemon
+#
+daemon=no
+
+#################################
+# delegation-only Which domains we only accept delegations from
+#
+# delegation-only=
+
+#################################
+# disable-edns Disable EDNS
+#
+# disable-edns=
+
+#################################
+# disable-edns-ping Disable EDNSPing
+#
+# disable-edns-ping=no
+
+#################################
+# disable-packetcache Disable packetcache
+#
+# disable-packetcache=no
+
+dnssec={% if TRUST_ANCHORS|length > 0 %}validate{%else%}process{%endif%}
+
+#################################
+# dont-query If set, do not query these netmasks for DNS data
+#
+# dont-query=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10
+dont-query=
+
+#################################
+# entropy-source If set, read entropy from this file
+#
+# entropy-source=/dev/urandom
+
+#################################
+# etc-hosts-file Path to 'hosts' file
+#
+# etc-hosts-file=/etc/hosts
+
+#################################
+# export-etc-hosts If we should serve up contents from /etc/hosts
+#
+# export-etc-hosts=off
+
+#################################
+# forward-zones Zones for which we forward queries, comma separated domain=ip pairs
+#
+# forward-zones=
+
+#################################
+# forward-zones-file File with (+)domain=ip pairs for forwarding
+#
+# forward-zones-file=
+
+#################################
+# forward-zones-recurse Zones for which we forward queries with recursion bit, comma separated domain=ip pairs
+#
+# forward-zones-recurse=
+
+#################################
+# hint-file If set, load root hints from this file
+#
+# hint-file=
+hint-file=hints.pdns
+
+#################################
+# ignore-rd-bit Assume each packet requires recursion, for compatability
+#
+# ignore-rd-bit=off
+
+#################################
+# local-address IP addresses to listen on, separated by spaces or commas. Also accepts ports.
+#
+local-address={{SELF_ADDR}}
+
+#################################
+# local-port port to listen on
+#
+local-port=53
+
+#################################
+# log-common-errors If we should log rather common errors
+#
+# log-common-errors=yes
+
+#################################
+# logging-facility Facility to log messages as. 0 corresponds to local0
+#
+# logging-facility=
+
+lua-config-file={{WORKING_DIR}}/dnssec.lua
+
+#################################
+# lua-dns-script Filename containing an optional 'lua' script that will be used to modify dns answers
+#
+# lua-dns-script=
+
+#################################
+# max-cache-entries If set, maximum number of entries in the main cache
+#
+# max-cache-entries=1000000
+max-cache-entries=1000000
+
+#################################
+# max-cache-ttl maximum number of seconds to keep a cached entry in memory
+#
+# max-cache-ttl=86400
+
+#################################
+# max-mthreads Maximum number of simultaneous Mtasker threads
+#
+# max-mthreads=2048
+
+#################################
+# max-negative-ttl maximum number of seconds to keep a negative cached entry in memory
+#
+# max-negative-ttl=3600
+
+#################################
+# max-packetcache-entries maximum number of entries to keep in the packetcache
+#
+# max-packetcache-entries=500000
+
+#################################
+# max-tcp-clients Maximum number of simultaneous TCP clients
+#
+# max-tcp-clients=128
+
+#################################
+# max-tcp-per-client If set, maximum number of TCP sessions per client (IP address)
+#
+# max-tcp-per-client=0
+
+#################################
+# network-timeout Wait this nummer of milliseconds for network i/o
+#
+# network-timeout=1500
+
+#################################
+# no-shuffle Don't change
+#
+# no-shuffle=off
+
+#################################
+# packetcache-servfail-ttl maximum number of seconds to keep a cached servfail entry in packetcache
+#
+# packetcache-servfail-ttl=60
+
+#################################
+# packetcache-ttl maximum number of seconds to keep a cached entry in packetcache
+#
+# packetcache-ttl=3600
+
+#################################
+# pdns-distributes-queries If PowerDNS itself should distribute queries over threads (EXPERIMENTAL)
+#
+# pdns-distributes-queries=no
+
+#################################
+# processes Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)
+#
+# processes=1
+
+#################################
+# query-local-address Source IP address for sending queries
+#
+query-local-address=0.0.0.0
+
+#################################
+# query-local-address6 Source IPv6 address for sending queries
+query-local-address6=::
+
+#################################
+# quiet Suppress logging of questions and answers
+#
+quiet=no
+
+#################################
+# remotes-ringbuffer-entries maximum number of packets to store statistics for
+#
+# remotes-ringbuffer-entries=0
+
+security-poll-suffix=
+
+#################################
+# serve-rfc1918 If we should be authoritative for RFC 1918 private IP space
+#
+serve-rfc1918=no
+
+#################################
+# server-id Returned when queried for 'server.id' TXT or NSID, defaults to hostname
+#
+# server-id=
+
+#################################
+# setgid If set, change group id to this gid for more security
+#
+#setgid=pdns
+
+#################################
+# setuid If set, change user id to this uid for more security
+#
+#setuid=pdns
+
+#################################
+# single-socket If set, only use a single socket for outgoing queries
+#
+# single-socket=off
+
+#################################
+# soa-minimum-ttl Don't change
+#
+# soa-minimum-ttl=0
+
+#################################
+# soa-serial-offset Don't change
+#
+# soa-serial-offset=0
+
+#################################
+# socket-dir Where the controlsocket will live
+#
+socket-dir={{WORKING_DIR}}
+
+#################################
+# socket-group Group of socket
+#
+# socket-group=
+
+#################################
+# socket-mode Permissions for socket
+#
+# socket-mode=
+
+#################################
+# socket-owner Owner of socket
+#
+# socket-owner=
+
+#################################
+# spoof-nearmiss-max If non-zero, assume spoofing after this many near misses
+#
+# spoof-nearmiss-max=20
+
+#################################
+# stack-size stack size per mthread
+#
+# stack-size=200000
+
+#################################
+# threads Launch this number of threads
+#
+threads=1
+
+#################################
+# trace if we should output heaps of logging
+#
+trace=on
+
+#################################
+# version-string string reported on version.pdns or version.bind
+#
+# version-string=PowerDNS Recursor 3.3 $Id: pdns_recursor.cc 1712 2010-09-11 13:40:03Z ahu $
+
+
diff --git a/tests/deckard/template/unbound.j2 b/tests/deckard/template/unbound.j2
new file mode 100644
index 0000000..722374b
--- /dev/null
+++ b/tests/deckard/template/unbound.j2
@@ -0,0 +1,780 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page, version 1.5.10.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters.
+server:
+ # whitespace is not necessary, but looks cleaner.
+
+ # verbosity number, 0 is least verbose. 1 is default.
+ verbosity: 3
+
+ # print statistics to the log (for every thread) every N seconds.
+ # Set to "" or 0 to disable. Default is disabled.
+ # Needs to be disabled for munin plugin
+ statistics-interval: 0
+
+ # enable cumulative statistics, without clearing them after printing.
+ # Needs to be disabled for munin plugin
+ statistics-cumulative: no
+
+ # enable extended statistics (query types, answer codes, status)
+ # printed from unbound-control. default off, because of speed.
+ # Needs to be enabled for munin plugin
+ extended-statistics: yes
+
+ # number of threads to create. 1 disables threading.
+ num-threads: 1
+
+ # specify the interfaces to answer queries from by ip-address.
+ # The default is to listen to localhost (127.0.0.1 and ::1).
+ # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+ # specify every interface[@port] on a new 'interface:' labelled line.
+ # The listen interfaces are not changed on reload, only on restart.
+ interface: {{SELF_ADDR}}
+ # interface: ::0
+ # interface: 192.0.2.153
+ # interface: 192.0.2.154
+ # interface: 192.0.2.154@5003
+ # interface: 2001:DB8::5
+ #
+ # for dns over tls and raw dns over port 80
+ # interface: 0.0.0.0@443
+ # interface: ::0@443
+ # interface: 0.0.0.0@80
+ # interface: ::0@80
+
+ # enable this feature to copy the source address of queries to reply.
+ # Socket options are not supported on all platforms. experimental.
+ # interface-automatic: yes
+ #
+ # NOTE: Enable this option when specifying interface 0.0.0.0 or ::0
+ # NOTE: Disabled per Fedora policy not to listen to * on default install
+ # NOTE: If deploying on non-default port, eg 80/443, this needs to be disabled
+ interface-automatic: no
+
+ # port to answer queries from
+ # port: 53
+
+ # specify the interfaces to send outgoing queries to authoritative
+ # server from by ip-address. If none, the default (all) interface
+ # is used. Specify every interface on a 'outgoing-interface:' line.
+ # outgoing-interface: 192.0.2.153
+ # outgoing-interface: 2001:DB8::5
+ # outgoing-interface: 2001:DB8::6
+
+ # Specify a netblock to use remainder 64 bits as random bits for
+ # upstream queries. Uses freebind option (Linux).
+ # outgoing-interface: 2001:DB8::/64
+ # Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+ # And: ip -6 route add local 2001:db8::/64 dev lo
+ # And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+ # Set this to yes to prefer ipv6 upstream servers over ipv4.
+ # prefer-ip6: no
+
+ # number of ports to allocate per thread, determines the size of the
+ # port range that can be open simultaneously. About double the
+ # num-queries-per-thread, or, use as many as the OS will allow you.
+ # outgoing-range: 4096
+
+ # permit unbound to use this port number or port range for
+ # making outgoing queries, using an outgoing interface.
+ # Only ephemeral ports are allowed by SElinux
+ #outgoing-port-permit: 32768-60999
+
+ # deny unbound the use this of port number or port range for
+ # making outgoing queries, using an outgoing interface.
+ # Use this to make sure unbound does not grab a UDP port that some
+ # other server on this computer needs. The default is to avoid
+ # IANA-assigned port numbers.
+ # If multiple outgoing-port-permit and outgoing-port-avoid options
+ # are present, they are processed in order.
+ # Our SElinux policy does not allow non-ephemeral ports to be used
+ #outgoing-port-avoid: 0-32767
+
+ # number of outgoing simultaneous tcp buffers to hold per thread.
+ # outgoing-num-tcp: 10
+
+ # number of incoming simultaneous tcp buffers to hold per thread.
+ # incoming-num-tcp: 10
+
+ # buffer size for UDP port 53 incoming (SO_RCVBUF socket option).
+ # 0 is system default. Use 4m to catch query spikes for busy servers.
+ # so-rcvbuf: 0
+
+ # buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
+ # 0 is system default. Use 4m to handle spikes on very busy servers.
+ # so-sndbuf: 0
+
+ # use SO_REUSEPORT to distribute queries over threads.
+ # so-reuseport: no
+
+ # use IP_TRANSPARENT so the interface: addresses can be non-local
+ # and you can config non-existing IPs that are going to work later on
+ # (uses IP_BINDANY on FreeBSD).
+ #ip-transparent: yes
+
+ # use IP_FREEBIND so the interface: addresses can be non-local
+ # and you can bind to nonexisting IPs and interfaces that are down.
+ # Linux only. On Linux you also have ip-transparent that is similar.
+ # ip-freebind: no
+
+ # EDNS reassembly buffer to advertise to UDP peers (the actual buffer
+ # is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
+ # edns-buffer-size: 4096
+
+ # Maximum UDP response size (not applied to TCP response).
+ # Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
+ # 3072 causes +dnssec any isc.org queries to need TC=1. Helps mitigating DDOS
+ #max-udp-size: 3072
+
+ # buffer size for handling DNS data. No messages larger than this
+ # size can be sent or received, by UDP or TCP. In bytes.
+ # msg-buffer-size: 65552
+
+ # the amount of memory to use for the message cache.
+ # plain value in bytes or you can append k, m or G. default is "4Mb".
+ # msg-cache-size: 4m
+
+ # the number of slabs to use for the message cache.
+ # the number of slabs must be a power of 2.
+ # more slabs reduce lock contention, but fragment memory usage.
+ # msg-cache-slabs: 4
+
+ # the number of queries that a thread gets to service.
+ # num-queries-per-thread: 1024
+
+ # if very busy, 50% queries run to completion, 50% get timeout in msec
+ # jostle-timeout: 200
+
+ # msec to wait before close of port on timeout UDP. 0 disables.
+ # delay-close: 0
+
+ # the amount of memory to use for the RRset cache.
+ # plain value in bytes or you can append k, m or G. default is "4Mb".
+ # rrset-cache-size: 4m
+
+ # the number of slabs to use for the RRset cache.
+ # the number of slabs must be a power of 2.
+ # more slabs reduce lock contention, but fragment memory usage.
+ # rrset-cache-slabs: 4
+
+ # the time to live (TTL) value lower bound, in seconds. Default 0.
+ # If more than an hour could easily give trouble due to stale data.
+ # cache-min-ttl: 0
+
+ # the time to live (TTL) value cap for RRsets and messages in the
+ # cache. Items are not cached for longer. In seconds.
+ # cache-max-ttl: 86400
+
+ # the time to live (TTL) value cap for negative responses in the cache
+ # cache-max-negative-ttl: 3600
+
+ # the time to live (TTL) value for cached roundtrip times, lameness and
+ # EDNS version information for hosts. In seconds.
+ # infra-host-ttl: 900
+
+ # minimum wait time for responses, increase if uplink is long. In msec.
+ # infra-cache-min-rtt: 50
+
+ # the number of slabs to use for the Infrastructure cache.
+ # the number of slabs must be a power of 2.
+ # more slabs reduce lock contention, but fragment memory usage.
+ # infra-cache-slabs: 4
+
+ # the maximum number of hosts that are cached (roundtrip, EDNS, lame).
+ # infra-cache-numhosts: 10000
+
+ # define a number of tags here, use with local-zone, access-control.
+ # repeat the define-tag statement to add additional tags.
+ # define-tag: "tag1 tag2 tag3"
+
+ # Enable IPv4, "yes" or "no".
+ # do-ip4: yes
+
+ # Enable IPv6, "yes" or "no".
+ # do-ip6: yes
+
+ # Enable UDP, "yes" or "no".
+ # NOTE: if setting up an unbound on tls443 for public use, you might want to
+ # disable UDP to avoid being used in DNS amplification attacks.
+ # do-udp: yes
+
+ # Enable TCP, "yes" or "no".
+ # do-tcp: yes
+
+ # upstream connections use TCP only (and no UDP), "yes" or "no"
+ # useful for tunneling scenarios, default no.
+ # tcp-upstream: no
+
+ # Maximum segment size (MSS) of TCP socket on which the server
+ # responds to queries. Default is 0, system default MSS.
+ # tcp-mss: 0
+
+ # Maximum segment size (MSS) of TCP socket for outgoing queries.
+ # Default is 0, system default MSS.
+ # outgoing-tcp-mss: 0
+
+ # Detach from the terminal, run in background, "yes" or "no".
+ do-daemonize: no
+
+ # control which clients are allowed to make (recursive) queries
+ # to this server. Specify classless netblocks with /size and action.
+ # By default everything is refused, except for localhost.
+ # Choose deny (drop message), refuse (polite error reply),
+ # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+ # deny_non_local (drop queries unless can be answered from local-data)
+ # refuse_non_local (like deny_non_local but polite error reply).
+ # access-control: 0.0.0.0/0 refuse
+ # access-control: 127.0.0.0/8 allow
+ access-control: ::0/0 allow_snoop
+ # access-control: ::1 allow
+ # access-control: ::ffff:127.0.0.1 allow
+
+ # tag access-control with list of tags (in "" with spaces between)
+ # Clients using this access control element use localzones that
+ # are tagged with one of these tags.
+ # access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+ # set action for particular tag for given access control element
+ # if you have multiple tag values, the tag used to lookup the action
+ # is the first tag match between access-control-tag and local-zone-tag
+ # where "first" comes from the order of the define-tag values.
+ # access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+ # set redirect data for particular tag for access control element
+ # access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
+ # if given, a chroot(2) is done to the given directory.
+ # i.e. you can chroot to the working directory, for example,
+ # for extra security, but make sure all files are in that directory.
+ #
+ # If chroot is enabled, you should pass the configfile (from the
+ # commandline) as a full path from the original root. After the
+ # chroot has been performed the now defunct portion of the config
+ # file path is removed to be able to reread the config after a reload.
+ #
+ # All other file paths (working dir, logfile, roothints, and
+ # key files) can be specified in several ways:
+ # o as an absolute path relative to the new root.
+ # o as a relative path to the working directory.
+ # o as an absolute path relative to the original root.
+ # In the last case the path is adjusted to remove the unused portion.
+ #
+ # The pid file can be absolute and outside of the chroot, it is
+ # written just prior to performing the chroot and dropping permissions.
+ #
+ # Additionally, unbound may need to access /dev/random (for entropy).
+ # How to do this is specific to your OS.
+ #
+ # If you give "" no chroot is performed. The path must not end in a /.
+ # chroot: "/var/lib/unbound"
+ chroot: ""
+
+ # if given, user privileges are dropped (after binding port),
+ # and the given username is assumed. Default is user "unbound".
+ # If you give "" no privileges are dropped.
+ username: ""
+
+ # the working directory. The relative files in this config are
+ # relative to this directory. If you give "" the working directory
+ # is not changed.
+ # If you give a server: directory: dir before include: file statements
+ # then those includes can be relative to the working directory.
+ directory: ""
+
+ # the log file, "" means log to stderr.
+ # Use of this option sets use-syslog to "no".
+ # logfile: ""
+
+ # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
+ # log to, with identity "unbound". If yes, it overrides the logfile.
+ use-syslog: no
+
+ # print UTC timestamp in ascii to logfile, default is epoch in seconds.
+ log-time-ascii: yes
+
+ # print one line with time, IP, name, type, class for every query.
+ log-queries: yes
+
+ # the pid file. Can be an absolute path outside of chroot/work dir.
+ pidfile: "unbound.pid"
+
+ # file to read root hints from.
+ # get one from https://www.internic.net/domain/named.cache
+ root-hints: "hints.zone"
+
+ # enable to not answer id.server and hostname.bind queries.
+ # hide-identity: no
+
+ # enable to not answer version.server and version.bind queries.
+ # hide-version: no
+
+ # the identity to report. Leave "" or default to return hostname.
+ # identity: ""
+
+ # the version to report. Leave "" or default to return package version.
+ # version: ""
+
+ # the target fetch policy.
+ # series of integers describing the policy per dependency depth.
+ # The number of values in the list determines the maximum dependency
+ # depth the recursor will pursue before giving up. Each integer means:
+ # -1 : fetch all targets opportunistically,
+ # 0: fetch on demand,
+ # positive value: fetch that many targets opportunistically.
+ # Enclose the list of numbers between quotes ("").
+ target-fetch-policy: "0 0 0 0 0"
+
+ # Harden against very small EDNS buffer sizes.
+ # harden-short-bufsize: no
+
+ # Harden against unseemly large queries.
+ # harden-large-queries: no
+
+ # Harden against out of zone rrsets, to avoid spoofing attempts.
+
+ {% if HARDEN_GLUE == "true" %}
+ harden-glue: yes
+ {% else %}
+ harden-glue: no
+ {% endif %}
+
+ # Harden against receiving dnssec-stripped data. If you turn it
+ # off, failing to validate dnskey data for a trustanchor will
+ # trigger insecure mode for that zone (like without a trustanchor).
+ # Default on, which insists on dnssec data for trust-anchored zones.
+ harden-dnssec-stripped: yes
+
+ # Harden against queries that fall under dnssec-signed nxdomain names.
+ harden-below-nxdomain: yes
+
+ # Harden the referral path by performing additional queries for
+ # infrastructure data. Validates the replies (if possible).
+ # Default off, because the lookups burden the server. Experimental
+ # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+ harden-referral-path: yes
+
+ # Harden against algorithm downgrade when multiple algorithms are
+ # advertised in the DS record. If no, allows the weakest algorithm
+ # to validate the zone.
+ harden-algo-downgrade: yes
+
+ # Sent minimum amount of information to upstream servers to enhance
+ # privacy. Only sent minimum required labels of the QNAME and set QTYPE
+ # to NS when possible.
+ {% if QMIN == "false" %}
+ qname-minimisation: no
+ {% else %}
+ qname-minimisation: yes
+ {% endif %}
+
+ # Use 0x20-encoded random bits in the query to foil spoof attempts.
+ # This feature is an experimental implementation of draft dns-0x20.
+ use-caps-for-id: yes
+
+ # Domains (and domains in them) without support for dns-0x20 and
+ # the fallback fails because they keep sending different answers.
+ # caps-whitelist: "licdn.com"
+ # caps-whitelist: "senderbase.org"
+
+ # Enforce privacy of these addresses. Strips them away from answers.
+ # It may cause DNSSEC validation to additionally mark it as bogus.
+ # Protects against 'DNS Rebinding' (uses browser as network proxy).
+ # Only 'private-domain' and 'local-data' names are allowed to have
+ # these private addresses. No default.
+ # private-address: 10.0.0.0/8
+ # private-address: 172.16.0.0/12
+ # private-address: 192.168.0.0/16
+ # private-address: 169.254.0.0/16
+ # private-address: fd00::/8
+ # private-address: fe80::/10
+ # private-address: ::ffff:0:0/96
+
+ # Allow the domain (and its subdomains) to contain private addresses.
+ # local-data statements are allowed to contain private addresses too.
+ # private-domain: "example.com"
+
+ # If nonzero, unwanted replies are not only reported in statistics,
+ # but also a running total is kept per thread. If it reaches the
+ # threshold, a warning is printed and a defensive action is taken,
+ # the cache is cleared to flush potential poison out of it.
+ # A suggested value is 10000000, the default is 0 (turned off).
+ unwanted-reply-threshold: 10000000
+
+ # Do not query the following addresses. No DNS queries are sent there.
+ # List one address per entry. List classless netblocks with /size,
+ # do-not-query-address: 127.0.0.1/8
+ # do-not-query-address: ::1
+
+ # if yes, the above default do-not-query-address entries are present.
+ # if no, localhost can be queried (for testing and debugging).
+ {% if DO_NOT_QUERY_LOCALHOST == "false" %}
+ do-not-query-localhost: no
+ {% else %}
+ do-not-query-localhost: yes
+ {% endif %}
+
+ # if yes, perform prefetching of almost expired message cache entries.
+ prefetch: no
+
+ # if yes, perform key lookups adjacent to normal lookups.
+ prefetch-key: no
+
+ # if yes, Unbound rotates RRSet order in response.
+ rrset-roundrobin: yes
+
+ # if yes, Unbound doesn't insert authority/additional sections
+ # into response messages when those sections are not required.
+ minimal-responses: no
+
+ # true to disable DNSSEC lameness check in iterator.
+ # disable-dnssec-lame-check: no
+
+ # module configuration of the server. A string with identifiers
+ # separated by spaces. Syntax: "[dns64] [validator] iterator"
+ # module-config: "validator iterator"
+
+ # File with trusted keys, kept uptodate using RFC5011 probes,
+ # initial file like trust-anchor-file, then it stores metadata.
+ # Use several entries, one per domain name, to track multiple zones.
+ #
+ # If you want to perform DNSSEC validation, run unbound-anchor before
+ # you start unbound (i.e. in the system boot scripts). And enable:
+ # Please note usage of unbound-anchor root anchor is at your own risk
+ # and under the terms of our LICENSE (see that file in the source).
+ # auto-trust-anchor-file: "/var/lib/unbound/root.key"
+
+ {% for TAF in TRUST_ANCHOR_FILES %}
+ auto-trust-anchor-file: "{{TAF}}"
+ {% endfor %}
+
+ # File with DLV trusted keys. Same format as trust-anchor-file.
+ # There can be only one DLV configured, it is trusted from root down.
+ # DLV is going to be decommissioned. Please do not use it any more.
+ # dlv-anchor-file: "dlv.isc.org.key"
+
+ # File with trusted keys for validation. Specify more than one file
+ # with several entries, one file per entry.
+ # Zone file format, with DS and DNSKEY entries.
+ # Note this gets out of date, use auto-trust-anchor-file please.
+
+ # Trusted key for validation. DS or DNSKEY. specify the RR on a
+ # single line, surrounded by "". TTL is ignored. class is IN default.
+ # Note this gets out of date, use auto-trust-anchor-file please.
+ # (These examples are from August 2007 and may not be valid anymore).
+ # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+ # File with trusted keys for validation. Specify more than one file
+ # with several entries, one file per entry. Like trust-anchor-file
+ # but has a different file format. Format is BIND-9 style format,
+ # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+ # you need external update procedures to track changes in keys.
+ # trusted-keys-file: ""
+ #
+ #trusted-keys-file: /etc/unbound/keys.d/*.key
+ #auto-trust-anchor-file: "/var/lib/unbound/root.key"
+
+ # Ignore chain of trust. Domain is treated as insecure.
+ # domain-insecure: "example.com"
+ {% for DI in NEGATIVE_TRUST_ANCHORS %}
+ domain-insecure: "{{DI}}"
+ {% endfor %}
+
+
+ # Override the date for validation with a specific fixed date.
+ # Do not set this unless you are debugging signature inception
+ # and expiration. "" or "0" turns the feature off. -1 ignores date.
+ # val-override-date: ""
+
+ # The time to live for bogus data, rrsets and messages. This avoids
+ # some of the revalidation, until the time interval expires. in secs.
+ # val-bogus-ttl: 60
+
+ # The signature inception and expiration dates are allowed to be off
+ # by 10% of the signature lifetime (expir-incep) from our local clock.
+ # This leeway is capped with a minimum and a maximum. In seconds.
+ # val-sig-skew-min: 3600
+ # val-sig-skew-max: 86400
+
+ # Should additional section of secure message also be kept clean of
+ # unsecure data. Useful to shield the users of this validator from
+ # potential bogus data in the additional section. All unsigned data
+ # in the additional section is removed from secure messages.
+ val-clean-additional: yes
+
+ # Turn permissive mode on to permit bogus messages. Thus, messages
+ # for which security checks failed will be returned to clients,
+ # instead of SERVFAIL. It still performs the security checks, which
+ # result in interesting log files and possibly the AD bit in
+ # replies if the message is found secure. The default is off.
+ # NOTE: TURNING THIS ON DISABLES ALL DNSSEC SECURITY
+ val-permissive-mode: no
+
+ # Ignore the CD flag in incoming queries and refuse them bogus data.
+ # Enable it if the only clients of unbound are legacy servers (w2008)
+ # that set CD but cannot validate themselves.
+ # ignore-cd-flag: no
+
+ # Have the validator log failed validations for your diagnosis.
+ # 0: off. 1: A line per failed user query. 2: With reason and bad IP.
+ val-log-level: 2
+
+ # It is possible to configure NSEC3 maximum iteration counts per
+ # keysize. Keep this table very short, as linear search is done.
+ # A message with an NSEC3 with larger count is marked insecure.
+ # List in ascending order the keysize and count values.
+ # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+ # instruct the auto-trust-anchor-file probing to add anchors after ttl.
+ # add-holddown: 2592000 # 30 days
+
+ # instruct the auto-trust-anchor-file probing to del anchors after ttl.
+ # del-holddown: 2592000 # 30 days
+
+ # auto-trust-anchor-file probing removes missing anchors after ttl.
+ # If the value 0 is given, missing anchors are not removed.
+ # keep-missing: 31622400 # 366 days
+
+ # debug option that allows very small holddown times for key rollover,
+ # otherwise the RFC mandates probe intervals must be at least 1 hour.
+ # permit-small-holddown: no
+
+ # the amount of memory to use for the key cache.
+ # plain value in bytes or you can append k, m or G. default is "4Mb".
+ # key-cache-size: 4m
+
+ # the number of slabs to use for the key cache.
+ # the number of slabs must be a power of 2.
+ # more slabs reduce lock contention, but fragment memory usage.
+ # key-cache-slabs: 4
+
+ # the amount of memory to use for the negative cache (used for DLV).
+ # plain value in bytes or you can append k, m or G. default is "1Mb".
+ # neg-cache-size: 1m
+
+ # By default, for a number of zones a small default 'nothing here'
+ # reply is built-in. Query traffic is thus blocked. If you
+ # wish to serve such zone you can unblock them by uncommenting one
+ # of the nodefault statements below.
+ # You may also have to use domain-insecure: zone to make DNSSEC work,
+ # unless you have your own trust anchors for this zone.
+ local-zone: "test." nodefault
+ local-zone: "localhost." nodefault
+ local-zone: "127.in-addr.arpa." nodefault
+ local-zone: "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." nodefault
+ local-zone: "onion." nodefault
+ local-zone: "10.in-addr.arpa." nodefault
+ local-zone: "16.172.in-addr.arpa." nodefault
+ local-zone: "17.172.in-addr.arpa." nodefault
+ local-zone: "18.172.in-addr.arpa." nodefault
+ local-zone: "19.172.in-addr.arpa." nodefault
+ local-zone: "20.172.in-addr.arpa." nodefault
+ local-zone: "21.172.in-addr.arpa." nodefault
+ local-zone: "22.172.in-addr.arpa." nodefault
+ local-zone: "23.172.in-addr.arpa." nodefault
+ local-zone: "24.172.in-addr.arpa." nodefault
+ local-zone: "25.172.in-addr.arpa." nodefault
+ local-zone: "26.172.in-addr.arpa." nodefault
+ local-zone: "27.172.in-addr.arpa." nodefault
+ local-zone: "28.172.in-addr.arpa." nodefault
+ local-zone: "29.172.in-addr.arpa." nodefault
+ local-zone: "30.172.in-addr.arpa." nodefault
+ local-zone: "31.172.in-addr.arpa." nodefault
+ local-zone: "168.192.in-addr.arpa." nodefault
+ local-zone: "0.in-addr.arpa." nodefault
+ local-zone: "254.169.in-addr.arpa." nodefault
+ local-zone: "2.0.192.in-addr.arpa." nodefault
+ local-zone: "100.51.198.in-addr.arpa." nodefault
+ local-zone: "113.0.203.in-addr.arpa." nodefault
+ local-zone: "255.255.255.255.in-addr.arpa." nodefault
+ local-zone: "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." nodefault
+ local-zone: "d.f.ip6.arpa." nodefault
+ local-zone: "8.e.f.ip6.arpa." nodefault
+ local-zone: "9.e.f.ip6.arpa." nodefault
+ local-zone: "a.e.f.ip6.arpa." nodefault
+ local-zone: "b.e.f.ip6.arpa." nodefault
+ local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
+ # And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
+
+ # If unbound is running service for the local host then it is useful
+ # to perform lan-wide lookups to the upstream, and unblock the
+ # long list of local-zones above. If this unbound is a dns server
+ # for a network of computers, disabled is better and stops information
+ # leakage of local lan information.
+ unblock-lan-zones: yes
+
+ # The insecure-lan-zones option disables validation for
+ # these zones, as if they were all listed as domain-insecure.
+ # insecure-lan-zones: no
+
+ # a number of locally served zones can be configured.
+ # local-zone: <zone> <type>
+ # local-data: "<resource record string>"
+ # o deny serves local data (if any), else, drops queries.
+ # o refuse serves local data (if any), else, replies with error.
+ # o static serves local data, else, nxdomain or nodata answer.
+ # o transparent gives local data, but resolves normally for other names
+ # o redirect serves the zone data for any subdomain in the zone.
+ # o nodefault can be used to normally resolve AS112 zones.
+ # o typetransparent resolves normally for other types and other names
+ # o inform resolves normally, but logs client IP address
+ # o inform_deny drops queries and logs client IP address
+ # o always_transparent, always_refuse, always_nxdomain, resolve in
+ # that way but ignore local data for that name.
+ #
+ # defaults are localhost address, reverse for 127.0.0.1 and ::1
+ # and nxdomain for AS112 zones. If you configure one of these zones
+ # the default content is omitted, or you can omit it with 'nodefault'.
+ #
+ # If you configure local-data without specifying local-zone, by
+ # default a transparent local-zone is created for the data.
+ #
+ # You can add locally served data with
+ # local-zone: "local." static
+ # local-data: "mycomputer.local. IN A 192.0.2.51"
+ # local-data: 'mytext.local TXT "content of text record"'
+ #
+ # You can override certain queries with
+ # local-data: "adserver.example.com A 127.0.0.1"
+ #
+ # You can redirect a domain to a fixed address with
+ # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+ # local-zone: "example.com" redirect
+ # local-data: "example.com A 192.0.2.3"
+ #
+ # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+ # You can also add PTR records using local-data directly, but then
+ # you need to do the reverse notation yourself.
+ # local-data-ptr: "192.0.2.3 www.example.com"
+
+ #include: /etc/unbound/local.d/*.conf
+
+ # tag a localzone with a list of tag names (in "" with spaces between)
+ # local-zone-tag: "example.com" "tag2 tag3"
+
+ # add a netblock specific override to a localzone, with zone type
+ # local-zone-override: "example.com" 192.0.2.0/24 refuse
+
+ # service clients over SSL (on the TCP sockets), with plain DNS inside
+ # the SSL stream. Give the certificate to use and private key.
+ # default is "" (disabled). requires restart to take effect.
+ # ssl-service-key: "/etc/unbound/unbound_server.key"
+ # ssl-service-pem: "/etc/unbound/unbound_server.pem"
+ # ssl-port: 443
+ #
+ # request upstream over SSL (with plain DNS inside the SSL stream).
+ # Default is no. Can be turned on and off with unbound-control.
+ # ssl-upstream: no
+
+ # DNS64 prefix. Must be specified when DNS64 is use.
+ # Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
+ # dns64-prefix: 64:ff9b::0/96
+
+ # ratelimit for uncached, new queries, this limits recursion effort.
+ # ratelimiting is experimental, and may help against randomqueryflood.
+ # if 0(default) it is disabled, otherwise state qps allowed per zone.
+ # ratelimit: 0
+
+ # ratelimits are tracked in a cache, size in bytes of cache (or k,m).
+ # ratelimit-size: 4m
+ # ratelimit cache slabs, reduces lock contention if equal to cpucount.
+ # ratelimit-slabs: 4
+
+ # 0 blocks when ratelimited, otherwise let 1/xth traffic through
+ # ratelimit-factor: 10
+
+ # override the ratelimit for a specific domain name.
+ # give this setting multiple times to have multiple overrides.
+ # ratelimit-for-domain: example.com 1000
+ # override the ratelimits for all domains below a domain name
+ # can give this multiple times, the name closest to the zone is used.
+ # ratelimit-below-domain: com 1000
+
+# Python config section. To enable:
+# o use --with-pythonmodule to configure before compiling.
+# o list python in the module-config string (above) to enable.
+# o and give a python-script to run.
+python:
+ # Script file to load
+ # python-script: "/etc/unbound/ubmodule-tst.py"
+
+# Remote control config section.
+remote-control:
+ # Enable remote control with unbound-control(8) here.
+ # set up the keys and certificates with unbound-control-setup.
+ # Note: required for unbound-munin package
+ control-enable: no
+
+ # Set to no and use an absolute path as control-interface to use
+ # a unix local named pipe for unbound-control.
+ # control-use-cert: yes
+
+ # what interfaces are listened to for remote control.
+ # give 0.0.0.0 and ::0 to listen to all interfaces.
+ # control-interface: 127.0.0.1
+ # control-interface: ::1
+
+ # port number for remote control operations.
+ # control-port: 8953
+
+ # unbound server key file.
+ #server-key-file: "/etc/unbound/unbound_server.key"
+
+ # unbound server certificate file.
+ #server-cert-file: "/etc/unbound/unbound_server.pem"
+
+ # unbound-control key file.
+ #control-key-file: "/etc/unbound/unbound_control.key"
+
+ # unbound-control certificate file.
+ #control-cert-file: "/etc/unbound/unbound_control.pem"
+
+# Stub and Forward zones
+#include: /etc/unbound/conf.d/*.conf
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of nameservers. list zero or more
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
+# the list is treated as priming hints (default is no).
+# With stub-first yes, it attempts without the stub if it fails.
+# Consider adding domain-insecure: name and local-zone: name nodefault
+# to the server: section if the stub is a locally served zone.
+# stub-zone:
+# name: "example.com"
+# stub-addr: 192.0.2.68
+# stub-prime: no
+# stub-first: no
+# stub-zone:
+# name: "example.org"
+# stub-host: ns.example.com.
+
+# You can now also dynamically create and delete stub-zone's using
+# unbound-control stub_add domain.com 1.2.3.4 5.6.7.8
+# unbound-control stub_remove domain.com 1.2.3.4 5.6.7.8
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# If you enable forward-first, it attempts without the forward if it fails.
+# forward-zone:
+# name: "example.com"
+# forward-addr: 192.0.2.68
+# forward-addr: 192.0.2.73@5355 # forward to port 5355.
+# forward-first: no
+# forward-zone:
+# name: "example.org"
+# forward-host: fwd.example.com
+#
+# You can now also dynamically create and delete forward-zone's using
+# unbound-control forward_add domain.com 1.2.3.4 5.6.7.8
+# unbound-control forward_remove domain.com 1.2.3.4 5.6.7.8
diff --git a/tests/deckard/template/unbound_dnssec.j2 b/tests/deckard/template/unbound_dnssec.j2
new file mode 100644
index 0000000..282dc9f
--- /dev/null
+++ b/tests/deckard/template/unbound_dnssec.j2
@@ -0,0 +1,3 @@
+{% for TA in TRUST_ANCHORS %}
+{{TA}}
+{% endfor %}
diff --git a/tests/deckard/tests/__init__.py b/tests/deckard/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/deckard/tests/__init__.py
diff --git a/tests/deckard/tests/test_deckard.py b/tests/deckard/tests/test_deckard.py
new file mode 100644
index 0000000..50096ea
--- /dev/null
+++ b/tests/deckard/tests/test_deckard.py
@@ -0,0 +1,30 @@
+""" This is unittest file for parse methods in scenario.py """
+import os
+import shutil
+import tempfile
+
+from deckard import create_trust_anchor_files
+
+
+def test_create_trust_anchor_files():
+ """Trust anchors must be into separate files grouped by domain."""
+ anchor1a = u'domain1.com.\t3600\tIN\tDS\t11901 7 1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ anchor1b = u'domain1.com.\t3600\tIN\tDS\t11902 7 1 1111111111111111111111111111111111111111'
+ anchor2a = u'domain2.net.\t3600\tIN\tDS\t59835 7 1 cccccccccccccccccccccccccccccccccccccccc'
+ trust_anchors = {'domain1.com': [anchor1a, anchor1b],
+ 'domain2.net': [anchor2a]}
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ file_names = create_trust_anchor_files(trust_anchors, tmpdir)
+ assert sorted(file_names) == sorted('{wd}/ta/{f}'.format(wd=tmpdir, f=f)
+ for f in [u'domain1.com.key', u'domain2.net.key'])
+ for path in file_names:
+ with open(path) as ta_file:
+ file_name = os.path.basename(path)
+ assert file_name[-4:] == '.key'
+ domain = file_name[:-4]
+ assert ta_file.read() == ''.join(u'{}\n'.format(ta)
+ for ta in trust_anchors[domain])
+ finally:
+ shutil.rmtree(tmpdir)
diff --git a/tests/deckard/tools/divide_tests.sh b/tests/deckard/tools/divide_tests.sh
new file mode 100644
index 0000000..1856610
--- /dev/null
+++ b/tests/deckard/tools/divide_tests.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+# Sorts .rpl tests into several categories.
+# Takes a diretory with the tests as an argument and moves the test to its subdirectories.
+# Env variable SCRIPT= sets *_run.sh script for finding working tests, default script is kresd_run.sh
+# Env variable DEST= sets output directory where the tests will be copied and divided into subfolders. Default value is working directory.
+
+set -o nounset
+set -o errexit
+
+SOURCE="$1"
+
+SCRIPT=${SCRIPT:-"./../kresd_run.sh"}
+DEST=${DEST:-"."}
+
+rm -rf "$DEST/sorted_tests"
+mkdir "$DEST/sorted_tests"
+for TEST in "$SOURCE/"*.rpl
+do
+ cp "$TEST" "$DEST/sorted_tests"
+done
+
+# Test with the same name is already imported in deckard/sets/resolver
+echo Already imported:
+mkdir -p "$DEST/sorted_tests/imported"
+for TEST in `comm -12 <(ls -F ../sets/resolver/*.rpl | xargs -n 1 basename) <(ls -F "$DEST/sorted_tests" | xargs -n 1 basename)`
+do
+ echo -e '\t' "$TEST"
+ mv "$DEST/sorted_tests/$TEST" "$DEST/sorted_tests/imported"
+done
+
+# Parse failed
+echo Parse failed:
+mkdir -p "$DEST/sorted_tests/parsefail"
+for TEST in "$DEST/sorted_tests/"*.rpl
+do
+ if ! python3 parse.py "$TEST" >/dev/null 2>/dev/null
+ then
+ echo -e '\t' $(basename "$TEST")
+ mv "$TEST" "$DEST/sorted_tests/parsefail"
+ fi
+done
+
+
+# Invalid DSA signatures (common in old testbound tests)
+echo Invalid DSA signatures:
+mkdir -p "$DEST/sorted_tests/invaliddsa"
+for TEST in "$DEST/sorted_tests/"*.rpl
+do
+ if ! python3 invalid_dsa.py "$TEST" >/dev/null 2>/dev/null
+ then
+ echo -e '\t' $(basename "$TEST")
+ mv "$TEST" "$DEST/sorted_tests/invaliddsa"
+ fi
+done
+
+
+# Working in selected script
+echo Working in $SCRIPT:
+mkdir -p "$DEST/sorted_tests/working"
+for TEST in "$DEST/sorted_tests/"*.rpl
+do
+ if TESTS="$(readlink -m $TEST)" $SCRIPT >/dev/null 2>/dev/null
+ then
+ echo -e '\t' $(basename "$TEST")
+ mv "$TEST" "$DEST/sorted_tests/working"
+ fi
+done
+
+echo Others:
+mkdir -p "$DEST/sorted_tests/others"
+for TEST in "$DEST/sorted_tests/"*.rpl
+do
+ echo -e '\t' $(basename "$TEST")
+ mv "$TEST" "$DEST/sorted_tests/others"
+done
+
diff --git a/tests/deckard/tools/invalid_dsa.py b/tests/deckard/tools/invalid_dsa.py
new file mode 100644
index 0000000..fd1c845
--- /dev/null
+++ b/tests/deckard/tools/invalid_dsa.py
@@ -0,0 +1,83 @@
+"""Returns 1 if there is a DNSSEC DSA signature which is not 41 bytes long.\
+0 otherwise.
+"""
+
+import os
+import sys
+import argparse
+import dns
+import pydnstest
+import pydnstest.scenario
+import pydnstest.augwrap
+
+
+def parse(test):
+ """ Parse the test"""
+ _, config = pydnstest.scenario.parse_file(os.path.realpath(test))
+ aug = pydnstest.augwrap.AugeasWrapper(
+ confpath=os.path.realpath(test),
+ lens='Deckard', loadpath="../pydnstest")
+ node = aug.tree
+ return config, node
+
+
+def get_dsakeys(config, node):
+ """ Make list of all DSA keys in the test"""
+ dsakeys = []
+ for conf in config:
+ if conf[0] == "trust-anchor":
+ conf[1] = conf[1][1:-1]
+ trust_anchor = conf[1].split()
+ for i, word in enumerate(trust_anchor):
+ if word == "DS":
+ algorithm = trust_anchor[i + 2]
+ if algorithm in ("3", "DSA"):
+ dsakeys.append(trust_anchor[i + 1])
+
+ for entry in node.match("/scenario/range/entry"):
+ records = list(entry.match("/section/answer/record"))
+ records.extend(list(entry.match("/section/authority/record")))
+ records.extend(list(entry.match("/section/additional/record")))
+
+ for record in records:
+ if record["/type"].value == "DS":
+ if record["/data"].value[1] in ["3", "DSA"]:
+ dsakeys.append(record["/data"].value[2])
+ return dsakeys
+
+
+def check_rrsig(node, dsakeys):
+ """ Find records with wrong lenght of rrsig"""
+ for key in dsakeys: # pylint: disable=too-many-nested-blocks
+ for entry in node.match("/scenario/range/entry"):
+ records = list(entry.match("/section/answer/record"))
+ records.extend(list(entry.match("/section/authority/record")))
+ records.extend(list(entry.match("/section/additional/record")))
+
+ for record in records:
+ if record["/type"].value == "RRSIG":
+ rrset = dns.rrset.from_text(record["/domain"].value, 300,
+ 1, dns.rdatatype.RRSIG,
+ record["/data"].value)
+ if rrset.items[0].key_tag == int(key):
+ if len(rrset.items[0].signature) != 41:
+ return True
+ return False
+
+
+def main():
+ """Returns 1 if there is a DNSSEC DSA signature which is not 41 bytes long. \
+ 0 otherwise."""
+ argparser = argparse.ArgumentParser()
+ argparser.add_argument("file")
+ args = argparser.parse_args()
+ config, node = parse(args.file)
+ dsakeys = get_dsakeys(config, node)
+ bad_rrsig = check_rrsig(node, dsakeys)
+ if bad_rrsig:
+ sys.exit(1)
+ else:
+ sys.exit(0)
+
+
+main()
diff --git a/tests/deckard/tools/parse.py b/tests/deckard/tools/parse.py
new file mode 100644
index 0000000..139b284
--- /dev/null
+++ b/tests/deckard/tools/parse.py
@@ -0,0 +1,21 @@
+"""Returns 0 if the test is parsed, 1 if not."""
+
+import sys
+import os
+import argparse
+import pydnstest
+import pydnstest.scenario
+
+
+def main():
+ """Returns 0 if the test is parsed, 1 if not."""
+ argparser = argparse.ArgumentParser()
+ argparser.add_argument("file")
+ args = argparser.parse_args()
+ if pydnstest.scenario.parse_file(os.path.realpath(args.file)):
+ sys.exit(0)
+ else:
+ sys.exit(1)
+
+
+main()
diff --git a/tests/deckard/unbound_run.sh b/tests/deckard/unbound_run.sh
new file mode 100755
index 0000000..a5189e0
--- /dev/null
+++ b/tests/deckard/unbound_run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -o errexit -o nounset
+
+RUNDIR="$(dirname "$0")"
+cd "$RUNDIR" && ./run.sh --config configs/unbound.yaml "$@"
diff --git a/tests/dnstap/src/dnstap-test/config b/tests/dnstap/src/dnstap-test/config
new file mode 100644
index 0000000..50fca58
--- /dev/null
+++ b/tests/dnstap/src/dnstap-test/config
@@ -0,0 +1,11 @@
+verbose(true)
+modules = {
+ 'hints',
+ dnstap = {
+ socket_path = "/tmp/dnstap.sock",
+ log_responses = true,
+ }
+}
+hints['fake1.localdomain'] = '1.2.3.4'
+hints['fake2.localdomain'] = '1.2.3.5'
+hints['fake3.localdomain'] = '1.2.3.6'
diff --git a/tests/dnstap/src/dnstap-test/dnstap.mk b/tests/dnstap/src/dnstap-test/dnstap.mk
new file mode 100644
index 0000000..ab462a9
--- /dev/null
+++ b/tests/dnstap/src/dnstap-test/dnstap.mk
@@ -0,0 +1,19 @@
+# dnstap tests
+GOPATH := $(abspath tests/dnstap)
+DNSTAP_TEST := dnstap-test
+DNSTAP_PATH := $(GOPATH)/src/$(DNSTAP_TEST)
+CONFIG := $(DNSTAP_PATH)/config
+CMD := daemon/kresd
+ZONES := "fake1.localdomain,fake2.localdomain,fake3.localdomain"
+TIMEOUT := 60s
+check-dnstap: daemon
+ @echo "Checking dnstap functionality"
+ GOPATH=$(GOPATH) go get -u github.com/FiloSottile/gvt
+ cd $(DNSTAP_PATH) && $(GOPATH)/bin/gvt restore
+ GOPATH=$(GOPATH) go install $(DNSTAP_TEST)
+ $(GOPATH)/bin/$(DNSTAP_TEST) -c $(CONFIG) -cmd $(CMD) -q $(ZONES) -t $(TIMEOUT)
+
+clean-dnstap:
+ rm -rf $(GOPATH)/{bin,pkg,src/dnstap-test/vendor/github.com,src/github.com}
+
+.PHONY: check-dnstap clean-dnstap
diff --git a/tests/dnstap/src/dnstap-test/main.go b/tests/dnstap/src/dnstap-test/main.go
new file mode 100644
index 0000000..6ef3e1e
--- /dev/null
+++ b/tests/dnstap/src/dnstap-test/main.go
@@ -0,0 +1,245 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "github.com/cloudflare/dns"
+ dnstap "github.com/dnstap/golang-dnstap"
+ "github.com/golang/protobuf/proto"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "strings"
+ "time"
+)
+
+const (
+ kresdWorkDir = "/tmp/"
+)
+
+var (
+ kresdArgs = []string{
+ "-f1",
+ "-v",
+ "-q",
+ }
+)
+
+func qnameFromFrame(b []byte) (string, error) {
+ dt := &dnstap.Dnstap{}
+ var name string
+ if err := proto.Unmarshal(b, dt); err != nil {
+ return name, err
+ }
+ m := dt.Message
+ if *m.Type != dnstap.Message_RESOLVER_RESPONSE {
+ return name, fmt.Errorf("incorrect message type")
+ }
+ if m.ResponseMessage == nil {
+ return name, fmt.Errorf("no message payload")
+ }
+ if err := dns.IsMsg(m.ResponseMessage); err != nil {
+ return name, err
+ }
+ var msg dns.Msg
+ if err := msg.Unpack(m.ResponseMessage); err != nil {
+ return name, err
+ }
+ if len(msg.Question) < 1 {
+ return name, fmt.Errorf("question empty")
+ }
+ return msg.Question[0].Name, nil
+}
+
+func listenOn() (net.Addr, *os.File, error) {
+ udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
+ IP: net.ParseIP("127.0.0.1"),
+ Port: 0,
+ })
+ if err != nil {
+ return nil, nil, err
+ }
+
+ file, err := udpConn.File()
+ if err != nil {
+ return nil, nil, err
+ }
+ return udpConn.LocalAddr(), file, nil
+}
+
+func runKresd(ctx context.Context, path, configFile string, grace time.Duration) (chan bool, error) {
+ ch := make(chan bool)
+ kresdArgs = append(kresdArgs, "-c"+configFile)
+ kresdArgs = append(kresdArgs, kresdWorkDir)
+ // we have 1 object in ExtraFiles with index 0
+ // child fd will be 3 + i = 3
+ kresdArgs = append(kresdArgs, "-S3")
+
+ file := ctx.Value("file").(*os.File)
+ debug := ctx.Value("debug").(bool)
+
+ cmd := exec.CommandContext(ctx, path, kresdArgs...)
+ cmd.ExtraFiles = []*os.File{file}
+
+ var stdout, stderr io.ReadCloser
+ var err error
+ if debug {
+ stdout, err = cmd.StdoutPipe()
+ if err != nil {
+ log.Printf("stdoutpipe: %v\n", err)
+ return ch, err
+ }
+
+ stderr, err = cmd.StderrPipe()
+ if err != nil {
+ log.Printf("stderrpipe: %v\n", err)
+ return ch, err
+ }
+ }
+
+ go func() {
+ status := false
+ defer func() {
+ ch <- status // kresd done
+ }()
+ if err := cmd.Start(); err != nil {
+ log.Printf("start: %v\n", err)
+ return
+ }
+ time.Sleep(grace)
+ ch <- true // Started kresd
+
+ if debug {
+ s, err := ioutil.ReadAll(stdout)
+ if err != nil {
+ log.Printf("readall: %v\n", err)
+ return
+ }
+ if len(s) > 0 {
+ fmt.Printf("stdout:\n%s\n", s)
+ }
+
+ s, err = ioutil.ReadAll(stderr)
+ if err != nil {
+ log.Printf("readall: %v\n", err)
+ return
+ }
+ if len(s) > 0 {
+ fmt.Printf("stderr:\n%s\n", s)
+ }
+ }
+
+ if err := cmd.Wait(); err != nil && err.Error() != "signal: killed" {
+ log.Printf("wait: %v\n", err)
+ return
+ }
+ status = true
+ }()
+ return ch, nil
+}
+
+func main() {
+ var (
+ unixSocket = flag.String("u", "/tmp/dnstap.sock", "dnstap socket")
+ kresdPath = flag.String("cmd", "daemon/kresd", "kresd path")
+ configFile = flag.String("c", "config", "config file")
+ qnames = flag.String("q", ".", "list of comma separated zones")
+ grace = flag.String("g", "1s", "Time to wait for daemon start")
+ timeout = flag.String("t", "60s", "Test Timeout")
+ debug = flag.Bool("d", false, "Debug")
+ )
+
+ flag.Parse()
+
+ kresdStartGracePeriod, err := time.ParseDuration(*grace)
+ if err != nil {
+ panic(err)
+ }
+
+ testTimeout, err := time.ParseDuration(*timeout)
+ if err != nil {
+ panic(err)
+ }
+
+ input, err := dnstap.NewFrameStreamSockInputFromPath(*unixSocket)
+ if err != nil {
+ panic(err)
+ }
+
+ output := make(chan []byte)
+ go input.ReadInto(output)
+
+ ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
+
+ // Create a UDP listening socket on random port
+ // FD will be passed on to kresd
+ addr, file, err := listenOn()
+ if err != nil {
+ panic(err)
+ }
+ if *debug {
+ log.Printf("listen addr:%v", addr)
+ }
+ ctx = context.WithValue(ctx, "file", file)
+ ctx = context.WithValue(ctx, "debug", *debug)
+
+ ch, err := runKresd(ctx, *kresdPath, *configFile, kresdStartGracePeriod)
+ if err != nil {
+ panic(err)
+ }
+
+ log.Printf("Waiting for kresd to start\n")
+ status := <-ch
+ if !status {
+ os.Exit(1) // error starting
+ }
+
+ go func() {
+ parts := strings.Split(*qnames, ",")
+
+ if len(parts) == 0 {
+ log.Printf("qname count is 0")
+ }
+ for _, name := range parts {
+ m := new(dns.Msg)
+ fqdn := dns.Fqdn(name)
+ m.SetQuestion(fqdn, dns.TypeA)
+ c := new(dns.Client)
+ resp, _, err := c.Exchange(m, fmt.Sprintf("%v", addr))
+ if err != nil {
+ log.Printf("%v\n", err)
+ os.Exit(1) // Test Failed
+ }
+ if *debug {
+ log.Printf("Response: %v", resp)
+ }
+
+ // Check dnstap output
+ o := <-output
+ if *debug {
+ log.Printf("raw dnstap:%v", o)
+ }
+ dtName, err := qnameFromFrame(o)
+ if err != nil {
+ log.Printf("%v\n", err)
+ os.Exit(1)
+ }
+ if fqdn != dtName {
+ log.Printf("expected %v got %v", fqdn, dtName)
+ os.Exit(1) // Test failed
+ }
+ log.Printf("matched qname: %v", dtName)
+ }
+ cancel() // Send signal to close daemon
+ }()
+
+ status = <-ch
+ if !status {
+ os.Exit(1) // error in wait
+ }
+ log.Printf("Tested OK\n")
+}
diff --git a/tests/dnstap/src/dnstap-test/vendor/manifest b/tests/dnstap/src/dnstap-test/vendor/manifest
new file mode 100644
index 0000000..27c1dec
--- /dev/null
+++ b/tests/dnstap/src/dnstap-test/vendor/manifest
@@ -0,0 +1,55 @@
+{
+ "version": 0,
+ "dependencies": [
+ {
+ "importpath": "github.com/cloudflare/dns",
+ "repository": "https://github.com/cloudflare/dns",
+ "vcs": "git",
+ "revision": "e20ffa3da443071c7b3d164dec5b1f80dfb2ecf3",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/dnstap/golang-dnstap",
+ "repository": "https://github.com/dnstap/golang-dnstap",
+ "vcs": "git",
+ "revision": "0145fd8482619f9c04788c7ba4e96cdeef64a041",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/farsightsec/golang-framestream",
+ "repository": "https://github.com/farsightsec/golang-framestream",
+ "vcs": "git",
+ "revision": "b600ccf606747139c84b6d69b5c3988164db4d42",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/golang/protobuf/proto",
+ "repository": "https://github.com/golang/protobuf",
+ "vcs": "git",
+ "revision": "8ee79997227bf9b34611aee7946ae64735e6fd93",
+ "branch": "master",
+ "path": "/proto",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/golang/protobuf/ptypes/any",
+ "repository": "https://github.com/golang/protobuf",
+ "vcs": "git",
+ "revision": "8ee79997227bf9b34611aee7946ae64735e6fd93",
+ "branch": "master",
+ "path": "ptypes/any",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/miekg/dns",
+ "repository": "https://github.com/miekg/dns",
+ "vcs": "git",
+ "revision": "f4d2b086946a624202dc59e6a43f72e8f3f02bc1",
+ "branch": "master",
+ "notests": true
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/hints_zone.j2 b/tests/hints_zone.j2
new file mode 100644
index 0000000..b46b30d
--- /dev/null
+++ b/tests/hints_zone.j2
@@ -0,0 +1,9 @@
+; This file holds the information on root name servers needed to
+; initialize cache of Internet domain name servers
+
+. 3600000 NS K.ROOT-SERVERS.NET.
+{% if ':' in ROOT_ADDR %}
+K.ROOT-SERVERS.NET. 3600000 AAAA {{ROOT_ADDR}}
+{% else %}
+K.ROOT-SERVERS.NET. 3600000 A {{ROOT_ADDR}}
+{% endif %}
diff --git a/tests/kresd_config.j2 b/tests/kresd_config.j2
new file mode 100644
index 0000000..52814b5
--- /dev/null
+++ b/tests/kresd_config.j2
@@ -0,0 +1,53 @@
+net = { '{{SELF_ADDR}}' }
+-- hints.root({['k.root-servers.net'] = '{{ROOT_ADDR}}'})
+_hint_root_file('hints')
+
+cache.size = 2*MB
+
+
+{% if QMIN == "false" %}
+option('NO_MINIMIZE', true)
+{% else %}
+option('NO_MINIMIZE', false)
+{% endif %}
+
+{% if DO_NOT_QUERY_LOCALHOST == "false" %}
+option('ALLOW_LOCAL', true)
+{% else %}
+option('ALLOW_LOCAL', false)
+{% endif %}
+
+{% if HARDEN_GLUE == "true" %}
+mode('normal')
+{% else %}
+mode('permissive')
+{% endif %}
+
+{% for TAF in TRUST_ANCHOR_FILES %}
+trust_anchors.add_file('{{TAF}}')
+{% endfor %}
+trust_anchors.set_insecure({
+
+{% for DI in NEGATIVE_TRUST_ANCHORS %}
+"{{DI}}",
+{% endfor %}
+})
+
+verbose(true)
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(cache.count() == 0)
+assert(cache.stats() ~= nil)
+assert(cache.backends() ~= nil)
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(net.list()['{{SELF_ADDR}}'])
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function (ev) return 1 end)
+event.cancel(ev)
+ev = event.after(0, function (ev) return 1 end)
diff --git a/tests/mock_cmodule.c b/tests/mock_cmodule.c
new file mode 100644
index 0000000..64dfbb8
--- /dev/null
+++ b/tests/mock_cmodule.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/module.h"
+
+/*
+ * Mock module implementation.
+ */
+
+int mock_cmodule_init(struct kr_module *module)
+{
+ return kr_ok();
+}
+
+int mock_cmodule_deinit(struct kr_module *module)
+{
+ return kr_ok();
+}
+
+KR_MODULE_EXPORT(mock_cmodule)
diff --git a/tests/pytests/README.rst b/tests/pytests/README.rst
new file mode 100644
index 0000000..9a11ccd
--- /dev/null
+++ b/tests/pytests/README.rst
@@ -0,0 +1,54 @@
+Python client tests for kresd
+=============================
+
+The tests run `/usr/bin/env kresd` (can be modified with `$PATH`) with custom config
+and execute client-side testing, such as TCP / TLS connection management.
+
+Requirements
+------------
+
+- pip3 install -r requirements.txt
+
+Executing tests
+---------------
+
+Tests can be executed with the pytest framework.
+
+.. code-block:: bash
+
+ $ pytest-3 # sequential, all tests (with exception of few special tests)
+ $ pytest-3 test_conn_mgmt.py::test_ignore_garbage # specific test only
+ $ pytest-3 --html pytests.html --self-contained-html # html report
+
+It's highly recommended to run these tests in parallel, since lot of them
+wait for kresd timeout. This can be done with `python-xdist`:
+
+.. code-block:: bash
+
+ $ pytest-3 -n 24 # parallel with 24 jobs
+
+Each test spawns an independent kresd instance, so test failures shouldn't affect
+each other.
+
+Some tests are omitted from automatic test collection by default, due to their
+resource contraints. These typicially have to be executed separately by providing
+the path to test file directly.
+
+.. code-block:: bash
+
+ $ pytest-3 conn_flood.py
+
+Note: some tests may fail without an internet connection.
+
+Developer notes
+---------------
+
+Typically, each test requires a setup of kresd, and a connected socket to run tests on.
+The framework provides a few useful pytest fixtures to simplify this process:
+
+- `kresd_sock` provides a connected socket to a test-specific, running kresd instance.
+ It expands to 4 values (tests) - IPv4 TCP, IPv6 TCP, IPv4 TLS, IPv6 TLS sockets
+- `make_kresd_sock` is similar to `kresd_sock`, except it's a factory function that
+ produces a new connected socket (of the same type) on each call
+- `kresd`, `kresd_tt` are all Kresd instances, already running
+ and initialized with config (with no / valid TLS certificates)
diff --git a/tests/pytests/certs/tt-certgen-expired.sh b/tests/pytests/certs/tt-certgen-expired.sh
new file mode 100755
index 0000000..7750291
--- /dev/null
+++ b/tests/pytests/certs/tt-certgen-expired.sh
@@ -0,0 +1,18 @@
+# !/bin/bash
+
+if [ ! -d ./demoCA ]; then
+ mkdir ./demoCA
+fi
+if [ ! -d ./demoCA/newcerts ]; then
+ mkdir ./demoCA/newcerts
+fi
+touch ./demoCA/index.txt
+touch ./demoCA/index.txt.attr
+if [ ! -f ./demoCA/serial ]; then
+ echo 01 > ./demoCA/serial
+fi
+
+openssl genrsa -out tt-expired.key.pem 2048
+openssl req -config tt.conf -new -key tt-expired.key.pem -out tt-expired.csr.pem
+openssl ca -config tt.conf -selfsign -keyfile tt-expired.key.pem -out tt-expired.cert.pem -in tt-expired.csr.pem -startdate 19700101000000Z -enddate 19700101000000Z
+
diff --git a/tests/pytests/certs/tt-certgen.sh b/tests/pytests/certs/tt-certgen.sh
new file mode 100755
index 0000000..b6b3d7f
--- /dev/null
+++ b/tests/pytests/certs/tt-certgen.sh
@@ -0,0 +1,4 @@
+# !/bin/sh
+
+openssl req -config tt.conf -new -x509 -newkey rsa:2048 -nodes -keyout tt.key.pem -sha256 -out tt.cert.pem -days 20000
+
diff --git a/tests/pytests/certs/tt-expired.cert.pem b/tests/pytests/certs/tt-expired.cert.pem
new file mode 100644
index 0000000..c9f8c09
--- /dev/null
+++ b/tests/pytests/certs/tt-expired.cert.pem
@@ -0,0 +1,80 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=CZ, ST=PRAGUE, CN=transport-test-server.com
+ Validity
+ Not Before: Jan 1 00:00:00 1970 GMT
+ Not After : Jan 1 00:00:00 1970 GMT
+ Subject: C=CZ, ST=PRAGUE, CN=transport-test-server.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:6b:1a:11:47:01:ac:eb:5c:2d:cf:ce:6a:a4:
+ 00:ce:2f:d1:25:03:5f:06:38:02:92:24:18:92:2a:
+ 69:19:b2:2b:a3:4f:f7:79:de:35:c3:f5:72:37:83:
+ 44:93:f9:76:fc:89:29:32:9c:0d:4b:95:7d:d1:5d:
+ 40:e9:ba:49:50:7d:c6:0a:c8:1e:e7:90:1e:37:7c:
+ 0b:23:a3:e3:bc:c9:53:81:de:d6:5f:cb:b2:3d:36:
+ ac:59:b0:33:91:8f:0c:5f:10:20:70:bf:a3:22:b3:
+ 98:ac:d4:7a:ea:67:b8:b1:8c:cf:e5:fe:8f:a0:a5:
+ 02:ad:6d:ce:f1:62:ab:dc:5d:96:9c:4f:95:47:d5:
+ 82:b7:b3:e3:87:4c:8d:38:85:2a:24:9d:7f:c7:a4:
+ 0e:bd:8a:2d:6b:d2:d4:e8:78:62:1b:aa:25:5f:5a:
+ 64:e5:76:23:ae:11:03:9a:5c:ed:a2:ba:51:ec:b1:
+ f3:ae:ba:5c:eb:dd:49:63:ca:c7:af:0c:16:1d:94:
+ 95:3a:ce:2c:8f:e2:94:7f:1f:a1:76:e2:9f:d1:41:
+ 31:f0:68:e5:ae:df:d0:75:a0:34:f5:25:93:85:b3:
+ 25:50:42:6c:00:c0:fe:3b:e0:fb:00:de:75:33:86:
+ 6a:21:35:14:9d:7f:4a:af:f7:15:f2:d7:bb:2f:de:
+ df:ab
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ B3:42:0A:9A:00:19:CB:CB:24:A0:02:45:1E:8A:B0:54:CB:9F:55:FE
+ X509v3 Authority Key Identifier:
+ keyid:B3:42:0A:9A:00:19:CB:CB:24:A0:02:45:1E:8A:B0:54:CB:9F:55:FE
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 32:9a:05:e3:6f:ae:ee:b1:a2:12:0a:9f:0a:e7:78:26:df:90:
+ fb:84:60:ae:13:fc:ff:fd:42:84:23:14:c3:2e:e2:a9:df:4b:
+ 5c:2f:5b:0e:3d:f9:5a:56:50:13:bc:89:1a:08:70:dd:6c:6c:
+ e8:ae:cf:22:39:92:f2:3b:40:03:8f:4e:bc:54:88:6b:fd:8c:
+ b6:eb:30:90:21:db:fc:4e:5c:7e:12:75:e2:52:76:df:19:0f:
+ 30:49:1e:15:bc:ba:6a:e6:f7:af:93:ad:e4:36:da:47:47:a6:
+ 88:b0:ae:46:1e:91:e1:d6:b1:5e:a4:f0:68:02:81:57:86:5d:
+ 17:d1:6c:7e:7a:9f:5e:0d:fc:10:e7:7a:1a:b5:f9:4b:1d:78:
+ a4:9a:9d:d7:c2:64:c3:52:28:7f:a1:b7:25:d7:13:3f:09:7f:
+ f2:fd:dd:c6:91:eb:9b:51:80:e2:36:cb:9f:5b:4e:47:eb:77:
+ d3:cc:8b:18:b5:0b:97:a2:53:8e:fb:9b:94:7d:57:21:32:c6:
+ f3:67:93:a4:9b:eb:46:b7:cd:08:43:99:dd:c1:c3:51:b9:19:
+ ef:92:77:1c:84:67:80:67:95:ba:00:75:3d:7b:8b:ff:24:30:
+ f1:fa:6d:da:31:9d:cf:06:da:5d:04:07:14:45:8c:6b:e7:21:
+ 31:ec:7b:23
+-----BEGIN CERTIFICATE-----
+MIIDfjCCAmagAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJDWjEP
+MA0GA1UECAwGUFJBR1VFMSIwIAYDVQQDDBl0cmFuc3BvcnQtdGVzdC1zZXJ2ZXIu
+Y29tMCIYDzE5NzAwMTAxMDAwMDAwWhgPMTk3MDAxMDEwMDAwMDBaMEIxCzAJBgNV
+BAYTAkNaMQ8wDQYDVQQIDAZQUkFHVUUxIjAgBgNVBAMMGXRyYW5zcG9ydC10ZXN0
+LXNlcnZlci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/axoR
+RwGs61wtz85qpADOL9ElA18GOAKSJBiSKmkZsiujT/d53jXD9XI3g0ST+Xb8iSky
+nA1LlX3RXUDpuklQfcYKyB7nkB43fAsjo+O8yVOB3tZfy7I9NqxZsDORjwxfECBw
+v6Mis5is1HrqZ7ixjM/l/o+gpQKtbc7xYqvcXZacT5VH1YK3s+OHTI04hSoknX/H
+pA69ii1r0tToeGIbqiVfWmTldiOuEQOaXO2iulHssfOuulzr3UljysevDBYdlJU6
+ziyP4pR/H6F24p/RQTHwaOWu39B1oDT1JZOFsyVQQmwAwP474PsA3nUzhmohNRSd
+f0qv9xXy17sv3t+rAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W
+HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSzQgqaABnL
+yySgAkUeirBUy59V/jAfBgNVHSMEGDAWgBSzQgqaABnLyySgAkUeirBUy59V/jAN
+BgkqhkiG9w0BAQsFAAOCAQEAMpoF42+u7rGiEgqfCud4Jt+Q+4RgrhP8//1ChCMU
+wy7iqd9LXC9bDj35WlZQE7yJGghw3Wxs6K7PIjmS8jtAA49OvFSIa/2MtuswkCHb
+/E5cfhJ14lJ23xkPMEkeFby6aub3r5Ot5DbaR0emiLCuRh6R4daxXqTwaAKBV4Zd
+F9FsfnqfXg38EOd6GrX5Sx14pJqd18Jkw1Iof6G3JdcTPwl/8v3dxpHrm1GA4jbL
+n1tOR+t308yLGLULl6JTjvublH1XITLG82eTpJvrRrfNCEOZ3cHDUbkZ75J3HIRn
+gGeVugB1PXuL/yQw8fpt2jGdzwbaXQQHFEWMa+chMex7Iw==
+-----END CERTIFICATE-----
diff --git a/tests/pytests/certs/tt-expired.key.pem b/tests/pytests/certs/tt-expired.key.pem
new file mode 100644
index 0000000..ca2988c
--- /dev/null
+++ b/tests/pytests/certs/tt-expired.key.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAv2saEUcBrOtcLc/OaqQAzi/RJQNfBjgCkiQYkippGbIro0/3
+ed41w/VyN4NEk/l2/IkpMpwNS5V90V1A6bpJUH3GCsge55AeN3wLI6PjvMlTgd7W
+X8uyPTasWbAzkY8MXxAgcL+jIrOYrNR66me4sYzP5f6PoKUCrW3O8WKr3F2WnE+V
+R9WCt7Pjh0yNOIUqJJ1/x6QOvYota9LU6HhiG6olX1pk5XYjrhEDmlztorpR7LHz
+rrpc691JY8rHrwwWHZSVOs4sj+KUfx+hduKf0UEx8Gjlrt/QdaA09SWThbMlUEJs
+AMD+O+D7AN51M4ZqITUUnX9Kr/cV8te7L97fqwIDAQABAoIBAEA4ytIpJKLDhHXK
+VtLom2ySFnV4oBUSDarCeYvwtrpsUL/GQJ2etCM+4kdFv2h2NjmcOzpDqSJG0aPA
+ydqhKZ/b0uojIltGuxyafZJDllDsqxvTi9EwImjvQvwEZgjcGaZ7Xqb1ZOJrpzm1
+QFgM3KaVO9tKgR3Avxk40kmidU7FctFi5IELwnH/RR1OHvJbxOE4+i0LlDx0QzhX
+QHtnvHLqLLdqsFk8KvuVuVj1FwqJ6cSL0JrAdt7dnGmXBo4PDqT8Hj0AjM+CcNrV
+1D6Li9xr4y55EZUK2qU/FVDC3LqlYQy5mBfasJAXPQG4RgSVFxJ929HC7gi8vMCO
+UMeLniECgYEA6gBoRwzQ5pJUXfZGW41lJt08utfycGZm7VrA81r0x0F+DcuZ2t6J
+kB9Wnp/MNpB4DJLbl7oM2OlFOO3cw0n3VaFpNMPHVHzNbyi1hp94AIIeDz/sxfUI
+Lx7ynAQSPPQzDRfVJesT8waBdweA71TBOlrFQ2Cp7O4Qf+p0akQSv3cCgYEA0Wnd
+1Gbierv2m6Jnblg+brTMQwbRsOAM2n0V4Gd2kRaLSYd23ebshvx8xTWipRlrb5vP
+UEh+LkfuscqaJDCrikasht9z5FJtfIzHKgTrLSoR3MJRjrnuLJWTQUwSqzd0UNN6
+HigV6p+CqesNnELErak53IMfmkHAhTSkII8R9m0CgYBRY+DhTaDfgegcYouoTm7v
+bKYx6uillciZKCbSvkFDiREaJUYXba31ViEfvT8ff3JyFSaSCKFtVP3BxmIx/ukr
+fKAGPU54oYwm7Mbu00q/CoMAFOD7HbZCBYanI3dggiO7mx2FOdXPguTHDPIYzKcE
+8AuK2vVftpJAm8DwMUtAEwKBgH/eRc5ZGDdbKGS10LQm+9A7Y3IV6to2pIKQ2FfS
+tSo4espmBeXPCGQQLdt5OZvYHqril77s1OdLkutKy74HXecr6lLchHZJAoOHrmDw
+6e0FAC0tFgGxdEYS+vxnCAs17DciOjHJxkAiL/WzCfd9KXzklOkZw6U8OuLbVtBu
+q8gtAoGAbl03XZm+SHrO7XjHK/Fe5YD13cOirg48htvjbpqEDZNQr3l0eVnEj074
+IopDa/wUFlaaqPZ/DVFctqSocyskWIP4u9HfmsNBHjK5zQlge7B1fNVao++YKund
+qnVnXjWQuF2aL8k2geFxdSKmHTF4/N1qEyeyR+tMaFpGfMZOuM8=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/pytests/certs/tt.cert.pem b/tests/pytests/certs/tt.cert.pem
new file mode 100644
index 0000000..2ea4898
--- /dev/null
+++ b/tests/pytests/certs/tt.cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDkTCCAnmgAwIBAgIJAP/KybHquuyUMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV
+BAYTAkNaMQ8wDQYDVQQIDAZQUkFHVUUxIjAgBgNVBAMMGXRyYW5zcG9ydC10ZXN0
+LXNlcnZlci5jb20wIBcNMTgwNzE4MTAwODIzWhgPMjA3MzA0MjAxMDA4MjNaMEIx
+CzAJBgNVBAYTAkNaMQ8wDQYDVQQIDAZQUkFHVUUxIjAgBgNVBAMMGXRyYW5zcG9y
+dC10ZXN0LXNlcnZlci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDRAQDAX6+lFKurvm7fgQqm8WyYzT/wxfPJjsVQGe87OlH1KFzVfzYzgEt0RMlM
+eZgipREBZB2zK+WFM5RBHWYAwlI5PKt7EAGn8q1Zm4z+M9Uom3/Hy3bZ9q+AJwjk
+odpHYuFyWJqHIQBqaQ3SFyJwdZ/GsuzEUfWuIl74oyyMAeykTKFGdaVuIlLC3fKm
+8UCnfk99i/LEXUwRcmOV0uaG7deN5ITDDCFdb615yVjLkMhGY/jHK7uuxATOopEk
+4vThQ1aQjSkHwluaqFUW6Zl4QF8WOAufoWQPFZ8XxmUYEIG/sMvLv6dol7ltjEbC
+bfyzlS+9Qbnq6MfhTZF/4jAPAgMBAAGjgYcwgYQwHQYDVR0OBBYEFBNiUgCiKw4b
+CFNKaEkqhkNSer7wMB8GA1UdIwQYMBaAFBNiUgCiKw4bCFNKaEkqhkNSer7wMA8G
+A1UdEwEB/wQFMAMBAf8wJAYDVR0RBB0wG4IZdHJhbnNwb3J0LXRlc3Qtc2VydmVy
+LmNvbTALBgNVHQ8EBAMCAaYwDQYJKoZIhvcNAQELBQADggEBACz1ZQ8XkGobhTcA
+hkSTSw0ko6qwVuJJD5ue3SUcWLATsskohTJmN6bde3IMDRyQvLJAlMdG2p1qMbtA
+OTbnQJTT7oDLaW8w2D+eO5oWTJvxLpl6TxbIfJN/8ITB1ltOCxTU9cVNbd2eh8sj
+l3R4etg9djYRrqtNxCQZOYSwvhHw2MefnwjGVuJEu6JYOn3IE8Jqsh/LI59C87nE
+MetZrXlzC6kSAFfRYgQET9RhBobMU9yFR8zGVHDFoxqNQs2lYKPz/3rFPetL2rjT
+cFwzxkxDdwn+RNisBc1LMfIg7pvSMFR6sAnpjeRHN0Uoem1jj2qtzjbFENDuyQ4/
+HSi4UcE=
+-----END CERTIFICATE-----
diff --git a/tests/pytests/certs/tt.conf b/tests/pytests/certs/tt.conf
new file mode 100644
index 0000000..5ac7737
--- /dev/null
+++ b/tests/pytests/certs/tt.conf
@@ -0,0 +1,353 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+# Policies used by the TSA examples.
+tsa_policy1 = 1.2.3.4.1
+tsa_policy2 = 1.2.3.4.5.6
+tsa_policy3 = 1.2.3.4.5.7
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certs with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem# The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = default # use public key default MD
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = optional
+stateOrProvinceName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 2048
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = CZ
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = PRAGUE
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default =
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+#organizationalUnitName_default =
+
+commonName = Common Name (e.g. server FQDN or YOUR name)
+commonName_max = 64
+commonName_default = transport-test-server.com
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This is required for TSA certificates.
+# extendedKeyUsage = critical,timeStamping
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer
+
+basicConstraints = critical,CA:true
+
+subjectAltName = @alternate_names
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as an test self-signed certificate it is best
+# left out by default.
+keyUsage = digitalSignature, keyEncipherment, cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
+
+####################################################################
+[ tsa ]
+
+default_tsa = tsa_config1 # the default TSA section
+
+[ tsa_config1 ]
+
+# These are used by the TSA reply generation only.
+dir = ./demoCA # TSA root directory
+serial = $dir/tsaserial # The current serial number (mandatory)
+crypto_device = builtin # OpenSSL engine to use for signing
+signer_cert = $dir/tsacert.pem # The TSA signing certificate
+ # (optional)
+certs = $dir/cacert.pem # Certificate chain to include in reply
+ # (optional)
+signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
+signer_digest = sha256 # Signing digest to use. (Optional)
+default_policy = tsa_policy1 # Policy if request did not specify it
+ # (optional)
+other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
+digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
+accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
+clock_precision_digits = 0 # number of digits after dot. (optional)
+ordering = yes # Is ordering defined for timestamps?
+ # (optional, default: no)
+tsa_name = yes # Must the TSA name be included in the reply?
+ # (optional, default: no)
+ess_cert_id_chain = no # Must the ESS cert id chain be included?
+ # (optional, default: no)
+
+[ alternate_names ]
+
+DNS.1 = transport-test-server.com
diff --git a/tests/pytests/certs/tt.key.pem b/tests/pytests/certs/tt.key.pem
new file mode 100644
index 0000000..1974be7
--- /dev/null
+++ b/tests/pytests/certs/tt.key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDRAQDAX6+lFKur
+vm7fgQqm8WyYzT/wxfPJjsVQGe87OlH1KFzVfzYzgEt0RMlMeZgipREBZB2zK+WF
+M5RBHWYAwlI5PKt7EAGn8q1Zm4z+M9Uom3/Hy3bZ9q+AJwjkodpHYuFyWJqHIQBq
+aQ3SFyJwdZ/GsuzEUfWuIl74oyyMAeykTKFGdaVuIlLC3fKm8UCnfk99i/LEXUwR
+cmOV0uaG7deN5ITDDCFdb615yVjLkMhGY/jHK7uuxATOopEk4vThQ1aQjSkHwlua
+qFUW6Zl4QF8WOAufoWQPFZ8XxmUYEIG/sMvLv6dol7ltjEbCbfyzlS+9Qbnq6Mfh
+TZF/4jAPAgMBAAECggEBALSs10d18FMW0WjAUPxpgxnaLnTRSesMVLjy8ONT6Bkd
+S2hRIh91vxc6WwABzrqLita4N0EqmPoggmNpuUmo7lrNoWLVbbAOoD/da7nA3FuL
+10MpWYcP/ohh1klEdU2gFSAM/LNqoPsbrk5OzqHFWgI5zItqdX8pEucb01nBRWsp
+VMY2vzVuFB2jweZQ5+LCpfSMcRIzlxQa9CG4Peu6YW1Z4b3aUcS63/829JN/ZOGd
+uoRqR+gP71yNIt6i7wA5cot5FRmzlFEGhb1XzBOB1FFHOiknOZzbBtDsGUUmVtfA
+6mXcTumhdHbC0bXnHei/s2s9X0EeyQFYPkoS4NUQ2dECgYEA/7lhgn89K8rpUPnS
+eccTpKVPWp8luQei98Hi/F94kwP32l7Zl7Bmu2nltUoB1GBRXoXY6KzTphmT6ioA
+8joLCKIii5/nOdZAdHbIN2tkXS56h524q5I2jKogjfRrpCaAJE8x99f8L9uTBfZb
+/7BBQDHai1/S6LcpIRf/4g1/xBsCgYEA0Tq4V5hR9mGDUFir1FDGhA3ijDkIE/sO
+3QGTU7W90BL27te98FuQtWOPqfd1fi26WypNpNQUZb3V4x5tmDcpWscfj6I10432
+4zECPlDgaevucJjj245U7WjUhdAvlRy6K8H/8MgRBAjw9h8dwIGIx9gmOqKdA+/h
+ve3xyjKQex0CgYAz0XzQ1LewiA1/OyBLTOvOETFjS5x5QfLkAYXdXfswzz0KIu40
+rqoij/LcKYL1Zg8W+Ehb3amFnuk6KgjHDLvvo+scH+ra7W9iKi+oCzrrJt/tWyhw
+m9Ax8Mdn/H9TY/nTYbjeYAXaLMQ+EQ3TYgPW3kNKusAiJ/tNmW9gfxvEwQKBgGSJ
+Rbj5fTDZjGKYKQDdS3Z6wYhFg0culObHcgaARtPruPHtgtwy82blj0vJl5Bo4qoZ
+urNgIOj+ff8jSOAiaWGwWs8Gz7x289IZY42UCTF8Z9d878g5LT/i5nPiJGsPIboS
+/yuwxtRcg4SQURiGZbY5e60jJDWXF67O3icdguVVAoGARXLufXvZ/9Xf1DmFFxjq
+PJMCa1sfofqjB4KqYbt17vFtTsddCiyqsbpx36oY6nIdm9yUiGo10YaSEJtDEGLS
+L3TPZ4s8M8dcjOfj8Kk75pKbJ7NY4qA64dtbxcZbrFp3/mGZkDing94y+Zc/aFqa
+xQsA/yhmYV9r+FHDL54Cn6I=
+-----END PRIVATE KEY-----
diff --git a/tests/pytests/conftest.py b/tests/pytests/conftest.py
new file mode 100644
index 0000000..e10ba3a
--- /dev/null
+++ b/tests/pytests/conftest.py
@@ -0,0 +1,78 @@
+import socket
+
+import pytest
+
+from kresd import init_portdir, make_kresd
+
+
+@pytest.fixture
+def kresd(tmpdir):
+ with make_kresd(tmpdir) as kresd:
+ yield kresd
+
+
+@pytest.fixture
+def kresd_tt(tmpdir):
+ with make_kresd(tmpdir, 'tt') as kresd:
+ yield kresd
+
+
+@pytest.fixture(params=[
+ 'ip_tcp_socket',
+ 'ip6_tcp_socket',
+ 'ip_tls_socket',
+ 'ip6_tls_socket',
+])
+def make_kresd_sock(request, kresd):
+ """Factory function to create sockets of the same kind."""
+ sock_func = getattr(kresd, request.param)
+
+ def _make_kresd_sock():
+ return sock_func()
+
+ return _make_kresd_sock
+
+
+@pytest.fixture
+def kresd_sock(make_kresd_sock):
+ return make_kresd_sock()
+
+
+@pytest.fixture(params=[
+ socket.AF_INET,
+ socket.AF_INET6,
+])
+def sock_family(request):
+ return request.param
+
+
+@pytest.fixture(params=[
+ True,
+ False
+])
+def single_buffer(request): # whether to send all data in a single buffer
+ return request.param
+
+
+@pytest.fixture(params=[
+ True,
+ False
+])
+def query_before(request): # whether to send an initial query
+ return request.param
+
+
+@pytest.mark.optionalhook
+def pytest_metadata(metadata): # filter potentially sensitive data from GitLab CI
+ keys_to_delete = []
+ for key in metadata.keys():
+ key_lower = key.lower()
+ if 'password' in key_lower or 'token' in key_lower or \
+ key_lower.startswith('ci') or key_lower.startswith('gitlab'):
+ keys_to_delete.append(key)
+ for key in keys_to_delete:
+ del metadata[key]
+
+
+def pytest_sessionstart(session): # pylint: disable=unused-argument
+ init_portdir()
diff --git a/tests/pytests/conn_flood.py b/tests/pytests/conn_flood.py
new file mode 100644
index 0000000..8c2625a
--- /dev/null
+++ b/tests/pytests/conn_flood.py
@@ -0,0 +1,83 @@
+"""Test opening as many connections as possible.
+
+Due to resource-intensity of this test, it's filename doesn't contain
+"test" on purpose, so it doesn't automatically get picked up by pytest
+(to allow easy parallel testing).
+
+To execute this test, pass the filename of this file to pytest directly.
+Also, make sure not to use parallel execution (-n).
+"""
+
+import resource
+import time
+
+import pytest
+
+from kresd import Kresd
+import utils
+
+
+MAX_SOCKETS = 10000 # upper bound of how many connections to open
+MAX_ITERATIONS = 10 # number of iterations to run the test
+
+# we can't use softlimit ifself since kresd already has open sockets,
+# so use lesser value
+RESERVED_NOFILE = 40 # 40 is empirical value
+
+
+@pytest.mark.parametrize('sock_func_name', [
+ 'ip_tcp_socket',
+ 'ip6_tcp_socket',
+ 'ip_tls_socket',
+ 'ip6_tls_socket',
+])
+def test_conn_flood(tmpdir, sock_func_name):
+ def create_sockets(make_sock, nsockets):
+ sockets = []
+ next_ping = time.time() + 4 # less than tcp idle timeout / 2
+ while True:
+ additional_sockets = 0
+ while time.time() < next_ping:
+ nsock_to_init = min(100, nsockets - len(sockets))
+ if not nsock_to_init:
+ return sockets
+ sockets.extend([make_sock() for _ in range(nsock_to_init)])
+ additional_sockets += nsock_to_init
+
+ # large number of connections can take a lot of time to open
+ # send some valid data to avoid TCP idle timeout for already open sockets
+ next_ping = time.time() + 4
+ for s in sockets:
+ utils.ping_alive(s)
+
+ # break when no more than 20% additional sockets are created
+ if additional_sockets / len(sockets) < 0.2:
+ return sockets
+
+ max_num_of_open_files = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - RESERVED_NOFILE
+ nsockets = min(max_num_of_open_files, MAX_SOCKETS)
+
+ # create kresd instance with verbose=False
+ ip = '127.0.0.1'
+ ip6 = '::1'
+ with Kresd(tmpdir, ip=ip, ip6=ip6, verbose=False) as kresd:
+ make_sock = getattr(kresd, sock_func_name) # function for creating sockets
+ sockets = create_sockets(make_sock, nsockets)
+ print("\nEstablished {} connections".format(len(sockets)))
+
+ print("Start sending data")
+ for i in range(MAX_ITERATIONS):
+ for s in sockets:
+ utils.ping_alive(s)
+ print("Iteration {} done...".format(i))
+
+ print("Close connections")
+ for s in sockets:
+ s.close()
+
+ # check in kresd is alive
+ print("Check upstream is still alive")
+ sock = make_sock()
+ utils.ping_alive(sock)
+
+ print("OK!")
diff --git a/tests/pytests/kresd.py b/tests/pytests/kresd.py
new file mode 100644
index 0000000..4b122f6
--- /dev/null
+++ b/tests/pytests/kresd.py
@@ -0,0 +1,305 @@
+from collections import namedtuple
+from contextlib import ContextDecorator, contextmanager
+import os
+from pathlib import Path
+import random
+import re
+import shutil
+import socket
+import subprocess
+import time
+
+import jinja2
+
+import utils
+
+
+PYTESTS_DIR = os.path.dirname(os.path.realpath(__file__))
+CERTS_DIR = os.path.join(PYTESTS_DIR, 'certs')
+TEMPLATES_DIR = os.path.join(PYTESTS_DIR, 'templates')
+KRESD_CONF_TEMPLATE = 'kresd.conf.j2'
+KRESD_STARTUP_MSGID = 10005 # special unique ID at the start of the "test" log
+KRESD_PORTDIR = '/tmp/pytest-kresd-portdir'
+KRESD_TESTPORT_MIN = 1024
+KRESD_TESTPORT_MAX = 32768 # avoid overlap with docker ephemeral port range
+
+
+def init_portdir():
+ try:
+ shutil.rmtree(KRESD_PORTDIR)
+ except FileNotFoundError:
+ pass
+ os.makedirs(KRESD_PORTDIR)
+
+
+def create_file_from_template(template_path, dest, data):
+ env = jinja2.Environment(
+ loader=jinja2.FileSystemLoader(TEMPLATES_DIR))
+ template = env.get_template(template_path)
+ rendered_template = template.render(**data)
+
+ with open(dest, "w") as fh:
+ fh.write(rendered_template)
+
+
+Forward = namedtuple('Forward', ['proto', 'ip', 'port', 'hostname', 'ca_file'])
+
+
+class Kresd(ContextDecorator):
+ def __init__(
+ self, workdir, port=None, tls_port=None, ip=None, ip6=None, certname=None,
+ verbose=True, hints=None, forward=None):
+ if ip is None and ip6 is None:
+ raise ValueError("IPv4 or IPv6 must be specified!")
+ self.workdir = str(workdir)
+ self.port = port
+ self.tls_port = tls_port
+ self.ip = ip
+ self.ip6 = ip6
+ self.process = None
+ self.sockets = []
+ self.logfile = None
+ self.verbose = verbose
+ self.hints = {} if hints is None else hints
+ self.forward = forward
+
+ if certname:
+ self.tls_cert_path = os.path.join(CERTS_DIR, certname + '.cert.pem')
+ self.tls_key_path = os.path.join(CERTS_DIR, certname + '.key.pem')
+ else:
+ self.tls_cert_path = None
+ self.tls_key_path = None
+
+ @property
+ def config_path(self):
+ return str(os.path.join(self.workdir, 'kresd.conf'))
+
+ @property
+ def logfile_path(self):
+ return str(os.path.join(self.workdir, 'kresd.log'))
+
+ def __enter__(self):
+ if self.port is not None:
+ take_port(self.port, self.ip, self.ip6, timeout=120)
+ else:
+ self.port = make_port(self.ip, self.ip6)
+ if self.tls_port is not None:
+ take_port(self.tls_port, self.ip, self.ip6, timeout=120)
+ else:
+ self.tls_port = make_port(self.ip, self.ip6)
+
+ create_file_from_template(KRESD_CONF_TEMPLATE, self.config_path, {'kresd': self})
+ self.logfile = open(self.logfile_path, 'w')
+ self.process = subprocess.Popen(
+ ['kresd', '-c', self.config_path, '-f', '1', self.workdir],
+ stdout=self.logfile, env=os.environ.copy())
+
+ try:
+ self._wait_for_tcp_port() # wait for ports to be up and responding
+ if not self.all_ports_alive(msgid=10001):
+ raise RuntimeError("Kresd not listening on all ports")
+
+ # issue special msgid to mark start of test log
+ sock = self.ip_tcp_socket() if self.ip else self.ip6_tcp_socket()
+ assert utils.try_ping_alive(sock, close=True, msgid=KRESD_STARTUP_MSGID)
+
+ # sanity check - kresd didn't crash
+ self.process.poll()
+ if self.process.returncode is not None:
+ raise RuntimeError("Kresd crashed with returncode: {}".format(
+ self.process.returncode))
+ except (RuntimeError, ConnectionError): # pylint: disable=try-except-raise
+ with open(self.logfile_path) as log: # print log for debugging
+ print(log.read())
+ raise
+
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ try:
+ if not self.all_ports_alive(msgid=1006):
+ raise RuntimeError("Kresd crashed")
+ finally:
+ for sock in self.sockets:
+ sock.close()
+ self.process.terminate()
+ self.logfile.close()
+ Path(KRESD_PORTDIR, str(self.port)).unlink()
+
+ def all_ports_alive(self, msgid=10001):
+ alive = True
+ if self.ip:
+ alive &= utils.try_ping_alive(self.ip_tcp_socket(), close=True, msgid=msgid)
+ alive &= utils.try_ping_alive(self.ip_tls_socket(), close=True, msgid=msgid + 1)
+ if self.ip6:
+ alive &= utils.try_ping_alive(self.ip6_tcp_socket(), close=True, msgid=msgid + 2)
+ alive &= utils.try_ping_alive(self.ip6_tls_socket(), close=True, msgid=msgid + 3)
+ return alive
+
+ def _wait_for_tcp_port(self, max_delay=10, delay_step=0.2):
+ family = socket.AF_INET if self.ip else socket.AF_INET6
+ i = 0
+ end_time = time.time() + max_delay
+
+ while time.time() < end_time:
+ i += 1
+
+ # use exponential backoff algorhitm to choose next delay
+ rand_delay = random.randrange(0, i)
+ time.sleep(rand_delay * delay_step)
+
+ try:
+ sock, dest = self.stream_socket(family, timeout=5)
+ sock.connect(dest)
+ except ConnectionRefusedError:
+ continue
+ else:
+ try:
+ return utils.try_ping_alive(sock, close=True, msgid=10000)
+ except socket.timeout:
+ continue
+ finally:
+ sock.close()
+ raise RuntimeError("Kresd didn't start in time")
+
+ def socket_dest(self, family, tls=False):
+ port = self.tls_port if tls else self.port
+ if family == socket.AF_INET:
+ return self.ip, port
+ elif family == socket.AF_INET6:
+ return self.ip6, port, 0, 0
+ raise RuntimeError("Unsupported socket family: {}".format(family))
+
+ def stream_socket(self, family, tls=False, timeout=20):
+ """Initialize a socket and return it along with the destination without connecting."""
+ sock = socket.socket(family, socket.SOCK_STREAM)
+ sock.settimeout(timeout)
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ dest = self.socket_dest(family, tls)
+ self.sockets.append(sock)
+ return sock, dest
+
+ def _tcp_socket(self, family):
+ sock, dest = self.stream_socket(family)
+ sock.connect(dest)
+ return sock
+
+ def ip_tcp_socket(self):
+ return self._tcp_socket(socket.AF_INET)
+
+ def ip6_tcp_socket(self):
+ return self._tcp_socket(socket.AF_INET6)
+
+ def _tls_socket(self, family):
+ sock, dest = self.stream_socket(family, tls=True)
+ ctx = utils.make_ssl_context(insecure=True)
+ ssock = ctx.wrap_socket(sock)
+ try:
+ ssock.connect(dest)
+ except OSError as exc:
+ if exc.errno == 0: # sometimes happens shortly after startup
+ return None
+ return ssock
+
+ def _tls_socket_with_retry(self, family):
+ sock = self._tls_socket(family)
+ if sock is None:
+ time.sleep(0.1)
+ sock = self._tls_socket(family)
+ if sock is None:
+ raise RuntimeError("Failed to create TLS socket!")
+ return sock
+
+ def ip_tls_socket(self):
+ return self._tls_socket_with_retry(socket.AF_INET)
+
+ def ip6_tls_socket(self):
+ return self._tls_socket_with_retry(socket.AF_INET6)
+
+ def partial_log(self):
+ partial_log = '\n (... ommiting log start)\n'
+ with open(self.logfile_path) as log: # display partial log for debugging
+ past_startup_msgid = False
+ past_startup = False
+ for line in log:
+ if past_startup:
+ partial_log += line
+ else: # find real start of test log (after initial alive-pings)
+ if not past_startup_msgid:
+ if re.match(KRESD_LOG_STARTUP_MSGID, line) is not None:
+ past_startup_msgid = True
+ else:
+ if re.match(KRESD_LOG_IO_CLOSE, line) is not None:
+ past_startup = True
+ return partial_log
+
+
+def is_port_free(port, ip=None, ip6=None):
+ def check(family, type_, dest):
+ sock = socket.socket(family, type_)
+ sock.bind(dest)
+ sock.close()
+
+ try:
+ if ip is not None:
+ check(socket.AF_INET, socket.SOCK_STREAM, (ip, port))
+ check(socket.AF_INET, socket.SOCK_DGRAM, (ip, port))
+ if ip6 is not None:
+ check(socket.AF_INET6, socket.SOCK_STREAM, (ip6, port, 0, 0))
+ check(socket.AF_INET6, socket.SOCK_DGRAM, (ip6, port, 0, 0))
+ except OSError as exc:
+ if exc.errno == 98: # address alrady in use
+ return False
+ else:
+ raise
+ return True
+
+
+def take_port(port, ip=None, ip6=None, timeout=0):
+ port_path = Path(KRESD_PORTDIR, str(port))
+ end_time = time.time() + timeout
+ try:
+ port_path.touch(exist_ok=False)
+ except FileExistsError:
+ raise ValueError(
+ "Port {} already reserved by system or another kresd instance!".format(port))
+
+ while True:
+ if is_port_free(port, ip, ip6):
+ # NOTE: The port_path isn't removed, so other instances don't have to attempt to
+ # take the same port again. This has the side effect of leaving many of these
+ # files behind, because when another kresd shuts down and removes its file, the
+ # port still can't be reserved for a while. This shouldn't become an issue unless
+ # we have thousands of tests (and run out of the port range).
+ break
+
+ if time.time() < end_time:
+ time.sleep(5)
+ else:
+ raise ValueError(
+ "Port {} is reserved by system!".format(port))
+ return port
+
+
+def make_port(ip=None, ip6=None):
+ for _ in range(10): # max attempts
+ port = random.randint(KRESD_TESTPORT_MIN, KRESD_TESTPORT_MAX)
+ try:
+ take_port(port, ip, ip6)
+ except ValueError:
+ continue # port reserved by system / another kresd instance
+ return port
+ raise RuntimeError("No available port found!")
+
+
+KRESD_LOG_STARTUP_MSGID = re.compile(r'^\[{}.*'.format(KRESD_STARTUP_MSGID))
+KRESD_LOG_IO_CLOSE = re.compile(r'^\[io\].*closed by peer.*')
+
+
+@contextmanager
+def make_kresd(
+ workdir, certname=None, ip='127.0.0.1', ip6='::1', forward=None, hints=None,
+ port=None, tls_port=None):
+ with Kresd(workdir, port, tls_port, ip, ip6, certname, forward=forward, hints=hints) as kresd:
+ yield kresd
+ print(kresd.partial_log())
diff --git a/tests/pytests/pylintrc b/tests/pytests/pylintrc
new file mode 100644
index 0000000..d9cf1a1
--- /dev/null
+++ b/tests/pytests/pylintrc
@@ -0,0 +1,29 @@
+[MESSAGES CONTROL]
+
+disable=
+ missing-docstring,
+ too-many-arguments,
+ too-many-instance-attributes,
+ fixme,
+ unused-import, # checked by flake8
+ line-too-long, # checked by flake8
+ invalid-name,
+ broad-except,
+ bad-continuation,
+ global-statement,
+ no-else-return,
+ redefined-outer-name, # commonly used with pytest fixtures
+
+
+[SIMILARITIES]
+min-similarity-lines=6
+ignore-comments=yes
+ignore-docstrings=yes
+ignore-imports=no
+
+[DESIGN]
+max-parents=10
+max-locals=20
+
+[TYPECHECK]
+ignored-modules=ssl
diff --git a/tests/pytests/rehandshake/Makefile b/tests/pytests/rehandshake/Makefile
new file mode 100644
index 0000000..170b89e
--- /dev/null
+++ b/tests/pytests/rehandshake/Makefile
@@ -0,0 +1,28 @@
+CC=gcc
+CFLAGS_TLS=-DDEBUG -ggdb3 -O0 -lgnutls -luv
+CFLAGS_TCP=-DDEBUG -ggdb3 -O0 -luv
+
+all: tcproxy tlsproxy
+
+tlsproxy: tls-proxy.o tlsproxy.o
+ $(CC) tls-proxy.o tlsproxy.o -o tlsproxy $(CFLAGS_TLS)
+
+tls-proxy.o: tls-proxy.c tls-proxy.h array.h
+ $(CC) -c -o $@ $< $(CFLAGS_TLS)
+
+tlsproxy.o: tlsproxy.c tls-proxy.h
+ $(CC) -c -o $@ $< $(CFLAGS_TLS)
+
+tcproxy: tcp-proxy.o tcproxy.o
+ $(CC) tcp-proxy.o tcproxy.o -o tcproxy $(CFLAGS_TCP)
+
+tcp-proxy.o: tcp-proxy.c tcp-proxy.h array.h
+ $(CC) -c -o $@ $< $(CFLAGS_TCP)
+
+tcproxy.o: tcproxy.c tcp-proxy.h
+ $(CC) -c -o $@ $< $(CFLAGS_TCP)
+
+clean:
+ rm -f tcp-proxy.o tcproxy.o tcproxy tls-proxy.o tlsproxy.o tlsproxy
+
+.PHONY: all clean
diff --git a/tests/pytests/rehandshake/array.h b/tests/pytests/rehandshake/array.h
new file mode 100644
index 0000000..ece4dd1
--- /dev/null
+++ b/tests/pytests/rehandshake/array.h
@@ -0,0 +1,166 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/**
+ *
+ * @file array.h
+ * @brief A set of simple macros to make working with dynamic arrays easier.
+ *
+ * @note The C has no generics, so it is implemented mostly using macros.
+ * Be aware of that, as direct usage of the macros in the evaluating macros
+ * may lead to different expectations:
+ *
+ * @code{.c}
+ * MIN(array_push(arr, val), other)
+ * @endcode
+ *
+ * May evaluate the code twice, leading to unexpected behaviour.
+ * This is a price to pay for the absence of proper generics.
+ *
+ * # Example usage:
+ *
+ * @code{.c}
+ * array_t(const char*) arr;
+ * array_init(arr);
+ *
+ * // Reserve memory in advance
+ * if (array_reserve(arr, 2) < 0) {
+ * return ENOMEM;
+ * }
+ *
+ * // Already reserved, cannot fail
+ * array_push(arr, "princess");
+ * array_push(arr, "leia");
+ *
+ * // Not reserved, may fail
+ * if (array_push(arr, "han") < 0) {
+ * return ENOMEM;
+ * }
+ *
+ * // It does not hide what it really is
+ * for (size_t i = 0; i < arr.len; ++i) {
+ * printf("%s\n", arr.at[i]);
+ * }
+ *
+ * // Random delete
+ * array_del(arr, 0);
+ * @endcode
+ * \addtogroup generics
+ * @{
+ */
+
+#pragma once
+#include <stdlib.h>
+
+/** Simplified Qt containers growth strategy. */
+static inline size_t array_next_count(size_t want)
+{
+ if (want < 2048) {
+ return (want < 20) ? want + 4 : want * 2;
+ } else {
+ return want + 2048;
+ }
+}
+
+/** @internal Incremental memory reservation */
+static inline int array_std_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+{
+ if (*have >= want) {
+ return 0;
+ }
+ /* Simplified Qt containers growth strategy */
+ size_t next_size = array_next_count(want);
+ void *mem_new = realloc(*mem, next_size * elm_size);
+ if (mem_new != NULL) {
+ *mem = mem_new;
+ *have = next_size;
+ return 0;
+ }
+ return -1;
+}
+
+/** @internal Wrapper for stdlib free. */
+static inline void array_std_free(void *baton, void *p)
+{
+ free(p);
+}
+
+/** Declare an array structure. */
+#define array_t(type) struct {type * at; size_t len; size_t cap; }
+
+/** Zero-initialize the array. */
+#define array_init(array) ((array).at = NULL, (array).len = (array).cap = 0)
+
+/** Free and zero-initialize the array (plain malloc/free). */
+#define array_clear(array) \
+ array_clear_mm(array, array_std_free, NULL)
+
+/** Make the array empty and free pointed-to memory.
+ * Mempool usage: pass mm_free and a knot_mm_t* . */
+#define array_clear_mm(array, free, baton) \
+ (free)((baton), (array).at), array_init(array)
+
+/** Reserve capacity for at least n elements.
+ * @return 0 if success, <0 on failure */
+#define array_reserve(array, n) \
+ array_reserve_mm(array, n, array_std_reserve, NULL)
+
+/** Reserve capacity for at least n elements.
+ * Mempool usage: pass kr_memreserve and a knot_mm_t* .
+ * @return 0 if success, <0 on failure */
+#define array_reserve_mm(array, n, reserve, baton) \
+ (reserve)((baton), (char **) &(array).at, sizeof((array).at[0]), (n), &(array).cap)
+
+/**
+ * Push value at the end of the array, resize it if necessary.
+ * Mempool usage: pass kr_memreserve and a knot_mm_t* .
+ * @note May fail if the capacity is not reserved.
+ * @return element index on success, <0 on failure
+ */
+#define array_push_mm(array, val, reserve, baton) \
+ (int)((array).len < (array).cap ? ((array).at[(array).len] = val, (array).len++) \
+ : (array_reserve_mm(array, ((array).cap + 1), reserve, baton) < 0 ? -1 \
+ : ((array).at[(array).len] = val, (array).len++)))
+
+/**
+ * Push value at the end of the array, resize it if necessary (plain malloc/free).
+ * @note May fail if the capacity is not reserved.
+ * @return element index on success, <0 on failure
+ */
+#define array_push(array, val) \
+ array_push_mm(array, val, array_std_reserve, NULL)
+
+/**
+ * Pop value from the end of the array.
+ */
+#define array_pop(array) \
+ (array).len -= 1
+
+/**
+ * Remove value at given index.
+ * @return 0 on success, <0 on failure
+ */
+#define array_del(array, i) \
+ (int)((i) < (array).len ? ((array).len -= 1,(array).at[i] = (array).at[(array).len], 0) : -1)
+
+/**
+ * Return last element of the array.
+ * @warning Undefined if the array is empty.
+ */
+#define array_tail(array) \
+ (array).at[(array).len - 1]
+
+/** @} */
diff --git a/tests/pytests/rehandshake/tcp-proxy.c b/tests/pytests/rehandshake/tcp-proxy.c
new file mode 100644
index 0000000..ba7198b
--- /dev/null
+++ b/tests/pytests/rehandshake/tcp-proxy.c
@@ -0,0 +1,336 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <uv.h>
+#include "array.h"
+
+struct buf {
+ char buf[16 * 1024];
+ size_t size;
+};
+
+enum peer_state {
+ STATE_NOT_CONNECTED,
+ STATE_LISTENING,
+ STATE_CONNECTED,
+ STATE_CONNECT_IN_PROGRESS,
+ STATE_CLOSING_IN_PROGRESS
+};
+
+struct proxy_ctx {
+ uv_loop_t *loop;
+ uv_tcp_t server;
+ uv_tcp_t client;
+ uv_tcp_t upstream;
+ struct sockaddr_storage server_addr;
+ struct sockaddr_storage upstream_addr;
+
+ int server_state;
+ int client_state;
+ int upstream_state;
+
+ array_t(struct buf *) buffer_pool;
+ array_t(struct buf *) upstream_pending;
+};
+
+static void read_from_upstream_cb(uv_stream_t *upstream, ssize_t nread, const uv_buf_t *buf);
+static void read_from_client_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf);
+
+static struct buf *borrow_io_buffer(struct proxy_ctx *proxy)
+{
+ struct buf *buf = NULL;
+ if (proxy->buffer_pool.len > 0) {
+ buf = array_tail(proxy->buffer_pool);
+ array_pop(proxy->buffer_pool);
+ } else {
+ buf = calloc(1, sizeof (struct buf));
+ }
+ return buf;
+}
+
+static void release_io_buffer(struct proxy_ctx *proxy, struct buf *buf)
+{
+ if (!buf) {
+ return;
+ }
+
+ if (proxy->buffer_pool.len < 1000) {
+ buf->size = 0;
+ array_push(proxy->buffer_pool, buf);
+ } else {
+ free(buf);
+ }
+}
+
+static void push_to_upstream_pending(struct proxy_ctx *proxy, const char *buf, size_t size)
+{
+ while (size > 0) {
+ struct buf *b = borrow_io_buffer(proxy);
+ b->size = size <= sizeof(b->buf) ? size : sizeof(b->buf);
+ memcpy(b->buf, buf, b->size);
+ array_push(proxy->upstream_pending, b);
+ size -= b->size;
+ }
+}
+
+static struct buf *get_first_upstream_pending(struct proxy_ctx *proxy)
+{
+ struct buf *buf = NULL;
+ if (proxy->upstream_pending.len > 0) {
+ buf = proxy->upstream_pending.at[0];
+ }
+ return buf;
+}
+
+static void remove_first_upstream_pending(struct proxy_ctx *proxy)
+{
+ for (int i = 1; i < proxy->upstream_pending.len; ++i) {
+ proxy->upstream_pending.at[i - 1] = proxy->upstream_pending.at[i];
+ }
+ if (proxy->upstream_pending.len > 0) {
+ proxy->upstream_pending.len -= 1;
+ }
+}
+
+static void clear_upstream_pending(struct proxy_ctx *proxy)
+{
+ for (int i = 1; i < proxy->upstream_pending.len; ++i) {
+ struct buf *b = proxy->upstream_pending.at[i];
+ release_io_buffer(proxy, b);
+ }
+ proxy->upstream_pending.len = 0;
+}
+
+static void clear_buffer_pool(struct proxy_ctx *proxy)
+{
+ for (int i = 1; i < proxy->buffer_pool.len; ++i) {
+ struct buf *b = proxy->buffer_pool.at[i];
+ free(b);
+ }
+ proxy->buffer_pool.len = 0;
+}
+
+static void alloc_uv_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
+{
+ buf->base = (char*)malloc(suggested_size);
+ buf->len = suggested_size;
+}
+
+static void on_client_close(uv_handle_t *handle)
+{
+ struct proxy_ctx *proxy = (struct proxy_ctx *)handle->loop->data;
+ proxy->client_state = STATE_NOT_CONNECTED;
+}
+
+static void on_upstream_close(uv_handle_t *handle)
+{
+ struct proxy_ctx *proxy = (struct proxy_ctx *)handle->loop->data;
+ proxy->upstream_state = STATE_NOT_CONNECTED;
+}
+
+static void write_to_client_cb(uv_write_t *req, int status)
+{
+ struct proxy_ctx *proxy = (struct proxy_ctx *)req->handle->loop->data;
+ free(req);
+ if (status) {
+ fprintf(stderr, "error writing to client: %s\n", uv_strerror(status));
+ clear_upstream_pending(proxy);
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->client, on_client_close);
+ }
+}
+
+static void write_to_upstream_cb(uv_write_t *req, int status)
+{
+ struct proxy_ctx *proxy = (struct proxy_ctx *)req->handle->loop->data;
+ free(req);
+ if (status) {
+ fprintf(stderr, "error writing to upstream: %s\n", uv_strerror(status));
+ clear_upstream_pending(proxy);
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ return;
+ }
+ if (proxy->upstream_pending.len > 0) {
+ struct buf *buf = get_first_upstream_pending(proxy);
+ remove_first_upstream_pending(proxy);
+ release_io_buffer(proxy, buf);
+ if (proxy->upstream_state == STATE_CONNECTED &&
+ proxy->upstream_pending.len > 0) {
+ buf = get_first_upstream_pending(proxy);
+ /* TODO avoid allocation */
+ uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ uv_buf_t wrbuf = uv_buf_init(buf->buf, buf->size);
+ uv_write(req, (uv_stream_t *)&proxy->upstream, &wrbuf, 1, write_to_upstream_cb);
+ }
+ }
+}
+
+static void on_client_connection(uv_stream_t *server, int status)
+{
+ if (status < 0) {
+ fprintf(stderr, "incoming connection error: %s\n", uv_strerror(status));
+ return;
+ }
+
+ fprintf(stdout, "incoming connection\n");
+
+ struct proxy_ctx *proxy = (struct proxy_ctx *)server->loop->data;
+ if (proxy->client_state != STATE_NOT_CONNECTED) {
+ fprintf(stderr, "client already connected, ignoring\n");
+ return;
+ }
+
+ uv_tcp_init(proxy->loop, &proxy->client);
+ proxy->client_state = STATE_CONNECTED;
+ if (uv_accept(server, (uv_stream_t*)&proxy->client) == 0) {
+ uv_read_start((uv_stream_t*)&proxy->client, alloc_uv_buffer, read_from_client_cb);
+ } else {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->client, on_client_close);
+ }
+}
+
+static void on_connect_to_upstream(uv_connect_t *req, int status)
+{
+ struct proxy_ctx *proxy = (struct proxy_ctx *)req->handle->loop->data;
+ free(req);
+ if (status < 0) {
+ fprintf(stderr, "error connecting to upstream: %s\n", uv_strerror(status));
+ clear_upstream_pending(proxy);
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ return;
+ }
+
+ proxy->upstream_state = STATE_CONNECTED;
+ uv_read_start((uv_stream_t*)&proxy->upstream, alloc_uv_buffer, read_from_upstream_cb);
+ if (proxy->upstream_pending.len > 0) {
+ struct buf *buf = get_first_upstream_pending(proxy);
+ /* TODO avoid allocation */
+ uv_write_t *wreq = (uv_write_t *) malloc(sizeof(uv_write_t));
+ uv_buf_t wrbuf = uv_buf_init(buf->buf, buf->size);
+ uv_write(wreq, (uv_stream_t *)&proxy->upstream, &wrbuf, 1, write_to_upstream_cb);
+ }
+}
+
+static void read_from_client_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
+{
+ if (nread == 0) {
+ return;
+ }
+ struct proxy_ctx *proxy = (struct proxy_ctx *)client->loop->data;
+ if (nread < 0) {
+ if (nread != UV_EOF) {
+ fprintf(stderr, "error reading from client: %s\n", uv_err_name(nread));
+ }
+ if (proxy->client_state == STATE_CONNECTED) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*) client, on_client_close);
+ }
+ return;
+ }
+ if (proxy->upstream_state == STATE_CONNECTED) {
+ if (proxy->upstream_pending.len > 0) {
+ push_to_upstream_pending(proxy, buf->base, nread);
+ } else {
+ /* TODO avoid allocation */
+ uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ uv_buf_t wrbuf = uv_buf_init(buf->base, nread);
+ uv_write(req, (uv_stream_t *)&proxy->upstream, &wrbuf, 1, write_to_upstream_cb);
+ }
+ } else if (proxy->upstream_state == STATE_NOT_CONNECTED) {
+ /* TODO avoid allocation */
+ uv_tcp_init(proxy->loop, &proxy->upstream);
+ uv_connect_t *conn = (uv_connect_t *) malloc(sizeof(uv_connect_t));
+ proxy->upstream_state = STATE_CONNECT_IN_PROGRESS;
+ uv_tcp_connect(conn, &proxy->upstream, (struct sockaddr *)&proxy->upstream_addr,
+ on_connect_to_upstream);
+ push_to_upstream_pending(proxy, buf->base, nread);
+ } else if (proxy->upstream_state == STATE_CONNECT_IN_PROGRESS) {
+ push_to_upstream_pending(proxy, buf->base, nread);
+ }
+}
+
+static void read_from_upstream_cb(uv_stream_t *upstream, ssize_t nread, const uv_buf_t *buf)
+{
+ if (nread == 0) {
+ return;
+ }
+ struct proxy_ctx *proxy = (struct proxy_ctx *)upstream->loop->data;
+ if (nread < 0) {
+ if (nread != UV_EOF) {
+ fprintf(stderr, "error reading from upstream: %s\n", uv_err_name(nread));
+ }
+ clear_upstream_pending(proxy);
+ if (proxy->upstream_state == STATE_CONNECTED) {
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ }
+ return;
+ }
+ if (proxy->client_state == STATE_CONNECTED) {
+ /* TODO Avoid allocation */
+ uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ uv_buf_t wrbuf = uv_buf_init(buf->base, nread);
+ uv_write(req, (uv_stream_t *)&proxy->client, &wrbuf, 1, write_to_client_cb);
+ }
+}
+
+struct proxy_ctx *proxy_allocate()
+{
+ return malloc(sizeof(struct proxy_ctx));
+}
+
+int proxy_init(struct proxy_ctx *proxy,
+ const char *server_addr, int server_port,
+ const char *upstream_addr, int upstream_port)
+{
+ proxy->loop = uv_default_loop();
+ uv_tcp_init(proxy->loop, &proxy->server);
+ int res = uv_ip4_addr(server_addr, server_port, (struct sockaddr_in *)&proxy->server_addr);
+ if (res != 0) {
+ return res;
+ }
+ res = uv_ip4_addr(upstream_addr, upstream_port, (struct sockaddr_in *)&proxy->upstream_addr);
+ if (res != 0) {
+ return res;
+ }
+ array_init(proxy->buffer_pool);
+ array_init(proxy->upstream_pending);
+ proxy->server_state = STATE_NOT_CONNECTED;
+ proxy->client_state = STATE_NOT_CONNECTED;
+ proxy->upstream_state = STATE_NOT_CONNECTED;
+
+ proxy->loop->data = proxy;
+ return 0;
+}
+
+void proxy_free(struct proxy_ctx *proxy)
+{
+ if (!proxy) {
+ return;
+ }
+ clear_upstream_pending(proxy);
+ clear_buffer_pool(proxy);
+ /* TODO correctly close all the uv_tcp_t */
+ free(proxy);
+}
+
+int proxy_start_listen(struct proxy_ctx *proxy)
+{
+ uv_tcp_bind(&proxy->server, (const struct sockaddr*)&proxy->server_addr, 0);
+ int ret = uv_listen((uv_stream_t*)&proxy->server, 128, on_client_connection);
+ if (ret == 0) {
+ proxy->server_state = STATE_LISTENING;
+ }
+ return ret;
+}
+
+int proxy_run(struct proxy_ctx *proxy)
+{
+ return uv_run(proxy->loop, UV_RUN_DEFAULT);
+}
diff --git a/tests/pytests/rehandshake/tcp-proxy.h b/tests/pytests/rehandshake/tcp-proxy.h
new file mode 100644
index 0000000..668a65f
--- /dev/null
+++ b/tests/pytests/rehandshake/tcp-proxy.h
@@ -0,0 +1,12 @@
+#pragma once
+
+struct proxy_ctx;
+
+struct proxy_ctx *proxy_allocate();
+void proxy_free(struct proxy_ctx *proxy);
+int proxy_init(struct proxy_ctx *proxy,
+ const char *server_addr, int server_port,
+ const char *upstream_addr, int upstream_port);
+int proxy_start_listen(struct proxy_ctx *proxy);
+int proxy_run(struct proxy_ctx *proxy);
+
diff --git a/tests/pytests/rehandshake/tcproxy.c b/tests/pytests/rehandshake/tcproxy.c
new file mode 100644
index 0000000..87a6b4c
--- /dev/null
+++ b/tests/pytests/rehandshake/tcproxy.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include "tcp-proxy.h"
+
+int main()
+{
+ struct proxy_ctx *proxy = proxy_allocate();
+ if (!proxy) {
+ fprintf(stderr, "can't allocate proxy structure\n");
+ return 1;
+ }
+ int res = proxy_init(proxy, "127.0.0.1", 54000, "127.0.0.1", 53001);
+ if (res) {
+ fprintf(stderr, "can't initialize proxy by given addresses\n");
+ return res;
+ }
+ res = proxy_start_listen(proxy);
+ if (res) {
+ fprintf(stderr, "error starting listen, error code: %i\n", res);
+ return res;
+ }
+ res = proxy_run(proxy);
+ proxy_free(proxy);
+ return res;
+}
+
diff --git a/tests/pytests/rehandshake/tls-proxy.c b/tests/pytests/rehandshake/tls-proxy.c
new file mode 100644
index 0000000..bf6cc0d
--- /dev/null
+++ b/tests/pytests/rehandshake/tls-proxy.c
@@ -0,0 +1,848 @@
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <gnutls/gnutls.h>
+#include <uv.h>
+#include "array.h"
+
+#define TLS_MAX_SEND_RETRIES 100
+#define CLIENT_ANSWER_CHUNK_SIZE 8
+struct buf {
+ char buf[16 * 1024];
+ size_t size;
+};
+
+enum peer_state {
+ STATE_NOT_CONNECTED,
+ STATE_LISTENING,
+ STATE_CONNECTED,
+ STATE_CONNECT_IN_PROGRESS,
+ STATE_CLOSING_IN_PROGRESS
+};
+
+enum handshake_state {
+ TLS_HS_NOT_STARTED = 0,
+ TLS_HS_EXPECTED,
+ TLS_HS_IN_PROGRESS,
+ TLS_HS_DONE,
+ TLS_HS_CLOSING,
+ TLS_HS_LAST
+};
+
+struct tls_ctx {
+ gnutls_session_t session;
+ int handshake_state;
+ gnutls_certificate_credentials_t credentials;
+ gnutls_priority_t priority_cache;
+ /* for reading from the network */
+ const uint8_t *buf;
+ ssize_t nread;
+ ssize_t consumed;
+ uint8_t recv_buf[4096];
+};
+
+struct tls_proxy_ctx {
+ uv_loop_t *loop;
+ uv_tcp_t server;
+ uv_tcp_t client;
+ uv_tcp_t upstream;
+ struct sockaddr_storage server_addr;
+ struct sockaddr_storage upstream_addr;
+ struct sockaddr_storage client_addr;
+
+ int server_state;
+ int client_state;
+ int upstream_state;
+
+ array_t(struct buf *) buffer_pool;
+ array_t(struct buf *) upstream_pending;
+ array_t(struct buf *) client_pending;
+
+ char io_buf[0xFFFF];
+ struct tls_ctx tls;
+};
+
+static void read_from_upstream_cb(uv_stream_t *upstream, ssize_t nread, const uv_buf_t *buf);
+static void read_from_client_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf);
+static ssize_t proxy_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len);
+static ssize_t proxy_gnutls_push(gnutls_transport_ptr_t h, const void *buf, size_t len);
+static int tls_process_from_upstream(struct tls_proxy_ctx *proxy, const uint8_t *buf, ssize_t nread);
+static int tls_process_from_client(struct tls_proxy_ctx *proxy, const uint8_t *buf, ssize_t nread);
+static int write_to_upstream_pending(struct tls_proxy_ctx *proxy);
+static int write_to_client_pending(struct tls_proxy_ctx *proxy);
+
+
+static int gnutls_references = 0;
+
+const void *ip_addr(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return NULL;
+ }
+ switch (addr->sa_family) {
+ case AF_INET: return (const void *)&(((const struct sockaddr_in *)addr)->sin_addr);
+ case AF_INET6: return (const void *)&(((const struct sockaddr_in6 *)addr)->sin6_addr);
+ default: return NULL;
+ }
+}
+
+uint16_t ip_addr_port(const struct sockaddr *addr)
+{
+ if (!addr) {
+ return 0;
+ }
+ switch (addr->sa_family) {
+ case AF_INET: return ntohs(((const struct sockaddr_in *)addr)->sin_port);
+ case AF_INET6: return ntohs(((const struct sockaddr_in6 *)addr)->sin6_port);
+ default: return 0;
+ }
+}
+
+static int ip_addr_str(const struct sockaddr *addr, char *buf, size_t *buflen)
+{
+ int ret = 0;
+ if (!addr || !buf || !buflen) {
+ return EINVAL;
+ }
+
+ char str[INET6_ADDRSTRLEN + 6];
+ if (!inet_ntop(addr->sa_family, ip_addr(addr), str, sizeof(str))) {
+ return errno;
+ }
+ int len = strlen(str);
+ str[len] = '#';
+ snprintf(&str[len + 1], 6, "%uh", ip_addr_port(addr));
+ len += 6;
+ str[len] = 0;
+ if (len >= *buflen) {
+ ret = ENOSPC;
+ } else {
+ memcpy(buf, str, len + 1);
+ }
+ *buflen = len;
+ return ret;
+}
+
+static inline char *ip_straddr(const struct sockaddr *addr)
+{
+ assert(addr != NULL);
+ /* We are the sinle-threaded application */
+ static char str[INET6_ADDRSTRLEN + 6];
+ size_t len = sizeof(str);
+ int ret = ip_addr_str(addr, str, &len);
+ return ret != 0 || len == 0 ? NULL : str;
+}
+
+static struct buf *borrow_io_buffer(struct tls_proxy_ctx *proxy)
+{
+ struct buf *buf = NULL;
+ if (proxy->buffer_pool.len > 0) {
+ buf = array_tail(proxy->buffer_pool);
+ array_pop(proxy->buffer_pool);
+ } else {
+ buf = calloc(1, sizeof (struct buf));
+ }
+ return buf;
+}
+
+static void release_io_buffer(struct tls_proxy_ctx *proxy, struct buf *buf)
+{
+ if (!buf) {
+ return;
+ }
+
+ if (proxy->buffer_pool.len < 1000) {
+ buf->size = 0;
+ array_push(proxy->buffer_pool, buf);
+ } else {
+ free(buf);
+ }
+}
+
+static struct buf *get_first_upstream_pending(struct tls_proxy_ctx *proxy)
+{
+ struct buf *buf = NULL;
+ if (proxy->upstream_pending.len > 0) {
+ buf = proxy->upstream_pending.at[0];
+ }
+ return buf;
+}
+
+static struct buf *get_first_client_pending(struct tls_proxy_ctx *proxy)
+{
+ struct buf *buf = NULL;
+ if (proxy->client_pending.len > 0) {
+ buf = proxy->client_pending.at[0];
+ }
+ return buf;
+}
+
+static void remove_first_upstream_pending(struct tls_proxy_ctx *proxy)
+{
+ for (int i = 1; i < proxy->upstream_pending.len; ++i) {
+ proxy->upstream_pending.at[i - 1] = proxy->upstream_pending.at[i];
+ }
+ if (proxy->upstream_pending.len > 0) {
+ proxy->upstream_pending.len -= 1;
+ }
+}
+
+static void remove_first_client_pending(struct tls_proxy_ctx *proxy)
+{
+ for (int i = 1; i < proxy->client_pending.len; ++i) {
+ proxy->client_pending.at[i - 1] = proxy->client_pending.at[i];
+ }
+ if (proxy->client_pending.len > 0) {
+ proxy->client_pending.len -= 1;
+ }
+}
+
+static void clear_upstream_pending(struct tls_proxy_ctx *proxy)
+{
+ for (int i = 0; i < proxy->upstream_pending.len; ++i) {
+ struct buf *b = proxy->upstream_pending.at[i];
+ release_io_buffer(proxy, b);
+ }
+ proxy->upstream_pending.len = 0;
+}
+
+static void clear_client_pending(struct tls_proxy_ctx *proxy)
+{
+ for (int i = 0; i < proxy->client_pending.len; ++i) {
+ struct buf *b = proxy->client_pending.at[i];
+ release_io_buffer(proxy, b);
+ }
+ proxy->client_pending.len = 0;
+}
+
+static void clear_buffer_pool(struct tls_proxy_ctx *proxy)
+{
+ for (int i = 0; i < proxy->buffer_pool.len; ++i) {
+ struct buf *b = proxy->buffer_pool.at[i];
+ free(b);
+ }
+ proxy->buffer_pool.len = 0;
+}
+
+static void alloc_uv_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)handle->loop->data;
+ buf->base = proxy->io_buf;
+ buf->len = sizeof(proxy->io_buf);
+}
+
+static void on_client_close(uv_handle_t *handle)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)handle->loop->data;
+ gnutls_deinit(proxy->tls.session);
+ proxy->tls.handshake_state = TLS_HS_NOT_STARTED;
+ proxy->client_state = STATE_NOT_CONNECTED;
+}
+
+static void on_dummmy_client_close(uv_handle_t *handle)
+{
+ free(handle);
+}
+
+static void on_upstream_close(uv_handle_t *handle)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)handle->loop->data;
+ proxy->upstream_state = STATE_NOT_CONNECTED;
+}
+
+static void write_to_client_cb(uv_write_t *req, int status)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)req->handle->loop->data;
+ free(req);
+ if (status) {
+ fprintf(stderr, "error writing to client: %s\n", uv_strerror(status));
+ clear_client_pending(proxy);
+ clear_upstream_pending(proxy);
+ if (proxy->client_state == STATE_CONNECTED) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->client, on_client_close);
+ return;
+ }
+ }
+ fprintf(stdout, "successfully wrote to client, pending len is %zd\n",
+ proxy->client_pending.len);
+ if (proxy->client_state == STATE_CONNECTED &&
+ proxy->tls.handshake_state == TLS_HS_DONE) {
+ write_to_client_pending(proxy);
+ }
+}
+
+static void write_to_upstream_cb(uv_write_t *req, int status)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)req->handle->loop->data;
+ if (status) {
+ free(req);
+ fprintf(stderr, "error writing to upstream: %s\n", uv_strerror(status));
+ clear_upstream_pending(proxy);
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ return;
+ }
+ if (req->data != NULL) {
+ assert(proxy->upstream_pending.len > 0);
+ struct buf *buf = get_first_upstream_pending(proxy);
+ assert(req->data == (void *)buf->buf);
+ fprintf(stdout, "successfully wrote %zi bytes to upstream, pending len is %zd\n",
+ buf->size, proxy->upstream_pending.len);
+ remove_first_upstream_pending(proxy);
+ release_io_buffer(proxy, buf);
+ } else {
+ fprintf(stdout, "successfully wrote bytes to upstream, pending len is %zd\n",
+ proxy->upstream_pending.len);
+ }
+ if (proxy->upstream_state == STATE_CONNECTED &&
+ proxy->upstream_pending.len > 0) {
+ write_to_upstream_pending(proxy);
+ }
+ free(req);
+}
+
+static void on_client_connection(uv_stream_t *server, int status)
+{
+ if (status < 0) {
+ fprintf(stderr, "incoming connection error: %s\n", uv_strerror(status));
+ return;
+ }
+
+ int err = 0;
+ int ret = 0;
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)server->loop->data;
+ if (proxy->client_state != STATE_NOT_CONNECTED) {
+ fprintf(stderr, "incoming connection");
+ uv_tcp_t *dummy_client = malloc(sizeof(uv_tcp_t));
+ uv_tcp_init(proxy->loop, dummy_client);
+ err = uv_accept(server, (uv_stream_t*)dummy_client);
+ if (err == 0) {
+ struct sockaddr dummy_addr;
+ int dummy_addr_len = sizeof(dummy_addr);
+ ret = uv_tcp_getpeername(dummy_client,
+ &dummy_addr,
+ &dummy_addr_len);
+ if (ret == 0) {
+ fprintf(stderr, " from %s", ip_straddr(&dummy_addr));
+ }
+ uv_close((uv_handle_t *)dummy_client, on_dummmy_client_close);
+ } else {
+ on_dummmy_client_close((uv_handle_t *)dummy_client);
+ }
+ fprintf(stderr, " - client already connected, rejecting\n");
+ return;
+ }
+
+ uv_tcp_init(proxy->loop, &proxy->client);
+ uv_tcp_nodelay((uv_tcp_t *)&proxy->client, 1);
+ proxy->client_state = STATE_CONNECTED;
+ err = uv_accept(server, (uv_stream_t*)&proxy->client);
+ if (err != 0) {
+ fprintf(stderr, "incoming connection - uv_accept() failed: (%d) %s\n",
+ err, uv_strerror(err));
+ return;
+ }
+
+ struct sockaddr *addr = (struct sockaddr *)&(proxy->client_addr);
+ int addr_len = sizeof(proxy->client_addr);
+ ret = uv_tcp_getpeername(&proxy->client, addr, &addr_len);
+ if (ret || addr->sa_family == AF_UNSPEC) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->client, on_client_close);
+ fprintf(stderr, "incoming connection - uv_tcp_getpeername() failed: (%d) %s\n",
+ err, uv_strerror(err));
+ return;
+ }
+
+ fprintf(stdout, "incoming connection from %s\n", ip_straddr(addr));
+
+ uv_read_start((uv_stream_t*)&proxy->client, alloc_uv_buffer, read_from_client_cb);
+
+ const char *errpos = NULL;
+ struct tls_ctx *tls = &proxy->tls;
+ assert (tls->handshake_state == TLS_HS_NOT_STARTED);
+ err = gnutls_init(&tls->session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_init() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ }
+ err = gnutls_priority_set(tls->session, tls->priority_cache);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_priority_set() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ }
+ err = gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, tls->credentials);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_credentials_set() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ }
+ gnutls_certificate_server_set_request(tls->session, GNUTLS_CERT_IGNORE);
+ gnutls_handshake_set_timeout(tls->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
+
+ gnutls_transport_set_pull_function(tls->session, proxy_gnutls_pull);
+ gnutls_transport_set_push_function(tls->session, proxy_gnutls_push);
+ gnutls_transport_set_ptr(tls->session, proxy);
+
+ tls->handshake_state = TLS_HS_IN_PROGRESS;
+}
+
+static void on_connect_to_upstream(uv_connect_t *req, int status)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)req->handle->loop->data;
+ free(req);
+ if (status < 0) {
+ fprintf(stderr, "error connecting to upstream (%s): %s\n",
+ ip_straddr((struct sockaddr *)&proxy->upstream_addr),
+ uv_strerror(status));
+ clear_upstream_pending(proxy);
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ return;
+ }
+ fprintf(stdout, "connected to %s\n", ip_straddr((struct sockaddr *)&proxy->upstream_addr));
+
+ proxy->upstream_state = STATE_CONNECTED;
+ uv_read_start((uv_stream_t*)&proxy->upstream, alloc_uv_buffer, read_from_upstream_cb);
+ if (proxy->upstream_pending.len > 0) {
+ write_to_upstream_pending(proxy);
+ }
+}
+
+static void read_from_client_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
+{
+ fprintf(stdout, "reading %zd bytes from client\n", nread);
+ if (nread == 0) {
+ return;
+ }
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)client->loop->data;
+ if (nread < 0) {
+ if (nread != UV_EOF) {
+ fprintf(stderr, "error reading from client: %s\n", uv_err_name(nread));
+ } else {
+ fprintf(stdout, "client has closed the connection\n");
+ }
+ if (proxy->client_state == STATE_CONNECTED) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*) client, on_client_close);
+ }
+ return;
+ }
+
+ int res = tls_process_from_client(proxy, buf->base, nread);
+ if (res < 0) {
+ if (proxy->client_state == STATE_CONNECTED) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*) client, on_client_close);
+ }
+ }
+}
+
+static void read_from_upstream_cb(uv_stream_t *upstream, ssize_t nread, const uv_buf_t *buf)
+{
+ fprintf(stdout, "reading %zd bytes from upstream\n", nread);
+ if (nread == 0) {
+ return;
+ }
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)upstream->loop->data;
+ if (nread < 0) {
+ if (nread != UV_EOF) {
+ fprintf(stderr, "error reading from upstream: %s\n", uv_err_name(nread));
+ } else {
+ fprintf(stdout, "upstream has closed the connection\n");
+ }
+ clear_upstream_pending(proxy);
+ if (proxy->upstream_state == STATE_CONNECTED) {
+ proxy->upstream_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->upstream, on_upstream_close);
+ }
+ return;
+ }
+ int res = tls_process_from_upstream(proxy, buf->base, nread);
+ if (res < 0) {
+ fprintf(stderr, "error sending tls data to client\n");
+ if (proxy->client_state == STATE_CONNECTED) {
+ proxy->client_state = STATE_CLOSING_IN_PROGRESS;
+ uv_close((uv_handle_t*)&proxy->client, on_client_close);
+ }
+ }
+}
+
+static void push_to_upstream_pending(struct tls_proxy_ctx *proxy, const char *buf, size_t size)
+{
+ while (size > 0) {
+ struct buf *b = borrow_io_buffer(proxy);
+ b->size = size <= sizeof(b->buf) ? size : sizeof(b->buf);
+ memcpy(b->buf, buf, b->size);
+ array_push(proxy->upstream_pending, b);
+ size -= b->size;
+ buf += b->size;
+ }
+}
+
+static void push_to_client_pending(struct tls_proxy_ctx *proxy, const char *buf, size_t size)
+{
+ while (size > 0) {
+ struct buf *b = borrow_io_buffer(proxy);
+ b->size = size <= sizeof(b->buf) ? size : sizeof(b->buf);
+ if (b->size > CLIENT_ANSWER_CHUNK_SIZE) {
+ b->size = CLIENT_ANSWER_CHUNK_SIZE;
+ }
+ memcpy(b->buf, buf, b->size);
+ array_push(proxy->client_pending, b);
+ size -= b->size;
+ buf += b->size;
+ }
+}
+
+static int write_to_upstream_pending(struct tls_proxy_ctx *proxy)
+{
+ struct buf *buf = get_first_upstream_pending(proxy);
+ /* TODO avoid allocation */
+ uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ uv_buf_t wrbuf = uv_buf_init(buf->buf, buf->size);
+ req->data = buf->buf;
+ fprintf(stdout, "writing %zd bytes to upstream\n", buf->size);
+ return uv_write(req, (uv_stream_t *)&proxy->upstream, &wrbuf, 1, write_to_upstream_cb);
+}
+
+static ssize_t proxy_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)h;
+ struct tls_ctx *t = &proxy->tls;
+
+ fprintf(stdout, "\t gnutls: pulling %zd bytes from client\n", len);
+
+ if (t->nread <= t->consumed) {
+ errno = EAGAIN;
+ fprintf(stdout, "\t gnutls: return EAGAIN\n");
+ return -1;
+ }
+
+ ssize_t avail = t->nread - t->consumed;
+ ssize_t transfer = (avail <= len ? avail : len);
+ memcpy(buf, t->buf + t->consumed, transfer);
+ t->consumed += transfer;
+ return transfer;
+}
+
+ssize_t proxy_gnutls_push(gnutls_transport_ptr_t h, const void *buf, size_t len)
+{
+ struct tls_proxy_ctx *proxy = (struct tls_proxy_ctx *)h;
+ struct tls_ctx *t = &proxy->tls;
+ fprintf(stdout, "\t gnutls: writing %zd bytes to client\n", len);
+
+ ssize_t ret = -1;
+ const size_t req_size_aligned = ((sizeof(uv_write_t) / 16) + 1) * 16;
+ char *common_buf = malloc(req_size_aligned + len);
+ uv_write_t *req = (uv_write_t *) common_buf;
+ char *data = common_buf + req_size_aligned;
+ const uv_buf_t uv_buf[1] = {
+ { data, len }
+ };
+ memcpy(data, buf, len);
+ req->data = data;
+ int res = uv_write(req, (uv_stream_t *)&proxy->client, uv_buf, 1, write_to_client_cb);
+ if (res == 0) {
+ ret = len;
+ } else {
+ free(common_buf);
+ errno = EIO;
+ }
+ return ret;
+}
+
+static int write_to_client_pending(struct tls_proxy_ctx *proxy)
+{
+ if (proxy->client_pending.len == 0) {
+ return 0;
+ }
+
+ struct buf *buf = get_first_client_pending(proxy);
+ uv_buf_t wrbuf = uv_buf_init(buf->buf, buf->size);
+ fprintf(stdout, "writing %zd bytes to client\n", buf->size);
+
+ gnutls_session_t tls_session = proxy->tls.session;
+ assert(proxy->tls.handshake_state != TLS_HS_IN_PROGRESS);
+ assert(gnutls_record_check_corked(tls_session) == 0);
+
+ char *data = buf->buf;
+ size_t len = buf->size;
+
+ ssize_t count = 0;
+ ssize_t submitted = len;
+ ssize_t retries = 0;
+ do {
+ count = gnutls_record_send(tls_session, data, len);
+ if (count < 0) {
+ if (gnutls_error_is_fatal(count)) {
+ fprintf(stderr, "gnutls_record_send failed: %s (%zd)\n",
+ gnutls_strerror_name(count), count);
+ return -1;
+ }
+ if (++retries > TLS_MAX_SEND_RETRIES) {
+ fprintf(stderr, "gnutls_record_send: too many sequential non-fatal errors (%zd), last error is: %s (%zd)\n",
+ retries, gnutls_strerror_name(count), count);
+ return -1;
+ }
+ } else if (count != 0) {
+ data += count;
+ len -= count;
+ retries = 0;
+ } else {
+ if (++retries < TLS_MAX_SEND_RETRIES) {
+ continue;
+ }
+ fprintf(stderr, "gnutls_record_send: too many retries (%zd)\n",
+ retries);
+ fprintf(stderr, "tls_push_to_client didn't send all data(%zd of %zd)\n",
+ len, submitted);
+ return -1;
+ }
+ } while (len > 0);
+
+ remove_first_client_pending(proxy);
+ release_io_buffer(proxy, buf);
+
+ fprintf(stdout, "submitted %zd bytes to client\n", submitted);
+ assert (gnutls_safe_renegotiation_status(tls_session) != 0);
+ assert (gnutls_rehandshake(tls_session) == GNUTLS_E_SUCCESS);
+ /* Prevent write-to-client callback from sending next pending chunk.
+ * At the same time tls_process_from_client() must not call gnutls_handshake()
+ * as there can be application data in this direction. */
+ proxy->tls.handshake_state = TLS_HS_EXPECTED;
+ fprintf(stdout, "rehandshake started\n");
+ return submitted;
+}
+
+static int tls_process_from_upstream(struct tls_proxy_ctx *proxy, const uint8_t *buf, ssize_t len)
+{
+ gnutls_session_t tls_session = proxy->tls.session;
+
+ fprintf(stdout, "pushing %zd bytes to client\n", len);
+
+ assert(gnutls_record_check_corked(tls_session) == 0);
+ ssize_t submitted = 0;
+ if (proxy->client_state != STATE_CONNECTED) {
+ return submitted;
+ }
+
+ bool list_was_empty = (proxy->client_pending.len == 0);
+ push_to_client_pending(proxy, buf, len);
+ submitted = len;
+ if (proxy->tls.handshake_state == TLS_HS_DONE) {
+ if (list_was_empty && proxy->client_pending.len > 0) {
+ int ret = write_to_client_pending(proxy);
+ if (ret < 0) {
+ submitted = -1;
+ }
+ }
+ }
+
+ return submitted;
+}
+
+int tls_process_handshake(struct tls_proxy_ctx *proxy)
+{
+ struct tls_ctx *tls = &proxy->tls;
+ int ret = 1;
+ while (tls->handshake_state == TLS_HS_IN_PROGRESS) {
+ fprintf(stdout, "TLS handshake in progress...\n");
+ int err = gnutls_handshake(tls->session);
+ if (err == GNUTLS_E_SUCCESS) {
+ tls->handshake_state = TLS_HS_DONE;
+ fprintf(stdout, "TLS handshake has completed\n");
+ ret = 1;
+ if (proxy->client_pending.len != 0) {
+ write_to_client_pending(proxy);
+ }
+ } else if (gnutls_error_is_fatal(err)) {
+ fprintf(stderr, "gnutls_handshake failed: %s (%d)\n",
+ gnutls_strerror_name(err), err);
+ ret = -1;
+ break;
+ } else {
+ fprintf(stderr, "gnutls_handshake nonfatal error: %s (%d)\n",
+ gnutls_strerror_name(err), err);
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+int tls_process_from_client(struct tls_proxy_ctx *proxy, const uint8_t *buf, ssize_t nread)
+{
+ struct tls_ctx *tls = &proxy->tls;
+
+ tls->buf = buf;
+ tls->nread = nread >= 0 ? nread : 0;
+ tls->consumed = 0;
+
+ fprintf(stdout, "tls_process: reading %zd bytes from client\n", nread);
+
+ int ret = tls_process_handshake(proxy);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ int submitted = 0;
+ while (true) {
+ ssize_t count = 0;
+ count = gnutls_record_recv(tls->session, tls->recv_buf, sizeof(tls->recv_buf));
+ if (count == GNUTLS_E_AGAIN) {
+ break; /* No data available */
+ } else if (count == GNUTLS_E_INTERRUPTED) {
+ continue; /* Try reading again */
+ } else if (count == GNUTLS_E_REHANDSHAKE) {
+ tls->handshake_state = TLS_HS_IN_PROGRESS;
+ ret = tls_process_handshake(proxy);
+ if (ret <= 0) {
+ return ret;
+ }
+ continue;
+ } else if (count < 0) {
+ fprintf(stderr, "gnutls_record_recv failed: %s (%zd)\n",
+ gnutls_strerror_name(count), count);
+ return -1;
+ } else if (count == 0) {
+ break;
+ }
+ if (proxy->upstream_state == STATE_CONNECTED) {
+ bool upstream_pending_is_empty = (proxy->upstream_pending.len == 0);
+ push_to_upstream_pending(proxy, tls->recv_buf, count);
+ if (upstream_pending_is_empty) {
+ write_to_upstream_pending(proxy);
+ }
+ } else if (proxy->upstream_state == STATE_NOT_CONNECTED) {
+ /* TODO avoid allocation */
+ uv_tcp_init(proxy->loop, &proxy->upstream);
+ uv_connect_t *conn = (uv_connect_t *) malloc(sizeof(uv_connect_t));
+ proxy->upstream_state = STATE_CONNECT_IN_PROGRESS;
+ fprintf(stdout, "connecting to %s\n",
+ ip_straddr((struct sockaddr *)&proxy->upstream_addr));
+ uv_tcp_connect(conn, &proxy->upstream, (struct sockaddr *)&proxy->upstream_addr,
+ on_connect_to_upstream);
+ push_to_upstream_pending(proxy, tls->recv_buf, count);
+ } else if (proxy->upstream_state == STATE_CONNECT_IN_PROGRESS) {
+ push_to_upstream_pending(proxy, tls->recv_buf, count);
+ }
+ submitted += count;
+ }
+ return submitted;
+}
+
+struct tls_proxy_ctx *tls_proxy_allocate()
+{
+ return malloc(sizeof(struct tls_proxy_ctx));
+}
+
+int tls_proxy_init(struct tls_proxy_ctx *proxy,
+ const char *server_addr, int server_port,
+ const char *upstream_addr, int upstream_port,
+ const char *cert_file, const char *key_file)
+{
+ proxy->loop = uv_default_loop();
+ uv_tcp_init(proxy->loop, &proxy->server);
+ int res = uv_ip4_addr(server_addr, server_port, (struct sockaddr_in *)&proxy->server_addr);
+ if (res != 0) {
+ fprintf(stderr, "uv_ip4_addr failed with string '%s'\n", server_addr);
+ return -1;
+ }
+ res = uv_ip4_addr(upstream_addr, upstream_port, (struct sockaddr_in *)&proxy->upstream_addr);
+ if (res != 0) {
+ fprintf(stderr, "uv_ip4_addr failed with string '%s'\n", upstream_addr);
+ return -1;
+ }
+ array_init(proxy->buffer_pool);
+ array_init(proxy->upstream_pending);
+ array_init(proxy->client_pending);
+ proxy->server_state = STATE_NOT_CONNECTED;
+ proxy->client_state = STATE_NOT_CONNECTED;
+ proxy->upstream_state = STATE_NOT_CONNECTED;
+
+ proxy->loop->data = proxy;
+
+ int err = 0;
+ if (gnutls_references == 0) {
+ err = gnutls_global_init();
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_global_init() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ return -1;
+ }
+ }
+ gnutls_references += 1;
+
+ err = gnutls_certificate_allocate_credentials(&proxy->tls.credentials);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_certificate_allocate_credentials() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ return -1;
+ }
+
+ err = gnutls_certificate_set_x509_system_trust(proxy->tls.credentials);
+ if (err <= 0) {
+ fprintf(stderr, "gnutls_certificate_set_x509_system_trust() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ return -1;
+ }
+
+ if (cert_file && key_file) {
+ err = gnutls_certificate_set_x509_key_file(proxy->tls.credentials,
+ cert_file, key_file, GNUTLS_X509_FMT_PEM);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_certificate_set_x509_key_file() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ return -1;
+ }
+ }
+
+ err = gnutls_priority_init(&proxy->tls.priority_cache, NULL, NULL);
+ if (err != GNUTLS_E_SUCCESS) {
+ fprintf(stderr, "gnutls_priority_init() failed: (%d) %s\n",
+ err, gnutls_strerror_name(err));
+ return -1;
+ }
+
+
+ proxy->tls.handshake_state = TLS_HS_NOT_STARTED;
+ return 0;
+}
+
+void tls_proxy_free(struct tls_proxy_ctx *proxy)
+{
+ if (!proxy) {
+ return;
+ }
+ clear_upstream_pending(proxy);
+ clear_client_pending(proxy);
+ clear_buffer_pool(proxy);
+ gnutls_certificate_free_credentials(proxy->tls.credentials);
+ gnutls_priority_deinit(proxy->tls.priority_cache);
+ /* TODO correctly close all the uv_tcp_t */
+ free(proxy);
+
+ gnutls_references -= 1;
+ if (gnutls_references == 0) {
+ gnutls_global_deinit();
+ }
+}
+
+int tls_proxy_start_listen(struct tls_proxy_ctx *proxy)
+{
+ uv_tcp_bind(&proxy->server, (const struct sockaddr*)&proxy->server_addr, 0);
+ int ret = uv_listen((uv_stream_t*)&proxy->server, 128, on_client_connection);
+ if (ret == 0) {
+ proxy->server_state = STATE_LISTENING;
+ }
+ return ret;
+}
+
+int tls_proxy_run(struct tls_proxy_ctx *proxy)
+{
+ return uv_run(proxy->loop, UV_RUN_DEFAULT);
+}
diff --git a/tests/pytests/rehandshake/tls-proxy.h b/tests/pytests/rehandshake/tls-proxy.h
new file mode 100644
index 0000000..1204eda
--- /dev/null
+++ b/tests/pytests/rehandshake/tls-proxy.h
@@ -0,0 +1,14 @@
+#pragma once
+
+struct tls_proxy_ctx;
+
+struct tls_proxy_ctx *tls_proxy_allocate();
+void tls_proxy_free(struct tls_proxy_ctx *proxy);
+int tls_proxy_init(struct tls_proxy_ctx *proxy,
+ const char *server_addr, int server_port,
+ const char *upstream_addr, int upstream_port,
+ const char *cert_file, const char *key_file);
+int tls_proxy_start_listen(struct tls_proxy_ctx *proxy);
+int tls_proxy_run(struct tls_proxy_ctx *proxy);
+
+
diff --git a/tests/pytests/rehandshake/tlsproxy.c b/tests/pytests/rehandshake/tlsproxy.c
new file mode 100644
index 0000000..0c074f1
--- /dev/null
+++ b/tests/pytests/rehandshake/tlsproxy.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "tls-proxy.h"
+#include <gnutls/gnutls.h>
+
+int main()
+{
+ struct tls_proxy_ctx *proxy = tls_proxy_allocate();
+ if (!proxy) {
+ fprintf(stderr, "can't allocate tls_proxy structure\n");
+ return 1;
+ }
+ int res = tls_proxy_init(proxy,
+ "127.0.0.1", 53921, /* Address to listen */
+ "127.0.0.1", 53910, /* Upstream address */
+ "../certs/tt.cert.pem",
+ "../certs/tt.key.pem");
+ if (res) {
+ fprintf(stderr, "can't initialize tls_proxy structure\n");
+ return res;
+ }
+ res = tls_proxy_start_listen(proxy);
+ if (res) {
+ fprintf(stderr, "error starting listen, error code: %i\n", res);
+ return res;
+ }
+ fprintf(stdout, "started...\n");
+ res = tls_proxy_run(proxy);
+ tls_proxy_free(proxy);
+ return res;
+}
+
diff --git a/tests/pytests/requirements.txt b/tests/pytests/requirements.txt
new file mode 100644
index 0000000..6e2e4d2
--- /dev/null
+++ b/tests/pytests/requirements.txt
@@ -0,0 +1,5 @@
+dnspython
+jinja2
+pytest
+pytest-html
+pytest-xdist
diff --git a/tests/pytests/templates/kresd.conf.j2 b/tests/pytests/templates/kresd.conf.j2
new file mode 100644
index 0000000..4d95521
--- /dev/null
+++ b/tests/pytests/templates/kresd.conf.j2
@@ -0,0 +1,42 @@
+modules = {
+ 'policy',
+ 'hints > iterate',
+}
+
+verbose({{ 'true' if kresd.verbose else 'false' }})
+
+{% if kresd.ip %}
+net.listen('{{ kresd.ip }}', {{ kresd.port }})
+net.listen('{{ kresd.ip }}', {{ kresd.tls_port }}, {tls = true})
+{% endif %}
+
+{% if kresd.ip6 %}
+net.listen('{{ kresd.ip6 }}', {{ kresd.port }})
+net.listen('{{ kresd.ip6 }}', {{ kresd.tls_port }}, {tls = true})
+{% endif %}
+
+net.ipv4=true
+net.ipv6=true
+
+{% if kresd.tls_key_path and kresd.tls_cert_path %}
+net.tls("{{ kresd.tls_cert_path }}", "{{ kresd.tls_key_path }}")
+{% endif %}
+
+{% for name, ip in kresd.hints.items() %}
+hints['{{ name }}'] = '{{ ip }}'
+{% endfor %}
+
+policy.add(policy.all(policy.QTRACE))
+
+{% if kresd.forward %}
+policy.add(policy.all(
+ {% if kresd.forward.proto == 'tls' %}
+ policy.TLS_FORWARD({
+ {"{{ kresd.forward.ip }}@{{ kresd.forward.port }}", hostname='{{ kresd.forward.hostname}}', ca_file='{{ kresd.forward.ca_file }}'}})
+ {% endif %}
+))
+{% endif %}
+
+modules.unload("ta_signal_query")
+modules.unload("priming")
+modules.unload("detect_time_skew")
diff --git a/tests/pytests/test_conn_mgmt.py b/tests/pytests/test_conn_mgmt.py
new file mode 100644
index 0000000..c4b1cba
--- /dev/null
+++ b/tests/pytests/test_conn_mgmt.py
@@ -0,0 +1,213 @@
+"""TCP Connection Management tests"""
+
+import socket
+import struct
+import time
+
+import pytest
+
+import utils
+
+
+@pytest.mark.parametrize('garbage_lengths', [
+ (1,),
+ (1024,),
+ (65533,), # max size garbage
+ (65533, 65533),
+ (1024, 1024, 1024),
+ # (0,), # currently kresd uses this as a heuristic of "lost in bytestream"
+ # (0, 1024), # and closes the connection
+])
+def test_ignore_garbage(kresd_sock, garbage_lengths, single_buffer, query_before):
+ """Send chunk of garbage, prefixed by garbage length. It should be ignored."""
+ buff = b''
+ if query_before: # optionally send initial query
+ msg_buff_before, msgid_before = utils.get_msgbuff()
+ if single_buffer:
+ buff += msg_buff_before
+ else:
+ kresd_sock.sendall(msg_buff_before)
+
+ for glength in garbage_lengths: # prepare garbage data
+ if glength is None:
+ continue
+ garbage_buff = utils.get_prefixed_garbage(glength)
+ if single_buffer:
+ buff += garbage_buff
+ else:
+ kresd_sock.sendall(garbage_buff)
+
+ msg_buff, msgid = utils.get_msgbuff() # final query
+ buff += msg_buff
+ kresd_sock.sendall(buff)
+
+ if query_before:
+ answer_before = utils.receive_parse_answer(kresd_sock)
+ assert answer_before.id == msgid_before
+ answer = utils.receive_parse_answer(kresd_sock)
+ assert answer.id == msgid
+
+
+def test_pipelining(kresd_sock):
+ """
+ First query takes longer to resolve - answer to second query should arrive sooner.
+
+ This test requires internet connection.
+ """
+ # initialization (to avoid issues with net.ipv6=true)
+ buff_pre, msgid_pre = utils.get_msgbuff('0.delay.getdnsapi.net.')
+ kresd_sock.sendall(buff_pre)
+ msg_answer = utils.receive_parse_answer(kresd_sock)
+ assert msg_answer.id == msgid_pre
+
+ # test
+ buff1, msgid1 = utils.get_msgbuff('1500.delay.getdnsapi.net.', msgid=1)
+ buff2, msgid2 = utils.get_msgbuff('1.delay.getdnsapi.net.', msgid=2)
+ buff = buff1 + buff2
+ kresd_sock.sendall(buff)
+
+ msg_answer = utils.receive_parse_answer(kresd_sock)
+ assert msg_answer.id == msgid2
+
+ msg_answer = utils.receive_parse_answer(kresd_sock)
+ assert msg_answer.id == msgid1
+
+
+@pytest.mark.parametrize('duration, delay', [
+ (utils.MAX_TIMEOUT, 0.1),
+ (utils.MAX_TIMEOUT, 3),
+ (utils.MAX_TIMEOUT, 7),
+ (utils.MAX_TIMEOUT + 10, 3),
+])
+def test_long_lived(kresd_sock, duration, delay):
+ """Establish and keep connection alive for longer than maximum timeout."""
+ utils.ping_alive(kresd_sock)
+ end_time = time.time() + duration
+
+ while time.time() < end_time:
+ time.sleep(delay)
+ utils.ping_alive(kresd_sock)
+
+
+def test_close(kresd_sock, query_before):
+ """Establish a connection and wait for timeout from kresd."""
+ if query_before:
+ utils.ping_alive(kresd_sock)
+ time.sleep(utils.MAX_TIMEOUT)
+
+ with utils.expect_kresd_close():
+ utils.ping_alive(kresd_sock)
+
+
+def test_slow_lorris(kresd_sock, query_before):
+ """Simulate slow-lorris attack by sending byte after byte with delays in between."""
+ if query_before:
+ utils.ping_alive(kresd_sock)
+
+ buff, _ = utils.get_msgbuff()
+ end_time = time.time() + utils.MAX_TIMEOUT
+
+ with utils.expect_kresd_close():
+ for i in range(len(buff)):
+ b = buff[i:i+1]
+ kresd_sock.send(b)
+ if time.time() > end_time:
+ break
+ time.sleep(1)
+
+
+@pytest.mark.parametrize('sock_func_name', [
+ 'ip_tcp_socket',
+ 'ip6_tcp_socket',
+])
+def test_oob(kresd, sock_func_name):
+ """TCP out-of-band (urgent) data must not crash resolver."""
+ make_sock = getattr(kresd, sock_func_name)
+ sock = make_sock()
+ msg_buff, msgid = utils.get_msgbuff()
+ sock.sendall(msg_buff, socket.MSG_OOB)
+
+ try:
+ msg_answer = utils.receive_parse_answer(sock)
+ assert msg_answer.id == msgid
+ except ConnectionError:
+ pass # TODO kresd responds with TCP RST, this should be fixed
+
+ # check kresd is alive
+ sock2 = make_sock()
+ utils.ping_alive(sock2)
+
+
+def flood_buffer(msgcount):
+ flood_buff = bytes()
+ msgbuff, _ = utils.get_msgbuff()
+ noid_msgbuff = msgbuff[2:]
+
+ def gen_msg(msgid):
+ return struct.pack("!H", len(msgbuff)) + struct.pack("!H", msgid) + noid_msgbuff
+
+ for i in range(msgcount):
+ flood_buff += gen_msg(i)
+ return flood_buff
+
+
+def test_query_flood_close(make_kresd_sock):
+ """Flood resolver with queries and close the connection."""
+ buff = flood_buffer(10000)
+ sock1 = make_kresd_sock()
+ sock1.sendall(buff)
+ sock1.close()
+
+ sock2 = make_kresd_sock()
+ utils.ping_alive(sock2)
+
+
+def test_query_flood_no_recv(make_kresd_sock):
+ """Flood resolver with queries but don't read any data."""
+ # A use-case for TCP_USER_TIMEOUT socket option? See RFC 793 and RFC 5482
+
+ # It seems it doesn't works as expected. libuv doesn't return any error
+ # (neither on uv_write() call, not in the callback) when kresd sends answers,
+ # so kresd can't recognize that client didn't read any answers. At a certain
+ # point, kresd stops receiving queries from the client (whilst client keep
+ # sending) and closes connection due to timeout.
+
+ buff = flood_buffer(10000)
+ sock1 = make_kresd_sock()
+ end_time = time.time() + utils.MAX_TIMEOUT
+
+ with utils.expect_kresd_close(rst_ok=True): # connection must be closed
+ while time.time() < end_time:
+ sock1.sendall(buff)
+ time.sleep(0.5)
+
+ sock2 = make_kresd_sock()
+ utils.ping_alive(sock2) # resolver must stay alive
+
+
+@pytest.mark.parametrize('glength, gcount, delay', [
+ (65533, 100, 0.5),
+ (0, 100000, 0.5),
+ (1024, 1000, 0.5),
+ (65533, 1, 0),
+ (0, 1, 0),
+ (1024, 1, 0),
+])
+def test_query_flood_garbage(make_kresd_sock, glength, gcount, delay, query_before):
+ """Flood resolver with prefixed garbage."""
+ sock1 = make_kresd_sock()
+ if query_before:
+ utils.ping_alive(sock1)
+
+ gbuff = utils.get_prefixed_garbage(glength)
+ buff = gbuff * gcount
+
+ end_time = time.time() + utils.MAX_TIMEOUT
+
+ with utils.expect_kresd_close(rst_ok=True): # connection must be closed
+ while time.time() < end_time:
+ sock1.sendall(buff)
+ time.sleep(delay)
+
+ sock2 = make_kresd_sock()
+ utils.ping_alive(sock2) # resolver must stay alive
diff --git a/tests/pytests/test_prefix.py b/tests/pytests/test_prefix.py
new file mode 100644
index 0000000..5d8ef16
--- /dev/null
+++ b/tests/pytests/test_prefix.py
@@ -0,0 +1,113 @@
+"""TCP Connection Management tests - prefix length
+
+RFC1035
+4.2.2. TCP usage
+The message is prefixed with a two byte length field which gives the message
+length, excluding the two byte length field.
+
+The following test suite focuses on edge cases for the prefix - when it
+is either too short or too long, instead of matching the length of DNS
+message exactly.
+"""
+
+import time
+
+import pytest
+
+import utils
+
+
+@pytest.fixture(params=[
+ 'no_query_before',
+ 'query_before',
+ 'query_before_in_single_buffer',
+])
+def send_query(request):
+ """Function sends a buffer, either by itself, or with a valid query before.
+ If a valid query is sent before, it can be sent either in a separate buffer, or
+ along with the provided buffer."""
+
+ # pylint: disable=possibly-unused-variable
+
+ def no_query_before(sock, buff): # pylint: disable=unused-argument
+ sock.sendall(buff)
+
+ def query_before(sock, buff, single_buffer=False):
+ """Send an initial query and expect a response."""
+ msg_buff, msgid = utils.get_msgbuff()
+
+ if single_buffer:
+ sock.sendall(msg_buff + buff)
+ else:
+ sock.sendall(msg_buff)
+ sock.sendall(buff)
+
+ answer = utils.receive_parse_answer(sock)
+ assert answer.id == msgid
+
+ def query_before_in_single_buffer(sock, buff):
+ return query_before(sock, buff, single_buffer=True)
+
+ return locals()[request.param]
+
+
+@pytest.mark.parametrize('datalen', [
+ 1, # just one byte of DNS header
+ 11, # DNS header size minus 1
+ 14, # DNS Header size plus 2
+])
+def test_prefix_cuts_message(kresd_sock, datalen, send_query):
+ """Prefix is shorter than the DNS message."""
+ wire, _ = utils.prepare_wire()
+ assert datalen < len(wire)
+ invalid_buff = utils.prepare_buffer(wire, datalen)
+
+ send_query(kresd_sock, invalid_buff) # buffer breaks parsing of TCP stream
+
+ with utils.expect_kresd_close():
+ utils.ping_alive(kresd_sock)
+
+
+def test_prefix_greater_than_message(kresd_sock, send_query):
+ """Prefix is greater than the length of the entire DNS message."""
+ wire, invalid_msgid = utils.prepare_wire()
+ datalen = len(wire) + 16
+ invalid_buff = utils.prepare_buffer(wire, datalen)
+
+ send_query(kresd_sock, invalid_buff)
+
+ valid_buff, _ = utils.get_msgbuff()
+ kresd_sock.sendall(valid_buff)
+
+ # invalid_buff is answered (treats additional data as trailing garbage)
+ answer = utils.receive_parse_answer(kresd_sock)
+ assert answer.id == invalid_msgid
+
+ # parsing stream is broken by the invalid_buff, valid query is never answered
+ with utils.expect_kresd_close():
+ utils.receive_parse_answer(kresd_sock)
+
+
+@pytest.mark.parametrize('glength', [
+ 0,
+ 1,
+ 8,
+ 1024,
+ 4096,
+ 20000,
+])
+def test_prefix_trailing_garbage(kresd_sock, glength, query_before):
+ """Send messages with trailing garbage (its length included in prefix)."""
+ if query_before:
+ utils.ping_alive(kresd_sock)
+
+ for _ in range(10):
+ wire, msgid = utils.prepare_wire()
+ wire += utils.get_garbage(glength)
+ buff = utils.prepare_buffer(wire)
+
+ kresd_sock.sendall(buff)
+ answer = utils.receive_parse_answer(kresd_sock)
+ assert answer.id == msgid
+
+ time.sleep(0.1)
diff --git a/tests/pytests/test_rehandshake.py b/tests/pytests/test_rehandshake.py
new file mode 100644
index 0000000..ffbc10b
--- /dev/null
+++ b/tests/pytests/test_rehandshake.py
@@ -0,0 +1,87 @@
+"""TLS rehandshake test
+
+Test utilizes rehandshake/tls-proxy, which forwards queries to configured
+resolver, but when it sends the response back to the query source, it
+performs a rehandshake after every 8 bytes sent.
+
+It is expected the answer will be received by the source kresd instance
+and sent back to the client (this test).
+
+Make sure to run `make all` in `rehandshake/` to compile the proxy.
+"""
+
+import os
+import re
+import subprocess
+import time
+
+import dns
+import dns.rcode
+import pytest
+
+from kresd import CERTS_DIR, Forward, make_kresd, PYTESTS_DIR
+import utils
+
+
+REHANDSHAKE_PROXY = os.path.join(PYTESTS_DIR, 'rehandshake', 'tlsproxy')
+
+
+@pytest.mark.skipif(not os.path.exists(REHANDSHAKE_PROXY),
+ reason="tlsproxy not found (did you compile it?)")
+def test_rehandshake(tmpdir):
+ def resolve_hint(sock, qname):
+ buff, msgid = utils.get_msgbuff(qname)
+ sock.sendall(buff)
+ answer = utils.receive_parse_answer(sock)
+ assert answer.id == msgid
+ assert answer.rcode() == dns.rcode.NOERROR
+ assert answer.answer[0][0].address == '127.0.0.1'
+
+ hints = {
+ '0.foo.': '127.0.0.1',
+ '1.foo.': '127.0.0.1',
+ '2.foo.': '127.0.0.1',
+ '3.foo.': '127.0.0.1',
+ }
+ # run forward target instance
+ workdir = os.path.join(str(tmpdir), 'kresd_fwd_target')
+ os.makedirs(workdir)
+
+ with make_kresd(workdir, hints=hints, port=53910) as kresd_fwd_target:
+ sock = kresd_fwd_target.ip_tls_socket()
+ resolve_hint(sock, '0.foo.')
+
+ # run proxy
+ cwd, cmd = os.path.split(REHANDSHAKE_PROXY)
+ cmd = './' + cmd
+ ca_file = os.path.join(CERTS_DIR, 'tt.cert.pem')
+ try:
+ proxy = subprocess.Popen(
+ [cmd], cwd=cwd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+ # run test kresd instance
+ workdir2 = os.path.join(str(tmpdir), 'kresd')
+ os.makedirs(workdir2)
+ forward = Forward(proto='tls', ip='127.0.0.1', port=53921,
+ hostname='transport-test-server.com', ca_file=ca_file)
+ with make_kresd(workdir2, forward=forward) as kresd:
+ sock2 = kresd.ip_tcp_socket()
+ try:
+ for hint in hints:
+ resolve_hint(sock2, hint)
+ time.sleep(0.1)
+ finally:
+ # verify log
+ n_connecting_to = 0
+ n_rehandshake = 0
+ partial_log = kresd.partial_log()
+ print(partial_log)
+ for line in partial_log.splitlines():
+ if re.search(r"connecting to: .*", line) is not None:
+ n_connecting_to += 1
+ elif re.search(r"TLS rehandshake .* has started", line) is not None:
+ n_rehandshake += 1
+ assert n_connecting_to == 0 # shouldn't be present in partial log
+ assert n_rehandshake > 0
+ finally:
+ proxy.terminate()
diff --git a/tests/pytests/test_tls.py b/tests/pytests/test_tls.py
new file mode 100644
index 0000000..361741d
--- /dev/null
+++ b/tests/pytests/test_tls.py
@@ -0,0 +1,77 @@
+"""TLS-specific tests"""
+
+import itertools
+import os
+from socket import AF_INET, AF_INET6
+import ssl
+import sys
+
+import pytest
+
+from kresd import make_kresd
+import utils
+
+
+def test_tls_no_cert(kresd, sock_family):
+ """Use TLS without certificates."""
+ sock, dest = kresd.stream_socket(sock_family, tls=True)
+ ctx = utils.make_ssl_context(insecure=True)
+ ssock = ctx.wrap_socket(sock)
+ ssock.connect(dest)
+
+ utils.ping_alive(ssock)
+
+
+def test_tls_selfsigned_cert(kresd_tt, sock_family):
+ """Use TLS with a self signed certificate."""
+ sock, dest = kresd_tt.stream_socket(sock_family, tls=True)
+ ctx = utils.make_ssl_context(verify_location=kresd_tt.tls_cert_path)
+ ssock = ctx.wrap_socket(sock, server_hostname='transport-test-server.com')
+ ssock.connect(dest)
+
+ utils.ping_alive(ssock)
+
+
+def test_tls_cert_hostname_mismatch(kresd_tt, sock_family):
+ """Attempt to use self signed certificate and incorrect hostname."""
+ sock, dest = kresd_tt.stream_socket(sock_family, tls=True)
+ ctx = utils.make_ssl_context(verify_location=kresd_tt.tls_cert_path)
+ ssock = ctx.wrap_socket(sock, server_hostname='wrong-host-name')
+
+ with pytest.raises(ssl.CertificateError):
+ ssock.connect(dest)
+
+
+@pytest.mark.skipif(sys.version_info < (3, 6),
+ reason="requires python3.6 or higher")
+@pytest.mark.parametrize('sf1, sf2, sf3', itertools.product(
+ [AF_INET, AF_INET6], [AF_INET, AF_INET6], [AF_INET, AF_INET6]))
+def test_tls_session_resumption(tmpdir, sf1, sf2, sf3):
+ """Attempt TLS session resumption against the same kresd instance and a different one."""
+ # TODO ensure that session can't be resumed after session ticket key regeneration
+ # at the first kresd instance
+
+ def connect(kresd, ctx, sf, session=None):
+ sock, dest = kresd.stream_socket(sf, tls=True)
+ ssock = ctx.wrap_socket(
+ sock, server_hostname='transport-test-server.com', session=session)
+ ssock.connect(dest)
+ new_session = ssock.session
+ assert new_session.has_ticket
+ assert ssock.session_reused == (session is not None)
+ utils.ping_alive(ssock)
+ ssock.close()
+ return new_session
+
+ workdir = os.path.join(str(tmpdir), 'kresd')
+ os.makedirs(workdir)
+
+ with make_kresd(workdir, 'tt') as kresd:
+ ctx = utils.make_ssl_context(verify_location=kresd.tls_cert_path)
+ session = connect(kresd, ctx, sf1) # initial conn
+ connect(kresd, ctx, sf2, session) # resume session on the same instance
+
+ workdir2 = os.path.join(str(tmpdir), 'kresd2')
+ os.makedirs(workdir2)
+ with make_kresd(workdir2, 'tt') as kresd2:
+ connect(kresd2, ctx, sf3, session) # resume session on a different instance
diff --git a/tests/pytests/utils.py b/tests/pytests/utils.py
new file mode 100644
index 0000000..dcdc14c
--- /dev/null
+++ b/tests/pytests/utils.py
@@ -0,0 +1,131 @@
+from contextlib import contextmanager
+import random
+import ssl
+import struct
+import time
+
+import dns
+import dns.message
+import pytest
+
+
+# default net.tcp_in_idle is 10s, TCP_DEFER_ACCEPT 3s, some extra for
+# Python handling / edge cases
+MAX_TIMEOUT = 16
+
+
+def receive_answer(sock):
+ answer_total_len = 0
+ data = sock.recv(2)
+ if not data:
+ return None
+ answer_total_len = struct.unpack_from("!H", data)[0]
+
+ answer_received_len = 0
+ data_answer = b''
+ while answer_received_len < answer_total_len:
+ data_chunk = sock.recv(answer_total_len - answer_received_len)
+ if not data_chunk:
+ return None
+ data_answer += data_chunk
+ answer_received_len += len(data_answer)
+
+ return data_answer
+
+
+def receive_parse_answer(sock):
+ data_answer = receive_answer(sock)
+
+ if data_answer is None:
+ raise BrokenPipeError("kresd closed connection")
+
+ msg_answer = dns.message.from_wire(data_answer, one_rr_per_rrset=True)
+ return msg_answer
+
+
+def prepare_wire(
+ qname='localhost.',
+ qtype=dns.rdatatype.A,
+ qclass=dns.rdataclass.IN,
+ msgid=None):
+ """Utility function to generate DNS wire format message"""
+ msg = dns.message.make_query(qname, qtype, qclass)
+ if msgid is not None:
+ msg.id = msgid
+ return msg.to_wire(), msg.id
+
+
+def prepare_buffer(wire, datalen=None):
+ """Utility function to prepare TCP buffer from DNS message in wire format"""
+ assert isinstance(wire, bytes)
+ if datalen is None:
+ datalen = len(wire)
+ return struct.pack("!H", datalen) + wire
+
+
+def get_msgbuff(qname='localhost.', qtype=dns.rdatatype.A, msgid=None):
+ wire, msgid = prepare_wire(qname, qtype, msgid=msgid)
+ buff = prepare_buffer(wire)
+ return buff, msgid
+
+
+def get_garbage(length):
+ return bytes(random.getrandbits(8) for _ in range(length))
+
+
+def get_prefixed_garbage(length):
+ data = get_garbage(length)
+ return prepare_buffer(data)
+
+
+def try_ping_alive(sock, msgid=None, close=False):
+ try:
+ ping_alive(sock, msgid)
+ except AssertionError:
+ return False
+ finally:
+ if close:
+ sock.close()
+ return True
+
+
+def ping_alive(sock, msgid=None):
+ buff, msgid = get_msgbuff(msgid=msgid)
+ sock.sendall(buff)
+ answer = receive_parse_answer(sock)
+ assert answer.id == msgid
+
+
+@contextmanager
+def expect_kresd_close(rst_ok=False):
+ with pytest.raises(BrokenPipeError, message="kresd didn't close the connection"):
+ try:
+ time.sleep(0.2) # give kresd time to close connection with TCP FIN
+ yield
+ except ConnectionResetError:
+ if rst_ok:
+ raise BrokenPipeError
+ else:
+ pytest.skip("kresd closed connection with TCP RST")
+
+
+def make_ssl_context(insecure=False, verify_location=None):
+ # set TLS v1.2+
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS)
+ context.options |= ssl.OP_NO_SSLv2
+ context.options |= ssl.OP_NO_SSLv3
+ context.options |= ssl.OP_NO_TLSv1
+ context.options |= ssl.OP_NO_TLSv1_1
+
+ if insecure:
+ # turn off certificate verification
+ context.check_hostname = False
+ context.verify_mode = ssl.CERT_NONE
+ else:
+ context.verify_mode = ssl.CERT_REQUIRED
+ context.check_hostname = True
+
+ if verify_location is not None:
+ context.load_verify_locations(verify_location)
+
+ return context
diff --git a/tests/test.h b/tests/test.h
new file mode 100644
index 0000000..79167d2
--- /dev/null
+++ b/tests/test.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <cmocka.h>
+
+/* Silence clang/GCC warnings when using cmocka 1.0 */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+#include "lib/defines.h"
+#include "lib/utils.h"
+#include <libknot/descriptor.h>
+#include <libknot/rrset.h>
+
+/* Helpers */
+static inline void *mm_test_malloc(void *ctx, size_t n)
+{ return test_malloc(n); }
+static inline void mm_test_free(void *p)
+{ if (p) test_free(p); }
+
+/** Memory context using CMocka allocator. */
+static inline void test_mm_ctx_init(knot_mm_t *mm)
+{
+ mm->alloc = &mm_test_malloc;
+ mm->free = &mm_test_free;
+}
+
+/** Recursively delete directory. */
+static inline int test_tmpdir_remove(const char *path)
+{
+ char buf[512];
+ struct dirent *ent = NULL;
+ DIR *dir = opendir(path);
+ if (dir == NULL) {
+ return kr_error(errno);
+ }
+ while ((ent = readdir(dir)) != NULL) {
+ /* Skip special dirs (this presumes no files begin with '.') */
+ if (ent->d_name[0] == '.') {
+ continue;
+ }
+ sprintf(buf, "%s/%s", path, ent->d_name);
+ remove(buf);
+ }
+ remove(path);
+ closedir(dir);
+ return 0;
+}
+
+/** Create temporary directory. */
+static inline const char* test_tmpdir_create(void)
+{
+ static char env_path[64];
+ strcpy(env_path, "./tmpXXXXXX");
+ return mkdtemp(env_path);
+}
+
+/** Generate random string with given length. */
+static inline void test_randstr(char* dst, size_t len)
+{
+ if (len == 0) {
+ return;
+ }
+
+ for (int i = 0; i < len - 1; ++i) {
+ dst[i] = '0' + (int) (('Z'-'0') * (rand() / (RAND_MAX + 1.0)));
+ }
+ dst[len - 1] = '\0';
+ return;
+}
+
+/** Init RRSet with type TXT, random owner and random payload.
+ * @note Static memory reused, copy it if you need persistence.
+ */
+static inline void test_random_rr(knot_rrset_t *rr, uint32_t ttl)
+{
+ static uint8_t owner_buf[KNOT_DNAME_MAXLEN];
+ static uint8_t rdata_buf[65535];
+ knot_rdata_t *rdata = (knot_rdata_t *)rdata_buf;
+
+ uint16_t num = rand() % (sizeof(owner_buf) - 2);
+ uint8_t tmp_buf[KNOT_DNAME_MAXLEN];
+
+ /* Create random label. */
+ memset(owner_buf, 0, sizeof(owner_buf));
+ uint8_t label_len = num % KNOT_DNAME_MAXLABELLEN;
+ owner_buf[0] = label_len;
+ test_randstr((char *)(owner_buf + 1), label_len);
+
+ /* Create payload */
+ tmp_buf[0] = num;
+ test_randstr((char *)(tmp_buf + 1), tmp_buf[0] + 1);
+ knot_rdata_init(rdata, num + 1, tmp_buf);
+
+ /* Assign static buffers. */
+ knot_rrset_init(rr, owner_buf, KNOT_RRTYPE_TXT, KNOT_CLASS_IN, ttl);
+ rr->rrs.count = 1;
+ rr->rrs.rdata = rdata;
+}
+
diff --git a/tests/test_array.c b/tests/test_array.c
new file mode 100644
index 0000000..995ae71
--- /dev/null
+++ b/tests/test_array.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "tests/test.h"
+#include "lib/generic/array.h"
+
+knot_mm_t global_mm;
+
+static void test_array(void **state)
+{
+ int ret = 0;
+ array_t(int) arr;
+ array_init(arr);
+
+ /* Basic access */
+ assert_int_equal(arr.len, 0);
+ assert_int_equal(array_push(arr, 5), 0);
+ assert_int_equal(arr.at[0], 5);
+ assert_int_equal(array_tail(arr), 5);
+ array_clear(arr);
+
+ /* Reserve capacity and fill. */
+ assert_true(array_reserve(arr, 5) >= 0);
+ for (unsigned i = 0; i < 100; ++i) {
+ ret = array_push(arr, i);
+ assert_true(ret >= 0);
+ }
+
+ /* Make sure reservation holds. */
+ assert_true(array_reserve(arr, 5) >= 0);
+
+ /* Delete elements. */
+ array_del(arr, 0);
+ while (arr.len > 0) {
+ array_pop(arr);
+ }
+
+ /* Overfill. */
+ for (unsigned i = 0; i < 4096; ++i) {
+ ret = array_push(arr, i);
+ assert_true(ret >= 0);
+ }
+
+ array_clear(arr);
+}
+
+/** Reservation through tracked memory allocator. */
+static int test_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+{
+ if (want > *have) {
+ void *new_mem = mm_alloc(baton, elm_size * want);
+ if (*mem != NULL) {
+ memcpy(new_mem, *mem, (*have) * elm_size);
+ mm_free(baton, *mem);
+ }
+ *mem = new_mem;
+ *have = want;
+ }
+
+ return 0;
+}
+
+/** Reservation through fake memory allocator. */
+static int fake_reserve(void *baton, char **mem, size_t elm_size, size_t want, size_t *have)
+{
+ return -1;
+}
+
+static void test_array_mm(void **state)
+{
+ array_t(int) arr;
+ array_init(arr);
+
+ /* Reserve using fake memory allocator. */
+ assert_false(array_reserve_mm(arr, 5, fake_reserve, NULL) >= 0);
+
+ /* Reserve capacity and fill. */
+ assert_true(array_reserve_mm(arr, 100, test_reserve, &global_mm) >= 0);
+ for (unsigned i = 0; i < 100; ++i) {
+ int ret = array_push(arr, i);
+ assert_true(ret >= 0);
+ }
+
+ array_clear_mm(arr, mm_free, &global_mm);
+
+}
+
+int main(void)
+{
+ test_mm_ctx_init(&global_mm);
+
+ const UnitTest tests[] = {
+ unit_test(test_array),
+ unit_test(test_array_mm)
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/test_cache.c b/tests/test_cache.c
new file mode 100644
index 0000000..56e0305
--- /dev/null
+++ b/tests/test_cache.c
@@ -0,0 +1,395 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <dlfcn.h>
+#include <ucw/mempool.h>
+
+#include "tests/test.h"
+#include "lib/cache.h"
+#include "lib/cache/cdb_lmdb.h"
+
+
+
+knot_mm_t global_mm;
+knot_rrset_t global_rr;
+const char *global_env;
+struct kr_cache_entry global_fake_ce;
+
+#define NAMEDB_INTS 256
+#define NAMEDB_DATA_SIZE (NAMEDB_INTS * sizeof(int))
+uint8_t namedb_data[NAMEDB_DATA_SIZE];
+knot_db_val_t global_namedb_data = {namedb_data, NAMEDB_DATA_SIZE};
+
+#define CACHE_SIZE (64 * CPU_PAGE_SIZE)
+#define CACHE_TTL 10
+#define CACHE_TIME 0
+
+int (*original_knot_rdataset_gather)(knot_rdataset_t *dst, knot_rdata_t **src,
+ uint16_t count, knot_mm_t *mm) = NULL;
+
+int knot_rdataset_gather(knot_rdataset_t *dst, knot_rdata_t **src, uint16_t count,
+ knot_mm_t *mm)
+{
+ int err, err_mock;
+ err_mock = (int)mock();
+ if (original_knot_rdataset_gather == NULL) {
+ original_knot_rdataset_gather = dlsym(RTLD_NEXT,"knot_rdataset_gather");
+ assert_non_null (original_knot_rdataset_gather);
+ }
+ err = original_knot_rdataset_gather(dst, src, count, mm);
+ if (err_mock != 0)
+ err = err_mock;
+ return err;
+}
+
+/* Simulate init failure */
+static int fake_test_init(knot_db_t **db, struct kr_cdb_opts *opts, knot_mm_t *pool)
+{
+ static char static_buffer[1024];
+ *db = static_buffer;
+ return mock();
+}
+
+static int fake_test_sync(knot_db_t *db)
+{
+ return 0;
+}
+
+static void fake_test_deinit(knot_db_t *db)
+{
+}
+
+/* Stub for find */
+static int fake_test_find(knot_db_t *db, knot_db_val_t *key, knot_db_val_t *val, int maxcount)
+{
+ val->data = &global_fake_ce;
+ return 0;
+}
+
+/* Stub for insert */
+static int fake_test_ins(knot_db_t *db, knot_db_val_t *key, knot_db_val_t *val, int maxcount)
+{
+ struct kr_cache_entry *header = val->data;
+ int ret, err = (int)mock();
+ if (val->len == sizeof(*header) + NAMEDB_DATA_SIZE) {
+ header = val->data;
+ ret = memcmp(header->data,namedb_data,NAMEDB_DATA_SIZE);
+ if (header->timestamp != global_fake_ce.timestamp || header->ttl != global_fake_ce.ttl || ret != 0) {
+ err = KNOT_EINVAL;
+ }
+ }
+ return err;
+}
+
+/* Fake api */
+static const struct kr_cdb_api *fake_knot_db_lmdb_api(void)
+{
+ static const struct kr_cdb_api api = {
+ "lmdb_fake_api",
+ fake_test_init, fake_test_deinit, NULL, NULL, fake_test_sync,
+ fake_test_find, fake_test_ins, NULL,
+ NULL, NULL
+ };
+
+ return &api;
+}
+
+/* Test cache open */
+static int test_open(void **state, const struct kr_cdb_api *api)
+{
+ static struct kr_cache cache;
+ struct kr_cdb_opts opts = {
+ global_env,
+ CACHE_SIZE,
+ };
+ memset(&cache, 0, sizeof(cache));
+ *state = &cache;
+ return kr_cache_open(&cache, api, &opts, &global_mm);
+}
+
+/* fake api test open */
+static void test_open_fake_api(void **state)
+{
+ bool res = false;
+ will_return(fake_test_init, KNOT_EINVAL);
+ assert_int_equal(test_open(state, fake_knot_db_lmdb_api()), KNOT_EINVAL);
+ will_return(fake_test_init, 0);
+ assert_int_equal(test_open(state, fake_knot_db_lmdb_api()), 0);
+ res = (((struct kr_cache *)(*state))->api == fake_knot_db_lmdb_api());
+ assert_true(res);
+}
+
+static void test_open_conventional_api(void **state)
+{
+ bool res = false;
+ assert_int_equal(test_open(state, NULL),0);
+ res = (((struct kr_cache *)(*state))->api == kr_cdb_lmdb());
+ assert_true(res);
+}
+
+
+/* Test cache teardown. */
+static void test_close(void **state)
+{
+ kr_cache_close(*state);
+ *state = NULL;
+}
+
+/* test invalid parameters and some api failures */
+static void test_fake_invalid (void **state)
+{
+ const struct kr_cdb_api *api_saved = NULL;
+ knot_dname_t dname[] = "";
+ struct kr_cache *cache = *state;
+ struct kr_cache_entry *entry = NULL;
+ int ret = 0;
+
+ ret = kr_cache_peek(cache, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, &entry, 0);
+ assert_int_equal(ret, 0);
+ api_saved = cache->api;
+ cache->api = NULL;
+ ret = kr_cache_peek(cache, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, &entry, 0);
+ cache->api = api_saved;
+ assert_int_not_equal(ret, 0);
+ kr_cache_sync(cache);
+}
+
+static void test_fake_insert(void **state)
+{
+ int ret_cache_ins_ok, ret_cache_ins_inval;
+ knot_dname_t dname[] = "";
+ struct kr_cache *cache = (*state);
+ test_randstr((char *)&global_fake_ce, sizeof(global_fake_ce));
+ test_randstr((char *)namedb_data, NAMEDB_DATA_SIZE);
+
+ will_return(fake_test_ins, 0);
+ ret_cache_ins_ok = kr_cache_insert(cache, KR_CACHE_USER, dname,
+ KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data);
+ will_return(fake_test_ins,KNOT_EINVAL);
+ ret_cache_ins_inval = kr_cache_insert(cache, KR_CACHE_USER, dname,
+ KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data);
+ assert_int_equal(ret_cache_ins_ok, 0);
+ assert_int_equal(ret_cache_ins_inval, KNOT_EINVAL);
+ kr_cache_sync(cache);
+}
+
+/* Test invalid parameters and some api failures. */
+static void test_invalid(void **state)
+{
+ knot_dname_t dname[] = "";
+ uint32_t timestamp = CACHE_TIME;
+ struct kr_cache_entry *entry = NULL;
+ struct kr_cache *cache = (*state);
+ struct kr_cdb_opts opts = {
+ global_env,
+ CACHE_SIZE,
+ };
+
+ knot_rrset_init_empty(&global_rr);
+
+ assert_int_equal(kr_cache_open(NULL, NULL, &opts, &global_mm),KNOT_EINVAL);
+ assert_int_not_equal(kr_cache_peek(NULL, KR_CACHE_USER, dname, KNOT_RRTYPE_TSIG, NULL, &timestamp), 0);
+ assert_int_not_equal(kr_cache_peek(cache, KR_CACHE_USER, NULL, KNOT_RRTYPE_TSIG, &entry, &timestamp), 0);
+ assert_int_not_equal(kr_cache_peek_rr(NULL, NULL, NULL, NULL, NULL), 0);
+ assert_int_not_equal(kr_cache_peek_rr(cache, NULL, NULL, NULL, NULL), 0);
+ assert_int_not_equal(kr_cache_insert_rr(cache, NULL, 0, 0, 0), 0);
+ assert_int_not_equal(kr_cache_insert_rr(NULL, NULL, 0, 0, 0), 0);
+ assert_int_not_equal(kr_cache_insert(NULL, KR_CACHE_USER, dname,
+ KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data), 0);
+ assert_int_not_equal(kr_cache_insert(cache, KR_CACHE_USER, NULL,
+ KNOT_RRTYPE_TSIG, &global_fake_ce, global_namedb_data), 0);
+ assert_int_not_equal(kr_cache_insert(cache, KR_CACHE_USER, dname,
+ KNOT_RRTYPE_TSIG, NULL, global_namedb_data), 0);
+ assert_int_not_equal(kr_cache_remove(cache, 0, NULL, 0), 0);
+ assert_int_not_equal(kr_cache_remove(cache, KR_CACHE_RR, NULL, 0), 0);
+ assert_int_not_equal(kr_cache_remove(NULL, 0, NULL, 0), 0);
+ assert_int_not_equal(kr_cache_clear(NULL), 0);
+ kr_cache_sync(cache);
+}
+
+/* Test cache write */
+static void test_insert_rr(void **state)
+{
+ test_random_rr(&global_rr, CACHE_TTL);
+ struct kr_cache *cache = (*state);
+ int ret = kr_cache_insert_rr(cache, &global_rr, 0, 0, CACHE_TIME);
+ assert_int_equal(ret, 0);
+ kr_cache_sync(cache);
+}
+
+static void test_materialize(void **state)
+{
+ return; /* will be gone or need big rework in 2.0.0 anyway */
+ knot_rrset_t output_rr;
+ knot_dname_t * owner_saved = global_rr.owner;
+ bool res_cmp_ok_empty, res_cmp_fail_empty;
+ bool res_cmp_ok, res_cmp_fail;
+
+ global_rr.owner = NULL;
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ kr_cache_materialize(&output_rr, &global_rr, 0, &global_mm);
+ res_cmp_ok_empty = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_HEADER);
+ res_cmp_fail_empty = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr, &global_mm);
+ global_rr.owner = owner_saved;
+ assert_true(res_cmp_ok_empty);
+ assert_false(res_cmp_fail_empty);
+
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ will_return (knot_rdataset_gather, 0);
+ kr_cache_materialize(&output_rr, &global_rr, 0, &global_mm);
+ res_cmp_ok = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr, &global_mm);
+ assert_true(res_cmp_ok);
+
+ knot_rrset_init(&output_rr, NULL, 0, 0);
+ will_return (knot_rdataset_gather, KNOT_ENOMEM);
+ kr_cache_materialize(&output_rr, &global_rr, 0, &global_mm);
+ res_cmp_fail = knot_rrset_equal(&global_rr, &output_rr, KNOT_RRSET_COMPARE_WHOLE);
+ knot_rrset_clear(&output_rr, &global_mm);
+ assert_false(res_cmp_fail);
+}
+
+/* Test cache read */
+static void test_query(void **state)
+{
+ struct kr_cache *cache = (*state);
+ knot_rrset_t cache_rr;
+ knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
+
+ for (uint32_t timestamp = CACHE_TIME; timestamp < CACHE_TIME + CACHE_TTL; ++timestamp) {
+ uint8_t rank = 0;
+ uint8_t flags = 0;
+ uint32_t drift = timestamp;
+ int query_ret = kr_cache_peek_rr(cache, &cache_rr, &rank, &flags, &drift);
+ bool rr_equal = knot_rrset_equal(&global_rr, &cache_rr, KNOT_RRSET_COMPARE_WHOLE);
+ assert_int_equal(query_ret, 0);
+ assert_true(rr_equal);
+ }
+ kr_cache_sync(cache);
+}
+
+/* Test cache read (simulate aged entry) */
+static void test_query_aged(void **state)
+{
+ uint8_t rank = 0;
+ uint8_t flags = 0;
+ uint32_t timestamp = CACHE_TIME + CACHE_TTL + 1;
+ knot_rrset_t cache_rr;
+ knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
+
+ struct kr_cache *cache = (*state);
+ int ret = kr_cache_peek_rr(cache, &cache_rr, &rank, &flags, &timestamp);
+ assert_int_equal(ret, kr_error(ESTALE));
+ kr_cache_sync(cache);
+}
+
+/* Test cache removal */
+static void test_remove(void **state)
+{
+ uint8_t rank = 0;
+ uint8_t flags = 0;
+ uint32_t timestamp = CACHE_TIME;
+ knot_rrset_t cache_rr;
+ knot_rrset_init(&cache_rr, global_rr.owner, global_rr.type, global_rr.rclass);
+
+ struct kr_cache *cache = (*state);
+ int ret = kr_cache_remove(cache, KR_CACHE_RR, cache_rr.owner, cache_rr.type);
+ assert_int_equal(ret, 0);
+ ret = kr_cache_peek_rr(cache, &cache_rr, &rank, &flags, &timestamp);
+ assert_int_equal(ret, KNOT_ENOENT);
+ kr_cache_sync(cache);
+}
+
+/* Test cache fill */
+static void test_fill(void **state)
+{
+ struct kr_cache *cache = (*state);
+
+ /* Fill with random values. */
+ int ret = 0;
+ for (unsigned i = 0; i < CACHE_SIZE; ++i) {
+ knot_rrset_t rr;
+ test_random_rr(&rr, CACHE_TTL);
+ ret = kr_cache_insert_rr(cache, &rr, 0, 0, CACHE_TTL - 1);
+ if (ret != 0) {
+ break;
+ }
+ ret = kr_cache_sync(cache);
+ if (ret != 0) {
+ break;
+ }
+ }
+
+ /* Expect we run out of space */
+ assert_int_equal(ret, kr_error(ENOSPC));
+ kr_cache_sync(cache);
+}
+
+/* Test cache clear */
+static void test_clear(void **state)
+{
+ struct kr_cache *cache = (*state);
+ int preempt_ret = kr_cache_clear(cache);
+ int count_ret = cache->api->count(cache->db);
+
+ assert_int_equal(preempt_ret, 0);
+ assert_int_equal(count_ret, 1); /* Version record */
+}
+
+int main(void)
+{
+ /* Initialize */
+ test_mm_ctx_init(&global_mm);
+ global_env = test_tmpdir_create();
+
+ /* Invalid input */
+ const UnitTest tests_bad[] = {
+ group_test_setup(test_open_fake_api),
+ unit_test(test_fake_invalid),
+ unit_test(test_fake_insert),
+ group_test_teardown(test_close)
+ };
+
+ const UnitTest tests[] = {
+ /* Invalid input */
+ unit_test(test_invalid),
+ /* Cache persistence */
+ group_test_setup(test_open_conventional_api),
+ unit_test(test_insert_rr),
+ unit_test(test_materialize),
+ unit_test(test_query),
+ /* Cache aging */
+ unit_test(test_query_aged),
+ /* Removal */
+ unit_test(test_remove),
+ /* Cache fill */
+ unit_test(test_fill),
+ unit_test(test_clear),
+ group_test_teardown(test_close)
+ };
+
+ int ret = run_group_tests(tests_bad);
+ if (ret == 0) {
+ ret = run_group_tests(tests);
+ }
+
+ /* Cleanup */
+ test_tmpdir_remove(global_env);
+ return ret;
+}
diff --git a/tests/test_integration.mk b/tests/test_integration.mk
new file mode 100644
index 0000000..a5d36c3
--- /dev/null
+++ b/tests/test_integration.mk
@@ -0,0 +1,48 @@
+#
+# Integration tests
+#
+# 1. Run tests from main Deckard repo (generic DNS tests)
+# 2. Run tests from kresd repo (kresd-specific tests)
+
+SUBMODULES_DIRTY := $(shell git submodule status --recursive | cut -c 1 | grep -q '[^ ]' && echo $$?)
+REAL_PREFIX=$(realpath $(PREFIX))
+REAL_CURDIR=$(realpath $(CURDIR))
+
+# Integration tests from Deckard repo
+deckard_DIR := $(TOPSRCDIR)/tests/deckard
+
+$(deckard_DIR)/Makefile:
+ @git submodule update --init --recursive
+
+# this is necessary to avoid multiple parallel but independent runs
+# of 'make depend' from $(deckard_DIR)/run.sh
+$(deckard_DIR)/env.sh: $(deckard_DIR)/Makefile
+ @make -C "$(deckard_DIR)" depend
+
+check-install-precond:
+ $(if $(SUBMODULES_DIRTY), $(warning Warning: Git submodules are not up-to-date, expect test failures),)
+ $(if $(findstring $(REAL_CURDIR),$(REAL_PREFIX)),, $(warning Warning: PREFIX does not point into source directory; testing version in $(PREFIX)!))
+ @test -x "$(SBINDIR)/kresd" || (echo 'to run integration tests install kresd into into $$PREFIX ($(SBINDIR)/kresd)' && exit 1)
+
+# Deckard requires additional depedencies so it is not part of installcheck
+deckard: check-install-precond $(deckard_DIR)/env.sh
+ COVERAGE_ENV_SCRIPT="$(TOPSRCDIR)/scripts/coverage_env.sh" DAEMONSRCDIR="$(TOPSRCDIR)" COVERAGE_STATSDIR="$(COVERAGE_STATSDIR)/deckard" $(preload_syms) PATH="$(SBINDIR):$(PATH)" "$(deckard_DIR)/kresd_run.sh"
+
+
+tests_integr := \
+ $(wildcard daemon/*.test.integr) \
+ $(wildcard modules/*/*.test.integr) \
+ $(wildcard modules/*/test.integr) \
+ $(wildcard modules/*/*/test.integr) \
+ $(wildcard modules/*/*/*.test.integr)
+
+define make_integr_test
+$(1): check-install-precond $(deckard_DIR)/env.sh
+ echo "Integration tests from $1" && cd "$(TOPSRCDIR)" && COVERAGE_ENV_SCRIPT="$(TOPSRCDIR)/scripts/coverage_env.sh" DAEMONSRCDIR="$(TOPSRCDIR)" COVERAGE_STATSDIR="$(COVERAGE_STATSDIR)/deckard" $(preload_syms) PATH="$(SBINDIR):$(PATH)" "$(deckard_DIR)/run.sh" "--config=$(abspath $(1))/deckard.yaml" "--scenarios=$(abspath $(1))"
+.PHONY: $(1)
+endef
+
+$(foreach test,$(tests_integr),$(eval $(call make_integr_test,$(test))))
+
+check-integration: deckard $(tests_integr)
+.PHONY: check-install-precond deckard check-integration $(tests_integr)
diff --git a/tests/test_lru.c b/tests/test_lru.c
new file mode 100644
index 0000000..eaa1539
--- /dev/null
+++ b/tests/test_lru.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tests/test.h"
+#include "lib/generic/lru.h"
+
+typedef lru_t(int) lru_int_t;
+#define HASH_SIZE 1024
+#define KEY_LEN(x) (strlen(x) + 1)
+
+/*
+ * Sample dictionary
+ */
+static const char *dict[] = {
+ "catagmatic", "prevaricator", "statoscope", "workhand", "benzamide",
+ "alluvia", "fanciful", "bladish", "Tarsius", "unfast", "appropriative",
+ "seraphically", "monkeypod", "deflectometer", "tanglesome", "zodiacal",
+ "physiologically", "economizer", "forcepslike", "betrumpet",
+ "Danization", "broadthroat", "randir", "usherette", "nephropyosis",
+ "hematocyanin", "chrysohermidin", "uncave", "mirksome", "podophyllum",
+ "siphonognathous", "indoor", "featheriness", "forwardation",
+ "archruler", "soricoid", "Dailamite", "carmoisin", "controllability",
+ "unpragmatical", "childless", "transumpt", "productive",
+ "thyreotoxicosis", "oversorrow", "disshadow", "osse", "roar",
+ "pantomnesia", "talcer", "hydrorrhoea", "Satyridae", "undetesting",
+ "smoothbored", "widower", "sivathere", "pendle", "saltation",
+ "autopelagic", "campfight", "unexplained", "Macrorhamphosus",
+ "absconsa", "counterflory", "interdependent", "triact", "reconcentration",
+ "oversharpness", "sarcoenchondroma", "superstimulate", "assessory",
+ "pseudepiscopacy", "telescopically", "ventriloque", "politicaster",
+ "Caesalpiniaceae", "inopportunity", "Helion", "uncompatible",
+ "cephaloclasia", "oversearch", "Mahayanistic", "quarterspace",
+ "bacillogenic", "hamartite", "polytheistical", "unescapableness",
+ "Pterophorus", "cradlemaking", "Hippoboscidae", "overindustrialize",
+ "perishless", "cupidity", "semilichen", "gadge", "detrimental",
+ "misencourage", "toparchia", "lurchingly", "apocatastasis"
+};
+
+static void test_insert(void **state)
+{
+ lru_int_t *lru = *state;
+ int dict_size = sizeof(dict) / sizeof(const char *);
+ int i;
+
+ for (i = 0; i < dict_size; i++) {
+ int *data = lru_get_new(lru, dict[i], KEY_LEN(dict[i]), NULL);
+ if (!data) {
+ continue;
+ }
+ *data = i;
+ assert_true(*lru_get_try(lru, dict[i], KEY_LEN(dict[i])) == i);
+ }
+}
+
+static void test_missing(void **state)
+{
+ lru_int_t *lru = *state;
+ const char *notin = "not in lru";
+ assert_true(lru_get_try(lru, notin, KEY_LEN(notin)) == NULL);
+}
+
+static void test_eviction(void **state)
+{
+ lru_int_t *lru = *state;
+ char key[16];
+ for (unsigned i = 0; i < HASH_SIZE; ++i) {
+ test_randstr(key, sizeof(key));
+ int *data = lru_get_new(lru, key, sizeof(key), NULL);
+ if (!data) {
+ continue;
+ }
+ *data = i;
+ if (*lru_get_try(lru, key, sizeof(key)) != i) {
+ assert_true(0);
+ }
+ }
+}
+
+static void test_init(void **state)
+{
+ lru_int_t *lru;
+ lru_create(&lru, HASH_SIZE, NULL, NULL);
+ assert_non_null(lru);
+ *state = lru;
+}
+
+static void test_deinit(void **state)
+{
+ lru_int_t *lru = *state;
+ lru_free(lru);
+}
+
+/* Program entry point */
+int main(int argc, char **argv)
+{
+ const UnitTest tests[] = {
+ group_test_setup(test_init),
+ unit_test(test_insert),
+ unit_test(test_missing),
+ unit_test(test_eviction),
+ group_test_teardown(test_deinit)
+ };
+
+ return run_group_tests(tests);
+}
diff --git a/tests/test_map.c b/tests/test_map.c
new file mode 100644
index 0000000..b9e624a
--- /dev/null
+++ b/tests/test_map.c
@@ -0,0 +1,131 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tests/test.h"
+#include "lib/generic/map.h"
+
+/*
+ * Sample dictionary
+ */
+static const char *dict[] = {
+ "catagmatic", "prevaricator", "statoscope", "workhand", "benzamide",
+ "alluvia", "fanciful", "bladish", "Tarsius", "unfast", "appropriative",
+ "seraphically", "monkeypod", "deflectometer", "tanglesome", "zodiacal",
+ "physiologically", "economizer", "forcepslike", "betrumpet",
+ "Danization", "broadthroat", "randir", "usherette", "nephropyosis",
+ "hematocyanin", "chrysohermidin", "uncave", "mirksome", "podophyllum",
+ "siphonognathous", "indoor", "featheriness", "forwardation",
+ "archruler", "soricoid", "Dailamite", "carmoisin", "controllability",
+ "unpragmatical", "childless", "transumpt", "productive",
+ "thyreotoxicosis", "oversorrow", "disshadow", "osse", "roar",
+ "pantomnesia", "talcer", "hydrorrhoea", "Satyridae", "undetesting",
+ "smoothbored", "widower", "sivathere", "pendle", "saltation",
+ "autopelagic", "campfight", "unexplained", "Macrorhamphosus",
+ "absconsa", "counterflory", "interdependent", "triact", "reconcentration",
+ "oversharpness", "sarcoenchondroma", "superstimulate", "assessory",
+ "pseudepiscopacy", "telescopically", "ventriloque", "politicaster",
+ "Caesalpiniaceae", "inopportunity", "Helion", "uncompatible",
+ "cephaloclasia", "oversearch", "Mahayanistic", "quarterspace",
+ "bacillogenic", "hamartite", "polytheistical", "unescapableness",
+ "Pterophorus", "cradlemaking", "Hippoboscidae", "overindustrialize",
+ "perishless", "cupidity", "semilichen", "gadge", "detrimental",
+ "misencourage", "toparchia", "lurchingly", "apocatastasis"
+};
+
+/* Insertions */
+static void test_insert(void **state)
+{
+ map_t *tree = *state;
+ int dict_size = sizeof(dict) / sizeof(const char *);
+ int i;
+
+ for (i = 0; i < dict_size; i++) {
+ assert_int_equal(map_set(tree, dict[i], (void *)dict[i]), 0);
+ }
+}
+
+/* Searching */
+static void test_get(void **state)
+{
+ map_t *tree = *state;
+ char *in;
+ const char *notin = "not in tree";
+
+ in = malloc(strlen(dict[23])+1);
+ strcpy(in, dict[23]);
+
+ assert_true(map_get(tree, in) == dict[23]);
+ assert_true(map_get(tree, notin) == NULL);
+ assert_true(map_get(tree, "") == NULL);
+ in[strlen(in)/2] = '\0';
+ assert_true(map_get(tree, in) == NULL);
+
+ free(in);
+}
+
+/* Deletion */
+static void test_delete(void **state)
+{
+ map_t *tree = *state;
+ assert_int_equal(map_del(tree, dict[91]), 0);
+ assert_false(map_contains(tree, dict[91]));
+ assert_int_equal(map_del(tree, "most likely not in tree"), 1);
+}
+
+/* Test null value existence */
+static void test_null_value(void **state)
+{
+ map_t *tree = *state;
+ char *key = "foo";
+
+ assert_int_equal(map_set(tree, key, (void *)0), 0);
+ assert_true(map_contains(tree, key));
+ assert_int_equal(map_del(tree, key), 0);
+}
+
+static void test_init(void **state)
+{
+ static map_t tree;
+ tree = map_make(NULL);
+ *state = &tree;
+ assert_non_null(*state);
+}
+
+static void test_deinit(void **state)
+{
+ map_t *tree = *state;
+ map_clear(tree);
+}
+
+/* Program entry point */
+int main(int argc, char **argv)
+{
+ const UnitTest tests[] = {
+ group_test_setup(test_init),
+ unit_test(test_insert),
+ unit_test(test_get),
+ unit_test(test_delete),
+ unit_test(test_null_value),
+ group_test_teardown(test_deinit)
+ };
+
+ return run_group_tests(tests);
+}
diff --git a/tests/test_module.c b/tests/test_module.c
new file mode 100644
index 0000000..f17a879
--- /dev/null
+++ b/tests/test_module.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 201 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "tests/test.h"
+#include "lib/module.h"
+
+static void test_module_params(void **state)
+{
+ struct kr_module module;
+ assert_int_equal(kr_module_load(NULL, NULL, NULL), kr_error(EINVAL));
+ assert_int_equal(kr_module_load(&module, NULL, NULL), kr_error(EINVAL));
+ kr_module_unload(NULL);
+}
+
+static void test_module_builtin(void **state)
+{
+ struct kr_module module;
+ assert_int_equal(kr_module_load(&module, "iterate", NULL), 0);
+ kr_module_unload(&module);
+}
+
+static void test_module_c(void **state)
+{
+ struct kr_module module;
+ assert_int_equal(kr_module_load(&module, "mock_cmodule", "tests"), 0);
+ kr_module_unload(&module);
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_module_params),
+ unit_test(test_module_builtin),
+ unit_test(test_module_c),
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/test_pack.c b/tests/test_pack.c
new file mode 100644
index 0000000..a648832
--- /dev/null
+++ b/tests/test_pack.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "tests/test.h"
+#include "lib/generic/pack.h"
+
+#define U8(x) (const uint8_t *)(x)
+knot_mm_t global_mm;
+
+static void test_pack_std(void **state)
+{
+ int ret = 0;
+ pack_t pack;
+ pack_init(pack);
+ assert_int_equal(pack.len, 0);
+
+ /* Test that iterator on empty pack works */
+ assert_null(pack_head(pack));
+ assert_null(pack_tail(pack));
+ assert_null(pack_obj_find(&pack, U8(""), 1));
+ assert_int_equal(pack_obj_len(pack_head(pack)), 0);
+ assert_int_equal(pack_obj_del(&pack, U8(""), 1), -1);
+
+ /* Push/delete without reservation. */
+ assert_int_not_equal(pack_obj_push(&pack, U8(""), 1), 0);
+ assert_int_not_equal(pack_obj_del(&pack, U8(""), 1), 0);
+
+ /* Reserve capacity and fill. */
+ assert_true(pack_reserve(pack, 10, 10 * 2) >= 0);
+ for (unsigned i = 0; i < 10; ++i) {
+ ret = pack_obj_push(&pack, U8("de"), 2);
+ assert_true(ret >= 0);
+ }
+
+ /* Iterate */
+ uint8_t *it = pack_head(pack);
+ assert_non_null(it);
+ unsigned count = 0;
+ while (it != pack_tail(pack)) {
+ assert_int_equal(pack_obj_len(it), 2);
+ assert_true(memcmp(pack_obj_val(it), "de", 2) == 0);
+ it = pack_obj_next(it);
+ count += 1;
+ }
+
+ /* Find */
+ it = pack_obj_find(&pack, U8("de"), 2);
+ assert_non_null(it);
+ it = pack_obj_find(&pack, U8("ed"), 2);
+ assert_null(it);
+
+ /* Delete */
+ assert_int_not_equal(pack_obj_del(&pack, U8("be"), 2), 0);
+ assert_int_equal(pack_obj_del(&pack, U8("de"), 2), 0);
+ assert_int_equal(pack.len, 9*(2+2)); /* 9 objects, length=2 */
+
+ pack_clear(pack);
+}
+
+int main(void)
+{
+ test_mm_ctx_init(&global_mm);
+
+ const UnitTest tests[] = {
+ unit_test(test_pack_std),
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/test_queue.c b/tests/test_queue.c
new file mode 100644
index 0000000..0b14944
--- /dev/null
+++ b/tests/test_queue.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "tests/test.h"
+#include "lib/generic/queue.h"
+
+/* The main intention is to use queues with pointers, so we test the same-sized int. */
+typedef queue_t(ptrdiff_t) queue_int_t;
+typedef queue_it_t(int) queue_int_it_t;
+
+static void test_int(void **state_)
+{
+ queue_int_t q;
+ queue_init(q);
+
+ queue_push_head(q, 2);
+ queue_push_head(q, 1);
+ queue_push_head(q, 0);
+ for (int i = 0; i < 100; ++i) {
+ assert_int_equal(queue_head(q), i);
+ queue_push(q, i + 3);
+ queue_pop(q);
+ }
+ assert_int_equal(queue_len(q), 3);
+ for (int i = 99; i > 0; --i) {
+ assert_int_equal(queue_head(q), i + 1);
+ queue_push_head(q, i);
+ }
+ assert_int_equal(queue_len(q), 3 + 99);
+
+ /* Basic iterator test. */
+ {
+ int i = 0;
+ for (queue_int_it_t it = queue_it_begin(q); !queue_it_finished(it);
+ queue_it_next(it)) {
+ ++queue_it_val(it);
+ ++i;
+ }
+ assert_int_equal(queue_len(q), i);
+ }
+
+ queue_deinit(q);
+ queue_init(q);
+
+ for (int i = 0; i < 100; ++i) {
+ queue_push(q, 2*i);
+ queue_push(q, 2*i + 1);
+ assert_int_equal(queue_head(q), i);
+ queue_pop(q);
+ }
+
+ queue_deinit(q);
+}
+
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_int),
+ };
+
+ return run_tests(tests);
+}
+
diff --git a/tests/test_rplan.c b/tests/test_rplan.c
new file mode 100644
index 0000000..ad083fd
--- /dev/null
+++ b/tests/test_rplan.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "tests/test.h"
+#include "lib/resolve.h"
+#include "lib/rplan.h"
+
+static void test_rplan_params(void **state)
+{
+ /* NULL rplan */
+
+ assert_int_equal(kr_rplan_init(NULL, NULL, NULL), KNOT_EINVAL);
+ assert_null((void *)kr_rplan_push(NULL, NULL, NULL, 0, 0));
+ assert_int_equal(kr_rplan_pop(NULL, NULL), KNOT_EINVAL);
+ assert_true(kr_rplan_empty(NULL) == true);
+ kr_rplan_deinit(NULL);
+
+ /* NULL mandatory parameters */
+
+ struct kr_rplan rplan;
+ assert_int_equal(kr_rplan_init(&rplan, NULL, NULL), KNOT_EOK);
+ assert_null((void *)kr_rplan_push(&rplan, NULL, NULL, 0, 0));
+ assert_int_equal(kr_rplan_pop(&rplan, NULL), KNOT_EINVAL);
+ assert_true(kr_rplan_empty(&rplan) == true);
+ kr_rplan_deinit(&rplan);
+}
+
+static void test_rplan_push(void **state)
+{
+ knot_mm_t mm;
+ test_mm_ctx_init(&mm);
+ struct kr_request request = {
+ .pool = mm,
+ .options = {},
+ };
+
+ struct kr_rplan rplan;
+ kr_rplan_init(&rplan, &request, &mm);
+
+ /* Push query. */
+ assert_non_null((void *)kr_rplan_push(&rplan, NULL, (knot_dname_t *)"", 0, 0));
+
+ kr_rplan_deinit(&rplan);
+}
+
+/**
+ * Set and clear must not omit any bit, especially around byte boundaries.
+ */
+static void test_rplan_flags(void **state)
+{
+ static struct kr_qflags f1, f2, ones, zeros; /* static => initialized to zeroes */
+ assert_true(memcmp(&f1, &f2, sizeof(f1)) == 0); /* sanity check */
+ memset(&ones, 0xff, sizeof(ones)); /* all ones */
+
+ /* test set */
+ kr_qflags_set(&f1, ones);
+ assert_true(memcmp(&f1, &ones, sizeof(f1)) == 0); /* 1 == 1 */
+
+ /* test clear */
+ memset(&f2, 0xff, sizeof(f2)); /* all ones */
+ kr_qflags_clear(&f2, ones);
+ assert_true(memcmp(&f2, &zeros, sizeof(f1)) == 0); /* 0 == 0 */
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_rplan_params),
+ unit_test(test_rplan_push),
+ unit_test(test_rplan_flags)
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/test_set.c b/tests/test_set.c
new file mode 100644
index 0000000..5f82d82
--- /dev/null
+++ b/tests/test_set.c
@@ -0,0 +1,220 @@
+/*
+ * critbit89 - A crit-bit tree implementation for strings in C89
+ * Written by Jonas Gehring <jonas@jgehring.net>
+ */
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tests/test.h"
+#include "lib/generic/set.h"
+#include "lib/utils.h"
+
+
+/*
+ * Sample dictionary: 100 random words from /usr/share/dict/words
+ * Generated using random.org:
+ * MAX=`wc -l < /usr/share/dict/words | tr -d " "`
+ * for i in `curl "http://www.random.org/integers/?num=100&min=1&max=$MAX&col=1&base=10&format=plain&rnd=new"`; do
+ * nl /usr/share/dict/words | grep -w $i | tr -d "0-9\t "
+ * done
+ */
+static const char *dict[] = {
+ "catagmatic", "prevaricator", "statoscope", "workhand", "benzamide",
+ "alluvia", "fanciful", "bladish", "Tarsius", "unfast", "appropriative",
+ "seraphically", "monkeypod", "deflectometer", "tanglesome", "zodiacal",
+ "physiologically", "economizer", "forcepslike", "betrumpet",
+ "Danization", "broadthroat", "randir", "usherette", "nephropyosis",
+ "hematocyanin", "chrysohermidin", "uncave", "mirksome", "podophyllum",
+ "siphonognathous", "indoor", "featheriness", "forwardation",
+ "archruler", "soricoid", "Dailamite", "carmoisin", "controllability",
+ "unpragmatical", "childless", "transumpt", "productive",
+ "thyreotoxicosis", "oversorrow", "disshadow", "osse", "roar",
+ "pantomnesia", "talcer", "hydrorrhoea", "Satyridae", "undetesting",
+ "smoothbored", "widower", "sivathere", "pendle", "saltation",
+ "autopelagic", "campfight", "unexplained", "Macrorhamphosus",
+ "absconsa", "counterflory", "interdependent", "triact", "reconcentration",
+ "oversharpness", "sarcoenchondroma", "superstimulate", "assessory",
+ "pseudepiscopacy", "telescopically", "ventriloque", "politicaster",
+ "Caesalpiniaceae", "inopportunity", "Helion", "uncompatible",
+ "cephaloclasia", "oversearch", "Mahayanistic", "quarterspace",
+ "bacillogenic", "hamartite", "polytheistical", "unescapableness",
+ "Pterophorus", "cradlemaking", "Hippoboscidae", "overindustrialize",
+ "perishless", "cupidity", "semilichen", "gadge", "detrimental",
+ "misencourage", "toparchia", "lurchingly", "apocatastasis"
+};
+
+/* Insertions */
+static void test_insert(void **state)
+{
+ set_t *set = *state;
+ int dict_size = sizeof(dict) / sizeof(const char *);
+ int i;
+
+ for (i = 0; i < dict_size; i++) {
+ assert_int_equal(set_add(set, dict[i]), 0);
+ }
+}
+
+/* Insertion of duplicate element */
+static void test_insert_dup(void **state)
+{
+ set_t *set = *state;
+ int dict_size = sizeof(dict) / sizeof(const char *);
+ int i;
+
+ for (i = 0; i < dict_size; i++) {
+ if (!set_contains(set, dict[i])) {
+ continue;
+ }
+ assert_int_equal(set_add(set, dict[i]), 1);
+ }
+}
+
+/* Searching */
+static void test_contains(void **state)
+{
+ set_t *set = *state;
+ char *in;
+ const char *notin = "not in set";
+
+ in = malloc(strlen(dict[23])+1);
+ strcpy(in, dict[23]);
+
+ assert_true(set_contains(set, in));
+ assert_false(set_contains(set, notin));
+ assert_false(set_contains(set, ""));
+ in[strlen(in)/2] = '\0';
+ assert_false(set_contains(set, in));
+
+ free(in);
+}
+
+/* Count number of items */
+static int count_cb(const char *s, void *_, void *n) { (*(int *)n)++; return 0; }
+static void test_complete(set_t *set, int n)
+{
+ int i = 0;
+ if (set_walk(set, count_cb, &i) != 0) {
+ abort();
+ }
+ if (i != n) {
+ abort();
+ }
+}
+static void test_complete_full(void **state) { test_complete(*state, sizeof(dict) / sizeof(const char *)); }
+static void test_complete_zero(void **state) { test_complete(*state, 0); }
+
+/* Deletion */
+static void test_delete(void **state)
+{
+ set_t *set = *state;
+ assert_int_equal(set_del(set, dict[91]), 0);
+ assert_int_equal(set_del(set, "most likely not in set"), 1);
+}
+
+/* Complete deletion */
+static void test_delete_all(void **state)
+{
+ set_t *set = *state;
+ int dict_size = sizeof(dict) / sizeof(const char *);
+ int i;
+
+ for (i = 0; i < dict_size; i++) {
+ if (!set_contains(set, dict[i])) {
+ continue;
+ }
+ assert_int_equal(set_del(set, dict[i]), 0);
+ }
+}
+
+/* Fake allocator */
+static void *fake_malloc(void *b, size_t s) { return NULL; }
+static void test_allocator(void **state)
+{
+ knot_mm_t fake_pool = { .ctx = NULL, .alloc = fake_malloc, .free = NULL };
+ set_t set = set_make(&fake_pool);
+ assert_int_equal(set_add(&set, dict[0]), ENOMEM);
+}
+
+/* Empty set */
+static void test_empty(void **state)
+{
+ set_t *set = *state;
+ assert_int_equal(set_contains(set, dict[1]), 0);
+ assert_int_not_equal(set_del(set, dict[1]), 0);
+}
+
+/* Prefix walking */
+static void test_prefixes(void **state)
+{
+ set_t *set = *state;
+ int i = 0;
+ if ((set_add(set, "1str") != 0) ||
+ (set_add(set, "11str2") != 0) ||
+ (set_add(set, "12str") != 0) ||
+ (set_add(set, "11str") != 0)) {
+ assert_int_equal(1, 0);
+ }
+
+ assert_int_equal(set_walk_prefixed(set, "11", count_cb, &i), 0);
+ assert_int_equal(i, 2);
+ i = 0;
+ assert_int_equal(set_walk_prefixed(set, "13", count_cb, &i), 0);
+ assert_int_equal(i, 0);
+ i = 0;
+ assert_int_equal(set_walk_prefixed(set, "12345678", count_cb, &i), 0);
+ assert_int_equal(i, 0);
+ i = 0;
+ assert_int_equal(set_walk_prefixed(set, "11str", count_cb, &i), 0);
+ assert_int_equal(i, 2);
+}
+
+static void test_clear(void **state)
+{
+ set_t *set = *state;
+ set_clear(set);
+}
+
+static void test_init(void **state)
+{
+ static set_t set;
+ set = set_make(NULL);
+ *state = &set;
+ assert_non_null(*state);
+}
+
+static void test_deinit(void **state)
+{
+ set_t *set = *state;
+ set_clear(set);
+}
+
+/* Program entry point */
+int main(int argc, char **argv)
+{
+ const UnitTest tests[] = {
+ group_test_setup(test_init),
+ unit_test(test_insert),
+ unit_test(test_complete_full),
+ unit_test(test_insert_dup),
+ unit_test(test_contains),
+ unit_test(test_delete),
+ unit_test(test_clear),
+ unit_test(test_insert),
+ unit_test(test_complete_full),
+ unit_test(test_delete_all),
+ unit_test(test_complete_zero),
+ unit_test(test_allocator),
+ unit_test(test_clear),
+ unit_test(test_empty),
+ unit_test(test_insert),
+ unit_test(test_prefixes),
+ group_test_teardown(test_deinit)
+ };
+
+ return run_group_tests(tests);
+}
diff --git a/tests/test_trie.c b/tests/test_trie.c
new file mode 100644
index 0000000..a029153
--- /dev/null
+++ b/tests/test_trie.c
@@ -0,0 +1,165 @@
+/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "lib/generic/trie.h"
+#include "tests/test.h"
+
+static const char *dict[] = {
+ "catagmatic", "prevaricator", "statoscope", "workhand", "benzamide",
+ "work", "workhands", // have some keys that are prefixes of each other
+ "alluvia", "fanciful", "bladish", "Tarsius", "unfast", "appropriative",
+ "seraphically", "monkeypod", "deflectometer", "tanglesome", "zodiacal",
+ "physiologically", "economizer", "forcepslike", "betrumpet",
+ "Danization", "broadthroat", "randir", "usherette", "nephropyosis",
+ "hematocyanin", "chrysohermidin", "uncave", "mirksome", "podophyllum",
+ "siphonognathous", "indoor", "featheriness", "forwardation",
+ "archruler", "soricoid", "Dailamite", "carmoisin", "controllability",
+ "unpragmatical", "childless", "transumpt", "productive",
+ "thyreotoxicosis", "oversorrow", "disshadow", "osse", "roar",
+ "pantomnesia", "talcer", "hydrorrhoea", "Satyridae", "undetesting",
+ "smoothbored", "widower", "sivathere", "pendle", "saltation",
+ "autopelagic", "campfight", "unexplained", "Macrorhamphosus",
+ "absconsa", "counterflory", "interdependent", "triact", "reconcentration",
+ "oversharpness", "sarcoenchondroma", "superstimulate", "assessory",
+ "pseudepiscopacy", "telescopically", "ventriloque", "politicaster",
+ "Caesalpiniaceae", "inopportunity", "Helion", "uncompatible",
+ "cephaloclasia", "oversearch", "Mahayanistic", "quarterspace",
+ "bacillogenic", "hamartite", "polytheistical", "unescapableness",
+ "Pterophorus", "cradlemaking", "Hippoboscidae", "overindustrialize",
+ "perishless", "cupidity", "semilichen", "gadge", "detrimental",
+ "misencourage", "toparchia", "lurchingly", "apocatastasis"
+};
+#define KEY_LEN(x) (strlen(x) + 1)
+static const int dict_size = sizeof(dict) / sizeof(const char *);
+
+static void test_init(void **state)
+{
+ trie_t *t = trie_create(NULL);
+ assert_non_null(t);
+ *state = t;
+}
+
+static void test_insert(void **state)
+{
+ trie_t *t = *state;
+
+ for (int i = 0; i < dict_size; ++i) {
+ trie_val_t *data = trie_get_ins(t, dict[i], KEY_LEN(dict[i]));
+ assert_non_null(data);
+ assert_null(*data);
+ *data = NULL + (ptrdiff_t)i; // yes, ugly
+ assert_ptr_equal(trie_get_try(t, dict[i], KEY_LEN(dict[i])), data);
+ }
+ assert_int_equal(trie_weight(t), dict_size);
+}
+
+static void test_missing(void **state)
+{
+ trie_t *t = *state;
+ const char *notin = "p";
+ assert_null(trie_get_try(t, notin, KEY_LEN(notin)));
+}
+
+static int cmpstringp(const void *p1, const void *p2)
+{
+ return strcmp(* (char * const *) p1, * (char * const *) p2);
+}
+
+static void test_iter(void **state)
+{
+ // prepare sorted dictionary
+ char *dict_sorted[dict_size];
+ memcpy(dict_sorted, dict, sizeof(dict));
+ qsort(dict_sorted, dict_size, sizeof(dict[0]), cmpstringp);
+
+ // iterate and check the order is consistent
+ trie_t *t = *state;
+ trie_it_t *it = trie_it_begin(t);
+ for (int i = 0; i < dict_size; ++i, trie_it_next(it)) {
+ assert_false(trie_it_finished(it));
+ size_t len;
+ const char *key = trie_it_key(it, &len);
+ assert_int_equal(KEY_LEN(key), len);
+ assert_string_equal(key, dict_sorted[i]);
+ assert_ptr_equal(dict[*trie_it_val(it) - NULL], dict_sorted[i]);
+ }
+ assert_true(trie_it_finished(it));
+ trie_it_free(it);
+}
+
+static void test_queue(void **state)
+{
+ trie_t *t = *state;
+ // remove all the elements in ascending order
+ for (int i = 0; i < dict_size; ++i) {
+ char *key;
+ uint32_t len;
+ trie_val_t *data = trie_get_first(t, &key, &len);
+ assert_non_null(key);
+ assert_int_equal(len, KEY_LEN(key));
+ assert_non_null(data);
+ ptrdiff_t key_i = *data - NULL;
+ assert_string_equal(key, dict[key_i]);
+
+ len = 30;
+ char key_buf[len];
+ ptrdiff_t key_i_new;
+ int ret = trie_del_first(t, key_buf, &len, (trie_val_t *)&key_i_new);
+ assert_int_equal(ret, kr_ok());
+ assert_int_equal(KEY_LEN(key_buf), len);
+ assert_int_equal(key_i, key_i_new);
+ assert_string_equal(dict[key_i], key_buf);
+ }
+}
+
+static void test_leq_bug(void **state)
+{
+ /* We use different contents of the trie,
+ * so that the particular bug would've been triggered. */
+ trie_t *t = trie_create(NULL);
+ char key = 'a';
+ trie_get_ins(t, &key, sizeof(key));
+
+ key = 0xff;
+ trie_val_t *val;
+ int ret = trie_get_leq(t, &key, sizeof(key), &val);
+ assert_int_equal(ret, 1);
+ trie_free(t);
+}
+
+static void test_deinit(void **state)
+{
+ trie_t *t = *state;
+ trie_free(t);
+ *state = NULL;
+}
+
+/* Program entry point */
+int main(int argc, char **argv)
+{
+ const UnitTest tests[] = {
+ group_test_setup(test_init),
+ unit_test(test_insert),
+ unit_test(test_leq_bug),
+ unit_test(test_missing),
+ unit_test(test_iter),
+ unit_test(test_queue),
+ group_test_teardown(test_deinit)
+ };
+
+ return run_group_tests(tests);
+}
+
diff --git a/tests/test_utils.c b/tests/test_utils.c
new file mode 100644
index 0000000..e6371c3
--- /dev/null
+++ b/tests/test_utils.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2015-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <sys/socket.h>
+#include <stdio.h>
+#include <contrib/cleanup.h>
+
+#include "tests/test.h"
+#include "lib/utils.h"
+
+static void test_strcatdup(void **state)
+{
+ auto_free char *empty_res = kr_strcatdup(0);
+ assert_null(empty_res);
+
+ auto_free char *null_res = kr_strcatdup(1, NULL);
+ assert_null(null_res);
+
+ auto_free char *nullcat_res = kr_strcatdup(2, NULL, "beef");
+ assert_string_equal(nullcat_res, "beef");
+
+ auto_free char *multi_res = kr_strcatdup(3, "need", "beef", "dead");
+ assert_string_equal(multi_res, "needbeefdead");
+
+ /* Test fails if this leaks. */
+ auto_fclose FILE* null_file = fopen("/dev/null", "r");
+ (void)(null_file);
+
+ /* Test fails if this leaks. */
+ auto_close int null_sock = socket(AF_INET, SOCK_DGRAM, 0);
+ (void)(null_sock);
+}
+
+static inline int test_bitcmp(const char *subnet, const char *str_addr, size_t len)
+{
+ char addr_buf[16] = {'\0'};
+ kr_straddr_subnet(addr_buf, str_addr);
+ return kr_bitcmp(subnet, addr_buf, len);
+}
+
+static void test_straddr(void **state)
+{
+ const char *ip4_ok = "1.2.3.0/30";
+ const char *ip4_bad = "1.2.3.0/33";
+ const char *ip4_in = "1.2.3.1";
+ const char *ip4_out = "1.2.3.5";
+ const char *ip6_ok = "7caa::/4";
+ const char *ip6_bad = "7caa::/129";
+ const char *ip6_in = "7caa::aa7c";
+ const char *ip6_out = "8caa::aa7c";
+ /* Parsing family */
+ assert_int_equal(kr_straddr_family(ip4_ok), AF_INET);
+ assert_int_equal(kr_straddr_family(ip4_in), AF_INET);
+ assert_int_equal(kr_straddr_family(ip6_ok), AF_INET6);
+ assert_int_equal(kr_straddr_family(ip6_in), AF_INET6);
+ /* Parsing subnet */
+ char ip4_sub[4], ip6_sub[16];
+ assert_true(kr_straddr_subnet(ip4_sub, ip4_bad) < 0);
+ assert_int_equal(kr_straddr_subnet(ip4_sub, ip4_ok), 30);
+ assert_true(kr_straddr_subnet(ip6_sub, ip6_bad) < 0);
+ assert_int_equal(kr_straddr_subnet(ip6_sub, ip6_ok), 4);
+ /* Matching subnet */
+ assert_int_equal(test_bitcmp(ip4_sub, ip4_in, 30), 0);
+ assert_int_not_equal(test_bitcmp(ip4_sub, ip4_out, 30), 0);
+ assert_int_equal(test_bitcmp(ip6_sub, ip6_in, 4), 0);
+ assert_int_not_equal(test_bitcmp(ip6_sub, ip6_out, 4), 0);
+}
+
+static void test_strptime_diff(void **state)
+{
+ char *format = "%Y-%m-%dT%H:%M:%S";
+ const char *errmsg = NULL;
+ double output;
+
+ errmsg = kr_strptime_diff(format,
+ "2019-01-09T12:06:04",
+ "2019-01-09T12:06:04", &output);
+ assert_true(errmsg == NULL);
+ /* double type -> equality is not reliable */
+ assert_true(output > -0.01 && output < 0.01);
+
+ errmsg = kr_strptime_diff(format,
+ "2019-01-09T12:06:04",
+ "2019-01-09T11:06:04", &output);
+ assert_true(errmsg == NULL);
+ /* double type -> equality is not reliable */
+ assert_true(output > -3600.01 && output < 3600.01);
+
+ /* invalid inputs */
+ errmsg = kr_strptime_diff(format,
+ "2019-01-09T25:06:04",
+ "2019-01-09T11:06:04", &output);
+ assert_true(errmsg != NULL);
+
+ errmsg = kr_strptime_diff("fail",
+ "2019-01-09T23:06:04",
+ "2019-01-09T11:06:04", &output);
+ assert_true(errmsg != NULL);
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_strcatdup),
+ unit_test(test_straddr),
+ unit_test(test_strptime_diff),
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/test_zonecut.c b/tests/test_zonecut.c
new file mode 100644
index 0000000..877c83a
--- /dev/null
+++ b/tests/test_zonecut.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <netinet/in.h>
+
+#include "tests/test.h"
+#include "lib/zonecut.h"
+
+static void test_zonecut_params(void **state)
+{
+ /* NULL args */
+ struct kr_zonecut cut;
+ assert_int_not_equal(kr_zonecut_init(NULL, NULL, NULL), 0);
+ assert_int_not_equal(kr_zonecut_init(&cut, NULL, NULL), 0);
+ kr_zonecut_deinit(NULL);
+ kr_zonecut_set(NULL, NULL);
+ kr_zonecut_set(&cut, NULL);
+ /* TODO triggerring inner assert:
+ assert_int_not_equal(kr_zonecut_add(NULL, NULL, NULL, 0), 0);
+ */
+ assert_null((void *)kr_zonecut_find(NULL, NULL));
+ assert_null((void *)kr_zonecut_find(&cut, NULL));
+ assert_int_not_equal(kr_zonecut_set_sbelt(NULL, NULL), 0);
+ assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, NULL, 0, 0), 0);
+}
+
+static void test_zonecut_copy(void **state)
+{
+ const knot_dname_t *n_root = (const uint8_t *)"";
+ struct kr_zonecut cut1, cut2;
+ kr_zonecut_init(&cut1, n_root, NULL);
+ kr_zonecut_init(&cut2, n_root, NULL);
+ /* Insert some values */
+ const knot_dname_t
+ *n_1 = (const uint8_t *)"\4dead",
+ *n_2 = (const uint8_t *)"\3bee\1f";
+ assert_int_equal(kr_zonecut_add(&cut1, n_1, NULL, 0), 0);
+ assert_int_equal(kr_zonecut_add(&cut1, n_2, NULL, 0), 0);
+ /* Copy */
+ assert_int_equal(kr_zonecut_copy(&cut2, &cut1), 0);
+ /* Check if exist */
+ assert_non_null(kr_zonecut_find(&cut2, n_1));
+ assert_non_null(kr_zonecut_find(&cut2, n_2));
+ assert_null(kr_zonecut_find(&cut2, (const uint8_t *)"\5death"));
+ kr_zonecut_deinit(&cut1);
+ kr_zonecut_deinit(&cut2);
+}
+
+int main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_zonecut_params),
+ unit_test(test_zonecut_copy)
+ };
+
+ return run_tests(tests);
+}
diff --git a/tests/testdata_notimpl/iter_class_any.rpl b/tests/testdata_notimpl/iter_class_any.rpl
new file mode 100644
index 0000000..5c4bb4b
--- /dev/null
+++ b/tests/testdata_notimpl/iter_class_any.rpl
@@ -0,0 +1,150 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test lookup of class any response
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. ANY A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. ANY A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dnsseclame_bug.rpl b/tests/testdata_notimpl/iter_dnsseclame_bug.rpl
new file mode 100644
index 0000000..0210e2d
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dnsseclame_bug.rpl
@@ -0,0 +1,465 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Bug test dnssec-lame detection at ds point with target queries.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+; Note this timing is so it will provide answers at the beginning.
+RANGE_BEGIN 0 30
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; no example.net delegation answers yet.
+
+RANGE_END
+
+; e.gtld-servers.net.
+; Note this timing is so it will not provide answers at the beginning,
+; but only later on.
+RANGE_BEGIN 30 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+; Note this timing is so it will not provide answers at the beginning,
+; but only later on.
+RANGE_BEGIN 30 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; This server is DNSSEC LAME!
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+; dnssec-lameness detection depends on this information
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+STEP 10 NOTHING
+; recursion at time 10.
+; first recursion with answers in 0-30 time
+; with bug it now resolves to the bad version
+; fixed, it stops waiting for more target queries.
+
+STEP 40 NOTHING
+; next recursion with more answers at time 40.
+
+; recursion happens here.
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dnsseclame_ds.rpl b/tests/testdata_notimpl/iter_dnsseclame_ds.rpl
new file mode 100644
index 0000000..8b91100
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dnsseclame_ds.rpl
@@ -0,0 +1,414 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at ds point.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; This server is DNSSEC LAME!
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+SECTION AUTHORITY
+; dnssec-lameness detection depends on this information
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dnsseclame_ds_ok.rpl b/tests/testdata_notimpl/iter_dnsseclame_ds_ok.rpl
new file mode 100644
index 0000000..8b7edeb
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dnsseclame_ds_ok.rpl
@@ -0,0 +1,367 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at ds point, which is ok.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+; no NS set. not needed for this test.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; fine DNSKEY response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+ENTRY_END
+
+; correct delegation with DS
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+RANGE_END
+
+; server is not DNSSEC lame.
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. IN NS ns.example.net.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.sub.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dnsseclame_ta.rpl b/tests/testdata_notimpl/iter_dnsseclame_ta.rpl
new file mode 100644
index 0000000..d179401
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dnsseclame_ta.rpl
@@ -0,0 +1,327 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection at anchor point.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+; this entry; glue will make unbound take this reference first.
+; it is however, the lame server.
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+e.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; lame DNSKEY response.
+; here without sigs (assuming server does unknown-RR type handling)
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+ENTRY_END
+
+; lame NS response
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+; the lame response. No RRSIGS.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; the wrong answer.
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+; dnssec-lameness detection depends on this information
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dnsseclame_ta_ok.rpl b/tests/testdata_notimpl/iter_dnsseclame_ta_ok.rpl
new file mode 100644
index 0000000..d53377b
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dnsseclame_ta_ok.rpl
@@ -0,0 +1,303 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test dnssec-lame detection with anchor point that is ok.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+; the response is not lame at all.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854}
+ENTRY_END
+
+; response is not lame.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_dp_turnsuseless.rpl b/tests/testdata_notimpl/iter_dp_turnsuseless.rpl
new file mode 100644
index 0000000..9d0c355
--- /dev/null
+++ b/tests/testdata_notimpl/iter_dp_turnsuseless.rpl
@@ -0,0 +1,166 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test parent-child dichotomy where dp turns useless
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; data for ns-crap does not exist.
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+ns-crap. IN NS
+SECTION AUTHORITY
+; very short TTL so it'll expire.
+. 2 SOA . . 1 2 3 4 5
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+; very short TTL so it can time out quickly.
+example.com. 2 IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns-crap.
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 2 IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.com. IN NS
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns-crap.
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 2 IN A 10.20.30.40
+ENTRY_END
+
+; parent side stuff times out
+STEP 40 TIME_PASSES ELAPSE 5.0
+
+; actual retry logic must fire
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 2 IN A 10.20.30.40
+ENTRY_END
+
+
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_ds_locate_ns.rpl b/tests/testdata_notimpl/iter_ds_locate_ns.rpl
new file mode 100644
index 0000000..d3b613e
--- /dev/null
+++ b/tests/testdata_notimpl/iter_ds_locate_ns.rpl
@@ -0,0 +1,145 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for parent nameservers of DS
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; content of root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-servers.net. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_ds_locate_ns_cname.rpl b/tests/testdata_notimpl/iter_ds_locate_ns_cname.rpl
new file mode 100644
index 0000000..d99d301
--- /dev/null
+++ b/tests/testdata_notimpl/iter_ds_locate_ns_cname.rpl
@@ -0,0 +1,155 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for DS with CNAME
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; content of root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+root-servers.net. IN CNAME blabla.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+blabla.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-servers.net. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_ds_locate_ns_detach.rpl b/tests/testdata_notimpl/iter_ds_locate_ns_detach.rpl
new file mode 100644
index 0000000..9288fe5
--- /dev/null
+++ b/tests/testdata_notimpl/iter_ds_locate_ns_detach.rpl
@@ -0,0 +1,296 @@
+; config options
+server:
+ target-fetch-policy: "3 2 1 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for DS and with detached queries
+; the additional targets looked up cause detached queries.
+; hence the target fetch policy is increased above.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.server.net.
+net. IN NS b.server.net.
+net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.server.net.
+; The b.server.net and c.server.net servers are here to cause
+; extra lookups to be generated (to create detached queries in the
+; iterator), there is no IP address that answers for them set up.
+; force DSNSFind, we host a grandchild zone.
+; also, this range of steps is without responses for b and c, so that
+; they can be force to happen later (after the DSNS is activated).
+RANGE_BEGIN 0 20
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.server.net.
+net. IN NS b.server.net.
+net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN A
+SECTION ANSWER
+a.server.net. IN A 192.5.6.30
+SECTION AUTHORITY
+net. IN NS a.server.net.
+net. IN NS b.server.net.
+net. IN NS c.server.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.net. IN NS
+SECTION ANSWER
+sub.example.net. IN NS a.server.net.
+sub.example.net. IN NS b.server.net.
+sub.example.net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.net. IN A
+SECTION AUTHORITY
+sub.example.net. IN NS a.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.server.net range with all the answers (to finish the test).
+RANGE_BEGIN 30 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.server.net.
+net. IN NS b.server.net.
+net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN A
+SECTION ANSWER
+a.server.net. IN A 192.5.6.30
+SECTION AUTHORITY
+net. IN NS a.server.net.
+net. IN NS b.server.net.
+net. IN NS c.server.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.server.net. IN A
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.server.net. IN A
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.net. IN NS
+SECTION ANSWER
+sub.example.net. IN NS a.server.net.
+sub.example.net. IN NS b.server.net.
+sub.example.net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.net. IN A
+SECTION AUTHORITY
+sub.example.net. IN NS a.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.sub.example.net. IN DS
+ENTRY_END
+
+; make traffic flow at this time
+STEP 15 TRAFFIC
+
+STEP 20 TRAFFIC
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 50 TRAFFIC
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_ds_locate_ns_nosoa.rpl b/tests/testdata_notimpl/iter_ds_locate_ns_nosoa.rpl
new file mode 100644
index 0000000..9c14cea
--- /dev/null
+++ b/tests/testdata_notimpl/iter_ds_locate_ns_nosoa.rpl
@@ -0,0 +1,145 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for DS without a SOA record
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; content of root-servers.net
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN NS
+SECTION ANSWER
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+;root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+root-servers.net. IN A
+SECTION AUTHORITY
+root-servers.net. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+root-servers.net. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+root-servers.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_emptydp.rpl b/tests/testdata_notimpl/iter_emptydp.rpl
new file mode 100644
index 0000000..dc17986
--- /dev/null
+++ b/tests/testdata_notimpl/iter_emptydp.rpl
@@ -0,0 +1,263 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+ target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with empty delegation from cache.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+
+; sneak in some data into the cache to simulate partial data after timeouts
+; gets scrubbed anyway.
+example.net. NS ns.example.net.
+
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+; com zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ENTRY_END
+
+; net zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+; example.net. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.com. zone
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+; bogus
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+; make sure glue fetch is done.
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_emptydp_for_glue.rpl b/tests/testdata_notimpl/iter_emptydp_for_glue.rpl
new file mode 100644
index 0000000..d469bc2
--- /dev/null
+++ b/tests/testdata_notimpl/iter_emptydp_for_glue.rpl
@@ -0,0 +1,493 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "1189950146"
+ target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with empty delegation for glue address
+; setup:
+; query for www.example.com.
+; needs example.com served by ns.example.net and ns.example.org
+; needs example.net served by ns.example.net and ns.example.org
+; needs example.org served by ns.example.net and ns.example.org
+; but the cache has all these NS rrsets, but not the addresses.
+; observed in the wild this was from the in-addr zone towards two
+; domains with such a setup. and high TTL NS, lower for A.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+
+; sneak in some data into the cache to simulate partial data after timeouts
+; gets scrubbed away now ....
+example.com. NS ns.example.net.
+example.com. NS ns.example.org.
+example.net. NS ns.example.net.
+example.net. NS ns.example.org.
+example.org. NS ns.example.net.
+example.org. NS ns.example.org.
+
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+org. IN A
+SECTION AUTHORITY
+org. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+; com zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. NS ns.example.net.
+example.com. NS ns.example.org.
+SECTION ADDITIONAL
+; no glue!
+ENTRY_END
+
+; net zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. NS ns.example.net.
+example.net. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+; org zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+org. IN A
+SECTION ANSWER
+org. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.org. IN A
+SECTION AUTHORITY
+example.org. NS ns.example.net.
+example.org. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.org. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+; example.org. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.org. IN NS
+SECTION ANSWER
+example.org. NS ns.example.net.
+example.org. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.org. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.org. IN A
+SECTION ANSWER
+ns.example.org. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.org. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.net. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. NS ns.example.net.
+example.net. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.com. zone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+; bogus message.
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.example.org.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+
+; example.org. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.org. IN NS
+SECTION ANSWER
+example.org. NS ns.example.net.
+example.org. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.org. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.org. IN A
+SECTION ANSWER
+ns.example.org. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.org. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.net. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. NS ns.example.net.
+example.net. NS ns.example.org.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.com. zone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+; make sure glue fetch is done.
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; make sure NS fetch is done.
+STEP 14 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+example.org. IN NS
+ENTRY_END
+
+STEP 15 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH ; none
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_fwdfirst.rpl b/tests/testdata_notimpl/iter_fwdfirst.rpl
new file mode 100644
index 0000000..8f362af
--- /dev/null
+++ b/tests/testdata_notimpl/iter_fwdfirst.rpl
@@ -0,0 +1,157 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+forward-zone:
+ name: "example.com"
+ forward-addr: 1.2.3.6 # failing resolver
+ forward-first: yes
+
+CONFIG_END
+
+SCENARIO_BEGIN Test forward-first directive
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; local resolver (that fails a lot)
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA SERVFAIL
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_fwdfirstequal.rpl b/tests/testdata_notimpl/iter_fwdfirstequal.rpl
new file mode 100644
index 0000000..98d5d70
--- /dev/null
+++ b/tests/testdata_notimpl/iter_fwdfirstequal.rpl
@@ -0,0 +1,157 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+forward-zone:
+ name: "."
+ forward-addr: 1.2.3.6 # failing resolver
+ forward-first: yes
+
+CONFIG_END
+
+SCENARIO_BEGIN Test forward-first directive with equal stub name configured.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; local resolver (that fails a lot)
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA SERVFAIL
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_fwdstub.rpl b/tests/testdata_notimpl/iter_fwdstub.rpl
new file mode 100644
index 0000000..0cdcc9e
--- /dev/null
+++ b/tests/testdata_notimpl/iter_fwdstub.rpl
@@ -0,0 +1,218 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+forward-zone:
+ name: "example.com"
+ forward-addr: 10.0.0.1
+stub-zone:
+ name: "sub.example.com"
+ stub-addr: 10.0.0.2
+CONFIG_END
+
+SCENARIO_BEGIN Test iterative resolve with a stub under a forward zone
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; forwarder for example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.0.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.0.0.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; fail all other queries
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+RANGE_END
+
+; stub for sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.0.2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.0.0.5
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+
+; check if forwarder is honored
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.0.0.4
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; try to resolve from stub zone
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.0.0.5
+;SECTION AUTHORITY
+;sub.example.com. IN NS ns.sub.example.com.
+;SECTION ADDITIONAL
+;ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_fwdstubroot.rpl b/tests/testdata_notimpl/iter_fwdstubroot.rpl
new file mode 100644
index 0000000..99e1994
--- /dev/null
+++ b/tests/testdata_notimpl/iter_fwdstubroot.rpl
@@ -0,0 +1,175 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+forward-zone:
+ name: "."
+ forward-addr: 10.0.0.1
+stub-zone:
+ name: "sub.example.com"
+ stub-addr: 10.0.0.2
+CONFIG_END
+
+SCENARIO_BEGIN Test iterative resolve with a stub under a forward root zone
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+
+; No answers from the actual root, blocked.
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; forwarder for example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.0.1
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.0.0.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; fail all other queries
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.com. IN A
+ENTRY_END
+RANGE_END
+
+; stub for sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.0.2
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.0.0.5
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; try to resolve from stub zone
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 10.0.0.5
+;SECTION AUTHORITY
+;sub.example.com. IN NS ns.sub.example.com.
+;SECTION ADDITIONAL
+;ns.sub.example.com. IN A 1.2.3.44
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_got6only.rpl b/tests/testdata_notimpl/iter_got6only.rpl
new file mode 100644
index 0000000..b842f5c
--- /dev/null
+++ b/tests/testdata_notimpl/iter_got6only.rpl
@@ -0,0 +1,135 @@
+; config options
+server:
+ do-ip6: no
+ target-fetch-policy: "0 0 0 0 0 "
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator when only ip6 in dp but doip6 is no
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.bla.com.
+SECTION ADDITIONAL
+; not included
+;ns.bla.com. IN A 1.2.3.4
+
+; and this one is useless because do-ip6 is "no"
+ns.bla.com. IN AAAA ::53
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.bla.com. IN A
+SECTION ANSWER
+ns.bla.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_pcdiff.rpl b/tests/testdata_notimpl/iter_pcdiff.rpl
new file mode 100644
index 0000000..8ff4a59
--- /dev/null
+++ b/tests/testdata_notimpl/iter_pcdiff.rpl
@@ -0,0 +1,210 @@
+; config options
+ target-fetch-policy: "0 0 0 0 0"
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with recursion and parent child differ.
+; and the child gives bad information.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; The parent-IP version
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; The child IP version. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_pcnamerec.rpl b/tests/testdata_notimpl/iter_pcnamerec.rpl
new file mode 100644
index 0000000..d5cce88
--- /dev/null
+++ b/tests/testdata_notimpl/iter_pcnamerec.rpl
@@ -0,0 +1,275 @@
+; config options
+ target-fetch-policy: "0 0 0 0 0"
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with parent child differ names recursive.
+; the parent has an extra name that is the only working one.
+; and that name needs its parent-side glue to work.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; the working version.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.55
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; Broken. Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+; now that the bad child NS record is in cache, ask something else.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+mail.example.com. IN A 10.20.30.20
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_primenoglue.rpl b/tests/testdata_notimpl/iter_primenoglue.rpl
new file mode 100644
index 0000000..2cf72d5
--- /dev/null
+++ b/tests/testdata_notimpl/iter_primenoglue.rpl
@@ -0,0 +1,383 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with root prime answer without glue.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+; glue ommitted!
+;K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+
+; sneak in some data into the cache to simulate partial data after timeouts
+; scrubbed away...
+example.net. NS ns.example.net.
+
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+; com zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ENTRY_END
+
+; net zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+A.ROOT-SERVERS.NET. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN A
+SECTION AUTHORITY
+ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+A.ROOT-SERVERS.NET. IN A 198.41.0.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION AUTHORITY
+example.net. NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; A.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 198.41.0.4
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ROOT-SERVERS.NET. IN NS
+SECTION ANSWER
+ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+A.ROOT-SERVERS.NET. IN A 198.41.0.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+A.ROOT-SERVERS.NET. IN A
+SECTION ANSWER
+A.ROOT-SERVERS.NET. IN A 198.41.0.4
+SECTION AUTHORITY
+ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+A.ROOT-SERVERS.NET. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+SECTION ANSWER
+; no ip6 address: we want to use only one address for K. to avoid having
+; to duplicate the entries in this file for both addresses.
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+; example.net. zone
+ENTRY_BEGIN
+MATCH opcode qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; example.com. zone
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+; make sure glue fetch is done.
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 13 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+ENTRY_END
+
+STEP 14 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+K.ROOT-SERVERS.NET. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_privaddr.rpl b/tests/testdata_notimpl/iter_privaddr.rpl
new file mode 100644
index 0000000..7992910
--- /dev/null
+++ b/tests/testdata_notimpl/iter_privaddr.rpl
@@ -0,0 +1,285 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+ private-address: 10.0.0.0/8
+ private-address: 172.16.0.0/12
+ private-address: 192.168.0.0/16
+ private-address: 169.254.0.0/16
+ private-address: fd00::/8
+ private-address: fe80::/10
+
+ private-domain: "example.net"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator scrubber with private addresses.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; root server authoritative for example.net too.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.net. IN A
+SECTION ANSWER
+mail.example.net. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 192.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.com. IN AAAA
+SECTION ANSWER
+mail.example.com. IN AAAA fe80::15
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+foo.example.com. IN A
+SECTION ANSWER
+foo.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+toss.example.com. IN A
+SECTION ANSWER
+toss.example.com. IN A 10.20.30.40
+toss.example.com. IN A 1.2.3.4
+toss.example.com. IN A 10.20.30.41
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; public address is not scrubbed
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 192.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; IPv4 address is scrubbed
+STEP 3 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+foo.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+foo.example.com. IN A
+SECTION ANSWER
+; scrubbed away
+;foo.example.com. IN A 10.20.30.40
+ENTRY_END
+
+; IPv6 address is scrubbed
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN AAAA
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mail.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+; allowed domain is not scrubbed.
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.net. IN A
+ENTRY_END
+
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.net. IN A
+SECTION ANSWER
+mail.example.net. IN A 10.20.30.40
+ENTRY_END
+
+; rest of RRset intact, only 10/8 tossed away.
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+toss.example.com. IN A
+ENTRY_END
+
+STEP 70 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+toss.example.com. IN A
+SECTION ANSWER
+; toss.example.com. IN A 10.20.30.40
+toss.example.com. IN A 1.2.3.4
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_ranoaa_lame.rpl b/tests/testdata_notimpl/iter_ranoaa_lame.rpl
new file mode 100644
index 0000000..c78f36a
--- /dev/null
+++ b/tests/testdata_notimpl/iter_ranoaa_lame.rpl
@@ -0,0 +1,293 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test detection of RA but no AA lameness
+; in this scenario mistakenly, a recursive server is deployed, instead
+; of an authoritative server. It gives answers from cache.
+; However, unbound is doing recursion on behalf of its client, and does
+; not trust the server to do so.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+; this entry; glue will make unbound take this reference first.
+; it is however, the lame server.
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net. IN A 192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+; the lame response.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; the wrong answer.
+www.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.55
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;example.com. IN NS ns.example.net.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.example.net IN A 1.2.3.44
+ENTRY_END
+
+; query still pending
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.net. IN AAAA
+ENTRY_END
+
+; query still pending
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+REPLY RD RA
+SECTION QUESTION
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_cname_an.rpl b/tests/testdata_notimpl/iter_scrub_cname_an.rpl
new file mode 100644
index 0000000..1fa6c84
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_cname_an.rpl
@@ -0,0 +1,181 @@
+; config options
+server:
+ harden-referral-path: no
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test scrub of CNAME in answer section
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; root prime is sent
+STEP 20 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+. IN NS
+ENTRY_END
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 40 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; query sent to .com server
+STEP 60 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; STEP 62 CHECK_OUT_QUERY
+; ENTRY_BEGIN
+; MATCH qname qtype opcode
+; SECTION QUESTION
+; com. IN NS
+; ENTRY_END
+; STEP 63 REPLY
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; com. IN NS
+; SECTION ANSWER
+; com. IN NS a.gtld-servers.net.
+; SECTION ADDITIONAL
+; a.gtld-servers.net. IN A 192.5.6.30
+; ENTRY_END
+
+STEP 70 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+; this query reply has to be scrubbed
+STEP 80 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; STEP 82 CHECK_OUT_QUERY
+; ENTRY_BEGIN
+; MATCH qname qtype opcode
+; SECTION QUESTION
+; example.com. IN NS
+; ENTRY_END
+; STEP 83 REPLY
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; example.com. IN NS
+; SECTION ANSWER
+; example.com. IN NS ns1.example.com.
+; SECTION ADDITIONAL
+; ns1.example.com. IN A 168.192.2.2
+; ENTRY_END
+
+STEP 90 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME next.example.com.
+next.example.com. IN A 10.20.30.0
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+; iterator should try again and ask the other nameserver.
+STEP 100 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+next.example.com. IN A
+ENTRY_END
+STEP 110 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+next.example.com. IN A
+SECTION ANSWER
+next.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+; is the final answer correct?
+STEP 200 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN CNAME next.example.com.
+next.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_dname_insec.rpl b/tests/testdata_notimpl/iter_scrub_dname_insec.rpl
new file mode 100644
index 0000000..921ef12
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_dname_insec.rpl
@@ -0,0 +1,250 @@
+; config options
+server:
+ harden-referral-path: no
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test scrub of insecure DNAME in answer section
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+x.y.example.com. IN A
+ENTRY_END
+
+; root prime is sent
+STEP 20 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+. IN NS
+ENTRY_END
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; query sent to root server
+STEP 40 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+x.y.example.com. IN A
+ENTRY_END
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; query sent to .com server
+STEP 60 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+x.y.example.com. IN A
+ENTRY_END
+
+; STEP 62 CHECK_OUT_QUERY
+; ENTRY_BEGIN
+; MATCH qname qtype opcode
+; SECTION QUESTION
+; com. IN NS
+; ENTRY_END
+; STEP 63 REPLY
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; com. IN NS
+; SECTION ANSWER
+; com. IN NS a.gtld-servers.net.
+; SECTION ADDITIONAL
+; a.gtld-servers.net. IN A 192.5.6.30
+; ENTRY_END
+
+STEP 70 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+STEP 80 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+x.y.example.com. IN A
+ENTRY_END
+
+; STEP 82 CHECK_OUT_QUERY
+; ENTRY_BEGIN
+; MATCH qname qtype opcode
+; SECTION QUESTION
+; example.com. IN NS
+; ENTRY_END
+; STEP 83 REPLY
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; example.com. IN NS
+; SECTION ANSWER
+; example.com. IN NS ns1.example.com.
+; SECTION ADDITIONAL
+; ns1.example.com. IN A 168.192.2.2
+; ENTRY_END
+
+STEP 90 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+x.y.example.com. IN CNAME x.z.example.com.
+x.z.example.com. IN A 10.20.30.0
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+STEP 100 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+x.z.example.com. IN A
+ENTRY_END
+STEP 110 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+x.z.example.com. IN A
+SECTION ANSWER
+x.z.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+; answer to first query (simply puts DNAME in cache)
+STEP 120 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+x.y.example.com. IN CNAME x.z.example.com.
+x.z.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+; now, DNAME insecure from cache should not be used.
+; new query
+STEP 200 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+other.y.example.com. IN A
+ENTRY_END
+
+STEP 210 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+other.y.example.com. IN A
+ENTRY_END
+STEP 220 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+other.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+other.y.example.com. IN CNAME other.z.example.com.
+other.z.example.com. IN A 50.60.70.0
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+STEP 230 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+other.z.example.com. IN A
+ENTRY_END
+STEP 240 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+other.z.example.com. IN A
+SECTION ANSWER
+other.z.example.com. IN A 50.60.70.80
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+STEP 250 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+other.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+other.y.example.com. IN CNAME other.z.example.com.
+other.z.example.com. IN A 50.60.70.80
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_dname_sec.rpl b/tests/testdata_notimpl/iter_scrub_dname_sec.rpl
new file mode 100644
index 0000000..0d06bf4
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_dname_sec.rpl
@@ -0,0 +1,212 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test scrub of secure DNAME in answer section
+
+RANGE_BEGIN 0 100
+; all adresses
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; x.y.example.com. IN A
+; SECTION AUTHORITY
+; com. IN NS a.gtld-servers.net.
+; SECTION ADDITIONAL
+; a.gtld-servers.net. IN A 192.5.6.30
+; ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; ENTRY_BEGIN
+; MATCH opcode qtype qname
+; ADJUST copy_id
+; REPLY QR NOERROR
+; SECTION QUESTION
+; x.y.example.com. IN A
+; SECTION AUTHORITY
+; example.com. IN NS ns1.example.com.
+; SECTION ADDITIONAL
+; ns1.example.com. IN A 168.192.2.2
+; ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854}
+x.y.example.com. IN CNAME x.z.example.com.
+x.z.example.com. IN A 10.20.30.0
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AA3IkI13XbKFU5NSqBVA9oM1WiyEKCy4DYFOAdihDf6uHps9lce3kEc= ;{id = 2854}
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AKcUlwrSz2xYKnQ7b7oMblRa0rKjfUNT900bIkGjLKLWDUGc8mKZE2M= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+x.z.example.com. IN A
+SECTION ANSWER
+x.z.example.com. IN A 10.20.30.40
+x.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. ADZ12PiZGEjVUyLLYkct/SBE2WT4D5IkMOKdcl0dzQ0XRAC5y/0bS7A= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854}
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns1.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ACHcJehLt4Hz+rAdxMPE96o7HJAEFohFXbxrKYlG+0WLfYAvH2nxU8k= ;{id = 2854}
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AInP69g8uR1n/aRg4gmGu8UoM+zZYgjOqbNN2IvOxw3bk/q+g05jKg0= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+
+RANGE_END
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+x.y.example.com. IN A
+ENTRY_END
+
+; answer to first query (simply puts DNAME in cache)
+STEP 90 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO
+SECTION QUESTION
+x.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854}
+x.y.example.com. IN CNAME x.z.example.com.
+x.z.example.com. IN A 10.20.30.40
+x.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. ADZ12PiZGEjVUyLLYkct/SBE2WT4D5IkMOKdcl0dzQ0XRAC5y/0bS7A= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+;ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854}
+ENTRY_END
+
+; now, DNAME is secure and can be used from cache.
+; new query
+STEP 200 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+other.y.example.com. IN A
+ENTRY_END
+
+STEP 230 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH qname qtype opcode
+SECTION QUESTION
+other.z.example.com. IN A
+ENTRY_END
+STEP 240 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+other.z.example.com. IN A
+SECTION ANSWER
+other.z.example.com. IN A 50.60.70.80
+other.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. AAp6G89oAvkyAaeF2d35AJNlzMhedGo0Bcppl0IOyF3HRzoc51vjJoU= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns1.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854}
+SECTION ADDITIONAL
+ns1.example.com. IN A 168.192.2.2
+ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854}
+ENTRY_END
+
+STEP 250 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO
+SECTION QUESTION
+other.y.example.com. IN A
+SECTION ANSWER
+y.example.com. DNAME z.example.com.
+y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854}
+other.y.example.com. IN CNAME other.z.example.com.
+other.z.example.com. IN A 50.60.70.80
+other.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. AAp6G89oAvkyAaeF2d35AJNlzMhedGo0Bcppl0IOyF3HRzoc51vjJoU= ;{id = 2854}
+;SECTION AUTHORITY
+;example.com. IN NS ns1.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854}
+;SECTION ADDITIONAL
+;ns1.example.com. IN A 168.192.2.2
+;ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_ns.rpl b/tests/testdata_notimpl/iter_scrub_ns.rpl
new file mode 100644
index 0000000..365f0b5
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_ns.rpl
@@ -0,0 +1,103 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+stub-zone:
+ name: "example.com"
+ stub-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Test scrubber to scrub NS record for lamelike reply from stub
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; must be scrubbed
+www.burritolovers.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example1234.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; LAME
+com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_ns_fwd.rpl b/tests/testdata_notimpl/iter_scrub_ns_fwd.rpl
new file mode 100644
index 0000000..239dc37
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_ns_fwd.rpl
@@ -0,0 +1,103 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+forward-zone:
+ name: "example.com"
+ forward-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Test scrubber to scrub NS record for lamelike reply from fwd
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY RD RA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; must be scrubbed
+www.burritolovers.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example1234.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY RD RA QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; LAME
+com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_scrub_ns_side.rpl b/tests/testdata_notimpl/iter_scrub_ns_side.rpl
new file mode 100644
index 0000000..98d00fd
--- /dev/null
+++ b/tests/testdata_notimpl/iter_scrub_ns_side.rpl
@@ -0,0 +1,103 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+stub-zone:
+ name: "example.com"
+ stub-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Test scrubber to scrub NS record to the side of the query
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+; must be scrubbed
+www.burritolovers.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example1234.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+; not pertinent to the query
+www.example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+mail.example.com. IN A
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+mail.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_stub_noroot.rpl b/tests/testdata_notimpl/iter_stub_noroot.rpl
new file mode 100644
index 0000000..f0740b6
--- /dev/null
+++ b/tests/testdata_notimpl/iter_stub_noroot.rpl
@@ -0,0 +1,64 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 81.187.81.187
+stub-zone:
+ name: "lp0.eu"
+ stub-addr: 81.2.80.65
+ stub-prime: no
+CONFIG_END
+
+SCENARIO_BEGIN Test resolve of stub zone without root prime.
+
+; this server does not respond. (for the root)
+RANGE_BEGIN 0 100
+ ADDRESS 81.187.81.187
+ENTRY_BEGIN
+MATCH
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+. IN NS
+ENTRY_END
+RANGE_END
+
+; lp0.eu server
+RANGE_BEGIN 0 100
+ ADDRESS 81.2.80.65
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+proxima.lp0.eu. IN A
+SECTION ANSWER
+proxima.lp0.eu. IN A 81.2.80.65
+SECTION AUTHORITY
+lp0.eu. IN NS proxima.lp0.eu.
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+proxima.lp0.eu. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+proxima.lp0.eu. IN A
+SECTION ANSWER
+proxima.lp0.eu. IN A 81.2.80.65
+;SECTION AUTHORITY
+;lp0.eu. IN NS proxima.lp0.eu.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_stubfirst.rpl b/tests/testdata_notimpl/iter_stubfirst.rpl
new file mode 100644
index 0000000..5f16679
--- /dev/null
+++ b/tests/testdata_notimpl/iter_stubfirst.rpl
@@ -0,0 +1,157 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+stub-zone:
+ name: "example.com"
+ stub-addr: 1.2.3.6 # failing server
+ stub-first: yes
+
+CONFIG_END
+
+SCENARIO_BEGIN Test stub-first directive
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; local authority (that fails a lot)
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.50
+SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_stublastresort.rpl b/tests/testdata_notimpl/iter_stublastresort.rpl
new file mode 100644
index 0000000..040c9be
--- /dev/null
+++ b/tests/testdata_notimpl/iter_stublastresort.rpl
@@ -0,0 +1,259 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+
+stub-zone:
+ name: "example.com"
+ stub-addr: 1.2.3.6
+ stub-prime: yes
+
+CONFIG_END
+
+SCENARIO_BEGIN Test stub with stub-prime and last resort fallback
+; the last resort fallback should not activate, as the
+; configured stub must be used for this data, or its primed data.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; the stub-prime server.
+; local authority (that fails a lot)
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.7
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+;ns.example.com. IN A 1.2.3.7
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.70
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; the primed server
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.7
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.8
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.80
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; crap server that the primed server refers to.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.8
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+;www.example.com. IN A 10.20.30.50
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.com.
+;SECTION ADDITIONAL
+;ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/testdata_notimpl/iter_timeout_ra_aaaa.rpl b/tests/testdata_notimpl/iter_timeout_ra_aaaa.rpl
new file mode 100644
index 0000000..baa11c4
--- /dev/null
+++ b/tests/testdata_notimpl/iter_timeout_ra_aaaa.rpl
@@ -0,0 +1,244 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with timeouts on reclame AAAA dropping server
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+. IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+. IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. 280 IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+; This server is REC_LAME
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. 280 IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 10 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 280 IN NS ns.example.net.
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+ENTRY_END
+
+; query for (dropped) AAAA record.
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+
+; the AAAA query times out.
+STEP 21 TIMEOUT
+STEP 22 TIMEOUT
+STEP 23 TIMEOUT
+STEP 24 TIMEOUT
+STEP 25 TIMEOUT
+
+; we get servfail, but the AAA arrives again (after the servfail times
+; out of the cache)
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+STEP 31 TIME_PASSES ELAPSE 6
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+
+; timeouts for AAAA keep happening.
+STEP 41 TIMEOUT
+STEP 42 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+STEP 43 TIME_PASSES ELAPSE 12
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+; fallback queries
+STEP 51 TRAFFIC
+; and it fails, no parentside entries and so on.
+STEP 52 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+STEP 53 TIME_PASSES ELAPSE 12
+
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+STEP 61 TIMEOUT
+STEP 62 TRAFFIC
+STEP 63 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+
+STEP 70 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+STEP 72 TRAFFIC
+STEP 73 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+;SECTION AUTHORITY
+;example.com. IN NS ns.example.net.
+ENTRY_END
+
+SCENARIO_END
diff --git a/tests/tests.mk b/tests/tests.mk
new file mode 100644
index 0000000..91edbb3
--- /dev/null
+++ b/tests/tests.mk
@@ -0,0 +1,33 @@
+# Platform-specific library injection
+ifeq ($(PLATFORM),Darwin)
+ preload_syms := DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_LIBRARY_PATH="$(abspath lib):$(DYLD_LIBRARY_PATH)"
+else
+ preload_syms := LD_LIBRARY_PATH="$(abspath lib):$(LD_LIBRARY_PATH)"
+endif
+
+# Unit tests
+ifeq ($(HAS_cmocka), yes)
+include tests/unit.mk
+else
+$(warning cmocka not found, skipping unit tests)
+endif
+
+CLEAN_DNSTAP :=
+ifeq ($(ENABLE_DNSTAP)|$(HAS_go),yes|yes)
+include tests/dnstap/src/dnstap-test/dnstap.mk
+CLEAN_DNSTAP := clean-dnstap
+endif
+tests-clean: $(foreach test,$(tests_BIN),$(test)-clean) mock_cmodule-clean $(CLEAN_DNSTAP)
+
+# Targets
+tests: check-unit
+# installcheck requires kresd to be installed in its final destination
+# (DESTDIR is not supported right now because module path gets hardcoded)
+
+installcheck: check-config
+
+include tests/config/test_config.mk
+include tests/test_integration.mk
+
+
+.PHONY: installcheck tests tests-clean
diff --git a/tests/unit.mk b/tests/unit.mk
new file mode 100644
index 0000000..6819fb0
--- /dev/null
+++ b/tests/unit.mk
@@ -0,0 +1,43 @@
+#
+# Unit tests
+#
+
+tests_BIN := \
+ test_array \
+ test_lru \
+ test_map \
+ test_module \
+ test_pack \
+ test_queue \
+ test_rplan \
+ test_set \
+ test_trie \
+ test_utils \
+ test_zonecut \
+ #test_cache TODO: re-consider how best to test cache
+
+mock_cmodule_CFLAGS := -fPIC
+mock_cmodule_SOURCES := tests/mock_cmodule.c
+$(eval $(call make_lib,mock_cmodule,tests))
+
+# Dependencies
+tests_DEPEND := $(libkres) $(mock_cmodule) $(mock_gomodule)
+tests_LIBS := $(libkres_TARGET) $(libkres_LIBS) $(cmocka_LIBS) $(lmdb_LIBS)
+
+# Make test binaries
+define make_test
+$(1)_CFLAGS := -fPIE
+$(1)_SOURCES := tests/$(1).c
+$(1)_LIBS := $(tests_LIBS)
+$(1)_DEPEND := $(tests_DEPEND)
+$(call make_bin,$(1),tests)
+$(1): $$($(1))
+ $(shell ./scripts/coverage_env.sh "$(TOPSRCDIR)" "$(COVERAGE_STATSDIR)/tests_unit" "$(1)") $(preload_syms) $(DEBUGGER) $$<
+.PHONY: $(1)
+endef
+
+# Targets
+$(foreach test,$(tests_BIN),$(eval $(call make_test,$(test))))
+check-unit: $(foreach test,$(tests_BIN),$(test))
+
+.PHONY: check-unit